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