]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/i386/isa/sound/sscape.c
This commit was generated by cvs2svn to compensate for changes in r52400,
[FreeBSD/FreeBSD.git] / sys / i386 / isa / sound / sscape.c
1 /*
2  * sound/sscape.c
3  * 
4  * Low level driver for Ensoniq Soundscape
5  * 
6  * Copyright by Hannu Savolainen 1994
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
30 #include <i386/isa/sound/sound_config.h>
31
32 #if NSSCAPE > 0
33
34 #include <i386/isa/sound/coproc.h>
35
36 #define EXCLUDE_NATIVE_PCM
37
38 /*
39  * I/O ports
40  */
41 #define MIDI_DATA        0
42 #define MIDI_CTRL        1
43 #define HOST_CTRL        2
44 #define TX_READY                0x02
45 #define RX_READY                0x01
46 #define HOST_DATA        3
47 #define ODIE_ADDR        4
48 #define ODIE_DATA        5
49
50 /*
51  * Indirect registers
52  */
53 #define GA_INTSTAT_REG   0
54 #define GA_INTENA_REG    1
55 #define GA_DMAA_REG      2
56 #define GA_DMAB_REG      3
57 #define GA_INTCFG_REG    4
58 #define GA_DMACFG_REG    5
59 #define GA_CDCFG_REG     6
60 #define GA_SMCFGA_REG    7
61 #define GA_SMCFGB_REG    8
62 #define GA_HMCTL_REG     9
63
64 /*
65  * DMA channel identifiers (A and B)
66  */
67 #define SSCAPE_DMA_A            0
68 #define SSCAPE_DMA_B            1
69
70 #define PORT(name)      (devc->base+name)
71
72 /*
73  * Host commands recognized by the OBP microcode
74  */
75 #define CMD_GEN_HOST_ACK        0x80
76 #define CMD_GEN_MPU_ACK         0x81
77 #define CMD_GET_BOARD_TYPE      0x82
78 #define CMD_SET_CONTROL         0x88
79 #define CMD_GET_CONTROL         0x89
80 #define         CTL_MASTER_VOL          0
81 #define         CTL_MIC_MODE            2
82 #define         CTL_SYNTH_VOL           4
83 #define         CTL_WAVE_VOL            7
84 #define CMD_SET_MT32            0x96
85 #define CMD_GET_MT32            0x97
86 #define CMD_SET_EXTMIDI         0x9b
87 #define CMD_GET_EXTMIDI         0x9c
88
89 #define CMD_ACK                 0x80
90
91 typedef struct sscape_info {
92         int             base, irq, dma;
93         int             ok;     /* Properly detected */
94         int             failed;
95         int             dma_allocated;
96         int             my_audiodev;
97         int             opened;
98         sound_os_info  *osp;
99 }
100
101                 sscape_info;
102 static struct sscape_info dev_info =
103 {0};
104 static struct sscape_info *devc = &dev_info;
105
106 static int     *sscape_sleeper = NULL;
107 static volatile struct snd_wait sscape_sleep_flag =
108 {0};
109
110 /* Some older cards have assigned interrupt bits differently than new ones */
111 static char     valid_interrupts_old[] =
112 {9, 7, 5, 15};
113
114 static char     valid_interrupts_new[] =
115 {9, 5, 7, 10};
116
117 static char    *valid_interrupts = valid_interrupts_new;
118
119 #ifdef REVEAL_SPEA
120 static char     old_hardware = 1;
121
122 #else
123 static char     old_hardware = 0;
124
125 #endif
126
127 static u_char
128 sscape_read(struct sscape_info * devc, int reg)
129 {
130         u_long   flags;
131         u_char   val;
132
133         flags = splhigh();
134         outb(PORT(ODIE_ADDR), reg);
135         val = inb(PORT(ODIE_DATA));
136         splx(flags);
137         return val;
138 }
139
140 static void
141 sscape_write(struct sscape_info * devc, int reg, int data)
142 {
143         u_long   flags;
144
145         flags = splhigh();
146         outb(PORT(ODIE_ADDR), reg);
147         outb(PORT(ODIE_DATA), data);
148         splx(flags);
149 }
150
151 static void
152 host_open(struct sscape_info * devc)
153 {
154         outb(PORT(HOST_CTRL), 0x00);    /* Put the board to the host mode */
155 }
156
157 static void
158 host_close(struct sscape_info * devc)
159 {
160         outb(PORT(HOST_CTRL), 0x03);    /* Put the board to the MIDI mode */
161 }
162
163 static int
164 host_write(struct sscape_info * devc, u_char *data, int count)
165 {
166         u_long   flags;
167         int             i, timeout_val;
168
169         flags = splhigh();
170
171         /*
172          * Send the command and data bytes
173          */
174
175         for (i = 0; i < count; i++) {
176                 for (timeout_val = 10000; timeout_val > 0; timeout_val--)
177                         if (inb(PORT(HOST_CTRL)) & TX_READY)
178                                 break;
179
180                 if (timeout_val <= 0) {
181                         splx(flags);
182                         return 0;
183                 }
184                 outb(PORT(HOST_DATA), data[i]);
185         }
186
187
188         splx(flags);
189
190         return 1;
191 }
192
193 static int
194 host_read(struct sscape_info * devc)
195 {
196         u_long   flags;
197         int             timeout_val;
198         u_char   data;
199
200         flags = splhigh();
201
202         /*
203          * Read a byte
204          */
205
206         for (timeout_val = 10000; timeout_val > 0; timeout_val--)
207                 if (inb(PORT(HOST_CTRL)) & RX_READY)
208                         break;
209
210         if (timeout_val <= 0) {
211                 splx(flags);
212                 return -1;
213         }
214         data = inb(PORT(HOST_DATA));
215
216         splx(flags);
217
218         return data;
219 }
220
221 static int
222 host_command1(struct sscape_info * devc, int cmd)
223 {
224         u_char   buf[10];
225
226         buf[0] = (u_char) (cmd & 0xff);
227
228         return host_write(devc, buf, 1);
229 }
230
231 static int
232 host_command2(struct sscape_info * devc, int cmd, int parm1)
233 {
234         u_char   buf[10];
235
236         buf[0] = (u_char) (cmd & 0xff);
237         buf[1] = (u_char) (parm1 & 0xff);
238
239         return host_write(devc, buf, 2);
240 }
241
242 static int
243 host_command3(struct sscape_info * devc, int cmd, int parm1, int parm2)
244 {
245         u_char   buf[10];
246
247         buf[0] = (u_char) (cmd & 0xff);
248         buf[1] = (u_char) (parm1 & 0xff);
249         buf[2] = (u_char) (parm2 & 0xff);
250
251         return host_write(devc, buf, 3);
252 }
253
254 static void
255 set_mt32(struct sscape_info * devc, int value)
256 {
257         host_open(devc);
258         host_command2(devc, CMD_SET_MT32,
259                       value ? 1 : 0);
260         if (host_read(devc) != CMD_ACK) {
261                 printf("SNDSCAPE: Setting MT32 mode failed\n");
262         }
263         host_close(devc);
264 }
265
266 static void
267 set_control(struct sscape_info * devc, int ctrl, int value)
268 {
269         host_open(devc);
270         host_command3(devc, CMD_SET_CONTROL, ctrl, value);
271         if (host_read(devc) != CMD_ACK) {
272                 printf("SNDSCAPE: Setting control (%d) failed\n", ctrl);
273         }
274         host_close(devc);
275 }
276
277 static int
278 get_board_type(struct sscape_info * devc)
279 {
280         int             tmp;
281
282         host_open(devc);
283         if (!host_command1(devc, CMD_GET_BOARD_TYPE))
284                 tmp = -1;
285         else
286                 tmp = host_read(devc);
287         host_close(devc);
288         return tmp;
289 }
290
291 void
292 sscapeintr(int irq)
293 {
294     u_char   bits, tmp;
295
296     bits = sscape_read(devc, GA_INTSTAT_REG);
297     DEB(printf("sscapeintr(0x%02x)\n", bits));
298     if ((sscape_sleep_flag.mode & WK_SLEEP)) {
299         sscape_sleep_flag.mode = WK_WAKEUP;
300         wakeup(sscape_sleeper);
301     }
302     if (bits & 0x02) {  /* Host interface interrupt */
303         printf("SSCAPE: Host interrupt, data=%02x\n", host_read(devc));
304     }
305 #if (defined(CONFIG_MPU401) || defined(CONFIG_MPU_EMU)) && defined(CONFIG_MIDI)
306     if (bits & 0x01) {
307         static int debug = 0;
308
309         mpuintr(irq);
310         if (debug++ > 10) {     /* Temporary debugging hack */
311             sscape_write(devc, GA_INTENA_REG, 0x00); /* Disable all interr. */
312         }
313     }
314 #endif
315
316     /*
317      * Acknowledge interrupts (toggle the interrupt bits)
318      */
319
320     tmp = sscape_read(devc, GA_INTENA_REG);
321     sscape_write(devc, GA_INTENA_REG, (~bits & 0x0e) | (tmp & 0xf1));
322 }
323
324
325 static void
326 do_dma(struct sscape_info * devc, int dma_chan, u_long buf, int blk_size, int mode)
327 {
328     u_char   temp;
329
330     if (dma_chan != SSCAPE_DMA_A) {
331         printf("SSCAPE: Tried to use DMA channel  != A. Why?\n");
332         return;
333     }
334     DMAbuf_start_dma(devc->my_audiodev, buf, blk_size, mode);
335
336     temp = devc->dma << 4;      /* Setup DMA channel select bits */
337     if (devc->dma <= 3)
338         temp |= 0x80;   /* 8 bit DMA channel */
339
340     temp |= 1;          /* Trigger DMA */
341     sscape_write(devc, GA_DMAA_REG, temp);
342     temp &= 0xfe;               /* Clear DMA trigger */
343     sscape_write(devc, GA_DMAA_REG, temp);
344 }
345
346 static int
347 verify_mpu(struct sscape_info * devc)
348 {
349     /*
350      * The SoundScape board could be in three modes (MPU, 8250 and host).
351      * If the card is not in the MPU mode, enabling the MPU driver will
352      * cause infinite loop (the driver believes that there is always some
353      * received data in the buffer.
354      * 
355      * Detect this by looking if there are more than 10 received MIDI bytes
356      * (0x00) in the buffer.
357      */
358
359     int             i;
360
361     for (i = 0; i < 10; i++) {
362         if (inb(devc->base + HOST_CTRL) & 0x80)
363             return 1;
364
365         if (inb(devc->base) != 0x00)
366             return 1;
367     }
368
369     printf("SoundScape: The device is not in the MPU-401 mode\n");
370     return 0;
371 }
372
373 static int
374 sscape_coproc_open(void *dev_info, int sub_device)
375 {
376     if (sub_device == COPR_MIDI) {
377         set_mt32(devc, 0);
378         if (!verify_mpu(devc))
379             return -(EIO);
380     }
381     sscape_sleep_flag.aborting = 0;
382     sscape_sleep_flag.mode = WK_NONE;
383     return 0;
384 }
385
386 static void
387 sscape_coproc_close(void *dev_info, int sub_device)
388 {
389     struct sscape_info *devc = dev_info;
390     u_long   flags;
391
392     flags = splhigh();
393     if (devc->dma_allocated) {
394         sscape_write(devc, GA_DMAA_REG, 0x20);  /* DMA channel disabled */
395 #ifdef CONFIG_NATIVE_PCM
396 #endif
397         devc->dma_allocated = 0;
398     }
399     sscape_sleep_flag.aborting = 0;
400     sscape_sleep_flag.mode = WK_NONE;
401     splx(flags);
402
403     return;
404 }
405
406 static void
407 sscape_coproc_reset(void *dev_info)
408 {
409 }
410
411 static int
412 sscape_download_boot(struct sscape_info * devc, u_char *block, int size, int flag)
413 {
414     u_long   flags;
415     u_char   temp;
416     int             done, timeout_val;
417
418     if (flag & CPF_FIRST) {
419         /*
420          * First block. Have to allocate DMA and to reset the board
421          * before continuing.
422          */
423
424         flags = splhigh();
425         if (devc->dma_allocated == 0) {
426             devc->dma_allocated = 1;
427         }
428         splx(flags);
429
430         sscape_write(devc, GA_HMCTL_REG,
431            (temp = sscape_read(devc, GA_HMCTL_REG)) & 0x3f);    /* Reset */
432
433         for (timeout_val = 10000; timeout_val > 0; timeout_val--)
434             sscape_read(devc, GA_HMCTL_REG);    /* Delay */
435
436         /* Take board out of reset */
437         sscape_write(devc, GA_HMCTL_REG,
438                    (temp = sscape_read(devc, GA_HMCTL_REG)) | 0x80);
439     }
440     /*
441      * Transfer one code block using DMA
442      */
443     bcopy(block, audio_devs[devc->my_audiodev]->dmap_out->raw_buf, size);
444
445     flags = splhigh();
446     /******** INTERRUPTS DISABLED NOW ********/
447     do_dma(devc, SSCAPE_DMA_A,
448                audio_devs[devc->my_audiodev]->dmap_out->raw_buf_phys,
449                size, 1);
450
451     /*
452      * Wait until transfer completes.
453      */
454     sscape_sleep_flag.aborting = 0;
455     sscape_sleep_flag.mode = WK_NONE;
456     done = 0;
457     timeout_val = 100;
458     while (!done && timeout_val-- > 0) {
459         int   chn;
460         sscape_sleeper = &chn;
461         DO_SLEEP(chn, sscape_sleep_flag, 1);
462
463         done = 1;
464     }
465
466     splx(flags);
467     if (!done)
468         return 0;
469
470     if (flag & CPF_LAST) {
471         /*
472          * Take the board out of reset
473          */
474         outb(PORT(HOST_CTRL), 0x00);
475         outb(PORT(MIDI_CTRL), 0x00);
476
477         temp = sscape_read(devc, GA_HMCTL_REG);
478         temp |= 0x40;
479         sscape_write(devc, GA_HMCTL_REG, temp); /* Kickstart the board */
480
481         /*
482          * Wait until the ODB wakes up
483          */
484
485         flags = splhigh();
486         done = 0;
487         timeout_val = 5 * hz;
488         while (!done && timeout_val-- > 0) {
489           int   chn;
490
491           sscape_sleeper = &chn;
492           DO_SLEEP(chn, sscape_sleep_flag, 1);
493
494           if (inb(PORT(HOST_DATA)) == 0xff)     /* OBP startup acknowledge */
495             done = 1;
496         }
497         splx(flags);
498         if (!done) {
499             printf("SoundScape: The OBP didn't respond after code download\n");
500             return 0;
501         }
502         flags = splhigh();
503         done = 0;
504         timeout_val = 5 * hz;
505         while (!done && timeout_val-- > 0) {
506           int   chn;
507
508           sscape_sleeper = &chn;
509           DO_SLEEP(chn, sscape_sleep_flag, 1);
510
511           if (inb(PORT(HOST_DATA)) == 0xfe)     /* Host startup acknowledge */
512             done = 1;
513         }
514         splx(flags);
515         if (!done) {
516             printf("SoundScape: OBP Initialization failed.\n");
517             return 0;
518         }
519         printf("SoundScape board of type %d initialized OK\n",
520                get_board_type(devc));
521
522         set_control(devc, CTL_MASTER_VOL, 100);
523         set_control(devc, CTL_SYNTH_VOL, 100);
524
525 #ifdef SSCAPE_DEBUG3
526         /*
527          * Temporary debugging aid. Print contents of the registers
528          * after downloading the code.
529          */
530         {
531             int             i;
532
533             for (i = 0; i < 13; i++)
534                 printf("I%d = %02x (new value)\n", i, sscape_read(devc, i));
535         }
536 #endif
537
538     }
539     return 1;
540 }
541
542 static int
543 download_boot_block(void *dev_info, copr_buffer * buf)
544 {
545     if (buf->len <= 0 || buf->len > sizeof(buf->data))
546         return -(EINVAL);
547
548     if (!sscape_download_boot(devc, buf->data, buf->len, buf->flags)) {
549         printf("SSCAPE: Unable to load microcode block to the OBP.\n");
550         return -(EIO);
551     }
552     return 0;
553 }
554
555 static int
556 sscape_coproc_ioctl(void *dev_info, u_int cmd, ioctl_arg arg, int local)
557 {
558
559     switch (cmd) {
560     case SNDCTL_COPR_RESET:
561         sscape_coproc_reset(dev_info);
562         return 0;
563         break;
564
565     case SNDCTL_COPR_LOAD:
566         {
567             copr_buffer    *buf;
568             int             err;
569
570             buf = (copr_buffer *) malloc(sizeof(copr_buffer), M_TEMP, M_WAITOK);
571             if (buf == NULL)
572                 return -(ENOSPC);
573             bcopy(&(((char *) arg)[0]), (char *) buf, sizeof(*buf));
574             err = download_boot_block(dev_info, buf);
575             free(buf, M_TEMP);
576             return err;
577         }
578         break;
579
580     default:
581         return -(EINVAL);
582     }
583
584 }
585
586 static coproc_operations sscape_coproc_operations =
587 {
588         "SoundScape M68K",
589         sscape_coproc_open,
590         sscape_coproc_close,
591         sscape_coproc_ioctl,
592         sscape_coproc_reset,
593         &dev_info
594 };
595
596 static int
597 sscape_audio_open(int dev, int mode)
598 {
599     u_long   flags;
600     sscape_info    *devc = (sscape_info *) audio_devs[dev]->devc;
601
602     flags = splhigh();
603     if (devc->opened) {
604         splx(flags);
605         return -(EBUSY);
606     }
607     devc->opened = 1;
608     splx(flags);
609 #ifdef SSCAPE_DEBUG4
610     /*
611      * Temporary debugging aid. Print contents of the registers when the
612      * device is opened.
613      */
614     {
615         int             i;
616
617         for (i = 0; i < 13; i++)
618             printf("I%d = %02x\n", i, sscape_read(devc, i));
619     }
620 #endif
621
622     return 0;
623 }
624
625 static void
626 sscape_audio_close(int dev)
627 {
628     u_long   flags;
629     sscape_info    *devc = (sscape_info *) audio_devs[dev]->devc;
630
631     DEB(printf("sscape_audio_close(void)\n"));
632
633     flags = splhigh();
634
635     devc->opened = 0;
636
637     splx(flags);
638 }
639
640 static int
641 set_speed(sscape_info * devc, int arg)
642 {
643     return 8000;
644 }
645
646 static int
647 set_channels(sscape_info * devc, int arg)
648 {
649     return 1;
650 }
651
652 static int
653 set_format(sscape_info * devc, int arg)
654 {
655     return AFMT_U8;
656 }
657
658 static int
659 sscape_audio_ioctl(int dev, u_int cmd, ioctl_arg arg, int local)
660 {
661     sscape_info    *devc = (sscape_info *) audio_devs[dev]->devc;
662
663     switch (cmd) {
664     case SOUND_PCM_WRITE_RATE:
665         if (local)
666             return set_speed(devc, (int) arg);
667         return *(int *) arg = set_speed(devc, (*(int *) arg));
668
669     case SOUND_PCM_READ_RATE:
670         if (local)
671             return 8000;
672         return *(int *) arg = 8000;
673
674     case SNDCTL_DSP_STEREO:
675         if (local)
676             return set_channels(devc, (int) arg + 1) - 1;
677         return *(int *) arg = set_channels(devc, (*(int *) arg) + 1) - 1;
678
679     case SOUND_PCM_WRITE_CHANNELS:
680         if (local)
681             return set_channels(devc, (int) arg);
682         return *(int *) arg = set_channels(devc, (*(int *) arg));
683
684     case SOUND_PCM_READ_CHANNELS:
685         if (local)
686             return 1;
687         return *(int *) arg = 1;
688
689     case SNDCTL_DSP_SAMPLESIZE:
690         if (local)
691             return set_format(devc, (int) arg);
692         return *(int *) arg = set_format(devc, (*(int *) arg));
693
694     case SOUND_PCM_READ_BITS:
695         if (local)
696             return 8;
697         return *(int *) arg = 8;
698
699     default:;
700     }
701     return -(EINVAL);
702 }
703
704 static void
705 sscape_audio_output_block(int dev, u_long buf, int count, int intrflag, int dma_restart)
706 {
707 }
708
709 static void
710 sscape_audio_start_input(int dev, u_long buf, int count, int intrflag, int dma_restart)
711 {
712 }
713
714 static int
715 sscape_audio_prepare_for_input(int dev, int bsize, int bcount)
716 {
717     return 0;
718 }
719
720 static int
721 sscape_audio_prepare_for_output(int dev, int bsize, int bcount)
722 {
723     return 0;
724 }
725
726 static void
727 sscape_audio_halt(int dev)
728 {
729 }
730
731 static void
732 sscape_audio_reset(int dev)
733 {
734     sscape_audio_halt(dev);
735 }
736
737
738 #if !defined(EXCLUDE_NATIVE_PCM) && defined(CONFIG_AUDIO)
739 static struct audio_operations sscape_audio_operations =
740 {
741         "Not functional",
742         0,
743         AFMT_U8 | AFMT_S16_LE,
744         NULL,
745         sscape_audio_open,
746         sscape_audio_close,
747         sscape_audio_output_block,
748         sscape_audio_start_input,
749         sscape_audio_ioctl,
750         sscape_audio_prepare_for_input,
751         sscape_audio_prepare_for_output,
752         sscape_audio_reset,
753         sscape_audio_halt,
754         NULL,
755         NULL
756 };
757 #endif /* !defined(EXCLUDE_NATIVE_PCM) && defined(CONFIG_AUDIO) */
758
759 static int      sscape_detected = 0;
760
761 void
762 attach_sscape(struct address_info * hw_config)
763 {
764 #ifndef SSCAPE_REGS
765     /*
766      * Config register values for Spea/V7 Media FX and Ensoniq S-2000.
767      * These values are card dependent. If you have another SoundScape
768      * based card, you have to find the correct values. Do the following:
769      * - Compile this driver with SSCAPE_DEBUG1 defined. - Shut down and
770      * power off your machine. - Boot with DOS so that the SSINIT.EXE
771      * program is run. - Warm boot to {Linux|SYSV|BSD} and write down the
772      * lines displayed when detecting the SoundScape. - Modify the
773      * following list to use the values printed during boot. Undefine the
774      * SSCAPE_DEBUG1
775      */
776 #define SSCAPE_REGS { \
777 /* I0 */        0x00, \
778                 0xf0, /* Note! Ignored. Set always to 0xf0 */ \
779                 0x20, /* Note! Ignored. Set always to 0x20 */ \
780                 0x20, /* Note! Ignored. Set always to 0x20 */ \
781                 0xf5, /* Ignored */ \
782                 0x10, \
783                 0x00, \
784                 0x2e, /* I7 MEM config A. Likely to vary between models */ \
785                 0x00, /* I8 MEM config B. Likely to vary between models */ \
786 /* I9 */        0x40 /* Ignored */ \
787         }
788 #endif
789
790     u_long   flags;
791     static u_char regs[10] = SSCAPE_REGS;
792
793     int             i, irq_bits = 0xff;
794
795     if (sscape_detected != hw_config->io_base)
796         return;
797
798     if (old_hardware) {
799         valid_interrupts = valid_interrupts_old;
800         conf_printf("Ensoniq Soundscape (old)", hw_config);
801     } else
802         conf_printf("Ensoniq Soundscape", hw_config);
803
804     for (i = 0; i < sizeof(valid_interrupts); i++)
805         if (hw_config->irq == valid_interrupts[i]) {
806             irq_bits = i;
807             break;
808         }
809     if (hw_config->irq > 15 || (regs[4] = irq_bits == 0xff)) {
810         printf("Invalid IRQ%d\n", hw_config->irq);
811         return;
812     }
813     flags = splhigh();
814
815     for (i = 1; i < 10; i++)
816         switch (i) {
817         case 1: /* Host interrupt enable */
818             sscape_write(devc, i, 0xf0);        /* All interrupts enabled */
819             break;
820
821         case 2: /* DMA A status/trigger register */
822         case 3: /* DMA B status/trigger register */
823             sscape_write(devc, i, 0x20);        /* DMA channel disabled */
824             break;
825
826         case 4: /* Host interrupt config reg */
827             sscape_write(devc, i, 0xf0 | (irq_bits << 2) | irq_bits);
828             break;
829
830         case 5: /* Don't destroy CD-ROM DMA config bits (0xc0) */
831             sscape_write(devc, i, (regs[i] & 0x3f) |
832                          (sscape_read(devc, i) & 0xc0));
833             break;
834
835         case 6: /* CD-ROM config. Don't touch. */
836             break;
837
838         case 9: /* Master control reg. Don't modify CR-ROM
839                  * bits. Disable SB emul */
840             sscape_write(devc, i, (sscape_read(devc, i) & 0xf0) | 0x00);
841             break;
842
843         default:
844             sscape_write(devc, i, regs[i]);
845         }
846
847     splx(flags);
848
849 #ifdef SSCAPE_DEBUG2
850     /*
851      * Temporary debugging aid. Print contents of the registers after
852      * changing them.
853      */
854     {
855         int             i;
856
857         for (i = 0; i < 13; i++)
858             printf("I%d = %02x (new value)\n", i, sscape_read(devc, i));
859     }
860 #endif
861
862 #if defined(CONFIG_MIDI) && defined(CONFIG_MPU_EMU)
863     if (probe_mpu401(hw_config))
864         hw_config->always_detect = 1;
865     {
866         int             prev_devs;
867
868         prev_devs = num_midis;
869         attach_mpu401(hw_config);
870
871         if (num_midis == (prev_devs + 1))       /* The MPU driver
872                                                  * installed itself */
873             midi_devs[prev_devs]->coproc = &sscape_coproc_operations;
874     }
875 #endif
876
877 #ifndef EXCLUDE_NATIVE_PCM
878     /* Not supported yet */
879
880 #ifdef CONFIG_AUDIO
881     if (num_audiodevs < MAX_AUDIO_DEV) {
882         int my_dev;
883
884         audio_devs[my_dev = num_audiodevs++] = &sscape_audio_operations;
885         audio_devs[my_dev]->dmachan1 = hw_config->dma;
886         audio_devs[my_dev]->buffsize = DSP_BUFFSIZE;
887         audio_devs[my_dev]->devc = devc;
888         devc->my_audiodev = my_dev;
889         devc->opened = 0;
890         audio_devs[my_dev]->coproc = &sscape_coproc_operations;
891         if (snd_set_irq_handler(hw_config->irq, sscapeintr, devc->osp) < 0)
892             printf("Error: Can't allocate IRQ for SoundScape\n");
893         sscape_write(devc, GA_INTENA_REG, 0x80);        /* Master IRQ enable */
894     } else
895         printf("SoundScape: More than enough audio devices detected\n");
896 #endif
897 #endif
898     devc->ok = 1;
899     devc->failed = 0;
900     return;
901 }
902
903 int
904 probe_sscape(struct address_info * hw_config)
905 {
906     u_char   save;
907
908     devc->failed = 1;
909     devc->base = hw_config->io_base;
910     devc->irq = hw_config->irq;
911     devc->dma = hw_config->dma;
912     devc->osp = hw_config->osp;
913
914     if (sscape_detected != 0 && sscape_detected != hw_config->io_base)
915         return 0;
916
917     /*
918      * First check that the address register of "ODIE" is there and that
919      * it has exactly 4 writeable bits. First 4 bits
920      */
921     if ((save = inb(PORT(ODIE_ADDR))) & 0xf0)
922         return 0;
923
924     outb(PORT(ODIE_ADDR), 0x00);
925     if (inb(PORT(ODIE_ADDR)) != 0x00)
926         return 0;
927
928     outb(PORT(ODIE_ADDR), 0xff);
929     if (inb(PORT(ODIE_ADDR)) != 0x0f)
930         return 0;
931
932     outb(PORT(ODIE_ADDR), save);
933
934     /*
935      * Now verify that some indirect registers return zero on some bits.
936      * This may break the driver with some future revisions of "ODIE"
937      * but...
938      */
939
940     if (sscape_read(devc, 0) & 0x0c)
941         return 0;
942
943     if (sscape_read(devc, 1) & 0x0f)
944         return 0;
945
946     if (sscape_read(devc, 5) & 0x0f)
947         return 0;
948
949 #ifdef SSCAPE_DEBUG1
950     /*
951      * Temporary debugging aid. Print contents of the registers before
952      * changing them.
953      */
954     {
955         int             i;
956
957         for (i = 0; i < 13; i++)
958             printf("I%d = %02x (old value)\n", i, sscape_read(devc, i));
959     }
960 #endif
961
962     if (old_hardware) { /* Check that it's really an old Spea/Reveal card. */
963         u_char   tmp;
964         int             cc;
965
966         if (!((tmp = sscape_read(devc, GA_HMCTL_REG)) & 0xc0)) {
967             sscape_write(devc, GA_HMCTL_REG, tmp | 0x80);
968             for (cc = 0; cc < 200000; ++cc)
969                 inb(devc->base + ODIE_ADDR);
970         } else
971             old_hardware = 0;
972     }
973     if (0) {
974         printf("sscape.c: Can't allocate DMA channel\n");
975         return 0;
976     }
977     sscape_detected = hw_config->io_base;
978
979     return 1;
980 }
981
982 int
983 probe_ss_mss(struct address_info * hw_config)
984 {
985     int             i, irq_bits = 0xff;
986
987     if (devc->failed)
988         return 0;
989
990     if (devc->ok == 0) {
991         printf("SoundScape: Invalid initialization order.\n");
992         return 0;
993     }
994     for (i = 0; i < sizeof(valid_interrupts); i++)
995         if (hw_config->irq == valid_interrupts[i]) {
996             irq_bits = i;
997             break;
998         }
999     if (hw_config->irq > 15 || irq_bits == 0xff) {
1000         printf("SoundScape: Invalid MSS IRQ%d\n", hw_config->irq);
1001         return 0;
1002     }
1003     return ad1848_detect(hw_config->io_base, NULL, hw_config->osp);
1004 }
1005
1006 void
1007 attach_ss_mss(struct address_info * hw_config)
1008 {
1009     /*
1010      * This routine configures the SoundScape card for use with the Win
1011      * Sound System driver. The AD1848 codec interface uses the CD-ROM
1012      * config registers of the "ODIE".
1013      */
1014
1015     int             i, irq_bits = 0xff;
1016
1017 #ifndef CONFIG_NATIVE_PCM
1018     int             prev_devs = num_audiodevs;
1019 #endif
1020
1021     /*
1022      * Setup the DMA polarity.
1023      */
1024     sscape_write(devc, GA_DMACFG_REG, 0x50);
1025
1026     /*
1027      * Take the gate-arry off of the DMA channel.
1028      */
1029     sscape_write(devc, GA_DMAB_REG, 0x20);
1030
1031     /*
1032      * Init the AD1848 (CD-ROM) config reg.
1033      */
1034
1035     for (i = 0; i < sizeof(valid_interrupts); i++)
1036         if (hw_config->irq == valid_interrupts[i]) {
1037             irq_bits = i;
1038             break;
1039         }
1040     sscape_write(devc, GA_CDCFG_REG, 0x89 | (hw_config->dma << 4) |
1041              (irq_bits << 1));
1042
1043     if (hw_config->irq == devc->irq)
1044         printf("SoundScape: Warning! WSS mode can't share IRQ with MIDI\n");
1045
1046     ad1848_init("SoundScape", hw_config->io_base,
1047                     hw_config->irq,
1048                     hw_config->dma,
1049                     hw_config->dma,
1050                     0,
1051                     devc->osp);
1052
1053 #ifndef CONFIG_NATIVE_PCM
1054     /* Check if the AD1848 driver installed itself */
1055     if (num_audiodevs == (prev_devs + 1))
1056         audio_devs[prev_devs]->coproc = &sscape_coproc_operations;
1057 #endif
1058
1059     return;
1060 }
1061
1062 #endif