blob: 7b167b74375b5b5d3540d7dd58417ae989a57b6e [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
2 * sound/wf_midi.c
3 *
4 * The low level driver for the WaveFront ICS2115 MIDI interface(s)
5 * Note that there is also an MPU-401 emulation (actually, a UART-401
6 * emulation) on the CS4232 on the Tropez Plus. This code has nothing
7 * to do with that interface at all.
8 *
9 * The interface is essentially just a UART-401, but is has the
10 * interesting property of supporting what Turtle Beach called
11 * "Virtual MIDI" mode. In this mode, there are effectively *two*
12 * MIDI buses accessible via the interface, one that is routed
13 * solely to/from the external WaveFront synthesizer and the other
14 * corresponding to the pin/socket connector used to link external
15 * MIDI devices to the board.
16 *
17 * This driver fully supports this mode, allowing two distinct
18 * midi devices (/dev/midiNN and /dev/midiNN+1) to be used
19 * completely independently, giving 32 channels of MIDI routing,
20 * 16 to the WaveFront synth and 16 to the external MIDI bus.
21 *
22 * Switching between the two is accomplished externally by the driver
23 * using the two otherwise unused MIDI bytes. See the code for more details.
24 *
25 * NOTE: VIRTUAL MIDI MODE IS ON BY DEFAULT (see wavefront.c)
26 *
27 * The main reason to turn off Virtual MIDI mode is when you want to
28 * tightly couple the WaveFront synth with an external MIDI
29 * device. You won't be able to distinguish the source of any MIDI
30 * data except via SysEx ID, but thats probably OK, since for the most
31 * part, the WaveFront won't be sending any MIDI data at all.
32 *
33 * The main reason to turn on Virtual MIDI Mode is to provide two
34 * completely independent 16-channel MIDI buses, one to the
35 * WaveFront and one to any external MIDI devices. Given the 32
36 * voice nature of the WaveFront, its pretty easy to find a use
37 * for all 16 channels driving just that synth.
38 *
39 */
40
41/*
42 * Copyright (C) by Paul Barton-Davis 1998
43 * Some portions of this file are derived from work that is:
44 *
45 * CopyriGht (C) by Hannu Savolainen 1993-1996
46 *
47 * USS/Lite for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL)
48 * Version 2 (June 1991). See the "COPYING" file distributed with this software
49 * for more info.
50 */
51
52#include <linux/init.h>
53#include <linux/interrupt.h>
54#include <linux/spinlock.h>
55#include "sound_config.h"
56
57#include <linux/wavefront.h>
58
59#ifdef MODULE
60
61struct wf_mpu_config {
62 int base;
63#define DATAPORT(d) (d)->base
64#define COMDPORT(d) (d)->base+1
65#define STATPORT(d) (d)->base+1
66
67 int irq;
68 int opened;
69 int devno;
70 int synthno;
71 int mode;
72#define MODE_MIDI 1
73#define MODE_SYNTH 2
74
75 void (*inputintr) (int dev, unsigned char data);
76 char isvirtual; /* do virtual I/O stuff */
77};
78
79static struct wf_mpu_config devs[2];
80static struct wf_mpu_config *phys_dev = &devs[0];
81static struct wf_mpu_config *virt_dev = &devs[1];
82
83static void start_uart_mode (void);
84static DEFINE_SPINLOCK(lock);
85
86#define OUTPUT_READY 0x40
87#define INPUT_AVAIL 0x80
88#define MPU_ACK 0xFE
89#define UART_MODE_ON 0x3F
90
91static inline int wf_mpu_status (void)
92{
93 return inb (STATPORT (phys_dev));
94}
95
96static inline int input_avail (void)
97{
98 return !(wf_mpu_status() & INPUT_AVAIL);
99}
100
101static inline int output_ready (void)
102{
103 return !(wf_mpu_status() & OUTPUT_READY);
104}
105
106static inline int read_data (void)
107{
108 return inb (DATAPORT (phys_dev));
109}
110
111static inline void write_data (unsigned char byte)
112{
113 outb (byte, DATAPORT (phys_dev));
114}
115
116/*
117 * States for the input scanner (should be in dev_table.h)
118 */
119
120#define MST_SYSMSG 100 /* System message (sysx etc). */
121#define MST_MTC 102 /* Midi Time Code (MTC) qframe msg */
122#define MST_SONGSEL 103 /* Song select */
123#define MST_SONGPOS 104 /* Song position pointer */
124#define MST_TIMED 105 /* Leading timing byte rcvd */
125
126/* buffer space check for input scanner */
127
128#define BUFTEST(mi) if (mi->m_ptr >= MI_MAX || mi->m_ptr < 0) \
129{printk(KERN_ERR "WF-MPU: Invalid buffer pointer %d/%d, s=%d\n", \
130 mi->m_ptr, mi->m_left, mi->m_state);mi->m_ptr--;}
131
132static unsigned char len_tab[] = /* # of data bytes following a status
133 */
134{
135 2, /* 8x */
136 2, /* 9x */
137 2, /* Ax */
138 2, /* Bx */
139 1, /* Cx */
140 1, /* Dx */
141 2, /* Ex */
142 0 /* Fx */
143};
144
145static int
146wf_mpu_input_scanner (int devno, int synthdev, unsigned char midic)
147
148{
149 struct midi_input_info *mi = &midi_devs[devno]->in_info;
150
151 switch (mi->m_state) {
152 case MST_INIT:
153 switch (midic) {
154 case 0xf8:
155 /* Timer overflow */
156 break;
157
158 case 0xfc:
159 break;
160
161 case 0xfd:
162 /* XXX do something useful with this. If there is
163 an external MIDI timer (e.g. a hardware sequencer,
164 a useful timer can be derived ...
165
166 For now, no timer support.
167 */
168 break;
169
170 case 0xfe:
171 return MPU_ACK;
172 break;
173
174 case 0xf0:
175 case 0xf1:
176 case 0xf2:
177 case 0xf3:
178 case 0xf4:
179 case 0xf5:
180 case 0xf6:
181 case 0xf7:
182 break;
183
184 case 0xf9:
185 break;
186
187 case 0xff:
188 mi->m_state = MST_SYSMSG;
189 break;
190
191 default:
192 if (midic <= 0xef) {
193 mi->m_state = MST_TIMED;
194 }
195 else
196 printk (KERN_ERR "<MPU: Unknown event %02x> ",
197 midic);
198 }
199 break;
200
201 case MST_TIMED:
202 {
203 int msg = ((int) (midic & 0xf0) >> 4);
204
205 mi->m_state = MST_DATA;
206
207 if (msg < 8) { /* Data byte */
208
209 msg = ((int) (mi->m_prev_status & 0xf0) >> 4);
210 msg -= 8;
211 mi->m_left = len_tab[msg] - 1;
212
213 mi->m_ptr = 2;
214 mi->m_buf[0] = mi->m_prev_status;
215 mi->m_buf[1] = midic;
216
217 if (mi->m_left <= 0) {
218 mi->m_state = MST_INIT;
219 do_midi_msg (synthdev, mi->m_buf, mi->m_ptr);
220 mi->m_ptr = 0;
221 }
222 } else if (msg == 0xf) { /* MPU MARK */
223
224 mi->m_state = MST_INIT;
225
226 switch (midic) {
227 case 0xf8:
228 break;
229
230 case 0xf9:
231 break;
232
233 case 0xfc:
234 break;
235
236 default:
237 break;
238 }
239 } else {
240 mi->m_prev_status = midic;
241 msg -= 8;
242 mi->m_left = len_tab[msg];
243
244 mi->m_ptr = 1;
245 mi->m_buf[0] = midic;
246
247 if (mi->m_left <= 0) {
248 mi->m_state = MST_INIT;
249 do_midi_msg (synthdev, mi->m_buf, mi->m_ptr);
250 mi->m_ptr = 0;
251 }
252 }
253 }
254 break;
255
256 case MST_SYSMSG:
257 switch (midic) {
258 case 0xf0:
259 mi->m_state = MST_SYSEX;
260 break;
261
262 case 0xf1:
263 mi->m_state = MST_MTC;
264 break;
265
266 case 0xf2:
267 mi->m_state = MST_SONGPOS;
268 mi->m_ptr = 0;
269 break;
270
271 case 0xf3:
272 mi->m_state = MST_SONGSEL;
273 break;
274
275 case 0xf6:
276 mi->m_state = MST_INIT;
277
278 /*
279 * Real time messages
280 */
281 case 0xf8:
282 /* midi clock */
283 mi->m_state = MST_INIT;
284 /* XXX need ext MIDI timer support */
285 break;
286
287 case 0xfA:
288 mi->m_state = MST_INIT;
289 /* XXX need ext MIDI timer support */
290 break;
291
292 case 0xFB:
293 mi->m_state = MST_INIT;
294 /* XXX need ext MIDI timer support */
295 break;
296
297 case 0xFC:
298 mi->m_state = MST_INIT;
299 /* XXX need ext MIDI timer support */
300 break;
301
302 case 0xFE:
303 /* active sensing */
304 mi->m_state = MST_INIT;
305 break;
306
307 case 0xff:
308 mi->m_state = MST_INIT;
309 break;
310
311 default:
312 printk (KERN_ERR "unknown MIDI sysmsg %0x\n", midic);
313 mi->m_state = MST_INIT;
314 }
315 break;
316
317 case MST_MTC:
318 mi->m_state = MST_INIT;
319 break;
320
321 case MST_SYSEX:
322 if (midic == 0xf7) {
323 mi->m_state = MST_INIT;
324 } else {
325 /* XXX fix me */
326 }
327 break;
328
329 case MST_SONGPOS:
330 BUFTEST (mi);
331 mi->m_buf[mi->m_ptr++] = midic;
332 if (mi->m_ptr == 2) {
333 mi->m_state = MST_INIT;
334 mi->m_ptr = 0;
335 /* XXX need ext MIDI timer support */
336 }
337 break;
338
339 case MST_DATA:
340 BUFTEST (mi);
341 mi->m_buf[mi->m_ptr++] = midic;
342 if ((--mi->m_left) <= 0) {
343 mi->m_state = MST_INIT;
344 do_midi_msg (synthdev, mi->m_buf, mi->m_ptr);
345 mi->m_ptr = 0;
346 }
347 break;
348
349 default:
350 printk (KERN_ERR "Bad state %d ", mi->m_state);
351 mi->m_state = MST_INIT;
352 }
353
354 return 1;
355}
356
357static irqreturn_t
358wf_mpuintr(int irq, void *dev_id, struct pt_regs *dummy)
359
360{
361 struct wf_mpu_config *physical_dev = dev_id;
362 static struct wf_mpu_config *input_dev;
363 struct midi_input_info *mi = &midi_devs[physical_dev->devno]->in_info;
364 int n;
365
366 if (!input_avail()) { /* not for us */
367 return IRQ_NONE;
368 }
369
370 if (mi->m_busy)
371 return IRQ_HANDLED;
372 spin_lock(&lock);
373 mi->m_busy = 1;
374
375 if (!input_dev) {
376 input_dev = physical_dev;
377 }
378
379 n = 50; /* XXX why ? */
380
381 do {
382 unsigned char c = read_data ();
383
384 if (phys_dev->isvirtual) {
385
386 if (c == WF_EXTERNAL_SWITCH) {
387 input_dev = virt_dev;
388 continue;
389 } else if (c == WF_INTERNAL_SWITCH) {
390 input_dev = phys_dev;
391 continue;
392 } /* else just leave it as it is */
393
394 } else {
395 input_dev = phys_dev;
396 }
397
398 if (input_dev->mode == MODE_SYNTH) {
399
400 wf_mpu_input_scanner (input_dev->devno,
401 input_dev->synthno, c);
402
403 } else if (input_dev->opened & OPEN_READ) {
404
405 if (input_dev->inputintr) {
406 input_dev->inputintr (input_dev->devno, c);
407 }
408 }
409
410 } while (input_avail() && n-- > 0);
411
412 mi->m_busy = 0;
413 spin_unlock(&lock);
414 return IRQ_HANDLED;
415}
416
417static int
418wf_mpu_open (int dev, int mode,
419 void (*input) (int dev, unsigned char data),
420 void (*output) (int dev)
421 )
422{
423 struct wf_mpu_config *devc;
424
425 if (dev < 0 || dev >= num_midis || midi_devs[dev]==NULL)
426 return -(ENXIO);
427
428 if (phys_dev->devno == dev) {
429 devc = phys_dev;
430 } else if (phys_dev->isvirtual && virt_dev->devno == dev) {
431 devc = virt_dev;
432 } else {
433 printk (KERN_ERR "WF-MPU: unknown device number %d\n", dev);
434 return -(EINVAL);
435 }
436
437 if (devc->opened) {
438 return -(EBUSY);
439 }
440
441 devc->mode = MODE_MIDI;
442 devc->opened = mode;
443 devc->synthno = 0;
444
445 devc->inputintr = input;
446 return 0;
447}
448
449static void
450wf_mpu_close (int dev)
451{
452 struct wf_mpu_config *devc;
453
454 if (dev < 0 || dev >= num_midis || midi_devs[dev]==NULL)
455 return;
456
457 if (phys_dev->devno == dev) {
458 devc = phys_dev;
459 } else if (phys_dev->isvirtual && virt_dev->devno == dev) {
460 devc = virt_dev;
461 } else {
462 printk (KERN_ERR "WF-MPU: unknown device number %d\n", dev);
463 return;
464 }
465
466 devc->mode = 0;
467 devc->inputintr = NULL;
468 devc->opened = 0;
469}
470
471static int
472wf_mpu_out (int dev, unsigned char midi_byte)
473{
474 int timeout;
475 unsigned long flags;
476 static int lastoutdev = -1;
477 unsigned char switchch;
478
479 if (phys_dev->isvirtual && lastoutdev != dev) {
480
481 if (dev == phys_dev->devno) {
482 switchch = WF_INTERNAL_SWITCH;
483 } else if (dev == virt_dev->devno) {
484 switchch = WF_EXTERNAL_SWITCH;
485 } else {
486 printk (KERN_ERR "WF-MPU: bad device number %d", dev);
487 return (0);
488 }
489
490 /* XXX fix me */
491
492 for (timeout = 30000; timeout > 0 && !output_ready ();
493 timeout--);
494
495 spin_lock_irqsave(&lock,flags);
496
497 if (!output_ready ()) {
498 printk (KERN_WARNING "WF-MPU: Send switch "
499 "byte timeout\n");
500 spin_unlock_irqrestore(&lock,flags);
501 return 0;
502 }
503
504 write_data (switchch);
505 spin_unlock_irqrestore(&lock,flags);
506 }
507
508 lastoutdev = dev;
509
510 /*
511 * Sometimes it takes about 30000 loops before the output becomes ready
512 * (After reset). Normally it takes just about 10 loops.
513 */
514
515 /* XXX fix me */
516
517 for (timeout = 30000; timeout > 0 && !output_ready (); timeout--);
518
519 spin_lock_irqsave(&lock,flags);
520 if (!output_ready ()) {
521 spin_unlock_irqrestore(&lock,flags);
522 printk (KERN_WARNING "WF-MPU: Send data timeout\n");
523 return 0;
524 }
525
526 write_data (midi_byte);
527 spin_unlock_irqrestore(&lock,flags);
528
529 return 1;
530}
531
532static inline int wf_mpu_start_read (int dev) {
533 return 0;
534}
535
536static inline int wf_mpu_end_read (int dev) {
537 return 0;
538}
539
540static int wf_mpu_ioctl (int dev, unsigned cmd, void __user *arg)
541{
542 printk (KERN_WARNING
543 "WF-MPU: Intelligent mode not supported by hardware.\n");
544 return -(EINVAL);
545}
546
547static int wf_mpu_buffer_status (int dev)
548{
549 return 0;
550}
551
552static struct synth_operations wf_mpu_synth_operations[2];
553static struct midi_operations wf_mpu_midi_operations[2];
554
555static struct midi_operations wf_mpu_midi_proto =
556{
557 .owner = THIS_MODULE,
558 .info = {"WF-MPU MIDI", 0, MIDI_CAP_MPU401, SNDCARD_MPU401},
559 .in_info = {0}, /* in_info */
560 .open = wf_mpu_open,
561 .close = wf_mpu_close,
562 .ioctl = wf_mpu_ioctl,
563 .outputc = wf_mpu_out,
564 .start_read = wf_mpu_start_read,
565 .end_read = wf_mpu_end_read,
566 .buffer_status = wf_mpu_buffer_status,
567};
568
569static struct synth_info wf_mpu_synth_info_proto =
570{"WaveFront MPU-401 interface", 0,
571 SYNTH_TYPE_MIDI, MIDI_TYPE_MPU401, 0, 128, 0, 128, SYNTH_CAP_INPUT};
572
573static struct synth_info wf_mpu_synth_info[2];
574
575static int
576wf_mpu_synth_ioctl (int dev, unsigned int cmd, void __user *arg)
577{
578 int midi_dev;
579 int index;
580
581 midi_dev = synth_devs[dev]->midi_dev;
582
583 if (midi_dev < 0 || midi_dev > num_midis || midi_devs[midi_dev]==NULL)
584 return -(ENXIO);
585
586 if (midi_dev == phys_dev->devno) {
587 index = 0;
588 } else if (phys_dev->isvirtual && midi_dev == virt_dev->devno) {
589 index = 1;
590 } else {
591 return -(EINVAL);
592 }
593
594 switch (cmd) {
595
596 case SNDCTL_SYNTH_INFO:
597 if (copy_to_user(arg,
598 &wf_mpu_synth_info[index],
599 sizeof (struct synth_info)))
600 return -EFAULT;
601 return 0;
602
603 case SNDCTL_SYNTH_MEMAVL:
604 return 0x7fffffff;
605
606 default:
607 return -EINVAL;
608 }
609}
610
611static int
612wf_mpu_synth_open (int dev, int mode)
613{
614 int midi_dev;
615 struct wf_mpu_config *devc;
616
617 midi_dev = synth_devs[dev]->midi_dev;
618
619 if (midi_dev < 0 || midi_dev > num_midis || midi_devs[midi_dev]==NULL) {
620 return -(ENXIO);
621 }
622
623 if (phys_dev->devno == midi_dev) {
624 devc = phys_dev;
625 } else if (phys_dev->isvirtual && virt_dev->devno == midi_dev) {
626 devc = virt_dev;
627 } else {
628 printk (KERN_ERR "WF-MPU: unknown device number %d\n", dev);
629 return -(EINVAL);
630 }
631
632 if (devc->opened) {
633 return -(EBUSY);
634 }
635
636 devc->mode = MODE_SYNTH;
637 devc->synthno = dev;
638 devc->opened = mode;
639 devc->inputintr = NULL;
640 return 0;
641}
642
643static void
644wf_mpu_synth_close (int dev)
645{
646 int midi_dev;
647 struct wf_mpu_config *devc;
648
649 midi_dev = synth_devs[dev]->midi_dev;
650
651 if (phys_dev->devno == midi_dev) {
652 devc = phys_dev;
653 } else if (phys_dev->isvirtual && virt_dev->devno == midi_dev) {
654 devc = virt_dev;
655 } else {
656 printk (KERN_ERR "WF-MPU: unknown device number %d\n", dev);
657 return;
658 }
659
660 devc->inputintr = NULL;
661 devc->opened = 0;
662 devc->mode = 0;
663}
664
665#define _MIDI_SYNTH_C_
666#define MIDI_SYNTH_NAME "WaveFront (MIDI)"
667#define MIDI_SYNTH_CAPS SYNTH_CAP_INPUT
668#include "midi_synth.h"
669
670static struct synth_operations wf_mpu_synth_proto =
671{
672 .owner = THIS_MODULE,
673 .id = "WaveFront (ICS2115)",
674 .info = NULL, /* info field, filled in during configuration */
675 .midi_dev = 0, /* MIDI dev XXX should this be -1 ? */
676 .synth_type = SYNTH_TYPE_MIDI,
677 .synth_subtype = SAMPLE_TYPE_WAVEFRONT,
678 .open = wf_mpu_synth_open,
679 .close = wf_mpu_synth_close,
680 .ioctl = wf_mpu_synth_ioctl,
681 .kill_note = midi_synth_kill_note,
682 .start_note = midi_synth_start_note,
683 .set_instr = midi_synth_set_instr,
684 .reset = midi_synth_reset,
685 .hw_control = midi_synth_hw_control,
686 .load_patch = midi_synth_load_patch,
687 .aftertouch = midi_synth_aftertouch,
688 .controller = midi_synth_controller,
689 .panning = midi_synth_panning,
690 .bender = midi_synth_bender,
691 .setup_voice = midi_synth_setup_voice,
692 .send_sysex = midi_synth_send_sysex
693};
694
695static int
696config_wf_mpu (struct wf_mpu_config *dev)
697
698{
699 int is_external;
700 char *name;
701 int index;
702
703 if (dev == phys_dev) {
704 name = "WaveFront internal MIDI";
705 is_external = 0;
706 index = 0;
707 memcpy ((char *) &wf_mpu_synth_operations[index],
708 (char *) &wf_mpu_synth_proto,
709 sizeof (struct synth_operations));
710 } else {
711 name = "WaveFront external MIDI";
712 is_external = 1;
713 index = 1;
714 /* no synth operations for an external MIDI interface */
715 }
716
717 memcpy ((char *) &wf_mpu_synth_info[dev->devno],
718 (char *) &wf_mpu_synth_info_proto,
719 sizeof (struct synth_info));
720
721 strcpy (wf_mpu_synth_info[index].name, name);
722
723 wf_mpu_synth_operations[index].midi_dev = dev->devno;
724 wf_mpu_synth_operations[index].info = &wf_mpu_synth_info[index];
725
726 memcpy ((char *) &wf_mpu_midi_operations[index],
727 (char *) &wf_mpu_midi_proto,
728 sizeof (struct midi_operations));
729
730 if (is_external) {
731 wf_mpu_midi_operations[index].converter = NULL;
732 } else {
733 wf_mpu_midi_operations[index].converter =
734 &wf_mpu_synth_operations[index];
735 }
736
737 strcpy (wf_mpu_midi_operations[index].info.name, name);
738
739 midi_devs[dev->devno] = &wf_mpu_midi_operations[index];
740 midi_devs[dev->devno]->in_info.m_busy = 0;
741 midi_devs[dev->devno]->in_info.m_state = MST_INIT;
742 midi_devs[dev->devno]->in_info.m_ptr = 0;
743 midi_devs[dev->devno]->in_info.m_left = 0;
744 midi_devs[dev->devno]->in_info.m_prev_status = 0;
745
746 devs[index].opened = 0;
747 devs[index].mode = 0;
748
749 return (0);
750}
751
752int virtual_midi_enable (void)
753
754{
755 if ((virt_dev->devno < 0) &&
756 (virt_dev->devno = sound_alloc_mididev()) == -1) {
757 printk (KERN_ERR
758 "WF-MPU: too many midi devices detected\n");
759 return -1;
760 }
761
762 config_wf_mpu (virt_dev);
763
764 phys_dev->isvirtual = 1;
765 return virt_dev->devno;
766}
767
768int
769virtual_midi_disable (void)
770
771{
772 unsigned long flags;
773
774 spin_lock_irqsave(&lock,flags);
775
776 wf_mpu_close (virt_dev->devno);
777 /* no synth on virt_dev, so no need to call wf_mpu_synth_close() */
778 phys_dev->isvirtual = 0;
779
780 spin_unlock_irqrestore(&lock,flags);
781
782 return 0;
783}
784
785int __init detect_wf_mpu (int irq, int io_base)
786{
787 if (!request_region(io_base, 2, "wavefront midi")) {
788 printk (KERN_WARNING "WF-MPU: I/O port %x already in use.\n",
789 io_base);
790 return -1;
791 }
792
793 phys_dev->base = io_base;
794 phys_dev->irq = irq;
795 phys_dev->devno = -1;
796 virt_dev->devno = -1;
797
798 return 0;
799}
800
801int __init install_wf_mpu (void)
802{
803 if ((phys_dev->devno = sound_alloc_mididev()) < 0){
804
805 printk (KERN_ERR "WF-MPU: Too many MIDI devices detected.\n");
806 release_region(phys_dev->base, 2);
807 return -1;
808 }
809
810 phys_dev->isvirtual = 0;
811
812 if (config_wf_mpu (phys_dev)) {
813
814 printk (KERN_WARNING
815 "WF-MPU: configuration for MIDI device %d failed\n",
816 phys_dev->devno);
817 sound_unload_mididev (phys_dev->devno);
818
819 }
820
821 /* OK, now we're configured to handle an interrupt ... */
822
823 if (request_irq (phys_dev->irq, wf_mpuintr, SA_INTERRUPT|SA_SHIRQ,
824 "wavefront midi", phys_dev) < 0) {
825
826 printk (KERN_ERR "WF-MPU: Failed to allocate IRQ%d\n",
827 phys_dev->irq);
828 return -1;
829
830 }
831
832 /* This being a WaveFront (ICS-2115) emulated MPU-401, we have
833 to switch it into UART (dumb) mode, because otherwise, it
834 won't do anything at all.
835 */
836
837 start_uart_mode ();
838
839 return phys_dev->devno;
840}
841
842void
843uninstall_wf_mpu (void)
844
845{
846 release_region (phys_dev->base, 2);
847 free_irq (phys_dev->irq, phys_dev);
848 sound_unload_mididev (phys_dev->devno);
849
850 if (virt_dev->devno >= 0) {
851 sound_unload_mididev (virt_dev->devno);
852 }
853}
854
855static void
856start_uart_mode (void)
857
858{
859 int ok, i;
860 unsigned long flags;
861
862 spin_lock_irqsave(&lock,flags);
863
864 /* XXX fix me */
865
866 for (i = 0; i < 30000 && !output_ready (); i++);
867
868 outb (UART_MODE_ON, COMDPORT(phys_dev));
869
870 for (ok = 0, i = 50000; i > 0 && !ok; i--) {
871 if (input_avail ()) {
872 if (read_data () == MPU_ACK) {
873 ok = 1;
874 }
875 }
876 }
877
878 spin_unlock_irqrestore(&lock,flags);
879}
880#endif