linux-old/drivers/sound/aedsp16.c
<<
>>
Prefs
   1/*
   2   drivers/sound/aedsp16.c
   3
   4   Audio Excel DSP 16 software configuration routines
   5   Copyright (C) 1995,1996,1997,1998  Riccardo Facchetti (fizban@tin.it)
   6
   7   This program is free software; you can redistribute it and/or modify
   8   it under the terms of the GNU General Public License as published by
   9   the Free Software Foundation; either version 2 of the License, or
  10   (at your option) any later version.
  11
  12   This program is distributed in the hope that it will be useful,
  13   but WITHOUT ANY WARRANTY; without even the implied warranty of
  14   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  15   GNU General Public License for more details.
  16
  17   You should have received a copy of the GNU General Public License
  18   along with this program; if not, write to the Free Software
  19   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  20
  21 */
  22/*
  23 * Include the main OSS Lite header file. It include all the os, OSS Lite, etc
  24 * headers needed by this source.
  25 */
  26#include <linux/config.h>
  27#include <linux/delay.h>
  28#include <linux/module.h>
  29#include <linux/init.h>
  30#include "sound_config.h"
  31
  32/*
  33 * Sanity checks
  34 */
  35
  36#if defined(CONFIG_SOUND_AEDSP16_SBPRO) && defined(CONFIG_SOUND_AEDSP16_MSS)
  37#error You have to enable only one of the MSS and SBPRO emulations.
  38#endif
  39
  40/*
  41
  42   READ THIS
  43
  44   This module started to configure the Audio Excel DSP 16 Sound Card.
  45   Now works with the SC-6000 (old aedsp16) and new SC-6600 based cards.
  46
  47   NOTE: I have NO idea about Audio Excel DSP 16 III. If someone owns this
  48   audio card and want to see the kernel support for it, please contact me.
  49
  50   Audio Excel DSP 16 is an SB pro II, Microsoft Sound System and MPU-401
  51   compatible card.
  52   It is software-only configurable (no jumpers to hard-set irq/dma/mpu-irq),
  53   so before this module, the only way to configure the DSP under linux was
  54   boot the MS-DOS loading the sound.sys device driver (this driver soft-
  55   configure the sound board hardware by massaging someone of its registers),
  56   and then ctrl-alt-del to boot linux with the DSP configured by the DOS
  57   driver.
  58
  59   This module works configuring your Audio Excel DSP 16's irq, dma and
  60   mpu-401-irq. The OSS Lite routines rely on the fact that if the
  61   hardware is there, they can detect it. The problem with AEDSP16 is
  62   that no hardware can be found by the probe routines if the sound card
  63   is not configured properly. Sometimes the kernel probe routines can find
  64   an SBPRO even when the card is not configured (this is the standard setup
  65   of the card), but the SBPRO emulation don't work well if the card is not
  66   properly initialized. For this reason
  67
  68   aedsp16_init_board()
  69
  70   routine is called before the OSS Lite probe routines try to detect the
  71   hardware.
  72
  73   NOTE (READ THE NOTE TOO, IT CONTAIN USEFUL INFORMATIONS)
  74
  75   NOTE: Now it works with SC-6000 and SC-6600 based audio cards. The new cards
  76   have no jumper switch at all. No more WSS or MPU-401 I/O port switches. They
  77   have to be configured by software.
  78
  79   NOTE: The driver is merged with the new OSS Lite sound driver. It works
  80   as a lowlevel driver.
  81
  82   The Audio Excel DSP 16 Sound Card emulates both SBPRO and MSS;
  83   the OSS Lite sound driver can be configured for SBPRO and MSS cards
  84   at the same time, but the aedsp16 can't be two cards!!
  85   When we configure it, we have to choose the SBPRO or the MSS emulation
  86   for AEDSP16. We also can install a *REAL* card of the other type (see [1]).
  87
  88   NOTE: If someone can test the combination AEDSP16+MSS or AEDSP16+SBPRO
  89   please let me know if it works.
  90
  91   The MPU-401 support can be compiled in together with one of the other
  92   two operating modes.
  93
  94   NOTE: This is something like plug-and-play: we have only to plug
  95   the AEDSP16 board in the socket, and then configure and compile
  96   a kernel that uses the AEDSP16 software configuration capability.
  97   No jumper setting is needed!
  98
  99   For example, if you want AEDSP16 to be an SBPro, on irq 10, dma 3
 100   you have just to make config the OSS Lite package, configuring
 101   the AEDSP16 sound card, then activating the SBPro emulation mode
 102   and at last configuring IRQ and DMA.
 103   Compile the kernel and run it.
 104
 105   NOTE: This means for SC-6000 cards that you can choose irq and dma,
 106   but not the I/O addresses. To change I/O addresses you have to set
 107   them with jumpers. For SC-6600 cards you have no jumpers so you have
 108   to set up your full card configuration in the make config.
 109
 110   You can change the irq/dma/mirq settings WITHOUT THE NEED to open
 111   your computer and massage the jumpers (there are no irq/dma/mirq
 112   jumpers to be configured anyway, only I/O BASE values have to be
 113   configured with jumpers)
 114
 115   For some ununderstandable reason, the card default of irq 7, dma 1,
 116   don't work for me. Seems to be an IRQ or DMA conflict. Under heavy
 117   HDD work, the kernel start to erupt out a lot of messages like:
 118
 119   'Sound: DMA timed out - IRQ/DRQ config error?'
 120
 121   For what I can say, I have NOT any conflict at irq 7 (under linux I'm
 122   using the lp polling driver), and dma line 1 is unused as stated by
 123   /proc/dma. I can suppose this is a bug of AEDSP16. I know my hardware so
 124   I'm pretty sure I have not any conflict, but may be I'm wrong. Who knows!
 125   Anyway a setting of irq 10, dma 3 works really fine.
 126
 127   NOTE: if someone can use AEDSP16 with irq 7, dma 1, please let me know
 128   the emulation mode, all the installed hardware and the hardware
 129   configuration (irq and dma settings of all the hardware).
 130
 131   This init module should work with SBPRO+MSS, when one of the two is
 132   the AEDSP16 emulation and the other the real card. (see [1])
 133   For example:
 134
 135   AEDSP16 (0x220) in SBPRO emu (0x220) + real MSS + other
 136   AEDSP16 (0x220) in MSS emu + real SBPRO (0x240) + other
 137
 138   MPU401 should work. (see [2])
 139
 140   [1]
 141       ---
 142       Date: Mon, 29 Jul 1997 08:35:40 +0100
 143       From: Mr S J Greenaway <sjg95@unixfe.rl.ac.uk>
 144
 145       [...]
 146       Just to let you know got my Audio Excel (emulating a MSS) working
 147       with my original SB16, thanks for the driver!
 148       [...]
 149       ---
 150
 151   [2] Not tested by me for lack of hardware.
 152
 153   TODO, WISHES AND TECH
 154
 155   - About I/O ports allocation -
 156
 157   Request the 2x0h region (port base) in any case if we are using this card.
 158
 159   NOTE: the "aedsp16 (base)" string with which we are requesting the aedsp16
 160   port base region (see code) does not mean necessarily that we are emulating
 161   sbpro.  Even if this region is the sbpro I/O ports region, we use this
 162   region to access the control registers of the card, and if emulating
 163   sbpro, I/O sbpro registers too. If we are emulating MSS, the sbpro
 164   registers are not used, in no way, to emulate an sbpro: they are
 165   used only for configuration purposes.
 166
 167   Started Fri Mar 17 16:13:18 MET 1995
 168
 169   v0.1 (ALPHA, was an user-level program called AudioExcelDSP16.c)
 170   - Initial code.
 171   v0.2 (ALPHA)
 172   - Cleanups.
 173   - Integrated with Linux voxware v 2.90-2 kernel sound driver.
 174   - SoundBlaster Pro mode configuration.
 175   - Microsoft Sound System mode configuration.
 176   - MPU-401 mode configuration.
 177   v0.3 (ALPHA)
 178   - Cleanups.
 179   - Rearranged the code to let aedsp16_init_board be more general.
 180   - Erased the REALLY_SLOW_IO. We don't need it. Erased the linux/io.h
 181   inclusion too. We rely on os.h
 182   - Used the  to get a variable
 183   len string (we are not sure about the len of Copyright string).
 184   This works with any SB and compatible.
 185   - Added the code to request_region at device init (should go in
 186   the main body of voxware).
 187   v0.4 (BETA)
 188   - Better configure.c patch for aedsp16 configuration (better
 189   logic of inclusion of AEDSP16 support)
 190   - Modified the conditional compilation to better support more than
 191   one sound card of the emulated type (read the NOTES above)
 192   - Moved the sb init routine from the attach to the very first
 193   probe in sb_card.c
 194   - Rearrangements and cleanups
 195   - Wiped out some unnecessary code and variables: this is kernel
 196   code so it is better save some TEXT and DATA
 197   - Fixed the request_region code. We must allocate the aedsp16 (sbpro)
 198   I/O ports in any case because they are used to access the DSP
 199   configuration registers and we can not allow anyone to get them.
 200   v0.5
 201   - cleanups on comments
 202   - prep for diffs against v3.0-proto-950402
 203   v0.6
 204   - removed the request_region()s when compiling the MODULE sound.o
 205   because we are not allowed (by the actual voxware structure) to
 206   release_region()
 207   v0.7 (pre ALPHA, not distributed)
 208   - started porting this module to kernel 1.3.84. Dummy probe/attach
 209   routines.
 210   v0.8 (ALPHA)
 211   - attached all the init routines.
 212   v0.9 (BETA)
 213   - Integrated with linux-pre2.0.7
 214   - Integrated with configuration scripts.
 215   - Cleaned up and beautyfied the code.
 216   v0.9.9 (BETA)
 217   - Thanks to Piercarlo Grandi: corrected the conditonal compilation code.
 218     Now only the code configured is compiled in, with some memory saving.
 219   v0.9.10
 220   - Integration into the sound/lowlevel/ section of the sound driver.
 221   - Re-organized the code.
 222   v0.9.11 (not distributed)
 223   - Rewritten the init interface-routines to initialize the AEDSP16 in
 224     one shot.
 225   - More cosmetics.
 226   - SC-6600 support.
 227   - More soft/hard configuration.
 228   v0.9.12
 229   - Refined the v0.9.11 code with conditional compilation to distinguish
 230     between SC-6000 and SC-6600 code.
 231   v1.0.0
 232   - Prep for merging with OSS Lite and Linux kernel 2.1.13
 233   - Corrected a bug in request/check/release region calls (thanks to the
 234     new kernel exception handling).
 235   v1.1
 236   - Revamped for integration with new modularized sound drivers: to enhance
 237     the flexibility of modular version, I have removed all the conditional
 238     compilation for SBPRO, MPU and MSS code. Now it is all managed with
 239     the ae_config structure.
 240   v1.2
 241   - Module informations added.
 242   - Removed aedsp16_delay_10msec(), now using mdelay(10)
 243   - All data and funcs moved to .*.init section.
 244   v1.3
 245   Arnaldo Carvalho de Melo <acme@conectiva.com.br> - 2000/09/27
 246   - got rid of check_region
 247
 248   Known Problems:
 249   - Audio Excel DSP 16 III don't work with this driver.
 250
 251   Credits:
 252   Many thanks to Gerald Britton <gbritton@CapAccess.org>. He helped me a
 253   lot in testing the 0.9.11 and 0.9.12 versions of this driver.
 254
 255 */
 256
 257
 258#define VERSION "1.3"           /* Version of Audio Excel DSP 16 driver */
 259
 260#undef  AEDSP16_DEBUG           /* Define this to 1 to enable debug code     */
 261#undef  AEDSP16_DEBUG_MORE      /* Define this to 1 to enable more debug     */
 262#undef  AEDSP16_INFO            /* Define this to 1 to enable info code      */
 263
 264#if defined(AEDSP16_DEBUG)
 265# define DBG(x)  printk x
 266# if defined(AEDSP16_DEBUG_MORE)
 267#  define DBG1(x) printk x
 268# else
 269#  define DBG1(x)
 270# endif
 271#else
 272# define DBG(x)
 273# define DBG1(x)
 274#endif
 275
 276/*
 277 * Misc definitions
 278 */
 279#define TRUE    1
 280#define FALSE   0
 281
 282/*
 283 * Region Size for request/check/release region.
 284 */
 285#define IOBASE_REGION_SIZE      0x10
 286
 287/*
 288 * Hardware related defaults
 289 */
 290#define DEF_AEDSP16_IOB 0x220   /* 0x220(default) 0x240                 */
 291#define DEF_AEDSP16_IRQ 7       /* 5 7(default) 9 10 11                 */
 292#define DEF_AEDSP16_MRQ 0       /* 5 7 9 10 0(default), 0 means disable */
 293#define DEF_AEDSP16_DMA 1       /* 0 1(default) 3                       */
 294
 295/*
 296 * Commands of AEDSP16's DSP (SBPRO+special).
 297 * Some of them are COMMAND_xx, in the future they may change.
 298 */
 299#define WRITE_MDIRQ_CFG   0x50  /* Set M&I&DRQ mask (the real config)   */
 300#define COMMAND_52        0x52  /*                                      */
 301#define READ_HARD_CFG     0x58  /* Read Hardware Config (I/O base etc)  */
 302#define COMMAND_5C        0x5c  /*                                      */
 303#define COMMAND_60        0x60  /*                                      */
 304#define COMMAND_66        0x66  /*                                      */
 305#define COMMAND_6C        0x6c  /*                                      */
 306#define COMMAND_6E        0x6e  /*                                      */
 307#define COMMAND_88        0x88  /*                                      */
 308#define DSP_INIT_MSS      0x8c  /* Enable Microsoft Sound System mode   */
 309#define COMMAND_C5        0xc5  /*                                      */
 310#define GET_DSP_VERSION   0xe1  /* Get DSP Version                      */
 311#define GET_DSP_COPYRIGHT 0xe3  /* Get DSP Copyright                    */
 312
 313/*
 314 * Offsets of AEDSP16 DSP I/O ports. The offset is added to base I/O port
 315 * to have the actual I/O port.
 316 * Register permissions are:
 317 * (wo) == Write Only
 318 * (ro) == Read  Only
 319 * (w-) == Write
 320 * (r-) == Read
 321 */
 322#define DSP_RESET    0x06       /* offset of DSP RESET             (wo) */
 323#define DSP_READ     0x0a       /* offset of DSP READ              (ro) */
 324#define DSP_WRITE    0x0c       /* offset of DSP WRITE             (w-) */
 325#define DSP_COMMAND  0x0c       /* offset of DSP COMMAND           (w-) */
 326#define DSP_STATUS   0x0c       /* offset of DSP STATUS            (r-) */
 327#define DSP_DATAVAIL 0x0e       /* offset of DSP DATA AVAILABLE    (ro) */
 328
 329
 330#define RETRY           10      /* Various retry values on I/O opera-   */
 331#define STATUSRETRY   1000      /* tions. Sometimes we have to          */
 332#define HARDRETRY   500000      /* wait for previous cmd to complete    */
 333
 334/*
 335 * Size of character arrays that store name and version of sound card
 336 */
 337#define CARDNAMELEN 15          /* Size of the card's name in chars     */
 338#define CARDVERLEN  2           /* Size of the card's version in chars  */
 339
 340#if defined(CONFIG_SC6600)
 341/*
 342 * Bitmapped flags of hard configuration
 343 */
 344/*
 345 * Decode macros (xl == low byte, xh = high byte)
 346 */
 347#define IOBASE(xl)              ((xl & 0x01)?0x240:0x220)
 348#define JOY(xl)                 (xl & 0x02)
 349#define MPUADDR(xl)             (                       \
 350                                (xl & 0x0C)?0x330:      \
 351                                (xl & 0x08)?0x320:      \
 352                                (xl & 0x04)?0x310:      \
 353                                                0x300)
 354#define WSSADDR(xl)             ((xl & 0x10)?0xE80:0x530)
 355#define CDROM(xh)               (xh & 0x20)
 356#define CDROMADDR(xh)           (((xh & 0x1F) << 4) + 0x200)
 357/*
 358 * Encode macros
 359 */
 360#define BLDIOBASE(xl, val) {            \
 361        xl &= ~0x01;                    \
 362        if (val == 0x240)               \
 363                xl |= 0x01;             \
 364        }
 365#define BLDJOY(xl, val) {               \
 366        xl &= ~0x02;                    \
 367        if (val == 1)                   \
 368                xl |= 0x02;             \
 369        }
 370#define BLDMPUADDR(xl, val) {           \
 371        xl &= ~0x0C;                    \
 372        switch (val) {                  \
 373                case 0x330:             \
 374                        xl |= 0x0C;     \
 375                        break;          \
 376                case 0x320:             \
 377                        xl |= 0x08;     \
 378                        break;          \
 379                case 0x310:             \
 380                        xl |= 0x04;     \
 381                        break;          \
 382                case 0x300:             \
 383                        xl |= 0x00;     \
 384                        break;          \
 385                default:                \
 386                        xl |= 0x00;     \
 387                        break;          \
 388                }                       \
 389        }
 390#define BLDWSSADDR(xl, val) {           \
 391        xl &= ~0x10;                    \
 392        if (val == 0xE80)               \
 393                xl |= 0x10;             \
 394        }
 395#define BLDCDROM(xh, val) {             \
 396        xh &= ~0x20;                    \
 397        if (val == 1)                   \
 398                xh |= 0x20;             \
 399        }
 400#define BLDCDROMADDR(xh, val) {         \
 401        int tmp = val;                  \
 402        tmp -= 0x200;                   \
 403        tmp >>= 4;                      \
 404        tmp &= 0x1F;                    \
 405        xh |= tmp;                      \
 406        xh &= 0x7F;                     \
 407        xh |= 0x40;                     \
 408        }
 409#endif /* CONFIG_SC6600 */
 410
 411/*
 412 * Bit mapped flags for calling aedsp16_init_board(), and saving the current
 413 * emulation mode.
 414 */
 415#define INIT_NONE   (0   )
 416#define INIT_SBPRO  (1<<0)
 417#define INIT_MSS    (1<<1)
 418#define INIT_MPU401 (1<<2)
 419
 420static int      soft_cfg __initdata = 0;        /* bitmapped config */
 421static int      soft_cfg_mss __initdata = 0;    /* bitmapped mss config */
 422static int      ver[CARDVERLEN] __initdata = {0, 0};    /* DSP Ver:
 423                                                   hi->ver[0] lo->ver[1] */
 424
 425#if defined(CONFIG_SC6600)
 426static int      hard_cfg[2]     /* lo<-hard_cfg[0] hi<-hard_cfg[1]      */
 427                     __initdata = { 0, 0};
 428#endif /* CONFIG_SC6600 */
 429
 430#if defined(CONFIG_SC6600)
 431/* Decoded hard configuration */
 432struct  d_hcfg {
 433        int iobase;
 434        int joystick;
 435        int mpubase;
 436        int wssbase;
 437        int cdrom;
 438        int cdrombase;
 439};
 440
 441struct d_hcfg decoded_hcfg __initdata = {0, };
 442
 443#endif /* CONFIG_SC6600 */
 444
 445/* orVals contain the values to be or'ed                                */
 446struct orVals {
 447        int     val;            /* irq|mirq|dma                         */
 448        int     or;             /* soft_cfg |= TheStruct.or             */
 449};
 450
 451/* aedsp16_info contain the audio card configuration                  */
 452struct aedsp16_info {
 453        int base_io;            /* base I/O address for accessing card  */
 454        int irq;                /* irq value for DSP I/O                */
 455        int mpu_irq;            /* irq for mpu401 interface I/O         */
 456        int dma;                /* dma value for DSP I/O                */
 457        int mss_base;           /* base I/O for Microsoft Sound System  */
 458        int mpu_base;           /* base I/O for MPU-401 emulation       */
 459        int init;               /* Initialization status of the card    */
 460};
 461
 462/*
 463 * Magic values that the DSP will eat when configuring irq/mirq/dma
 464 */
 465/* DSP IRQ conversion array             */
 466static struct orVals orIRQ[] __initdata = {
 467        {0x05, 0x28},
 468        {0x07, 0x08},
 469        {0x09, 0x10},
 470        {0x0a, 0x18},
 471        {0x0b, 0x20},
 472        {0x00, 0x00}
 473};
 474
 475/* MPU-401 IRQ conversion array         */
 476static struct orVals orMIRQ[] __initdata = {
 477        {0x05, 0x04},
 478        {0x07, 0x44},
 479        {0x09, 0x84},
 480        {0x0a, 0xc4},
 481        {0x00, 0x00}
 482};
 483
 484/* DMA Channels conversion array        */
 485static struct orVals orDMA[] __initdata = {
 486        {0x00, 0x01},
 487        {0x01, 0x02},
 488        {0x03, 0x03},
 489        {0x00, 0x00}
 490};
 491
 492static struct aedsp16_info ae_config __initdata = {
 493        DEF_AEDSP16_IOB,
 494        DEF_AEDSP16_IRQ,
 495        DEF_AEDSP16_MRQ,
 496        DEF_AEDSP16_DMA,
 497        -1,
 498        -1,
 499        INIT_NONE
 500};
 501
 502/*
 503 * Buffers to store audio card informations
 504 */
 505static char     DSPCopyright[CARDNAMELEN + 1] __initdata = {0, };
 506static char     DSPVersion[CARDVERLEN + 1] __initdata = {0, };
 507
 508static int __init aedsp16_wait_data(int port)
 509{
 510        int             loop = STATUSRETRY;
 511        unsigned char   ret = 0;
 512
 513        DBG1(("aedsp16_wait_data (0x%x): ", port));
 514
 515        do {
 516                  ret = inb(port + DSP_DATAVAIL);
 517        /*
 518         * Wait for data available (bit 7 of ret == 1)
 519         */
 520          } while (!(ret & 0x80) && loop--);
 521
 522        if (ret & 0x80) {
 523                DBG1(("success.\n"));
 524                return TRUE;
 525        }
 526
 527        DBG1(("failure.\n"));
 528        return FALSE;
 529}
 530
 531static int __init aedsp16_read(int port)
 532{
 533        int inbyte;
 534
 535        DBG(("    Read DSP Byte (0x%x): ", port));
 536
 537        if (aedsp16_wait_data(port) == FALSE) {
 538                DBG(("failure.\n"));
 539                return -1;
 540        }
 541
 542        inbyte = inb(port + DSP_READ);
 543
 544        DBG(("read [0x%x]/{%c}.\n", inbyte, inbyte));
 545
 546        return inbyte;
 547}
 548
 549static int __init aedsp16_test_dsp(int port)
 550{
 551        return ((aedsp16_read(port) == 0xaa) ? TRUE : FALSE);
 552}
 553
 554static int __init aedsp16_dsp_reset(int port)
 555{
 556        /*
 557         * Reset DSP
 558         */
 559
 560        DBG(("Reset DSP:\n"));
 561
 562        outb(1, (port + DSP_RESET));
 563        udelay(10);
 564        outb(0, (port + DSP_RESET));
 565        udelay(10);
 566        udelay(10);
 567        if (aedsp16_test_dsp(port) == TRUE) {
 568                DBG(("success.\n"));
 569                return TRUE;
 570        } else
 571                DBG(("failure.\n"));
 572        return FALSE;
 573}
 574
 575static int __init aedsp16_write(int port, int cmd)
 576{
 577        unsigned char   ret;
 578        int             loop = HARDRETRY;
 579
 580        DBG(("    Write DSP Byte (0x%x) [0x%x]: ", port, cmd));
 581
 582        do {
 583                ret = inb(port + DSP_STATUS);
 584                /*
 585                 * DSP ready to receive data if bit 7 of ret == 0
 586                 */
 587                if (!(ret & 0x80)) {
 588                        outb(cmd, port + DSP_COMMAND);
 589                        DBG(("success.\n"));
 590                        return 0;
 591                }
 592        } while (loop--);
 593
 594        DBG(("timeout.\n"));
 595        printk("[AEDSP16] DSP Command (0x%x) timeout.\n", cmd);
 596
 597        return -1;
 598}
 599
 600#if defined(CONFIG_SC6600)
 601
 602#if defined(AEDSP16_INFO) || defined(AEDSP16_DEBUG)
 603void __init aedsp16_pinfo(void) {
 604        DBG(("\n Base address:  %x\n", decoded_hcfg.iobase));
 605        DBG((" Joystick    : %s present\n", decoded_hcfg.joystick?"":" not"));
 606        DBG((" WSS addr    :  %x\n", decoded_hcfg.wssbase));
 607        DBG((" MPU-401 addr:  %x\n", decoded_hcfg.mpubase));
 608        DBG((" CDROM       : %s present\n", (decoded_hcfg.cdrom!=4)?"":" not"));
 609        DBG((" CDROMADDR   :  %x\n\n", decoded_hcfg.cdrombase));
 610}
 611#endif
 612
 613void __init aedsp16_hard_decode(void) {
 614
 615        DBG((" aedsp16_hard_decode: 0x%x, 0x%x\n", hard_cfg[0], hard_cfg[1]));
 616
 617/*
 618 * Decode Cfg Bytes.
 619 */
 620        decoded_hcfg.iobase     = IOBASE(hard_cfg[0]);
 621        decoded_hcfg.joystick   = JOY(hard_cfg[0]);
 622        decoded_hcfg.wssbase    = WSSADDR(hard_cfg[0]);
 623        decoded_hcfg.mpubase    = MPUADDR(hard_cfg[0]);
 624        decoded_hcfg.cdrom      = CDROM(hard_cfg[1]);
 625        decoded_hcfg.cdrombase  = CDROMADDR(hard_cfg[1]);
 626
 627#if defined(AEDSP16_INFO) || defined(AEDSP16_DEBUG)
 628        printk(" Original sound card configuration:\n");
 629        aedsp16_pinfo();
 630#endif
 631
 632/*
 633 * Now set up the real kernel configuration.
 634 */
 635        decoded_hcfg.iobase     = ae_config.base_io;
 636        decoded_hcfg.wssbase    = ae_config.mss_base;
 637        decoded_hcfg.mpubase    = ae_config.mpu_base;
 638
 639#if defined(CONFIG_SC6600_JOY)
 640        decoded_hcfg.joystick   = CONFIG_SC6600_JOY; /* Enable */
 641#endif
 642#if defined(CONFIG_SC6600_CDROM)
 643        decoded_hcfg.cdrom      = CONFIG_SC6600_CDROM; /* 4:N-3:I-2:G-1:P-0:S */
 644#endif
 645#if defined(CONFIG_SC6600_CDROMBASE)
 646        decoded_hcfg.cdrombase  = CONFIG_SC6600_CDROMBASE; /* 0 Disable */
 647#endif
 648
 649#if defined(AEDSP16_DEBUG)
 650        DBG((" New Values:\n"));
 651        aedsp16_pinfo();
 652#endif
 653
 654        DBG(("success.\n"));
 655}
 656
 657void __init aedsp16_hard_encode(void) {
 658
 659        DBG((" aedsp16_hard_encode: 0x%x, 0x%x\n", hard_cfg[0], hard_cfg[1]));
 660
 661        hard_cfg[0] = 0;
 662        hard_cfg[1] = 0;
 663
 664        hard_cfg[0] |= 0x20;
 665
 666        BLDIOBASE (hard_cfg[0], decoded_hcfg.iobase);
 667        BLDWSSADDR(hard_cfg[0], decoded_hcfg.wssbase);
 668        BLDMPUADDR(hard_cfg[0], decoded_hcfg.mpubase);
 669        BLDJOY(hard_cfg[0], decoded_hcfg.joystick);
 670        BLDCDROM(hard_cfg[1], decoded_hcfg.cdrom);
 671        BLDCDROMADDR(hard_cfg[1], decoded_hcfg.cdrombase);
 672
 673#if defined(AEDSP16_DEBUG)
 674        aedsp16_pinfo();
 675#endif
 676
 677        DBG((" aedsp16_hard_encode: 0x%x, 0x%x\n", hard_cfg[0], hard_cfg[1]));
 678        DBG(("success.\n"));
 679
 680}
 681
 682static int __init aedsp16_hard_write(int port) {
 683
 684        DBG(("aedsp16_hard_write:\n"));
 685
 686        if (aedsp16_write(port, COMMAND_6C)) {
 687                printk("[AEDSP16] CMD 0x%x: failed!\n", COMMAND_6C);
 688                DBG(("failure.\n"));
 689                return FALSE;
 690        }
 691        if (aedsp16_write(port, COMMAND_5C)) {
 692                printk("[AEDSP16] CMD 0x%x: failed!\n", COMMAND_5C);
 693                DBG(("failure.\n"));
 694                return FALSE;
 695        }
 696        if (aedsp16_write(port, hard_cfg[0])) {
 697                printk("[AEDSP16] DATA 0x%x: failed!\n", hard_cfg[0]);
 698                DBG(("failure.\n"));
 699                return FALSE;
 700        }
 701        if (aedsp16_write(port, hard_cfg[1])) {
 702                printk("[AEDSP16] DATA 0x%x: failed!\n", hard_cfg[1]);
 703                DBG(("failure.\n"));
 704                return FALSE;
 705        }
 706        if (aedsp16_write(port, COMMAND_C5)) {
 707                printk("[AEDSP16] CMD 0x%x: failed!\n", COMMAND_C5);
 708                DBG(("failure.\n"));
 709                return FALSE;
 710        }
 711
 712        DBG(("success.\n"));
 713
 714        return TRUE;
 715}
 716
 717static int __init aedsp16_hard_read(int port) {
 718
 719        DBG(("aedsp16_hard_read:\n"));
 720
 721        if (aedsp16_write(port, READ_HARD_CFG)) {
 722                printk("[AEDSP16] CMD 0x%x: failed!\n", READ_HARD_CFG);
 723                DBG(("failure.\n"));
 724                return FALSE;
 725        }
 726
 727        if ((hard_cfg[0] = aedsp16_read(port)) == -1) {
 728                printk("[AEDSP16] aedsp16_read after CMD 0x%x: failed\n",
 729                        READ_HARD_CFG);
 730                DBG(("failure.\n"));
 731                return FALSE;
 732        }
 733        if ((hard_cfg[1] = aedsp16_read(port)) == -1) {
 734                printk("[AEDSP16] aedsp16_read after CMD 0x%x: failed\n",
 735                        READ_HARD_CFG);
 736                DBG(("failure.\n"));
 737                return FALSE;
 738        }
 739        if (aedsp16_read(port) == -1) {
 740                printk("[AEDSP16] aedsp16_read after CMD 0x%x: failed\n",
 741                        READ_HARD_CFG);
 742                DBG(("failure.\n"));
 743                return FALSE;
 744        }
 745
 746        DBG(("success.\n"));
 747
 748        return TRUE;
 749}
 750
 751static int __init aedsp16_ext_cfg_write(int port) {
 752
 753        int extcfg, val;
 754
 755        if (aedsp16_write(port, COMMAND_66)) {
 756                printk("[AEDSP16] CMD 0x%x: failed!\n", COMMAND_66);
 757                return FALSE;
 758        }
 759
 760        extcfg = 7;
 761        if (decoded_hcfg.cdrom != 2)
 762                extcfg = 0x0F;
 763        if ((decoded_hcfg.cdrom == 4) ||
 764            (decoded_hcfg.cdrom == 3))
 765                extcfg &= ~2;
 766        if (decoded_hcfg.cdrombase == 0)
 767                extcfg &= ~2;
 768        if (decoded_hcfg.mpubase == 0)
 769                extcfg &= ~1;
 770
 771        if (aedsp16_write(port, extcfg)) {
 772                printk("[AEDSP16] Write extcfg: failed!\n");
 773                return FALSE;
 774        }
 775        if (aedsp16_write(port, 0)) {
 776                printk("[AEDSP16] Write extcfg: failed!\n");
 777                return FALSE;
 778        }
 779        if (decoded_hcfg.cdrom == 3) {
 780                if (aedsp16_write(port, COMMAND_52)) {
 781                        printk("[AEDSP16] CMD 0x%x: failed!\n", COMMAND_52);
 782                        return FALSE;
 783                }
 784                if ((val = aedsp16_read(port)) == -1) {
 785                        printk("[AEDSP16] aedsp16_read after CMD 0x%x: failed\n"
 786                                        , COMMAND_52);
 787                        return FALSE;
 788                }
 789                val &= 0x7F;
 790                if (aedsp16_write(port, COMMAND_60)) {
 791                        printk("[AEDSP16] CMD 0x%x: failed!\n", COMMAND_60);
 792                        return FALSE;
 793                }
 794                if (aedsp16_write(port, val)) {
 795                        printk("[AEDSP16] Write val: failed!\n");
 796                        return FALSE;
 797                }
 798        }
 799
 800        return TRUE;
 801}
 802
 803#endif /* CONFIG_SC6600 */
 804
 805static int __init aedsp16_cfg_write(int port) {
 806        if (aedsp16_write(port, WRITE_MDIRQ_CFG)) {
 807                printk("[AEDSP16] CMD 0x%x: failed!\n", WRITE_MDIRQ_CFG);
 808                return FALSE;
 809        }
 810        if (aedsp16_write(port, soft_cfg)) {
 811                printk("[AEDSP16] Initialization of (M)IRQ and DMA: failed!\n");
 812                return FALSE;
 813        }
 814        return TRUE;
 815}
 816
 817static int __init aedsp16_init_mss(int port)
 818{
 819        DBG(("aedsp16_init_mss:\n"));
 820
 821        mdelay(10);
 822
 823        if (aedsp16_write(port, DSP_INIT_MSS)) {
 824                printk("[AEDSP16] aedsp16_init_mss [0x%x]: failed!\n",
 825                                DSP_INIT_MSS);
 826                DBG(("failure.\n"));
 827                return FALSE;
 828        }
 829        
 830        mdelay(10);
 831
 832        if (aedsp16_cfg_write(port) == FALSE)
 833                return FALSE;
 834
 835        outb(soft_cfg_mss, ae_config.mss_base);
 836
 837        DBG(("success.\n"));
 838
 839        return TRUE;
 840}
 841
 842static int __init aedsp16_setup_board(int port) {
 843        int     loop = RETRY;
 844
 845#if defined(CONFIG_SC6600)
 846        int     val = 0;
 847
 848        if (aedsp16_hard_read(port) == FALSE) {
 849                printk("[AEDSP16] aedsp16_hard_read: failed!\n");
 850                return FALSE;
 851        }
 852
 853        if (aedsp16_write(port, COMMAND_52)) {
 854                printk("[AEDSP16] CMD 0x%x: failed!\n", COMMAND_52);
 855                return FALSE;
 856        }
 857
 858        if ((val = aedsp16_read(port)) == -1) {
 859                printk("[AEDSP16] aedsp16_read after CMD 0x%x: failed\n",
 860                                COMMAND_52);
 861                return FALSE;
 862        }
 863#endif
 864
 865        do {
 866                if (aedsp16_write(port, COMMAND_88)) {
 867                        printk("[AEDSP16] CMD 0x%x: failed!\n", COMMAND_88);
 868                        return FALSE;
 869                }
 870                mdelay(10);
 871        } while ((aedsp16_wait_data(port) == FALSE) && loop--);
 872
 873        if (aedsp16_read(port) == -1) {
 874                printk("[AEDSP16] aedsp16_read after CMD 0x%x: failed\n",
 875                                COMMAND_88);
 876                return FALSE;
 877        }
 878
 879#if !defined(CONFIG_SC6600)
 880        if (aedsp16_write(port, COMMAND_5C)) {
 881                printk("[AEDSP16] CMD 0x%x: failed!\n", COMMAND_5C);
 882                return FALSE;
 883        }
 884#endif
 885
 886        if (aedsp16_cfg_write(port) == FALSE)
 887                return FALSE;
 888
 889#if defined(CONFIG_SC6600)
 890        if (aedsp16_write(port, COMMAND_60)) {
 891                printk("[AEDSP16] CMD 0x%x: failed!\n", COMMAND_60);
 892                return FALSE;
 893        }
 894        if (aedsp16_write(port, val)) {
 895                printk("[AEDSP16] DATA 0x%x: failed!\n", val);
 896                return FALSE;
 897        }
 898        if (aedsp16_write(port, COMMAND_6E)) {
 899                printk("[AEDSP16] CMD 0x%x: failed!\n", COMMAND_6E);
 900                return FALSE;
 901        }
 902        if (aedsp16_write(port, ver[0])) {
 903                printk("[AEDSP16] DATA 0x%x: failed!\n", ver[0]);
 904                return FALSE;
 905        }
 906        if (aedsp16_write(port, ver[1])) {
 907                printk("[AEDSP16] DATA 0x%x: failed!\n", ver[1]);
 908                return FALSE;
 909        }
 910
 911        if (aedsp16_hard_write(port) == FALSE) {
 912                printk("[AEDSP16] aedsp16_hard_write: failed!\n");
 913                return FALSE;
 914        }
 915
 916        if (aedsp16_write(port, COMMAND_5C)) {
 917                printk("[AEDSP16] CMD 0x%x: failed!\n", COMMAND_5C);
 918                return FALSE;
 919        }
 920
 921#if defined(THIS_IS_A_THING_I_HAVE_NOT_TESTED_YET)
 922        if (aedsp16_cfg_write(port) == FALSE)
 923                return FALSE;
 924#endif
 925
 926#endif
 927
 928        return TRUE;
 929}
 930
 931static int __init aedsp16_stdcfg(int port) {
 932        if (aedsp16_write(port, WRITE_MDIRQ_CFG)) {
 933                printk("[AEDSP16] CMD 0x%x: failed!\n", WRITE_MDIRQ_CFG);
 934                return FALSE;
 935        }
 936        /*
 937         * 0x0A == (IRQ 7, DMA 1, MIRQ 0)
 938         */
 939        if (aedsp16_write(port, 0x0A)) {
 940                printk("[AEDSP16] aedsp16_stdcfg: failed!\n");
 941                return FALSE;
 942        }
 943        return TRUE;
 944}
 945
 946static int __init aedsp16_dsp_version(int port)
 947{
 948        int             len = 0;
 949        int             ret;
 950
 951        DBG(("Get DSP Version:\n"));
 952
 953        if (aedsp16_write(ae_config.base_io, GET_DSP_VERSION)) {
 954                printk("[AEDSP16] CMD 0x%x: failed!\n", GET_DSP_VERSION);
 955                DBG(("failed.\n"));
 956                return FALSE;
 957        }
 958
 959        do {
 960                if ((ret = aedsp16_read(port)) == -1) {
 961                        DBG(("failed.\n"));
 962                        return FALSE;
 963                }
 964        /*
 965         * We already know how many int are stored (2), so we know when the
 966         * string is finished.
 967         */
 968                ver[len++] = ret;
 969          } while (len < CARDVERLEN);
 970        sprintf(DSPVersion, "%d.%d", ver[0], ver[1]);
 971
 972        DBG(("success.\n"));
 973
 974        return TRUE;
 975}
 976
 977static int __init aedsp16_dsp_copyright(int port)
 978{
 979        int             len = 0;
 980        int             ret;
 981
 982        DBG(("Get DSP Copyright:\n"));
 983
 984        if (aedsp16_write(ae_config.base_io, GET_DSP_COPYRIGHT)) {
 985                printk("[AEDSP16] CMD 0x%x: failed!\n", GET_DSP_COPYRIGHT);
 986                DBG(("failed.\n"));
 987                return FALSE;
 988        }
 989
 990        do {
 991                if ((ret = aedsp16_read(port)) == -1) {
 992        /*
 993         * If no more data available, return to the caller, no error if len>0.
 994         * We have no other way to know when the string is finished.
 995         */
 996                        if (len)
 997                                break;
 998                        else {
 999                                DBG(("failed.\n"));
1000                                return FALSE;
1001                        }
1002                }
1003
1004                DSPCopyright[len++] = ret;
1005
1006          } while (len < CARDNAMELEN);
1007
1008        DBG(("success.\n"));
1009
1010        return TRUE;
1011}
1012
1013static void __init aedsp16_init_tables(void)
1014{
1015        int i = 0;
1016
1017        memset(DSPCopyright, 0, CARDNAMELEN + 1);
1018        memset(DSPVersion, 0, CARDVERLEN + 1);
1019
1020        for (i = 0; orIRQ[i].or; i++)
1021                if (orIRQ[i].val == ae_config.irq) {
1022                        soft_cfg |= orIRQ[i].or;
1023                        soft_cfg_mss |= orIRQ[i].or;
1024                }
1025
1026        for (i = 0; orMIRQ[i].or; i++)
1027                if (orMIRQ[i].or == ae_config.mpu_irq)
1028                        soft_cfg |= orMIRQ[i].or;
1029
1030        for (i = 0; orDMA[i].or; i++)
1031                if (orDMA[i].val == ae_config.dma) {
1032                        soft_cfg |= orDMA[i].or;
1033                        soft_cfg_mss |= orDMA[i].or;
1034                }
1035}
1036
1037static int __init aedsp16_init_board(void)
1038{
1039        aedsp16_init_tables();
1040
1041        if (aedsp16_dsp_reset(ae_config.base_io) == FALSE) {
1042                printk("[AEDSP16] aedsp16_dsp_reset: failed!\n");
1043                return FALSE;
1044        }
1045        if (aedsp16_dsp_copyright(ae_config.base_io) == FALSE) {
1046                printk("[AEDSP16] aedsp16_dsp_copyright: failed!\n");
1047                return FALSE;
1048        }
1049
1050        /*
1051         * My AEDSP16 card return SC-6000 in DSPCopyright, so
1052         * if we have something different, we have to be warned.
1053         */
1054        if (strcmp("SC-6000", DSPCopyright))
1055                printk("[AEDSP16] Warning: non SC-6000 audio card!\n");
1056
1057        if (aedsp16_dsp_version(ae_config.base_io) == FALSE) {
1058                printk("[AEDSP16] aedsp16_dsp_version: failed!\n");
1059                return FALSE;
1060        }
1061
1062        if (aedsp16_stdcfg(ae_config.base_io) == FALSE) {
1063                printk("[AEDSP16] aedsp16_stdcfg: failed!\n");
1064                return FALSE;
1065        }
1066
1067#if defined(CONFIG_SC6600)
1068        if (aedsp16_hard_read(ae_config.base_io) == FALSE) {
1069                printk("[AEDSP16] aedsp16_hard_read: failed!\n");
1070                return FALSE;
1071        }
1072
1073        aedsp16_hard_decode();
1074
1075        aedsp16_hard_encode();
1076
1077        if (aedsp16_hard_write(ae_config.base_io) == FALSE) {
1078                printk("[AEDSP16] aedsp16_hard_write: failed!\n");
1079                return FALSE;
1080        }
1081
1082        if (aedsp16_ext_cfg_write(ae_config.base_io) == FALSE) {
1083                printk("[AEDSP16] aedsp16_ext_cfg_write: failed!\n");
1084                return FALSE;
1085        }
1086#endif /* CONFIG_SC6600 */
1087
1088        if (aedsp16_setup_board(ae_config.base_io) == FALSE) {
1089                printk("[AEDSP16] aedsp16_setup_board: failed!\n");
1090                return FALSE;
1091        }
1092
1093        if (ae_config.mss_base != -1) {
1094                if (ae_config.init & INIT_MSS) {
1095                        if (aedsp16_init_mss(ae_config.base_io) == FALSE) {
1096                                printk("[AEDSP16] Can not initialize"
1097                                       "Microsoft Sound System mode.\n");
1098                                return FALSE;
1099                        }
1100                }
1101        }
1102
1103#if !defined(MODULE) || defined(AEDSP16_INFO) || defined(AEDSP16_DEBUG)
1104
1105        printk("Audio Excel DSP 16 init v%s (%s %s) [",
1106                VERSION, DSPCopyright,
1107                DSPVersion);
1108
1109        if (ae_config.mpu_base != -1) {
1110                if (ae_config.init & INIT_MPU401) {
1111                        printk("MPU401");
1112                        if ((ae_config.init & INIT_MSS) ||
1113                            (ae_config.init & INIT_SBPRO))
1114                                printk(" ");
1115                }
1116        }
1117
1118        if (ae_config.mss_base == -1) {
1119                if (ae_config.init & INIT_SBPRO) {
1120                        printk("SBPro");
1121                        if (ae_config.init & INIT_MSS)
1122                                printk(" ");
1123                }
1124        }
1125
1126        if (ae_config.mss_base != -1)
1127                if (ae_config.init & INIT_MSS)
1128                        printk("MSS");
1129
1130        printk("]\n");
1131#endif /* MODULE || AEDSP16_INFO || AEDSP16_DEBUG */
1132
1133        mdelay(10);
1134
1135        return TRUE;
1136}
1137
1138static int __init init_aedsp16_sb(void)
1139{
1140        DBG(("init_aedsp16_sb: "));
1141
1142/*
1143 * If the card is already init'ed MSS, we can not init it to SBPRO too
1144 * because the board can not emulate simultaneously MSS and SBPRO.
1145 */
1146        if (ae_config.init & INIT_MSS)
1147                return FALSE;
1148        if (ae_config.init & INIT_SBPRO)
1149                return FALSE;
1150
1151        ae_config.init |= INIT_SBPRO;
1152
1153        DBG(("done.\n"));
1154
1155        return TRUE;
1156}
1157
1158static void __init uninit_aedsp16_sb(void)
1159{
1160        DBG(("uninit_aedsp16_sb: "));
1161
1162        ae_config.init &= ~INIT_SBPRO;
1163
1164        DBG(("done.\n"));
1165}
1166
1167static int __init init_aedsp16_mss(void)
1168{
1169        DBG(("init_aedsp16_mss: "));
1170
1171/*
1172 * If the card is already init'ed SBPRO, we can not init it to MSS too
1173 * because the board can not emulate simultaneously MSS and SBPRO.
1174 */
1175        if (ae_config.init & INIT_SBPRO)
1176                return FALSE;
1177        if (ae_config.init & INIT_MSS)
1178                return FALSE;
1179/*
1180 * We must allocate the CONFIG_AEDSP16_BASE region too because these are the 
1181 * I/O ports to access card's control registers.
1182 */
1183        if (!(ae_config.init & INIT_MPU401)) {
1184                if (!request_region(ae_config.base_io, IOBASE_REGION_SIZE,
1185                                "aedsp16 (base)")) {
1186                        printk(
1187                        "AEDSP16 BASE I/O port region is already in use.\n");
1188                        return FALSE;
1189                }
1190        }
1191
1192        ae_config.init |= INIT_MSS;
1193
1194        DBG(("done.\n"));
1195
1196        return TRUE;
1197}
1198
1199static void __init uninit_aedsp16_mss(void)
1200{
1201        DBG(("uninit_aedsp16_mss: "));
1202
1203        if ((!(ae_config.init & INIT_MPU401)) &&
1204           (ae_config.init & INIT_MSS)) {
1205                release_region(ae_config.base_io, IOBASE_REGION_SIZE);
1206                DBG(("AEDSP16 base region released.\n"));
1207        }
1208
1209        ae_config.init &= ~INIT_MSS;
1210        DBG(("done.\n"));
1211}
1212
1213static int __init init_aedsp16_mpu(void)
1214{
1215        DBG(("init_aedsp16_mpu: "));
1216
1217        if (ae_config.init & INIT_MPU401)
1218                return FALSE;
1219
1220/*
1221 * We must request the CONFIG_AEDSP16_BASE region too because these are the I/O 
1222 * ports to access card's control registers.
1223 */
1224        if (!(ae_config.init & (INIT_MSS | INIT_SBPRO))) {
1225                if (!request_region(ae_config.base_io, IOBASE_REGION_SIZE,
1226                                        "aedsp16 (base)")) {
1227                        printk(
1228                        "AEDSP16 BASE I/O port region is already in use.\n");
1229                        return FALSE;
1230                }
1231        }
1232
1233        ae_config.init |= INIT_MPU401;
1234
1235        DBG(("done.\n"));
1236
1237        return TRUE;
1238}
1239
1240static void __init uninit_aedsp16_mpu(void)
1241{
1242        DBG(("uninit_aedsp16_mpu: "));
1243
1244        if ((!(ae_config.init & (INIT_MSS | INIT_SBPRO))) &&
1245           (ae_config.init & INIT_MPU401)) {
1246                release_region(ae_config.base_io, IOBASE_REGION_SIZE);
1247                DBG(("AEDSP16 base region released.\n"));
1248        }
1249
1250        ae_config.init &= ~INIT_MPU401;
1251
1252        DBG(("done.\n"));
1253}
1254
1255int __init init_aedsp16(void)
1256{
1257        int initialized = FALSE;
1258
1259        DBG(("Initializing BASE[0x%x] IRQ[%d] DMA[%d] MIRQ[%d]\n",
1260             ae_config.base_io,ae_config.irq,ae_config.dma,ae_config.mpu_irq));
1261
1262        if (ae_config.mss_base == -1) {
1263                if (init_aedsp16_sb() == FALSE) {
1264                        uninit_aedsp16_sb();
1265                } else {
1266                        initialized = TRUE;
1267                }
1268        }
1269
1270        if (ae_config.mpu_base != -1) {
1271                if (init_aedsp16_mpu() == FALSE) {
1272                        uninit_aedsp16_mpu();
1273                } else {
1274                        initialized = TRUE;
1275                }
1276        }
1277
1278/*
1279 * In the sequence of init routines, the MSS init MUST be the last!
1280 * This because of the special register programming the MSS mode needs.
1281 * A board reset would disable the MSS mode restoring the default SBPRO
1282 * mode.
1283 */
1284        if (ae_config.mss_base != -1) {
1285                if (init_aedsp16_mss() == FALSE) {
1286                        uninit_aedsp16_mss();
1287                } else {
1288                        initialized = TRUE;
1289                }
1290        }
1291
1292        if (initialized)
1293                initialized = aedsp16_init_board();
1294        return initialized;
1295}
1296
1297void __init uninit_aedsp16(void)
1298{
1299        if (ae_config.mss_base != -1)
1300                uninit_aedsp16_mss();
1301        else
1302                uninit_aedsp16_sb();
1303        if (ae_config.mpu_base != -1)
1304                uninit_aedsp16_mpu();
1305}
1306
1307static int __initdata io = -1;
1308static int __initdata irq = -1;
1309static int __initdata dma = -1;
1310static int __initdata mpu_irq = -1;
1311static int __initdata mss_base = -1;
1312static int __initdata mpu_base = -1;
1313
1314MODULE_PARM(io, "i");
1315MODULE_PARM_DESC(io, "I/O base address (0x220 0x240)");
1316MODULE_PARM(irq, "i");
1317MODULE_PARM_DESC(irq, "IRQ line (5 7 9 10 11)");
1318MODULE_PARM(dma, "i");
1319MODULE_PARM_DESC(dma, "dma line (0 1 3)");
1320MODULE_PARM(mpu_irq, "i");
1321MODULE_PARM_DESC(mpu_irq, "MPU-401 IRQ line (5 7 9 10 0)");
1322MODULE_PARM(mss_base, "i");
1323MODULE_PARM_DESC(mss_base, "MSS emulation I/O base address (0x530 0xE80)");
1324MODULE_PARM(mpu_base, "i");
1325MODULE_PARM_DESC(mpu_base,"MPU-401 I/O base address (0x300 0x310 0x320 0x330)");
1326MODULE_AUTHOR("Riccardo Facchetti <fizban@tin.it>");
1327MODULE_DESCRIPTION("Audio Excel DSP 16 Driver Version " VERSION);
1328MODULE_LICENSE("GPL");
1329
1330static int __init do_init_aedsp16(void) {
1331        printk("Audio Excel DSP 16 init driver Copyright (C) Riccardo Facchetti 1995-98\n");
1332        if (io == -1 || dma == -1 || irq == -1) {
1333                printk(KERN_INFO "aedsp16: I/O, IRQ and DMA are mandatory\n");
1334                return -EINVAL;
1335        }
1336
1337        ae_config.base_io = io;
1338        ae_config.irq = irq;
1339        ae_config.dma = dma;
1340
1341        ae_config.mss_base = mss_base;
1342        ae_config.mpu_base = mpu_base;
1343        ae_config.mpu_irq = mpu_irq;
1344
1345        if (init_aedsp16() == FALSE) {
1346                printk(KERN_ERR "aedsp16: initialization failed\n");
1347                /*
1348                 * XXX
1349                 * What error should we return here ?
1350                 */
1351                return -EINVAL;
1352        }
1353        return 0;
1354}
1355
1356static void __exit cleanup_aedsp16(void) {
1357        uninit_aedsp16();
1358}
1359
1360module_init(do_init_aedsp16);
1361module_exit(cleanup_aedsp16);
1362
1363#ifndef MODULE
1364static int __init setup_aedsp16(char *str)
1365{
1366        /* io, irq, dma, mss_io, mpu_io, mpu_irq */
1367        int ints[7];
1368        
1369        str = get_options(str, ARRAY_SIZE(ints), ints);
1370
1371        io       = ints[1];
1372        irq      = ints[2];
1373        dma      = ints[3];
1374        mss_base = ints[4];
1375        mpu_base = ints[5];
1376        mpu_irq  = ints[6];
1377        return 1;
1378}
1379
1380__setup("aedsp16=", setup_aedsp16);
1381#endif
1382
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.