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