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