1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47#include <linux/io.h>
48#include <linux/init.h>
49#include <linux/time.h>
50#include <linux/wait.h>
51#include <sound/core.h>
52#include <sound/snd_wavefront.h>
53
54static inline int
55wf_mpu_status (snd_wavefront_midi_t *midi)
56
57{
58 return inb (midi->mpu_status_port);
59}
60
61static inline int
62input_avail (snd_wavefront_midi_t *midi)
63
64{
65 return !(wf_mpu_status(midi) & INPUT_AVAIL);
66}
67
68static inline int
69output_ready (snd_wavefront_midi_t *midi)
70
71{
72 return !(wf_mpu_status(midi) & OUTPUT_READY);
73}
74
75static inline int
76read_data (snd_wavefront_midi_t *midi)
77
78{
79 return inb (midi->mpu_data_port);
80}
81
82static inline void
83write_data (snd_wavefront_midi_t *midi, unsigned char byte)
84
85{
86 outb (byte, midi->mpu_data_port);
87}
88
89static snd_wavefront_midi_t *
90get_wavefront_midi (struct snd_rawmidi_substream *substream)
91
92{
93 struct snd_card *card;
94 snd_wavefront_card_t *acard;
95
96 if (substream == NULL || substream->rmidi == NULL)
97 return NULL;
98
99 card = substream->rmidi->card;
100
101 if (card == NULL)
102 return NULL;
103
104 if (card->private_data == NULL)
105 return NULL;
106
107 acard = card->private_data;
108
109 return &acard->wavefront.midi;
110}
111
112static void snd_wavefront_midi_output_write(snd_wavefront_card_t *card)
113{
114 snd_wavefront_midi_t *midi = &card->wavefront.midi;
115 snd_wavefront_mpu_id mpu;
116 unsigned long flags;
117 unsigned char midi_byte;
118 int max = 256, mask = 1;
119 int timeout;
120
121
122
123
124
125
126
127
128
129
130
131
132 if (midi->substream_output[midi->output_mpu] == NULL) {
133 goto __second;
134 }
135
136 while (max > 0) {
137
138
139
140 for (timeout = 30000; timeout > 0; timeout--) {
141 if (output_ready (midi))
142 break;
143 }
144
145 spin_lock_irqsave (&midi->virtual, flags);
146 if ((midi->mode[midi->output_mpu] & MPU401_MODE_OUTPUT) == 0) {
147 spin_unlock_irqrestore (&midi->virtual, flags);
148 goto __second;
149 }
150 if (output_ready (midi)) {
151 if (snd_rawmidi_transmit(midi->substream_output[midi->output_mpu], &midi_byte, 1) == 1) {
152 if (!midi->isvirtual ||
153 (midi_byte != WF_INTERNAL_SWITCH &&
154 midi_byte != WF_EXTERNAL_SWITCH))
155 write_data(midi, midi_byte);
156 max--;
157 } else {
158 if (midi->istimer) {
159 if (--midi->istimer <= 0)
160 del_timer(&midi->timer);
161 }
162 midi->mode[midi->output_mpu] &= ~MPU401_MODE_OUTPUT_TRIGGER;
163 spin_unlock_irqrestore (&midi->virtual, flags);
164 goto __second;
165 }
166 } else {
167 spin_unlock_irqrestore (&midi->virtual, flags);
168 return;
169 }
170 spin_unlock_irqrestore (&midi->virtual, flags);
171 }
172
173 __second:
174
175 if (midi->substream_output[!midi->output_mpu] == NULL) {
176 return;
177 }
178
179 while (max > 0) {
180
181
182
183 for (timeout = 30000; timeout > 0; timeout--) {
184 if (output_ready (midi))
185 break;
186 }
187
188 spin_lock_irqsave (&midi->virtual, flags);
189 if (!midi->isvirtual)
190 mask = 0;
191 mpu = midi->output_mpu ^ mask;
192 mask = 0;
193 if ((midi->mode[mpu] & MPU401_MODE_OUTPUT) == 0) {
194 spin_unlock_irqrestore (&midi->virtual, flags);
195 return;
196 }
197 if (snd_rawmidi_transmit_empty(midi->substream_output[mpu]))
198 goto __timer;
199 if (output_ready (midi)) {
200 if (mpu != midi->output_mpu) {
201 write_data(midi, mpu == internal_mpu ?
202 WF_INTERNAL_SWITCH :
203 WF_EXTERNAL_SWITCH);
204 midi->output_mpu = mpu;
205 } else if (snd_rawmidi_transmit(midi->substream_output[mpu], &midi_byte, 1) == 1) {
206 if (!midi->isvirtual ||
207 (midi_byte != WF_INTERNAL_SWITCH &&
208 midi_byte != WF_EXTERNAL_SWITCH))
209 write_data(midi, midi_byte);
210 max--;
211 } else {
212 __timer:
213 if (midi->istimer) {
214 if (--midi->istimer <= 0)
215 del_timer(&midi->timer);
216 }
217 midi->mode[mpu] &= ~MPU401_MODE_OUTPUT_TRIGGER;
218 spin_unlock_irqrestore (&midi->virtual, flags);
219 return;
220 }
221 } else {
222 spin_unlock_irqrestore (&midi->virtual, flags);
223 return;
224 }
225 spin_unlock_irqrestore (&midi->virtual, flags);
226 }
227}
228
229static int snd_wavefront_midi_input_open(struct snd_rawmidi_substream *substream)
230{
231 unsigned long flags;
232 snd_wavefront_midi_t *midi;
233 snd_wavefront_mpu_id mpu;
234
235 if (snd_BUG_ON(!substream || !substream->rmidi))
236 return -ENXIO;
237 if (snd_BUG_ON(!substream->rmidi->private_data))
238 return -ENXIO;
239
240 mpu = *((snd_wavefront_mpu_id *) substream->rmidi->private_data);
241
242 midi = get_wavefront_midi(substream);
243 if (!midi)
244 return -EIO;
245
246 spin_lock_irqsave (&midi->open, flags);
247 midi->mode[mpu] |= MPU401_MODE_INPUT;
248 midi->substream_input[mpu] = substream;
249 spin_unlock_irqrestore (&midi->open, flags);
250
251 return 0;
252}
253
254static int snd_wavefront_midi_output_open(struct snd_rawmidi_substream *substream)
255{
256 unsigned long flags;
257 snd_wavefront_midi_t *midi;
258 snd_wavefront_mpu_id mpu;
259
260 if (snd_BUG_ON(!substream || !substream->rmidi))
261 return -ENXIO;
262 if (snd_BUG_ON(!substream->rmidi->private_data))
263 return -ENXIO;
264
265 mpu = *((snd_wavefront_mpu_id *) substream->rmidi->private_data);
266
267 midi = get_wavefront_midi(substream);
268 if (!midi)
269 return -EIO;
270
271 spin_lock_irqsave (&midi->open, flags);
272 midi->mode[mpu] |= MPU401_MODE_OUTPUT;
273 midi->substream_output[mpu] = substream;
274 spin_unlock_irqrestore (&midi->open, flags);
275
276 return 0;
277}
278
279static int snd_wavefront_midi_input_close(struct snd_rawmidi_substream *substream)
280{
281 unsigned long flags;
282 snd_wavefront_midi_t *midi;
283 snd_wavefront_mpu_id mpu;
284
285 if (snd_BUG_ON(!substream || !substream->rmidi))
286 return -ENXIO;
287 if (snd_BUG_ON(!substream->rmidi->private_data))
288 return -ENXIO;
289
290 mpu = *((snd_wavefront_mpu_id *) substream->rmidi->private_data);
291
292 midi = get_wavefront_midi(substream);
293 if (!midi)
294 return -EIO;
295
296 spin_lock_irqsave (&midi->open, flags);
297 midi->mode[mpu] &= ~MPU401_MODE_INPUT;
298 spin_unlock_irqrestore (&midi->open, flags);
299
300 return 0;
301}
302
303static int snd_wavefront_midi_output_close(struct snd_rawmidi_substream *substream)
304{
305 unsigned long flags;
306 snd_wavefront_midi_t *midi;
307 snd_wavefront_mpu_id mpu;
308
309 if (snd_BUG_ON(!substream || !substream->rmidi))
310 return -ENXIO;
311 if (snd_BUG_ON(!substream->rmidi->private_data))
312 return -ENXIO;
313
314 mpu = *((snd_wavefront_mpu_id *) substream->rmidi->private_data);
315
316 midi = get_wavefront_midi(substream);
317 if (!midi)
318 return -EIO;
319
320 spin_lock_irqsave (&midi->open, flags);
321 midi->mode[mpu] &= ~MPU401_MODE_OUTPUT;
322 spin_unlock_irqrestore (&midi->open, flags);
323 return 0;
324}
325
326static void snd_wavefront_midi_input_trigger(struct snd_rawmidi_substream *substream, int up)
327{
328 unsigned long flags;
329 snd_wavefront_midi_t *midi;
330 snd_wavefront_mpu_id mpu;
331
332 if (substream == NULL || substream->rmidi == NULL)
333 return;
334
335 if (substream->rmidi->private_data == NULL)
336 return;
337
338 mpu = *((snd_wavefront_mpu_id *) substream->rmidi->private_data);
339
340 midi = get_wavefront_midi(substream);
341 if (!midi)
342 return;
343
344 spin_lock_irqsave (&midi->virtual, flags);
345 if (up) {
346 midi->mode[mpu] |= MPU401_MODE_INPUT_TRIGGER;
347 } else {
348 midi->mode[mpu] &= ~MPU401_MODE_INPUT_TRIGGER;
349 }
350 spin_unlock_irqrestore (&midi->virtual, flags);
351}
352
353static void snd_wavefront_midi_output_timer(struct timer_list *t)
354{
355 snd_wavefront_midi_t *midi = from_timer(midi, t, timer);
356 snd_wavefront_card_t *card = midi->timer_card;
357 unsigned long flags;
358
359 spin_lock_irqsave (&midi->virtual, flags);
360 mod_timer(&midi->timer, 1 + jiffies);
361 spin_unlock_irqrestore (&midi->virtual, flags);
362 snd_wavefront_midi_output_write(card);
363}
364
365static void snd_wavefront_midi_output_trigger(struct snd_rawmidi_substream *substream, int up)
366{
367 unsigned long flags;
368 snd_wavefront_midi_t *midi;
369 snd_wavefront_mpu_id mpu;
370
371 if (substream == NULL || substream->rmidi == NULL)
372 return;
373
374 if (substream->rmidi->private_data == NULL)
375 return;
376
377 mpu = *((snd_wavefront_mpu_id *) substream->rmidi->private_data);
378
379 midi = get_wavefront_midi(substream);
380 if (!midi)
381 return;
382
383 spin_lock_irqsave (&midi->virtual, flags);
384 if (up) {
385 if ((midi->mode[mpu] & MPU401_MODE_OUTPUT_TRIGGER) == 0) {
386 if (!midi->istimer) {
387 timer_setup(&midi->timer,
388 snd_wavefront_midi_output_timer,
389 0);
390 mod_timer(&midi->timer, 1 + jiffies);
391 }
392 midi->istimer++;
393 midi->mode[mpu] |= MPU401_MODE_OUTPUT_TRIGGER;
394 }
395 } else {
396 midi->mode[mpu] &= ~MPU401_MODE_OUTPUT_TRIGGER;
397 }
398 spin_unlock_irqrestore (&midi->virtual, flags);
399
400 if (up)
401 snd_wavefront_midi_output_write((snd_wavefront_card_t *)substream->rmidi->card->private_data);
402}
403
404void
405snd_wavefront_midi_interrupt (snd_wavefront_card_t *card)
406
407{
408 unsigned long flags;
409 snd_wavefront_midi_t *midi;
410 static struct snd_rawmidi_substream *substream = NULL;
411 static int mpu = external_mpu;
412 int max = 128;
413 unsigned char byte;
414
415 midi = &card->wavefront.midi;
416
417 if (!input_avail (midi)) {
418 snd_wavefront_midi_output_write(card);
419 return;
420 }
421
422 spin_lock_irqsave (&midi->virtual, flags);
423 while (--max) {
424
425 if (input_avail (midi)) {
426 byte = read_data (midi);
427
428 if (midi->isvirtual) {
429 if (byte == WF_EXTERNAL_SWITCH) {
430 substream = midi->substream_input[external_mpu];
431 mpu = external_mpu;
432 } else if (byte == WF_INTERNAL_SWITCH) {
433 substream = midi->substream_output[internal_mpu];
434 mpu = internal_mpu;
435 }
436 } else {
437 substream = midi->substream_input[internal_mpu];
438 mpu = internal_mpu;
439 }
440
441 if (substream == NULL) {
442 continue;
443 }
444
445 if (midi->mode[mpu] & MPU401_MODE_INPUT_TRIGGER) {
446 snd_rawmidi_receive(substream, &byte, 1);
447 }
448 } else {
449 break;
450 }
451 }
452 spin_unlock_irqrestore (&midi->virtual, flags);
453
454 snd_wavefront_midi_output_write(card);
455}
456
457void
458snd_wavefront_midi_enable_virtual (snd_wavefront_card_t *card)
459
460{
461 unsigned long flags;
462
463 spin_lock_irqsave (&card->wavefront.midi.virtual, flags);
464 card->wavefront.midi.isvirtual = 1;
465 card->wavefront.midi.output_mpu = internal_mpu;
466 card->wavefront.midi.input_mpu = internal_mpu;
467 spin_unlock_irqrestore (&card->wavefront.midi.virtual, flags);
468}
469
470void
471snd_wavefront_midi_disable_virtual (snd_wavefront_card_t *card)
472
473{
474 unsigned long flags;
475
476 spin_lock_irqsave (&card->wavefront.midi.virtual, flags);
477
478
479 card->wavefront.midi.isvirtual = 0;
480 spin_unlock_irqrestore (&card->wavefront.midi.virtual, flags);
481}
482
483int
484snd_wavefront_midi_start (snd_wavefront_card_t *card)
485
486{
487 int ok, i;
488 unsigned char rbuf[4], wbuf[4];
489 snd_wavefront_t *dev;
490 snd_wavefront_midi_t *midi;
491
492 dev = &card->wavefront;
493 midi = &dev->midi;
494
495
496
497
498
499
500
501 for (i = 0; i < 30000 && !output_ready (midi); i++);
502
503 if (!output_ready (midi)) {
504 snd_printk ("MIDI interface not ready for command\n");
505 return -1;
506 }
507
508
509
510
511
512 dev->interrupts_are_midi = 1;
513
514 outb (UART_MODE_ON, midi->mpu_command_port);
515
516 for (ok = 0, i = 50000; i > 0 && !ok; i--) {
517 if (input_avail (midi)) {
518 if (read_data (midi) == MPU_ACK) {
519 ok = 1;
520 break;
521 }
522 }
523 }
524
525 if (!ok) {
526 snd_printk ("cannot set UART mode for MIDI interface");
527 dev->interrupts_are_midi = 0;
528 return -1;
529 }
530
531
532
533 if (snd_wavefront_cmd (dev, WFC_MISYNTH_ON, rbuf, wbuf)) {
534 snd_printk ("can't enable MIDI-IN-2-synth routing.\n");
535
536 }
537
538
539
540
541
542
543
544
545
546
547
548
549 if (snd_wavefront_cmd (dev, WFC_VMIDI_OFF, rbuf, wbuf)) {
550 snd_printk ("virtual MIDI mode not disabled\n");
551 return 0;
552 }
553
554 snd_wavefront_midi_enable_virtual (card);
555
556 if (snd_wavefront_cmd (dev, WFC_VMIDI_ON, rbuf, wbuf)) {
557 snd_printk ("cannot enable virtual MIDI mode.\n");
558 snd_wavefront_midi_disable_virtual (card);
559 }
560 return 0;
561}
562
563const struct snd_rawmidi_ops snd_wavefront_midi_output =
564{
565 .open = snd_wavefront_midi_output_open,
566 .close = snd_wavefront_midi_output_close,
567 .trigger = snd_wavefront_midi_output_trigger,
568};
569
570const struct snd_rawmidi_ops snd_wavefront_midi_input =
571{
572 .open = snd_wavefront_midi_input_open,
573 .close = snd_wavefront_midi_input_close,
574 .trigger = snd_wavefront_midi_input_trigger,
575};
576
577