1 /*- 2 * Copyright (c) 2003 Mathew Kanner 3 * Copyright (c) 1998 The NetBSD Foundation, Inc. 4 * All rights reserved. 5 * 6 * This code is derived from software contributed to The NetBSD Foundation 7 * by Lennart Augustsson (augustss@netbsd.org). 8 * 9 * Redistribution and use in source and binary forms, with or without 10 * modification, are permitted provided that the following conditions 11 * are met: 12 * 1. Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * 2. Redistributions in binary form must reproduce the above copyright 15 * notice, this list of conditions and the following disclaimer in the 16 * documentation and/or other materials provided with the distribution. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 19 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 20 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 21 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 22 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 23 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 24 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 25 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 26 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28 * POSSIBILITY OF SUCH DAMAGE. 29 */ 30 31 /* 32 * Parts of this file started out as NetBSD: midi.c 1.31 33 * They are mostly gone. Still the most obvious will be the state 34 * machine midi_in 35 */ 36 37 #include <sys/cdefs.h> 38 __FBSDID("$FreeBSD: head/sys/dev/sound/midi/midi.c 227309 2011-11-07 15:43:11Z ed $"); 39 40 #include <sys/param.h> 41 #include <sys/queue.h> 42 #include <sys/kernel.h> 43 #include <sys/lock.h> 44 #include <sys/proc.h> 45 #include <sys/signalvar.h> 46 #include <sys/conf.h> 47 #include <sys/sysctl.h> 48 #include <sys/types.h> 49 #include <sys/malloc.h> 50 #include <sys/systm.h> 51 #include <sys/fcntl.h> 52 #include <sys/uio.h> 53 #include <sys/poll.h> 54 #include <sys/sbuf.h> 55 #include <sys/kobj.h> 56 #include <sys/module.h> 57 #include <sys/device.h> 58 59 #ifdef HAVE_KERNEL_OPTION_HEADERS 60 #include "opt_snd.h" 61 #endif 62 63 #include <dev/sound/midi/midi.h> 64 #include "mpu_if.h" 65 66 #include <dev/sound/midi/midiq.h> 67 #include "synth_if.h" 68 MALLOC_DEFINE(M_MIDI, "midi buffers", "Midi data allocation area"); 69 70 #define PCMMKMINOR(u, d, c) ((((c) & 0xff) << 16) | (((u) & 0x0f) << 4) | ((d) & 0x0f)) 71 #define MIDIMKMINOR(u, d, c) PCMMKMINOR(u, d, c) 72 73 #define MIDI_DEV_RAW 2 74 #define MIDI_DEV_MIDICTL 12 75 76 enum midi_states { 77 MIDI_IN_START, MIDI_IN_SYSEX, MIDI_IN_DATA 78 }; 79 80 /* 81 * The MPU interface current has init() uninit() inqsize(( outqsize() 82 * callback() : fiddle with the tx|rx status. 83 */ 84 85 #include "mpu_if.h" 86 87 /* 88 * /dev/rmidi Structure definitions 89 */ 90 91 #define MIDI_NAMELEN 16 92 struct snd_midi { 93 KOBJ_FIELDS; 94 struct lock lock; /* Protects all but queues */ 95 void *cookie; 96 97 int unit; /* Should only be used in midistat */ 98 int channel; /* Should only be used in midistat */ 99 100 int busy; 101 int flags; /* File flags */ 102 char name[MIDI_NAMELEN]; 103 struct lock qlock; /* Protects inq, outq and flags */ 104 MIDIQ_HEAD(, char) inq, outq; 105 int rchan, wchan; 106 struct kqinfo rkq, wkq; 107 int hiwat; /* QLEN(outq)>High-water -> disable 108 * writes from userland */ 109 enum midi_states inq_state; 110 int inq_status, inq_left; /* Variables for the state machine in 111 * Midi_in, this is to provide that 112 * signals only get issued only 113 * complete command packets. */ 114 struct proc *async; 115 struct cdev *dev; 116 struct synth_midi *synth; 117 int synth_flags; 118 TAILQ_ENTRY(snd_midi) link; 119 }; 120 121 struct synth_midi { 122 KOBJ_FIELDS; 123 struct snd_midi *m; 124 }; 125 126 static synth_open_t midisynth_open; 127 static synth_close_t midisynth_close; 128 static synth_writeraw_t midisynth_writeraw; 129 static synth_killnote_t midisynth_killnote; 130 static synth_startnote_t midisynth_startnote; 131 static synth_setinstr_t midisynth_setinstr; 132 static synth_alloc_t midisynth_alloc; 133 static synth_controller_t midisynth_controller; 134 static synth_bender_t midisynth_bender; 135 136 137 static kobj_method_t midisynth_methods[] = { 138 KOBJMETHOD(synth_open, midisynth_open), 139 KOBJMETHOD(synth_close, midisynth_close), 140 KOBJMETHOD(synth_writeraw, midisynth_writeraw), 141 KOBJMETHOD(synth_setinstr, midisynth_setinstr), 142 KOBJMETHOD(synth_startnote, midisynth_startnote), 143 KOBJMETHOD(synth_killnote, midisynth_killnote), 144 KOBJMETHOD(synth_alloc, midisynth_alloc), 145 KOBJMETHOD(synth_controller, midisynth_controller), 146 KOBJMETHOD(synth_bender, midisynth_bender), 147 KOBJMETHOD_END 148 }; 149 150 DEFINE_CLASS(midisynth, midisynth_methods, 0); 151 152 /* 153 * Module Exports & Interface 154 * 155 * struct midi_chan *midi_init(MPU_CLASS cls, int unit, int chan) int 156 * midi_uninit(struct snd_midi *) 0 == no error EBUSY or other error int 157 * Midi_in(struct midi_chan *, char *buf, int count) int Midi_out(struct 158 * midi_chan *, char *buf, int count) 159 * 160 * midi_{in,out} return actual size transfered 161 * 162 */ 163 164 165 /* 166 * midi_devs tailq, holder of all rmidi instances protected by midistat_lock 167 */ 168 169 TAILQ_HEAD(, snd_midi) midi_devs; 170 171 /* 172 * /dev/midistat variables and declarations, protected by midistat_lock 173 */ 174 175 static struct lock midistat_lock; 176 static int midistat_isopen = 0; 177 static struct sbuf midistat_sbuf; 178 static struct cdev *midistat_dev; 179 180 /* 181 * /dev/midistat dev_t declarations 182 */ 183 184 static d_open_t midistat_open; 185 static d_close_t midistat_close; 186 static d_read_t midistat_read; 187 188 static void midi_filter_detach(struct knote *); 189 static int midi_filter_read(struct knote *, long); 190 static int midi_filter_write(struct knote *, long); 191 192 static struct dev_ops midistat_ops = { 193 { "midistat", 0, D_MPSAFE }, 194 .d_open = midistat_open, 195 .d_close = midistat_close, 196 .d_read = midistat_read, 197 }; 198 199 static struct filterops midi_read_filterops = 200 { FILTEROP_ISFD, NULL, midi_filter_detach, midi_filter_read }; 201 static struct filterops midi_write_filterops = 202 { FILTEROP_ISFD, NULL, midi_filter_detach, midi_filter_write }; 203 204 /* 205 * /dev/rmidi dev_t declarations, struct variable access is protected by 206 * locks contained within the structure. 207 */ 208 209 static d_open_t midi_open; 210 static d_close_t midi_close; 211 static d_ioctl_t midi_ioctl; 212 static d_read_t midi_read; 213 static d_write_t midi_write; 214 static d_kqfilter_t midi_kqfilter; 215 216 static struct dev_ops midi_ops = { 217 { "rmidi", 0, D_MPSAFE }, 218 .d_open = midi_open, 219 .d_close = midi_close, 220 .d_read = midi_read, 221 .d_write = midi_write, 222 .d_ioctl = midi_ioctl, 223 .d_kqfilter = midi_kqfilter, 224 }; 225 226 /* 227 * Prototypes of library functions 228 */ 229 230 static int midi_destroy(struct snd_midi *, int); 231 static int midistat_prepare(struct sbuf * s); 232 static int midi_load(void); 233 static int midi_unload(void); 234 235 /* 236 * Misc declr. 237 */ 238 SYSCTL_NODE(_hw, OID_AUTO, midi, CTLFLAG_RD, 0, "Midi driver"); 239 static SYSCTL_NODE(_hw_midi, OID_AUTO, stat, CTLFLAG_RD, 0, "Status device"); 240 241 int midi_debug; 242 /* XXX: should this be moved into debug.midi? */ 243 SYSCTL_INT(_hw_midi, OID_AUTO, debug, CTLFLAG_RW, &midi_debug, 0, ""); 244 245 int midi_dumpraw; 246 SYSCTL_INT(_hw_midi, OID_AUTO, dumpraw, CTLFLAG_RW, &midi_dumpraw, 0, ""); 247 248 int midi_instroff; 249 SYSCTL_INT(_hw_midi, OID_AUTO, instroff, CTLFLAG_RW, &midi_instroff, 0, ""); 250 251 int midistat_verbose; 252 SYSCTL_INT(_hw_midi_stat, OID_AUTO, verbose, CTLFLAG_RW, 253 &midistat_verbose, 0, ""); 254 255 #define MIDI_DEBUG(l,a) if(midi_debug>=l) a 256 /* 257 * CODE START 258 */ 259 260 /* 261 * Register a new rmidi device. cls midi_if interface unit == 0 means 262 * auto-assign new unit number unit != 0 already assigned a unit number, eg. 263 * not the first channel provided by this device. channel, sub-unit 264 * cookie is passed back on MPU calls Typical device drivers will call with 265 * unit=0, channel=1..(number of channels) and cookie=soft_c and won't care 266 * what unit number is used. 267 * 268 * It is an error to call midi_init with an already used unit/channel combo. 269 * 270 * Returns NULL on error 271 * 272 */ 273 struct snd_midi * 274 midi_init(kobj_class_t cls, int unit, int channel, void *cookie) 275 { 276 struct snd_midi *m; 277 int i; 278 int inqsize, outqsize; 279 MIDI_TYPE *buf; 280 281 MIDI_DEBUG(1, kprintf("midiinit: unit %d/%d.\n", unit, channel)); 282 lockmgr(&midistat_lock, LK_EXCLUSIVE); 283 /* 284 * Protect against call with existing unit/channel or auto-allocate a 285 * new unit number. 286 */ 287 i = -1; 288 TAILQ_FOREACH(m, &midi_devs, link) { 289 lockmgr(&m->lock, LK_EXCLUSIVE); 290 if (unit != 0) { 291 if (m->unit == unit && m->channel == channel) { 292 lockmgr(&m->lock, LK_RELEASE); 293 goto err0; 294 } 295 } else { 296 /* 297 * Find a better unit number 298 */ 299 if (m->unit > i) 300 i = m->unit; 301 } 302 lockmgr(&m->lock, LK_RELEASE); 303 } 304 305 if (unit == 0) 306 unit = i + 1; 307 308 MIDI_DEBUG(1, kprintf("midiinit #2: unit %d/%d.\n", unit, channel)); 309 m = kmalloc(sizeof(*m), M_MIDI, M_WAITOK | M_ZERO); 310 311 m->synth = kmalloc(sizeof(*m->synth), M_MIDI, M_WAITOK | M_ZERO); 312 kobj_init((kobj_t)m->synth, &midisynth_class); 313 m->synth->m = m; 314 kobj_init((kobj_t)m, cls); 315 inqsize = MPU_INQSIZE(m, cookie); 316 outqsize = MPU_OUTQSIZE(m, cookie); 317 318 MIDI_DEBUG(1, kprintf("midiinit queues %d/%d.\n", inqsize, outqsize)); 319 if (!inqsize && !outqsize) 320 goto err1; 321 322 lockinit(&m->lock, "raw midi", 0, LK_CANRECURSE); 323 lockinit(&m->qlock, "q raw midi", 0, LK_CANRECURSE); 324 325 lockmgr(&m->lock, LK_EXCLUSIVE); 326 lockmgr(&m->qlock, LK_EXCLUSIVE); 327 328 if (inqsize) 329 buf = kmalloc(sizeof(MIDI_TYPE) * inqsize, M_MIDI, M_WAITOK); 330 else 331 buf = NULL; 332 333 MIDIQ_INIT(m->inq, buf, inqsize); 334 335 if (outqsize) 336 buf = kmalloc(sizeof(MIDI_TYPE) * outqsize, M_MIDI, M_WAITOK); 337 else 338 buf = NULL; 339 m->hiwat = outqsize / 2; 340 341 MIDIQ_INIT(m->outq, buf, outqsize); 342 343 if ((inqsize && !MIDIQ_BUF(m->inq)) || 344 (outqsize && !MIDIQ_BUF(m->outq))) 345 goto err2; 346 347 348 m->busy = 0; 349 m->flags = 0; 350 m->unit = unit; 351 m->channel = channel; 352 m->cookie = cookie; 353 354 if (MPU_INIT(m, cookie)) 355 goto err2; 356 357 lockmgr(&m->lock, LK_RELEASE); 358 lockmgr(&m->qlock, LK_RELEASE); 359 360 TAILQ_INSERT_TAIL(&midi_devs, m, link); 361 362 lockmgr(&midistat_lock, LK_RELEASE); 363 364 m->dev = make_dev(&midi_ops, 365 MIDIMKMINOR(unit, MIDI_DEV_RAW, channel), 366 UID_ROOT, GID_WHEEL, 0666, "midi%d.%d", unit, channel); 367 m->dev->si_drv1 = m; 368 369 return m; 370 371 err2: 372 lockuninit(&m->qlock); 373 lockuninit(&m->lock); 374 375 if (MIDIQ_BUF(m->inq)) 376 kfree(MIDIQ_BUF(m->inq), M_MIDI); 377 if (MIDIQ_BUF(m->outq)) 378 kfree(MIDIQ_BUF(m->outq), M_MIDI); 379 err1: 380 kfree(m, M_MIDI); 381 err0: 382 lockmgr(&midistat_lock, LK_RELEASE); 383 MIDI_DEBUG(1, kprintf("midi_init ended in error\n")); 384 return NULL; 385 } 386 387 /* 388 * midi_uninit does not call MIDI_UNINIT, as since this is the implementors 389 * entry point. midi_unint if fact, does not send any methods. A call to 390 * midi_uninit is a defacto promise that you won't manipulate ch anymore 391 * 392 */ 393 394 int 395 midi_uninit(struct snd_midi *m) 396 { 397 int err; 398 399 err = ENXIO; 400 lockmgr(&midistat_lock, LK_EXCLUSIVE); 401 lockmgr(&m->lock, LK_EXCLUSIVE); 402 if (m->busy) { 403 if (!(m->rchan || m->wchan)) 404 goto err; 405 406 if (m->rchan) { 407 wakeup(&m->rchan); 408 m->rchan = 0; 409 } 410 if (m->wchan) { 411 wakeup(&m->wchan); 412 m->wchan = 0; 413 } 414 } 415 err = midi_destroy(m, 0); 416 if (!err) 417 goto exit; 418 419 err: lockmgr(&m->lock, LK_RELEASE); 420 exit: lockmgr(&midistat_lock, LK_RELEASE); 421 return err; 422 } 423 424 /* 425 * midi_in: process all data until the queue is full, then discards the rest. 426 * Since midi_in is a state machine, data discards can cause it to get out of 427 * whack. Process as much as possible. It calls, wakeup, selnotify and 428 * psignal at most once. 429 */ 430 431 #ifdef notdef 432 static int midi_lengths[] = {2, 2, 2, 2, 1, 1, 2, 0}; 433 434 #endif /* notdef */ 435 /* Number of bytes in a MIDI command */ 436 #define MIDI_LENGTH(d) (midi_lengths[((d) >> 4) & 7]) 437 #define MIDI_ACK 0xfe 438 #define MIDI_IS_STATUS(d) ((d) >= 0x80) 439 #define MIDI_IS_COMMON(d) ((d) >= 0xf0) 440 441 #define MIDI_SYSEX_START 0xF0 442 #define MIDI_SYSEX_END 0xF7 443 444 445 int 446 midi_in(struct snd_midi *m, MIDI_TYPE *buf, int size) 447 { 448 /* int i, sig, enq; */ 449 int used; 450 451 /* MIDI_TYPE data; */ 452 MIDI_DEBUG(5, kprintf("midi_in: m=%p size=%d\n", m, size)); 453 454 /* 455 * XXX: locking flub 456 */ 457 if (!(m->flags & M_RX)) 458 return size; 459 460 used = 0; 461 462 lockmgr(&m->qlock, LK_EXCLUSIVE); 463 #if 0 464 /* 465 * Don't bother queuing if not in read mode. Discard everything and 466 * return size so the caller doesn't freak out. 467 */ 468 469 if (!(m->flags & M_RX)) 470 return size; 471 472 for (i = sig = 0; i < size; i++) { 473 474 data = buf[i]; 475 enq = 0; 476 if (data == MIDI_ACK) 477 continue; 478 479 switch (m->inq_state) { 480 case MIDI_IN_START: 481 if (MIDI_IS_STATUS(data)) { 482 switch (data) { 483 case 0xf0: /* Sysex */ 484 m->inq_state = MIDI_IN_SYSEX; 485 break; 486 case 0xf1: /* MTC quarter frame */ 487 case 0xf3: /* Song select */ 488 m->inq_state = MIDI_IN_DATA; 489 enq = 1; 490 m->inq_left = 1; 491 break; 492 case 0xf2: /* Song position pointer */ 493 m->inq_state = MIDI_IN_DATA; 494 enq = 1; 495 m->inq_left = 2; 496 break; 497 default: 498 if (MIDI_IS_COMMON(data)) { 499 enq = 1; 500 sig = 1; 501 } else { 502 m->inq_state = MIDI_IN_DATA; 503 enq = 1; 504 m->inq_status = data; 505 m->inq_left = MIDI_LENGTH(data); 506 } 507 break; 508 } 509 } else if (MIDI_IS_STATUS(m->inq_status)) { 510 m->inq_state = MIDI_IN_DATA; 511 if (!MIDIQ_FULL(m->inq)) { 512 used++; 513 MIDIQ_ENQ(m->inq, &m->inq_status, 1); 514 } 515 enq = 1; 516 m->inq_left = MIDI_LENGTH(m->inq_status) - 1; 517 } 518 break; 519 /* 520 * End of case MIDI_IN_START: 521 */ 522 523 case MIDI_IN_DATA: 524 enq = 1; 525 if (--m->inq_left <= 0) 526 sig = 1;/* deliver data */ 527 break; 528 case MIDI_IN_SYSEX: 529 if (data == MIDI_SYSEX_END) 530 m->inq_state = MIDI_IN_START; 531 break; 532 } 533 534 if (enq) 535 if (!MIDIQ_FULL(m->inq)) { 536 MIDIQ_ENQ(m->inq, &data, 1); 537 used++; 538 } 539 /* 540 * End of the state machines main "for loop" 541 */ 542 } 543 if (sig) { 544 #endif 545 MIDI_DEBUG(6, kprintf("midi_in: len %jd avail %jd\n", 546 (intmax_t)MIDIQ_LEN(m->inq), 547 (intmax_t)MIDIQ_AVAIL(m->inq))); 548 if (MIDIQ_AVAIL(m->inq) > size) { 549 used = size; 550 MIDIQ_ENQ(m->inq, buf, size); 551 } else { 552 MIDI_DEBUG(4, kprintf("midi_in: Discarding data qu\n")); 553 lockmgr(&m->qlock, LK_RELEASE); 554 return 0; 555 } 556 if (m->rchan) { 557 wakeup(&m->rchan); 558 m->rchan = 0; 559 } 560 KNOTE(&m->rkq.ki_note, 0); 561 if (m->async) { 562 PHOLD(m->async); 563 ksignal(m->async, SIGIO); 564 PRELE(m->async); 565 } 566 #if 0 567 } 568 #endif 569 lockmgr(&m->qlock, LK_RELEASE); 570 return used; 571 } 572 573 /* 574 * midi_out: The only clearer of the M_TXEN flag. 575 */ 576 int 577 midi_out(struct snd_midi *m, MIDI_TYPE *buf, int size) 578 { 579 int used; 580 581 /* 582 * XXX: locking flub 583 */ 584 if (!(m->flags & M_TXEN)) 585 return 0; 586 587 MIDI_DEBUG(2, kprintf("midi_out: %p\n", m)); 588 lockmgr(&m->qlock, LK_EXCLUSIVE); 589 used = MIN(size, MIDIQ_LEN(m->outq)); 590 MIDI_DEBUG(3, kprintf("midi_out: used %d\n", used)); 591 if (used) 592 MIDIQ_DEQ(m->outq, buf, used); 593 if (MIDIQ_EMPTY(m->outq)) { 594 m->flags &= ~M_TXEN; 595 MPU_CALLBACKP(m, m->cookie, m->flags); 596 } 597 if (used && MIDIQ_AVAIL(m->outq) > m->hiwat) { 598 if (m->wchan) { 599 wakeup(&m->wchan); 600 m->wchan = 0; 601 } 602 KNOTE(&m->wkq.ki_note, 0); 603 if (m->async) { 604 PHOLD(m->async); 605 ksignal(m->async, SIGIO); 606 PRELE(m->async); 607 } 608 } 609 lockmgr(&m->qlock, LK_RELEASE); 610 return used; 611 } 612 613 614 /* 615 * /dev/rmidi#.# device access functions 616 */ 617 int 618 midi_open(struct dev_open_args *ap) 619 { 620 cdev_t i_dev = ap->a_head.a_dev; 621 int flags = ap->a_oflags; 622 struct snd_midi *m = i_dev->si_drv1; 623 int retval; 624 625 #if 0 /* XXX */ 626 MIDI_DEBUG(1, kprintf("midiopen %p %s %s\n", td, 627 flags & FREAD ? "M_RX" : "", flags & FWRITE ? "M_TX" : "")); 628 #endif 629 if (m == NULL) 630 return ENXIO; 631 632 lockmgr(&m->lock, LK_EXCLUSIVE); 633 lockmgr(&m->qlock, LK_EXCLUSIVE); 634 635 retval = 0; 636 637 if (flags & FREAD) { 638 if (MIDIQ_SIZE(m->inq) == 0) 639 retval = ENXIO; 640 else if (m->flags & M_RX) 641 retval = EBUSY; 642 if (retval) 643 goto err; 644 } 645 if (flags & FWRITE) { 646 if (MIDIQ_SIZE(m->outq) == 0) 647 retval = ENXIO; 648 else if (m->flags & M_TX) 649 retval = EBUSY; 650 if (retval) 651 goto err; 652 } 653 m->busy++; 654 655 m->rchan = 0; 656 m->wchan = 0; 657 m->async = 0; 658 659 if (flags & FREAD) { 660 m->flags |= M_RX | M_RXEN; 661 /* 662 * Only clear the inq, the outq might still have data to drain 663 * from a previous session 664 */ 665 MIDIQ_CLEAR(m->inq); 666 }; 667 668 if (flags & FWRITE) 669 m->flags |= M_TX; 670 671 MPU_CALLBACK(m, m->cookie, m->flags); 672 673 MIDI_DEBUG(2, kprintf("midi_open: opened.\n")); 674 675 err: lockmgr(&m->qlock, LK_RELEASE); 676 lockmgr(&m->lock, LK_RELEASE); 677 return retval; 678 } 679 680 int 681 midi_close(struct dev_close_args *ap) 682 { 683 cdev_t i_dev = ap->a_head.a_dev; 684 int flags = ap->a_fflag; 685 struct snd_midi *m = i_dev->si_drv1; 686 int retval; 687 int oldflags; 688 689 #if 0 /* XXX */ 690 MIDI_DEBUG(1, kprintf("midi_close %p %s %s\n", td, 691 flags & FREAD ? "M_RX" : "", flags & FWRITE ? "M_TX" : "")); 692 #endif 693 694 if (m == NULL) 695 return ENXIO; 696 697 lockmgr(&m->lock, LK_EXCLUSIVE); 698 lockmgr(&m->qlock, LK_EXCLUSIVE); 699 700 if ((flags & FREAD && !(m->flags & M_RX)) || 701 (flags & FWRITE && !(m->flags & M_TX))) { 702 retval = ENXIO; 703 goto err; 704 } 705 m->busy--; 706 707 oldflags = m->flags; 708 709 if (flags & FREAD) 710 m->flags &= ~(M_RX | M_RXEN); 711 if (flags & FWRITE) 712 m->flags &= ~M_TX; 713 714 if ((m->flags & (M_TXEN | M_RXEN)) != (oldflags & (M_RXEN | M_TXEN))) 715 MPU_CALLBACK(m, m->cookie, m->flags); 716 717 MIDI_DEBUG(1, kprintf("midi_close: closed, busy = %d.\n", m->busy)); 718 719 lockmgr(&m->qlock, LK_RELEASE); 720 lockmgr(&m->lock, LK_RELEASE); 721 retval = 0; 722 err: return retval; 723 } 724 725 /* 726 * TODO: midi_read, per oss programmer's guide pg. 42 should return as soon 727 * as data is available. 728 */ 729 int 730 midi_read(struct dev_read_args *ap) 731 { 732 cdev_t i_dev = ap->a_head.a_dev; 733 struct uio *uio = ap->a_uio; 734 int ioflag = ap->a_ioflag; 735 #define MIDI_RSIZE 32 736 struct snd_midi *m = i_dev->si_drv1; 737 int retval; 738 int used; 739 char buf[MIDI_RSIZE]; 740 741 MIDI_DEBUG(5, kprintf("midiread: count=%lu\n", 742 (unsigned long)uio->uio_resid)); 743 744 retval = EIO; 745 746 if (m == NULL) 747 goto err0; 748 749 lockmgr(&m->lock, LK_EXCLUSIVE); 750 lockmgr(&m->qlock, LK_EXCLUSIVE); 751 752 if (!(m->flags & M_RX)) 753 goto err1; 754 755 while (uio->uio_resid > 0) { 756 while (MIDIQ_EMPTY(m->inq)) { 757 retval = EWOULDBLOCK; 758 if (ioflag & O_NONBLOCK) 759 goto err1; 760 lockmgr(&m->lock, LK_RELEASE); 761 m->rchan = 1; 762 retval = lksleep(&m->rchan, &m->qlock, 763 PCATCH, "midi RX", 0); 764 /* 765 * We slept, maybe things have changed since last 766 * dying check 767 */ 768 if (retval == EINTR) 769 goto err0; 770 if (m != i_dev->si_drv1) 771 retval = ENXIO; 772 /* if (retval && retval != ERESTART) */ 773 if (retval) 774 goto err0; 775 lockmgr(&m->lock, LK_EXCLUSIVE); 776 lockmgr(&m->qlock, LK_EXCLUSIVE); 777 m->rchan = 0; 778 if (!m->busy) 779 goto err1; 780 } 781 MIDI_DEBUG(6, kprintf("midi_read start\n")); 782 /* 783 * At this point, it is certain that m->inq has data 784 */ 785 786 used = MIN(MIDIQ_LEN(m->inq), uio->uio_resid); 787 used = MIN(used, MIDI_RSIZE); 788 789 MIDI_DEBUG(6, kprintf("midiread: uiomove cc=%d\n", used)); 790 MIDIQ_DEQ(m->inq, buf, used); 791 retval = uiomove(buf, used, uio); 792 if (retval) 793 goto err1; 794 } 795 796 /* 797 * If we Made it here then transfer is good 798 */ 799 retval = 0; 800 err1: lockmgr(&m->qlock, LK_RELEASE); 801 lockmgr(&m->lock, LK_RELEASE); 802 err0: MIDI_DEBUG(4, kprintf("midi_read: ret %d\n", retval)); 803 return retval; 804 } 805 806 /* 807 * midi_write: The only setter of M_TXEN 808 */ 809 810 int 811 midi_write(struct dev_write_args *ap) 812 { 813 cdev_t i_dev = ap->a_head.a_dev; 814 struct uio *uio = ap->a_uio; 815 int ioflag = ap->a_ioflag; 816 #define MIDI_WSIZE 32 817 struct snd_midi *m = i_dev->si_drv1; 818 int retval; 819 int used; 820 char buf[MIDI_WSIZE]; 821 822 823 MIDI_DEBUG(4, kprintf("midi_write\n")); 824 retval = 0; 825 if (m == NULL) 826 goto err0; 827 828 lockmgr(&m->lock, LK_EXCLUSIVE); 829 lockmgr(&m->qlock, LK_EXCLUSIVE); 830 831 if (!(m->flags & M_TX)) 832 goto err1; 833 834 while (uio->uio_resid > 0) { 835 while (MIDIQ_AVAIL(m->outq) == 0) { 836 retval = EWOULDBLOCK; 837 if (ioflag & O_NONBLOCK) 838 goto err1; 839 lockmgr(&m->lock, LK_RELEASE); 840 m->wchan = 1; 841 MIDI_DEBUG(3, kprintf("midi_write lksleep\n")); 842 retval = lksleep(&m->wchan, &m->qlock, 843 PCATCH, "midi TX", 0); 844 /* 845 * We slept, maybe things have changed since last 846 * dying check 847 */ 848 if (retval == EINTR) 849 goto err0; 850 if (m != i_dev->si_drv1) 851 retval = ENXIO; 852 if (retval) 853 goto err0; 854 lockmgr(&m->lock, LK_EXCLUSIVE); 855 lockmgr(&m->qlock, LK_EXCLUSIVE); 856 m->wchan = 0; 857 if (!m->busy) 858 goto err1; 859 } 860 861 /* 862 * We are certain than data can be placed on the queue 863 */ 864 865 used = MIN(MIDIQ_AVAIL(m->outq), uio->uio_resid); 866 used = MIN(used, MIDI_WSIZE); 867 MIDI_DEBUG(5, kprintf("midiout: resid %zd len %jd avail %jd\n", 868 uio->uio_resid, (intmax_t)MIDIQ_LEN(m->outq), 869 (intmax_t)MIDIQ_AVAIL(m->outq))); 870 871 872 MIDI_DEBUG(5, kprintf("midi_write: uiomove cc=%d\n", used)); 873 retval = uiomove(buf, used, uio); 874 if (retval) 875 goto err1; 876 MIDIQ_ENQ(m->outq, buf, used); 877 /* 878 * Inform the bottom half that data can be written 879 */ 880 if (!(m->flags & M_TXEN)) { 881 m->flags |= M_TXEN; 882 MPU_CALLBACK(m, m->cookie, m->flags); 883 } 884 } 885 /* 886 * If we Made it here then transfer is good 887 */ 888 retval = 0; 889 err1: lockmgr(&m->qlock, LK_RELEASE); 890 lockmgr(&m->lock, LK_RELEASE); 891 err0: return retval; 892 } 893 894 int 895 midi_ioctl(struct dev_ioctl_args *ap) 896 { 897 return ENXIO; 898 } 899 900 int 901 midi_kqfilter(struct dev_kqfilter_args *ap) 902 { 903 cdev_t dev = ap->a_head.a_dev; 904 struct knote *kn = ap->a_kn; 905 struct snd_midi *m; 906 struct klist *klist; 907 908 ap->a_result = 0; 909 m = dev->si_drv1; 910 911 switch (kn->kn_filter) { 912 case EVFILT_READ: 913 kn->kn_fop = &midi_read_filterops; 914 kn->kn_hook = (caddr_t)m; 915 klist = &m->rkq.ki_note; 916 break; 917 case EVFILT_WRITE: 918 kn->kn_fop = &midi_write_filterops; 919 kn->kn_hook = (caddr_t)m; 920 klist = &m->wkq.ki_note; 921 break; 922 default: 923 ap->a_result = EOPNOTSUPP; 924 return (0); 925 } 926 927 knote_insert(klist, kn); 928 929 return(0); 930 } 931 932 static void 933 midi_filter_detach(struct knote *kn) 934 { 935 struct snd_midi *m = (struct snd_midi *)kn->kn_hook; 936 struct klist *rklist = &m->rkq.ki_note; 937 struct klist *wklist = &m->wkq.ki_note; 938 939 knote_remove(rklist, kn); 940 knote_remove(wklist, kn); 941 } 942 943 static int 944 midi_filter_read(struct knote *kn, long hint) 945 { 946 struct snd_midi *m = (struct snd_midi *)kn->kn_hook; 947 int ready = 0; 948 949 lockmgr(&m->lock, LK_EXCLUSIVE); 950 lockmgr(&m->qlock, LK_EXCLUSIVE); 951 952 if (!MIDIQ_EMPTY(m->inq)) 953 ready = 1; 954 955 lockmgr(&m->lock, LK_RELEASE); 956 lockmgr(&m->qlock, LK_RELEASE); 957 958 return (ready); 959 } 960 961 static int 962 midi_filter_write(struct knote *kn, long hint) 963 { 964 struct snd_midi *m = (struct snd_midi *)kn->kn_hook; 965 int ready = 0; 966 967 lockmgr(&m->lock, LK_EXCLUSIVE); 968 lockmgr(&m->qlock, LK_EXCLUSIVE); 969 970 if (MIDIQ_AVAIL(m->outq) < m->hiwat) 971 ready = 1; 972 973 lockmgr(&m->lock, LK_RELEASE); 974 lockmgr(&m->qlock, LK_RELEASE); 975 976 return (ready); 977 } 978 979 /* 980 * /dev/midistat device functions 981 * 982 */ 983 static int 984 midistat_open(struct dev_open_args *ap) 985 { 986 int error; 987 988 MIDI_DEBUG(1, kprintf("midistat_open\n")); 989 lockmgr(&midistat_lock, LK_EXCLUSIVE); 990 991 if (midistat_isopen) { 992 lockmgr(&midistat_lock, LK_RELEASE); 993 return EBUSY; 994 } 995 midistat_isopen = 1; 996 997 if (sbuf_new(&midistat_sbuf, NULL, 4096, SBUF_AUTOEXTEND) == NULL) { 998 error = ENXIO; 999 goto out; 1000 } 1001 error = (midistat_prepare(&midistat_sbuf) > 0) ? 0 : ENOMEM; 1002 1003 out: 1004 if (error) 1005 midistat_isopen = 0; 1006 lockmgr(&midistat_lock, LK_RELEASE); 1007 return error; 1008 } 1009 1010 static int 1011 midistat_close(struct dev_close_args *ap) 1012 { 1013 MIDI_DEBUG(1, kprintf("midistat_close\n")); 1014 lockmgr(&midistat_lock, LK_EXCLUSIVE); 1015 if (!midistat_isopen) { 1016 lockmgr(&midistat_lock, LK_RELEASE); 1017 return EBADF; 1018 } 1019 sbuf_delete(&midistat_sbuf); 1020 midistat_isopen = 0; 1021 1022 lockmgr(&midistat_lock, LK_RELEASE); 1023 return 0; 1024 } 1025 1026 static int 1027 midistat_read(struct dev_read_args *ap) 1028 { 1029 struct uio *uio = ap->a_uio; 1030 int l, err; 1031 1032 MIDI_DEBUG(4, kprintf("midistat_read\n")); 1033 lockmgr(&midistat_lock, LK_EXCLUSIVE); 1034 if (!midistat_isopen) { 1035 lockmgr(&midistat_lock, LK_RELEASE); 1036 return EBADF; 1037 } 1038 l = min(uio->uio_resid, sbuf_len(&midistat_sbuf) - uio->uio_offset); 1039 err = 0; 1040 if (l > 0) { 1041 err = uiomove(sbuf_data(&midistat_sbuf) + uio->uio_offset, 1042 l, uio); 1043 } 1044 lockmgr(&midistat_lock, LK_RELEASE); 1045 1046 return err; 1047 } 1048 1049 /* 1050 * Module library functions 1051 */ 1052 1053 static int 1054 midistat_prepare(struct sbuf *s) 1055 { 1056 struct snd_midi *m; 1057 1058 KKASSERT(lockowned(&midistat_lock)); 1059 1060 sbuf_printf(s, "FreeBSD Midi Driver (midi2)\n"); 1061 if (TAILQ_EMPTY(&midi_devs)) { 1062 sbuf_printf(s, "No devices installed.\n"); 1063 sbuf_finish(s); 1064 return sbuf_len(s); 1065 } 1066 sbuf_printf(s, "Installed devices:\n"); 1067 1068 TAILQ_FOREACH(m, &midi_devs, link) { 1069 lockmgr(&m->lock, LK_EXCLUSIVE); 1070 sbuf_printf(s, "%s [%d/%d:%s]", m->name, m->unit, m->channel, 1071 MPU_PROVIDER(m, m->cookie)); 1072 sbuf_printf(s, "%s", MPU_DESCR(m, m->cookie, midistat_verbose)); 1073 sbuf_printf(s, "\n"); 1074 lockmgr(&m->lock, LK_RELEASE); 1075 } 1076 1077 sbuf_finish(s); 1078 return sbuf_len(s); 1079 } 1080 1081 #ifdef notdef 1082 /* 1083 * Convert IOCTL command to string for debugging 1084 */ 1085 1086 static char * 1087 midi_cmdname(int cmd) 1088 { 1089 static struct { 1090 int cmd; 1091 char *name; 1092 } *tab, cmdtab_midiioctl[] = { 1093 #define A(x) {x, ## x} 1094 /* 1095 * Once we have some real IOCTLs define, the following will 1096 * be relavant. 1097 * 1098 * A(SNDCTL_MIDI_PRETIME), A(SNDCTL_MIDI_MPUMODE), 1099 * A(SNDCTL_MIDI_MPUCMD), A(SNDCTL_SYNTH_INFO), 1100 * A(SNDCTL_MIDI_INFO), A(SNDCTL_SYNTH_MEMAVL), 1101 * A(SNDCTL_FM_LOAD_INSTR), A(SNDCTL_FM_4OP_ENABLE), 1102 * A(MIOSPASSTHRU), A(MIOGPASSTHRU), A(AIONWRITE), 1103 * A(AIOGSIZE), A(AIOSSIZE), A(AIOGFMT), A(AIOSFMT), 1104 * A(AIOGMIX), A(AIOSMIX), A(AIOSTOP), A(AIOSYNC), 1105 * A(AIOGCAP), 1106 */ 1107 #undef A 1108 { 1109 -1, "unknown" 1110 }, 1111 }; 1112 1113 for (tab = cmdtab_midiioctl; tab->cmd != cmd && tab->cmd != -1; tab++); 1114 return tab->name; 1115 } 1116 1117 #endif /* notdef */ 1118 1119 /* 1120 * midisynth 1121 */ 1122 1123 1124 int 1125 midisynth_open(void *n, void *arg, int flags) 1126 { 1127 struct snd_midi *m = ((struct synth_midi *)n)->m; 1128 int retval; 1129 1130 MIDI_DEBUG(1, kprintf("midisynth_open %s %s\n", 1131 flags & FREAD ? "M_RX" : "", flags & FWRITE ? "M_TX" : "")); 1132 1133 if (m == NULL) 1134 return ENXIO; 1135 1136 lockmgr(&m->lock, LK_EXCLUSIVE); 1137 lockmgr(&m->qlock, LK_EXCLUSIVE); 1138 1139 retval = 0; 1140 1141 if (flags & FREAD) { 1142 if (MIDIQ_SIZE(m->inq) == 0) 1143 retval = ENXIO; 1144 else if (m->flags & M_RX) 1145 retval = EBUSY; 1146 if (retval) 1147 goto err; 1148 } 1149 if (flags & FWRITE) { 1150 if (MIDIQ_SIZE(m->outq) == 0) 1151 retval = ENXIO; 1152 else if (m->flags & M_TX) 1153 retval = EBUSY; 1154 if (retval) 1155 goto err; 1156 } 1157 m->busy++; 1158 1159 /* 1160 * TODO: Consider m->async = 0; 1161 */ 1162 1163 if (flags & FREAD) { 1164 m->flags |= M_RX | M_RXEN; 1165 /* 1166 * Only clear the inq, the outq might still have data to drain 1167 * from a previous session 1168 */ 1169 MIDIQ_CLEAR(m->inq); 1170 m->rchan = 0; 1171 }; 1172 1173 if (flags & FWRITE) { 1174 m->flags |= M_TX; 1175 m->wchan = 0; 1176 } 1177 m->synth_flags = flags & (FREAD | FWRITE); 1178 1179 MPU_CALLBACK(m, m->cookie, m->flags); 1180 1181 1182 err: lockmgr(&m->qlock, LK_RELEASE); 1183 lockmgr(&m->lock, LK_RELEASE); 1184 MIDI_DEBUG(2, kprintf("midisynth_open: return %d.\n", retval)); 1185 return retval; 1186 } 1187 1188 int 1189 midisynth_close(void *n) 1190 { 1191 struct snd_midi *m = ((struct synth_midi *)n)->m; 1192 int retval; 1193 int oldflags; 1194 1195 MIDI_DEBUG(1, kprintf("midisynth_close %s %s\n", 1196 m->synth_flags & FREAD ? "M_RX" : "", 1197 m->synth_flags & FWRITE ? "M_TX" : "")); 1198 1199 if (m == NULL) 1200 return ENXIO; 1201 1202 lockmgr(&m->lock, LK_EXCLUSIVE); 1203 lockmgr(&m->qlock, LK_EXCLUSIVE); 1204 1205 if ((m->synth_flags & FREAD && !(m->flags & M_RX)) || 1206 (m->synth_flags & FWRITE && !(m->flags & M_TX))) { 1207 retval = ENXIO; 1208 goto err; 1209 } 1210 m->busy--; 1211 1212 oldflags = m->flags; 1213 1214 if (m->synth_flags & FREAD) 1215 m->flags &= ~(M_RX | M_RXEN); 1216 if (m->synth_flags & FWRITE) 1217 m->flags &= ~M_TX; 1218 1219 if ((m->flags & (M_TXEN | M_RXEN)) != (oldflags & (M_RXEN | M_TXEN))) 1220 MPU_CALLBACK(m, m->cookie, m->flags); 1221 1222 MIDI_DEBUG(1, kprintf("midi_close: closed, busy = %d.\n", m->busy)); 1223 1224 lockmgr(&m->qlock, LK_RELEASE); 1225 lockmgr(&m->lock, LK_RELEASE); 1226 retval = 0; 1227 err: return retval; 1228 } 1229 1230 /* 1231 * Always blocking. 1232 */ 1233 1234 int 1235 midisynth_writeraw(void *n, uint8_t *buf, size_t len) 1236 { 1237 struct snd_midi *m = ((struct synth_midi *)n)->m; 1238 int retval; 1239 int used; 1240 int i; 1241 1242 MIDI_DEBUG(4, kprintf("midisynth_writeraw\n")); 1243 1244 retval = 0; 1245 1246 if (m == NULL) 1247 return ENXIO; 1248 1249 lockmgr(&m->lock, LK_EXCLUSIVE); 1250 lockmgr(&m->qlock, LK_EXCLUSIVE); 1251 1252 if (!(m->flags & M_TX)) 1253 goto err1; 1254 1255 if (midi_dumpraw) 1256 kprintf("midi dump: "); 1257 1258 while (len > 0) { 1259 while (MIDIQ_AVAIL(m->outq) == 0) { 1260 if (!(m->flags & M_TXEN)) { 1261 m->flags |= M_TXEN; 1262 MPU_CALLBACK(m, m->cookie, m->flags); 1263 } 1264 lockmgr(&m->lock, LK_RELEASE); 1265 m->wchan = 1; 1266 MIDI_DEBUG(3, kprintf("midisynth_writeraw lksleep\n")); 1267 retval = lksleep(&m->wchan, &m->qlock, 1268 PCATCH, "midi TX", 0); 1269 /* 1270 * We slept, maybe things have changed since last 1271 * dying check 1272 */ 1273 if (retval == EINTR) 1274 goto err0; 1275 1276 if (retval) 1277 goto err0; 1278 lockmgr(&m->lock, LK_EXCLUSIVE); 1279 lockmgr(&m->qlock, LK_EXCLUSIVE); 1280 m->wchan = 0; 1281 if (!m->busy) 1282 goto err1; 1283 } 1284 1285 /* 1286 * We are certain than data can be placed on the queue 1287 */ 1288 1289 used = MIN(MIDIQ_AVAIL(m->outq), len); 1290 used = MIN(used, MIDI_WSIZE); 1291 MIDI_DEBUG(5, 1292 kprintf("midi_synth: resid %zu len %jd avail %jd\n", 1293 len, (intmax_t)MIDIQ_LEN(m->outq), 1294 (intmax_t)MIDIQ_AVAIL(m->outq))); 1295 1296 if (midi_dumpraw) 1297 for (i = 0; i < used; i++) 1298 kprintf("%x ", buf[i]); 1299 1300 MIDIQ_ENQ(m->outq, buf, used); 1301 len -= used; 1302 1303 /* 1304 * Inform the bottom half that data can be written 1305 */ 1306 if (!(m->flags & M_TXEN)) { 1307 m->flags |= M_TXEN; 1308 MPU_CALLBACK(m, m->cookie, m->flags); 1309 } 1310 } 1311 /* 1312 * If we Made it here then transfer is good 1313 */ 1314 if (midi_dumpraw) 1315 kprintf("\n"); 1316 1317 retval = 0; 1318 err1: lockmgr(&m->qlock, LK_RELEASE); 1319 lockmgr(&m->lock, LK_RELEASE); 1320 err0: return retval; 1321 } 1322 1323 static int 1324 midisynth_killnote(void *n, uint8_t chn, uint8_t note, uint8_t vel) 1325 { 1326 u_char c[3]; 1327 1328 1329 if (note > 127 || chn > 15) 1330 return (EINVAL); 1331 1332 if (vel > 127) 1333 vel = 127; 1334 1335 if (vel == 64) { 1336 c[0] = 0x90 | (chn & 0x0f); /* Note on. */ 1337 c[1] = (u_char)note; 1338 c[2] = 0; 1339 } else { 1340 c[0] = 0x80 | (chn & 0x0f); /* Note off. */ 1341 c[1] = (u_char)note; 1342 c[2] = (u_char)vel; 1343 } 1344 1345 return midisynth_writeraw(n, c, 3); 1346 } 1347 1348 static int 1349 midisynth_setinstr(void *n, uint8_t chn, uint16_t instr) 1350 { 1351 u_char c[2]; 1352 1353 if (instr > 127 || chn > 15) 1354 return EINVAL; 1355 1356 c[0] = 0xc0 | (chn & 0x0f); /* Progamme change. */ 1357 c[1] = instr + midi_instroff; 1358 1359 return midisynth_writeraw(n, c, 2); 1360 } 1361 1362 static int 1363 midisynth_startnote(void *n, uint8_t chn, uint8_t note, uint8_t vel) 1364 { 1365 u_char c[3]; 1366 1367 if (note > 127 || chn > 15) 1368 return EINVAL; 1369 1370 if (vel > 127) 1371 vel = 127; 1372 1373 c[0] = 0x90 | (chn & 0x0f); /* Note on. */ 1374 c[1] = (u_char)note; 1375 c[2] = (u_char)vel; 1376 1377 return midisynth_writeraw(n, c, 3); 1378 } 1379 static int 1380 midisynth_alloc(void *n, uint8_t chan, uint8_t note) 1381 { 1382 return chan; 1383 } 1384 1385 static int 1386 midisynth_controller(void *n, uint8_t chn, uint8_t ctrlnum, uint16_t val) 1387 { 1388 u_char c[3]; 1389 1390 if (ctrlnum > 127 || chn > 15) 1391 return EINVAL; 1392 1393 c[0] = 0xb0 | (chn & 0x0f); /* Control Message. */ 1394 c[1] = ctrlnum; 1395 c[2] = val; 1396 return midisynth_writeraw(n, c, 3); 1397 } 1398 1399 static int 1400 midisynth_bender(void *n, uint8_t chn, uint16_t val) 1401 { 1402 u_char c[3]; 1403 1404 1405 if (val > 16383 || chn > 15) 1406 return EINVAL; 1407 1408 c[0] = 0xe0 | (chn & 0x0f); /* Pitch bend. */ 1409 c[1] = (u_char)val & 0x7f; 1410 c[2] = (u_char)(val >> 7) & 0x7f; 1411 1412 return midisynth_writeraw(n, c, 3); 1413 } 1414 1415 /* 1416 * Single point of midi destructions. 1417 */ 1418 static int 1419 midi_destroy(struct snd_midi *m, int midiuninit) 1420 { 1421 1422 KKASSERT(lockowned(&midistat_lock)); 1423 KKASSERT(lockowned(&m->lock)); 1424 1425 MIDI_DEBUG(3, kprintf("midi_destroy\n")); 1426 m->dev->si_drv1 = NULL; 1427 lockmgr(&m->lock, LK_RELEASE); /* XXX */ 1428 destroy_dev(m->dev); 1429 TAILQ_REMOVE(&midi_devs, m, link); 1430 if (midiuninit) 1431 MPU_UNINIT(m, m->cookie); 1432 kfree(MIDIQ_BUF(m->inq), M_MIDI); 1433 kfree(MIDIQ_BUF(m->outq), M_MIDI); 1434 lockuninit(&m->qlock); 1435 lockuninit(&m->lock); 1436 kfree(m, M_MIDI); 1437 return 0; 1438 } 1439 1440 /* 1441 * Load and unload functions, creates the /dev/midistat device 1442 */ 1443 1444 static int 1445 midi_load(void) 1446 { 1447 lockinit(&midistat_lock, "midistat lock", 0, LK_CANRECURSE); 1448 TAILQ_INIT(&midi_devs); /* Initialize the queue. */ 1449 1450 midistat_dev = make_dev(&midistat_ops, 1451 MIDIMKMINOR(0, MIDI_DEV_MIDICTL, 0), 1452 UID_ROOT, GID_WHEEL, 0666, "midistat"); 1453 1454 return 0; 1455 } 1456 1457 static int 1458 midi_unload(void) 1459 { 1460 struct snd_midi *m; 1461 int retval; 1462 1463 MIDI_DEBUG(1, kprintf("midi_unload()\n")); 1464 retval = EBUSY; 1465 lockmgr(&midistat_lock, LK_EXCLUSIVE); 1466 if (midistat_isopen) 1467 goto exit0; 1468 1469 TAILQ_FOREACH(m, &midi_devs, link) { 1470 lockmgr(&m->lock, LK_EXCLUSIVE); 1471 if (m->busy) 1472 retval = EBUSY; 1473 else 1474 retval = midi_destroy(m, 1); 1475 if (retval) 1476 goto exit1; 1477 } 1478 1479 lockmgr(&midistat_lock, LK_RELEASE); /* XXX */ 1480 1481 destroy_dev(midistat_dev); 1482 /* 1483 * Made it here then unload is complete 1484 */ 1485 lockuninit(&midistat_lock); 1486 return 0; 1487 1488 exit1: 1489 lockmgr(&m->lock, LK_RELEASE); 1490 exit0: 1491 lockmgr(&midistat_lock, LK_RELEASE); 1492 if (retval) 1493 MIDI_DEBUG(2, kprintf("midi_unload: failed\n")); 1494 return retval; 1495 } 1496 1497 extern int seq_modevent(module_t mod, int type, void *data); 1498 1499 static int 1500 midi_modevent(module_t mod, int type, void *data) 1501 { 1502 int retval; 1503 1504 retval = 0; 1505 1506 switch (type) { 1507 case MOD_LOAD: 1508 retval = midi_load(); 1509 #if 0 1510 if (retval == 0) 1511 retval = seq_modevent(mod, type, data); 1512 #endif 1513 break; 1514 1515 case MOD_UNLOAD: 1516 retval = midi_unload(); 1517 #if 0 1518 if (retval == 0) 1519 retval = seq_modevent(mod, type, data); 1520 #endif 1521 break; 1522 1523 default: 1524 break; 1525 } 1526 1527 return retval; 1528 } 1529 1530 kobj_t 1531 midimapper_addseq(void *arg1, int *unit, void **cookie) 1532 { 1533 unit = 0; 1534 1535 return (kobj_t)arg1; 1536 } 1537 1538 int 1539 midimapper_open(void *arg1, void **cookie) 1540 { 1541 int retval = 0; 1542 struct snd_midi *m; 1543 1544 lockmgr(&midistat_lock, LK_EXCLUSIVE); 1545 1546 TAILQ_FOREACH(m, &midi_devs, link) { 1547 retval++; 1548 } 1549 1550 lockmgr(&midistat_lock, LK_RELEASE); 1551 return retval; 1552 } 1553 1554 int 1555 midimapper_close(void *arg1, void *cookie) 1556 { 1557 return 0; 1558 } 1559 1560 kobj_t 1561 midimapper_fetch_synth(void *arg, void *cookie, int unit) 1562 { 1563 struct snd_midi *m; 1564 int retval = 0; 1565 1566 lockmgr(&midistat_lock, LK_EXCLUSIVE); 1567 1568 TAILQ_FOREACH(m, &midi_devs, link) { 1569 if (unit == retval) { 1570 lockmgr(&midistat_lock, LK_RELEASE); 1571 return (kobj_t)m->synth; 1572 } 1573 retval++; 1574 } 1575 1576 lockmgr(&midistat_lock, LK_RELEASE); 1577 return NULL; 1578 } 1579 1580 DEV_MODULE(midi, midi_modevent, NULL); 1581 MODULE_VERSION(midi, 1); 1582