xref: /freebsd/sys/dev/sound/midi/midi.c (revision e4b31985b54b626b2bbf486a82dd789f3dd381db)
1 /*-
2  * SPDX-License-Identifier: BSD-2-Clause
3  *
4  * Copyright (c) 2003 Mathew Kanner
5  * Copyright (c) 1998 The NetBSD Foundation, Inc.
6  * All rights reserved.
7  *
8  * This code is derived from software contributed to The NetBSD Foundation
9  * by Lennart Augustsson (augustss@netbsd.org).
10  *
11  * Redistribution and use in source and binary forms, with or without
12  * modification, are permitted provided that the following conditions
13  * are met:
14  * 1. Redistributions of source code must retain the above copyright
15  *    notice, this list of conditions and the following disclaimer.
16  * 2. Redistributions in binary form must reproduce the above copyright
17  *    notice, this list of conditions and the following disclaimer in the
18  *    documentation and/or other materials provided with the distribution.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
21  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
22  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
24  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30  * POSSIBILITY OF SUCH DAMAGE.
31  */
32 
33 #include <sys/param.h>
34 #include <sys/systm.h>
35 #include <sys/queue.h>
36 #include <sys/kernel.h>
37 #include <sys/lock.h>
38 #include <sys/mutex.h>
39 #include <sys/proc.h>
40 #include <sys/signalvar.h>
41 #include <sys/conf.h>
42 #include <sys/selinfo.h>
43 #include <sys/sysctl.h>
44 #include <sys/malloc.h>
45 #include <sys/sx.h>
46 #include <sys/proc.h>
47 #include <sys/fcntl.h>
48 #include <sys/types.h>
49 #include <sys/uio.h>
50 #include <sys/poll.h>
51 #include <sys/sbuf.h>
52 #include <sys/kobj.h>
53 #include <sys/module.h>
54 
55 #ifdef HAVE_KERNEL_OPTION_HEADERS
56 #include "opt_snd.h"
57 #endif
58 
59 #include <dev/sound/midi/midi.h>
60 #include "mpu_if.h"
61 
62 #include <dev/sound/midi/midiq.h>
63 MALLOC_DEFINE(M_MIDI, "midi buffers", "Midi data allocation area");
64 
65 #define MIDI_NAMELEN   16
66 struct snd_midi {
67 	KOBJ_FIELDS;
68 	struct mtx lock;		/* Protects all but queues */
69 	void   *cookie;
70 
71 	int	unit;			/* Should only be used in midistat */
72 	int	channel;		/* Should only be used in midistat */
73 
74 	int	busy;
75 	int	flags;			/* File flags */
76 	char	name[MIDI_NAMELEN];
77 	struct mtx qlock;		/* Protects inq, outq and flags */
78 	MIDIQ_HEAD(, char) inq, outq;
79 	int	rchan, wchan;
80 	struct selinfo rsel, wsel;
81 	int	hiwat;			/* QLEN(outq)>High-water -> disable
82 					 * writes from userland */
83 	struct cdev *dev;
84 	TAILQ_ENTRY(snd_midi) link;
85 };
86 
87 TAILQ_HEAD(, snd_midi) midi_devs;
88 
89 struct sx mstat_lock;
90 
91 static d_open_t midi_open;
92 static d_close_t midi_close;
93 static d_ioctl_t midi_ioctl;
94 static d_read_t midi_read;
95 static d_write_t midi_write;
96 static d_poll_t midi_poll;
97 
98 static struct cdevsw midi_cdevsw = {
99 	.d_version = D_VERSION,
100 	.d_open = midi_open,
101 	.d_close = midi_close,
102 	.d_read = midi_read,
103 	.d_write = midi_write,
104 	.d_ioctl = midi_ioctl,
105 	.d_poll = midi_poll,
106 	.d_name = "rmidi",
107 };
108 
109 static int      midi_destroy(struct snd_midi *, int);
110 static int      midi_load(void);
111 static int      midi_unload(void);
112 
113 SYSCTL_NODE(_hw, OID_AUTO, midi, CTLFLAG_RD | CTLFLAG_MPSAFE, 0,
114     "Midi driver");
115 
116 int             midi_debug;
117 /* XXX: should this be moved into debug.midi? */
118 SYSCTL_INT(_hw_midi, OID_AUTO, debug, CTLFLAG_RW, &midi_debug, 0, "");
119 
120 #define MIDI_DEBUG(l,a)	if(midi_debug>=l) a
121 
122 void
midistat_lock(void)123 midistat_lock(void)
124 {
125 	sx_xlock(&mstat_lock);
126 }
127 
128 void
midistat_unlock(void)129 midistat_unlock(void)
130 {
131 	sx_xunlock(&mstat_lock);
132 }
133 
134 void
midistat_lockassert(void)135 midistat_lockassert(void)
136 {
137 	sx_assert(&mstat_lock, SA_XLOCKED);
138 }
139 
140 /*
141  * Register a new rmidi device. cls midi_if interface unit == 0 means
142  * auto-assign new unit number unit != 0 already assigned a unit number, eg.
143  * not the first channel provided by this device. channel,	sub-unit
144  * cookie is passed back on MPU calls Typical device drivers will call with
145  * unit=0, channel=1..(number of channels) and cookie=soft_c and won't care
146  * what unit number is used.
147  *
148  * It is an error to call midi_init with an already used unit/channel combo.
149  */
150 struct snd_midi *
midi_init(kobj_class_t cls,int unit,int channel,void * cookie)151 midi_init(kobj_class_t cls, int unit, int channel, void *cookie)
152 {
153 	struct snd_midi *m;
154 	int i;
155 	int inqsize, outqsize;
156 	uint8_t *buf;
157 
158 	MIDI_DEBUG(1, printf("midiinit: unit %d/%d.\n", unit, channel));
159 	midistat_lock();
160 	/*
161 	 * Protect against call with existing unit/channel or auto-allocate a
162 	 * new unit number.
163 	 */
164 	i = -1;
165 	TAILQ_FOREACH(m, &midi_devs, link) {
166 		mtx_lock(&m->lock);
167 		if (unit != 0) {
168 			if (m->unit == unit && m->channel == channel) {
169 				mtx_unlock(&m->lock);
170 				goto err0;
171 			}
172 		} else {
173 			/*
174 			 * Find a better unit number
175 			 */
176 			if (m->unit > i)
177 				i = m->unit;
178 		}
179 		mtx_unlock(&m->lock);
180 	}
181 
182 	if (unit == 0)
183 		unit = i + 1;
184 
185 	MIDI_DEBUG(1, printf("midiinit #2: unit %d/%d.\n", unit, channel));
186 	m = malloc(sizeof(*m), M_MIDI, M_WAITOK | M_ZERO);
187 	kobj_init((kobj_t)m, cls);
188 	inqsize = MPU_INQSIZE(m, cookie);
189 	outqsize = MPU_OUTQSIZE(m, cookie);
190 
191 	MIDI_DEBUG(1, printf("midiinit queues %d/%d.\n", inqsize, outqsize));
192 	if (!inqsize && !outqsize)
193 		goto err1;
194 
195 	mtx_init(&m->lock, "raw midi", NULL, 0);
196 	mtx_init(&m->qlock, "q raw midi", NULL, 0);
197 
198 	mtx_lock(&m->lock);
199 	mtx_lock(&m->qlock);
200 
201 	if (inqsize)
202 		buf = malloc(sizeof(uint8_t) * inqsize, M_MIDI, M_NOWAIT);
203 	else
204 		buf = NULL;
205 
206 	MIDIQ_INIT(m->inq, buf, inqsize);
207 
208 	if (outqsize)
209 		buf = malloc(sizeof(uint8_t) * outqsize, M_MIDI, M_NOWAIT);
210 	else
211 		buf = NULL;
212 	m->hiwat = outqsize / 2;
213 
214 	MIDIQ_INIT(m->outq, buf, outqsize);
215 
216 	if ((inqsize && !MIDIQ_BUF(m->inq)) ||
217 	    (outqsize && !MIDIQ_BUF(m->outq)))
218 		goto err2;
219 
220 	m->busy = 0;
221 	m->flags = 0;
222 	m->unit = unit;
223 	m->channel = channel;
224 	m->cookie = cookie;
225 
226 	if (MPU_INIT(m, cookie))
227 		goto err2;
228 
229 	mtx_unlock(&m->lock);
230 	mtx_unlock(&m->qlock);
231 
232 	TAILQ_INSERT_TAIL(&midi_devs, m, link);
233 
234 	midistat_unlock();
235 
236 	m->dev = make_dev(&midi_cdevsw, unit, UID_ROOT, GID_WHEEL, 0666,
237 	    "midi%d.%d", unit, channel);
238 	m->dev->si_drv1 = m;
239 
240 	return m;
241 
242 err2:
243 	mtx_destroy(&m->qlock);
244 	mtx_destroy(&m->lock);
245 
246 	if (MIDIQ_BUF(m->inq))
247 		free(MIDIQ_BUF(m->inq), M_MIDI);
248 	if (MIDIQ_BUF(m->outq))
249 		free(MIDIQ_BUF(m->outq), M_MIDI);
250 err1:
251 	free(m, M_MIDI);
252 err0:
253 	midistat_unlock();
254 	MIDI_DEBUG(1, printf("midi_init ended in error\n"));
255 	return NULL;
256 }
257 
258 /*
259  * midi_uninit does not call MIDI_UNINIT, as since this is the implementors
260  * entry point. midi_uninit if fact, does not send any methods. A call to
261  * midi_uninit is a defacto promise that you won't manipulate ch anymore
262  */
263 int
midi_uninit(struct snd_midi * m)264 midi_uninit(struct snd_midi *m)
265 {
266 	int err;
267 
268 	err = EBUSY;
269 	midistat_lock();
270 	mtx_lock(&m->lock);
271 	if (m->busy) {
272 		if (!(m->rchan || m->wchan))
273 			goto err;
274 
275 		if (m->rchan) {
276 			wakeup(&m->rchan);
277 			m->rchan = 0;
278 		}
279 		if (m->wchan) {
280 			wakeup(&m->wchan);
281 			m->wchan = 0;
282 		}
283 	}
284 	err = midi_destroy(m, 0);
285 	if (!err)
286 		goto exit;
287 
288 err:
289 	mtx_unlock(&m->lock);
290 exit:
291 	midistat_unlock();
292 	return err;
293 }
294 
295 #ifdef notdef
296 static int midi_lengths[] = {2, 2, 2, 2, 1, 1, 2, 0};
297 
298 #endif					/* notdef */
299 /* Number of bytes in a MIDI command */
300 #define MIDI_LENGTH(d) (midi_lengths[((d) >> 4) & 7])
301 #define MIDI_ACK	0xfe
302 #define MIDI_IS_STATUS(d) ((d) >= 0x80)
303 #define MIDI_IS_COMMON(d) ((d) >= 0xf0)
304 
305 #define MIDI_SYSEX_START	0xF0
306 #define MIDI_SYSEX_END	    0xF7
307 
308 /*
309  * midi_in: process all data until the queue is full, then discards the rest.
310  * Since midi_in is a state machine, data discards can cause it to get out of
311  * whack.  Process as much as possible.  It calls, wakeup, selnotify and
312  * psignal at most once.
313  */
314 int
midi_in(struct snd_midi * m,uint8_t * buf,int size)315 midi_in(struct snd_midi *m, uint8_t *buf, int size)
316 {
317 	int used;
318 
319 	MIDI_DEBUG(5, printf("midi_in: m=%p size=%d\n", m, size));
320 
321 /*
322  * XXX: locking flub
323  */
324 	if (!(m->flags & M_RX))
325 		return size;
326 
327 	used = 0;
328 
329 	mtx_lock(&m->qlock);
330 	MIDI_DEBUG(6, printf("midi_in: len %jd avail %jd\n",
331 	    (intmax_t)MIDIQ_LEN(m->inq),
332 	    (intmax_t)MIDIQ_AVAIL(m->inq)));
333 	if (MIDIQ_AVAIL(m->inq) > size) {
334 		used = size;
335 		MIDIQ_ENQ(m->inq, buf, size);
336 	} else {
337 		MIDI_DEBUG(4, printf("midi_in: Discarding data qu\n"));
338 		mtx_unlock(&m->qlock);
339 		return 0;
340 	}
341 	if (m->rchan) {
342 		wakeup(&m->rchan);
343 		m->rchan = 0;
344 	}
345 	selwakeup(&m->rsel);
346 	mtx_unlock(&m->qlock);
347 	return used;
348 }
349 
350 /*
351  * midi_out: The only clearer of the M_TXEN flag.
352  */
353 int
midi_out(struct snd_midi * m,uint8_t * buf,int size)354 midi_out(struct snd_midi *m, uint8_t *buf, int size)
355 {
356 	int used;
357 
358 /*
359  * XXX: locking flub
360  */
361 	if (!(m->flags & M_TXEN))
362 		return 0;
363 
364 	MIDI_DEBUG(2, printf("midi_out: %p\n", m));
365 	mtx_lock(&m->qlock);
366 	used = MIN(size, MIDIQ_LEN(m->outq));
367 	MIDI_DEBUG(3, printf("midi_out: used %d\n", used));
368 	if (used)
369 		MIDIQ_DEQ(m->outq, buf, used);
370 	if (MIDIQ_EMPTY(m->outq)) {
371 		m->flags &= ~M_TXEN;
372 		MPU_CALLBACKP(m, m->cookie, m->flags);
373 	}
374 	if (used && MIDIQ_AVAIL(m->outq) > m->hiwat) {
375 		if (m->wchan) {
376 			wakeup(&m->wchan);
377 			m->wchan = 0;
378 		}
379 		selwakeup(&m->wsel);
380 	}
381 	mtx_unlock(&m->qlock);
382 	return used;
383 }
384 
385 int
midi_open(struct cdev * i_dev,int flags,int mode,struct thread * td)386 midi_open(struct cdev *i_dev, int flags, int mode, struct thread *td)
387 {
388 	struct snd_midi *m = i_dev->si_drv1;
389 	int retval;
390 
391 	MIDI_DEBUG(1, printf("midiopen %p %s %s\n", td,
392 	    flags & FREAD ? "M_RX" : "", flags & FWRITE ? "M_TX" : ""));
393 	if (m == NULL)
394 		return ENXIO;
395 
396 	mtx_lock(&m->lock);
397 	mtx_lock(&m->qlock);
398 
399 	retval = 0;
400 
401 	if (flags & FREAD) {
402 		if (MIDIQ_SIZE(m->inq) == 0)
403 			retval = ENXIO;
404 		else if (m->flags & M_RX)
405 			retval = EBUSY;
406 		if (retval)
407 			goto err;
408 	}
409 	if (flags & FWRITE) {
410 		if (MIDIQ_SIZE(m->outq) == 0)
411 			retval = ENXIO;
412 		else if (m->flags & M_TX)
413 			retval = EBUSY;
414 		if (retval)
415 			goto err;
416 	}
417 	m->busy++;
418 
419 	m->rchan = 0;
420 	m->wchan = 0;
421 
422 	if (flags & FREAD) {
423 		m->flags |= M_RX | M_RXEN;
424 		/*
425 	         * Only clear the inq, the outq might still have data to drain
426 	         * from a previous session
427 	         */
428 		MIDIQ_CLEAR(m->inq);
429 	}
430 
431 	if (flags & FWRITE)
432 		m->flags |= M_TX;
433 
434 	MPU_CALLBACK(m, m->cookie, m->flags);
435 
436 	MIDI_DEBUG(2, printf("midi_open: opened.\n"));
437 
438 err:	mtx_unlock(&m->qlock);
439 	mtx_unlock(&m->lock);
440 	return retval;
441 }
442 
443 int
midi_close(struct cdev * i_dev,int flags,int mode,struct thread * td)444 midi_close(struct cdev *i_dev, int flags, int mode, struct thread *td)
445 {
446 	struct snd_midi *m = i_dev->si_drv1;
447 	int retval;
448 	int oldflags;
449 
450 	MIDI_DEBUG(1, printf("midi_close %p %s %s\n", td,
451 	    flags & FREAD ? "M_RX" : "", flags & FWRITE ? "M_TX" : ""));
452 
453 	if (m == NULL)
454 		return ENXIO;
455 
456 	mtx_lock(&m->lock);
457 	mtx_lock(&m->qlock);
458 
459 	if ((flags & FREAD && !(m->flags & M_RX)) ||
460 	    (flags & FWRITE && !(m->flags & M_TX))) {
461 		retval = ENXIO;
462 		goto err;
463 	}
464 	m->busy--;
465 
466 	oldflags = m->flags;
467 
468 	if (flags & FREAD)
469 		m->flags &= ~(M_RX | M_RXEN);
470 	if (flags & FWRITE)
471 		m->flags &= ~M_TX;
472 
473 	if ((m->flags & (M_TXEN | M_RXEN)) != (oldflags & (M_RXEN | M_TXEN)))
474 		MPU_CALLBACK(m, m->cookie, m->flags);
475 
476 	MIDI_DEBUG(1, printf("midi_close: closed, busy = %d.\n", m->busy));
477 
478 	mtx_unlock(&m->qlock);
479 	mtx_unlock(&m->lock);
480 	retval = 0;
481 err:	return retval;
482 }
483 
484 /*
485  * TODO: midi_read, per oss programmer's guide pg. 42 should return as soon
486  * as data is available.
487  */
488 int
midi_read(struct cdev * i_dev,struct uio * uio,int ioflag)489 midi_read(struct cdev *i_dev, struct uio *uio, int ioflag)
490 {
491 #define MIDI_RSIZE 32
492 	struct snd_midi *m = i_dev->si_drv1;
493 	int retval;
494 	int used;
495 	char buf[MIDI_RSIZE];
496 
497 	MIDI_DEBUG(5, printf("midiread: count=%lu\n",
498 	    (unsigned long)uio->uio_resid));
499 
500 	retval = EIO;
501 
502 	if (m == NULL)
503 		goto err0;
504 
505 	mtx_lock(&m->lock);
506 	mtx_lock(&m->qlock);
507 
508 	if (!(m->flags & M_RX))
509 		goto err1;
510 
511 	while (uio->uio_resid > 0) {
512 		while (MIDIQ_EMPTY(m->inq)) {
513 			retval = EWOULDBLOCK;
514 			if (ioflag & O_NONBLOCK)
515 				goto err1;
516 			mtx_unlock(&m->lock);
517 			m->rchan = 1;
518 			retval = msleep(&m->rchan, &m->qlock,
519 			    PCATCH | PDROP, "midi RX", 0);
520 			/*
521 			 * We slept, maybe things have changed since last
522 			 * dying check
523 			 */
524 			if (retval == EINTR)
525 				goto err0;
526 			if (m != i_dev->si_drv1)
527 				retval = ENXIO;
528 			/* if (retval && retval != ERESTART) */
529 			if (retval)
530 				goto err0;
531 			mtx_lock(&m->lock);
532 			mtx_lock(&m->qlock);
533 			m->rchan = 0;
534 			if (!m->busy)
535 				goto err1;
536 		}
537 		MIDI_DEBUG(6, printf("midi_read start\n"));
538 		/*
539 	         * At this point, it is certain that m->inq has data
540 	         */
541 
542 		used = MIN(MIDIQ_LEN(m->inq), uio->uio_resid);
543 		used = MIN(used, MIDI_RSIZE);
544 
545 		MIDI_DEBUG(6, printf("midiread: uiomove cc=%d\n", used));
546 		MIDIQ_DEQ(m->inq, buf, used);
547 		retval = uiomove(buf, used, uio);
548 		if (retval)
549 			goto err1;
550 	}
551 
552 	/*
553 	 * If we Made it here then transfer is good
554 	 */
555 	retval = 0;
556 err1:	mtx_unlock(&m->qlock);
557 	mtx_unlock(&m->lock);
558 err0:	MIDI_DEBUG(4, printf("midi_read: ret %d\n", retval));
559 	return retval;
560 }
561 
562 /*
563  * midi_write: The only setter of M_TXEN
564  */
565 
566 int
midi_write(struct cdev * i_dev,struct uio * uio,int ioflag)567 midi_write(struct cdev *i_dev, struct uio *uio, int ioflag)
568 {
569 #define MIDI_WSIZE 32
570 	struct snd_midi *m = i_dev->si_drv1;
571 	int retval;
572 	int used;
573 	char buf[MIDI_WSIZE];
574 
575 	MIDI_DEBUG(4, printf("midi_write\n"));
576 	retval = 0;
577 	if (m == NULL)
578 		goto err0;
579 
580 	mtx_lock(&m->lock);
581 	mtx_lock(&m->qlock);
582 
583 	if (!(m->flags & M_TX))
584 		goto err1;
585 
586 	while (uio->uio_resid > 0) {
587 		while (MIDIQ_AVAIL(m->outq) == 0) {
588 			retval = EWOULDBLOCK;
589 			if (ioflag & O_NONBLOCK)
590 				goto err1;
591 			mtx_unlock(&m->lock);
592 			m->wchan = 1;
593 			MIDI_DEBUG(3, printf("midi_write msleep\n"));
594 			retval = msleep(&m->wchan, &m->qlock,
595 			    PCATCH | PDROP, "midi TX", 0);
596 			/*
597 			 * We slept, maybe things have changed since last
598 			 * dying check
599 			 */
600 			if (retval == EINTR)
601 				goto err0;
602 			if (m != i_dev->si_drv1)
603 				retval = ENXIO;
604 			if (retval)
605 				goto err0;
606 			mtx_lock(&m->lock);
607 			mtx_lock(&m->qlock);
608 			m->wchan = 0;
609 			if (!m->busy)
610 				goto err1;
611 		}
612 
613 		/*
614 	         * We are certain than data can be placed on the queue
615 	         */
616 
617 		used = MIN(MIDIQ_AVAIL(m->outq), uio->uio_resid);
618 		used = MIN(used, MIDI_WSIZE);
619 		MIDI_DEBUG(5, printf("midiout: resid %zd len %jd avail %jd\n",
620 		    uio->uio_resid, (intmax_t)MIDIQ_LEN(m->outq),
621 		    (intmax_t)MIDIQ_AVAIL(m->outq)));
622 
623 		MIDI_DEBUG(5, printf("midi_write: uiomove cc=%d\n", used));
624 		retval = uiomove(buf, used, uio);
625 		if (retval)
626 			goto err1;
627 		MIDIQ_ENQ(m->outq, buf, used);
628 		/*
629 	         * Inform the bottom half that data can be written
630 	         */
631 		if (!(m->flags & M_TXEN)) {
632 			m->flags |= M_TXEN;
633 			MPU_CALLBACK(m, m->cookie, m->flags);
634 		}
635 	}
636 	/*
637 	 * If we Made it here then transfer is good
638 	 */
639 	retval = 0;
640 err1:	mtx_unlock(&m->qlock);
641 	mtx_unlock(&m->lock);
642 err0:	return retval;
643 }
644 
645 int
midi_ioctl(struct cdev * i_dev,u_long cmd,caddr_t arg,int mode,struct thread * td)646 midi_ioctl(struct cdev *i_dev, u_long cmd, caddr_t arg, int mode,
647     struct thread *td)
648 {
649 	return ENXIO;
650 }
651 
652 int
midi_poll(struct cdev * i_dev,int events,struct thread * td)653 midi_poll(struct cdev *i_dev, int events, struct thread *td)
654 {
655 	struct snd_midi *m = i_dev->si_drv1;
656 	int revents;
657 
658 	if (m == NULL)
659 		return 0;
660 
661 	revents = 0;
662 
663 	mtx_lock(&m->lock);
664 	mtx_lock(&m->qlock);
665 
666 	if (events & (POLLIN | POLLRDNORM))
667 		if (!MIDIQ_EMPTY(m->inq))
668 			events |= events & (POLLIN | POLLRDNORM);
669 
670 	if (events & (POLLOUT | POLLWRNORM))
671 		if (MIDIQ_AVAIL(m->outq) < m->hiwat)
672 			events |= events & (POLLOUT | POLLWRNORM);
673 
674 	if (revents == 0) {
675 		if (events & (POLLIN | POLLRDNORM))
676 			selrecord(td, &m->rsel);
677 
678 		if (events & (POLLOUT | POLLWRNORM))
679 			selrecord(td, &m->wsel);
680 	}
681 	mtx_unlock(&m->lock);
682 	mtx_unlock(&m->qlock);
683 
684 	return (revents);
685 }
686 
687 /*
688  * Single point of midi destructions.
689  */
690 static int
midi_destroy(struct snd_midi * m,int midiuninit)691 midi_destroy(struct snd_midi *m, int midiuninit)
692 {
693 	midistat_lockassert();
694 	mtx_assert(&m->lock, MA_OWNED);
695 
696 	MIDI_DEBUG(3, printf("midi_destroy\n"));
697 	m->dev->si_drv1 = NULL;
698 	mtx_unlock(&m->lock);	/* XXX */
699 	destroy_dev(m->dev);
700 	TAILQ_REMOVE(&midi_devs, m, link);
701 	if (midiuninit)
702 		MPU_UNINIT(m, m->cookie);
703 	free(MIDIQ_BUF(m->inq), M_MIDI);
704 	free(MIDIQ_BUF(m->outq), M_MIDI);
705 	mtx_destroy(&m->qlock);
706 	mtx_destroy(&m->lock);
707 	free(m, M_MIDI);
708 	return 0;
709 }
710 
711 static int
midi_load(void)712 midi_load(void)
713 {
714 	sx_init(&mstat_lock, "midistat lock");
715 	TAILQ_INIT(&midi_devs);
716 
717 	return 0;
718 }
719 
720 static int
midi_unload(void)721 midi_unload(void)
722 {
723 	struct snd_midi *m, *tmp;
724 	int retval;
725 
726 	MIDI_DEBUG(1, printf("midi_unload()\n"));
727 	retval = EBUSY;
728 	midistat_lock();
729 	TAILQ_FOREACH_SAFE(m, &midi_devs, link, tmp) {
730 		mtx_lock(&m->lock);
731 		if (m->busy)
732 			retval = EBUSY;
733 		else
734 			retval = midi_destroy(m, 1);
735 		if (retval)
736 			goto exit;
737 	}
738 	midistat_unlock();
739 
740 	sx_destroy(&mstat_lock);
741 	return 0;
742 
743 exit:
744 	mtx_unlock(&m->lock);
745 	midistat_unlock();
746 	if (retval)
747 		MIDI_DEBUG(2, printf("midi_unload: failed\n"));
748 	return retval;
749 }
750 
751 static int
midi_modevent(module_t mod,int type,void * data)752 midi_modevent(module_t mod, int type, void *data)
753 {
754 	int retval;
755 
756 	retval = 0;
757 
758 	switch (type) {
759 	case MOD_LOAD:
760 		retval = midi_load();
761 		break;
762 
763 	case MOD_UNLOAD:
764 		retval = midi_unload();
765 		break;
766 
767 	default:
768 		break;
769 	}
770 
771 	return retval;
772 }
773 
774 DEV_MODULE(midi, midi_modevent, NULL);
775 MODULE_VERSION(midi, 1);
776