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