xref: /freebsd/sys/dev/sound/midi/midi.c (revision 4b2eaea43fec8e8792be611dea204071a10b655a)
1 /*
2  * Main midi driver for FreeBSD. This file provides the main
3  * entry points for probe/attach and all i/o demultiplexing, including
4  * default routines for generic devices.
5  *
6  * (C) 1999 Seigo Tanimura
7  *
8  * Redistribution and use in source and binary forms, with or
9  * without modification, are permitted provided that the following
10  * conditions are met:
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above
14  *    copyright notice, this list of conditions and the following
15  *    disclaimer in the documentation and/or other materials provided
16  *    with the distribution.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS
19  * IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
21  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE
22  * AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
23  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
24  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
27  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
28  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
29  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30  *
31  *
32  * For each card type a template "mididev_info" structure contains
33  * all the relevant parameters, both for configuration and runtime.
34  *
35  * In this file we build tables of pointers to the descriptors for
36  * the various supported cards. The generic probe routine scans
37  * the table(s) looking for a matching entry, then invokes the
38  * board-specific probe routine. If successful, a pointer to the
39  * correct mididev_info is stored in mididev_last_probed, for subsequent
40  * use in the attach routine. The generic attach routine copies
41  * the template to a permanent descriptor (midi_info and
42  * friends), initializes all generic parameters, and calls the
43  * board-specific attach routine.
44  *
45  * On device calls, the generic routines do the checks on unit and
46  * device parameters, then call the board-specific routines if
47  * available, or try to perform the task using the default code.
48  *
49  * $FreeBSD$
50  *
51  */
52 
53 #include <dev/sound/midi/midi.h>
54 
55 static devclass_t midi_devclass;
56 
57 static d_open_t midiopen;
58 static d_close_t midiclose;
59 static d_ioctl_t midiioctl;
60 static d_read_t midiread;
61 static d_write_t midiwrite;
62 static d_poll_t midipoll;
63 
64 /* These functions are local. */
65 static d_open_t midistat_open;
66 static d_close_t midistat_close;
67 static d_read_t midistat_read;
68 static int midi_initstatus(char *buf, int size);
69 static int midi_readstatus(char *buf, int *ptr, struct uio *uio);
70 
71 #define CDEV_MAJOR MIDI_CDEV_MAJOR
72 static struct cdevsw midi_cdevsw = {
73 	/* open */	midiopen,
74 	/* close */	midiclose,
75 	/* read */	midiread,
76 	/* write */	midiwrite,
77 	/* ioctl */	midiioctl,
78 	/* poll */	midipoll,
79 	/* mmap */	nommap,
80 	/* strategy */	nostrategy,
81 	/* name */	"midi",
82 	/* maj */	CDEV_MAJOR,
83 	/* dump */	nodump,
84 	/* psize */	nopsize,
85 	/* flags */	0,
86 };
87 
88 /*
89  * descriptors for active devices. also used as the public softc
90  * of a device.
91  */
92 static TAILQ_HEAD(,_mididev_info)	midi_info;
93 static int		nmidi, nsynth;
94 /* Mutex to protect midi_info, nmidi and nsynth. */
95 static struct mtx	midiinfo_mtx;
96 static int		midiinfo_mtx_init;
97 
98 /* These make the buffer for /dev/midistat */
99 static int		midistatbusy;
100 static char		midistatbuf[4096];
101 static int		midistatptr;
102 
103 SYSCTL_NODE(_hw, OID_AUTO, midi, CTLFLAG_RD, 0, "Midi driver");
104 
105 int			midi_debug;
106 SYSCTL_INT(_hw_midi, OID_AUTO, debug, CTLFLAG_RW, &midi_debug, 0, "");
107 
108 midi_cmdtab	cmdtab_midiioctl[] = {
109 	{SNDCTL_MIDI_PRETIME,	"SNDCTL_MIDI_PRETIME"},
110 	{SNDCTL_MIDI_MPUMODE,	"SNDCTL_MIDI_MPUMODE"},
111 	{SNDCTL_MIDI_MPUCMD,	"SNDCTL_MIDI_MPUCMD"},
112 	{SNDCTL_SYNTH_INFO,	"SNDCTL_SYNTH_INFO"},
113 	{SNDCTL_MIDI_INFO,	"SNDCTL_MIDI_INFO"},
114 	{SNDCTL_SYNTH_MEMAVL,	"SNDCTL_SYNTH_MEMAVL"},
115 	{SNDCTL_FM_LOAD_INSTR,	"SNDCTL_FM_LOAD_INSTR"},
116 	{SNDCTL_FM_4OP_ENABLE,	"SNDCTL_FM_4OP_ENABLE"},
117 	{MIOSPASSTHRU,		"MIOSPASSTHRU"},
118 	{MIOGPASSTHRU,		"MIOGPASSTHRU"},
119 	{AIONWRITE,		"AIONWRITE"},
120 	{AIOGSIZE,		"AIOGSIZE"},
121 	{AIOSSIZE,		"AIOSSIZE"},
122 	{AIOGFMT,		"AIOGFMT"},
123 	{AIOSFMT,		"AIOSFMT"},
124 	{AIOGMIX,		"AIOGMIX"},
125 	{AIOSMIX,		"AIOSMIX"},
126 	{AIOSTOP,		"AIOSTOP"},
127 	{AIOSYNC,		"AIOSYNC"},
128 	{AIOGCAP,		"AIOGCAP"},
129 	{-1,			NULL},
130 };
131 
132 /*
133  * This is the generic init routine.
134  * Must be called after device-specific init.
135  */
136 int
137 midiinit(mididev_info *d, device_t dev)
138 {
139 	int unit;
140 
141 	/*
142 	 * initialize standard parameters for the device. This can be
143 	 * overridden by device-specific configurations but better do
144 	 * here the generic things.
145 	 */
146 
147 	MIDI_DEBUG(printf("midiinit: unit %d.\n", d->unit));
148 
149 	unit = d->unit;
150 	d->softc = device_get_softc(dev);
151 	d->dev = dev;
152 	d->magic = MAGIC(d->unit); /* debugging... */
153 	d->flags = 0;
154 	d->fflags = 0;
155 	d->midi_dbuf_in.unit_size = 1;
156 	d->midi_dbuf_out.unit_size = 1;
157 	d->midi_dbuf_passthru.unit_size = 1;
158 
159 	mtx_unlock(&d->flagqueue_mtx);
160 
161 	if (midi_devclass == NULL) {
162 		midi_devclass = device_get_devclass(dev);
163 		make_dev(&midi_cdevsw, MIDIMKMINOR(0, MIDI_DEV_STATUS),
164 			 UID_ROOT, GID_WHEEL, 0444, "midistat");
165 	}
166 	make_dev(&midi_cdevsw, MIDIMKMINOR(unit, MIDI_DEV_MIDIN),
167 		 UID_ROOT, GID_WHEEL, 0666, "midi%d", unit);
168 
169 	return 0 ;
170 }
171 
172 /*
173  * a small utility function which, given a device number, returns
174  * a pointer to the associated mididev_info struct, and sets the unit
175  * number.
176  */
177 mididev_info *
178 get_mididev_info(dev_t i_dev, int *unit)
179 {
180 	int u;
181 
182 	if (MIDIDEV(i_dev) != MIDI_DEV_MIDIN)
183 		return NULL;
184 	u = MIDIUNIT(i_dev);
185 	if (unit)
186 		*unit = u;
187 
188 	return get_mididev_info_unit(u);
189 }
190 
191 /*
192  * a small utility function which, given a unit number, returns
193  * a pointer to the associated mididev_info struct.
194  */
195 mididev_info *
196 get_mididev_info_unit(int unit)
197 {
198 	mididev_info *md;
199 
200 	/* XXX */
201 	if (!midiinfo_mtx_init) {
202 		midiinfo_mtx_init = 1;
203 		mtx_init(&midiinfo_mtx, "midinf", NULL, MTX_DEF);
204 		TAILQ_INIT(&midi_info);
205 	}
206 
207 	mtx_lock(&midiinfo_mtx);
208 	TAILQ_FOREACH(md, &midi_info, md_link) {
209 		if (md->unit == unit)
210 			break;
211 	}
212 	mtx_unlock(&midiinfo_mtx);
213 
214 	return md;
215 }
216 
217 /*
218  * a small utility function which, given a unit number, returns
219  * a pointer to the associated mididev_info struct with MDT_MIDI.
220  */
221 mididev_info *
222 get_mididev_midi_unit(int unit)
223 {
224 	mididev_info *md;
225 
226 	/* XXX */
227 	if (!midiinfo_mtx_init) {
228 		midiinfo_mtx_init = 1;
229 		mtx_init(&midiinfo_mtx, "midinf", NULL, MTX_DEF);
230 		TAILQ_INIT(&midi_info);
231 	}
232 
233 	mtx_lock(&midiinfo_mtx);
234 	TAILQ_FOREACH(md, &midi_info, md_link) {
235 		if (md->midiunit == unit)
236 			break;
237 	}
238 	mtx_unlock(&midiinfo_mtx);
239 
240 	return md;
241 }
242 
243 /*
244  * a small utility function which, given a unit number, returns
245  * a pointer to the associated mididev_info struct with MDT_SYNTH.
246  */
247 mididev_info *
248 get_mididev_synth_unit(int unit)
249 {
250 	mididev_info *md;
251 
252 	/* XXX */
253 	if (!midiinfo_mtx_init) {
254 		midiinfo_mtx_init = 1;
255 		mtx_init(&midiinfo_mtx, "midinf", NULL, MTX_DEF);
256 		TAILQ_INIT(&midi_info);
257 	}
258 
259 	mtx_lock(&midiinfo_mtx);
260 	TAILQ_FOREACH(md, &midi_info, md_link) {
261 		if (md->synthunit == unit)
262 			break;
263 	}
264 	mtx_unlock(&midiinfo_mtx);
265 
266 	return md;
267 }
268 
269 /* Create a new midi device info structure. */
270 /* TODO: lock md, then exit. */
271 mididev_info *
272 create_mididev_info_unit(int type, mididev_info *mdinf, synthdev_info *syninf)
273 {
274 	int unit;
275 	mididev_info *md, *mdnew;
276 
277 	/* XXX */
278 	if (!midiinfo_mtx_init) {
279 		midiinfo_mtx_init = 1;
280 		mtx_init(&midiinfo_mtx, "midinf", NULL, MTX_DEF);
281 		TAILQ_INIT(&midi_info);
282 	}
283 
284 	/* As malloc(9) might block, allocate mididev_info now. */
285 	mdnew = malloc(sizeof(mididev_info), M_DEVBUF, M_ZERO);
286 	if (mdnew == NULL)
287 		return NULL;
288 	bcopy(mdinf, mdnew, sizeof(mididev_info));
289 	bcopy(syninf, &mdnew->synth, sizeof(synthdev_info));
290 	midibuf_init(&mdnew->midi_dbuf_in);
291 	midibuf_init(&mdnew->midi_dbuf_out);
292 	midibuf_init(&mdnew->midi_dbuf_passthru);
293 	mtx_init(&mdnew->flagqueue_mtx, "midflq", NULL, MTX_DEF);
294 	mtx_init(&mdnew->synth.vc_mtx, "synsvc", NULL, MTX_DEF);
295 	mtx_init(&mdnew->synth.status_mtx, "synsst", NULL, MTX_DEF);
296 
297 	mtx_lock(&midiinfo_mtx);
298 
299 	switch (type) {
300 	case MDT_MIDI:
301 		mdnew->midiunit = nmidi;
302 		mdnew->synthunit = nmidi;
303 		nmidi++;
304 		break;
305 	case MDT_SYNTH:
306 		mdnew->midiunit = -1;
307 		mdnew->synthunit = nsynth;
308 		nsynth++;
309 		break;
310 	default:
311 		mtx_unlock(&midiinfo_mtx);
312 		midibuf_destroy(&mdnew->midi_dbuf_in);
313 		midibuf_destroy(&mdnew->midi_dbuf_out);
314 		midibuf_destroy(&mdnew->midi_dbuf_passthru);
315 		mtx_destroy(&mdnew->flagqueue_mtx);
316 		mtx_destroy(&mdnew->synth.vc_mtx);
317 		mtx_destroy(&mdnew->synth.status_mtx);
318 		free(mdnew, M_DEVBUF);
319 		panic("unsupported device type");
320 		return NULL;
321 	}
322 	mdnew->mdtype = type;
323 
324 	for (unit = 0 ; ; unit++) {
325 		TAILQ_FOREACH(md, &midi_info, md_link) {
326 			if (md->unit == unit)
327 				break;
328 		}
329 		if (md == NULL)
330 			break;
331 	}
332 
333 	mdnew->unit = unit;
334 	mtx_lock(&mdnew->flagqueue_mtx);
335 	TAILQ_INSERT_TAIL(&midi_info, mdnew, md_link);
336 
337 	mtx_unlock(&midiinfo_mtx);
338 
339 	return mdnew;
340 }
341 
342 /* Return the number of configured devices. */
343 int
344 mididev_info_number(void)
345 {
346 	return nmidi + nsynth;
347 }
348 
349 /* Return the number of configured midi devices. */
350 int
351 mididev_midi_number(void)
352 {
353 	return nmidi;
354 }
355 
356 /* Return the number of configured synth devices. */
357 int
358 mididev_synth_number(void)
359 {
360 	return nsynth;
361 }
362 
363 /*
364  * here are the switches for the main functions. The switches do
365  * all necessary checks on the device number to make sure
366  * that the device is configured. They also provide some default
367  * functionalities so that device-specific drivers have to deal
368  * only with special cases.
369  */
370 
371 static int
372 midiopen(dev_t i_dev, int flags, int mode, struct thread *td)
373 {
374 	int ret;
375 
376 	switch (MIDIDEV(i_dev)) {
377 	case MIDI_DEV_MIDIN:
378 		ret = midi_open(i_dev, flags, mode, td);
379 		break;
380 	case MIDI_DEV_STATUS:
381 		ret = midistat_open(i_dev, flags, mode, td);
382 		break;
383 	default:
384 		ret = ENXIO;
385 		break;
386 	}
387 
388 	return (ret);
389 }
390 
391 static int
392 midiclose(dev_t i_dev, int flags, int mode, struct thread *td)
393 {
394 	int ret;
395 
396 	switch (MIDIDEV(i_dev)) {
397 	case MIDI_DEV_MIDIN:
398 		ret = midi_close(i_dev, flags, mode, td);
399 		break;
400 	case MIDI_DEV_STATUS:
401 		ret = midistat_close(i_dev, flags, mode, td);
402 		break;
403 	default:
404 		ret = ENXIO;
405 		break;
406 	}
407 
408 	return (ret);
409 }
410 
411 static int
412 midiread(dev_t i_dev, struct uio * buf, int flag)
413 {
414 	int ret;
415 
416 	switch (MIDIDEV(i_dev)) {
417 	case MIDI_DEV_MIDIN:
418 		ret = midi_read(i_dev, buf, flag);
419 		break;
420 	case MIDI_DEV_STATUS:
421 		ret = midistat_read(i_dev, buf, flag);
422 		break;
423 	default:
424 		ret = ENXIO;
425 		break;
426 	}
427 
428 	return (ret);
429 }
430 
431 static int
432 midiwrite(dev_t i_dev, struct uio * buf, int flag)
433 {
434 	int ret;
435 
436 	switch (MIDIDEV(i_dev)) {
437 	case MIDI_DEV_MIDIN:
438 		ret = midi_write(i_dev, buf, flag);
439 		break;
440 	default:
441 		ret = ENXIO;
442 		break;
443 	}
444 
445 	return (ret);
446 }
447 
448 static int
449 midiioctl(dev_t i_dev, u_long cmd, caddr_t arg, int mode, struct thread *td)
450 {
451 	int ret;
452 
453 	switch (MIDIDEV(i_dev)) {
454 	case MIDI_DEV_MIDIN:
455 		ret = midi_ioctl(i_dev, cmd, arg, mode, td);
456 		break;
457 	default:
458 		ret = ENXIO;
459 		break;
460 	}
461 
462 	return (ret);
463 }
464 
465 static int
466 midipoll(dev_t i_dev, int events, struct thread *td)
467 {
468 	int ret;
469 
470 	switch (MIDIDEV(i_dev)) {
471 	case MIDI_DEV_MIDIN:
472 		ret = midi_poll(i_dev, events, td);
473 		break;
474 	default:
475 		ret = ENXIO;
476 		break;
477 	}
478 
479 	return (ret);
480 }
481 
482 /*
483  * Followings are the generic methods in midi drivers.
484  */
485 
486 int
487 midi_open(dev_t i_dev, int flags, int mode, struct thread *td)
488 {
489 	int dev, unit, ret;
490 	mididev_info *d;
491 
492 	dev = minor(i_dev);
493 	d = get_mididev_info(i_dev, &unit);
494 
495 	MIDI_DEBUG(printf("midi_open: unit %d, flags 0x%x.\n", unit, flags));
496 
497 	if (d == NULL)
498 		return (ENXIO);
499 
500 	/* Mark this device busy. */
501 	mtx_lock(&d->flagqueue_mtx);
502 	device_busy(d->dev);
503 	if ((d->flags & MIDI_F_BUSY) != 0) {
504 		mtx_unlock(&d->flagqueue_mtx);
505 		printf("midi_open: unit %d is busy.\n", unit);
506 		return (EBUSY);
507 	}
508 	d->fflags = flags;
509 	d->flags |= MIDI_F_BUSY;
510 	d->flags &= ~(MIDI_F_READING | MIDI_F_WRITING);
511 	if ((d->fflags & O_NONBLOCK) != 0)
512 		d->flags |= MIDI_F_NBIO;
513 
514 	/* Init the queue. */
515 	if ((flags & FREAD) != 0)
516 		midibuf_clear(&d->midi_dbuf_in);
517 	if ((flags & FWRITE) != 0) {
518 		midibuf_clear(&d->midi_dbuf_out);
519 		midibuf_clear(&d->midi_dbuf_passthru);
520 	}
521 
522 	mtx_unlock(&d->flagqueue_mtx);
523 
524 	if (d->open == NULL)
525 		ret = 0;
526 	else
527 		ret = d->open(i_dev, flags, mode, td);
528 
529 	mtx_lock(&d->flagqueue_mtx);
530 
531 	/* Begin recording if nonblocking. */
532 	if ((d->flags & (MIDI_F_READING | MIDI_F_NBIO)) == MIDI_F_NBIO && (d->fflags & FREAD) != 0)
533 	d->callback(d, MIDI_CB_START | MIDI_CB_RD);
534 
535 	mtx_unlock(&d->flagqueue_mtx);
536 
537 	MIDI_DEBUG(printf("midi_open: opened.\n"));
538 
539 	return (ret);
540 }
541 
542 int
543 midi_close(dev_t i_dev, int flags, int mode, struct thread *td)
544 {
545 	int dev, unit, ret;
546 	mididev_info *d;
547 
548 	dev = minor(i_dev);
549 	d = get_mididev_info(i_dev, &unit);
550 
551 	MIDI_DEBUG(printf("midi_close: unit %d.\n", unit));
552 
553 	if (d == NULL)
554 		return (ENXIO);
555 
556 	mtx_lock(&d->flagqueue_mtx);
557 
558 	/* Stop recording and playing. */
559 	if ((d->flags & MIDI_F_READING) != 0)
560 		d->callback(d, MIDI_CB_ABORT | MIDI_CB_RD);
561 	if ((d->flags & MIDI_F_WRITING) != 0)
562 		d->callback(d, MIDI_CB_ABORT | MIDI_CB_WR);
563 
564 	/* Clear the queues. */
565 	if ((d->fflags & FREAD) != 0)
566 		midibuf_clear(&d->midi_dbuf_in);
567 	if ((d->fflags & FWRITE) != 0) {
568 		midibuf_clear(&d->midi_dbuf_out);
569 		midibuf_clear(&d->midi_dbuf_passthru);
570 	}
571 
572 	/* Stop playing and unmark this device busy. */
573 	d->flags &= ~MIDI_F_BUSY;
574 	d->fflags = 0;
575 
576 	device_unbusy(d->dev);
577 
578 	mtx_unlock(&d->flagqueue_mtx);
579 
580 	if (d->close == NULL)
581 		ret = 0;
582 	else
583 		ret = d->close(i_dev, flags, mode, td);
584 
585 	MIDI_DEBUG(printf("midi_close: closed.\n"));
586 
587 	return (ret);
588 }
589 
590 int
591 midi_read(dev_t i_dev, struct uio * buf, int flag)
592 {
593 	int dev, unit, len, lenr, ret;
594 	mididev_info *d ;
595 	u_char *uiobuf;
596 
597 	dev = minor(i_dev);
598 
599 	d = get_mididev_info(i_dev, &unit);
600 	MIDI_DEBUG(printf("midi_read: unit %d, resid %d.\n", unit, buf->uio_resid));
601 
602 	if (d == NULL)
603 		return (ENXIO);
604 
605 	ret = 0;
606 
607 	len = buf->uio_resid;
608 	lenr = 0;
609 
610 	uiobuf = (u_char *)malloc(len, M_DEVBUF, M_ZERO);
611 	if (uiobuf == NULL)
612 		return (ENOMEM);
613 
614 	mtx_lock(&d->flagqueue_mtx);
615 
616 	/* Begin recording. */
617 	d->callback(d, MIDI_CB_START | MIDI_CB_RD);
618 
619 	/* Have we got the data to read? */
620 	if ((d->flags & MIDI_F_NBIO) != 0 && d->midi_dbuf_in.rl == 0)
621 		ret = EAGAIN;
622 	else {
623 		if ((d->flags & MIDI_F_NBIO) != 0 && len > d->midi_dbuf_in.rl)
624 			len = d->midi_dbuf_in.rl;
625 		ret = midibuf_seqread(&d->midi_dbuf_in, uiobuf, len, &lenr,
626 				      d->callback, d, MIDI_CB_START | MIDI_CB_RD,
627 				      &d->flagqueue_mtx);
628 	}
629 
630 	mtx_unlock(&d->flagqueue_mtx);
631 
632 	if (lenr > 0)
633 		ret = uiomove(uiobuf, lenr, buf);
634 
635 	free(uiobuf, M_DEVBUF);
636 
637 	MIDI_DEBUG(printf("midi_read: ret %d, resid %d.\n", ret, buf->uio_resid));
638 
639 	return (ret);
640 }
641 
642 int
643 midi_write(dev_t i_dev, struct uio * buf, int flag)
644 {
645 	int dev, unit, len, len2, lenw, ret;
646 	mididev_info *d;
647 	u_char *uiobuf;
648 
649 	dev = minor(i_dev);
650 	d = get_mididev_info(i_dev, &unit);
651 
652 	MIDI_DEBUG(printf("midi_write: unit %d.\n", unit));
653 
654 	if (d == NULL)
655 		return (ENXIO);
656 
657 	ret = 0;
658 
659 	len = buf->uio_resid;
660 	lenw = 0;
661 
662 	uiobuf = (u_char *)malloc(len, M_DEVBUF, M_ZERO);
663 	if (uiobuf == NULL)
664 		return (ENOMEM);
665 
666 	ret = uiomove(uiobuf, len, buf);
667 	if (ret != 0) {
668 		free(uiobuf, M_DEVBUF);
669 		return (ret);
670 	}
671 
672 	mtx_lock(&d->flagqueue_mtx);
673 
674 	/* Have we got the data to write? */
675 	if ((d->flags & MIDI_F_NBIO) != 0 && d->midi_dbuf_out.fl == 0) {
676 		/* Begin playing. */
677 		d->callback(d, MIDI_CB_START | MIDI_CB_WR);
678 		ret = EAGAIN;
679 	} else {
680 		len2 = len;
681 		if ((d->flags & MIDI_F_NBIO) != 0 && len2 > d->midi_dbuf_out.fl)
682 			len2 = d->midi_dbuf_out.fl;
683 		ret = midibuf_seqwrite(&d->midi_dbuf_out, uiobuf, len2, &lenw,
684 				       d->callback, d, MIDI_CB_START | MIDI_CB_WR,
685 				       &d->flagqueue_mtx);
686 	}
687 
688 	mtx_unlock(&d->flagqueue_mtx);
689 
690 	free(uiobuf, M_DEVBUF);
691 	buf->uio_resid = len - lenw;
692 
693 	return (ret);
694 }
695 
696 /*
697  * generic midi ioctl. Functions of the default driver can be
698  * overridden by the device-specific ioctl call.
699  * If a device-specific call returns ENOSYS (Function not implemented),
700  * the default driver is called. Otherwise, the returned value
701  * is passed up.
702  *
703  * The default handler, for many parameters, sets the value in the
704  * descriptor, sets MIDI_F_INIT, and calls the callback function with
705  * reason INIT. If successful, the callback returns 1 and the caller
706  * can update the parameter.
707  */
708 
709 int
710 midi_ioctl(dev_t i_dev, u_long cmd, caddr_t arg, int mode, struct thread *td)
711 {
712 	int ret = ENOSYS, dev, unit;
713 	mididev_info *d;
714 	struct snd_size *sndsize;
715 	snd_sync_parm *sp;
716 
717 	dev = minor(i_dev);
718 	d = get_mididev_info(i_dev, &unit);
719 
720 	if (d == NULL)
721 		return (ENXIO);
722 
723 	if (d->ioctl)
724 		ret = d->ioctl(i_dev, cmd, arg, mode, td);
725 	if (ret != ENOSYS)
726 		return ret;
727 
728 	/*
729 	 * pass control to the default ioctl handler. Set ret to 0 now.
730 	 */
731 	ret = 0;
732 
733 	MIDI_DEBUG(printf("midi_ioctl: unit %d, cmd %s.\n", unit, midi_cmdname(cmd, cmdtab_midiioctl)));
734 
735 	/*
736 	 * all routines are called with int. blocked. Make sure that
737 	 * ints are re-enabled when calling slow or blocking functions!
738 	 */
739 	switch(cmd) {
740 
741 		/*
742 		 * we start with the new ioctl interface.
743 		 */
744 	case AIONWRITE:	/* how many bytes can write ? */
745 		mtx_lock(&d->flagqueue_mtx);
746 		*(int *)arg = d->midi_dbuf_out.fl;
747 		mtx_unlock(&d->flagqueue_mtx);
748 		MIDI_DEBUG(printf("midi_ioctl: fl %d.\n", *(int *)arg));
749 		break;
750 
751 	case AIOSSIZE:     /* set the current blocksize */
752 		sndsize = (struct snd_size *)arg;
753 		MIDI_DEBUG(printf("midi_ioctl: play %d, rec %d.\n", sndsize->play_size, sndsize->rec_size));
754 		mtx_lock(&d->flagqueue_mtx);
755 		if (sndsize->play_size <= d->midi_dbuf_out.unit_size && sndsize->rec_size <= d->midi_dbuf_in.unit_size) {
756 			d->midi_dbuf_out.blocksize = d->midi_dbuf_out.unit_size;
757 			d->midi_dbuf_in.blocksize = d->midi_dbuf_in.unit_size;
758 			sndsize->play_size = d->midi_dbuf_out.blocksize;
759 			sndsize->rec_size = d->midi_dbuf_in.blocksize;
760 			d->flags &= ~MIDI_F_HAS_SIZE;
761 			mtx_unlock(&d->flagqueue_mtx);
762 		}
763 		else {
764 			if (sndsize->play_size > d->midi_dbuf_out.bufsize / 4)
765 				sndsize->play_size = d->midi_dbuf_out.bufsize / 4;
766 			if (sndsize->rec_size > d->midi_dbuf_in.bufsize / 4)
767 				sndsize->rec_size = d->midi_dbuf_in.bufsize / 4;
768 			/* Round up the size to the multiple of EV_SZ. */
769 			d->midi_dbuf_out.blocksize =
770 			    ((sndsize->play_size + d->midi_dbuf_out.unit_size - 1)
771 			     / d->midi_dbuf_out.unit_size) * d->midi_dbuf_out.unit_size;
772 			d->midi_dbuf_in.blocksize =
773 			    ((sndsize->rec_size + d->midi_dbuf_in.unit_size - 1)
774 			     / d->midi_dbuf_in.unit_size) * d->midi_dbuf_in.unit_size;
775 			sndsize->play_size = d->midi_dbuf_out.blocksize;
776 			sndsize->rec_size = d->midi_dbuf_in.blocksize;
777 			d->flags |= MIDI_F_HAS_SIZE;
778 			mtx_unlock(&d->flagqueue_mtx);
779 		}
780 
781 		ret = 0;
782 		break;
783 
784 	case AIOGSIZE:	/* get the current blocksize */
785 		sndsize = (struct snd_size *)arg;
786 		mtx_lock(&d->flagqueue_mtx);
787 		sndsize->play_size = d->midi_dbuf_out.blocksize;
788 		sndsize->rec_size = d->midi_dbuf_in.blocksize;
789 		mtx_unlock(&d->flagqueue_mtx);
790 		MIDI_DEBUG(printf("midi_ioctl: play %d, rec %d.\n", sndsize->play_size, sndsize->rec_size));
791 
792 		ret = 0;
793 		break;
794 
795 	case AIOSTOP:
796 		mtx_lock(&d->flagqueue_mtx);
797 		if (*(int *)arg == AIOSYNC_PLAY) /* play */
798 			*(int *)arg = d->callback(d, MIDI_CB_STOP | MIDI_CB_WR);
799 		else if (*(int *)arg == AIOSYNC_CAPTURE)
800 			*(int *)arg = d->callback(d, MIDI_CB_STOP | MIDI_CB_RD);
801 		else {
802 			MIDI_DEBUG(printf("midi_ioctl: bad channel 0x%x.\n", *(int *)arg));
803 			*(int *)arg = 0 ;
804 		}
805 		mtx_unlock(&d->flagqueue_mtx);
806 		break ;
807 
808 	case AIOSYNC:
809 		sp = (snd_sync_parm *)arg;
810 		MIDI_DEBUG(printf("midi_ioctl: unimplemented, chan 0x%03lx pos %lu.\n",
811 			   sp->chan,
812 			   sp->pos));
813 		break;
814 		/*
815 		 * here follow the standard ioctls (filio.h etc.)
816 		 */
817 	case FIONREAD: /* get # bytes to read */
818 		mtx_lock(&d->flagqueue_mtx);
819 		*(int *)arg = d->midi_dbuf_in.rl;
820 		mtx_unlock(&d->flagqueue_mtx);
821 		MIDI_DEBUG(printf("midi_ioctl: rl %d.\n", *(int *)arg));
822 		break;
823 
824 	case FIOASYNC: /*set/clear async i/o */
825 		MIDI_DEBUG(printf("FIOASYNC\n"));
826 		    break;
827 
828 	case FIONBIO: /* set/clear non-blocking i/o */
829 		mtx_lock(&d->flagqueue_mtx);
830 		if (*(int *)arg == 0)
831 			d->flags &= ~MIDI_F_NBIO ;
832 		else
833 			d->flags |= MIDI_F_NBIO ;
834 		mtx_unlock(&d->flagqueue_mtx);
835 		MIDI_DEBUG(printf("midi_ioctl: arg %d.\n", *(int *)arg));
836 		break ;
837 
838 	case MIOSPASSTHRU: /* set/clear passthru */
839 		mtx_lock(&d->flagqueue_mtx);
840 		if (*(int *)arg == 0)
841 			d->flags &= ~MIDI_F_PASSTHRU ;
842 		else
843 			d->flags |= MIDI_F_PASSTHRU ;
844 
845 		/* Init the queue. */
846 		midibuf_clear(&d->midi_dbuf_passthru);
847 
848 		mtx_unlock(&d->flagqueue_mtx);
849 		MIDI_DEBUG(printf("midi_ioctl: passthru %d.\n", *(int *)arg));
850 
851 		/* FALLTHROUGH */
852 	case MIOGPASSTHRU: /* get passthru */
853 		mtx_lock(&d->flagqueue_mtx);
854 		if ((d->flags & MIDI_F_PASSTHRU) != 0)
855 			*(int *)arg = 1;
856 		else
857 			*(int *)arg = 0;
858 		mtx_unlock(&d->flagqueue_mtx);
859 		MIDI_DEBUG(printf("midi_ioctl: passthru %d.\n", *(int *)arg));
860 		break;
861 
862 	default:
863 		MIDI_DEBUG(printf("midi_ioctl: default ioctl midi%d subdev %d fn 0x%08lx fail\n",
864 				  unit, dev & 0xf, cmd));
865 		ret = EINVAL;
866 		break ;
867 	}
868 	return ret ;
869 }
870 
871 int
872 midi_poll(dev_t i_dev, int events, struct thread *td)
873 {
874 	int unit, dev, ret, lim;
875 	mididev_info *d;
876 
877 	dev = minor(i_dev);
878 	d = get_mididev_info(i_dev, &unit);
879 
880 	MIDI_DEBUG(printf("midi_poll: unit %d.\n", unit));
881 
882 	if (d == NULL)
883 		return (ENXIO);
884 
885 	ret = 0;
886 
887 	mtx_lock(&d->flagqueue_mtx);
888 
889 	/* Look up the apropriate queue and select it. */
890 	if ((events & (POLLOUT | POLLWRNORM)) != 0) {
891 		/* Start playing. */
892 		d->callback(d, MIDI_CB_START | MIDI_CB_WR);
893 
894 		/* Find out the boundary. */
895 		if ((d->flags & MIDI_F_HAS_SIZE) != 0)
896 			lim = d->midi_dbuf_out.blocksize;
897 		else
898 			lim = d->midi_dbuf_out.unit_size;
899 		if (d->midi_dbuf_out.fl < lim)
900 			/* No enough space, record select. */
901 			selrecord(td, &d->midi_dbuf_out.sel);
902 		else
903 			/* We can write now. */
904 			ret |= events & (POLLOUT | POLLWRNORM);
905 	}
906 	if ((events & (POLLIN | POLLRDNORM)) != 0) {
907 		/* Start recording. */
908 		d->callback(d, MIDI_CB_START | MIDI_CB_RD);
909 
910 		/* Find out the boundary. */
911 		if ((d->flags & MIDI_F_HAS_SIZE) != 0)
912 			lim = d->midi_dbuf_in.blocksize;
913 		else
914 			lim = d->midi_dbuf_in.unit_size;
915 		if (d->midi_dbuf_in.rl < lim)
916 			/* No data ready, record select. */
917 			selrecord(td, &d->midi_dbuf_in.sel);
918 		else
919 			/* We can write now. */
920 			ret |= events & (POLLIN | POLLRDNORM);
921 	}
922 
923 	mtx_unlock(&d->flagqueue_mtx);
924 
925 	return (ret);
926 }
927 
928 void
929 midi_intr(mididev_info *d)
930 {
931 	if (d->intr != NULL)
932 		d->intr(d->intrarg, d);
933 }
934 
935 /* Flush the output queue. */
936 #define MIDI_SYNC_TIMEOUT 1
937 int
938 midi_sync(mididev_info *d)
939 {
940 	int i, rl;
941 
942 	mtx_assert(&d->flagqueue_mtx, MA_OWNED);
943 
944 	MIDI_DEBUG(printf("midi_sync: unit %d.\n", d->unit));
945 
946 	while (d->midi_dbuf_out.rl > 0) {
947 		if ((d->flags & MIDI_F_WRITING) == 0)
948 			d->callback(d, MIDI_CB_START | MIDI_CB_WR);
949 		rl = d->midi_dbuf_out.rl;
950 		i = cv_timedwait_sig(&d->midi_dbuf_out.cv_out,
951 				     &d->flagqueue_mtx,
952 				     (d->midi_dbuf_out.bufsize * 10 * hz / 38400)
953 				     + MIDI_SYNC_TIMEOUT * hz);
954 		if (i == EINTR || i == ERESTART) {
955 			if (i == EINTR)
956 				d->callback(d, MIDI_CB_STOP | MIDI_CB_WR);
957 			return (i);
958 		}
959 		if (i == EWOULDBLOCK && rl == d->midi_dbuf_out.rl) {
960 			/* A queue seems to be stuck up. Give up and clear the queue. */
961 			d->callback(d, MIDI_CB_STOP | MIDI_CB_WR);
962 			midibuf_clear(&d->midi_dbuf_out);
963 			return (0);
964 		}
965 	}
966 
967 	return 0;
968 }
969 
970 /*
971  * These handle the status message of the midi drivers.
972  */
973 
974 int
975 midistat_open(dev_t i_dev, int flags, int mode, struct thread *td)
976 {
977 	if (midistatbusy)
978 		return (EBUSY);
979 
980 	bzero(midistatbuf, sizeof(midistatbuf));
981 	midistatptr = 0;
982 	if (midi_initstatus(midistatbuf, sizeof(midistatbuf) - 1))
983 		return (ENOMEM);
984 
985 	midistatbusy = 1;
986 
987 	return (0);
988 }
989 
990 int
991 midistat_close(dev_t i_dev, int flags, int mode, struct thread *td)
992 {
993 	midistatbusy = 0;
994 
995 	return (0);
996 }
997 
998 int
999 midistat_read(dev_t i_dev, struct uio * buf, int flag)
1000 {
1001 	return midi_readstatus(midistatbuf, &midistatptr, buf);
1002 }
1003 
1004 /*
1005  * finally, some "libraries"
1006  */
1007 
1008 /* Inits the buffer for /dev/midistat. */
1009 static int
1010 midi_initstatus(char *buf, int size)
1011 {
1012 	int i, p;
1013 	device_t dev;
1014 	mididev_info *md;
1015 
1016 	p = 0;
1017 	p += snprintf(buf, size, "FreeBSD Midi Driver (newmidi) %s %s\nInstalled devices:\n", __DATE__, __TIME__);
1018 	for (i = 0 ; i < mididev_info_number() ; i++) {
1019 		md = get_mididev_info_unit(i);
1020 		if (!MIDICONFED(md))
1021 			continue;
1022 		dev = devclass_get_device(midi_devclass, i);
1023 		if (p < size)
1024 			p += snprintf(&buf[p], size - p, "midi%d: <%s> %s\n", i, device_get_desc(dev), md->midistat);
1025 		else
1026 			return (1);
1027 	}
1028 
1029 	return (0);
1030 }
1031 
1032 /* Reads the status message. */
1033 static int
1034 midi_readstatus(char *buf, int *ptr, struct uio *uio)
1035 {
1036 	int len;
1037 
1038 	len = min(uio->uio_resid, strlen(&buf[*ptr]));
1039 	if (len > 0) {
1040 		uiomove(&buf[*ptr], len, uio);
1041 		*ptr += len;
1042 	}
1043 
1044 	return (0);
1045 }
1046 
1047 char
1048 *midi_cmdname(int cmd, midi_cmdtab *tab)
1049 {
1050 	while (tab->name != NULL) {
1051 		if (cmd == tab->cmd)
1052 			return (tab->name);
1053 		tab++;
1054 	}
1055 
1056 	return ("unknown");
1057 }
1058