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