Import 2.3.18pre1
[davej-history.git] / drivers / sound / v_midi.c
blobc1d695c99ababfbaea39c00006a2e7b07551d802
1 /*
2 * sound/v_midi.c
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
11 * for more info.
12 * ??
14 * Changes
15 * Alan Cox Modularisation, changed memory allocations
17 * Status
18 * Untested
21 #include <linux/config.h>
22 #include <linux/module.h>
24 #include "sound_config.h"
25 #include "soundmodule.h"
27 #ifdef CONFIG_VMIDI
29 #include "v_midi.h"
31 static vmidi_devc *v_devc[2] = { NULL, NULL};
32 static int midi1,midi2;
33 static void *midi_mem = NULL;
35 #ifdef MODULE
37 static struct address_info config; /* dummy */
39 int init_module(void)
41 printk("MIDI Loopback device driver\n");
42 if (!probe_v_midi(&config))
43 return -ENODEV;
44 attach_v_midi(&config);
45 SOUND_LOCK;
46 return 0;
49 void cleanup_module(void)
51 unload_v_midi(&config);
52 SOUND_LOCK_END;
55 #endif
58 * The DSP channel can be used either for input or output. Variable
59 * 'sb_irq_mode' will be set when the program calls read or write first time
60 * after open. Current version doesn't support mode changes without closing
61 * and reopening the device. Support for this feature may be implemented in a
62 * future version of this driver.
66 void (*midi_input_intr) (int dev, unsigned char data);
68 static int v_midi_open (int dev, int mode,
69 void (*input) (int dev, unsigned char data),
70 void (*output) (int dev)
73 vmidi_devc *devc = midi_devs[dev]->devc;
74 unsigned long flags;
76 if (devc == NULL)
77 return -(ENXIO);
79 save_flags (flags);
80 cli();
81 if (devc->opened)
83 restore_flags (flags);
84 return -(EBUSY);
86 devc->opened = 1;
87 restore_flags (flags);
89 devc->intr_active = 1;
91 if (mode & OPEN_READ)
93 devc->input_opened = 1;
94 devc->midi_input_intr = input;
97 return 0;
100 static void v_midi_close (int dev)
102 vmidi_devc *devc = midi_devs[dev]->devc;
103 unsigned long flags;
105 if (devc == NULL)
106 return;
108 save_flags (flags);
109 cli ();
110 devc->intr_active = 0;
111 devc->input_opened = 0;
112 devc->opened = 0;
113 restore_flags (flags);
116 static int v_midi_out (int dev, unsigned char midi_byte)
118 vmidi_devc *devc = midi_devs[dev]->devc;
119 vmidi_devc *pdevc = midi_devs[devc->pair_mididev]->devc;
121 if (devc == NULL)
122 return -(ENXIO);
124 if (pdevc->input_opened > 0){
125 if (MIDIbuf_avail(pdevc->my_mididev) > 500)
126 return 0;
127 pdevc->midi_input_intr (pdevc->my_mididev, midi_byte);
129 return 1;
132 static int v_midi_start_read (int dev)
134 return 0;
137 static int v_midi_end_read (int dev)
139 vmidi_devc *devc = midi_devs[dev]->devc;
140 if (devc == NULL)
141 return -ENXIO;
143 devc->intr_active = 0;
144 return 0;
147 /* why -EPERM and not -EINVAL?? */
149 static int v_midi_ioctl (int dev, unsigned cmd, caddr_t arg)
151 return -EPERM;
155 #define MIDI_SYNTH_NAME "Loopback MIDI"
156 #define MIDI_SYNTH_CAPS SYNTH_CAP_INPUT
158 #include "midi_synth.h"
160 static struct midi_operations v_midi_operations =
162 {"Loopback MIDI Port 1", 0, 0, SNDCARD_VMIDI},
163 &std_midi_synth,
164 {0},
165 v_midi_open,
166 v_midi_close,
167 v_midi_ioctl,
168 v_midi_out,
169 v_midi_start_read,
170 v_midi_end_read,
171 NULL,
172 NULL,
173 NULL,
174 NULL
177 static struct midi_operations v_midi_operations2 =
179 {"Loopback MIDI Port 2", 0, 0, SNDCARD_VMIDI},
180 &std_midi_synth,
181 {0},
182 v_midi_open,
183 v_midi_close,
184 v_midi_ioctl,
185 v_midi_out,
186 v_midi_start_read,
187 v_midi_end_read,
188 NULL,
189 NULL,
190 NULL,
191 NULL
195 * We kmalloc just one of these - it makes life simpler and the code
196 * cleaner and the memory handling far more efficient
199 struct vmidi_memory
201 /* Must be first */
202 struct midi_operations m_ops[2];
203 struct synth_operations s_ops[2];
204 struct vmidi_devc v_ops[2];
207 void attach_v_midi (struct address_info *hw_config)
209 struct vmidi_memory *m;
210 /* printk("Attaching v_midi device.....\n"); */
212 midi1 = sound_alloc_mididev();
213 if (midi1 == -1)
215 printk(KERN_ERR "v_midi: Too many midi devices detected\n");
216 return;
219 m=(struct vmidi_memory *)kmalloc(sizeof(struct vmidi_memory), GFP_KERNEL);
220 if (m == NULL)
222 printk(KERN_WARNING "Loopback MIDI: Failed to allocate memory\n");
223 sound_unload_mididev(midi1);
224 return;
227 midi_mem = m;
229 midi_devs[midi1] = &m->m_ops[0];
232 midi2 = sound_alloc_mididev();
233 if (midi2 == -1)
235 printk (KERN_ERR "v_midi: Too many midi devices detected\n");
236 kfree(m);
237 sound_unload_mididev(midi1);
238 return;
241 midi_devs[midi2] = &m->m_ops[1];
243 /* printk("VMIDI1: %d VMIDI2: %d\n",midi1,midi2); */
245 /* for MIDI-1 */
246 v_devc[0] = &m->v_ops[0];
247 memcpy ((char *) midi_devs[midi1], (char *) &v_midi_operations,
248 sizeof (struct midi_operations));
250 v_devc[0]->my_mididev = midi1;
251 v_devc[0]->pair_mididev = midi2;
252 v_devc[0]->opened = v_devc[0]->input_opened = 0;
253 v_devc[0]->intr_active = 0;
254 v_devc[0]->midi_input_intr = NULL;
256 midi_devs[midi1]->devc = v_devc[0];
258 midi_devs[midi1]->converter = &m->s_ops[0];
259 std_midi_synth.midi_dev = midi1;
260 memcpy ((char *) midi_devs[midi1]->converter, (char *) &std_midi_synth,
261 sizeof (struct synth_operations));
262 midi_devs[midi1]->converter->id = "V_MIDI 1";
264 /* for MIDI-2 */
265 v_devc[1] = &m->v_ops[1];
267 memcpy ((char *) midi_devs[midi2], (char *) &v_midi_operations2,
268 sizeof (struct midi_operations));
270 v_devc[1]->my_mididev = midi2;
271 v_devc[1]->pair_mididev = midi1;
272 v_devc[1]->opened = v_devc[1]->input_opened = 0;
273 v_devc[1]->intr_active = 0;
274 v_devc[1]->midi_input_intr = NULL;
276 midi_devs[midi2]->devc = v_devc[1];
277 midi_devs[midi2]->converter = &m->s_ops[1];
279 std_midi_synth.midi_dev = midi2;
280 memcpy ((char *) midi_devs[midi2]->converter, (char *) &std_midi_synth,
281 sizeof (struct synth_operations));
282 midi_devs[midi2]->converter->id = "V_MIDI 2";
284 sequencer_init();
285 /* printk("Attached v_midi device\n"); */
288 int probe_v_midi(struct address_info *hw_config)
290 return(1); /* always OK */
294 void unload_v_midi(struct address_info *hw_config)
296 sound_unload_mididev(midi1);
297 sound_unload_mididev(midi2);
298 kfree(midi_mem);
301 #endif