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