xref: /dflybsd-src/sys/dev/sound/midi/midi.c (revision 36e53ac29fb7ac9bf9a321b34497acbcce2f1141)
1 /*-
2  * Copyright (c) 2003 Mathew Kanner
3  * Copyright (c) 1998 The NetBSD Foundation, Inc.
4  * All rights reserved.
5  *
6  * This code is derived from software contributed to The NetBSD Foundation
7  * by Lennart Augustsson (augustss@netbsd.org).
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions
11  * are met:
12  * 1. Redistributions of source code must retain the above copyright
13  *    notice, this list of conditions and the following disclaimer.
14  * 2. Redistributions in binary form must reproduce the above copyright
15  *    notice, this list of conditions and the following disclaimer in the
16  *    documentation and/or other materials provided with the distribution.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
19  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
20  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
21  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
22  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28  * POSSIBILITY OF SUCH DAMAGE.
29  */
30 
31  /*
32   * Parts of this file started out as NetBSD: midi.c 1.31
33   * They are mostly gone.  Still the most obvious will be the state
34   * machine midi_in
35   */
36 
37 #include <sys/cdefs.h>
38 __FBSDID("$FreeBSD: head/sys/dev/sound/midi/midi.c 227309 2011-11-07 15:43:11Z ed $");
39 
40 #include <sys/param.h>
41 #include <sys/queue.h>
42 #include <sys/kernel.h>
43 #include <sys/lock.h>
44 #include <sys/mutex.h>
45 #include <sys/proc.h>
46 #include <sys/signalvar.h>
47 #include <sys/conf.h>
48 #include <sys/sysctl.h>
49 #include <sys/types.h>
50 #include <sys/malloc.h>
51 #include <sys/systm.h>
52 #include <sys/fcntl.h>
53 #include <sys/uio.h>
54 #include <sys/poll.h>
55 #include <sys/sbuf.h>
56 #include <sys/kobj.h>
57 #include <sys/module.h>
58 #include <sys/device.h>
59 
60 #ifdef HAVE_KERNEL_OPTION_HEADERS
61 #include "opt_snd.h"
62 #endif
63 
64 #include <dev/sound/midi/midi.h>
65 #include "mpu_if.h"
66 
67 #include <dev/sound/midi/midiq.h>
68 #include "synth_if.h"
69 MALLOC_DEFINE(M_MIDI, "midi buffers", "Midi data allocation area");
70 
71 #ifndef KOBJMETHOD_END
72 #define KOBJMETHOD_END	{ NULL, NULL }
73 #endif
74 
75 #define PCMMKMINOR(u, d, c) ((((c) & 0xff) << 16) | (((u) & 0x0f) << 4) | ((d) & 0x0f))
76 #define MIDIMKMINOR(u, d, c) PCMMKMINOR(u, d, c)
77 
78 #define MIDI_DEV_RAW	2
79 #define MIDI_DEV_MIDICTL 12
80 
81 enum midi_states {
82 	MIDI_IN_START, MIDI_IN_SYSEX, MIDI_IN_DATA
83 };
84 
85 /*
86  * The MPU interface current has init() uninit() inqsize(( outqsize()
87  * callback() : fiddle with the tx|rx status.
88  */
89 
90 #include "mpu_if.h"
91 
92 /*
93  * /dev/rmidi	Structure definitions
94  */
95 
96 #define MIDI_NAMELEN   16
97 struct snd_midi {
98 	KOBJ_FIELDS;
99 	struct lock lock;		/* Protects all but queues */
100 	void   *cookie;
101 
102 	int	unit;			/* Should only be used in midistat */
103 	int	channel;		/* Should only be used in midistat */
104 
105 	int	busy;
106 	int	flags;			/* File flags */
107 	char	name[MIDI_NAMELEN];
108 	struct lock qlock;		/* Protects inq, outq and flags */
109 	MIDIQ_HEAD(, char) inq, outq;
110 	int	rchan, wchan;
111 	struct kqinfo rkq, wkq;
112 	int	hiwat;			/* QLEN(outq)>High-water -> disable
113 					 * writes from userland */
114 	enum midi_states inq_state;
115 	int	inq_status, inq_left;	/* Variables for the state machine in
116 					 * Midi_in, this is to provide that
117 					 * signals only get issued only
118 					 * complete command packets. */
119 	struct proc *async;
120 	struct cdev *dev;
121 	struct synth_midi *synth;
122 	int	synth_flags;
123 	TAILQ_ENTRY(snd_midi) link;
124 };
125 
126 struct synth_midi {
127 	KOBJ_FIELDS;
128 	struct snd_midi *m;
129 };
130 
131 static synth_open_t midisynth_open;
132 static synth_close_t midisynth_close;
133 static synth_writeraw_t midisynth_writeraw;
134 static synth_killnote_t midisynth_killnote;
135 static synth_startnote_t midisynth_startnote;
136 static synth_setinstr_t midisynth_setinstr;
137 static synth_alloc_t midisynth_alloc;
138 static synth_controller_t midisynth_controller;
139 static synth_bender_t midisynth_bender;
140 
141 
142 static kobj_method_t midisynth_methods[] = {
143 	KOBJMETHOD(synth_open, midisynth_open),
144 	KOBJMETHOD(synth_close, midisynth_close),
145 	KOBJMETHOD(synth_writeraw, midisynth_writeraw),
146 	KOBJMETHOD(synth_setinstr, midisynth_setinstr),
147 	KOBJMETHOD(synth_startnote, midisynth_startnote),
148 	KOBJMETHOD(synth_killnote, midisynth_killnote),
149 	KOBJMETHOD(synth_alloc, midisynth_alloc),
150 	KOBJMETHOD(synth_controller, midisynth_controller),
151 	KOBJMETHOD(synth_bender, midisynth_bender),
152 	KOBJMETHOD_END
153 };
154 
155 DEFINE_CLASS(midisynth, midisynth_methods, 0);
156 
157 /*
158  * Module Exports & Interface
159  *
160  * struct midi_chan *midi_init(MPU_CLASS cls, int unit, int chan) int
161  * midi_uninit(struct snd_midi *) 0 == no error EBUSY or other error int
162  * Midi_in(struct midi_chan *, char *buf, int count) int Midi_out(struct
163  * midi_chan *, char *buf, int count)
164  *
165  * midi_{in,out} return actual size transfered
166  *
167  */
168 
169 
170 /*
171  * midi_devs tailq, holder of all rmidi instances protected by midistat_lock
172  */
173 
174 TAILQ_HEAD(, snd_midi) midi_devs;
175 
176 /*
177  * /dev/midistat variables and declarations, protected by midistat_lock
178  */
179 
180 static struct lock midistat_lock;
181 static int      midistat_isopen = 0;
182 static struct sbuf midistat_sbuf;
183 static int      midistat_bufptr;
184 static struct cdev *midistat_dev;
185 
186 /*
187  * /dev/midistat	dev_t declarations
188  */
189 
190 static d_open_t midistat_open;
191 static d_close_t midistat_close;
192 static d_read_t midistat_read;
193 
194 static void	midi_filter_detach(struct knote *);
195 static int	midi_filter_read(struct knote *, long);
196 static int	midi_filter_write(struct knote *, long);
197 
198 static struct dev_ops midistat_ops = {
199 	{ "midistat", 0, D_MPSAFE },
200 	.d_open = midistat_open,
201 	.d_close = midistat_close,
202 	.d_read = midistat_read,
203 };
204 
205 static struct filterops midi_read_filterops =
206 	{ FILTEROP_ISFD, NULL, midi_filter_detach, midi_filter_read };
207 static struct filterops midi_write_filterops =
208 	{ FILTEROP_ISFD, NULL, midi_filter_detach, midi_filter_write };
209 
210 /*
211  * /dev/rmidi dev_t declarations, struct variable access is protected by
212  * locks contained within the structure.
213  */
214 
215 static d_open_t midi_open;
216 static d_close_t midi_close;
217 static d_ioctl_t midi_ioctl;
218 static d_read_t midi_read;
219 static d_write_t midi_write;
220 static d_kqfilter_t midi_kqfilter;
221 
222 static struct dev_ops midi_ops = {
223 	{ "rmidi", 0, D_MPSAFE },
224 	.d_open = midi_open,
225 	.d_close = midi_close,
226 	.d_read = midi_read,
227 	.d_write = midi_write,
228 	.d_ioctl = midi_ioctl,
229 	.d_kqfilter = midi_kqfilter,
230 };
231 
232 /*
233  * Prototypes of library functions
234  */
235 
236 static int      midi_destroy(struct snd_midi *, int);
237 static int      midistat_prepare(struct sbuf * s);
238 static int      midi_load(void);
239 static int      midi_unload(void);
240 
241 /*
242  * Misc declr.
243  */
244 SYSCTL_NODE(_hw, OID_AUTO, midi, CTLFLAG_RD, 0, "Midi driver");
245 static SYSCTL_NODE(_hw_midi, OID_AUTO, stat, CTLFLAG_RD, 0, "Status device");
246 
247 int             midi_debug;
248 /* XXX: should this be moved into debug.midi? */
249 SYSCTL_INT(_hw_midi, OID_AUTO, debug, CTLFLAG_RW, &midi_debug, 0, "");
250 
251 int             midi_dumpraw;
252 SYSCTL_INT(_hw_midi, OID_AUTO, dumpraw, CTLFLAG_RW, &midi_dumpraw, 0, "");
253 
254 int             midi_instroff;
255 SYSCTL_INT(_hw_midi, OID_AUTO, instroff, CTLFLAG_RW, &midi_instroff, 0, "");
256 
257 int             midistat_verbose;
258 SYSCTL_INT(_hw_midi_stat, OID_AUTO, verbose, CTLFLAG_RW,
259 	&midistat_verbose, 0, "");
260 
261 #define MIDI_DEBUG(l,a)	if(midi_debug>=l) a
262 /*
263  * CODE START
264  */
265 
266 /*
267  * Register a new rmidi device. cls midi_if interface unit == 0 means
268  * auto-assign new unit number unit != 0 already assigned a unit number, eg.
269  * not the first channel provided by this device. channel,	sub-unit
270  * cookie is passed back on MPU calls Typical device drivers will call with
271  * unit=0, channel=1..(number of channels) and cookie=soft_c and won't care
272  * what unit number is used.
273  *
274  * It is an error to call midi_init with an already used unit/channel combo.
275  *
276  * Returns NULL on error
277  *
278  */
279 struct snd_midi *
280 midi_init(kobj_class_t cls, int unit, int channel, void *cookie)
281 {
282 	struct snd_midi *m;
283 	int i;
284 	int inqsize, outqsize;
285 	MIDI_TYPE *buf;
286 
287 	MIDI_DEBUG(1, kprintf("midiinit: unit %d/%d.\n", unit, channel));
288 	lockmgr(&midistat_lock, LK_EXCLUSIVE);
289 	/*
290 	 * Protect against call with existing unit/channel or auto-allocate a
291 	 * new unit number.
292 	 */
293 	i = -1;
294 	TAILQ_FOREACH(m, &midi_devs, link) {
295 		lockmgr(&m->lock, LK_EXCLUSIVE);
296 		if (unit != 0) {
297 			if (m->unit == unit && m->channel == channel) {
298 				lockmgr(&m->lock, LK_RELEASE);
299 				goto err0;
300 			}
301 		} else {
302 			/*
303 			 * Find a better unit number
304 			 */
305 			if (m->unit > i)
306 				i = m->unit;
307 		}
308 		lockmgr(&m->lock, LK_RELEASE);
309 	}
310 
311 	if (unit == 0)
312 		unit = i + 1;
313 
314 	MIDI_DEBUG(1, kprintf("midiinit #2: unit %d/%d.\n", unit, channel));
315 	m = kmalloc(sizeof(*m), M_MIDI, M_WAITOK | M_ZERO);
316 
317 	m->synth = kmalloc(sizeof(*m->synth), M_MIDI, M_WAITOK | M_ZERO);
318 	kobj_init((kobj_t)m->synth, &midisynth_class);
319 	m->synth->m = m;
320 	kobj_init((kobj_t)m, cls);
321 	inqsize = MPU_INQSIZE(m, cookie);
322 	outqsize = MPU_OUTQSIZE(m, cookie);
323 
324 	MIDI_DEBUG(1, kprintf("midiinit queues %d/%d.\n", inqsize, outqsize));
325 	if (!inqsize && !outqsize)
326 		goto err1;
327 
328 	lockinit(&m->lock, "raw midi", 0, LK_CANRECURSE);
329 	lockinit(&m->qlock, "q raw midi", 0, LK_CANRECURSE);
330 
331 	lockmgr(&m->lock, LK_EXCLUSIVE);
332 	lockmgr(&m->qlock, LK_EXCLUSIVE);
333 
334 	if (inqsize)
335 		buf = kmalloc(sizeof(MIDI_TYPE) * inqsize, M_MIDI, M_WAITOK);
336 	else
337 		buf = NULL;
338 
339 	MIDIQ_INIT(m->inq, buf, inqsize);
340 
341 	if (outqsize)
342 		buf = kmalloc(sizeof(MIDI_TYPE) * outqsize, M_MIDI, M_WAITOK);
343 	else
344 		buf = NULL;
345 	m->hiwat = outqsize / 2;
346 
347 	MIDIQ_INIT(m->outq, buf, outqsize);
348 
349 	if ((inqsize && !MIDIQ_BUF(m->inq)) ||
350 	    (outqsize && !MIDIQ_BUF(m->outq)))
351 		goto err2;
352 
353 
354 	m->busy = 0;
355 	m->flags = 0;
356 	m->unit = unit;
357 	m->channel = channel;
358 	m->cookie = cookie;
359 
360 	if (MPU_INIT(m, cookie))
361 		goto err2;
362 
363 	lockmgr(&m->lock, LK_RELEASE);
364 	lockmgr(&m->qlock, LK_RELEASE);
365 
366 	TAILQ_INSERT_TAIL(&midi_devs, m, link);
367 
368 	lockmgr(&midistat_lock, LK_RELEASE);
369 
370 	m->dev = make_dev(&midi_ops,
371 	    MIDIMKMINOR(unit, MIDI_DEV_RAW, channel),
372 	    UID_ROOT, GID_WHEEL, 0666, "midi%d.%d", unit, channel);
373 	m->dev->si_drv1 = m;
374 
375 	return m;
376 
377 err2:	lockuninit(&m->qlock);
378 	lockuninit(&m->lock);
379 
380 	if (MIDIQ_BUF(m->inq))
381 		kfree(MIDIQ_BUF(m->inq), M_MIDI);
382 	if (MIDIQ_BUF(m->outq))
383 		kfree(MIDIQ_BUF(m->outq), M_MIDI);
384 err1:	kfree(m, M_MIDI);
385 err0:	lockmgr(&midistat_lock, LK_RELEASE);
386 	MIDI_DEBUG(1, kprintf("midi_init ended in error\n"));
387 	return NULL;
388 }
389 
390 /*
391  * midi_uninit does not call MIDI_UNINIT, as since this is the implementors
392  * entry point. midi_unint if fact, does not send any methods. A call to
393  * midi_uninit is a defacto promise that you won't manipulate ch anymore
394  *
395  */
396 
397 int
398 midi_uninit(struct snd_midi *m)
399 {
400 	int err;
401 
402 	err = ENXIO;
403 	lockmgr(&midistat_lock, LK_EXCLUSIVE);
404 	lockmgr(&m->lock, LK_EXCLUSIVE);
405 	if (m->busy) {
406 		if (!(m->rchan || m->wchan))
407 			goto err;
408 
409 		if (m->rchan) {
410 			wakeup(&m->rchan);
411 			m->rchan = 0;
412 		}
413 		if (m->wchan) {
414 			wakeup(&m->wchan);
415 			m->wchan = 0;
416 		}
417 	}
418 	err = midi_destroy(m, 0);
419 	if (!err)
420 		goto exit;
421 
422 err:	lockmgr(&m->lock, LK_RELEASE);
423 exit:	lockmgr(&midistat_lock, LK_RELEASE);
424 	return err;
425 }
426 
427 /*
428  * midi_in: process all data until the queue is full, then discards the rest.
429  * Since midi_in is a state machine, data discards can cause it to get out of
430  * whack.  Process as much as possible.  It calls, wakeup, selnotify and
431  * psignal at most once.
432  */
433 
434 #ifdef notdef
435 static int midi_lengths[] = {2, 2, 2, 2, 1, 1, 2, 0};
436 
437 #endif					/* notdef */
438 /* Number of bytes in a MIDI command */
439 #define MIDI_LENGTH(d) (midi_lengths[((d) >> 4) & 7])
440 #define MIDI_ACK	0xfe
441 #define MIDI_IS_STATUS(d) ((d) >= 0x80)
442 #define MIDI_IS_COMMON(d) ((d) >= 0xf0)
443 
444 #define MIDI_SYSEX_START	0xF0
445 #define MIDI_SYSEX_END	    0xF7
446 
447 
448 int
449 midi_in(struct snd_midi *m, MIDI_TYPE *buf, int size)
450 {
451 	/* int             i, sig, enq; */
452 	int used;
453 
454 	/* MIDI_TYPE       data; */
455 	MIDI_DEBUG(5, kprintf("midi_in: m=%p size=%d\n", m, size));
456 
457 /*
458  * XXX: locking flub
459  */
460 	if (!(m->flags & M_RX))
461 		return size;
462 
463 	used = 0;
464 
465 	lockmgr(&m->qlock, LK_EXCLUSIVE);
466 #if 0
467 	/*
468 	 * Don't bother queuing if not in read mode.  Discard everything and
469 	 * return size so the caller doesn't freak out.
470 	 */
471 
472 	if (!(m->flags & M_RX))
473 		return size;
474 
475 	for (i = sig = 0; i < size; i++) {
476 
477 		data = buf[i];
478 		enq = 0;
479 		if (data == MIDI_ACK)
480 			continue;
481 
482 		switch (m->inq_state) {
483 		case MIDI_IN_START:
484 			if (MIDI_IS_STATUS(data)) {
485 				switch (data) {
486 				case 0xf0:	/* Sysex */
487 					m->inq_state = MIDI_IN_SYSEX;
488 					break;
489 				case 0xf1:	/* MTC quarter frame */
490 				case 0xf3:	/* Song select */
491 					m->inq_state = MIDI_IN_DATA;
492 					enq = 1;
493 					m->inq_left = 1;
494 					break;
495 				case 0xf2:	/* Song position pointer */
496 					m->inq_state = MIDI_IN_DATA;
497 					enq = 1;
498 					m->inq_left = 2;
499 					break;
500 				default:
501 					if (MIDI_IS_COMMON(data)) {
502 						enq = 1;
503 						sig = 1;
504 					} else {
505 						m->inq_state = MIDI_IN_DATA;
506 						enq = 1;
507 						m->inq_status = data;
508 						m->inq_left = MIDI_LENGTH(data);
509 					}
510 					break;
511 				}
512 			} else if (MIDI_IS_STATUS(m->inq_status)) {
513 				m->inq_state = MIDI_IN_DATA;
514 				if (!MIDIQ_FULL(m->inq)) {
515 					used++;
516 					MIDIQ_ENQ(m->inq, &m->inq_status, 1);
517 				}
518 				enq = 1;
519 				m->inq_left = MIDI_LENGTH(m->inq_status) - 1;
520 			}
521 			break;
522 			/*
523 			 * End of case MIDI_IN_START:
524 			 */
525 
526 		case MIDI_IN_DATA:
527 			enq = 1;
528 			if (--m->inq_left <= 0)
529 				sig = 1;/* deliver data */
530 			break;
531 		case MIDI_IN_SYSEX:
532 			if (data == MIDI_SYSEX_END)
533 				m->inq_state = MIDI_IN_START;
534 			break;
535 		}
536 
537 		if (enq)
538 			if (!MIDIQ_FULL(m->inq)) {
539 				MIDIQ_ENQ(m->inq, &data, 1);
540 				used++;
541 			}
542 		/*
543 	         * End of the state machines main "for loop"
544 	         */
545 	}
546 	if (sig) {
547 #endif
548 		MIDI_DEBUG(6, kprintf("midi_in: len %jd avail %jd\n",
549 		    (intmax_t)MIDIQ_LEN(m->inq),
550 		    (intmax_t)MIDIQ_AVAIL(m->inq)));
551 		if (MIDIQ_AVAIL(m->inq) > size) {
552 			used = size;
553 			MIDIQ_ENQ(m->inq, buf, size);
554 		} else {
555 			MIDI_DEBUG(4, kprintf("midi_in: Discarding data qu\n"));
556 			lockmgr(&m->qlock, LK_RELEASE);
557 			return 0;
558 		}
559 		if (m->rchan) {
560 			wakeup(&m->rchan);
561 			m->rchan = 0;
562 		}
563 		KNOTE(&m->rkq.ki_note, 0);
564 		if (m->async) {
565 			PHOLD(m->async);
566 			ksignal(m->async, SIGIO);
567 			PRELE(m->async);
568 		}
569 #if 0
570 	}
571 #endif
572 	lockmgr(&m->qlock, LK_RELEASE);
573 	return used;
574 }
575 
576 /*
577  * midi_out: The only clearer of the M_TXEN flag.
578  */
579 int
580 midi_out(struct snd_midi *m, MIDI_TYPE *buf, int size)
581 {
582 	int used;
583 
584 /*
585  * XXX: locking flub
586  */
587 	if (!(m->flags & M_TXEN))
588 		return 0;
589 
590 	MIDI_DEBUG(2, kprintf("midi_out: %p\n", m));
591 	lockmgr(&m->qlock, LK_EXCLUSIVE);
592 	used = MIN(size, MIDIQ_LEN(m->outq));
593 	MIDI_DEBUG(3, kprintf("midi_out: used %d\n", used));
594 	if (used)
595 		MIDIQ_DEQ(m->outq, buf, used);
596 	if (MIDIQ_EMPTY(m->outq)) {
597 		m->flags &= ~M_TXEN;
598 		MPU_CALLBACKP(m, m->cookie, m->flags);
599 	}
600 	if (used && MIDIQ_AVAIL(m->outq) > m->hiwat) {
601 		if (m->wchan) {
602 			wakeup(&m->wchan);
603 			m->wchan = 0;
604 		}
605 		KNOTE(&m->wkq.ki_note, 0);
606 		if (m->async) {
607 			PHOLD(m->async);
608 			ksignal(m->async, SIGIO);
609 			PRELE(m->async);
610 		}
611 	}
612 	lockmgr(&m->qlock, LK_RELEASE);
613 	return used;
614 }
615 
616 
617 /*
618  * /dev/rmidi#.#	device access functions
619  */
620 int
621 midi_open(struct dev_open_args *ap)
622 {
623 	cdev_t i_dev = ap->a_head.a_dev;
624 	int flags = ap->a_oflags;
625 	struct snd_midi *m = i_dev->si_drv1;
626 	int retval;
627 
628 #if 0 /* XXX */
629 	MIDI_DEBUG(1, kprintf("midiopen %p %s %s\n", td,
630 	    flags & FREAD ? "M_RX" : "", flags & FWRITE ? "M_TX" : ""));
631 #endif
632 	if (m == NULL)
633 		return ENXIO;
634 
635 	lockmgr(&m->lock, LK_EXCLUSIVE);
636 	lockmgr(&m->qlock, LK_EXCLUSIVE);
637 
638 	retval = 0;
639 
640 	if (flags & FREAD) {
641 		if (MIDIQ_SIZE(m->inq) == 0)
642 			retval = ENXIO;
643 		else if (m->flags & M_RX)
644 			retval = EBUSY;
645 		if (retval)
646 			goto err;
647 	}
648 	if (flags & FWRITE) {
649 		if (MIDIQ_SIZE(m->outq) == 0)
650 			retval = ENXIO;
651 		else if (m->flags & M_TX)
652 			retval = EBUSY;
653 		if (retval)
654 			goto err;
655 	}
656 	m->busy++;
657 
658 	m->rchan = 0;
659 	m->wchan = 0;
660 	m->async = 0;
661 
662 	if (flags & FREAD) {
663 		m->flags |= M_RX | M_RXEN;
664 		/*
665 	         * Only clear the inq, the outq might still have data to drain
666 	         * from a previous session
667 	         */
668 		MIDIQ_CLEAR(m->inq);
669 	};
670 
671 	if (flags & FWRITE)
672 		m->flags |= M_TX;
673 
674 	MPU_CALLBACK(m, m->cookie, m->flags);
675 
676 	MIDI_DEBUG(2, kprintf("midi_open: opened.\n"));
677 
678 err:	lockmgr(&m->qlock, LK_RELEASE);
679 	lockmgr(&m->lock, LK_RELEASE);
680 	return retval;
681 }
682 
683 int
684 midi_close(struct dev_close_args *ap)
685 {
686 	cdev_t i_dev = ap->a_head.a_dev;
687 	int flags = ap->a_fflag;
688 	struct snd_midi *m = i_dev->si_drv1;
689 	int retval;
690 	int oldflags;
691 
692 #if 0 /* XXX */
693 	MIDI_DEBUG(1, kprintf("midi_close %p %s %s\n", td,
694 	    flags & FREAD ? "M_RX" : "", flags & FWRITE ? "M_TX" : ""));
695 #endif
696 
697 	if (m == NULL)
698 		return ENXIO;
699 
700 	lockmgr(&m->lock, LK_EXCLUSIVE);
701 	lockmgr(&m->qlock, LK_EXCLUSIVE);
702 
703 	if ((flags & FREAD && !(m->flags & M_RX)) ||
704 	    (flags & FWRITE && !(m->flags & M_TX))) {
705 		retval = ENXIO;
706 		goto err;
707 	}
708 	m->busy--;
709 
710 	oldflags = m->flags;
711 
712 	if (flags & FREAD)
713 		m->flags &= ~(M_RX | M_RXEN);
714 	if (flags & FWRITE)
715 		m->flags &= ~M_TX;
716 
717 	if ((m->flags & (M_TXEN | M_RXEN)) != (oldflags & (M_RXEN | M_TXEN)))
718 		MPU_CALLBACK(m, m->cookie, m->flags);
719 
720 	MIDI_DEBUG(1, kprintf("midi_close: closed, busy = %d.\n", m->busy));
721 
722 	lockmgr(&m->qlock, LK_RELEASE);
723 	lockmgr(&m->lock, LK_RELEASE);
724 	retval = 0;
725 err:	return retval;
726 }
727 
728 /*
729  * TODO: midi_read, per oss programmer's guide pg. 42 should return as soon
730  * as data is available.
731  */
732 int
733 midi_read(struct dev_read_args *ap)
734 {
735 	cdev_t i_dev = ap->a_head.a_dev;
736 	struct uio *uio = ap->a_uio;
737 	int ioflag = ap->a_ioflag;
738 #define MIDI_RSIZE 32
739 	struct snd_midi *m = i_dev->si_drv1;
740 	int retval;
741 	int used;
742 	char buf[MIDI_RSIZE];
743 
744 	MIDI_DEBUG(5, kprintf("midiread: count=%lu\n",
745 	    (unsigned long)uio->uio_resid));
746 
747 	retval = EIO;
748 
749 	if (m == NULL)
750 		goto err0;
751 
752 	lockmgr(&m->lock, LK_EXCLUSIVE);
753 	lockmgr(&m->qlock, LK_EXCLUSIVE);
754 
755 	if (!(m->flags & M_RX))
756 		goto err1;
757 
758 	while (uio->uio_resid > 0) {
759 		while (MIDIQ_EMPTY(m->inq)) {
760 			retval = EWOULDBLOCK;
761 			if (ioflag & O_NONBLOCK)
762 				goto err1;
763 			lockmgr(&m->lock, LK_RELEASE);
764 			m->rchan = 1;
765 			retval = lksleep(&m->rchan, &m->qlock,
766 			    PCATCH, "midi RX", 0);
767 			/*
768 			 * We slept, maybe things have changed since last
769 			 * dying check
770 			 */
771 			if (retval == EINTR)
772 				goto err0;
773 			if (m != i_dev->si_drv1)
774 				retval = ENXIO;
775 			/* if (retval && retval != ERESTART) */
776 			if (retval)
777 				goto err0;
778 			lockmgr(&m->lock, LK_EXCLUSIVE);
779 			lockmgr(&m->qlock, LK_EXCLUSIVE);
780 			m->rchan = 0;
781 			if (!m->busy)
782 				goto err1;
783 		}
784 		MIDI_DEBUG(6, kprintf("midi_read start\n"));
785 		/*
786 	         * At this point, it is certain that m->inq has data
787 	         */
788 
789 		used = MIN(MIDIQ_LEN(m->inq), uio->uio_resid);
790 		used = MIN(used, MIDI_RSIZE);
791 
792 		MIDI_DEBUG(6, kprintf("midiread: uiomove cc=%d\n", used));
793 		MIDIQ_DEQ(m->inq, buf, used);
794 		retval = uiomove(buf, used, uio);
795 		if (retval)
796 			goto err1;
797 	}
798 
799 	/*
800 	 * If we Made it here then transfer is good
801 	 */
802 	retval = 0;
803 err1:	lockmgr(&m->qlock, LK_RELEASE);
804 	lockmgr(&m->lock, LK_RELEASE);
805 err0:	MIDI_DEBUG(4, kprintf("midi_read: ret %d\n", retval));
806 	return retval;
807 }
808 
809 /*
810  * midi_write: The only setter of M_TXEN
811  */
812 
813 int
814 midi_write(struct dev_write_args *ap)
815 {
816 	cdev_t i_dev = ap->a_head.a_dev;
817 	struct uio *uio = ap->a_uio;
818 	int ioflag = ap->a_ioflag;
819 #define MIDI_WSIZE 32
820 	struct snd_midi *m = i_dev->si_drv1;
821 	int retval;
822 	int used;
823 	char buf[MIDI_WSIZE];
824 
825 
826 	MIDI_DEBUG(4, kprintf("midi_write\n"));
827 	retval = 0;
828 	if (m == NULL)
829 		goto err0;
830 
831 	lockmgr(&m->lock, LK_EXCLUSIVE);
832 	lockmgr(&m->qlock, LK_EXCLUSIVE);
833 
834 	if (!(m->flags & M_TX))
835 		goto err1;
836 
837 	while (uio->uio_resid > 0) {
838 		while (MIDIQ_AVAIL(m->outq) == 0) {
839 			retval = EWOULDBLOCK;
840 			if (ioflag & O_NONBLOCK)
841 				goto err1;
842 			lockmgr(&m->lock, LK_RELEASE);
843 			m->wchan = 1;
844 			MIDI_DEBUG(3, kprintf("midi_write lksleep\n"));
845 			retval = lksleep(&m->wchan, &m->qlock,
846 			    PCATCH, "midi TX", 0);
847 			/*
848 			 * We slept, maybe things have changed since last
849 			 * dying check
850 			 */
851 			if (retval == EINTR)
852 				goto err0;
853 			if (m != i_dev->si_drv1)
854 				retval = ENXIO;
855 			if (retval)
856 				goto err0;
857 			lockmgr(&m->lock, LK_EXCLUSIVE);
858 			lockmgr(&m->qlock, LK_EXCLUSIVE);
859 			m->wchan = 0;
860 			if (!m->busy)
861 				goto err1;
862 		}
863 
864 		/*
865 	         * We are certain than data can be placed on the queue
866 	         */
867 
868 		used = MIN(MIDIQ_AVAIL(m->outq), uio->uio_resid);
869 		used = MIN(used, MIDI_WSIZE);
870 		MIDI_DEBUG(5, kprintf("midiout: resid %zd len %jd avail %jd\n",
871 		    uio->uio_resid, (intmax_t)MIDIQ_LEN(m->outq),
872 		    (intmax_t)MIDIQ_AVAIL(m->outq)));
873 
874 
875 		MIDI_DEBUG(5, kprintf("midi_write: uiomove cc=%d\n", used));
876 		retval = uiomove(buf, used, uio);
877 		if (retval)
878 			goto err1;
879 		MIDIQ_ENQ(m->outq, buf, used);
880 		/*
881 	         * Inform the bottom half that data can be written
882 	         */
883 		if (!(m->flags & M_TXEN)) {
884 			m->flags |= M_TXEN;
885 			MPU_CALLBACK(m, m->cookie, m->flags);
886 		}
887 	}
888 	/*
889 	 * If we Made it here then transfer is good
890 	 */
891 	retval = 0;
892 err1:	lockmgr(&m->qlock, LK_RELEASE);
893 	lockmgr(&m->lock, LK_RELEASE);
894 err0:	return retval;
895 }
896 
897 int
898 midi_ioctl(struct dev_ioctl_args *ap)
899 {
900 	return ENXIO;
901 }
902 
903 int
904 midi_kqfilter(struct dev_kqfilter_args *ap)
905 {
906 	cdev_t dev = ap->a_head.a_dev;
907 	struct knote *kn = ap->a_kn;
908 	struct snd_midi *m;
909 	struct klist *klist;
910 
911 	ap->a_result = 0;
912 	m = dev->si_drv1;
913 
914 	switch (kn->kn_filter) {
915 	case EVFILT_READ:
916 		kn->kn_fop = &midi_read_filterops;
917 		kn->kn_hook = (caddr_t)m;
918 		klist = &m->rkq.ki_note;
919 		break;
920 	case EVFILT_WRITE:
921 		kn->kn_fop = &midi_write_filterops;
922 		kn->kn_hook = (caddr_t)m;
923 		klist = &m->wkq.ki_note;
924 		break;
925 	default:
926 		ap->a_result = EOPNOTSUPP;
927 		return (0);
928 	}
929 
930 	knote_insert(klist, kn);
931 
932 	return(0);
933 }
934 
935 static void
936 midi_filter_detach(struct knote *kn)
937 {
938 	struct snd_midi *m = (struct snd_midi *)kn->kn_hook;
939 	struct klist *rklist = &m->rkq.ki_note;
940 	struct klist *wklist = &m->wkq.ki_note;
941 
942 	knote_remove(rklist, kn);
943 	knote_remove(wklist, kn);
944 }
945 
946 static int
947 midi_filter_read(struct knote *kn, long hint)
948 {
949 	struct snd_midi *m = (struct snd_midi *)kn->kn_hook;
950 	int ready = 0;
951 
952 	lockmgr(&m->lock, LK_EXCLUSIVE);
953 	lockmgr(&m->qlock, LK_EXCLUSIVE);
954 
955 	if (!MIDIQ_EMPTY(m->inq))
956 		ready = 1;
957 
958 	lockmgr(&m->lock, LK_RELEASE);
959 	lockmgr(&m->qlock, LK_RELEASE);
960 
961 	return (ready);
962 }
963 
964 static int
965 midi_filter_write(struct knote *kn, long hint)
966 {
967 	struct snd_midi *m = (struct snd_midi *)kn->kn_hook;
968 	int ready = 0;
969 
970 	lockmgr(&m->lock, LK_EXCLUSIVE);
971 	lockmgr(&m->qlock, LK_EXCLUSIVE);
972 
973 	if (MIDIQ_AVAIL(m->outq) < m->hiwat)
974 		ready = 1;
975 
976 	lockmgr(&m->lock, LK_RELEASE);
977 	lockmgr(&m->qlock, LK_RELEASE);
978 
979 	return (ready);
980 }
981 
982 /*
983  * /dev/midistat device functions
984  *
985  */
986 static int
987 midistat_open(struct dev_open_args *ap)
988 {
989 	int error;
990 
991 	MIDI_DEBUG(1, kprintf("midistat_open\n"));
992 	lockmgr(&midistat_lock, LK_EXCLUSIVE);
993 
994 	if (midistat_isopen) {
995 		lockmgr(&midistat_lock, LK_RELEASE);
996 		return EBUSY;
997 	}
998 	midistat_isopen = 1;
999 	lockmgr(&midistat_lock, LK_RELEASE);
1000 
1001 	if (sbuf_new(&midistat_sbuf, NULL, 4096, SBUF_AUTOEXTEND) == NULL) {
1002 		error = ENXIO;
1003 		lockmgr(&midistat_lock, LK_EXCLUSIVE);
1004 		goto out;
1005 	}
1006 	lockmgr(&midistat_lock, LK_EXCLUSIVE);
1007 	midistat_bufptr = 0;
1008 	error = (midistat_prepare(&midistat_sbuf) > 0) ? 0 : ENOMEM;
1009 
1010 out:	if (error)
1011 		midistat_isopen = 0;
1012 	lockmgr(&midistat_lock, LK_RELEASE);
1013 	return error;
1014 }
1015 
1016 static int
1017 midistat_close(struct dev_close_args *ap)
1018 {
1019 	MIDI_DEBUG(1, kprintf("midistat_close\n"));
1020 	lockmgr(&midistat_lock, LK_EXCLUSIVE);
1021 	if (!midistat_isopen) {
1022 		lockmgr(&midistat_lock, LK_RELEASE);
1023 		return EBADF;
1024 	}
1025 	sbuf_delete(&midistat_sbuf);
1026 	midistat_isopen = 0;
1027 
1028 	lockmgr(&midistat_lock, LK_RELEASE);
1029 	return 0;
1030 }
1031 
1032 static int
1033 midistat_read(struct dev_read_args *ap)
1034 {
1035 	struct uio *buf = ap->a_uio;
1036 	int l, err;
1037 
1038 	MIDI_DEBUG(4, kprintf("midistat_read\n"));
1039 	lockmgr(&midistat_lock, LK_EXCLUSIVE);
1040 	if (!midistat_isopen) {
1041 		lockmgr(&midistat_lock, LK_RELEASE);
1042 		return EBADF;
1043 	}
1044 	l = min(buf->uio_resid, sbuf_len(&midistat_sbuf) - midistat_bufptr);
1045 	err = 0;
1046 	if (l > 0) {
1047 		lockmgr(&midistat_lock, LK_RELEASE);
1048 		err = uiomove(sbuf_data(&midistat_sbuf) + midistat_bufptr, l,
1049 		    buf);
1050 		lockmgr(&midistat_lock, LK_EXCLUSIVE);
1051 	} else
1052 		l = 0;
1053 	midistat_bufptr += l;
1054 	lockmgr(&midistat_lock, LK_RELEASE);
1055 	return err;
1056 }
1057 
1058 /*
1059  * Module library functions
1060  */
1061 
1062 static int
1063 midistat_prepare(struct sbuf *s)
1064 {
1065 	struct snd_midi *m;
1066 
1067 	KKASSERT(lockowned(&midistat_lock));
1068 
1069 	sbuf_printf(s, "FreeBSD Midi Driver (midi2)\n");
1070 	if (TAILQ_EMPTY(&midi_devs)) {
1071 		sbuf_printf(s, "No devices installed.\n");
1072 		sbuf_finish(s);
1073 		return sbuf_len(s);
1074 	}
1075 	sbuf_printf(s, "Installed devices:\n");
1076 
1077 	TAILQ_FOREACH(m, &midi_devs, link) {
1078 		lockmgr(&m->lock, LK_EXCLUSIVE);
1079 		sbuf_printf(s, "%s [%d/%d:%s]", m->name, m->unit, m->channel,
1080 		    MPU_PROVIDER(m, m->cookie));
1081 		sbuf_printf(s, "%s", MPU_DESCR(m, m->cookie, midistat_verbose));
1082 		sbuf_printf(s, "\n");
1083 		lockmgr(&m->lock, LK_RELEASE);
1084 	}
1085 
1086 	sbuf_finish(s);
1087 	return sbuf_len(s);
1088 }
1089 
1090 #ifdef notdef
1091 /*
1092  * Convert IOCTL command to string for debugging
1093  */
1094 
1095 static char *
1096 midi_cmdname(int cmd)
1097 {
1098 	static struct {
1099 		int	cmd;
1100 		char   *name;
1101 	}     *tab, cmdtab_midiioctl[] = {
1102 #define A(x)	{x, ## x}
1103 		/*
1104 	         * Once we have some real IOCTLs define, the following will
1105 	         * be relavant.
1106 	         *
1107 	         * A(SNDCTL_MIDI_PRETIME), A(SNDCTL_MIDI_MPUMODE),
1108 	         * A(SNDCTL_MIDI_MPUCMD), A(SNDCTL_SYNTH_INFO),
1109 	         * A(SNDCTL_MIDI_INFO), A(SNDCTL_SYNTH_MEMAVL),
1110 	         * A(SNDCTL_FM_LOAD_INSTR), A(SNDCTL_FM_4OP_ENABLE),
1111 	         * A(MIOSPASSTHRU), A(MIOGPASSTHRU), A(AIONWRITE),
1112 	         * A(AIOGSIZE), A(AIOSSIZE), A(AIOGFMT), A(AIOSFMT),
1113 	         * A(AIOGMIX), A(AIOSMIX), A(AIOSTOP), A(AIOSYNC),
1114 	         * A(AIOGCAP),
1115 	         */
1116 #undef A
1117 		{
1118 			-1, "unknown"
1119 		},
1120 	};
1121 
1122 	for (tab = cmdtab_midiioctl; tab->cmd != cmd && tab->cmd != -1; tab++);
1123 	return tab->name;
1124 }
1125 
1126 #endif					/* notdef */
1127 
1128 /*
1129  * midisynth
1130  */
1131 
1132 
1133 int
1134 midisynth_open(void *n, void *arg, int flags)
1135 {
1136 	struct snd_midi *m = ((struct synth_midi *)n)->m;
1137 	int retval;
1138 
1139 	MIDI_DEBUG(1, kprintf("midisynth_open %s %s\n",
1140 	    flags & FREAD ? "M_RX" : "", flags & FWRITE ? "M_TX" : ""));
1141 
1142 	if (m == NULL)
1143 		return ENXIO;
1144 
1145 	lockmgr(&m->lock, LK_EXCLUSIVE);
1146 	lockmgr(&m->qlock, LK_EXCLUSIVE);
1147 
1148 	retval = 0;
1149 
1150 	if (flags & FREAD) {
1151 		if (MIDIQ_SIZE(m->inq) == 0)
1152 			retval = ENXIO;
1153 		else if (m->flags & M_RX)
1154 			retval = EBUSY;
1155 		if (retval)
1156 			goto err;
1157 	}
1158 	if (flags & FWRITE) {
1159 		if (MIDIQ_SIZE(m->outq) == 0)
1160 			retval = ENXIO;
1161 		else if (m->flags & M_TX)
1162 			retval = EBUSY;
1163 		if (retval)
1164 			goto err;
1165 	}
1166 	m->busy++;
1167 
1168 	/*
1169 	 * TODO: Consider m->async = 0;
1170 	 */
1171 
1172 	if (flags & FREAD) {
1173 		m->flags |= M_RX | M_RXEN;
1174 		/*
1175 	         * Only clear the inq, the outq might still have data to drain
1176 	         * from a previous session
1177 	         */
1178 		MIDIQ_CLEAR(m->inq);
1179 		m->rchan = 0;
1180 	};
1181 
1182 	if (flags & FWRITE) {
1183 		m->flags |= M_TX;
1184 		m->wchan = 0;
1185 	}
1186 	m->synth_flags = flags & (FREAD | FWRITE);
1187 
1188 	MPU_CALLBACK(m, m->cookie, m->flags);
1189 
1190 
1191 err:	lockmgr(&m->qlock, LK_RELEASE);
1192 	lockmgr(&m->lock, LK_RELEASE);
1193 	MIDI_DEBUG(2, kprintf("midisynth_open: return %d.\n", retval));
1194 	return retval;
1195 }
1196 
1197 int
1198 midisynth_close(void *n)
1199 {
1200 	struct snd_midi *m = ((struct synth_midi *)n)->m;
1201 	int retval;
1202 	int oldflags;
1203 
1204 	MIDI_DEBUG(1, kprintf("midisynth_close %s %s\n",
1205 	    m->synth_flags & FREAD ? "M_RX" : "",
1206 	    m->synth_flags & FWRITE ? "M_TX" : ""));
1207 
1208 	if (m == NULL)
1209 		return ENXIO;
1210 
1211 	lockmgr(&m->lock, LK_EXCLUSIVE);
1212 	lockmgr(&m->qlock, LK_EXCLUSIVE);
1213 
1214 	if ((m->synth_flags & FREAD && !(m->flags & M_RX)) ||
1215 	    (m->synth_flags & FWRITE && !(m->flags & M_TX))) {
1216 		retval = ENXIO;
1217 		goto err;
1218 	}
1219 	m->busy--;
1220 
1221 	oldflags = m->flags;
1222 
1223 	if (m->synth_flags & FREAD)
1224 		m->flags &= ~(M_RX | M_RXEN);
1225 	if (m->synth_flags & FWRITE)
1226 		m->flags &= ~M_TX;
1227 
1228 	if ((m->flags & (M_TXEN | M_RXEN)) != (oldflags & (M_RXEN | M_TXEN)))
1229 		MPU_CALLBACK(m, m->cookie, m->flags);
1230 
1231 	MIDI_DEBUG(1, kprintf("midi_close: closed, busy = %d.\n", m->busy));
1232 
1233 	lockmgr(&m->qlock, LK_RELEASE);
1234 	lockmgr(&m->lock, LK_RELEASE);
1235 	retval = 0;
1236 err:	return retval;
1237 }
1238 
1239 /*
1240  * Always blocking.
1241  */
1242 
1243 int
1244 midisynth_writeraw(void *n, uint8_t *buf, size_t len)
1245 {
1246 	struct snd_midi *m = ((struct synth_midi *)n)->m;
1247 	int retval;
1248 	int used;
1249 	int i;
1250 
1251 	MIDI_DEBUG(4, kprintf("midisynth_writeraw\n"));
1252 
1253 	retval = 0;
1254 
1255 	if (m == NULL)
1256 		return ENXIO;
1257 
1258 	lockmgr(&m->lock, LK_EXCLUSIVE);
1259 	lockmgr(&m->qlock, LK_EXCLUSIVE);
1260 
1261 	if (!(m->flags & M_TX))
1262 		goto err1;
1263 
1264 	if (midi_dumpraw)
1265 		kprintf("midi dump: ");
1266 
1267 	while (len > 0) {
1268 		while (MIDIQ_AVAIL(m->outq) == 0) {
1269 			if (!(m->flags & M_TXEN)) {
1270 				m->flags |= M_TXEN;
1271 				MPU_CALLBACK(m, m->cookie, m->flags);
1272 			}
1273 			lockmgr(&m->lock, LK_RELEASE);
1274 			m->wchan = 1;
1275 			MIDI_DEBUG(3, kprintf("midisynth_writeraw lksleep\n"));
1276 			retval = lksleep(&m->wchan, &m->qlock,
1277 			    PCATCH, "midi TX", 0);
1278 			/*
1279 			 * We slept, maybe things have changed since last
1280 			 * dying check
1281 			 */
1282 			if (retval == EINTR)
1283 				goto err0;
1284 
1285 			if (retval)
1286 				goto err0;
1287 			lockmgr(&m->lock, LK_EXCLUSIVE);
1288 			lockmgr(&m->qlock, LK_EXCLUSIVE);
1289 			m->wchan = 0;
1290 			if (!m->busy)
1291 				goto err1;
1292 		}
1293 
1294 		/*
1295 	         * We are certain than data can be placed on the queue
1296 	         */
1297 
1298 		used = MIN(MIDIQ_AVAIL(m->outq), len);
1299 		used = MIN(used, MIDI_WSIZE);
1300 		MIDI_DEBUG(5,
1301 		    kprintf("midi_synth: resid %zu len %jd avail %jd\n",
1302 		    len, (intmax_t)MIDIQ_LEN(m->outq),
1303 		    (intmax_t)MIDIQ_AVAIL(m->outq)));
1304 
1305 		if (midi_dumpraw)
1306 			for (i = 0; i < used; i++)
1307 				kprintf("%x ", buf[i]);
1308 
1309 		MIDIQ_ENQ(m->outq, buf, used);
1310 		len -= used;
1311 
1312 		/*
1313 	         * Inform the bottom half that data can be written
1314 	         */
1315 		if (!(m->flags & M_TXEN)) {
1316 			m->flags |= M_TXEN;
1317 			MPU_CALLBACK(m, m->cookie, m->flags);
1318 		}
1319 	}
1320 	/*
1321 	 * If we Made it here then transfer is good
1322 	 */
1323 	if (midi_dumpraw)
1324 		kprintf("\n");
1325 
1326 	retval = 0;
1327 err1:	lockmgr(&m->qlock, LK_RELEASE);
1328 	lockmgr(&m->lock, LK_RELEASE);
1329 err0:	return retval;
1330 }
1331 
1332 static int
1333 midisynth_killnote(void *n, uint8_t chn, uint8_t note, uint8_t vel)
1334 {
1335 	u_char c[3];
1336 
1337 
1338 	if (note > 127 || chn > 15)
1339 		return (EINVAL);
1340 
1341 	if (vel > 127)
1342 		vel = 127;
1343 
1344 	if (vel == 64) {
1345 		c[0] = 0x90 | (chn & 0x0f);	/* Note on. */
1346 		c[1] = (u_char)note;
1347 		c[2] = 0;
1348 	} else {
1349 		c[0] = 0x80 | (chn & 0x0f);	/* Note off. */
1350 		c[1] = (u_char)note;
1351 		c[2] = (u_char)vel;
1352 	}
1353 
1354 	return midisynth_writeraw(n, c, 3);
1355 }
1356 
1357 static int
1358 midisynth_setinstr(void *n, uint8_t chn, uint16_t instr)
1359 {
1360 	u_char c[2];
1361 
1362 	if (instr > 127 || chn > 15)
1363 		return EINVAL;
1364 
1365 	c[0] = 0xc0 | (chn & 0x0f);	/* Progamme change. */
1366 	c[1] = instr + midi_instroff;
1367 
1368 	return midisynth_writeraw(n, c, 2);
1369 }
1370 
1371 static int
1372 midisynth_startnote(void *n, uint8_t chn, uint8_t note, uint8_t vel)
1373 {
1374 	u_char c[3];
1375 
1376 	if (note > 127 || chn > 15)
1377 		return EINVAL;
1378 
1379 	if (vel > 127)
1380 		vel = 127;
1381 
1382 	c[0] = 0x90 | (chn & 0x0f);	/* Note on. */
1383 	c[1] = (u_char)note;
1384 	c[2] = (u_char)vel;
1385 
1386 	return midisynth_writeraw(n, c, 3);
1387 }
1388 static int
1389 midisynth_alloc(void *n, uint8_t chan, uint8_t note)
1390 {
1391 	return chan;
1392 }
1393 
1394 static int
1395 midisynth_controller(void *n, uint8_t chn, uint8_t ctrlnum, uint16_t val)
1396 {
1397 	u_char c[3];
1398 
1399 	if (ctrlnum > 127 || chn > 15)
1400 		return EINVAL;
1401 
1402 	c[0] = 0xb0 | (chn & 0x0f);	/* Control Message. */
1403 	c[1] = ctrlnum;
1404 	c[2] = val;
1405 	return midisynth_writeraw(n, c, 3);
1406 }
1407 
1408 static int
1409 midisynth_bender(void *n, uint8_t chn, uint16_t val)
1410 {
1411 	u_char c[3];
1412 
1413 
1414 	if (val > 16383 || chn > 15)
1415 		return EINVAL;
1416 
1417 	c[0] = 0xe0 | (chn & 0x0f);	/* Pitch bend. */
1418 	c[1] = (u_char)val & 0x7f;
1419 	c[2] = (u_char)(val >> 7) & 0x7f;
1420 
1421 	return midisynth_writeraw(n, c, 3);
1422 }
1423 
1424 /*
1425  * Single point of midi destructions.
1426  */
1427 static int
1428 midi_destroy(struct snd_midi *m, int midiuninit)
1429 {
1430 
1431 	KKASSERT(lockowned(&midistat_lock));
1432 	KKASSERT(lockowned(&m->lock));
1433 
1434 	MIDI_DEBUG(3, kprintf("midi_destroy\n"));
1435 	m->dev->si_drv1 = NULL;
1436 	lockmgr(&m->lock, LK_RELEASE);	/* XXX */
1437 	destroy_dev(m->dev);
1438 	TAILQ_REMOVE(&midi_devs, m, link);
1439 	if (midiuninit)
1440 		MPU_UNINIT(m, m->cookie);
1441 	kfree(MIDIQ_BUF(m->inq), M_MIDI);
1442 	kfree(MIDIQ_BUF(m->outq), M_MIDI);
1443 	lockuninit(&m->qlock);
1444 	lockuninit(&m->lock);
1445 	kfree(m, M_MIDI);
1446 	return 0;
1447 }
1448 
1449 /*
1450  * Load and unload functions, creates the /dev/midistat device
1451  */
1452 
1453 static int
1454 midi_load(void)
1455 {
1456 	lockinit(&midistat_lock, "midistat lock", 0, LK_CANRECURSE);
1457 	TAILQ_INIT(&midi_devs);		/* Initialize the queue. */
1458 
1459 	midistat_dev = make_dev(&midistat_ops,
1460 	    MIDIMKMINOR(0, MIDI_DEV_MIDICTL, 0),
1461 	    UID_ROOT, GID_WHEEL, 0666, "midistat");
1462 
1463 	return 0;
1464 }
1465 
1466 static int
1467 midi_unload(void)
1468 {
1469 	struct snd_midi *m;
1470 	int retval;
1471 
1472 	MIDI_DEBUG(1, kprintf("midi_unload()\n"));
1473 	retval = EBUSY;
1474 	lockmgr(&midistat_lock, LK_EXCLUSIVE);
1475 	if (midistat_isopen)
1476 		goto exit0;
1477 
1478 	TAILQ_FOREACH(m, &midi_devs, link) {
1479 		lockmgr(&m->lock, LK_EXCLUSIVE);
1480 		if (m->busy)
1481 			retval = EBUSY;
1482 		else
1483 			retval = midi_destroy(m, 1);
1484 		if (retval)
1485 			goto exit1;
1486 	}
1487 
1488 	lockmgr(&midistat_lock, LK_RELEASE);	/* XXX */
1489 
1490 	destroy_dev(midistat_dev);
1491 	/*
1492 	 * Made it here then unload is complete
1493 	 */
1494 	lockuninit(&midistat_lock);
1495 	return 0;
1496 
1497 exit1:
1498 	lockmgr(&m->lock, LK_RELEASE);
1499 exit0:
1500 	lockmgr(&midistat_lock, LK_RELEASE);
1501 	if (retval)
1502 		MIDI_DEBUG(2, kprintf("midi_unload: failed\n"));
1503 	return retval;
1504 }
1505 
1506 extern int seq_modevent(module_t mod, int type, void *data);
1507 
1508 static int
1509 midi_modevent(module_t mod, int type, void *data)
1510 {
1511 	int retval;
1512 
1513 	retval = 0;
1514 
1515 	switch (type) {
1516 	case MOD_LOAD:
1517 		retval = midi_load();
1518 #if 0
1519 		if (retval == 0)
1520 			retval = seq_modevent(mod, type, data);
1521 #endif
1522 		break;
1523 
1524 	case MOD_UNLOAD:
1525 		retval = midi_unload();
1526 #if 0
1527 		if (retval == 0)
1528 			retval = seq_modevent(mod, type, data);
1529 #endif
1530 		break;
1531 
1532 	default:
1533 		break;
1534 	}
1535 
1536 	return retval;
1537 }
1538 
1539 kobj_t
1540 midimapper_addseq(void *arg1, int *unit, void **cookie)
1541 {
1542 	unit = 0;
1543 
1544 	return (kobj_t)arg1;
1545 }
1546 
1547 int
1548 midimapper_open(void *arg1, void **cookie)
1549 {
1550 	int retval = 0;
1551 	struct snd_midi *m;
1552 
1553 	lockmgr(&midistat_lock, LK_EXCLUSIVE);
1554 
1555 	TAILQ_FOREACH(m, &midi_devs, link) {
1556 		retval++;
1557 	}
1558 
1559 	lockmgr(&midistat_lock, LK_RELEASE);
1560 	return retval;
1561 }
1562 
1563 int
1564 midimapper_close(void *arg1, void *cookie)
1565 {
1566 	return 0;
1567 }
1568 
1569 kobj_t
1570 midimapper_fetch_synth(void *arg, void *cookie, int unit)
1571 {
1572 	struct snd_midi *m;
1573 	int retval = 0;
1574 
1575 	lockmgr(&midistat_lock, LK_EXCLUSIVE);
1576 
1577 	TAILQ_FOREACH(m, &midi_devs, link) {
1578 		if (unit == retval) {
1579 			lockmgr(&midistat_lock, LK_RELEASE);
1580 			return (kobj_t)m->synth;
1581 		}
1582 		retval++;
1583 	}
1584 
1585 	lockmgr(&midistat_lock, LK_RELEASE);
1586 	return NULL;
1587 }
1588 
1589 DEV_MODULE(midi, midi_modevent, NULL);
1590 MODULE_VERSION(midi, 1);
1591