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