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