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