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