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-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-2  -  FREEBSD-11-1  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-4  -  FREEBSD-10-3  -  FREEBSD-10-2  -  FREEBSD-10-1  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-3  -  FREEBSD-9-2  -  FREEBSD-9-1  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-4  -  FREEBSD-8-3  -  FREEBSD-8-2  -  FREEBSD-8-1  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-4  -  FREEBSD-7-3  -  FREEBSD-7-2  -  FREEBSD-7-1  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-4  -  FREEBSD-6-3  -  FREEBSD-6-2  -  FREEBSD-6-1  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-5  -  FREEBSD-5-4  -  FREEBSD-5-3  -  FREEBSD-5-2  -  FREEBSD-5-1  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  linux-2.6  -  linux-2.4.22  -  MK83  -  MK84  -  PLAN9  -  DFBSD  -  NETBSD  -  NETBSD5  -  NETBSD4  -  NETBSD3  -  NETBSD20  -  OPENBSD  -  xnu-517  -  xnu-792  -  xnu-792.6.70  -  xnu-1228  -  xnu-1456.1.26  -  xnu-1699.24.8  -  xnu-2050.18.24  -  OPENSOLARIS  -  minix-3-1-1 
SearchContext: -  none  -  3  -  10 

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

Cache object: 8200826bce5591db3bac202adfa03747


[ 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.