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: releng/5.1/sys/dev/sound/midi/midi.c 111815 2003-03-03 12:15:54Z phk $
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 }
Cache object: 01bc7b003a06866959f34cefc4a15c27
|