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>
24 #include <linux/spinlock.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
;
55 spin_lock_irqsave(&devc
->lock
,flags
);
58 spin_unlock_irqrestore(&devc
->lock
,flags
);
62 spin_unlock_irqrestore(&devc
->lock
,flags
);
64 devc
->intr_active
= 1;
68 devc
->input_opened
= 1;
69 devc
->midi_input_intr
= input
;
75 static void v_midi_close (int dev
)
77 vmidi_devc
*devc
= midi_devs
[dev
]->devc
;
83 spin_lock_irqsave(&devc
->lock
,flags
);
84 devc
->intr_active
= 0;
85 devc
->input_opened
= 0;
87 spin_unlock_irqrestore(&devc
->lock
,flags
);
90 static int v_midi_out (int dev
, unsigned char midi_byte
)
92 vmidi_devc
*devc
= midi_devs
[dev
]->devc
;
98 pdevc
= midi_devs
[devc
->pair_mididev
]->devc
;
99 if (pdevc
->input_opened
> 0){
100 if (MIDIbuf_avail(pdevc
->my_mididev
) > 500)
102 pdevc
->midi_input_intr (pdevc
->my_mididev
, midi_byte
);
107 static inline int v_midi_start_read (int dev
)
112 static int v_midi_end_read (int dev
)
114 vmidi_devc
*devc
= midi_devs
[dev
]->devc
;
118 devc
->intr_active
= 0;
122 /* why -EPERM and not -EINVAL?? */
124 static inline int v_midi_ioctl (int dev
, unsigned cmd
, void __user
*arg
)
130 #define MIDI_SYNTH_NAME "Loopback MIDI"
131 #define MIDI_SYNTH_CAPS SYNTH_CAP_INPUT
133 #include "midi_synth.h"
135 static struct midi_operations v_midi_operations
=
137 .owner
= THIS_MODULE
,
138 .info
= {"Loopback MIDI Port 1", 0, 0, SNDCARD_VMIDI
},
139 .converter
= &std_midi_synth
,
142 .close
= v_midi_close
,
143 .ioctl
= v_midi_ioctl
,
144 .outputc
= v_midi_out
,
145 .start_read
= v_midi_start_read
,
146 .end_read
= v_midi_end_read
,
149 static struct midi_operations v_midi_operations2
=
151 .owner
= THIS_MODULE
,
152 .info
= {"Loopback MIDI Port 2", 0, 0, SNDCARD_VMIDI
},
153 .converter
= &std_midi_synth
,
156 .close
= v_midi_close
,
157 .ioctl
= v_midi_ioctl
,
158 .outputc
= v_midi_out
,
159 .start_read
= v_midi_start_read
,
160 .end_read
= v_midi_end_read
,
164 * We kmalloc just one of these - it makes life simpler and the code
165 * cleaner and the memory handling far more efficient
171 struct midi_operations m_ops
[2];
172 struct synth_operations s_ops
[2];
173 struct vmidi_devc v_ops
[2];
176 static void __init
attach_v_midi (struct address_info
*hw_config
)
178 struct vmidi_memory
*m
;
179 /* printk("Attaching v_midi device.....\n"); */
181 midi1
= sound_alloc_mididev();
184 printk(KERN_ERR
"v_midi: Too many midi devices detected\n");
188 m
=(struct vmidi_memory
*)kmalloc(sizeof(struct vmidi_memory
), GFP_KERNEL
);
191 printk(KERN_WARNING
"Loopback MIDI: Failed to allocate memory\n");
192 sound_unload_mididev(midi1
);
198 midi_devs
[midi1
] = &m
->m_ops
[0];
201 midi2
= sound_alloc_mididev();
204 printk (KERN_ERR
"v_midi: Too many midi devices detected\n");
206 sound_unload_mididev(midi1
);
210 midi_devs
[midi2
] = &m
->m_ops
[1];
212 /* printk("VMIDI1: %d VMIDI2: %d\n",midi1,midi2); */
215 v_devc
[0] = &m
->v_ops
[0];
216 memcpy ((char *) midi_devs
[midi1
], (char *) &v_midi_operations
,
217 sizeof (struct midi_operations
));
219 v_devc
[0]->my_mididev
= midi1
;
220 v_devc
[0]->pair_mididev
= midi2
;
221 v_devc
[0]->opened
= v_devc
[0]->input_opened
= 0;
222 v_devc
[0]->intr_active
= 0;
223 v_devc
[0]->midi_input_intr
= NULL
;
224 spin_lock_init(&v_devc
[0]->lock
);
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
;
245 spin_lock_init(&v_devc
[1]->lock
);
247 midi_devs
[midi2
]->devc
= v_devc
[1];
248 midi_devs
[midi2
]->converter
= &m
->s_ops
[1];
250 std_midi_synth
.midi_dev
= midi2
;
251 memcpy ((char *) midi_devs
[midi2
]->converter
, (char *) &std_midi_synth
,
252 sizeof (struct synth_operations
));
253 midi_devs
[midi2
]->converter
->id
= "V_MIDI 2";
256 /* printk("Attached v_midi device\n"); */
259 static inline int __init
probe_v_midi(struct address_info
*hw_config
)
261 return(1); /* always OK */
265 static void __exit
unload_v_midi(struct address_info
*hw_config
)
267 sound_unload_mididev(midi1
);
268 sound_unload_mididev(midi2
);
272 static struct address_info cfg
; /* dummy */
274 static int __init
init_vmidi(void)
276 printk("MIDI Loopback device driver\n");
277 if (!probe_v_midi(&cfg
))
284 static void __exit
cleanup_vmidi(void)
289 module_init(init_vmidi
);
290 module_exit(cleanup_vmidi
);
291 MODULE_LICENSE("GPL");