patch-1.3.34 linux/drivers/sound/mad16.c
Next file: linux/drivers/sound/mad16_sb_midi.c
Previous file: linux/drivers/sound/ics2101.c
Back to the patch index
Back to the overall index
- Lines: 392
- Date:
Wed Oct 11 07:55:40 1995
- Orig file:
v1.3.33/linux/drivers/sound/mad16.c
- Orig date:
Sun Aug 13 14:45:33 1995
diff -u --recursive --new-file v1.3.33/linux/drivers/sound/mad16.c linux/drivers/sound/mad16.c
@@ -1,4 +1,3 @@
-#define MAD16_OPL4 /* Disable this if you have problems with OPL3 */
/*
* sound/mad16.c
*
@@ -101,6 +100,8 @@
static int board_type = C928;
+static sound_os_info *mad16_osp;
+
#ifndef DDB
#define DDB(x)
#endif
@@ -111,22 +112,23 @@
unsigned long flags;
unsigned char tmp;
- DISABLE_INTR (flags);
+ save_flags (flags);
+ cli ();
switch (board_type) /* Output password */
{
case C928:
case MOZART:
- OUTB (0xE2, PASSWD_REG);
+ outb (0xE2, PASSWD_REG);
break;
case C929:
- OUTB (0xE3, PASSWD_REG);
+ outb (0xE3, PASSWD_REG);
break;
}
- tmp = INB (port);
- RESTORE_INTR (flags);
+ tmp = inb (port);
+ restore_flags (flags);
return tmp;
}
@@ -136,22 +138,23 @@
{
unsigned long flags;
- DISABLE_INTR (flags);
+ save_flags (flags);
+ cli ();
switch (board_type) /* Output password */
{
case C928:
case MOZART:
- OUTB (0xE2, PASSWD_REG);
+ outb (0xE2, PASSWD_REG);
break;
case C929:
- OUTB (0xE3, PASSWD_REG);
+ outb (0xE3, PASSWD_REG);
break;
}
- OUTB ((unsigned char) (value & 0xff), port);
- RESTORE_INTR (flags);
+ outb ((unsigned char) (value & 0xff), port);
+ restore_flags (flags);
}
static int
@@ -175,7 +178,7 @@
* the password. (This is how a MAD16 compatible card works).
*/
- if ((tmp2 = INB (MC1_PORT)) == tmp) /* It didn't close */
+ 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;
@@ -202,10 +205,14 @@
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.
@@ -213,14 +220,6 @@
DDB (printk ("--- Detecting MAD16 / Mozart ---\n"));
-#if 0
- for (i = 0xf8d; i <= 0xf93; i++)
- if (INB (i) != 0xff)
- {
- DDB (printk ("port 0x%03x != 0xff (0x%02x)\n", i, INB (i)));
- return 0;
- }
-#endif
/*
* Then try to detect with the old password
@@ -238,7 +237,7 @@
if (!detect_mad16 ())
return 0;
- printk ("mad16.c: 82C929 detected???\n");
+ DDB (printk ("mad16.c: 82C929 detected\n"));
}
else
{
@@ -246,12 +245,12 @@
if (((model = mad_read (MC3_PORT)) & 0x03) == 0x03)
{
- printk ("mad16.c: Mozart detected???\n");
+ DDB (printk ("mad16.c: Mozart detected\n"));
board_type = MOZART;
}
else
{
- printk ("mad16.c: 82C928 detected???\n");
+ DDB (printk ("mad16.c: 82C928 detected???\n"));
board_type = C928;
}
}
@@ -283,8 +282,6 @@
/*
* Set optional CD-ROM and joystick settings.
*/
-#define MAD16_CONF 0x06
-#define MAD16_CDSEL 0x03
#ifdef MAD16_CONF
tmp |= ((MAD16_CONF) & 0x0f); /* CD-ROM and joystick bits */
@@ -304,36 +301,168 @@
mad_write (MC2_PORT, tmp);
mad_write (MC3_PORT, 0xf0); /* Disable SB */
+ 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, 0x95); /* AD184x mode (0x9f for CS42xx) */
+ mad_write (MC5_PORT, 0xA5 | cs4231_mode);
mad_write (MC6_PORT, 0x03); /* Disable MPU401 */
}
else
{
mad_write (MC4_PORT, 0x02);
- mad_write (MC5_PORT, 0x10); /* AD184x mode (0x12 for CS42xx) */
+ mad_write (MC5_PORT, 0x30 | cs4231_mode);
}
for (i = 0xf8d; i <= 0xf93; i++)
DDB (printk ("port %03x after init = %03x\n", i, mad_read (i)));
- return probe_ms_sound (hw_config);
+/*
+ * Verify the WSS parameters
+ */
+
+ if (check_region (hw_config->io_base, 8))
+ {
+ printk ("MSS: I/O port conflict\n");
+ 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 ("MSS: Bad IRQ %d\n", hw_config->irq);
+ return 0;
+ }
+
+ if (hw_config->dma != 0 && hw_config->dma != 1 && hw_config->dma != 3)
+ {
+ printk ("MSS: Bad DMA %d\n", 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/slot\n");
+ return 0;
+ }
+
+ if (hw_config->irq > 7 && hw_config->irq != 9 && inb (hw_config->io_base + 3) & 0x80)
+ {
+ printk ("MSS: Can't use IRQ%d with a 8 bit card/slot\n", hw_config->irq);
+ return 0;
+ }
+
+ return 1;
}
long
attach_mad16 (long mem_start, struct address_info *hw_config)
{
+ static char interrupt_bits[12] =
+ {
+ -1, -1, -1, -1, -1, -1, -1, 0x08, -1, 0x10, 0x18, 0x20
+ };
+ 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;
- return attach_ms_sound (mem_start, hw_config);
+ if (!ad1848_detect (hw_config->io_base + 4, &ad_flags, mad16_osp))
+ return mem_start;
+
+ /*
+ * Set the IRQ and DMA addresses.
+ */
+
+ bits = interrupt_bits[hw_config->irq];
+ if (bits == -1)
+ return mem_start;
+
+ outb (bits | 0x40, config_port);
+ if ((inb (version_port) & 0x40) == 0)
+ printk ("[IRQ Conflict?]");
+
+/*
+ * 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))
+ {
+ dma2_bit = 0x04; /* Enable capture DMA */
+ }
+ else
+ {
+ printk ("MAD16: Invalid capture DMA\n");
+ dma2 = dma;
+ }
+ }
+ else
+ dma2 = dma;
+
+ outb (bits | dma_bits[dma] | dma2_bit, config_port); /* Write IRQ+DMA setup */
+
+ ad1848_init ("MAD16 WSS", hw_config->io_base + 4,
+ hw_config->irq,
+ dma,
+ dma2, 0,
+ hw_config->osp);
+ request_region (hw_config->io_base, 4, "MAD16 WSS config");
+
+ return mem_start;
}
long
attach_mad16_mpu (long mem_start, struct address_info *hw_config)
{
+ if (board_type < C929) /* Early chip. No MPU support. Just SB MIDI */
+ {
+#ifndef EXCLUDE_MIDI
+
+ if (mad_read (MC1_PORT) & 0x20)
+ hw_config->io_base = 0x240;
+ else
+ hw_config->io_base = 0x220;
+
+ return mad16_sb_dsp_init (mem_start, hw_config);
+#else
+ return 0;
+#endif
+ }
#if (!defined(EXCLUDE_MPU401) || !defined(EXCLUDE_MPU_EMU)) && !defined(EXCLUDE_MIDI)
if (!already_initialized)
@@ -365,10 +494,46 @@
return 0;
mpu_attached = 1;
- if (board_type < C929) /* Early chip. No MPU support */
+ if (board_type < C929) /* Early chip. No MPU support. Just SB MIDI */
{
- printk ("Mozart and OPTi 82C928 based cards don't support MPU401. Sorry\n");
+
+#ifndef EXCLUDE_MIDI
+ unsigned char tmp;
+
+ 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 ("mad16/Mozart: Invalid MIDI IRQ\n");
+ return 0;
+ }
+
+ mad_write (MC3_PORT, tmp | 0x04);
+ return mad16_sb_dsp_detect (hw_config);
+#else
return 0;
+#endif
}
tmp = 0x83; /* MPU-401 enable */
@@ -415,6 +580,25 @@
return probe_mpu401 (hw_config);
#else
return 0;
+#endif
+}
+
+void
+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);
+
+}
+
+void
+unload_mad16_mpu (struct address_info *hw_config)
+{
+#if (!defined(EXCLUDE_MPU401) || !defined(EXCLUDE_MPU_EMU)) && !defined(EXCLUDE_MIDI)
+ unload_mpu401 (hw_config);
#endif
}
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov
with Sam's (original) version of this