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