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