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