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