diff options
Diffstat (limited to 'sys/i386/isa/sound/pas2_card.c')
| -rw-r--r-- | sys/i386/isa/sound/pas2_card.c | 456 |
1 files changed, 205 insertions, 251 deletions
diff --git a/sys/i386/isa/sound/pas2_card.c b/sys/i386/isa/sound/pas2_card.c index 1bfd73fcc404..79acf57d45f5 100644 --- a/sys/i386/isa/sound/pas2_card.c +++ b/sys/i386/isa/sound/pas2_card.c @@ -1,11 +1,10 @@ -#define _PAS2_CARD_C_ /* * sound/pas2_card.c - * + * * Detection routine for the Pro Audio Spectrum cards. - * + * * Copyright by Hannu Savolainen 1993 - * + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: 1. Redistributions of source code must retain the above copyright @@ -13,7 +12,7 @@ * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. - * + * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE @@ -25,15 +24,15 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * + * */ +#include <i386/isa/sound/sound_config.h> -#include "sound_config.h" - -#if defined(CONFIGURE_SOUNDCARD) && !defined(EXCLUDE_PAS) +#if defined(CONFIG_PAS) +#define _PAS2_CARD_C_ #define DEFINE_TRANSLATIONS -#include "pas.h" +#include <i386/isa/sound/pas_hw.h> /* * The Address Translation code is used to convert I/O register addresses to @@ -44,12 +43,14 @@ int translat_code; static int pas_intr_mask = 0; static int pas_irq = 0; -static char pas_model; +sound_os_info *pas_osp; + +char pas_model; static char *pas_model_names[] = {"", "Pro AudioSpectrum+", "CDPC", "Pro AudioSpectrum 16", "Pro AudioSpectrum 16D"}; /* - * pas_read() and pas_write() are equivalents of INB() and OUTB() + * pas_read() and pas_write() are equivalents of inb and outb */ /* * These routines perform the I/O address translation required @@ -57,89 +58,72 @@ static char *pas_model_names[] = /* * to support other than the default base address */ +extern void mix_write(u_char data, int ioaddr); -unsigned char -pas_read (int ioaddr) +u_char +pas_read(int ioaddr) { - return INB (ioaddr ^ translat_code); + return inb(ioaddr ^ translat_code); } void -pas_write (unsigned char data, int ioaddr) +pas_write(u_char data, int ioaddr) { - OUTB (data, ioaddr ^ translat_code); + outb(ioaddr ^ translat_code, data); } void -pas2_msg (char *foo) +pas2_msg(char *foo) { - printk (" PAS2: %s.\n", foo); + printf(" PAS2: %s.\n", foo); } /******************* Begin of the Interrupt Handler ********************/ void -pasintr (int unused) +pasintr(int irq) { - int status; + int status; - status = pas_read (INTERRUPT_STATUS); - pas_write (status, INTERRUPT_STATUS); /* - * Clear interrupt - */ + status = pas_read(INTERRUPT_STATUS); + pas_write(status, INTERRUPT_STATUS); /* Clear interrupt */ - if (status & I_S_PCM_SAMPLE_BUFFER_IRQ) - { -#ifndef EXCLUDE_AUDIO - pas_pcm_interrupt (status, 1); -#endif - status &= ~I_S_PCM_SAMPLE_BUFFER_IRQ; - } - if (status & I_S_MIDI_IRQ) - { -#ifndef EXCLUDE_MIDI -#ifdef EXCLUDE_PRO_MIDI - pas_midi_interrupt (); + if (status & I_S_PCM_SAMPLE_BUFFER_IRQ) { +#ifdef CONFIG_AUDIO + pas_pcm_interrupt(status, 1); #endif + status &= ~I_S_PCM_SAMPLE_BUFFER_IRQ; + } + if (status & I_S_MIDI_IRQ) { +#ifdef CONFIG_MIDI + pas_midi_interrupt(); #endif - status &= ~I_S_MIDI_IRQ; - } - + status &= ~I_S_MIDI_IRQ; + } } int -pas_set_intr (int mask) +pas_set_intr(int mask) { - int err; - - if (!mask) - return 0; + if (!mask) + return 0; - if (!pas_intr_mask) - { - if ((err = snd_set_irq_handler (pas_irq, pasintr)) < 0) - return err; - } - pas_intr_mask |= mask; + pas_intr_mask |= mask; - pas_write (pas_intr_mask, INTERRUPT_MASK); - return 0; + pas_write(pas_intr_mask, INTERRUPT_MASK); + return 0; } int -pas_remove_intr (int mask) +pas_remove_intr(int mask) { - if (!mask) - return 0; + if (!mask) + return 0; - pas_intr_mask &= ~mask; - pas_write (pas_intr_mask, INTERRUPT_MASK); + pas_intr_mask &= ~mask; + pas_write(pas_intr_mask, INTERRUPT_MASK); - if (!pas_intr_mask) - { - snd_release_irq (pas_irq); - } - return 0; + return 0; } /******************* End of the Interrupt handler **********************/ @@ -147,261 +131,231 @@ pas_remove_intr (int mask) /******************* Begin of the Initialization Code ******************/ int -config_pas_hw (struct address_info *hw_config) +config_pas_hw(struct address_info * hw_config) { - char ok = 1; - unsigned int_ptrs; /* scsi/sound interrupt pointers */ + char ok = 1; + u_int int_ptrs; /* scsi/sound interrupt pointers */ - pas_irq = hw_config->irq; + pas_irq = hw_config->irq; - pas_write (0x00, INTERRUPT_MASK); + pas_write(0x00, INTERRUPT_MASK); - pas_write (0x36, SAMPLE_COUNTER_CONTROL); /* - * Local timer control * - * register - */ + pas_write(0x36, SAMPLE_COUNTER_CONTROL); /* Local timer control * + * register */ - pas_write (0x36, SAMPLE_RATE_TIMER); /* - * Sample rate timer (16 bit) - */ - pas_write (0, SAMPLE_RATE_TIMER); + pas_write(0x36, SAMPLE_RATE_TIMER); /* Sample rate timer (16 bit) */ + pas_write(0, SAMPLE_RATE_TIMER); - pas_write (0x74, SAMPLE_COUNTER_CONTROL); /* - * Local timer control * - * register - */ + pas_write(0x74, SAMPLE_COUNTER_CONTROL); /* Local timer control * + * register */ - pas_write (0x74, SAMPLE_BUFFER_COUNTER); /* - * Sample count register (16 - * * bit) - */ - pas_write (0, SAMPLE_BUFFER_COUNTER); + pas_write(0x74, SAMPLE_BUFFER_COUNTER); /* Sample count register (16 * + * bit) */ + pas_write(0, SAMPLE_BUFFER_COUNTER); - pas_write (F_F_PCM_BUFFER_COUNTER | F_F_PCM_RATE_COUNTER | F_F_MIXER_UNMUTE | 1, FILTER_FREQUENCY); - pas_write (P_C_PCM_DMA_ENABLE | P_C_PCM_MONO | P_C_PCM_DAC_MODE | P_C_MIXER_CROSS_L_TO_L | P_C_MIXER_CROSS_R_TO_R, PCM_CONTROL); - pas_write (S_M_PCM_RESET | S_M_FM_RESET | S_M_SB_RESET | S_M_MIXER_RESET /* - * | - * S_M_OPL3_DUAL_MONO - */ , SERIAL_MIXER); + pas_write(F_F_PCM_BUFFER_COUNTER | F_F_PCM_RATE_COUNTER | F_F_MIXER_UNMUTE | 1, FILTER_FREQUENCY); + pas_write(P_C_PCM_DMA_ENABLE | P_C_PCM_MONO | P_C_PCM_DAC_MODE | P_C_MIXER_CROSS_L_TO_L | P_C_MIXER_CROSS_R_TO_R, PCM_CONTROL); + pas_write(S_M_PCM_RESET | S_M_FM_RESET | S_M_SB_RESET | S_M_MIXER_RESET /* | S_M_OPL3_DUAL_MONO */ , SERIAL_MIXER); - pas_write (I_C_1_BOOT_RESET_ENABLE, IO_CONFIGURATION_1); + pas_write(I_C_1_BOOT_RESET_ENABLE +#ifdef PAS_JOYSTICK_ENABLE + | I_C_1_JOYSTICK_ENABLE +#endif + ,IO_CONFIGURATION_1); - if (pas_irq < 0 || pas_irq > 15) - { - printk ("PAS2: Invalid IRQ %d", pas_irq); - ok = 0; - } - else - { - int_ptrs = pas_read (IO_CONFIGURATION_3); - int_ptrs |= I_C_3_PCM_IRQ_translate[pas_irq] & 0xf; - pas_write (int_ptrs, IO_CONFIGURATION_3); - if (!I_C_3_PCM_IRQ_translate[pas_irq]) - { - printk ("PAS2: Invalid IRQ %d", pas_irq); - ok = 0; + if (pas_irq < 0 || pas_irq > 15) { + printf("PAS2: Invalid IRQ %d", pas_irq); + ok = 0; + } else { + int_ptrs = pas_read(IO_CONFIGURATION_3); + int_ptrs |= I_C_3_PCM_IRQ_translate[pas_irq] & 0xf; + pas_write(int_ptrs, IO_CONFIGURATION_3); + if (!I_C_3_PCM_IRQ_translate[pas_irq]) { + printf("PAS2: Invalid IRQ %d", pas_irq); + ok = 0; + } else { + if (snd_set_irq_handler(pas_irq, pasintr, hw_config->osp) < 0) + ok = 0; + } } - } - if (hw_config->dma < 0 || hw_config->dma > 7) - { - printk ("PAS2: Invalid DMA selection %d", hw_config->dma); - ok = 0; - } - else - { - pas_write (I_C_2_PCM_DMA_translate[hw_config->dma], IO_CONFIGURATION_2); - if (!I_C_2_PCM_DMA_translate[hw_config->dma]) - { - printk ("PAS2: Invalid DMA selection %d", hw_config->dma); - ok = 0; + if (hw_config->dma < 0 || hw_config->dma > 7) { + printf("PAS2: Invalid DMA selection %d", hw_config->dma); + ok = 0; + } else { + pas_write(I_C_2_PCM_DMA_translate[hw_config->dma], IO_CONFIGURATION_2); + if (!I_C_2_PCM_DMA_translate[hw_config->dma]) { + printf("PAS2: Invalid DMA selection %d", hw_config->dma); + ok = 0; + } else { + if (0) { + printf("pas2_card.c: Can't allocate DMA channel\n"); + ok = 0; + } + } } - } - /* - * This fixes the timing problems of the PAS due to the Symphony chipset - * as per Media Vision. Only define this if your PAS doesn't work correctly. - */ + /* + * This fixes the timing problems of the PAS due to the Symphony + * chipset as per Media Vision. Only define this if your PAS doesn't + * work correctly. + */ #ifdef SYMPHONY_PAS - OUTB (0x05, 0xa8); - OUTB (0x60, 0xa9); + outb(0xa8, 0x05); + outb(0xa9, 0x60); #endif #ifdef BROKEN_BUS_CLOCK - pas_write (S_C_1_PCS_ENABLE | S_C_1_PCS_STEREO | S_C_1_PCS_REALSOUND | S_C_1_FM_EMULATE_CLOCK, SYSTEM_CONFIGURATION_1); + pas_write(S_C_1_PCS_ENABLE | S_C_1_PCS_STEREO | S_C_1_PCS_REALSOUND | S_C_1_FM_EMULATE_CLOCK, SYSTEM_CONFIGURATION_1); #else - /* - * pas_write(S_C_1_PCS_ENABLE, SYSTEM_CONFIGURATION_1); - */ - pas_write (S_C_1_PCS_ENABLE | S_C_1_PCS_STEREO | S_C_1_PCS_REALSOUND, SYSTEM_CONFIGURATION_1); + /* + * pas_write(S_C_1_PCS_ENABLE, SYSTEM_CONFIGURATION_1); + */ + pas_write(S_C_1_PCS_ENABLE | S_C_1_PCS_STEREO | S_C_1_PCS_REALSOUND, SYSTEM_CONFIGURATION_1); #endif - pas_write (0x18, SYSTEM_CONFIGURATION_3); /* - * ??? - */ + pas_write(0x18, SYSTEM_CONFIGURATION_3); /* ??? */ - pas_write (F_F_MIXER_UNMUTE | 0x01, FILTER_FREQUENCY); /* - * Sets mute - * off and * - * selects - * filter - * rate * of - * 17.897 kHz - */ + pas_write(F_F_MIXER_UNMUTE | 0x01, FILTER_FREQUENCY); /* Sets mute off and * + * selects filter rate * + * of 17.897 kHz */ + pas_write(8, PRESCALE_DIVIDER); - if (pas_model == PAS_16 || pas_model == PAS_16D) - pas_write (8, PRESCALE_DIVIDER); - else - pas_write (0, PRESCALE_DIVIDER); + mix_write(P_M_MV508_ADDRESS | 5, PARALLEL_MIXER); + mix_write(5, PARALLEL_MIXER); - pas_write (P_M_MV508_ADDRESS | 5, PARALLEL_MIXER); - pas_write (5, PARALLEL_MIXER); +#if defined(CONFIG_SB_EMULATION) && defined(CONFIG_SB) -#if !defined(EXCLUDE_SB_EMULATION) || !defined(EXCLUDE_SB) + { + struct address_info *sb_config; - { - struct address_info *sb_config; + if ((sb_config = sound_getconf(SNDCARD_SB))) { + u_char irq_dma; - if ((sb_config = sound_getconf (SNDCARD_SB))) - { - unsigned char irq_dma; + /* + * Turn on Sound Blaster compatibility + */ + /* + * bit 1 = SB emulation + */ + /* + * bit 0 = MPU401 emulation (CDPC only :-( ) + */ + pas_write(0x02, COMPATIBILITY_ENABLE); - /* - * Turn on Sound Blaster compatibility - */ - /* - * bit 1 = SB emulation - */ - /* - * bit 0 = MPU401 emulation (CDPC only :-( ) - */ - pas_write (0x02, COMPATIBILITY_ENABLE); - - /* - * "Emulation address" - */ - pas_write ((sb_config->io_base >> 4) & 0x0f, EMULATION_ADDRESS); + /* + * "Emulation address" + */ + pas_write((sb_config->io_base >> 4) & 0x0f, EMULATION_ADDRESS); - if (!E_C_SB_DMA_translate[sb_config->dma]) - printk ("\n\nPAS16 Warning: Invalid SB DMA %d\n\n", - sb_config->dma); + if (!E_C_SB_DMA_translate[sb_config->dma]) + printf("\n\nPAS16 Warning: Invalid SB DMA %d\n\n", + sb_config->dma); - if (!E_C_SB_IRQ_translate[sb_config->irq]) - printk ("\n\nPAS16 Warning: Invalid SB IRQ %d\n\n", - sb_config->irq); + if (!E_C_SB_IRQ_translate[sb_config->irq]) + printf("\n\nPAS16 Warning: Invalid SB IRQ %d\n\n", + sb_config->irq); - irq_dma = E_C_SB_DMA_translate[sb_config->dma] | - E_C_SB_IRQ_translate[sb_config->irq]; + irq_dma = E_C_SB_DMA_translate[sb_config->dma] | + E_C_SB_IRQ_translate[sb_config->irq]; - pas_write (irq_dma, EMULATION_CONFIGURATION); - } - } + pas_write(irq_dma, EMULATION_CONFIGURATION); + } + } +#else + pas_write(0x00, COMPATIBILITY_ENABLE); #endif - if (!ok) - pas2_msg ("Driver not enabled"); + if (!ok) + pas2_msg("Driver not enabled"); - return ok; + return ok; } int -detect_pas_hw (struct address_info *hw_config) +detect_pas_hw(struct address_info * hw_config) { - unsigned char board_id, foo; + u_char board_id, foo; - /* - * WARNING: Setting an option like W:1 or so that disables warm boot reset - * of the card will screw up this detect code something fierce. Adding code - * to handle this means possibly interfering with other cards on the bus if - * you have something on base port 0x388. SO be forewarned. - */ + /* + * WARNING: Setting an option like W:1 or so that disables warm boot + * reset of the card will screw up this detect code something fierce. + * Adding code to handle this means possibly interfering with other + * cards on the bus if you have something on base port 0x388. SO be + * forewarned. + */ - OUTB (0xBC, MASTER_DECODE); /* - * Talk to first board - */ - OUTB (hw_config->io_base >> 2, MASTER_DECODE); /* - * Set base address - */ - translat_code = PAS_DEFAULT_BASE ^ hw_config->io_base; - pas_write (1, WAIT_STATE); /* - * One wait-state - */ + outb(MASTER_DECODE, 0xBC); /* Talk to first board */ + outb(MASTER_DECODE, hw_config->io_base >> 2); /* Set base address */ + translat_code = PAS_DEFAULT_BASE ^ hw_config->io_base; + pas_write(1, WAIT_STATE); /* One wait-state */ - board_id = pas_read (INTERRUPT_MASK); + board_id = pas_read(INTERRUPT_MASK); - if (board_id == 0xff) - return 0; + if (board_id == 0xff) + return 0; - /* - * We probably have a PAS-series board, now check for a PAS2-series board - * by trying to change the board revision bits. PAS2-series hardware won't - * let you do this - the bits are read-only. - */ + /* + * We probably have a PAS-series board, now check for a PAS2-series + * board by trying to change the board revision bits. PAS2-series + * hardware won't let you do this - the bits are read-only. + */ - foo = board_id ^ 0xe0; + foo = board_id ^ 0xe0; - pas_write (foo, INTERRUPT_MASK); - foo = INB (INTERRUPT_MASK); - pas_write (board_id, INTERRUPT_MASK); + pas_write(foo, INTERRUPT_MASK); + foo = inb(INTERRUPT_MASK); + pas_write(board_id, INTERRUPT_MASK); - if (board_id != foo) /* - * Not a PAS2 - */ - return 0; + if (board_id != foo) /* Not a PAS2 */ + return 0; - pas_model = O_M_1_to_card[pas_read (OPERATION_MODE_1) & 0x0f]; + pas_model = pas_read(CHIP_REV); - return pas_model; + return pas_model; } -long -attach_pas_card (long mem_start, struct address_info *hw_config) +void +attach_pas_card(struct address_info * hw_config) { - pas_irq = hw_config->irq; + pas_irq = hw_config->irq; + pas_osp = hw_config->osp; - if (detect_pas_hw (hw_config)) - { + if (detect_pas_hw(hw_config)) { - if ((pas_model = O_M_1_to_card[pas_read (OPERATION_MODE_1) & 0x0f])) - { - printk (" <%s rev %d>", pas_model_names[(int) pas_model], pas_read (BOARD_REV_ID)); - } + if ((pas_model = pas_read(CHIP_REV))) { + char temp[100]; - if (config_pas_hw (hw_config)) - { + sprintf(temp, + "%s rev %d", pas_model_names[(int) pas_model], + pas_read(BOARD_REV_ID)); + conf_printf(temp, hw_config); + } + if (config_pas_hw(hw_config)) { -#ifndef EXCLUDE_AUDIO - mem_start = pas_pcm_init (mem_start, hw_config); +#ifdef CONFIG_AUDIO + pas_pcm_init(hw_config); #endif -#if !defined(EXCLUDE_SB_EMULATION) && !defined(EXCLUDE_SB) +#if defined(CONFIG_SB_EMULATION) && defined(CONFIG_SB) - sb_dsp_disable_midi (); /* - * The SB emulation don't support * - * midi - */ + sb_dsp_disable_midi(); /* The SB emulation don't + * support * midi */ #endif -#ifndef EXCLUDE_YM3812 - enable_opl3_mode (0x388, 0x38a, 0); -#endif -#ifndef EXCLUDE_MIDI -#ifdef EXCLUDE_PRO_MIDI - mem_start = pas_midi_init (mem_start); -#endif +#ifdef CONFIG_MIDI + pas_midi_init(); #endif - - pas_init_mixer (); + pas_init_mixer(); + } } - } - - return mem_start; } int -probe_pas (struct address_info *hw_config) +probe_pas(struct address_info * hw_config) { - return detect_pas_hw (hw_config); + pas_osp = hw_config->osp; + return detect_pas_hw(hw_config); } #endif |
