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