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