1 /*
2 sound/aedsp16.c
3
4 Audio Excel DSP 16 software configuration routines
5
6 Copyright (C) 1995 Riccardo Facchetti (riccardo@cdc8g5.cdc.polimi.it)
7
8 Redistribution and use in source and binary forms, with or without
9 modification, are permitted provided that the following conditions are
10 met: 1. Redistributions of source code must retain the above copyright
11 notice, this list of conditions and the following disclaimer. 2.
12 Redistributions in binary form must reproduce the above copyright notice,
13 this list of conditions and the following disclaimer in the documentation
14 and/or other materials provided with the distribution.
15
16 THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY
17 EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
20 ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
22 SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
23 CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24 LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 SUCH DAMAGE.
27 */
28 /*
29 * Include the main voxware header file. It include all the os/voxware/etc
30 * headers needed by this source.
31 */
32 #include "sound_config.h"
33
34 #ifndef AEDSP16_BASE
35 #undef CONFIG_AEDSP16
36 #endif
37
38 #if defined(CONFIG_AEDSP16)
39 /*
40
41 READ THIS
42
43 This module is intended for Audio Excel DSP 16 Sound Card.
44
45 Audio Excel DSP 16 is an SB pro II, Microsoft Sound System
46 and MPU-401 compatible card.
47 It is software-only configurable (no jumpers to hard-set irq/dma/mpu-irq),
48 so before this module, the only way to configure the DSP under linux was
49 boot the MS-BAU loading the sound.sys device driver (this driver soft-
50 configure the sound board hardware by massaging someone of its registers),
51 and then ctrl-alt-del to boot linux with the DSP configured by the DOG
52 driver.
53
54 This module works configuring your Audio Excel DSP 16's
55 irq, dma and mpu-401-irq. The voxware probe routines rely on the
56 fact that if the hardware is there, they can detect it. The problem
57 with AEDSP16 is that no hardware can be found by the probe routines
58 if the sound card is not well configured. Sometimes the kernel probe
59 routines can find an SBPRO even when the card is not configured (this
60 is the standard setup of the card), but the SBPRO emulation don't work
61 well if the card is not properly initialized. For this reason
62
63 InitAEDSP16_...()
64
65 routines are called before the voxware probe routines try to detect the
66 hardware.
67
68 NOTE (READ THE NOTE TOO, IT CONTAIN USEFUL INFORMATIONS)
69
70 The Audio Excel DSP 16 Sound Card emulates both SBPRO and MSS;
71 the voxware sound driver can be configured for SBPRO and MSS cards
72 at the same time, but the aedsp16 can't be two cards!!
73 When we configure it, we have to choose the SBPRO or the MSS emulation
74 for AEDSP16. We also can install a *REAL* card of the other type
75 (see [1], not tested but I can't see any reason for it to fail).
76
77 NOTE: If someone can test the combination AEDSP16+MSS or AEDSP16+SBPRO
78 please let me know if it works.
79
80 The MPU-401 support can be compiled in together with one of the other
81 two operating modes.
82
83 The board configuration calls, are in the probe_...() routines because
84 we have to configure the board before probing it for a particular
85 hardware. After card configuration, we can probe the hardware.
86
87 NOTE: This is something like plug-and-play: we have only to plug
88 the AEDSP16 board in the socket, and then configure and compile
89 a kernel that uses the AEDSP16 software configuration capability.
90 No jumper setting is needed!
91
92 For example, if you want AEDSP16 to be an SBPro, on irq 10, dma 3
93 you have just to make config the voxware package, configuring
94 the SBPro sound card with that parameters, then when configure
95 asks if you have an AEDSP16, answer yes. That's it.
96 Compile the kernel and run it.
97
98 NOTE: This means that you can choose irq and dma, but not the
99 I/O addresses. To change I/O addresses you have to set them
100 with jumpers.
101
102 NOTE: InitAEDSP16_...() routines get as parameter the hw_config,
103 the hardware configuration of the - to be configured - board.
104 The InitAEDSP16() routine, configure the board following our
105 wishes, that are in the hw_config structure.
106
107 You can change the irq/dma/mirq settings WITHOUT THE NEED to open
108 your computer and massage the jumpers (there are no irq/dma/mirq
109 jumpers to be configured anyway, only I/O port ones have to be
110 configured with jumpers)
111
112 For some ununderstandable reason, the card default of irq 7, dma 1,
113 don't work for me. Seems to be an IRQ or DMA conflict. Under heavy
114 HDD work, the kernel start to erupt out a lot of messages like:
115
116 'Sound: DMA timed out - IRQ/DRQ config error?'
117
118 For what I can say, I have NOT any conflict at irq 7 (under linux I'm
119 using the lp polling driver), and dma line 1 is unused as stated by
120 /proc/dma. I can suppose this is a bug of AEDSP16. I know my hardware so
121 I'm pretty sure I have not any conflict, but may be I'm wrong. Who knows!
122 Anyway a setting of irq 10, dma 3 works really fine.
123
124 NOTE: if someone can use AEDSP16 with irq 7, dma 1, please let me know
125 the emulation mode, all the installed hardware and the hardware
126 configuration (irq and dma settings of all the hardware).
127
128 This init module should work with SBPRO+MSS, when one of the two is
129 the AEDSP16 emulation and the other the real card. (see [1])
130 For example:
131
132 AEDSP16 (0x220) in SBPRO emu (0x220) + real MSS + other
133 AEDSP16 (0x220) in MSS emu + real SBPRO (0x240) + other
134
135 MPU401 should work. (see [1])
136
137 [1] Not tested by me for lack of hardware.
138
139 TODO, WISHES AND TECH
140
141 May be there's lot of redundant delays, but for now I want to leave it
142 this way.
143
144 Should be interesting eventually write down a new ioctl for the
145 aedsp16, to let the suser() change the irq/dma/mirq on the fly.
146 The thing is not trivial.
147 In the real world, there's no need to have such an ioctl because
148 when we configure the kernel for compile, we can choose the config
149 parameters. If we change our mind, we can easily re-config the kernel
150 and re-compile.
151 Why let the suser() change the config parameters on the fly ?
152 If anyone have a reasonable answer to this question, I will write down
153 the code to do it.
154
155 More integration with voxware, using voxware low level routines to
156 read-write dsp is not possible because you may want to have MSS
157 support and in that case we can not rely on the functions included
158 in sb_dsp.c to control 0x2yy I/O ports. I will continue to use my
159 own I/O functions.
160
161 - About I/O ports allocation -
162
163 The request_region should be done at device probe in every sound card
164 module. This module is not the best site for requesting regions.
165 When the request_region code will be added to the main modules such as
166 sb, adlib, gus, ad1848, etc, the requesting code in this module should
167 go away.
168
169 I think the request regions should be done this way:
170
171 if (check_region(...))
172 return ERR; // I/O region alredy reserved
173 device_probe(...);
174 device_attach(...);
175 request_region(...); // reserve only when we are sure all is okay
176
177 Request the 2x0h region in any case if we are using this card.
178
179 NOTE: the "(sbpro)" string with which we are requesting the aedsp16 region
180 (see code) does not mean necessarly that we are emulating sbpro.
181 It mean that the region is the sbpro I/O ports region. We use this
182 region to access the control registers of the card, and if emulating
183 sbpro, I/O sbpro registers too. If we are emulating MSS, the sbpro
184 registers are not used, in no way, to emulate an sbpro: they are
185 used only for configuration pourposes.
186
187 Someone pointed out that should be possible use both the SBPRO and MSS
188 modes because the sound card have all the two chipsets, supposing that
189 the card is really two cards. I have tried something to have the two
190 modes work together, but, for some reason unknown to me, without success.
191
192 I think all the soft-config only cards have an init sequence similar to
193 this. If you have a card that is not an aedsp16, you can try to start
194 with this module changing it (mainly in the CMD? I think) to fit your
195 needs.
196
197 Started Fri Mar 17 16:13:18 MET 1995
198
199 v0.1 (ALPHA, was an user-level program called AudioExcelDSP16.c)
200 - Initial code.
201 v0.2 (ALPHA)
202 - Cleanups.
203 - Integrated with Linux voxware v 2.90-2 kernel sound driver.
204 - SoundBlaster Pro mode configuration.
205 - Microsoft Sound System mode configuration.
206 - MPU-401 mode configuration.
207 v0.3 (ALPHA)
208 - Cleanups.
209 - Rearranged the code to let InitAEDSP16 be more general.
210 - Erased the REALLY_SLOW_IO. We don't need it. Erased the linux/io.h
211 inclusion too. We rely on os.h
212 - Used the to get a variable
213 len string (we are not sure about the len of Copyright string).
214 This works with any SB and compatible.
215 - Added the code to request_region at device init (should go in
216 the main body of voxware).
217 v0.4 (BETA)
218 - Better configure.c patch for aedsp16 configuration (better
219 logic of inclusion of AEDSP16 support)
220 - Modified the conditional compilation to better support more than
221 one sound card of the emulated type (read the NOTES above)
222 - Moved the sb init routine from the attach to the very first
223 probe in sb_card.c
224 - Rearrangemens and cleanups
225 - Wiped out some unnecessary code and variables: this is kernel
226 code so it is better save some TEXT and DATA
227 - Fixed the request_region code. We must allocate the aedsp16 (sbpro)
228 I/O ports in any case because they are used to access the DSP
229 configuration registers and we can not allow anyone to get them.
230 v0.5
231 - cleanups on comments
232 - prep for diffs against v3.0-proto-950402
233 v0.6
234 - removed the request_region()s when compiling the MODULE sound.o
235 because we are not allowed (by the actual voxware structure) to
236 release_region()
237
238 */
239
240
241 #define VERSION "0.6" /* Version of Audio Excel DSP 16 driver */
242
243 #undef AEDSP16_DEBUG /* Define this to enable debug code */
244 /* Actually no debug code is activated */
245
246 /*
247 * Hardware related defaults
248 */
249 #define IRQ 7 /* 5 7(default) 9 10 11 */
250 #define MIRQ 0 /* 5 7 9 10 0(default), 0 means disable */
251 #define DMA 1 /* 0 1(default) 3 */
252
253 /*
254 * Commands of AEDSP16's DSP (SBPRO+special).
255 * For now they are CMDn, in the future they may change.
256 */
257 #define CMD1 0xe3 /* Get DSP Copyright */
258 #define CMD2 0xe1 /* Get DSP Version */
259 #define CMD3 0x88 /* */
260 #define CMD4 0x5c /* */
261 #define CMD5 0x50 /* Set M&I&DRQ mask (the real config) */
262 #define CMD6 0x8c /* Enable Microsoft Sound System mode */
263
264 /*
265 * Offsets of AEDSP16 DSP I/O ports. The offest is added to portbase
266 * to have the actual I/O port.
267 * Register permissions are:
268 * (wo) == Write Only
269 * (ro) == Read Only
270 * (w-) == Write
271 * (r-) == Read
272 */
273 #define DSP_RESET 0x06 /* offset of DSP RESET (wo) */
274 #define DSP_READ 0x0a /* offset of DSP READ (ro) */
275 #define DSP_WRITE 0x0c /* offset of DSP WRITE (w-) */
276 #define DSP_COMMAND 0x0c /* offset of DSP COMMAND (w-) */
277 #define DSP_STATUS 0x0c /* offset of DSP STATUS (r-) */
278 #define DSP_DATAVAIL 0x0e /* offset of DSP DATA AVAILABLE (ro) */
279
280
281 #define RETRY 10 /* Various retry values on I/O opera- */
282 #define STATUSRETRY 1000 /* tions. Sometimes we have to */
283 #define HARDRETRY 500000 /* wait for previous cmd to complete */
284
285 /*
286 * Size of character arrays that store name and version of sound card
287 */
288 #define CARDNAMELEN 15 /* Size of the card's name in chars */
289 #define CARDVERLEN 2 /* Size of the card's version in chars */
290
291 /*
292 * Bit mapped flags for calling InitAEDSP16(), and saving the current
293 * emulation mode.
294 */
295 #define INIT_NONE (0 )
296 #define INIT_SBPRO (1<<0)
297 #define INIT_MSS (1<<1)
298 #define INIT_MPU401 (1<<2)
299 #define RESET_DSP16 (1<<3)
300
301 /* Base HW Port for Audio Card */
302 static int portbase = AEDSP16_BASE;
303 static int irq = IRQ; /* irq for DSP I/O */
304 static int mirq = MIRQ; /* irq for MPU-401 I/O */
305 static int dma = DMA; /* dma for DSP I/O */
306
307 /* Init status of the card */
308 static int ae_init = INIT_NONE; /* (bitmapped variable) */
309 static int oredparams = 0; /* Will contain or'ed values of params */
310 static int gc = 0; /* generic counter (utility counter) */
311 struct orVals
312 { /* Contain the values to be or'ed */
313 int val; /* irq|mirq|dma */
314 int or; /* oredparams |= TheStruct.or */
315 };
316
317 /*
318 * Magic values that the DSP will eat when configuring irq/mirq/dma
319 */
320 /* DSP IRQ conversion array */
321 static struct orVals orIRQ[] =
322 {
323 {0x05, 0x28},
324 {0x07, 0x08},
325 {0x09, 0x10},
326 {0x0a, 0x18},
327 {0x0b, 0x20},
328 {0x00, 0x00}
329 };
330
331 /* MPU-401 IRQ conversion array */
332 static struct orVals orMIRQ[] =
333 {
334 {0x05, 0x04},
335 {0x07, 0x44},
336 {0x09, 0x84},
337 {0x0a, 0xc4},
338 {0x00, 0x00}
339 };
340
341 /* DMA Channels conversion array */
342 static struct orVals orDMA[] =
343 {
344 {0x00, 0x01},
345 {0x01, 0x02},
346 {0x03, 0x03},
347 {0x00, 0x00}
348 };
349
350 /*
351 * Buffers to store audio card informations
352 */
353 static char AudioExcelName[CARDNAMELEN + 1];
354 static char AudioExcelVersion[CARDVERLEN + 1];
355
356 static void
357 tenmillisec (void)
/* ![[previous]](../icons/n_left.png)
![[next]](../icons/right.png)
![[first]](../icons/n_first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
358 {
359
360 for (gc = 0; gc < 1000; gc++)
361 tenmicrosec ();
362 }
363
364 static int
365 WaitForDataAvail (int port)
/* ![[previous]](../icons/left.png)
![[next]](../icons/right.png)
![[first]](../icons/first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
366 {
367 int loop = STATUSRETRY;
368 unsigned char ret = 0;
369
370 do
371 {
372 ret = inb (port + DSP_DATAVAIL);
373 /*
374 * Wait for data available (bit 7 of ret == 1)
375 */
376 }
377 while (!(ret & 0x80) && loop--);
378
379 if (ret & 0x80)
380 return 0;
381
382 return -1;
383 }
384
385 static int
386 ReadData (int port)
/* ![[previous]](../icons/left.png)
![[next]](../icons/right.png)
![[first]](../icons/first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
387 {
388 if (WaitForDataAvail (port))
389 return -1;
390 return inb (port + DSP_READ);
391 }
392
393 static int
394 CheckDSPOkay (int port)
/* ![[previous]](../icons/left.png)
![[next]](../icons/right.png)
![[first]](../icons/first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
395 {
396 return ((ReadData (port) == 0xaa) ? 0 : -1);
397 }
398
399 static int
400 ResetBoard (int port)
/* ![[previous]](../icons/left.png)
![[next]](../icons/right.png)
![[first]](../icons/first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
401 {
402 /*
403 * Reset DSP
404 */
405 outb (1, (port + DSP_RESET));
406 tenmicrosec ();
407 outb (0, (port + DSP_RESET));
408 tenmicrosec ();
409 tenmicrosec ();
410 return CheckDSPOkay (port);
411 }
412
413 static int
414 WriteDSPCommand (int port, int cmd)
/* ![[previous]](../icons/left.png)
![[next]](../icons/right.png)
![[first]](../icons/first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
415 {
416 unsigned char ret;
417 int loop = HARDRETRY;
418
419 do
420 {
421 ret = inb (port + DSP_STATUS);
422 /*
423 * DSP ready to receive data if bit 7 of ret == 0
424 */
425 if (!(ret & 0x80))
426 {
427 outb (cmd, port + DSP_COMMAND);
428 return 0;
429 }
430 }
431 while (loop--);
432
433 printk ("[aedsp16] DSP Command (0x%x) timeout.\n", cmd);
434 return -1;
435 }
436
437 int
438 InitMSS (int port)
/* ![[previous]](../icons/left.png)
![[next]](../icons/right.png)
![[first]](../icons/first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
439 {
440
441 tenmillisec ();
442
443 if (WriteDSPCommand (port, CMD6))
444 {
445 printk ("[aedsp16] CMD 0x%x: failed!\n", CMD6);
446 return -1;
447 }
448
449 tenmillisec ();
450
451 return 0;
452 }
453
454 static int
455 SetUpBoard (int port)
/* ![[previous]](../icons/left.png)
![[next]](../icons/right.png)
![[first]](../icons/first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
456 {
457 int loop = RETRY;
458
459 do
460 {
461 if (WriteDSPCommand (portbase, CMD3))
462 {
463 printk ("[aedsp16] CMD 0x%x: failed!\n", CMD3);
464 return -1;
465 }
466
467 tenmillisec ();
468
469 }
470 while (WaitForDataAvail (port) && loop--);
471
472 #if defined(THIS_SHOULD_GO_AWAY)
473 if (CheckDSPOkay (port))
474 {
475 printk ("[aedsp16] CheckDSPOkay: failed\n");
476 return -1;
477 }
478 #else
479 if (ReadData (port) == -1)
480 {
481 printk ("[aedsp16] ReadData after CMD 0x%x: failed\n", CMD3);
482 return -1;
483 }
484 #endif
485
486 if (WriteDSPCommand (portbase, CMD4))
487 {
488 printk ("[aedsp16] CMD 0x%x: failed!\n", CMD4);
489 return -1;
490 }
491
492 if (WriteDSPCommand (portbase, CMD5))
493 {
494 printk ("[aedsp16] CMD 0x%x: failed!\n", CMD5);
495 return -1;
496 }
497
498 if (WriteDSPCommand (portbase, oredparams))
499 {
500 printk ("[aedsp16] Initialization of (M)IRQ and DMA: failed!\n");
501 return -1;
502 }
503 return 0;
504 }
505
506 static int
507 GetCardVersion (int port)
/* ![[previous]](../icons/left.png)
![[next]](../icons/right.png)
![[first]](../icons/first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
508 {
509 int len = 0;
510 int ret;
511 int ver[3];
512
513 do
514 {
515 if ((ret = ReadData (port)) == -1)
516 return -1;
517 /*
518 * We alredy know how many int are stored (2), so we know when the
519 * string is finished.
520 */
521 ver[len++] = ret;
522 }
523 while (len < CARDVERLEN);
524 sprintf (AudioExcelVersion, "%d.%d", ver[0], ver[1]);
525 return 0;
526 }
527
528 static int
529 GetCardName (int port)
/* ![[previous]](../icons/left.png)
![[next]](../icons/right.png)
![[first]](../icons/first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
530 {
531 int len = 0;
532 int ret;
533
534 do
535 {
536 if ((ret = ReadData (port)) == -1)
537 /*
538 * If no more data availabe, return to the caller, no error if len>0.
539 * We have no other way to know when the string is finished.
540 */
541 return (len ? 0 : -1);
542
543 AudioExcelName[len++] = ret;
544
545 }
546 while (len < CARDNAMELEN);
547 return 0;
548 }
549
550 static void
551 InitializeHardParams (void)
/* ![[previous]](../icons/left.png)
![[next]](../icons/right.png)
![[first]](../icons/first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
552 {
553
554 memset (AudioExcelName, 0, CARDNAMELEN + 1);
555 memset (AudioExcelVersion, 0, CARDVERLEN + 1);
556
557 for (gc = 0; orIRQ[gc].or; gc++)
558 if (orIRQ[gc].val == irq)
559 oredparams |= orIRQ[gc].or;
560
561 for (gc = 0; orMIRQ[gc].or; gc++)
562 if (orMIRQ[gc].or == mirq)
563 oredparams |= orMIRQ[gc].or;
564
565 for (gc = 0; orDMA[gc].or; gc++)
566 if (orDMA[gc].val == dma)
567 oredparams |= orDMA[gc].or;
568 }
569
570 static int
571 InitAEDSP16 (int which)
/* ![[previous]](../icons/left.png)
![[next]](../icons/right.png)
![[first]](../icons/first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
572 {
573 static char *InitName = NULL;
574
575 InitializeHardParams ();
576
577 if (ResetBoard (portbase))
578 {
579 printk ("[aedsp16] ResetBoard: failed!\n");
580 return -1;
581 }
582
583 #if defined(THIS_SHOULD_GO_AWAY)
584 if (CheckDSPOkay (portbase))
585 {
586 printk ("[aedsp16] CheckDSPOkay: failed!\n");
587 return -1;
588 }
589 #endif
590
591 if (WriteDSPCommand (portbase, CMD1))
592 {
593 printk ("[aedsp16] CMD 0x%x: failed!\n", CMD1);
594 return -1;
595 }
596
597 if (GetCardName (portbase))
598 {
599 printk ("[aedsp16] GetCardName: failed!\n");
600 return -1;
601 }
602
603 /*
604 * My AEDSP16 card return SC-6000 in AudioExcelName, so
605 * if we have something different, we have to be warned.
606 */
607 if (strcmp ("SC-6000", AudioExcelName))
608 printk ("[aedsp16] Warning: non SC-6000 audio card!\n");
609
610 if (WriteDSPCommand (portbase, CMD2))
611 {
612 printk ("[aedsp16] CMD 0x%x: failed!\n", CMD2);
613 return -1;
614 }
615
616 if (GetCardVersion (portbase))
617 {
618 printk ("[aedsp16] GetCardVersion: failed!\n");
619 return -1;
620 }
621
622 if (SetUpBoard (portbase))
623 {
624 printk ("[aedsp16] SetUpBoard: failed!\n");
625 return -1;
626 }
627
628 if (which == INIT_MSS)
629 {
630 if (InitMSS (portbase))
631 {
632 printk ("[aedsp16] Can't initialize Microsoft Sound System mode.\n");
633 return -1;
634 }
635 }
636
637 /*
638 * If we are resetting, do not print any message because we may be
639 * in playing and we do not want lost too much time.
640 */
641 if (!(which & RESET_DSP16))
642 {
643 if (which & INIT_MPU401)
644 InitName = "MPU401";
645 else if (which & INIT_SBPRO)
646 InitName = "SBPro";
647 else if (which & INIT_MSS)
648 InitName = "MSS";
649 else
650 InitName = "None";
651
652 printk ("Audio Excel DSP 16 init v%s (%s %s) [%s]\n",
653 VERSION, AudioExcelName,
654 AudioExcelVersion, InitName);
655 }
656
657 tenmillisec ();
658
659 return 0;
660 }
661
662 #if defined(AEDSP16_SBPRO)
663
664 int
665 InitAEDSP16_SBPRO (struct address_info *hw_config)
/* ![[previous]](../icons/left.png)
![[next]](../icons/right.png)
![[first]](../icons/first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
666 {
667 /*
668 * If the card is alredy init'ed MSS, we can not init it to SBPRO too
669 * because the board can not emulate simultaneously MSS and SBPRO.
670 */
671 if (ae_init & INIT_MSS)
672 return -1;
673 if (ae_init & INIT_SBPRO)
674 return 0;
675
676 /*
677 * For now we will leave this
678 * code included only when INCLUDE_AEDSP16 is configured in, but it should
679 * be better include it every time.
680 */
681 if (!(ae_init & INIT_MPU401))
682 {
683 if (check_region (hw_config->io_base, 0x0f))
684 {
685 printk ("AEDSP16/SBPRO I/O port region is alredy in use.\n");
686 return -1;
687 }
688 }
689
690 /*
691 * Set up the internal hardware parameters, to let the driver reach
692 * the Sound Card.
693 */
694 portbase = hw_config->io_base;
695 irq = hw_config->irq;
696 dma = hw_config->dma;
697
698 if (InitAEDSP16 (INIT_SBPRO))
699 return -1;
700
701 #if !defined(MODULE)
702 /*
703 * If we are compiling sound.o (MODULAR version) we can not
704 * request any region because there is not a uninit routine that
705 * can allow me to release the requested region.
706 */
707 if (!(ae_init & INIT_MPU401))
708 request_region (hw_config->io_base, 0x0f, "aedsp16 (sbpro)");
709 #endif
710
711 ae_init |= INIT_SBPRO;
712 return 0;
713 }
714
715 #endif /* AEDSP16_SBPRO */
716
717 #if defined(AEDSP16_MSS)
718
719 int
720 InitAEDSP16_MSS (struct address_info *hw_config)
/* ![[previous]](../icons/left.png)
![[next]](../icons/right.png)
![[first]](../icons/first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
721 {
722 /*
723 * If the card is alredy init'ed SBPRO, we can not init it to MSS too
724 * because the board can not emulate simultaneously MSS and SBPRO.
725 */
726 if (ae_init & INIT_SBPRO)
727 return -1;
728 if (ae_init & INIT_MSS)
729 return 0;
730
731 /*
732 * For now we will leave this
733 * code included only when INCLUDE_AEDSP16 is configured in, but it should
734 * be better include it every time.
735 */
736 if (check_region (hw_config->io_base, 0x08))
737 {
738 printk ("MSS I/O port region is alredy in use.\n");
739 return -1;
740 }
741
742 /*
743 * We must allocate the AEDSP16 region too because these are the I/O ports
744 * to access card's control registers.
745 */
746 if (!(ae_init & INIT_MPU401))
747 {
748 if (check_region (AEDSP16_BASE, 0x0f))
749 {
750 printk ("AEDSP16 I/O port region is alredy in use.\n");
751 return -1;
752 }
753 }
754
755
756 /*
757 * If we are configuring the card for MSS, the portbase for card
758 * configuration is the default one (0x220 unless you have changed the
759 * factory default with board switches), so no need to modify the
760 * portbase variable.
761 * The default is AEDSP16_BASE, that is the right value.
762 */
763 irq = hw_config->irq;
764 dma = hw_config->dma;
765
766 if (InitAEDSP16 (INIT_MSS))
767 return -1;
768
769 #if !defined(MODULE)
770 /*
771 * If we are compiling sound.o (MODULAR version) we can not
772 * request any region because there is not a uninit routine that
773 * can allow me to release the requested region. So when unloading
774 * and then reloading it, we are going to have some nice Oops!
775 */
776 request_region (hw_config->io_base, 0x08, "aedsp16 (mss)");
777 #endif
778
779 if (!(ae_init & INIT_MPU401))
780 request_region (AEDSP16_BASE, 0x0f, "aedsp16 (sbpro)");
781
782 ae_init |= INIT_MSS;
783 return 0;
784 }
785
786 #endif /* AEDSP16_MSS */
787
788 #if defined(AEDSP16_MPU401)
789
790 int
791 InitAEDSP16_MPU401 (struct address_info *hw_config)
/* ![[previous]](../icons/left.png)
![[next]](../icons/right.png)
![[first]](../icons/first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
792 {
793 if (ae_init & INIT_MPU401)
794 return 0;
795
796 /*
797 * For now we will leave this
798 * code included only when INCLUDE_AEDSP16 is configured in, but it should
799 * be better include it every time.
800 */
801 if (check_region (hw_config->io_base, 0x02))
802 {
803 printk ("SB I/O port region is alredy in use.\n");
804 return -1;
805 }
806
807 /*
808 * We must allocate the AEDSP16 region too because these are the I/O ports
809 * to access card's control registers.
810 */
811 if (!(ae_init & (INIT_MSS | INIT_SBPRO)))
812 {
813 if (check_region (AEDSP16_BASE, 0x0f))
814 {
815 printk ("AEDSP16 I/O port region is alredy in use.\n");
816 return -1;
817 }
818 }
819
820 /*
821 * If mpu401, the irq and dma are not important, do not touch it
822 * because we may use the default if sbpro is not yet configured,
823 * we may use the sbpro ones if configured, and nothing wrong
824 * should happen.
825 *
826 * The mirq default is 0, but once set it to non-0 value, we should
827 * not touch it anymore (unless I write an ioctl to do it, of course).
828 */
829 mirq = hw_config->irq;
830 if (InitAEDSP16 (INIT_MPU401))
831 return -1;
832
833 #if !defined(MODULE)
834 /*
835 * If we are compiling sound.o (MODULAR version) we can not
836 * request any region because there is not a uninit routine that
837 * can allow me to release the requested region.
838 */
839 request_region (hw_config->io_base, 0x02, "aedsp16 (mpu401)");
840 #endif
841
842 if (!(ae_init & (INIT_MSS | INIT_SBPRO)))
843 request_region (AEDSP16_BASE, 0x0f, "aedsp16 (sbpro)");
844
845 ae_init |= INIT_MPU401;
846 return 0;
847 }
848
849 #endif /* AEDSP16_MPU401 */
850
851 #if 0 /* Leave it out for now. We are not using this portion of code. */
852
853 /*
854 * Entry point for a reset function.
855 * May be I will write the infamous ioctl :)
856 */
857 int
858 ResetAEDSP16 (void)
/* ![[previous]](../icons/left.png)
![[next]](../icons/n_right.png)
![[first]](../icons/first.png)
![[last]](../icons/n_last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
859 {
860 #if defined(AEDSP16_DEBUG)
861 printk ("[aedsp16] ResetAEDSP16 called.\n");
862 #endif
863 return InitAEDSP16 (RESET_DSP16);
864 }
865
866 #endif /* 0 */
867
868 #endif /* CONFIG_AEDSP16 */