Initial import from FreeBSD RELENG_4:
[dragonfly.git] / sys / dev / sound / isa / i386 / gus / gus_card.c
1 /*
2  * sound/gus_card.c
3  * 
4  * Detection routine for the Gravis Ultrasound.
5  * 
6  * Copyright by Hannu Savolainen 1993
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 defined(CONFIG_GUS)
33
34 #include <i386/isa/sound/gus_hw.h>
35 #include <i386/isa/sound/iwdefs.h>
36
37 int             gus_base, gus_irq, gus_dma;
38 extern int      gus_wave_volume;
39 extern int      gus_pcm_volume;
40 extern int      have_gus_max;
41 extern int      gus_timer_enabled;
42
43 static sound_os_info *gus_osp;
44
45 #ifndef NOGUSPNP
46 int             IwaveOpen(char voices, char mode, struct address_info * hw);
47 #endif
48
49 void
50 attach_gus_card(struct address_info * hw_config)
51 {
52     int             io_addr;
53
54     gus_osp = hw_config->osp;
55
56     snd_set_irq_handler(hw_config->irq, gusintr, hw_config->osp);
57
58     if (gus_wave_detect(hw_config->io_base)) {
59         /* Try first the default */
60         gus_wave_init(hw_config);
61
62         /* 0x10c-> is MAX */
63
64         if (hw_config->dma2 != -1 && hw_config->dma2 != hw_config->dma)
65             if (0)
66                 printf("gus_card.c: Can't allocate DMA channel2\n");
67 #ifdef CONFIG_MIDI
68         gus_midi_init();
69 #endif
70         return ;
71     }
72 #ifndef EXCLUDE_GUS_IODETECT
73
74     /*
75      * Look at the possible base addresses (0x2X0, X=1, 2, 3, 4, 5, 6)
76      */
77
78     for (io_addr = 0x210; io_addr <= 0x260; io_addr += 0x10)
79         if (  (io_addr != hw_config->io_base)   /* Already tested */
80               &&  (gus_wave_detect(io_addr)) )  {
81             hw_config->io_base = io_addr;
82
83             printf(" WARNING! GUS found at %x, config was %x ",
84                         io_addr, hw_config->io_base);
85             gus_wave_init(hw_config);
86             /* 0x10c-> is MAX */
87             if (hw_config->dma2 != -1 && hw_config->dma2 != hw_config->dma)
88                 if (0)
89                     printf("gus_card.c: Can't allocate DMA channel2\n");
90 #ifdef CONFIG_MIDI
91             gus_midi_init();
92 #endif
93             return ;
94         }
95 #endif
96 }
97
98 int
99 probe_gus(struct address_info * hw_config)
100 {
101     int             io_addr;
102
103     gus_osp = hw_config->osp;
104 #ifndef NOGUSPNP
105     IwaveOpen((char) 32, (char) GUS_MODE, hw_config);
106 #endif
107     if (gus_wave_detect(hw_config->io_base))
108         return 1;
109     printf("oops I didnt find gus \n");
110 #undef EXCLUDE_GUS_IODETECT
111 #ifndef EXCLUDE_GUS_IODETECT
112
113     /*
114      * Look at the possible base addresses (0x2X0, X=1, 2, 3, 4, 5, 6)
115      */
116     for (io_addr = 0x210; io_addr <= 0x260; io_addr += 0x10)
117         if ( (io_addr != hw_config->io_base)    /* Already tested */
118              && (gus_wave_detect(io_addr)) ) {
119             hw_config->io_base = io_addr;
120             return 1;
121         }
122 #endif
123
124     return 0;
125 }
126
127 void
128 gusintr(int irq)
129 {
130     u_char   src;
131
132 #ifdef CONFIG_GUSMAX
133     if (have_gus_max)
134         ad1848_interrupt(irq);
135 #endif
136
137     for (;;) {
138         if (!(src = inb(u_IrqStatus)))
139             return;
140
141         if (src & DMA_TC_IRQ)
142             guswave_dma_irq();
143 #ifdef CONFIG_MIDI
144         if (src & (MIDI_TX_IRQ | MIDI_RX_IRQ))
145             gus_midi_interrupt(0);
146 #endif
147         if (src & (GF1_TIMER1_IRQ | GF1_TIMER2_IRQ)) {
148 #ifdef CONFIG_SEQUENCER
149             if (gus_timer_enabled)
150                 sound_timer_interrupt();
151             gus_write8(0x45, 0);        /* Ack IRQ */
152             gus_timer_command(4, 0x80); /* Reset IRQ flags */
153 #else
154             gus_write8(0x45, 0);        /* Stop timers */
155 #endif
156         }
157         if (src & (WAVETABLE_IRQ | ENVELOPE_IRQ))
158             gus_voice_irq();
159     }
160 }
161
162 #endif
163
164 /*
165  * Some extra code for the 16 bit sampling option
166  */
167 #if defined(CONFIG_GUS16)
168
169 int
170 probe_gus_db16(struct address_info * hw_config)
171 {
172     return ad1848_detect(hw_config->io_base, NULL, hw_config->osp);
173 }
174
175 void
176 attach_gus_db16(struct address_info * hw_config)
177 {
178     gus_pcm_volume = 100;
179     gus_wave_volume = 90;
180
181     ad1848_init("GUS 16 bit sampling", hw_config->io_base,
182                 hw_config->irq,
183                 hw_config->dma,
184                 hw_config->dma, 0,
185                 hw_config->osp);
186 }
187
188 #endif