timeout/untimeout ==> callout_*
[dragonfly.git] / sys / dev / sound / isa / i386 / uart / uart6850.c
CommitLineData
984263bc
MD
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.
6351dbd9
JS
28 *
29 * $DragonFly: src/sys/dev/sound/isa/i386/uart/Attic/uart6850.c,v 1.2 2004/09/19 16:51:03 joerg Exp $
984263bc
MD
30 */
31
6351dbd9
JS
32#include <sys/types.h>
33#include <sys/callout.h>
34#include <dev/sound/isa/i386/sound_config.h>
984263bc
MD
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
58static int uart6850_opened = 0;
59static int uart6850_base = 0x330;
60static int uart6850_irq;
61static int uart6850_detected = 0;
62static int my_dev;
63
64static int reset_uart6850(void);
65static void (*midi_input_intr) (int dev, u_char data);
66static void poll_uart6850(void *dummy);
67
984263bc
MD
68static sound_os_info *uart6850_osp;
69
6351dbd9
JS
70static struct callout uart6850_ch;
71SYSINIT(uart6850, SI_SUB_DRIVERS, SI_ORDER_ANY, callout_init, &uart6850_ch);
72
984263bc
MD
73static void
74uart6850_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
93void
94m6850intr(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
105static void
106poll_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
6351dbd9 118 callout_reset(&uart6850_ch, 1, poll_uart6850, NULL); /* Come back later */
984263bc
MD
119
120 splx(flags);
121}
122
123static int
124uart6850_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
144static void
145uart6850_close(int dev)
146{
147 uart6850_cmd(UART_MODE_ON);
148
149 uart6850_opened = 0;
150}
151
152static int
153uart6850_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
184static int
185uart6850_command(int dev, u_char *midi_byte)
186{
187 return 1;
188}
189
190static int
191uart6850_start_read(int dev)
192{
193 return 0;
194}
195
196static int
197uart6850_end_read(int dev)
198{
199 return 0;
200}
201
202static int
203uart6850_ioctl(int dev, u_int cmd, ioctl_arg arg)
204{
205 return -(EINVAL);
206}
207
208static void
209uart6850_kick(int dev)
210{
211}
212
213static int
214uart6850_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
223static 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
240void
241attach_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
273static int
274reset_uart6850(void)
275{
276 uart6850_read();
277 return 1; /* OK */
278}
279
280
281int
282probe_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