mad16.c
上传用户:jlfgdled
上传日期:2013-04-10
资源大小:33168k
文件大小:23k
- /*
- * Copyright (C) by Hannu Savolainen 1993-1997
- *
- * mad16.c
- *
- * Initialization code for OPTi MAD16 compatible audio chips. Including
- *
- * OPTi 82C928 MAD16 (replaced by C929)
- * OAK OTI-601D Mozart
- * OAK OTI-605 Mozart (later version with MPU401 Midi)
- * OPTi 82C929 MAD16 Pro
- * OPTi 82C930
- * OPTi 82C924
- *
- * These audio interface chips don't produce sound themselves. They just
- * connect some other components (OPL-[234] and a WSS compatible codec)
- * to the PC bus and perform I/O, DMA and IRQ address decoding. There is
- * also a UART for the MPU-401 mode (not 82C928/Mozart).
- * The Mozart chip appears to be compatible with the 82C928, although later
- * issues of the card, using the OTI-605 chip, have an MPU-401 compatable Midi
- * port. This port is configured differently to that of the OPTi audio chips.
- *
- * Changes
- *
- * Alan Cox Clean up, added module selections.
- *
- * A. Wik Added support for Opti924 PnP.
- * Improved debugging support. 16-May-1998
- * Fixed bug. 16-Jun-1998
- *
- * Torsten Duwe Made Opti924 PnP support non-destructive
- * 23-Dec-1998
- *
- * Paul Grayson Added support for Midi on later Mozart cards.
- * 25-Nov-1999
- * Christoph Hellwig Adapted to module_init/module_exit.
- * Arnaldo C. de Melo got rid of attach_uart401 21-Sep-2000
- *
- * Pavel Rabel Clean up Nov-2000
- */
- #include <linux/config.h>
- #include <linux/init.h>
- #include <linux/module.h>
- #include <linux/gameport.h>
- #include "sound_config.h"
- #include "ad1848.h"
- #include "sb.h"
- #include "mpu401.h"
- static int mad16_conf;
- static int mad16_cdsel;
- static struct gameport gameport;
- static int already_initialized = 0;
- #define C928 1
- #define MOZART 2
- #define C929 3
- #define C930 4
- #define C924 5
- /*
- * Registers
- *
- * The MAD16 occupies I/O ports 0xf8d to 0xf93 (fixed locations).
- * All ports are inactive by default. They can be activated by
- * writing 0xE2 or 0xE3 to the password register. The password is valid
- * only until the next I/O read or write.
- *
- * 82C930 uses 0xE4 as the password and indirect addressing to access
- * the config registers.
- */
- #define MC0_PORT 0xf8c /* Dummy port */
- #define MC1_PORT 0xf8d /* SB address, CD-ROM interface type, joystick */
- #define MC2_PORT 0xf8e /* CD-ROM address, IRQ, DMA, plus OPL4 bit */
- #define MC3_PORT 0xf8f
- #define PASSWD_REG 0xf8f
- #define MC4_PORT 0xf90
- #define MC5_PORT 0xf91
- #define MC6_PORT 0xf92
- #define MC7_PORT 0xf93
- #define MC8_PORT 0xf94
- #define MC9_PORT 0xf95
- #define MC10_PORT 0xf96
- #define MC11_PORT 0xf97
- #define MC12_PORT 0xf98
- static int board_type = C928;
- static int *mad16_osp;
- static int c931_detected; /* minor differences from C930 */
- static char c924pnp = 0; /* " " " C924 */
- static int debug = 0; /* debugging output */
- #ifdef DDB
- #undef DDB
- #endif
- #define DDB(x) {if (debug) x;}
- static unsigned char mad_read(int port)
- {
- unsigned long flags;
- unsigned char tmp;
- save_flags(flags);
- cli();
- switch (board_type) /* Output password */
- {
- case C928:
- case MOZART:
- outb((0xE2), PASSWD_REG);
- break;
- case C929:
- outb((0xE3), PASSWD_REG);
- break;
- case C930:
- /* outb(( 0xE4), PASSWD_REG); */
- break;
- case C924:
- /* the c924 has its ports relocated by -128 if
- PnP is enabled -aw */
- if (!c924pnp)
- outb((0xE5), PASSWD_REG); else
- outb((0xE5), PASSWD_REG - 0x80);
- break;
- }
- if (board_type == C930)
- {
- outb((port - MC0_PORT), 0xe0e); /* Write to index reg */
- tmp = inb(0xe0f); /* Read from data reg */
- }
- else
- if (!c924pnp)
- tmp = inb(port); else
- tmp = inb(port-0x80);
- restore_flags(flags);
- return tmp;
- }
- static void mad_write(int port, int value)
- {
- unsigned long flags;
- save_flags(flags);
- cli();
- switch (board_type) /* Output password */
- {
- case C928:
- case MOZART:
- outb((0xE2), PASSWD_REG);
- break;
- case C929:
- outb((0xE3), PASSWD_REG);
- break;
- case C930:
- /* outb(( 0xE4), PASSWD_REG); */
- break;
- case C924:
- if (!c924pnp)
- outb((0xE5), PASSWD_REG); else
- outb((0xE5), PASSWD_REG - 0x80);
- break;
- }
- if (board_type == C930)
- {
- outb((port - MC0_PORT), 0xe0e); /* Write to index reg */
- outb(((unsigned char) (value & 0xff)), 0xe0f);
- }
- else
- if (!c924pnp)
- outb(((unsigned char) (value & 0xff)), port); else
- outb(((unsigned char) (value & 0xff)), port-0x80);
- restore_flags(flags);
- }
- static int __init detect_c930(void)
- {
- unsigned char tmp = mad_read(MC1_PORT);
- if ((tmp & 0x06) != 0x06)
- {
- DDB(printk("Wrong C930 signature (%x)n", tmp));
- /* return 0; */
- }
- mad_write(MC1_PORT, 0);
- if (mad_read(MC1_PORT) != 0x06)
- {
- DDB(printk("Wrong C930 signature2 (%x)n", tmp));
- /* return 0; */
- }
- mad_write(MC1_PORT, tmp); /* Restore bits */
- mad_write(MC7_PORT, 0);
- if ((tmp = mad_read(MC7_PORT)) != 0)
- {
- DDB(printk("MC7 not writable (%x)n", tmp));
- return 0;
- }
- mad_write(MC7_PORT, 0xcb);
- if ((tmp = mad_read(MC7_PORT)) != 0xcb)
- {
- DDB(printk("MC7 not writable2 (%x)n", tmp));
- return 0;
- }
- tmp = mad_read(MC0_PORT+18);
- if (tmp == 0xff || tmp == 0x00)
- return 1;
- /* We probably have a C931 */
- DDB(printk("Detected C931 config=0x%02xn", tmp));
- c931_detected = 1;
- /*
- * We cannot configure the chip if it is in PnP mode.
- * If we have a CSN assigned (bit 8 in MC13) we first try
- * a software reset, then a software power off, finally
- * Clearing PnP mode. The last option is not
- * Bit 8 in MC13
- */
- if ((mad_read(MC0_PORT+13) & 0x80) == 0)
- return 1;
- /* Software reset */
- mad_write(MC9_PORT, 0x02);
- mad_write(MC9_PORT, 0x00);
- if ((mad_read(MC0_PORT+13) & 0x80) == 0)
- return 1;
-
- /* Power off, and on again */
- mad_write(MC9_PORT, 0xc2);
- mad_write(MC9_PORT, 0xc0);
- if ((mad_read(MC0_PORT+13) & 0x80) == 0)
- return 1;
-
- #if 0
- /* Force off PnP mode. This is not recommended because
- * the PnP bios will not recognize the chip on the next
- * warm boot and may assignd different resources to other
- * PnP/PCI cards.
- */
- mad_write(MC0_PORT+17, 0x04);
- #endif
- return 1;
- }
- static int __init detect_mad16(void)
- {
- unsigned char tmp, tmp2, bit;
- int i, port;
- /*
- * Check that reading a register doesn't return bus float (0xff)
- * when the card is accessed using password. This may fail in case
- * the card is in low power mode. Normally at least the power saving
- * mode bit should be 0.
- */
- if ((tmp = mad_read(MC1_PORT)) == 0xff)
- {
- DDB(printk("MC1_PORT returned 0xffn"));
- return 0;
- }
- for (i = 0xf8d; i <= 0xf98; i++)
- if (!c924pnp)
- DDB(printk("Port %0x (init value) = %0xn", i, mad_read(i))) else
- DDB(printk("Port %0x (init value) = %0xn", i-0x80, mad_read(i)));
- if (board_type == C930)
- return detect_c930();
- /*
- * Now check that the gate is closed on first I/O after writing
- * the password. (This is how a MAD16 compatible card works).
- */
- if ((tmp2 = inb(MC1_PORT)) == tmp) /* It didn't close */
- {
- DDB(printk("MC1_PORT didn't close after read (0x%02x)n", tmp2));
- return 0;
- }
- bit = (c924pnp) ? 0x20 : 0x80;
- port = (c924pnp) ? MC2_PORT : MC1_PORT;
- tmp = mad_read(port);
- mad_write(port, tmp ^ bit); /* Toggle a bit */
- if ((tmp2 = mad_read(port)) != (tmp ^ bit)) /* Compare the bit */
- {
- mad_write(port, tmp); /* Restore */
- DDB(printk("Bit revert test failed (0x%02x, 0x%02x)n", tmp, tmp2));
- return 0;
- }
- mad_write(port, tmp); /* Restore */
- return 1; /* Bingo */
- }
- static int __init wss_init(struct address_info *hw_config)
- {
- int ad_flags = 0;
- /*
- * Verify the WSS parameters
- */
- if (check_region(hw_config->io_base, 8))
- {
- printk(KERN_ERR "MSS: I/O port conflictn");
- return 0;
- }
- if (!ad1848_detect(hw_config->io_base + 4, &ad_flags, mad16_osp))
- return 0;
- /*
- * Check if the IO port returns valid signature. The original MS Sound
- * system returns 0x04 while some cards (AudioTrix Pro for example)
- * return 0x00.
- */
- if ((inb(hw_config->io_base + 3) & 0x3f) != 0x04 &&
- (inb(hw_config->io_base + 3) & 0x3f) != 0x00)
- {
- DDB(printk("No MSS signature detected on port 0x%x (0x%x)n", hw_config->io_base, inb(hw_config->io_base + 3)));
- return 0;
- }
- if (hw_config->irq > 11)
- {
- printk(KERN_ERR "MSS: Bad IRQ %dn", hw_config->irq);
- return 0;
- }
- if (hw_config->dma != 0 && hw_config->dma != 1 && hw_config->dma != 3)
- {
- printk(KERN_ERR "MSS: Bad DMA %dn", hw_config->dma);
- return 0;
- }
- /*
- * Check that DMA0 is not in use with a 8 bit board.
- */
- if (hw_config->dma == 0 && inb(hw_config->io_base + 3) & 0x80)
- {
- printk("MSS: Can't use DMA0 with a 8 bit card/slotn");
- return 0;
- }
- if (hw_config->irq > 7 && hw_config->irq != 9 && inb(hw_config->io_base + 3) & 0x80)
- printk(KERN_ERR "MSS: Can't use IRQ%d with a 8 bit card/slotn", hw_config->irq);
- return 1;
- }
- static int __init init_c930(struct address_info *hw_config)
- {
- unsigned char cfg = 0;
- if(c931_detected)
- {
- /* Bit 0 has reversd meaning. Bits 1 and 2 sese
- reversed on write.
- Support only IDE cdrom. IDE port programmed
- somewhere else. */
- cfg = (cfg & 0x09) ^ 0x07;
- }
- switch (hw_config->io_base)
- {
- case 0x530:
- cfg |= 0x00;
- break;
- case 0xe80:
- cfg |= 0x10;
- break;
- case 0xf40:
- cfg |= 0x20;
- break;
- case 0x604:
- cfg |= 0x30;
- break;
- default:
- printk(KERN_ERR "MAD16: Invalid codec port %xn", hw_config->io_base);
- return 0;
- }
- mad_write(MC1_PORT, cfg);
- /* MC2 is CD configuration. Don't touch it. */
- mad_write(MC3_PORT, 0); /* Disable SB mode IRQ and DMA */
- /* bit 2 of MC4 reverses it's meaning between the C930
- and the C931. */
- cfg = c931_detected ? 0x04 : 0x00;
- mad_write(MC4_PORT, 0x52|cfg);
- mad_write(MC5_PORT, 0x3C); /* Init it into mode2 */
- mad_write(MC6_PORT, 0x02); /* Enable WSS, Disable MPU and SB */
- mad_write(MC7_PORT, 0xCB);
- mad_write(MC10_PORT, 0x11);
- return wss_init(hw_config);
- }
- static int __init chip_detect(void)
- {
- int i;
- /*
- * Then try to detect with the old password
- */
- board_type = C924;
- DDB(printk("Detect using password = 0xE5n"));
-
- if (detect_mad16()) {
- return 1;
- }
-
- board_type = C928;
- DDB(printk("Detect using password = 0xE2n"));
- if (detect_mad16())
- {
- unsigned char model;
- if (((model = mad_read(MC3_PORT)) & 0x03) == 0x03) {
- DDB(printk("mad16.c: Mozart detectedn"));
- board_type = MOZART;
- } else {
- DDB(printk("mad16.c: 82C928 detected???n"));
- board_type = C928;
- }
- return 1;
- }
- board_type = C929;
- DDB(printk("Detect using password = 0xE3n"));
- if (detect_mad16())
- {
- DDB(printk("mad16.c: 82C929 detectedn"));
- return 1;
- }
- if (inb(PASSWD_REG) != 0xff)
- return 0;
- /*
- * First relocate MC# registers to 0xe0e/0xe0f, disable password
- */
- outb((0xE4), PASSWD_REG);
- outb((0x80), PASSWD_REG);
- board_type = C930;
- DDB(printk("Detect using password = 0xE4n"));
- for (i = 0xf8d; i <= 0xf93; i++)
- DDB(printk("port %03x = %02xn", i, mad_read(i)));
- if(detect_mad16()) {
- DDB(printk("mad16.c: 82C930 detectedn"));
- return 1;
- }
- /* The C931 has the password reg at F8D */
- outb((0xE4), 0xF8D);
- outb((0x80), 0xF8D);
- DDB(printk("Detect using password = 0xE4 for C931n"));
- if (detect_mad16()) {
- return 1;
- }
- board_type = C924;
- c924pnp++;
- DDB(printk("Detect using password = 0xE5 (again), port offset -0x80n"));
- if (detect_mad16()) {
- DDB(printk("mad16.c: 82C924 PnP detectedn"));
- return 1;
- }
-
- c924pnp=0;
- return 0;
- }
- static int __init probe_mad16(struct address_info *hw_config)
- {
- int i;
- static int valid_ports[] =
- {
- 0x530, 0xe80, 0xf40, 0x604
- };
- unsigned char tmp;
- unsigned char cs4231_mode = 0;
- int ad_flags = 0;
- if (already_initialized)
- return 0;
- mad16_osp = hw_config->osp;
- /*
- * Check that all ports return 0xff (bus float) when no password
- * is written to the password register.
- */
- DDB(printk("--- Detecting MAD16 / Mozart ---n"));
- if (!chip_detect())
- return 0;
- if (board_type == C930)
- return init_c930(hw_config);
- for (i = 0xf8d; i <= 0xf93; i++)
- if (!c924pnp)
- DDB(printk("port %03x = %02xn", i, mad_read(i))) else
- DDB(printk("port %03x = %02xn", i-0x80, mad_read(i)));
- /*
- * Set the WSS address
- */
- tmp = (mad_read(MC1_PORT) & 0x0f) | 0x80; /* Enable WSS, Disable SB */
- for (i = 0; i < 5; i++)
- {
- if (i > 3) /* Not a valid port */
- {
- printk(KERN_ERR "MAD16/Mozart: Bad WSS base address 0x%xn", hw_config->io_base);
- return 0;
- }
- if (valid_ports[i] == hw_config->io_base)
- {
- tmp |= i << 4; /* WSS port select bits */
- break;
- }
- }
- /*
- * Set optional CD-ROM and joystick settings.
- */
- tmp &= ~0x0f;
- mad_write(MC1_PORT, tmp);
- tmp = mad_read(MC2_PORT);
- mad_write(MC2_PORT, tmp);
- mad_write(MC3_PORT, 0xf0); /* Disable SB */
- if (board_type == C924) /* Specific C924 init values */
- {
- mad_write(MC4_PORT, 0xA0);
- mad_write(MC5_PORT, 0x05);
- mad_write(MC6_PORT, 0x03);
- }
- if (!ad1848_detect(hw_config->io_base + 4, &ad_flags, mad16_osp))
- return 0;
- if (ad_flags & (AD_F_CS4231 | AD_F_CS4248))
- cs4231_mode = 0x02; /* CS4248/CS4231 sync delay switch */
- if (board_type == C929)
- {
- mad_write(MC4_PORT, 0xa2);
- mad_write(MC5_PORT, 0xA5 | cs4231_mode);
- mad_write(MC6_PORT, 0x03); /* Disable MPU401 */
- }
- else
- {
- mad_write(MC4_PORT, 0x02);
- mad_write(MC5_PORT, 0x30 | cs4231_mode);
- }
- for (i = 0xf8d; i <= 0xf93; i++) if (!c924pnp)
- DDB(printk("port %03x after init = %02xn", i, mad_read(i))) else
- DDB(printk("port %03x after init = %02xn", i-0x80, mad_read(i)));
- wss_init(hw_config);
- return 1;
- }
- static void __init attach_mad16(struct address_info *hw_config)
- {
- static signed char interrupt_bits[12] = {
- -1, -1, -1, -1, -1, -1, -1, 0x08, -1, 0x10, 0x18, 0x20
- };
- signed char bits;
- static char dma_bits[4] = {
- 1, 2, 0, 3
- };
- int config_port = hw_config->io_base + 0, version_port = hw_config->io_base + 3;
- int ad_flags = 0, dma = hw_config->dma, dma2 = hw_config->dma2;
- unsigned char dma2_bit = 0;
- already_initialized = 1;
- if (!ad1848_detect(hw_config->io_base + 4, &ad_flags, mad16_osp))
- return;
- /*
- * Set the IRQ and DMA addresses.
- */
-
- if (board_type == C930 || c924pnp)
- interrupt_bits[5] = 0x28; /* Also IRQ5 is possible on C930 */
- bits = interrupt_bits[hw_config->irq];
- if (bits == -1)
- return;
- outb((bits | 0x40), config_port);
- if ((inb(version_port) & 0x40) == 0)
- printk(KERN_ERR "[IRQ Conflict?]n");
- /*
- * Handle the capture DMA channel
- */
- if (ad_flags & AD_F_CS4231 && dma2 != -1 && dma2 != dma)
- {
- if (!((dma == 0 && dma2 == 1) ||
- (dma == 1 && dma2 == 0) ||
- (dma == 3 && dma2 == 0)))
- { /* Unsupported combination. Try to swap channels */
- int tmp = dma;
- dma = dma2;
- dma2 = tmp;
- }
- if ((dma == 0 && dma2 == 1) || (dma == 1 && dma2 == 0) ||
- (dma == 3 && dma2 == 0))
- {
- dma2_bit = 0x04; /* Enable capture DMA */
- }
- else
- {
- printk("MAD16: Invalid capture DMAn");
- dma2 = dma;
- }
- }
- else dma2 = dma;
- outb((bits | dma_bits[dma] | dma2_bit), config_port); /* Write IRQ+DMA setup */
- hw_config->slots[0] = ad1848_init("mad16 WSS", hw_config->io_base + 4,
- hw_config->irq,
- dma,
- dma2, 0,
- hw_config->osp,
- THIS_MODULE);
- request_region(hw_config->io_base, 4, "mad16 WSS config");
- }
- static int __init probe_mad16_mpu(struct address_info *hw_config)
- {
- static int mpu_attached = 0;
- unsigned char tmp;
- if (!already_initialized) /* The MSS port must be initialized first */
- return 0;
- if (mpu_attached) /* Don't let them call this twice */
- return 0;
- mpu_attached = 1;
- if (board_type < C929) /* Early chip. No MPU support. Just SB MIDI */
- {
- #ifdef CONFIG_MAD16_OLDCARD
- tmp = mad_read(MC3_PORT);
- /*
- * MAD16 SB base is defined by the WSS base. It cannot be changed
- * alone.
- * Ignore configured I/O base. Use the active setting.
- */
- if (mad_read(MC1_PORT) & 0x20)
- hw_config->io_base = 0x240;
- else
- hw_config->io_base = 0x220;
- switch (hw_config->irq)
- {
- case 5:
- tmp = (tmp & 0x3f) | 0x80;
- break;
- case 7:
- tmp = (tmp & 0x3f);
- break;
- case 11:
- tmp = (tmp & 0x3f) | 0x40;
- break;
- default:
- printk(KERN_ERR "mad16/Mozart: Invalid MIDI IRQn");
- return 0;
- }
- mad_write(MC3_PORT, tmp | 0x04);
- hw_config->driver_use_1 = SB_MIDI_ONLY;
- if (!sb_dsp_detect(hw_config, 0, 0, NULL))
- return 0;
- if (mad_read(MC1_PORT) & 0x20)
- hw_config->io_base = 0x240;
- else
- hw_config->io_base = 0x220;
- hw_config->name = "Mad16/Mozart";
- sb_dsp_init(hw_config, THIS_MODULE);
- return 1;
- #else
- /* assuming all later Mozart cards are identified as
- * either 82C928 or Mozart. If so, following code attempts
- * to set MPU register. TODO - add probing
- */
- tmp = mad_read(MC8_PORT);
- switch (hw_config->irq)
- {
- case 5:
- tmp |= 0x08;
- break;
- case 7:
- tmp |= 0x10;
- break;
- case 9:
- tmp |= 0x18;
- break;
- case 10:
- tmp |= 0x20;
- break;
- case 11:
- tmp |= 0x28;
- break;
- default:
- printk(KERN_ERR "mad16/MOZART: invalid mpu_irqn");
- return 0;
- }
- switch (hw_config->io_base)
- {
- case 0x300:
- tmp |= 0x01;
- break;
- case 0x310:
- tmp |= 0x03;
- break;
- case 0x320:
- tmp |= 0x05;
- break;
- case 0x330:
- tmp |= 0x07;
- break;
- default:
- printk(KERN_ERR "mad16/MOZART: invalid mpu_ion");
- return 0;
- }
- mad_write(MC8_PORT, tmp); /* write MPU port parameters */
- goto probe_401;
- #endif
- }
- tmp = mad_read(MC6_PORT) & 0x83;
- tmp |= 0x80; /* MPU-401 enable */
- /* Set the MPU base bits */
- switch (hw_config->io_base)
- {
- case 0x300:
- tmp |= 0x60;
- break;
- case 0x310:
- tmp |= 0x40;
- break;
- case 0x320:
- tmp |= 0x20;
- break;
- case 0x330:
- tmp |= 0x00;
- break;
- default:
- printk(KERN_ERR "MAD16: Invalid MIDI port 0x%xn", hw_config->io_base);
- return 0;
- }
- /* Set the MPU IRQ bits */
- switch (hw_config->irq)
- {
- case 5:
- tmp |= 0x10;
- break;
- case 7:
- tmp |= 0x18;
- break;
- case 9:
- tmp |= 0x00;
- break;
- case 10:
- tmp |= 0x08;
- break;
- default:
- printk(KERN_ERR "MAD16: Invalid MIDI IRQ %dn", hw_config->irq);
- break;
- }
-
- mad_write(MC6_PORT, tmp); /* Write MPU401 config */
- #ifndef CONFIG_MAD16_OLDCARD
- probe_401:
- #endif
- hw_config->driver_use_1 = SB_MIDI_ONLY;
- hw_config->name = "Mad16/Mozart";
- return probe_uart401(hw_config, THIS_MODULE);
- }
- static void __exit unload_mad16(struct address_info *hw_config)
- {
- ad1848_unload(hw_config->io_base + 4,
- hw_config->irq,
- hw_config->dma,
- hw_config->dma2, 0);
- release_region(hw_config->io_base, 4);
- sound_unload_audiodev(hw_config->slots[0]);
- }
- static void __exit unload_mad16_mpu(struct address_info *hw_config)
- {
- #ifdef CONFIG_MAD16_OLDCARD
- if (board_type < C929) /* Early chip. No MPU support. Just SB MIDI */
- {
- sb_dsp_unload(hw_config, 0);
- return;
- }
- #endif
- unload_uart401(hw_config);
- }
- static struct address_info cfg;
- static struct address_info cfg_mpu;
- static int found_mpu;
- static int __initdata mpu_io = 0;
- static int __initdata mpu_irq = 0;
- static int __initdata io = -1;
- static int __initdata dma = -1;
- static int __initdata dma16 = -1; /* Set this for modules that need it */
- static int __initdata irq = -1;
- static int __initdata cdtype = 0;
- static int __initdata cdirq = 0;
- static int __initdata cdport = 0x340;
- static int __initdata cddma = -1;
- static int __initdata opl4 = 0;
- static int __initdata joystick = 0;
- MODULE_PARM(mpu_io, "i");
- MODULE_PARM(mpu_irq, "i");
- MODULE_PARM(io,"i");
- MODULE_PARM(dma,"i");
- MODULE_PARM(dma16,"i");
- MODULE_PARM(irq,"i");
- MODULE_PARM(cdtype,"i");
- MODULE_PARM(cdirq,"i");
- MODULE_PARM(cdport,"i");
- MODULE_PARM(cddma,"i");
- MODULE_PARM(opl4,"i");
- MODULE_PARM(joystick,"i");
- MODULE_PARM(debug,"i");
- static int __initdata dma_map[2][8] =
- {
- {0x03, -1, -1, -1, -1, 0x00, 0x01, 0x02},
- {0x03, -1, 0x01, 0x00, -1, -1, -1, -1}
- };
- static int __initdata irq_map[16] =
- {
- 0x00, -1, -1, 0x0A,
- -1, 0x04, -1, 0x08,
- -1, 0x10, 0x14, 0x18,
- -1, -1, -1, -1
- };
- static int __init init_mad16(void)
- {
- int dmatype = 0;
- printk(KERN_INFO "MAD16 audio driver Copyright (C) by Hannu Savolainen 1993-1996n");
- printk(KERN_INFO "CDROM ");
- switch (cdtype)
- {
- case 0x00:
- printk("Disabled");
- cdirq = 0;
- break;
- case 0x02:
- printk("Sony CDU31A");
- dmatype = 1;
- if(cddma == -1) cddma = 3;
- break;
- case 0x04:
- printk("Mitsumi");
- dmatype = 0;
- if(cddma == -1) cddma = 5;
- break;
- case 0x06:
- printk("Panasonic Lasermate");
- dmatype = 1;
- if(cddma == -1) cddma = 3;
- break;
- case 0x08:
- printk("Secondary IDE");
- dmatype = 0;
- if(cddma == -1) cddma = 5;
- break;
- case 0x0A:
- printk("Primary IDE");
- dmatype = 0;
- if(cddma == -1) cddma = 5;
- break;
- default:
- printk("n");
- printk(KERN_ERR "Invalid CDROM typen");
- return -EINVAL;
- }
- /*
- * Build the config words
- */
- mad16_conf = (joystick ^ 1) | cdtype;
- mad16_cdsel = 0;
- if (opl4)
- mad16_cdsel |= 0x20;
- if(cdtype){
- if (cddma > 7 || cddma < 0 || dma_map[dmatype][cddma] == -1)
- {
- printk("n");
- printk(KERN_ERR "Invalid CDROM DMAn");
- return -EINVAL;
- }
- if (cddma)
- printk(", DMA %d", cddma);
- else
- printk(", no DMA");
- if (!cdirq)
- printk(", no IRQ");
- else if (cdirq < 0 || cdirq > 15 || irq_map[cdirq] == -1)
- {
- printk(", invalid IRQ (disabling)");
- cdirq = 0;
- }
- else printk(", IRQ %d", cdirq);
- mad16_cdsel |= dma_map[dmatype][cddma];
- if (cdtype < 0x08)
- {
- switch (cdport)
- {
- case 0x340:
- mad16_cdsel |= 0x00;
- break;
- case 0x330:
- mad16_cdsel |= 0x40;
- break;
- case 0x360:
- mad16_cdsel |= 0x80;
- break;
- case 0x320:
- mad16_cdsel |= 0xC0;
- break;
- default:
- printk(KERN_ERR "Unknown CDROM I/O base %dn", cdport);
- return -EINVAL;
- }
- }
- mad16_cdsel |= irq_map[cdirq];
- }
- printk(".n");
- cfg.io_base = io;
- cfg.irq = irq;
- cfg.dma = dma;
- cfg.dma2 = dma16;
- if (cfg.io_base == -1 || cfg.dma == -1 || cfg.irq == -1) {
- printk(KERN_ERR "I/O, DMA and irq are mandatoryn");
- return -EINVAL;
- }
-
- if (!probe_mad16(&cfg))
- return -ENODEV;
- cfg_mpu.io_base = mpu_io;
- cfg_mpu.irq = mpu_irq;
- attach_mad16(&cfg);
- found_mpu = probe_mad16_mpu(&cfg_mpu);
- if (joystick == 1) {
- /* register gameport */
- if (!request_region(0x201, 1, "mad16 gameport"))
- printk(KERN_ERR "mad16: gameport address 0x201 already in usen");
- else {
- printk(KERN_ERR "mad16: gameport enabled at 0x201n");
- gameport.io = 0x201;
- gameport_register_port(&gameport);
- }
- }
- else printk(KERN_ERR "mad16: gameport disabled.n");
- return 0;
- }
- static void __exit cleanup_mad16(void)
- {
- if (found_mpu)
- unload_mad16_mpu(&cfg_mpu);
- unload_mad16(&cfg);
- }
- module_init(init_mad16);
- module_exit(cleanup_mad16);
- #ifndef MODULE
- static int __init setup_mad16(char *str)
- {
- /* io, irq */
- int ints[8];
-
- str = get_options(str, ARRAY_SIZE(ints), ints);
- io = ints[1];
- irq = ints[2];
- dma = ints[3];
- dma16 = ints[4];
- mpu_io = ints[5];
- mpu_irq = ints[6];
- joystick = ints[7];
- return 1;
- }
- __setup("mad16=", setup_mad16);
- #endif
- MODULE_LICENSE("GPL");