1 /*- 2 * SPDX-License-Identifier: BSD-2-Clause 3 * 4 * Copyright (c) 2003 Mathew Kanner 5 * Copyright (c) 1998 The NetBSD Foundation, Inc. 6 * All rights reserved. 7 * 8 * This code is derived from software contributed to The NetBSD Foundation 9 * by Lennart Augustsson (augustss@netbsd.org). 10 * 11 * Redistribution and use in source and binary forms, with or without 12 * modification, are permitted provided that the following conditions 13 * are met: 14 * 1. Redistributions of source code must retain the above copyright 15 * notice, this list of conditions and the following disclaimer. 16 * 2. Redistributions in binary form must reproduce the above copyright 17 * notice, this list of conditions and the following disclaimer in the 18 * documentation and/or other materials provided with the distribution. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 21 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 22 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 23 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 24 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 25 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 26 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 27 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 28 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 29 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 30 * POSSIBILITY OF SUCH DAMAGE. 31 */ 32 33 #include <sys/param.h> 34 #include <sys/systm.h> 35 #include <sys/queue.h> 36 #include <sys/kernel.h> 37 #include <sys/lock.h> 38 #include <sys/mutex.h> 39 #include <sys/proc.h> 40 #include <sys/signalvar.h> 41 #include <sys/conf.h> 42 #include <sys/selinfo.h> 43 #include <sys/sysctl.h> 44 #include <sys/malloc.h> 45 #include <sys/sx.h> 46 #include <sys/proc.h> 47 #include <sys/fcntl.h> 48 #include <sys/types.h> 49 #include <sys/uio.h> 50 #include <sys/poll.h> 51 #include <sys/sbuf.h> 52 #include <sys/kobj.h> 53 #include <sys/module.h> 54 55 #ifdef HAVE_KERNEL_OPTION_HEADERS 56 #include "opt_snd.h" 57 #endif 58 59 #include <dev/sound/midi/midi.h> 60 #include "mpu_if.h" 61 62 #include <dev/sound/midi/midiq.h> 63 MALLOC_DEFINE(M_MIDI, "midi buffers", "Midi data allocation area"); 64 65 #ifndef KOBJMETHOD_END 66 #define KOBJMETHOD_END { NULL, NULL } 67 #endif 68 69 #define MIDI_DEV_MIDICTL 12 70 71 enum midi_states { 72 MIDI_IN_START, MIDI_IN_SYSEX, MIDI_IN_DATA 73 }; 74 75 #define MIDI_NAMELEN 16 76 struct snd_midi { 77 KOBJ_FIELDS; 78 struct mtx lock; /* Protects all but queues */ 79 void *cookie; 80 81 int unit; /* Should only be used in midistat */ 82 int channel; /* Should only be used in midistat */ 83 84 int busy; 85 int flags; /* File flags */ 86 char name[MIDI_NAMELEN]; 87 struct mtx qlock; /* Protects inq, outq and flags */ 88 MIDIQ_HEAD(, char) inq, outq; 89 int rchan, wchan; 90 struct selinfo rsel, wsel; 91 int hiwat; /* QLEN(outq)>High-water -> disable 92 * writes from userland */ 93 enum midi_states inq_state; 94 int inq_status, inq_left; /* Variables for the state machine in 95 * Midi_in, this is to provide that 96 * signals only get issued only 97 * complete command packets. */ 98 struct proc *async; 99 struct cdev *dev; 100 TAILQ_ENTRY(snd_midi) link; 101 }; 102 103 TAILQ_HEAD(, snd_midi) midi_devs; 104 105 struct sx mstat_lock; 106 107 static d_open_t midi_open; 108 static d_close_t midi_close; 109 static d_ioctl_t midi_ioctl; 110 static d_read_t midi_read; 111 static d_write_t midi_write; 112 static d_poll_t midi_poll; 113 114 static struct cdevsw midi_cdevsw = { 115 .d_version = D_VERSION, 116 .d_open = midi_open, 117 .d_close = midi_close, 118 .d_read = midi_read, 119 .d_write = midi_write, 120 .d_ioctl = midi_ioctl, 121 .d_poll = midi_poll, 122 .d_name = "rmidi", 123 }; 124 125 static int midi_destroy(struct snd_midi *, int); 126 static int midi_load(void); 127 static int midi_unload(void); 128 129 SYSCTL_NODE(_hw, OID_AUTO, midi, CTLFLAG_RD | CTLFLAG_MPSAFE, 0, 130 "Midi driver"); 131 132 int midi_debug; 133 /* XXX: should this be moved into debug.midi? */ 134 SYSCTL_INT(_hw_midi, OID_AUTO, debug, CTLFLAG_RW, &midi_debug, 0, ""); 135 136 #define MIDI_DEBUG(l,a) if(midi_debug>=l) a 137 138 void 139 midistat_lock(void) 140 { 141 sx_xlock(&mstat_lock); 142 } 143 144 void 145 midistat_unlock(void) 146 { 147 sx_xunlock(&mstat_lock); 148 } 149 150 void 151 midistat_lockassert(void) 152 { 153 sx_assert(&mstat_lock, SA_XLOCKED); 154 } 155 156 /* 157 * Register a new rmidi device. cls midi_if interface unit == 0 means 158 * auto-assign new unit number unit != 0 already assigned a unit number, eg. 159 * not the first channel provided by this device. channel, sub-unit 160 * cookie is passed back on MPU calls Typical device drivers will call with 161 * unit=0, channel=1..(number of channels) and cookie=soft_c and won't care 162 * what unit number is used. 163 * 164 * It is an error to call midi_init with an already used unit/channel combo. 165 */ 166 struct snd_midi * 167 midi_init(kobj_class_t cls, int unit, int channel, void *cookie) 168 { 169 struct snd_midi *m; 170 int i; 171 int inqsize, outqsize; 172 uint8_t *buf; 173 174 MIDI_DEBUG(1, printf("midiinit: unit %d/%d.\n", unit, channel)); 175 midistat_lock(); 176 /* 177 * Protect against call with existing unit/channel or auto-allocate a 178 * new unit number. 179 */ 180 i = -1; 181 TAILQ_FOREACH(m, &midi_devs, link) { 182 mtx_lock(&m->lock); 183 if (unit != 0) { 184 if (m->unit == unit && m->channel == channel) { 185 mtx_unlock(&m->lock); 186 goto err0; 187 } 188 } else { 189 /* 190 * Find a better unit number 191 */ 192 if (m->unit > i) 193 i = m->unit; 194 } 195 mtx_unlock(&m->lock); 196 } 197 198 if (unit == 0) 199 unit = i + 1; 200 201 MIDI_DEBUG(1, printf("midiinit #2: unit %d/%d.\n", unit, channel)); 202 m = malloc(sizeof(*m), M_MIDI, M_WAITOK | M_ZERO); 203 kobj_init((kobj_t)m, cls); 204 inqsize = MPU_INQSIZE(m, cookie); 205 outqsize = MPU_OUTQSIZE(m, cookie); 206 207 MIDI_DEBUG(1, printf("midiinit queues %d/%d.\n", inqsize, outqsize)); 208 if (!inqsize && !outqsize) 209 goto err1; 210 211 mtx_init(&m->lock, "raw midi", NULL, 0); 212 mtx_init(&m->qlock, "q raw midi", NULL, 0); 213 214 mtx_lock(&m->lock); 215 mtx_lock(&m->qlock); 216 217 if (inqsize) 218 buf = malloc(sizeof(uint8_t) * inqsize, M_MIDI, M_NOWAIT); 219 else 220 buf = NULL; 221 222 MIDIQ_INIT(m->inq, buf, inqsize); 223 224 if (outqsize) 225 buf = malloc(sizeof(uint8_t) * outqsize, M_MIDI, M_NOWAIT); 226 else 227 buf = NULL; 228 m->hiwat = outqsize / 2; 229 230 MIDIQ_INIT(m->outq, buf, outqsize); 231 232 if ((inqsize && !MIDIQ_BUF(m->inq)) || 233 (outqsize && !MIDIQ_BUF(m->outq))) 234 goto err2; 235 236 m->busy = 0; 237 m->flags = 0; 238 m->unit = unit; 239 m->channel = channel; 240 m->cookie = cookie; 241 242 if (MPU_INIT(m, cookie)) 243 goto err2; 244 245 mtx_unlock(&m->lock); 246 mtx_unlock(&m->qlock); 247 248 TAILQ_INSERT_TAIL(&midi_devs, m, link); 249 250 midistat_unlock(); 251 252 m->dev = make_dev(&midi_cdevsw, unit, UID_ROOT, GID_WHEEL, 0666, 253 "midi%d.%d", unit, channel); 254 m->dev->si_drv1 = m; 255 256 return m; 257 258 err2: 259 mtx_destroy(&m->qlock); 260 mtx_destroy(&m->lock); 261 262 if (MIDIQ_BUF(m->inq)) 263 free(MIDIQ_BUF(m->inq), M_MIDI); 264 if (MIDIQ_BUF(m->outq)) 265 free(MIDIQ_BUF(m->outq), M_MIDI); 266 err1: 267 free(m, M_MIDI); 268 err0: 269 midistat_unlock(); 270 MIDI_DEBUG(1, printf("midi_init ended in error\n")); 271 return NULL; 272 } 273 274 /* 275 * midi_uninit does not call MIDI_UNINIT, as since this is the implementors 276 * entry point. midi_uninit if fact, does not send any methods. A call to 277 * midi_uninit is a defacto promise that you won't manipulate ch anymore 278 */ 279 int 280 midi_uninit(struct snd_midi *m) 281 { 282 int err; 283 284 err = EBUSY; 285 midistat_lock(); 286 mtx_lock(&m->lock); 287 if (m->busy) { 288 if (!(m->rchan || m->wchan)) 289 goto err; 290 291 if (m->rchan) { 292 wakeup(&m->rchan); 293 m->rchan = 0; 294 } 295 if (m->wchan) { 296 wakeup(&m->wchan); 297 m->wchan = 0; 298 } 299 } 300 err = midi_destroy(m, 0); 301 if (!err) 302 goto exit; 303 304 err: 305 mtx_unlock(&m->lock); 306 exit: 307 midistat_unlock(); 308 return err; 309 } 310 311 #ifdef notdef 312 static int midi_lengths[] = {2, 2, 2, 2, 1, 1, 2, 0}; 313 314 #endif /* notdef */ 315 /* Number of bytes in a MIDI command */ 316 #define MIDI_LENGTH(d) (midi_lengths[((d) >> 4) & 7]) 317 #define MIDI_ACK 0xfe 318 #define MIDI_IS_STATUS(d) ((d) >= 0x80) 319 #define MIDI_IS_COMMON(d) ((d) >= 0xf0) 320 321 #define MIDI_SYSEX_START 0xF0 322 #define MIDI_SYSEX_END 0xF7 323 324 /* 325 * midi_in: process all data until the queue is full, then discards the rest. 326 * Since midi_in is a state machine, data discards can cause it to get out of 327 * whack. Process as much as possible. It calls, wakeup, selnotify and 328 * psignal at most once. 329 */ 330 int 331 midi_in(struct snd_midi *m, uint8_t *buf, int size) 332 { 333 /* int i, sig, enq; */ 334 int used; 335 336 /* uint8_t data; */ 337 MIDI_DEBUG(5, printf("midi_in: m=%p size=%d\n", m, size)); 338 339 /* 340 * XXX: locking flub 341 */ 342 if (!(m->flags & M_RX)) 343 return size; 344 345 used = 0; 346 347 mtx_lock(&m->qlock); 348 #if 0 349 /* 350 * Don't bother queuing if not in read mode. Discard everything and 351 * return size so the caller doesn't freak out. 352 */ 353 354 if (!(m->flags & M_RX)) 355 return size; 356 357 for (i = sig = 0; i < size; i++) { 358 data = buf[i]; 359 enq = 0; 360 if (data == MIDI_ACK) 361 continue; 362 363 switch (m->inq_state) { 364 case MIDI_IN_START: 365 if (MIDI_IS_STATUS(data)) { 366 switch (data) { 367 case 0xf0: /* Sysex */ 368 m->inq_state = MIDI_IN_SYSEX; 369 break; 370 case 0xf1: /* MTC quarter frame */ 371 case 0xf3: /* Song select */ 372 m->inq_state = MIDI_IN_DATA; 373 enq = 1; 374 m->inq_left = 1; 375 break; 376 case 0xf2: /* Song position pointer */ 377 m->inq_state = MIDI_IN_DATA; 378 enq = 1; 379 m->inq_left = 2; 380 break; 381 default: 382 if (MIDI_IS_COMMON(data)) { 383 enq = 1; 384 sig = 1; 385 } else { 386 m->inq_state = MIDI_IN_DATA; 387 enq = 1; 388 m->inq_status = data; 389 m->inq_left = MIDI_LENGTH(data); 390 } 391 break; 392 } 393 } else if (MIDI_IS_STATUS(m->inq_status)) { 394 m->inq_state = MIDI_IN_DATA; 395 if (!MIDIQ_FULL(m->inq)) { 396 used++; 397 MIDIQ_ENQ(m->inq, &m->inq_status, 1); 398 } 399 enq = 1; 400 m->inq_left = MIDI_LENGTH(m->inq_status) - 1; 401 } 402 break; 403 /* 404 * End of case MIDI_IN_START: 405 */ 406 407 case MIDI_IN_DATA: 408 enq = 1; 409 if (--m->inq_left <= 0) 410 sig = 1;/* deliver data */ 411 break; 412 case MIDI_IN_SYSEX: 413 if (data == MIDI_SYSEX_END) 414 m->inq_state = MIDI_IN_START; 415 break; 416 } 417 418 if (enq) 419 if (!MIDIQ_FULL(m->inq)) { 420 MIDIQ_ENQ(m->inq, &data, 1); 421 used++; 422 } 423 /* 424 * End of the state machines main "for loop" 425 */ 426 } 427 if (sig) { 428 #endif 429 MIDI_DEBUG(6, printf("midi_in: len %jd avail %jd\n", 430 (intmax_t)MIDIQ_LEN(m->inq), 431 (intmax_t)MIDIQ_AVAIL(m->inq))); 432 if (MIDIQ_AVAIL(m->inq) > size) { 433 used = size; 434 MIDIQ_ENQ(m->inq, buf, size); 435 } else { 436 MIDI_DEBUG(4, printf("midi_in: Discarding data qu\n")); 437 mtx_unlock(&m->qlock); 438 return 0; 439 } 440 if (m->rchan) { 441 wakeup(&m->rchan); 442 m->rchan = 0; 443 } 444 selwakeup(&m->rsel); 445 if (m->async) { 446 PROC_LOCK(m->async); 447 kern_psignal(m->async, SIGIO); 448 PROC_UNLOCK(m->async); 449 } 450 #if 0 451 } 452 #endif 453 mtx_unlock(&m->qlock); 454 return used; 455 } 456 457 /* 458 * midi_out: The only clearer of the M_TXEN flag. 459 */ 460 int 461 midi_out(struct snd_midi *m, uint8_t *buf, int size) 462 { 463 int used; 464 465 /* 466 * XXX: locking flub 467 */ 468 if (!(m->flags & M_TXEN)) 469 return 0; 470 471 MIDI_DEBUG(2, printf("midi_out: %p\n", m)); 472 mtx_lock(&m->qlock); 473 used = MIN(size, MIDIQ_LEN(m->outq)); 474 MIDI_DEBUG(3, printf("midi_out: used %d\n", used)); 475 if (used) 476 MIDIQ_DEQ(m->outq, buf, used); 477 if (MIDIQ_EMPTY(m->outq)) { 478 m->flags &= ~M_TXEN; 479 MPU_CALLBACKP(m, m->cookie, m->flags); 480 } 481 if (used && MIDIQ_AVAIL(m->outq) > m->hiwat) { 482 if (m->wchan) { 483 wakeup(&m->wchan); 484 m->wchan = 0; 485 } 486 selwakeup(&m->wsel); 487 if (m->async) { 488 PROC_LOCK(m->async); 489 kern_psignal(m->async, SIGIO); 490 PROC_UNLOCK(m->async); 491 } 492 } 493 mtx_unlock(&m->qlock); 494 return used; 495 } 496 497 int 498 midi_open(struct cdev *i_dev, int flags, int mode, struct thread *td) 499 { 500 struct snd_midi *m = i_dev->si_drv1; 501 int retval; 502 503 MIDI_DEBUG(1, printf("midiopen %p %s %s\n", td, 504 flags & FREAD ? "M_RX" : "", flags & FWRITE ? "M_TX" : "")); 505 if (m == NULL) 506 return ENXIO; 507 508 mtx_lock(&m->lock); 509 mtx_lock(&m->qlock); 510 511 retval = 0; 512 513 if (flags & FREAD) { 514 if (MIDIQ_SIZE(m->inq) == 0) 515 retval = ENXIO; 516 else if (m->flags & M_RX) 517 retval = EBUSY; 518 if (retval) 519 goto err; 520 } 521 if (flags & FWRITE) { 522 if (MIDIQ_SIZE(m->outq) == 0) 523 retval = ENXIO; 524 else if (m->flags & M_TX) 525 retval = EBUSY; 526 if (retval) 527 goto err; 528 } 529 m->busy++; 530 531 m->rchan = 0; 532 m->wchan = 0; 533 m->async = 0; 534 535 if (flags & FREAD) { 536 m->flags |= M_RX | M_RXEN; 537 /* 538 * Only clear the inq, the outq might still have data to drain 539 * from a previous session 540 */ 541 MIDIQ_CLEAR(m->inq); 542 } 543 544 if (flags & FWRITE) 545 m->flags |= M_TX; 546 547 MPU_CALLBACK(m, m->cookie, m->flags); 548 549 MIDI_DEBUG(2, printf("midi_open: opened.\n")); 550 551 err: mtx_unlock(&m->qlock); 552 mtx_unlock(&m->lock); 553 return retval; 554 } 555 556 int 557 midi_close(struct cdev *i_dev, int flags, int mode, struct thread *td) 558 { 559 struct snd_midi *m = i_dev->si_drv1; 560 int retval; 561 int oldflags; 562 563 MIDI_DEBUG(1, printf("midi_close %p %s %s\n", td, 564 flags & FREAD ? "M_RX" : "", flags & FWRITE ? "M_TX" : "")); 565 566 if (m == NULL) 567 return ENXIO; 568 569 mtx_lock(&m->lock); 570 mtx_lock(&m->qlock); 571 572 if ((flags & FREAD && !(m->flags & M_RX)) || 573 (flags & FWRITE && !(m->flags & M_TX))) { 574 retval = ENXIO; 575 goto err; 576 } 577 m->busy--; 578 579 oldflags = m->flags; 580 581 if (flags & FREAD) 582 m->flags &= ~(M_RX | M_RXEN); 583 if (flags & FWRITE) 584 m->flags &= ~M_TX; 585 586 if ((m->flags & (M_TXEN | M_RXEN)) != (oldflags & (M_RXEN | M_TXEN))) 587 MPU_CALLBACK(m, m->cookie, m->flags); 588 589 MIDI_DEBUG(1, printf("midi_close: closed, busy = %d.\n", m->busy)); 590 591 mtx_unlock(&m->qlock); 592 mtx_unlock(&m->lock); 593 retval = 0; 594 err: return retval; 595 } 596 597 /* 598 * TODO: midi_read, per oss programmer's guide pg. 42 should return as soon 599 * as data is available. 600 */ 601 int 602 midi_read(struct cdev *i_dev, struct uio *uio, int ioflag) 603 { 604 #define MIDI_RSIZE 32 605 struct snd_midi *m = i_dev->si_drv1; 606 int retval; 607 int used; 608 char buf[MIDI_RSIZE]; 609 610 MIDI_DEBUG(5, printf("midiread: count=%lu\n", 611 (unsigned long)uio->uio_resid)); 612 613 retval = EIO; 614 615 if (m == NULL) 616 goto err0; 617 618 mtx_lock(&m->lock); 619 mtx_lock(&m->qlock); 620 621 if (!(m->flags & M_RX)) 622 goto err1; 623 624 while (uio->uio_resid > 0) { 625 while (MIDIQ_EMPTY(m->inq)) { 626 retval = EWOULDBLOCK; 627 if (ioflag & O_NONBLOCK) 628 goto err1; 629 mtx_unlock(&m->lock); 630 m->rchan = 1; 631 retval = msleep(&m->rchan, &m->qlock, 632 PCATCH | PDROP, "midi RX", 0); 633 /* 634 * We slept, maybe things have changed since last 635 * dying check 636 */ 637 if (retval == EINTR) 638 goto err0; 639 if (m != i_dev->si_drv1) 640 retval = ENXIO; 641 /* if (retval && retval != ERESTART) */ 642 if (retval) 643 goto err0; 644 mtx_lock(&m->lock); 645 mtx_lock(&m->qlock); 646 m->rchan = 0; 647 if (!m->busy) 648 goto err1; 649 } 650 MIDI_DEBUG(6, printf("midi_read start\n")); 651 /* 652 * At this point, it is certain that m->inq has data 653 */ 654 655 used = MIN(MIDIQ_LEN(m->inq), uio->uio_resid); 656 used = MIN(used, MIDI_RSIZE); 657 658 MIDI_DEBUG(6, printf("midiread: uiomove cc=%d\n", used)); 659 MIDIQ_DEQ(m->inq, buf, used); 660 retval = uiomove(buf, used, uio); 661 if (retval) 662 goto err1; 663 } 664 665 /* 666 * If we Made it here then transfer is good 667 */ 668 retval = 0; 669 err1: mtx_unlock(&m->qlock); 670 mtx_unlock(&m->lock); 671 err0: MIDI_DEBUG(4, printf("midi_read: ret %d\n", retval)); 672 return retval; 673 } 674 675 /* 676 * midi_write: The only setter of M_TXEN 677 */ 678 679 int 680 midi_write(struct cdev *i_dev, struct uio *uio, int ioflag) 681 { 682 #define MIDI_WSIZE 32 683 struct snd_midi *m = i_dev->si_drv1; 684 int retval; 685 int used; 686 char buf[MIDI_WSIZE]; 687 688 MIDI_DEBUG(4, printf("midi_write\n")); 689 retval = 0; 690 if (m == NULL) 691 goto err0; 692 693 mtx_lock(&m->lock); 694 mtx_lock(&m->qlock); 695 696 if (!(m->flags & M_TX)) 697 goto err1; 698 699 while (uio->uio_resid > 0) { 700 while (MIDIQ_AVAIL(m->outq) == 0) { 701 retval = EWOULDBLOCK; 702 if (ioflag & O_NONBLOCK) 703 goto err1; 704 mtx_unlock(&m->lock); 705 m->wchan = 1; 706 MIDI_DEBUG(3, printf("midi_write msleep\n")); 707 retval = msleep(&m->wchan, &m->qlock, 708 PCATCH | PDROP, "midi TX", 0); 709 /* 710 * We slept, maybe things have changed since last 711 * dying check 712 */ 713 if (retval == EINTR) 714 goto err0; 715 if (m != i_dev->si_drv1) 716 retval = ENXIO; 717 if (retval) 718 goto err0; 719 mtx_lock(&m->lock); 720 mtx_lock(&m->qlock); 721 m->wchan = 0; 722 if (!m->busy) 723 goto err1; 724 } 725 726 /* 727 * We are certain than data can be placed on the queue 728 */ 729 730 used = MIN(MIDIQ_AVAIL(m->outq), uio->uio_resid); 731 used = MIN(used, MIDI_WSIZE); 732 MIDI_DEBUG(5, printf("midiout: resid %zd len %jd avail %jd\n", 733 uio->uio_resid, (intmax_t)MIDIQ_LEN(m->outq), 734 (intmax_t)MIDIQ_AVAIL(m->outq))); 735 736 MIDI_DEBUG(5, printf("midi_write: uiomove cc=%d\n", used)); 737 retval = uiomove(buf, used, uio); 738 if (retval) 739 goto err1; 740 MIDIQ_ENQ(m->outq, buf, used); 741 /* 742 * Inform the bottom half that data can be written 743 */ 744 if (!(m->flags & M_TXEN)) { 745 m->flags |= M_TXEN; 746 MPU_CALLBACK(m, m->cookie, m->flags); 747 } 748 } 749 /* 750 * If we Made it here then transfer is good 751 */ 752 retval = 0; 753 err1: mtx_unlock(&m->qlock); 754 mtx_unlock(&m->lock); 755 err0: return retval; 756 } 757 758 int 759 midi_ioctl(struct cdev *i_dev, u_long cmd, caddr_t arg, int mode, 760 struct thread *td) 761 { 762 return ENXIO; 763 } 764 765 int 766 midi_poll(struct cdev *i_dev, int events, struct thread *td) 767 { 768 struct snd_midi *m = i_dev->si_drv1; 769 int revents; 770 771 if (m == NULL) 772 return 0; 773 774 revents = 0; 775 776 mtx_lock(&m->lock); 777 mtx_lock(&m->qlock); 778 779 if (events & (POLLIN | POLLRDNORM)) 780 if (!MIDIQ_EMPTY(m->inq)) 781 events |= events & (POLLIN | POLLRDNORM); 782 783 if (events & (POLLOUT | POLLWRNORM)) 784 if (MIDIQ_AVAIL(m->outq) < m->hiwat) 785 events |= events & (POLLOUT | POLLWRNORM); 786 787 if (revents == 0) { 788 if (events & (POLLIN | POLLRDNORM)) 789 selrecord(td, &m->rsel); 790 791 if (events & (POLLOUT | POLLWRNORM)) 792 selrecord(td, &m->wsel); 793 } 794 mtx_unlock(&m->lock); 795 mtx_unlock(&m->qlock); 796 797 return (revents); 798 } 799 800 /* 801 * Single point of midi destructions. 802 */ 803 static int 804 midi_destroy(struct snd_midi *m, int midiuninit) 805 { 806 midistat_lockassert(); 807 mtx_assert(&m->lock, MA_OWNED); 808 809 MIDI_DEBUG(3, printf("midi_destroy\n")); 810 m->dev->si_drv1 = NULL; 811 mtx_unlock(&m->lock); /* XXX */ 812 destroy_dev(m->dev); 813 TAILQ_REMOVE(&midi_devs, m, link); 814 if (midiuninit) 815 MPU_UNINIT(m, m->cookie); 816 free(MIDIQ_BUF(m->inq), M_MIDI); 817 free(MIDIQ_BUF(m->outq), M_MIDI); 818 mtx_destroy(&m->qlock); 819 mtx_destroy(&m->lock); 820 free(m, M_MIDI); 821 return 0; 822 } 823 824 static int 825 midi_load(void) 826 { 827 sx_init(&mstat_lock, "midistat lock"); 828 TAILQ_INIT(&midi_devs); 829 830 return 0; 831 } 832 833 static int 834 midi_unload(void) 835 { 836 struct snd_midi *m, *tmp; 837 int retval; 838 839 MIDI_DEBUG(1, printf("midi_unload()\n")); 840 retval = EBUSY; 841 midistat_lock(); 842 TAILQ_FOREACH_SAFE(m, &midi_devs, link, tmp) { 843 mtx_lock(&m->lock); 844 if (m->busy) 845 retval = EBUSY; 846 else 847 retval = midi_destroy(m, 1); 848 if (retval) 849 goto exit; 850 } 851 midistat_unlock(); 852 853 sx_destroy(&mstat_lock); 854 return 0; 855 856 exit: 857 mtx_unlock(&m->lock); 858 midistat_unlock(); 859 if (retval) 860 MIDI_DEBUG(2, printf("midi_unload: failed\n")); 861 return retval; 862 } 863 864 static int 865 midi_modevent(module_t mod, int type, void *data) 866 { 867 int retval; 868 869 retval = 0; 870 871 switch (type) { 872 case MOD_LOAD: 873 retval = midi_load(); 874 break; 875 876 case MOD_UNLOAD: 877 retval = midi_unload(); 878 break; 879 880 default: 881 break; 882 } 883 884 return retval; 885 } 886 887 DEV_MODULE(midi, midi_modevent, NULL); 888 MODULE_VERSION(midi, 1); 889