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