patch-1.3.9 linux/drivers/sound/aedsp16.c
Next file: linux/drivers/sound/audio.c
Previous file: linux/drivers/sound/ad1848_mixer.h
Back to the patch index
Back to the overall index
- Lines: 868
- Date:
Mon Jul 10 01:45:03 1995
- Orig file:
v1.3.8/linux/drivers/sound/aedsp16.c
- Orig date:
Thu Jan 1 02:00:00 1970
diff -u --recursive --new-file v1.3.8/linux/drivers/sound/aedsp16.c linux/drivers/sound/aedsp16.c
@@ -0,0 +1,867 @@
+/*
+ sound/aedsp16.c
+
+ Audio Excel DSP 16 software configuration routines
+
+ Copyright (C) 1995 Riccardo Facchetti (riccardo@cdc8g5.cdc.polimi.it)
+
+ 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
+ notice, this list of conditions and the following disclaimer. 2.
+ 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
+ DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
+ ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ 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 the main voxware header file. It include all the os/voxware/etc
+ * headers needed by this source.
+ */
+#include "sound_config.h"
+/*
+ * all but ioport.h :)
+ */
+#include <linux/ioport.h>
+
+#if defined(CONFIGURE_SOUNDCARD) && !defined(EXCLUDE_AEDSP16)
+/*
+
+ READ THIS
+
+ This module is intended for Audio Excel DSP 16 Sound Card.
+
+ Audio Excel DSP 16 is an SB pro II, Microsoft Sound System
+ and MPU-401 compatible card.
+ It is software-only configurable (no jumpers to hard-set irq/dma/mpu-irq),
+ so before this module, the only way to configure the DSP under linux was
+ boot the MS-BAU loading the sound.sys device driver (this driver soft-
+ configure the sound board hardware by massaging someone of its registers),
+ and then ctrl-alt-del to boot linux with the DSP configured by the DOG
+ driver.
+
+ This module works configuring your Audio Excel DSP 16's
+ irq, dma and mpu-401-irq. The voxware probe routines rely on the
+ fact that if the hardware is there, they can detect it. The problem
+ with AEDSP16 is that no hardware can be found by the probe routines
+ if the sound card is not well configured. Sometimes the kernel probe
+ routines can find an SBPRO even when the card is not configured (this
+ is the standard setup of the card), but the SBPRO emulation don't work
+ well if the card is not properly initialized. For this reason
+
+ InitAEDSP16_...()
+
+ routines are called before the voxware probe routines try to detect the
+ hardware.
+
+ NOTE (READ THE NOTE TOO, IT CONTAIN USEFUL INFORMATIONS)
+
+ The Audio Excel DSP 16 Sound Card emulates both SBPRO and MSS;
+ the voxware sound driver can be configured for SBPRO and MSS cards
+ at the same time, but the aedsp16 can't be two cards!!
+ When we configure it, we have to choose the SBPRO or the MSS emulation
+ for AEDSP16. We also can install a *REAL* card of the other type
+ (see [1], not tested but I can't see any reason for it to fail).
+
+ NOTE: If someone can test the combination AEDSP16+MSS or AEDSP16+SBPRO
+ please let me know if it works.
+
+ The MPU-401 support can be compiled in together with one of the other
+ two operating modes.
+
+ The board configuration calls, are in the probe_...() routines because
+ we have to configure the board before probing it for a particular
+ hardware. After card configuration, we can probe the hardware.
+
+ NOTE: This is something like plug-and-play: we have only to plug
+ the AEDSP16 board in the socket, and then configure and compile
+ a kernel that uses the AEDSP16 software configuration capability.
+ No jumper setting is needed!
+
+ For example, if you want AEDSP16 to be an SBPro, on irq 10, dma 3
+ you have just to make config the voxware package, configuring
+ the SBPro sound card with that parameters, then when configure
+ asks if you have an AEDSP16, answer yes. That's it.
+ Compile the kernel and run it.
+
+ NOTE: This means that you can choose irq and dma, but not the
+ I/O addresses. To change I/O addresses you have to set them
+ with jumpers.
+
+ NOTE: InitAEDSP16_...() routines get as parameter the hw_config,
+ the hardware configuration of the - to be configured - board.
+ The InitAEDSP16() routine, configure the board following our
+ wishes, that are in the hw_config structure.
+
+ You can change the irq/dma/mirq settings WITHOUT THE NEED to open
+ your computer and massage the jumpers (there are no irq/dma/mirq
+ jumpers to be configured anyway, only I/O port ones have to be
+ configured with jumpers)
+
+ For some ununderstandable reason, the card default of irq 7, dma 1,
+ don't work for me. Seems to be an IRQ or DMA conflict. Under heavy
+ HDD work, the kernel start to erupt out a lot of messages like:
+
+ 'Sound: DMA timed out - IRQ/DRQ config error?'
+
+ For what I can say, I have NOT any conflict at irq 7 (under linux I'm
+ using the lp polling driver), and dma line 1 is unused as stated by
+ /proc/dma. I can suppose this is a bug of AEDSP16. I know my hardware so
+ I'm pretty sure I have not any conflict, but may be I'm wrong. Who knows!
+ Anyway a setting of irq 10, dma 3 works really fine.
+
+ NOTE: if someone can use AEDSP16 with irq 7, dma 1, please let me know
+ the emulation mode, all the installed hardware and the hardware
+ configuration (irq and dma settings of all the hardware).
+
+ This init module should work with SBPRO+MSS, when one of the two is
+ the AEDSP16 emulation and the other the real card. (see [1])
+ For example:
+
+ AEDSP16 (0x220) in SBPRO emu (0x220) + real MSS + other
+ AEDSP16 (0x220) in MSS emu + real SBPRO (0x240) + other
+
+ MPU401 should work. (see [1])
+
+ [1] Not tested by me for lack of hardware.
+
+ TODO, WISHES AND TECH
+
+ May be there's lot of redundant delays, but for now I want to leave it
+ this way.
+
+ Should be interesting eventually write down a new ioctl for the
+ aedsp16, to let the suser() change the irq/dma/mirq on the fly.
+ The thing is not trivial.
+ In the real world, there's no need to have such an ioctl because
+ when we configure the kernel for compile, we can choose the config
+ parameters. If we change our mind, we can easily re-config the kernel
+ and re-compile.
+ Why let the suser() change the config parameters on the fly ?
+ If anyone have a reasonable answer to this question, I will write down
+ the code to do it.
+
+ More integration with voxware, using voxware low level routines to
+ read-write dsp is not possible because you may want to have MSS
+ support and in that case we can not rely on the functions included
+ in sb_dsp.c to control 0x2yy I/O ports. I will continue to use my
+ own I/O functions.
+
+ - About I/O ports allocation -
+
+ The request_region should be done at device probe in every sound card
+ module. This module is not the best site for requesting regions.
+ When the request_region code will be added to the main modules such as
+ sb, adlib, gus, ad1848, etc, the requesting code in this module should
+ go away.
+
+ I think the request regions should be done this way:
+
+ if (check_region(...))
+ return ERR; // I/O region alredy reserved
+ device_probe(...);
+ device_attach(...);
+ request_region(...); // reserve only when we are sure all is okay
+
+ Request the 2x0h region in any case if we are using this card.
+
+ NOTE: the "(sbpro)" string with which we are requesting the aedsp16 region
+ (see code) does not mean necessarly that we are emulating sbpro.
+ It mean that the region is the sbpro I/O ports region. We use this
+ region to access the control registers of the card, and if emulating
+ sbpro, I/O sbpro registers too. If we are emulating MSS, the sbpro
+ registers are not used, in no way, to emulate an sbpro: they are
+ used only for configuration pourposes.
+
+ Someone pointed out that should be possible use both the SBPRO and MSS
+ modes because the sound card have all the two chipsets, supposing that
+ the card is really two cards. I have tried something to have the two
+ modes work together, but, for some reason unknown to me, without success.
+
+ I think all the soft-config only cards have an init sequence similar to
+ this. If you have a card that is not an aedsp16, you can try to start
+ with this module changing it (mainly in the CMD? I think) to fit your
+ needs.
+
+ Started Fri Mar 17 16:13:18 MET 1995
+
+ v0.1 (ALPHA, was an user-level program called AudioExcelDSP16.c)
+ - Initial code.
+ v0.2 (ALPHA)
+ - Cleanups.
+ - Integrated with Linux voxware v 2.90-2 kernel sound driver.
+ - SoundBlaster Pro mode configuration.
+ - Microsoft Sound System mode configuration.
+ - MPU-401 mode configuration.
+ v0.3 (ALPHA)
+ - Cleanups.
+ - Rearranged the code to let InitAEDSP16 be more general.
+ - Erased the REALLY_SLOW_IO. We don't need it. Erased the linux/io.h
+ inclusion too. We rely on os.h
+ - Used the INB and OUTB #defined in os.h instead of inb and outb.
+ - Corrected the code for GetCardName (DSP Copyright) to get a variable
+ len string (we are not sure about the len of Copyright string).
+ This works with any SB and compatible.
+ - Added the code to request_region at device init (should go in
+ the main body of voxware).
+ v0.4 (BETA)
+ - Better configure.c patch for aedsp16 configuration (better
+ logic of inclusion of AEDSP16 support)
+ - Modified the conditional compilation to better support more than
+ one sound card of the emulated type (read the NOTES above)
+ - Moved the sb init routine from the attach to the very first
+ probe in sb_card.c
+ - Rearrangemens and cleanups
+ - Wiped out some unnecessary code and variables: this is kernel
+ code so it is better save some TEXT and DATA
+ - Fixed the request_region code. We must allocate the aedsp16 (sbpro)
+ I/O ports in any case because they are used to access the DSP
+ configuration registers and we can not allow anyone to get them.
+ v0.5
+ - cleanups on comments
+ - prep for diffs against v3.0-proto-950402
+ v0.6
+ - removed the request_region()s when compiling the MODULE sound.o
+ because we are not allowed (by the actual voxware structure) to
+ release_region()
+
+ */
+
+
+#define VERSION "0.6" /* Version of Audio Excel DSP 16 driver */
+
+#undef AEDSP16_DEBUG /* Define this to enable debug code */
+/* Actually no debug code is activated */
+
+/*
+ * Hardware related defaults
+ */
+#define IRQ 7 /* 5 7(default) 9 10 11 */
+#define MIRQ 0 /* 5 7 9 10 0(default), 0 means disable */
+#define DMA 1 /* 0 1(default) 3 */
+
+/*
+ * Commands of AEDSP16's DSP (SBPRO+special).
+ * For now they are CMDn, in the future they may change.
+ */
+#define CMD1 0xe3 /* Get DSP Copyright */
+#define CMD2 0xe1 /* Get DSP Version */
+#define CMD3 0x88 /* */
+#define CMD4 0x5c /* */
+#define CMD5 0x50 /* Set M&I&DRQ mask (the real config) */
+#define CMD6 0x8c /* Enable Microsoft Sound System mode */
+
+/*
+ * Offsets of AEDSP16 DSP I/O ports. The offest is added to portbase
+ * to have the actual I/O port.
+ * Register permissions are:
+ * (wo) == Write Only
+ * (ro) == Read Only
+ * (w-) == Write
+ * (r-) == Read
+ */
+#define DSP_RESET 0x06 /* offset of DSP RESET (wo) */
+#define DSP_READ 0x0a /* offset of DSP READ (ro) */
+#define DSP_WRITE 0x0c /* offset of DSP WRITE (w-) */
+#define DSP_COMMAND 0x0c /* offset of DSP COMMAND (w-) */
+#define DSP_STATUS 0x0c /* offset of DSP STATUS (r-) */
+#define DSP_DATAVAIL 0x0e /* offset of DSP DATA AVAILABLE (ro) */
+
+
+#define RETRY 10 /* Various retry values on I/O opera- */
+#define STATUSRETRY 1000 /* tions. Sometimes we have to */
+#define HARDRETRY 500000 /* wait for previous cmd to complete */
+
+/*
+ * Size of character arrays that store name and version of sound card
+ */
+#define CARDNAMELEN 15 /* Size of the card's name in chars */
+#define CARDVERLEN 2 /* Size of the card's version in chars */
+
+/*
+ * Bit mapped flags for calling InitAEDSP16(), and saving the current
+ * emulation mode.
+ */
+#define INIT_NONE (0 )
+#define INIT_SBPRO (1<<0)
+#define INIT_MSS (1<<1)
+#define INIT_MPU401 (1<<2)
+#define RESET_DSP16 (1<<3)
+
+/* Base HW Port for Audio Card */
+static int portbase = AEDSP16_BASE;
+static int irq = IRQ; /* irq for DSP I/O */
+static int mirq = MIRQ; /* irq for MPU-401 I/O */
+static int dma = DMA; /* dma for DSP I/O */
+
+/* Init status of the card */
+static int ae_init = INIT_NONE; /* (bitmapped variable) */
+static int oredparams = 0; /* Will contain or'ed values of params */
+static int gc = 0; /* generic counter (utility counter) */
+struct orVals
+ { /* Contain the values to be or'ed */
+ int val; /* irq|mirq|dma */
+ int or; /* oredparams |= TheStruct.or */
+ };
+
+/*
+ * Magic values that the DSP will eat when configuring irq/mirq/dma
+ */
+/* DSP IRQ conversion array */
+static struct orVals orIRQ[] =
+{
+ {0x05, 0x28},
+ {0x07, 0x08},
+ {0x09, 0x10},
+ {0x0a, 0x18},
+ {0x0b, 0x20},
+ {0x00, 0x00}
+};
+
+/* MPU-401 IRQ conversion array */
+static struct orVals orMIRQ[] =
+{
+ {0x05, 0x04},
+ {0x07, 0x44},
+ {0x09, 0x84},
+ {0x0a, 0xc4},
+ {0x00, 0x00}
+};
+
+/* DMA Channels conversion array */
+static struct orVals orDMA[] =
+{
+ {0x00, 0x01},
+ {0x01, 0x02},
+ {0x03, 0x03},
+ {0x00, 0x00}
+};
+
+/*
+ * Buffers to store audio card informations
+ */
+static char AudioExcelName[CARDNAMELEN + 1];
+static char AudioExcelVersion[CARDVERLEN + 1];
+
+static void
+tenmillisec (void)
+{
+
+ for (gc = 0; gc < 1000; gc++)
+ tenmicrosec ();
+}
+
+static int
+WaitForDataAvail (int port)
+{
+ int loop = STATUSRETRY;
+ unsigned char ret = 0;
+
+ do
+ {
+ ret = INB (port + DSP_DATAVAIL);
+ /*
+ * Wait for data available (bit 7 of ret == 1)
+ */
+ }
+ while (!(ret & 0x80) && loop--);
+
+ if (ret & 0x80)
+ return 0;
+
+ return -1;
+}
+
+static int
+ReadData (int port)
+{
+ if (WaitForDataAvail (port))
+ return -1;
+ return INB (port + DSP_READ);
+}
+
+static int
+CheckDSPOkay (int port)
+{
+ return ((ReadData (port) == 0xaa) ? 0 : -1);
+}
+
+static int
+ResetBoard (int port)
+{
+ /*
+ * Reset DSP
+ */
+ OUTB (1, (port + DSP_RESET));
+ tenmicrosec ();
+ OUTB (0, (port + DSP_RESET));
+ tenmicrosec ();
+ tenmicrosec ();
+ return CheckDSPOkay (port);
+}
+
+static int
+WriteDSPCommand (int port, int cmd)
+{
+ unsigned char ret;
+ int loop = HARDRETRY;
+
+ do
+ {
+ ret = INB (port + DSP_STATUS);
+ /*
+ * DSP ready to receive data if bit 7 of ret == 0
+ */
+ if (!(ret & 0x80))
+ {
+ OUTB (cmd, port + DSP_COMMAND);
+ return 0;
+ }
+ }
+ while (loop--);
+
+ printk ("[aedsp16] DSP Command (0x%x) timeout.\n", cmd);
+ return -1;
+}
+
+int
+InitMSS (int port)
+{
+
+ tenmillisec ();
+
+ if (WriteDSPCommand (port, CMD6))
+ {
+ printk ("[aedsp16] CMD 0x%x: failed!\n", CMD6);
+ return -1;
+ }
+
+ tenmillisec ();
+
+ return 0;
+}
+
+static int
+SetUpBoard (int port)
+{
+ int loop = RETRY;
+
+ do
+ {
+ if (WriteDSPCommand (portbase, CMD3))
+ {
+ printk ("[aedsp16] CMD 0x%x: failed!\n", CMD3);
+ return -1;
+ }
+
+ tenmillisec ();
+
+ }
+ while (WaitForDataAvail (port) && loop--);
+
+#if defined(THIS_SHOULD_GO_AWAY)
+ if (CheckDSPOkay (port))
+ {
+ printk ("[aedsp16] CheckDSPOkay: failed\n");
+ return -1;
+ }
+#else
+ if (ReadData (port) == -1)
+ {
+ printk ("[aedsp16] ReadData after CMD 0x%x: failed\n", CMD3);
+ return -1;
+ }
+#endif
+
+ if (WriteDSPCommand (portbase, CMD4))
+ {
+ printk ("[aedsp16] CMD 0x%x: failed!\n", CMD4);
+ return -1;
+ }
+
+ if (WriteDSPCommand (portbase, CMD5))
+ {
+ printk ("[aedsp16] CMD 0x%x: failed!\n", CMD5);
+ return -1;
+ }
+
+ if (WriteDSPCommand (portbase, oredparams))
+ {
+ printk ("[aedsp16] Initialization of (M)IRQ and DMA: failed!\n");
+ return -1;
+ }
+ return 0;
+}
+
+static int
+GetCardVersion (int port)
+{
+ int len = 0;
+ int ret;
+ int ver[3];
+
+ do
+ {
+ if ((ret = ReadData (port)) == -1)
+ return -1;
+ /*
+ * We alredy know how many int are stored (2), so we know when the
+ * string is finished.
+ */
+ ver[len++] = ret;
+ }
+ while (len < CARDVERLEN);
+ sprintf (AudioExcelVersion, "%d.%d", ver[0], ver[1]);
+ return 0;
+}
+
+static int
+GetCardName (int port)
+{
+ int len = 0;
+ int ret;
+
+ do
+ {
+ if ((ret = ReadData (port)) == -1)
+ /*
+ * If no more data availabe, return to the caller, no error if len>0.
+ * We have no other way to know when the string is finished.
+ */
+ return (len ? 0 : -1);
+
+ AudioExcelName[len++] = ret;
+
+ }
+ while (len < CARDNAMELEN);
+ return 0;
+}
+
+static void
+InitializeHardParams (void)
+{
+
+ memset (AudioExcelName, 0, CARDNAMELEN + 1);
+ memset (AudioExcelVersion, 0, CARDVERLEN + 1);
+
+ for (gc = 0; orIRQ[gc].or; gc++)
+ if (orIRQ[gc].val == irq)
+ oredparams |= orIRQ[gc].or;
+
+ for (gc = 0; orMIRQ[gc].or; gc++)
+ if (orMIRQ[gc].or == mirq)
+ oredparams |= orMIRQ[gc].or;
+
+ for (gc = 0; orDMA[gc].or; gc++)
+ if (orDMA[gc].val == dma)
+ oredparams |= orDMA[gc].or;
+}
+
+static int
+InitAEDSP16 (int which)
+{
+ static char *InitName = NULL;
+
+ InitializeHardParams ();
+
+ if (ResetBoard (portbase))
+ {
+ printk ("[aedsp16] ResetBoard: failed!\n");
+ return -1;
+ }
+
+#if defined(THIS_SHOULD_GO_AWAY)
+ if (CheckDSPOkay (portbase))
+ {
+ printk ("[aedsp16] CheckDSPOkay: failed!\n");
+ return -1;
+ }
+#endif
+
+ if (WriteDSPCommand (portbase, CMD1))
+ {
+ printk ("[aedsp16] CMD 0x%x: failed!\n", CMD1);
+ return -1;
+ }
+
+ if (GetCardName (portbase))
+ {
+ printk ("[aedsp16] GetCardName: failed!\n");
+ return -1;
+ }
+
+ /*
+ * My AEDSP16 card return SC-6000 in AudioExcelName, so
+ * if we have something different, we have to be warned.
+ */
+ if (strcmp ("SC-6000", AudioExcelName))
+ printk ("[aedsp16] Warning: non SC-6000 audio card!\n");
+
+ if (WriteDSPCommand (portbase, CMD2))
+ {
+ printk ("[aedsp16] CMD 0x%x: failed!\n", CMD2);
+ return -1;
+ }
+
+ if (GetCardVersion (portbase))
+ {
+ printk ("[aedsp16] GetCardVersion: failed!\n");
+ return -1;
+ }
+
+ if (SetUpBoard (portbase))
+ {
+ printk ("[aedsp16] SetUpBoard: failed!\n");
+ return -1;
+ }
+
+ if (which == INIT_MSS)
+ {
+ if (InitMSS (portbase))
+ {
+ printk ("[aedsp16] Can't initialize Microsoft Sound System mode.\n");
+ return -1;
+ }
+ }
+
+ /*
+ * If we are resetting, do not print any message because we may be
+ * in playing and we do not want lost too much time.
+ */
+ if (!(which & RESET_DSP16))
+ {
+ if (which & INIT_MPU401)
+ InitName = "MPU401";
+ else if (which & INIT_SBPRO)
+ InitName = "SBPro";
+ else if (which & INIT_MSS)
+ InitName = "MSS";
+ else
+ InitName = "None";
+
+ printk ("Audio Excel DSP 16 init v%s (%s %s) [%s]\n",
+ VERSION, AudioExcelName,
+ AudioExcelVersion, InitName);
+ }
+
+ tenmillisec ();
+
+ return 0;
+}
+
+#if defined(AEDSP16_SBPRO)
+
+int
+InitAEDSP16_SBPRO (struct address_info *hw_config)
+{
+ /*
+ * If the card is alredy init'ed MSS, we can not init it to SBPRO too
+ * because the board can not emulate simultaneously MSS and SBPRO.
+ */
+ if (ae_init & INIT_MSS)
+ return -1;
+ if (ae_init & INIT_SBPRO)
+ return 0;
+
+ /*
+ * For now we will leave this
+ * code included only when INCLUDE_AEDSP16 is configured in, but it should
+ * be better include it every time.
+ */
+ if (!(ae_init & INIT_MPU401))
+ {
+ if (check_region (hw_config->io_base, 0x0f))
+ {
+ printk ("AEDSP16/SBPRO I/O port region is alredy in use.\n");
+ return -1;
+ }
+ }
+
+ /*
+ * Set up the internal hardware parameters, to let the driver reach
+ * the Sound Card.
+ */
+ portbase = hw_config->io_base;
+ irq = hw_config->irq;
+ dma = hw_config->dma;
+ if (InitAEDSP16 (INIT_SBPRO))
+ return -1;
+
+#if !defined(MODULE)
+ /*
+ * If we are compiling sound.o (MODULAR version) we can not
+ * request any region because there is not a uninit routine that
+ * can allow me to release the requested region.
+ */
+ if (!(ae_init & INIT_MPU401))
+ request_region (hw_config->io_base, 0x0f, "aedsp16 (sbpro)");
+#endif
+
+ ae_init |= INIT_SBPRO;
+ return 0;
+}
+
+#endif /* AEDSP16_SBPRO */
+
+#if defined(AEDSP16_MSS)
+
+int
+InitAEDSP16_MSS (struct address_info *hw_config)
+{
+ /*
+ * If the card is alredy init'ed SBPRO, we can not init it to MSS too
+ * because the board can not emulate simultaneously MSS and SBPRO.
+ */
+ if (ae_init & INIT_SBPRO)
+ return -1;
+ if (ae_init & INIT_MSS)
+ return 0;
+
+ /*
+ * For now we will leave this
+ * code included only when INCLUDE_AEDSP16 is configured in, but it should
+ * be better include it every time.
+ */
+ if (check_region (hw_config->io_base, 0x08))
+ {
+ printk ("MSS I/O port region is alredy in use.\n");
+ return -1;
+ }
+
+ /*
+ * We must allocate the AEDSP16 region too because these are the I/O ports
+ * to access card's control registers.
+ */
+ if (!(ae_init & INIT_MPU401))
+ {
+ if (check_region (AEDSP16_BASE, 0x0f))
+ {
+ printk ("AEDSP16 I/O port region is alredy in use.\n");
+ return -1;
+ }
+ }
+
+
+ /*
+ * If we are configuring the card for MSS, the portbase for card
+ * configuration is the default one (0x220 unless you have changed the
+ * factory default with board switches), so no need to modify the
+ * portbase variable.
+ * The default is AEDSP16_BASE, that is the right value.
+ */
+ irq = hw_config->irq;
+ dma = hw_config->dma;
+ if (InitAEDSP16 (INIT_MSS))
+ return -1;
+
+#if !defined(MODULE)
+ /*
+ * If we are compiling sound.o (MODULAR version) we can not
+ * request any region because there is not a uninit routine that
+ * can allow me to release the requested region. So when unloading
+ * and then reloading it, we are going to have some nice Oops!
+ */
+ request_region (hw_config->io_base, 0x08, "aedsp16 (mss)");
+#endif
+
+ if (!(ae_init & INIT_MPU401))
+ request_region (AEDSP16_BASE, 0x0f, "aedsp16 (sbpro)");
+
+ ae_init |= INIT_MSS;
+ return 0;
+}
+
+#endif /* AEDSP16_MSS */
+
+#if defined(AEDSP16_MPU401)
+
+int
+InitAEDSP16_MPU401 (struct address_info *hw_config)
+{
+ if (ae_init & INIT_MPU401)
+ return 0;
+
+ /*
+ * For now we will leave this
+ * code included only when INCLUDE_AEDSP16 is configured in, but it should
+ * be better include it every time.
+ */
+ if (check_region (hw_config->io_base, 0x02))
+ {
+ printk ("SB I/O port region is alredy in use.\n");
+ return -1;
+ }
+
+ /*
+ * We must allocate the AEDSP16 region too because these are the I/O ports
+ * to access card's control registers.
+ */
+ if (!(ae_init & (INIT_MSS | INIT_SBPRO)))
+ {
+ if (check_region (AEDSP16_BASE, 0x0f))
+ {
+ printk ("AEDSP16 I/O port region is alredy in use.\n");
+ return -1;
+ }
+ }
+
+ /*
+ * If mpu401, the irq and dma are not important, do not touch it
+ * because we may use the default if sbpro is not yet configured,
+ * we may use the sbpro ones if configured, and nothing wrong
+ * should happen.
+ *
+ * The mirq default is 0, but once set it to non-0 value, we should
+ * not touch it anymore (unless I write an ioctl to do it, of course).
+ */
+ mirq = hw_config->irq;
+ if (InitAEDSP16 (INIT_MPU401))
+ return -1;
+
+#if !defined(MODULE)
+ /*
+ * If we are compiling sound.o (MODULAR version) we can not
+ * request any region because there is not a uninit routine that
+ * can allow me to release the requested region.
+ */
+ request_region (hw_config->io_base, 0x02, "aedsp16 (mpu401)");
+#endif
+
+ if (!(ae_init & (INIT_MSS | INIT_SBPRO)))
+ request_region (AEDSP16_BASE, 0x0f, "aedsp16 (sbpro)");
+
+ ae_init |= INIT_MPU401;
+ return 0;
+}
+
+#endif /* AEDSP16_MPU401 */
+
+#if 0 /* Leave it out for now. We are not using this portion of code. */
+
+/*
+ * Entry point for a reset function.
+ * May be I will write the infamous ioctl :)
+ */
+int
+ResetAEDSP16 (void)
+{
+#if defined(AEDSP16_DEBUG)
+ printk ("[aedsp16] ResetAEDSP16 called.\n");
+#endif
+ return InitAEDSP16 (RESET_DSP16);
+}
+
+#endif /* 0 */
+
+#endif /* !EXCLUDE_AEDSP16 */
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