The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/dev/sound/midi/midi.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

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

Cache object: 96cc382b2583a3750522f4d78f6f45e1


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.