Remove redundant panic.
[dragonfly.git] / sys / dev / sound / isa / i386 / uart / uart6850.c
1 /*
2  * sound/uart6850.c
3  * 
4  * Copyright by Hannu Savolainen 1993
5  * 
6  * Mon Nov 22 22:38:35 MET 1993 marco@driq.home.usn.nl: added 6850 support, used
7  * with COVOX SoundMaster II and custom cards.
8  * 
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions are
11  * met: 1. Redistributions of source code must retain the above copyright
12  * notice, this list of conditions and the following disclaimer. 2.
13  * Redistributions in binary form must reproduce the above copyright notice,
14  * this list of conditions and the following disclaimer in the documentation
15  * and/or other materials provided with the distribution.
16  * 
17  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY
18  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20  * DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
21  * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
23  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
24  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27  * SUCH DAMAGE.
28  *
29  * $DragonFly: src/sys/dev/sound/isa/i386/uart/Attic/uart6850.c,v 1.2 2004/09/19 16:51:03 joerg Exp $ 
30  */
31
32 #include <sys/types.h>
33 #include <sys/callout.h>
34 #include <dev/sound/isa/i386/sound_config.h>
35
36 #if     NSND > 0
37
38 #if 1
39 /* #if defined(CONFIG_UART6850) && defined(CONFIG_MIDI) */
40
41 #define DATAPORT   (uart6850_base)      /* * * Midi6850 Data I/O Port on IBM */
42 #define COMDPORT   (uart6850_base+1)    /* * * Midi6850 Command Port on IBM   */
43 #define STATPORT   (uart6850_base+1)    /* * * Midi6850 Status Port on IBM   */
44
45 #define uart6850_status()               inb( STATPORT)
46 #define input_avail()           (uart6850_status()&INPUT_AVAIL)
47 #define output_ready()          (uart6850_status()&OUTPUT_READY)
48 #define uart6850_cmd(cmd)       outb( COMDPORT,  cmd)
49 #define uart6850_read()         inb( DATAPORT)
50 #define uart6850_write(byte)    outb( DATAPORT,  byte)
51
52 #define OUTPUT_READY    0x02    /* * * Mask for Data Read Ready Bit   */
53 #define INPUT_AVAIL     0x01    /* * * Mask for Data Send Ready Bit   */
54
55 #define UART_RESET      0x95    /* * * 6850 Total Reset Command   */
56 #define UART_MODE_ON    0x03    /* * * 6850 Send/Receive UART Mode   */
57
58 static int      uart6850_opened = 0;
59 static int      uart6850_base = 0x330;
60 static int      uart6850_irq;
61 static int      uart6850_detected = 0;
62 static int      my_dev;
63
64 static int      reset_uart6850(void);
65 static void     (*midi_input_intr) (int dev, u_char data);
66 static void     poll_uart6850(void *dummy);
67
68 static sound_os_info *uart6850_osp;
69
70 static struct callout   uart6850_ch;
71 SYSINIT(uart6850, SI_SUB_DRIVERS, SI_ORDER_ANY, callout_init, &uart6850_ch);
72
73 static void
74 uart6850_input_loop(void)
75 {
76     int             count;
77
78     count = 10;
79
80     while (count)               /* Not timed out */
81         if (input_avail()) {
82             u_char   c = uart6850_read();
83
84             count = 100;
85
86             if (uart6850_opened & OPEN_READ)
87                 midi_input_intr(my_dev, c);
88             } else
89                 while (!input_avail() && count)
90                     count--;
91 }
92
93 void
94 m6850intr(int irq)
95 {
96     if (input_avail())
97         uart6850_input_loop();
98 }
99
100 /*
101  * It looks like there is no input interrupts in the UART mode. Let's try
102  * polling.
103  */
104
105 static void
106 poll_uart6850(void * dummy)
107 {
108     u_long   flags;
109
110     if (!(uart6850_opened & OPEN_READ))
111         return;         /* Device has been closed */
112
113     flags = splhigh();
114
115     if (input_avail())
116         uart6850_input_loop();
117
118     callout_reset(&uart6850_ch, 1, poll_uart6850, NULL); /* Come back later */
119
120     splx(flags);
121 }
122
123 static int
124 uart6850_open(int dev, int mode,
125               void (*input) (int dev, u_char data),
126               void (*output) (int dev)
127 )
128 {
129     if (uart6850_opened) {
130         printf("Midi6850: Midi busy\n");
131         return -(EBUSY);
132     }
133     uart6850_cmd(UART_RESET);
134
135     uart6850_input_loop();
136
137     midi_input_intr = input;
138     uart6850_opened = mode;
139     poll_uart6850(0);   /* Enable input polling */
140
141     return 0;
142 }
143
144 static void
145 uart6850_close(int dev)
146 {
147     uart6850_cmd(UART_MODE_ON);
148
149     uart6850_opened = 0;
150 }
151
152 static int
153 uart6850_out(int dev, u_char midi_byte)
154 {
155     int             timeout;
156     u_long   flags;
157
158     /*
159      * Test for input since pending input seems to block the output.
160      */
161
162     flags = splhigh();
163
164     if (input_avail())
165         uart6850_input_loop();
166
167     splx(flags);
168
169     /*
170      * Sometimes it takes about 13000 loops before the output becomes
171      * ready (After reset). Normally it takes just about 10 loops.
172      */
173
174     for (timeout = 30000; timeout > 0 && !output_ready(); timeout--);   /* Wait */
175
176     if (!output_ready()) {
177         printf("Midi6850: Timeout\n");
178         return 0;
179     }
180     uart6850_write(midi_byte);
181     return 1;
182 }
183
184 static int
185 uart6850_command(int dev, u_char *midi_byte)
186 {
187     return 1;
188 }
189
190 static int
191 uart6850_start_read(int dev)
192 {
193     return 0;
194 }
195
196 static int
197 uart6850_end_read(int dev)
198 {
199     return 0;
200 }
201
202 static int
203 uart6850_ioctl(int dev, u_int cmd, ioctl_arg arg)
204 {
205     return -(EINVAL);
206 }
207
208 static void
209 uart6850_kick(int dev)
210 {
211 }
212
213 static int
214 uart6850_buffer_status(int dev)
215 {
216     return 0;           /* No data in buffers */
217 }
218
219 #define MIDI_SYNTH_NAME "6850 UART Midi"
220 #define MIDI_SYNTH_CAPS SYNTH_CAP_INPUT
221 #include <i386/isa/sound/midi_synth.h>
222
223 static struct midi_operations uart6850_operations =
224 {
225         {"6850 UART", 0, 0, SNDCARD_UART6850},
226         &std_midi_synth,
227         {0},
228         uart6850_open,
229         uart6850_close,
230         uart6850_ioctl,
231         uart6850_out,
232         uart6850_start_read,
233         uart6850_end_read,
234         uart6850_kick,
235         uart6850_command,
236         uart6850_buffer_status
237 };
238
239
240 void
241 attach_uart6850(struct address_info * hw_config)
242 {
243     int             ok, timeout;
244     u_long   flags;
245
246     if (num_midis >= MAX_MIDI_DEV) {
247         printf("Sound: Too many midi devices detected\n");
248         return ;
249     }
250     uart6850_base = hw_config->io_base;
251     uart6850_osp = hw_config->osp;
252     uart6850_irq = hw_config->irq;
253
254     if (!uart6850_detected)
255         return ;
256
257     flags = splhigh();
258
259     for (timeout = 30000; timeout < 0 && !output_ready(); timeout--);   /* Wait */
260     uart6850_cmd(UART_MODE_ON);
261
262     ok = 1;
263
264     splx(flags);
265
266     conf_printf("6850 Midi Interface", hw_config);
267
268     std_midi_synth.midi_dev = my_dev = num_midis;
269     midi_devs[num_midis++] = &uart6850_operations;
270     return ;
271 }
272
273 static int
274 reset_uart6850(void)
275 {
276     uart6850_read();
277     return 1;           /* OK */
278 }
279
280
281 int
282 probe_uart6850(struct address_info * hw_config)
283 {
284     int             ok = 0;
285
286     uart6850_osp = hw_config->osp;
287     uart6850_base = hw_config->io_base;
288     uart6850_irq = hw_config->irq;
289
290     if (snd_set_irq_handler(uart6850_irq, m6850intr, uart6850_osp) < 0)
291         return 0;
292
293     ok = reset_uart6850();
294
295     uart6850_detected = ok;
296     return ok;
297 }
298
299 #endif
300 #endif