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
21 #include <linux/config.h>
22 #include <linux/module.h>
24 #include "sound_config.h"
25 #include "soundmodule.h"
31 static vmidi_devc
*v_devc
[2] = { NULL
, NULL
};
32 static int midi1
,midi2
;
33 static void *midi_mem
= NULL
;
37 static struct address_info config
; /* dummy */
41 printk("MIDI Loopback device driver\n");
42 if (!probe_v_midi(&config
))
44 attach_v_midi(&config
);
49 void cleanup_module(void)
51 unload_v_midi(&config
);
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
;
83 restore_flags (flags
);
87 restore_flags (flags
);
89 devc
->intr_active
= 1;
93 devc
->input_opened
= 1;
94 devc
->midi_input_intr
= input
;
100 static void v_midi_close (int dev
)
102 vmidi_devc
*devc
= midi_devs
[dev
]->devc
;
110 devc
->intr_active
= 0;
111 devc
->input_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
;
124 if (pdevc
->input_opened
> 0){
125 if (MIDIbuf_avail(pdevc
->my_mididev
) > 500)
127 pdevc
->midi_input_intr (pdevc
->my_mididev
, midi_byte
);
132 static int v_midi_start_read (int dev
)
137 static int v_midi_end_read (int dev
)
139 vmidi_devc
*devc
= midi_devs
[dev
]->devc
;
143 devc
->intr_active
= 0;
147 /* why -EPERM and not -EINVAL?? */
149 static int v_midi_ioctl (int dev
, unsigned cmd
, caddr_t arg
)
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
},
177 static struct midi_operations v_midi_operations2
=
179 {"Loopback MIDI Port 2", 0, 0, SNDCARD_VMIDI
},
195 * We kmalloc just one of these - it makes life simpler and the code
196 * cleaner and the memory handling far more efficient
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();
215 printk(KERN_ERR
"v_midi: Too many midi devices detected\n");
219 m
=(struct vmidi_memory
*)kmalloc(sizeof(struct vmidi_memory
), GFP_KERNEL
);
222 printk(KERN_WARNING
"Loopback MIDI: Failed to allocate memory\n");
223 sound_unload_mididev(midi1
);
229 midi_devs
[midi1
] = &m
->m_ops
[0];
232 midi2
= sound_alloc_mididev();
235 printk (KERN_ERR
"v_midi: Too many midi devices detected\n");
237 sound_unload_mididev(midi1
);
241 midi_devs
[midi2
] = &m
->m_ops
[1];
243 /* printk("VMIDI1: %d VMIDI2: %d\n",midi1,midi2); */
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";
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";
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
);