4 * The low level driver for the Sound Blaster DS chips.
7 * Copyright (C) by Hannu Savolainen 1993-1996
9 * USS/Lite for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL)
10 * Version 2 (June 1991). See the "COPYING" file distributed with this software
15 * Alan Cox Modularisation, changed memory allocations
16 * Christoph Hellwig Adapted to module_init/module_exit
22 #include <linux/init.h>
23 #include <linux/module.h>
25 #include "sound_config.h"
29 static vmidi_devc *v_devc[2] = { NULL, NULL};
30 static int midi1,midi2;
31 static void *midi_mem = NULL;
34 * The DSP channel can be used either for input or output. Variable
35 * 'sb_irq_mode' will be set when the program calls read or write first time
36 * after open. Current version doesn't support mode changes without closing
37 * and reopening the device. Support for this feature may be implemented in a
38 * future version of this driver.
42 void (*midi_input_intr) (int dev, unsigned char data);
44 static int v_midi_open (int dev, int mode,
45 void (*input) (int dev, unsigned char data),
46 void (*output) (int dev)
49 vmidi_devc *devc = midi_devs[dev]->devc;
59 restore_flags (flags);
63 restore_flags (flags);
65 devc->intr_active = 1;
69 devc->input_opened = 1;
70 devc->midi_input_intr = input;
76 static void v_midi_close (int dev)
78 vmidi_devc *devc = midi_devs[dev]->devc;
86 devc->intr_active = 0;
87 devc->input_opened = 0;
89 restore_flags (flags);
92 static int v_midi_out (int dev, unsigned char midi_byte)
94 vmidi_devc *devc = midi_devs[dev]->devc;
95 vmidi_devc *pdevc = midi_devs[devc->pair_mididev]->devc;
100 if (pdevc->input_opened > 0){
101 if (MIDIbuf_avail(pdevc->my_mididev) > 500)
103 pdevc->midi_input_intr (pdevc->my_mididev, midi_byte);
108 static inline int v_midi_start_read (int dev)
113 static int v_midi_end_read (int dev)
115 vmidi_devc *devc = midi_devs[dev]->devc;
119 devc->intr_active = 0;
123 /* why -EPERM and not -EINVAL?? */
125 static inline int v_midi_ioctl (int dev, unsigned cmd, caddr_t arg)
131 #define MIDI_SYNTH_NAME "Loopback MIDI"
132 #define MIDI_SYNTH_CAPS SYNTH_CAP_INPUT
134 #include "midi_synth.h"
136 static struct midi_operations v_midi_operations =
139 info: {"Loopback MIDI Port 1", 0, 0, SNDCARD_VMIDI},
140 converter: &std_midi_synth,
146 start_read: v_midi_start_read,
147 end_read: v_midi_end_read,
150 static struct midi_operations v_midi_operations2 =
153 info: {"Loopback MIDI Port 2", 0, 0, SNDCARD_VMIDI},
154 converter: &std_midi_synth,
160 start_read: v_midi_start_read,
161 end_read: v_midi_end_read,
165 * We kmalloc just one of these - it makes life simpler and the code
166 * cleaner and the memory handling far more efficient
172 struct midi_operations m_ops[2];
173 struct synth_operations s_ops[2];
174 struct vmidi_devc v_ops[2];
177 static void __init attach_v_midi (struct address_info *hw_config)
179 struct vmidi_memory *m;
180 /* printk("Attaching v_midi device.....\n"); */
182 midi1 = sound_alloc_mididev();
185 printk(KERN_ERR "v_midi: Too many midi devices detected\n");
189 m=(struct vmidi_memory *)kmalloc(sizeof(struct vmidi_memory), GFP_KERNEL);
192 printk(KERN_WARNING "Loopback MIDI: Failed to allocate memory\n");
193 sound_unload_mididev(midi1);
199 midi_devs[midi1] = &m->m_ops[0];
202 midi2 = sound_alloc_mididev();
205 printk (KERN_ERR "v_midi: Too many midi devices detected\n");
207 sound_unload_mididev(midi1);
211 midi_devs[midi2] = &m->m_ops[1];
213 /* printk("VMIDI1: %d VMIDI2: %d\n",midi1,midi2); */
216 v_devc[0] = &m->v_ops[0];
217 memcpy ((char *) midi_devs[midi1], (char *) &v_midi_operations,
218 sizeof (struct midi_operations));
220 v_devc[0]->my_mididev = midi1;
221 v_devc[0]->pair_mididev = midi2;
222 v_devc[0]->opened = v_devc[0]->input_opened = 0;
223 v_devc[0]->intr_active = 0;
224 v_devc[0]->midi_input_intr = NULL;
226 midi_devs[midi1]->devc = v_devc[0];
228 midi_devs[midi1]->converter = &m->s_ops[0];
229 std_midi_synth.midi_dev = midi1;
230 memcpy ((char *) midi_devs[midi1]->converter, (char *) &std_midi_synth,
231 sizeof (struct synth_operations));
232 midi_devs[midi1]->converter->id = "V_MIDI 1";
235 v_devc[1] = &m->v_ops[1];
237 memcpy ((char *) midi_devs[midi2], (char *) &v_midi_operations2,
238 sizeof (struct midi_operations));
240 v_devc[1]->my_mididev = midi2;
241 v_devc[1]->pair_mididev = midi1;
242 v_devc[1]->opened = v_devc[1]->input_opened = 0;
243 v_devc[1]->intr_active = 0;
244 v_devc[1]->midi_input_intr = NULL;
246 midi_devs[midi2]->devc = v_devc[1];
247 midi_devs[midi2]->converter = &m->s_ops[1];
249 std_midi_synth.midi_dev = midi2;
250 memcpy ((char *) midi_devs[midi2]->converter, (char *) &std_midi_synth,
251 sizeof (struct synth_operations));
252 midi_devs[midi2]->converter->id = "V_MIDI 2";
255 /* printk("Attached v_midi device\n"); */
258 static inline int __init probe_v_midi(struct address_info *hw_config)
260 return(1); /* always OK */
264 static void __exit unload_v_midi(struct address_info *hw_config)
266 sound_unload_mididev(midi1);
267 sound_unload_mididev(midi2);
271 static struct address_info cfg; /* dummy */
273 static int __init init_vmidi(void)
275 printk("MIDI Loopback device driver\n");
276 if (!probe_v_midi(&cfg))
283 static void __exit cleanup_vmidi(void)
288 module_init(init_vmidi);
289 module_exit(cleanup_vmidi);
290 MODULE_LICENSE("GPL");