| @@ -1,14 +1,14 @@ | | | @@ -1,14 +1,14 @@ |
1 | /* $NetBSD: sequencer.c,v 1.52.14.2 2011/11/20 20:00:15 jmcneill Exp $ */ | | 1 | /* $NetBSD: sequencer.c,v 1.52.14.3 2011/11/22 07:57:23 mrg Exp $ */ |
2 | | | 2 | |
3 | /* | | 3 | /* |
4 | * Copyright (c) 1998, 2008 The NetBSD Foundation, Inc. | | 4 | * Copyright (c) 1998, 2008 The NetBSD Foundation, Inc. |
5 | * All rights reserved. | | 5 | * All rights reserved. |
6 | * | | 6 | * |
7 | * This code is derived from software contributed to The NetBSD Foundation | | 7 | * This code is derived from software contributed to The NetBSD Foundation |
8 | * by Lennart Augustsson (augustss@NetBSD.org) and by Andrew Doran. | | 8 | * by Lennart Augustsson (augustss@NetBSD.org) and by Andrew Doran. |
9 | * | | 9 | * |
10 | * Redistribution and use in source and binary forms, with or without | | 10 | * Redistribution and use in source and binary forms, with or without |
11 | * modification, are permitted provided that the following conditions | | 11 | * modification, are permitted provided that the following conditions |
12 | * are met: | | 12 | * are met: |
13 | * 1. Redistributions of source code must retain the above copyright | | 13 | * 1. Redistributions of source code must retain the above copyright |
14 | * notice, this list of conditions and the following disclaimer. | | 14 | * notice, this list of conditions and the following disclaimer. |
| @@ -45,27 +45,27 @@ | | | @@ -45,27 +45,27 @@ |
45 | * o MIDI softc locks. These can be spinlocks and there can be many of | | 45 | * o MIDI softc locks. These can be spinlocks and there can be many of |
46 | * them, because we can open many MIDI devices. We take these only in two | | 46 | * them, because we can open many MIDI devices. We take these only in two |
47 | * places: when enabling redirection from the MIDI device and when | | 47 | * places: when enabling redirection from the MIDI device and when |
48 | * disabling it (open/close). midiseq_in() is called by the MIDI driver | | 48 | * disabling it (open/close). midiseq_in() is called by the MIDI driver |
49 | * with its own lock held when passing data into this module. To avoid | | 49 | * with its own lock held when passing data into this module. To avoid |
50 | * lock order and context problems, we package the received message as a | | 50 | * lock order and context problems, we package the received message as a |
51 | * sequencer_pcqitem_t and put onto a producer-consumer queue. A soft | | 51 | * sequencer_pcqitem_t and put onto a producer-consumer queue. A soft |
52 | * interrupt is scheduled to dequeue and decode the message later where we | | 52 | * interrupt is scheduled to dequeue and decode the message later where we |
53 | * can safely acquire the sequencer device's sc_lock. PCQ is lockless for | | 53 | * can safely acquire the sequencer device's sc_lock. PCQ is lockless for |
54 | * multiple producer, single consumer settings like this one. | | 54 | * multiple producer, single consumer settings like this one. |
55 | */ | | 55 | */ |
56 | | | 56 | |
57 | #include <sys/cdefs.h> | | 57 | #include <sys/cdefs.h> |
58 | __KERNEL_RCSID(0, "$NetBSD: sequencer.c,v 1.52.14.2 2011/11/20 20:00:15 jmcneill Exp $"); | | 58 | __KERNEL_RCSID(0, "$NetBSD: sequencer.c,v 1.52.14.3 2011/11/22 07:57:23 mrg Exp $"); |
59 | | | 59 | |
60 | #include "sequencer.h" | | 60 | #include "sequencer.h" |
61 | | | 61 | |
62 | #include <sys/param.h> | | 62 | #include <sys/param.h> |
63 | #include <sys/ioctl.h> | | 63 | #include <sys/ioctl.h> |
64 | #include <sys/fcntl.h> | | 64 | #include <sys/fcntl.h> |
65 | #include <sys/vnode.h> | | 65 | #include <sys/vnode.h> |
66 | #include <sys/select.h> | | 66 | #include <sys/select.h> |
67 | #include <sys/poll.h> | | 67 | #include <sys/poll.h> |
68 | #include <sys/kmem.h> | | 68 | #include <sys/kmem.h> |
69 | #include <sys/proc.h> | | 69 | #include <sys/proc.h> |
70 | #include <sys/systm.h> | | 70 | #include <sys/systm.h> |
71 | #include <sys/syslog.h> | | 71 | #include <sys/syslog.h> |
| @@ -360,56 +360,59 @@ seq_startoutput(struct sequencer_softc * | | | @@ -360,56 +360,59 @@ seq_startoutput(struct sequencer_softc * |
360 | while(!SEQ_QEMPTY(q) && !sc->timeout) { | | 360 | while(!SEQ_QEMPTY(q) && !sc->timeout) { |
361 | SEQ_QGET(q, cmd); | | 361 | SEQ_QGET(q, cmd); |
362 | seq_do_command(sc, &cmd); | | 362 | seq_do_command(sc, &cmd); |
363 | } | | 363 | } |
364 | } | | 364 | } |
365 | | | 365 | |
366 | static int | | 366 | static int |
367 | sequencerclose(dev_t dev, int flags, int ifmt, struct lwp *l) | | 367 | sequencerclose(dev_t dev, int flags, int ifmt, struct lwp *l) |
368 | { | | 368 | { |
369 | struct sequencer_softc *sc; | | 369 | struct sequencer_softc *sc; |
370 | struct midi_softc *msc; | | 370 | struct midi_softc *msc; |
371 | int unit, error; | | 371 | int unit, error; |
372 | | | 372 | |
373 | DPRINTF(("sequencerclose: %d\n", dev)); | | 373 | DPRINTF(("sequencerclose: %"PRIx64"\n", dev)); |
374 | | | 374 | |
375 | if ((error = sequencer_enter(dev, &sc)) != 0) | | 375 | if ((error = sequencer_enter(dev, &sc)) != 0) |
376 | return error; | | 376 | return error; |
377 | seq_drain(sc); | | 377 | seq_drain(sc); |
378 | if (sc->timeout) { | | 378 | if (sc->timeout) { |
379 | callout_halt(&sc->sc_callout, &sc->lock); | | 379 | callout_halt(&sc->sc_callout, &sc->lock); |
380 | sc->timeout = 0; | | 380 | sc->timeout = 0; |
381 | } | | 381 | } |
382 | /* Bin input from MIDI devices. */ | | 382 | /* Bin input from MIDI devices. */ |
383 | for (unit = 0; unit < sc->nmidi; unit++) { | | 383 | for (unit = 0; unit < sc->nmidi; unit++) { |
384 | msc = sc->devs[unit]->msc; | | 384 | msc = sc->devs[unit]->msc; |
385 | mutex_enter(msc->lock); | | 385 | mutex_enter(msc->lock); |
386 | msc->seqopen = 0; | | 386 | msc->seqopen = 0; |
387 | mutex_exit(msc->lock); | | 387 | mutex_exit(msc->lock); |
388 | } | | 388 | } |
389 | mutex_exit(&sc->lock); | | 389 | mutex_exit(&sc->lock); |
390 | | | 390 | |
391 | for (unit = 0; unit < sc->nmidi; unit++) | | 391 | for (unit = 0; unit < sc->nmidi; unit++) |
392 | midiseq_close(sc->devs[unit]); | | 392 | if (sc->devs[unit] != NULL) |
| | | 393 | midiseq_close(sc->devs[unit]); |
393 | if (sc->devs != NULL) { | | 394 | if (sc->devs != NULL) { |
394 | KASSERT(sc->ndevs > 0); | | 395 | KASSERT(sc->ndevs > 0); |
395 | kmem_free(sc->devs, sc->ndevs * sizeof(struct midi_dev *)); | | 396 | kmem_free(sc->devs, sc->ndevs * sizeof(struct midi_dev *)); |
396 | sc->devs = NULL; | | 397 | sc->devs = NULL; |
397 | } | | 398 | } |
398 | | | 399 | |
399 | mutex_enter(&sc->lock); | | 400 | mutex_enter(&sc->lock); |
400 | sc->isopen = 0; | | 401 | sc->isopen = 0; |
401 | sequencer_exit(sc); | | 402 | sequencer_exit(sc); |
402 | | | 403 | |
| | | 404 | DPRINTF(("sequencerclose: %"PRIx64" done\n", dev)); |
| | | 405 | |
403 | return (0); | | 406 | return (0); |
404 | } | | 407 | } |
405 | | | 408 | |
406 | static int | | 409 | static int |
407 | seq_input_event(struct sequencer_softc *sc, seq_event_t *cmd) | | 410 | seq_input_event(struct sequencer_softc *sc, seq_event_t *cmd) |
408 | { | | 411 | { |
409 | struct sequencer_queue *q; | | 412 | struct sequencer_queue *q; |
410 | proc_t *p; | | 413 | proc_t *p; |
411 | | | 414 | |
412 | KASSERT(mutex_owned(&sc->lock)); | | 415 | KASSERT(mutex_owned(&sc->lock)); |
413 | | | 416 | |
414 | DPRINTFN(2, ("seq_input_event: %02x %02x %02x %02x %02x " | | 417 | DPRINTFN(2, ("seq_input_event: %02x %02x %02x %02x %02x " |
415 | "%02x %02x %02x\n", cmd->tag, | | 418 | "%02x %02x %02x\n", cmd->tag, |
| @@ -500,27 +503,27 @@ seq_softintr(void *addr) | | | @@ -500,27 +503,27 @@ seq_softintr(void *addr) |
500 | } | | 503 | } |
501 | seq_input_event(sc, &ev); | | 504 | seq_input_event(sc, &ev); |
502 | mutex_exit(&sc->lock); | | 505 | mutex_exit(&sc->lock); |
503 | } | | 506 | } |
504 | | | 507 | |
505 | static int | | 508 | static int |
506 | sequencerread(dev_t dev, struct uio *uio, int ioflag) | | 509 | sequencerread(dev_t dev, struct uio *uio, int ioflag) |
507 | { | | 510 | { |
508 | struct sequencer_softc *sc; | | 511 | struct sequencer_softc *sc; |
509 | struct sequencer_queue *q; | | 512 | struct sequencer_queue *q; |
510 | seq_event_t ev; | | 513 | seq_event_t ev; |
511 | int error; | | 514 | int error; |
512 | | | 515 | |
513 | DPRINTFN(20, ("sequencerread: %d, count=%d, ioflag=%x\n", | | 516 | DPRINTFN(20, ("sequencerread: %"PRIx64", count=%d, ioflag=%x\n", |
514 | dev, (int)uio->uio_resid, ioflag)); | | 517 | dev, (int)uio->uio_resid, ioflag)); |
515 | | | 518 | |
516 | q = &sc->inq; | | 519 | q = &sc->inq; |
517 | if ((error = sequencer_enter(dev, &sc)) != 0) | | 520 | if ((error = sequencer_enter(dev, &sc)) != 0) |
518 | return error; | | 521 | return error; |
519 | if (sc->mode == SEQ_OLD) { | | 522 | if (sc->mode == SEQ_OLD) { |
520 | sequencer_exit(sc); | | 523 | sequencer_exit(sc); |
521 | DPRINTFN(-1,("sequencerread: old read\n")); | | 524 | DPRINTFN(-1,("sequencerread: old read\n")); |
522 | return EINVAL; /* XXX unimplemented */ | | 525 | return EINVAL; /* XXX unimplemented */ |
523 | } | | 526 | } |
524 | while (SEQ_QEMPTY(q)) { | | 527 | while (SEQ_QEMPTY(q)) { |
525 | if (ioflag & IO_NDELAY) { | | 528 | if (ioflag & IO_NDELAY) { |
526 | error = EWOULDBLOCK; | | 529 | error = EWOULDBLOCK; |
| @@ -547,27 +550,27 @@ sequencerread(dev_t dev, struct uio *uio | | | @@ -547,27 +550,27 @@ sequencerread(dev_t dev, struct uio *uio |
547 | sequencer_exit(sc); | | 550 | sequencer_exit(sc); |
548 | return error; | | 551 | return error; |
549 | } | | 552 | } |
550 | | | 553 | |
551 | static int | | 554 | static int |
552 | sequencerwrite(dev_t dev, struct uio *uio, int ioflag) | | 555 | sequencerwrite(dev_t dev, struct uio *uio, int ioflag) |
553 | { | | 556 | { |
554 | struct sequencer_softc *sc; | | 557 | struct sequencer_softc *sc; |
555 | struct sequencer_queue *q; | | 558 | struct sequencer_queue *q; |
556 | int error; | | 559 | int error; |
557 | seq_event_t cmdbuf; | | 560 | seq_event_t cmdbuf; |
558 | int size; | | 561 | int size; |
559 | | | 562 | |
560 | DPRINTFN(2, ("sequencerwrite: %d, count=%d\n", dev, | | 563 | DPRINTFN(2, ("sequencerwrite: %"PRIx64", count=%d\n", dev, |
561 | (int)uio->uio_resid)); | | 564 | (int)uio->uio_resid)); |
562 | | | 565 | |
563 | q = &sc->outq; | | 566 | q = &sc->outq; |
564 | | | 567 | |
565 | if ((error = sequencer_enter(dev, &sc)) != 0) | | 568 | if ((error = sequencer_enter(dev, &sc)) != 0) |
566 | return error; | | 569 | return error; |
567 | size = sc->mode == SEQ_NEW ? sizeof cmdbuf : SEQOLD_CMDSIZE; | | 570 | size = sc->mode == SEQ_NEW ? sizeof cmdbuf : SEQOLD_CMDSIZE; |
568 | while (uio->uio_resid >= size && error == 0) { | | 571 | while (uio->uio_resid >= size && error == 0) { |
569 | mutex_exit(&sc->lock); | | 572 | mutex_exit(&sc->lock); |
570 | error = uiomove(&cmdbuf, size, uio); | | 573 | error = uiomove(&cmdbuf, size, uio); |
571 | if (error == 0) { | | 574 | if (error == 0) { |
572 | if (sc->mode == SEQ_OLD && seq_to_new(&cmdbuf, uio)) { | | 575 | if (sc->mode == SEQ_OLD && seq_to_new(&cmdbuf, uio)) { |
573 | continue; | | 576 | continue; |
| @@ -610,27 +613,27 @@ sequencerwrite(dev_t dev, struct uio *ui | | | @@ -610,27 +613,27 @@ sequencerwrite(dev_t dev, struct uio *ui |
610 | return error; | | 613 | return error; |
611 | } | | 614 | } |
612 | | | 615 | |
613 | static int | | 616 | static int |
614 | sequencerioctl(dev_t dev, u_long cmd, void *addr, int flag, struct lwp *l) | | 617 | sequencerioctl(dev_t dev, u_long cmd, void *addr, int flag, struct lwp *l) |
615 | { | | 618 | { |
616 | struct sequencer_softc *sc; | | 619 | struct sequencer_softc *sc; |
617 | struct synth_info *si; | | 620 | struct synth_info *si; |
618 | struct midi_dev *md; | | 621 | struct midi_dev *md; |
619 | int devno, error, t; | | 622 | int devno, error, t; |
620 | struct timeval now; | | 623 | struct timeval now; |
621 | u_long tx; | | 624 | u_long tx; |
622 | | | 625 | |
623 | DPRINTFN(2, ("sequencerioctl: %d cmd=0x%08lx\n", dev, cmd)); | | 626 | DPRINTFN(2, ("sequencerioctl: %"PRIx64" cmd=0x%08lx\n", dev, cmd)); |
624 | | | 627 | |
625 | if ((error = sequencer_enter(dev, &sc)) != 0) | | 628 | if ((error = sequencer_enter(dev, &sc)) != 0) |
626 | return error; | | 629 | return error; |
627 | switch (cmd) { | | 630 | switch (cmd) { |
628 | case FIONBIO: | | 631 | case FIONBIO: |
629 | /* All handled in the upper FS layer. */ | | 632 | /* All handled in the upper FS layer. */ |
630 | break; | | 633 | break; |
631 | | | 634 | |
632 | case FIOASYNC: | | 635 | case FIOASYNC: |
633 | if (*(int *)addr) { | | 636 | if (*(int *)addr) { |
634 | if (sc->async != 0) | | 637 | if (sc->async != 0) |
635 | return EBUSY; | | 638 | return EBUSY; |
636 | sc->async = curproc->p_pid; | | 639 | sc->async = curproc->p_pid; |