📄 wf_midi.c
字号:
static voidwf_mpu_close (int dev){ struct wf_mpu_config *devc; if (dev < 0 || dev >= num_midis || midi_devs[dev]==NULL) return; if (phys_dev->devno == dev) { devc = phys_dev; } else if (phys_dev->isvirtual && virt_dev->devno == dev) { devc = virt_dev; } else { printk (KERN_ERR "WF-MPU: unknown device number %d\n", dev); return; } devc->mode = 0; devc->inputintr = NULL; devc->opened = 0;}static intwf_mpu_out (int dev, unsigned char midi_byte){ int timeout; unsigned long flags; static int lastoutdev = -1; unsigned char switchch; if (phys_dev->isvirtual && lastoutdev != dev) { if (dev == phys_dev->devno) { switchch = WF_INTERNAL_SWITCH; } else if (dev == virt_dev->devno) { switchch = WF_EXTERNAL_SWITCH; } else { printk (KERN_ERR "WF-MPU: bad device number %d", dev); return (0); } /* XXX fix me */ for (timeout = 30000; timeout > 0 && !output_ready (); timeout--); save_flags (flags); cli (); if (!output_ready ()) { printk (KERN_WARNING "WF-MPU: Send switch " "byte timeout\n"); restore_flags (flags); return 0; } write_data (switchch); restore_flags (flags); } lastoutdev = dev; /* * Sometimes it takes about 30000 loops before the output becomes ready * (After reset). Normally it takes just about 10 loops. */ /* XXX fix me */ for (timeout = 30000; timeout > 0 && !output_ready (); timeout--); save_flags (flags); cli (); if (!output_ready ()) { printk (KERN_WARNING "WF-MPU: Send data timeout\n"); restore_flags (flags); return 0; } write_data (midi_byte); restore_flags (flags); return 1;}static inline int wf_mpu_start_read (int dev) { return 0;}static inline int wf_mpu_end_read (int dev) { return 0;}static int wf_mpu_ioctl (int dev, unsigned cmd, caddr_t arg){ printk (KERN_WARNING "WF-MPU: Intelligent mode not supported by hardware.\n"); return -(EINVAL);}static int wf_mpu_buffer_status (int dev){ return 0;}static struct synth_operations wf_mpu_synth_operations[2];static struct midi_operations wf_mpu_midi_operations[2];static struct midi_operations wf_mpu_midi_proto ={ owner: THIS_MODULE, info: {"WF-MPU MIDI", 0, MIDI_CAP_MPU401, SNDCARD_MPU401}, in_info: {0}, /* in_info */ open: wf_mpu_open, close: wf_mpu_close, ioctl: wf_mpu_ioctl, outputc: wf_mpu_out, start_read: wf_mpu_start_read, end_read: wf_mpu_end_read, buffer_status: wf_mpu_buffer_status,};static struct synth_info wf_mpu_synth_info_proto ={"WaveFront MPU-401 interface", 0, SYNTH_TYPE_MIDI, MIDI_TYPE_MPU401, 0, 128, 0, 128, SYNTH_CAP_INPUT};static struct synth_info wf_mpu_synth_info[2];static intwf_mpu_synth_ioctl (int dev, unsigned int cmd, caddr_t arg){ int midi_dev; int index; midi_dev = synth_devs[dev]->midi_dev; if (midi_dev < 0 || midi_dev > num_midis || midi_devs[midi_dev]==NULL) return -(ENXIO); if (midi_dev == phys_dev->devno) { index = 0; } else if (phys_dev->isvirtual && midi_dev == virt_dev->devno) { index = 1; } else { return -(EINVAL); } switch (cmd) { case SNDCTL_SYNTH_INFO: if(copy_to_user (&((char *) arg)[0], &wf_mpu_synth_info[index], sizeof (struct synth_info))) return -EFAULT; return 0; case SNDCTL_SYNTH_MEMAVL: return 0x7fffffff; default: return -EINVAL; }}static intwf_mpu_synth_open (int dev, int mode){ int midi_dev; struct wf_mpu_config *devc; midi_dev = synth_devs[dev]->midi_dev; if (midi_dev < 0 || midi_dev > num_midis || midi_devs[midi_dev]==NULL) { return -(ENXIO); } if (phys_dev->devno == midi_dev) { devc = phys_dev; } else if (phys_dev->isvirtual && virt_dev->devno == midi_dev) { devc = virt_dev; } else { printk (KERN_ERR "WF-MPU: unknown device number %d\n", dev); return -(EINVAL); } if (devc->opened) { return -(EBUSY); } devc->mode = MODE_SYNTH; devc->synthno = dev; devc->opened = mode; devc->inputintr = NULL; return 0;}static voidwf_mpu_synth_close (int dev){ int midi_dev; struct wf_mpu_config *devc; midi_dev = synth_devs[dev]->midi_dev; if (phys_dev->devno == midi_dev) { devc = phys_dev; } else if (phys_dev->isvirtual && virt_dev->devno == midi_dev) { devc = virt_dev; } else { printk (KERN_ERR "WF-MPU: unknown device number %d\n", dev); return; } devc->inputintr = NULL; devc->opened = 0; devc->mode = 0;}#define _MIDI_SYNTH_C_#define MIDI_SYNTH_NAME "WaveFront (MIDI)"#define MIDI_SYNTH_CAPS SYNTH_CAP_INPUT#include "midi_synth.h"static struct synth_operations wf_mpu_synth_proto ={ owner: THIS_MODULE, id: "WaveFront (ICS2115)", info: NULL, /* info field, filled in during configuration */ midi_dev: 0, /* MIDI dev XXX should this be -1 ? */ synth_type: SYNTH_TYPE_MIDI, synth_subtype: SAMPLE_TYPE_WAVEFRONT, open: wf_mpu_synth_open, close: wf_mpu_synth_close, ioctl: wf_mpu_synth_ioctl, kill_note: midi_synth_kill_note, start_note: midi_synth_start_note, set_instr: midi_synth_set_instr, reset: midi_synth_reset, hw_control: midi_synth_hw_control, load_patch: midi_synth_load_patch, aftertouch: midi_synth_aftertouch, controller: midi_synth_controller, panning: midi_synth_panning, bender: midi_synth_bender, setup_voice: midi_synth_setup_voice, send_sysex: midi_synth_send_sysex};static intconfig_wf_mpu (struct wf_mpu_config *dev){ int is_external; char *name; int index; if (dev == phys_dev) { name = "WaveFront internal MIDI"; is_external = 0; index = 0; memcpy ((char *) &wf_mpu_synth_operations[index], (char *) &wf_mpu_synth_proto, sizeof (struct synth_operations)); } else { name = "WaveFront external MIDI"; is_external = 1; index = 1; /* no synth operations for an external MIDI interface */ } memcpy ((char *) &wf_mpu_synth_info[dev->devno], (char *) &wf_mpu_synth_info_proto, sizeof (struct synth_info)); strcpy (wf_mpu_synth_info[index].name, name); wf_mpu_synth_operations[index].midi_dev = dev->devno; wf_mpu_synth_operations[index].info = &wf_mpu_synth_info[index]; memcpy ((char *) &wf_mpu_midi_operations[index], (char *) &wf_mpu_midi_proto, sizeof (struct midi_operations)); if (is_external) { wf_mpu_midi_operations[index].converter = NULL; } else { wf_mpu_midi_operations[index].converter = &wf_mpu_synth_operations[index]; } strcpy (wf_mpu_midi_operations[index].info.name, name); midi_devs[dev->devno] = &wf_mpu_midi_operations[index]; midi_devs[dev->devno]->in_info.m_busy = 0; midi_devs[dev->devno]->in_info.m_state = MST_INIT; midi_devs[dev->devno]->in_info.m_ptr = 0; midi_devs[dev->devno]->in_info.m_left = 0; midi_devs[dev->devno]->in_info.m_prev_status = 0; devs[index].opened = 0; devs[index].mode = 0; return (0);}int virtual_midi_enable (void){ if ((virt_dev->devno < 0) && (virt_dev->devno = sound_alloc_mididev()) == -1) { printk (KERN_ERR "WF-MPU: too many midi devices detected\n"); return -1; } config_wf_mpu (virt_dev); phys_dev->isvirtual = 1; return virt_dev->devno;}intvirtual_midi_disable (void){ unsigned long flags; save_flags (flags); cli(); wf_mpu_close (virt_dev->devno); /* no synth on virt_dev, so no need to call wf_mpu_synth_close() */ phys_dev->isvirtual = 0; restore_flags (flags); return 0;}int __init detect_wf_mpu (int irq, int io_base){ if (check_region (io_base, 2)) { printk (KERN_WARNING "WF-MPU: I/O port %x already in use.\n", io_base); return -1; } phys_dev->base = io_base; phys_dev->irq = irq; phys_dev->devno = -1; virt_dev->devno = -1; return 0;}int __init install_wf_mpu (void){ if ((phys_dev->devno = sound_alloc_mididev()) < 0){ printk (KERN_ERR "WF-MPU: Too many MIDI devices detected.\n"); return -1; } request_region (phys_dev->base, 2, "wavefront midi"); phys_dev->isvirtual = 0; if (config_wf_mpu (phys_dev)) { printk (KERN_WARNING "WF-MPU: configuration for MIDI device %d failed\n", phys_dev->devno); sound_unload_mididev (phys_dev->devno); } /* OK, now we're configured to handle an interrupt ... */ if (request_irq (phys_dev->irq, wf_mpuintr, SA_INTERRUPT|SA_SHIRQ, "wavefront midi", phys_dev) < 0) { printk (KERN_ERR "WF-MPU: Failed to allocate IRQ%d\n", phys_dev->irq); return -1; } /* This being a WaveFront (ICS-2115) emulated MPU-401, we have to switch it into UART (dumb) mode, because otherwise, it won't do anything at all. */ start_uart_mode (); return phys_dev->devno;} voiduninstall_wf_mpu (void){ release_region (phys_dev->base, 2); free_irq (phys_dev->irq, phys_dev); sound_unload_mididev (phys_dev->devno); if (virt_dev->devno >= 0) { sound_unload_mididev (virt_dev->devno); }}static voidstart_uart_mode (void){ int ok, i; unsigned long flags; save_flags (flags); cli (); /* XXX fix me */ for (i = 0; i < 30000 && !output_ready (); i++); outb (UART_MODE_ON, COMDPORT(phys_dev)); for (ok = 0, i = 50000; i > 0 && !ok; i--) { if (input_avail ()) { if (read_data () == MPU_ACK) { ok = 1; } } } restore_flags (flags);}#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -