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