~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

Linux Cross Reference
Linux/drivers/sound/wf_midi.c

Version: ~ [ 2.4.0 ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  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 
 88 static inline int wf_mpu_status (void)
 89 {
 90         return inb (STATPORT (phys_dev));
 91 }
 92 
 93 static inline int input_avail (void)
 94 {
 95         return !(wf_mpu_status() & INPUT_AVAIL);
 96 }
 97 
 98 static inline int output_ready (void)
 99 {
100         return !(wf_mpu_status() & OUTPUT_READY);
101 }
102 
103 static inline int  read_data (void)
104 {
105         return inb (DATAPORT (phys_dev));
106 }
107 
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
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                         }
235                 } else {
236                         mi->m_prev_status = midic;
237                         msg -= 8;
238                         mi->m_left = len_tab[msg];
239               
240                         mi->m_ptr = 1;
241                         mi->m_buf[0] = midic;
242               
243                         if (mi->m_left <= 0) {
244                                 mi->m_state = MST_INIT;
245                                 do_midi_msg (synthdev, mi->m_buf, mi->m_ptr);
246                                 mi->m_ptr = 0;
247                         }
248                 }
249         }
250         break;
251 
252         case MST_SYSMSG:
253                 switch (midic) {
254                 case 0xf0:
255                         mi->m_state = MST_SYSEX;
256                         break;
257             
258                 case 0xf1:
259                         mi->m_state = MST_MTC;
260                         break;
261 
262                 case 0xf2:
263                         mi->m_state = MST_SONGPOS;
264                         mi->m_ptr = 0;
265                         break;
266             
267                 case 0xf3:
268                         mi->m_state = MST_SONGSEL;
269                         break;
270             
271                 case 0xf6:
272                         mi->m_state = MST_INIT;
273             
274                         /*
275                          *    Real time messages
276                          */
277                 case 0xf8:
278                         /* midi clock */
279                         mi->m_state = MST_INIT;
280                         /* XXX need ext MIDI timer support */
281                         break;
282             
283                 case 0xfA:
284                         mi->m_state = MST_INIT;
285                         /* XXX need ext MIDI timer support */
286                         break;
287             
288                 case 0xFB:
289                         mi->m_state = MST_INIT;
290                         /* XXX need ext MIDI timer support */
291                         break;
292             
293                 case 0xFC:
294                         mi->m_state = MST_INIT;
295                         /* XXX need ext MIDI timer support */
296                         break;
297             
298                 case 0xFE:
299                         /* active sensing */
300                         mi->m_state = MST_INIT;
301                         break;
302             
303                 case 0xff:
304                         mi->m_state = MST_INIT;
305                         break;
306 
307                 default:
308                         printk (KERN_ERR "unknown MIDI sysmsg %0x\n", midic);
309                         mi->m_state = MST_INIT;
310                 }
311                 break;
312 
313         case MST_MTC:
314                 mi->m_state = MST_INIT;
315                 break;
316 
317         case MST_SYSEX:
318                 if (midic == 0xf7) {
319                         mi->m_state = MST_INIT;
320                 } else {
321                         /* XXX fix me */
322                 }
323                 break;
324 
325         case MST_SONGPOS:
326                 BUFTEST (mi);
327                 mi->m_buf[mi->m_ptr++] = midic;
328                 if (mi->m_ptr == 2) {
329                         mi->m_state = MST_INIT;
330                         mi->m_ptr = 0;
331                         /* XXX need ext MIDI timer support */
332                 }
333                 break;
334 
335         case MST_DATA:
336                 BUFTEST (mi);
337                 mi->m_buf[mi->m_ptr++] = midic;
338                 if ((--mi->m_left) <= 0) {
339                         mi->m_state = MST_INIT;
340                         do_midi_msg (synthdev, mi->m_buf, mi->m_ptr);
341                         mi->m_ptr = 0;
342                 }
343                 break;
344 
345         default:
346                 printk (KERN_ERR "Bad state %d ", mi->m_state);
347                 mi->m_state = MST_INIT;
348         }
349 
350         return 1;
351 }
352 
353 void
354 wf_mpuintr (int irq, void *dev_id, struct pt_regs *dummy)
355 
356 {
357         struct wf_mpu_config *physical_dev = dev_id;
358         static struct wf_mpu_config *input_dev = 0;
359         struct midi_input_info *mi = &midi_devs[physical_dev->devno]->in_info;
360         int n;
361 
362         if (!input_avail()) { /* not for us */
363                 return;
364         }
365 
366         if (mi->m_busy) return;
367         mi->m_busy = 1;
368         sti (); 
369 
370         if (!input_dev) {
371                 input_dev = physical_dev;
372         }
373 
374         n = 50; /* XXX why ? */
375 
376         do {
377                 unsigned char c = read_data ();
378       
379                 if (phys_dev->isvirtual) {
380 
381                         if (c == WF_EXTERNAL_SWITCH) {
382                                 input_dev = virt_dev;
383                                 continue;
384                         } else if (c == WF_INTERNAL_SWITCH) { 
385                                 input_dev = phys_dev;
386                                 continue;
387                         } /* else just leave it as it is */
388 
389                 } else {
390                         input_dev = phys_dev;
391                 }
392 
393                 if (input_dev->mode == MODE_SYNTH) {
394           
395                         wf_mpu_input_scanner (input_dev->devno,
396                                               input_dev->synthno, c);
397           
398                 } else if (input_dev->opened & OPEN_READ) {
399           
400                         if (input_dev->inputintr) {
401                                 input_dev->inputintr (input_dev->devno, c);
402                         } 
403                 }
404 
405         } while (input_avail() && n-- > 0);
406 
407         mi->m_busy = 0;
408 }
409 
410 static int
411 wf_mpu_open (int dev, int mode,
412              void            (*input) (int dev, unsigned char data),
413              void            (*output) (int dev)
414         )
415 {
416         struct wf_mpu_config *devc;
417 
418         if (dev < 0 || dev >= num_midis || midi_devs[dev]==NULL)
419                 return -(ENXIO);
420 
421         if (phys_dev->devno == dev) {
422                 devc = phys_dev;
423         } else if (phys_dev->isvirtual && virt_dev->devno == dev) {
424                 devc = virt_dev;
425         } else {
426                 printk (KERN_ERR "WF-MPU: unknown device number %d\n", dev);
427                 return -(EINVAL);
428         }
429 
430         if (devc->opened) {
431                 return -(EBUSY);
432         }
433 
434         devc->mode = MODE_MIDI;
435         devc->opened = mode;
436         devc->synthno = 0;
437 
438         devc->inputintr = input;
439         return 0;
440 }
441  
442 static void
443 wf_mpu_close (int dev)
444 {
445         struct wf_mpu_config *devc;
446 
447         if (dev < 0 || dev >= num_midis || midi_devs[dev]==NULL)
448                 return;
449 
450         if (phys_dev->devno == dev) {
451                 devc = phys_dev;
452         } else if (phys_dev->isvirtual && virt_dev->devno == dev) {
453                 devc = virt_dev;
454         } else {
455                 printk (KERN_ERR "WF-MPU: unknown device number %d\n", dev);
456                 return;
457         }
458 
459         devc->mode = 0;
460         devc->inputintr = NULL;
461         devc->opened = 0;
462 }
463 
464 static int
465 wf_mpu_out (int dev, unsigned char midi_byte)
466 {
467         int             timeout;
468         unsigned long   flags;
469         static int lastoutdev = -1;
470         unsigned char switchch;
471 
472         if (phys_dev->isvirtual && lastoutdev != dev) {
473       
474                 if (dev == phys_dev->devno) { 
475                         switchch = WF_INTERNAL_SWITCH;
476                 } else if (dev == virt_dev->devno) { 
477                         switchch = WF_EXTERNAL_SWITCH;
478                 } else {
479                         printk (KERN_ERR "WF-MPU: bad device number %d", dev);
480                         return (0);
481                 }
482 
483                 /* XXX fix me */
484       
485                 for (timeout = 30000; timeout > 0 && !output_ready ();
486                      timeout--);
487       
488                 save_flags (flags);
489                 cli ();
490       
491                 if (!output_ready ()) {
492                         printk (KERN_WARNING "WF-MPU: Send switch "
493                                 "byte timeout\n");
494                         restore_flags (flags);
495                         return 0;
496                 }
497       
498                 write_data (switchch);
499                 restore_flags (flags);
500         } 
501 
502         lastoutdev = dev;
503 
504         /*
505          * Sometimes it takes about 30000 loops before the output becomes ready
506          * (After reset). Normally it takes just about 10 loops.
507          */
508 
509         /* XXX fix me */
510 
511         for (timeout = 30000; timeout > 0 && !output_ready (); timeout--);
512 
513         save_flags (flags);
514         cli ();
515         if (!output_ready ()) {
516                 printk (KERN_WARNING "WF-MPU: Send data timeout\n");
517                 restore_flags (flags);
518                 return 0;
519         }
520 
521         write_data (midi_byte);
522         restore_flags (flags);
523 
524         return 1;
525 }
526 
527 static inline int wf_mpu_start_read (int dev) {
528         return 0;
529 }
530 
531 static inline int wf_mpu_end_read (int dev) {
532         return 0;
533 }
534 
535 static int wf_mpu_ioctl (int dev, unsigned cmd, caddr_t arg)
536 {
537         printk (KERN_WARNING
538                 "WF-MPU: Intelligent mode not supported by hardware.\n");
539         return -(EINVAL);
540 }
541 
542 static int wf_mpu_buffer_status (int dev)
543 {
544         return 0;
545 }
546 
547 static struct synth_operations wf_mpu_synth_operations[2];
548 static struct midi_operations  wf_mpu_midi_operations[2];
549 
550 static struct midi_operations wf_mpu_midi_proto =
551 {
552         owner:          THIS_MODULE,
553         info:           {"WF-MPU MIDI", 0, MIDI_CAP_MPU401, SNDCARD_MPU401},
554         in_info:        {0},   /* in_info */
555         open:           wf_mpu_open,
556         close:          wf_mpu_close,
557         ioctl:          wf_mpu_ioctl,
558         outputc:        wf_mpu_out,
559         start_read:     wf_mpu_start_read,
560         end_read:       wf_mpu_end_read,
561         buffer_status:  wf_mpu_buffer_status,
562 };
563 
564 static struct synth_info wf_mpu_synth_info_proto =
565 {"WaveFront MPU-401 interface", 0,
566  SYNTH_TYPE_MIDI, MIDI_TYPE_MPU401, 0, 128, 0, 128, SYNTH_CAP_INPUT};
567 
568 static struct synth_info wf_mpu_synth_info[2];
569 
570 static int
571 wf_mpu_synth_ioctl (int dev,
572                     unsigned int cmd, caddr_t arg)
573 {
574         int             midi_dev;
575         int index;
576 
577         midi_dev = synth_devs[dev]->midi_dev;
578 
579         if (midi_dev < 0 || midi_dev > num_midis || midi_devs[midi_dev]==NULL)
580                 return -(ENXIO);
581 
582         if (midi_dev == phys_dev->devno) {
583                 index = 0;
584         } else if (phys_dev->isvirtual && midi_dev == virt_dev->devno) {
585                 index = 1;
586         } else {
587                 return -(EINVAL);
588         }
589 
590         switch (cmd) {
591 
592         case SNDCTL_SYNTH_INFO:
593                 copy_to_user (&((char *) arg)[0],
594                               &wf_mpu_synth_info[index],
595                               sizeof (struct synth_info));
596         
597                 return 0;
598                 break;
599         
600         case SNDCTL_SYNTH_MEMAVL:
601                 return 0x7fffffff;
602                 break;
603         
604         default:
605                 return -(EINVAL);
606         }
607 }
608 
609 static int
610 wf_mpu_synth_open (int dev, int mode)
611 {
612         int             midi_dev;
613         struct wf_mpu_config *devc;
614 
615         midi_dev = synth_devs[dev]->midi_dev;
616 
617         if (midi_dev < 0 || midi_dev > num_midis || midi_devs[midi_dev]==NULL) {
618                 return -(ENXIO);
619         }
620   
621         if (phys_dev->devno == midi_dev) {
622                 devc = phys_dev;
623         } else if (phys_dev->isvirtual && virt_dev->devno == midi_dev) {
624                 devc = virt_dev;
625         } else {
626                 printk (KERN_ERR "WF-MPU: unknown device number %d\n", dev);
627                 return -(EINVAL);
628         }
629 
630         if (devc->opened) {
631                 return -(EBUSY);
632         }
633   
634         devc->mode = MODE_SYNTH;
635         devc->synthno = dev;
636         devc->opened = mode;
637         devc->inputintr = NULL;
638         return 0;
639 }
640 
641 static void
642 wf_mpu_synth_close (int dev)
643 {
644         int             midi_dev;
645         struct wf_mpu_config *devc;
646 
647         midi_dev = synth_devs[dev]->midi_dev;
648 
649         if (phys_dev->devno == midi_dev) {
650                 devc = phys_dev;
651         } else if (phys_dev->isvirtual && virt_dev->devno == midi_dev) {
652                 devc = virt_dev;
653         } else {
654                 printk (KERN_ERR "WF-MPU: unknown device number %d\n", dev);
655                 return;
656         }
657 
658         devc->inputintr = NULL;
659         devc->opened = 0;
660         devc->mode = 0;
661 }
662 
663 #define _MIDI_SYNTH_C_
664 #define MIDI_SYNTH_NAME "WaveFront (MIDI)"
665 #define MIDI_SYNTH_CAPS SYNTH_CAP_INPUT
666 #include "midi_synth.h"
667 
668 static struct synth_operations wf_mpu_synth_proto =
669 {
670         owner:          THIS_MODULE,
671         id:             "WaveFront (ICS2115)",
672         info:           NULL,  /* info field, filled in during configuration */
673         midi_dev:       0,     /* MIDI dev XXX should this be -1 ? */
674         synth_type:     SYNTH_TYPE_MIDI,
675         synth_subtype:  SAMPLE_TYPE_WAVEFRONT,
676         open:           wf_mpu_synth_open,
677         close:          wf_mpu_synth_close,
678         ioctl:          wf_mpu_synth_ioctl,
679         kill_note:      midi_synth_kill_note,
680         start_note:     midi_synth_start_note,
681         set_instr:      midi_synth_set_instr,
682         reset:          midi_synth_reset,
683         hw_control:     midi_synth_hw_control,
684         load_patch:     midi_synth_load_patch,
685         aftertouch:     midi_synth_aftertouch,
686         controller:     midi_synth_controller,
687         panning:        midi_synth_panning,
688         bender:         midi_synth_bender,
689         setup_voice:    midi_synth_setup_voice,
690         send_sysex:     midi_synth_send_sysex
691 };
692 
693 static int
694 config_wf_mpu (struct wf_mpu_config *dev)
695 
696 {
697         int is_external;
698         char *name;
699         int index;
700 
701         if (dev == phys_dev) {
702                 name = "WaveFront internal MIDI";
703                 is_external = 0;
704                 index = 0;
705                 memcpy ((char *) &wf_mpu_synth_operations[index],
706                         (char *) &wf_mpu_synth_proto,
707                         sizeof (struct synth_operations));
708         } else {
709                 name = "WaveFront external MIDI";
710                 is_external = 1;
711                 index = 1;
712                 /* no synth operations for an external MIDI interface */
713         }
714 
715         memcpy ((char *) &wf_mpu_synth_info[dev->devno],
716                 (char *) &wf_mpu_synth_info_proto,
717                 sizeof (struct synth_info));
718 
719         strcpy (wf_mpu_synth_info[index].name, name);
720 
721         wf_mpu_synth_operations[index].midi_dev = dev->devno;
722         wf_mpu_synth_operations[index].info = &wf_mpu_synth_info[index];
723 
724         memcpy ((char *) &wf_mpu_midi_operations[index],
725                 (char *) &wf_mpu_midi_proto,
726                 sizeof (struct midi_operations));
727   
728         if (is_external) {
729                 wf_mpu_midi_operations[index].converter = NULL;
730         } else {
731                 wf_mpu_midi_operations[index].converter =
732                         &wf_mpu_synth_operations[index];
733         }
734 
735         strcpy (wf_mpu_midi_operations[index].info.name, name);
736 
737         midi_devs[dev->devno] = &wf_mpu_midi_operations[index];
738         midi_devs[dev->devno]->in_info.m_busy = 0;
739         midi_devs[dev->devno]->in_info.m_state = MST_INIT;
740         midi_devs[dev->devno]->in_info.m_ptr = 0;
741         midi_devs[dev->devno]->in_info.m_left = 0;
742         midi_devs[dev->devno]->in_info.m_prev_status = 0;
743 
744         devs[index].opened = 0;
745         devs[index].mode = 0;
746 
747         return (0);
748 }
749 
750 int virtual_midi_enable (void)
751 
752 {
753         if ((virt_dev->devno < 0) &&
754             (virt_dev->devno = sound_alloc_mididev()) == -1) {
755                 printk (KERN_ERR
756                         "WF-MPU: too many midi devices detected\n");
757                 return -1;
758         }
759 
760         config_wf_mpu (virt_dev);
761 
762         phys_dev->isvirtual = 1;
763         return virt_dev->devno;
764 }
765 
766 int
767 virtual_midi_disable (void)
768 
769 {
770         unsigned long flags;
771 
772         save_flags (flags);
773         cli();
774 
775         wf_mpu_close (virt_dev->devno);
776         /* no synth on virt_dev, so no need to call wf_mpu_synth_close() */
777         phys_dev->isvirtual = 0;
778 
779         restore_flags (flags);
780 
781         return 0;
782 }
783 
784 int __init detect_wf_mpu (int irq, int io_base)
785 {
786         if (check_region (io_base, 2)) {
787                 printk (KERN_WARNING "WF-MPU: I/O port %x already in use.\n",
788                         io_base);
789                 return -1;
790         }
791 
792         phys_dev->base = io_base;
793         phys_dev->irq = irq;
794         phys_dev->devno = -1;
795         virt_dev->devno = -1;
796 
797         return 0;
798 }
799 
800 int __init install_wf_mpu (void)
801 {
802         if ((phys_dev->devno = sound_alloc_mididev()) < 0){
803 
804                 printk (KERN_ERR "WF-MPU: Too many MIDI devices detected.\n");
805                 return -1;
806 
807         }
808 
809         request_region (phys_dev->base, 2, "wavefront midi");
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  
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         save_flags (flags);
863         cli ();
864 
865         /* XXX fix me */
866 
867         for (i = 0; i < 30000 && !output_ready (); i++);
868 
869         outb (UART_MODE_ON, COMDPORT(phys_dev));
870 
871         for (ok = 0, i = 50000; i > 0 && !ok; i--) {
872                 if (input_avail ()) {
873                         if (read_data () == MPU_ACK) {
874                                 ok = 1;
875                         }
876                 }
877         }
878 
879         restore_flags (flags);
880 }
881 #endif
882 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

This page was automatically generated by the LXR engine.
Visit the LXR main site for more information.