]> www.pilppa.org Git - linux-2.6-omap-h63xx.git/blob - sound/oss/wf_midi.c
3f3a390014caf29165fa0d45b06b7739fe5bd1e5
[linux-2.6-omap-h63xx.git] / sound / oss / wf_midi.c
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 <linux/interrupt.h>
54 #include <linux/spinlock.h>
55 #include "sound_config.h"
56
57 #include <linux/wavefront.h>
58
59 #ifdef MODULE
60
61 struct 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
79 static struct wf_mpu_config  devs[2];
80 static struct wf_mpu_config *phys_dev = &devs[0];
81 static struct wf_mpu_config *virt_dev = &devs[1];
82
83 static void start_uart_mode (void);
84 static 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
91 static inline int wf_mpu_status (void)
92 {
93         return inb (STATPORT (phys_dev));
94 }
95
96 static inline int input_avail (void)
97 {
98         return !(wf_mpu_status() & INPUT_AVAIL);
99 }
100
101 static inline int output_ready (void)
102 {
103         return !(wf_mpu_status() & OUTPUT_READY);
104 }
105
106 static inline int  read_data (void)
107 {
108         return inb (DATAPORT (phys_dev));
109 }
110
111 static 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
132 static 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
145 static int
146 wf_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
357 static irqreturn_t
358 wf_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
417 static int
418 wf_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  
449 static void
450 wf_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
471 static int
472 wf_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
532 static inline int wf_mpu_start_read (int dev) {
533         return 0;
534 }
535
536 static inline int wf_mpu_end_read (int dev) {
537         return 0;
538 }
539
540 static 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
547 static int wf_mpu_buffer_status (int dev)
548 {
549         return 0;
550 }
551
552 static struct synth_operations wf_mpu_synth_operations[2];
553 static struct midi_operations  wf_mpu_midi_operations[2];
554
555 static 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
569 static 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
573 static struct synth_info wf_mpu_synth_info[2];
574
575 static int
576 wf_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
611 static int
612 wf_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
643 static void
644 wf_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
670 static 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
695 static int
696 config_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
752 int 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
768 int
769 virtual_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
785 int __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
801 int __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, IRQF_DISABLED|IRQF_SHARED,
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  
842 void
843 uninstall_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
855 static void
856 start_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