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  * Main midi driver for FreeBSD. This file provides the main
    3  * entry points for probe/attach and all i/o demultiplexing, including
    4  * default routines for generic devices.
    5  * 
    6  * (C) 1999 Seigo Tanimura
    7  * 
    8  * Redistribution and use in source and binary forms, with or
    9  * without modification, are permitted provided that the following
   10  * conditions are met:
   11  * 1. Redistributions of source code must retain the above copyright
   12  *    notice, this list of conditions and the following disclaimer.
   13  * 2. Redistributions in binary form must reproduce the above
   14  *    copyright notice, this list of conditions and the following
   15  *    disclaimer in the documentation and/or other materials provided
   16  *    with the distribution.
   17  *
   18  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS
   19  * IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
   20  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
   21  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE
   22  * AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
   23  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
   24  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   25  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
   26  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
   27  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
   28  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
   29  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   30  *
   31  *
   32  * For each card type a template "mididev_info" structure contains
   33  * all the relevant parameters, both for configuration and runtime.
   34  *
   35  * In this file we build tables of pointers to the descriptors for
   36  * the various supported cards. The generic probe routine scans
   37  * the table(s) looking for a matching entry, then invokes the
   38  * board-specific probe routine. If successful, a pointer to the
   39  * correct mididev_info is stored in mididev_last_probed, for subsequent
   40  * use in the attach routine. The generic attach routine copies
   41  * the template to a permanent descriptor (midi_info and
   42  * friends), initializes all generic parameters, and calls the
   43  * board-specific attach routine.
   44  *
   45  * On device calls, the generic routines do the checks on unit and
   46  * device parameters, then call the board-specific routines if
   47  * available, or try to perform the task using the default code.
   48  *
   49  * $FreeBSD: releng/5.2/sys/dev/sound/midi/midi.c 111815 2003-03-03 12:15:54Z phk $
   50  *
   51  */
   52 
   53 #include <dev/sound/midi/midi.h>
   54 
   55 static devclass_t midi_devclass;
   56 
   57 static d_open_t midiopen;
   58 static d_close_t midiclose;
   59 static d_ioctl_t midiioctl;
   60 static d_read_t midiread;
   61 static d_write_t midiwrite;
   62 static d_poll_t midipoll;
   63 
   64 /* These functions are local. */
   65 static d_open_t midistat_open;
   66 static d_close_t midistat_close;
   67 static d_read_t midistat_read;
   68 static int midi_initstatus(char *buf, int size);
   69 static int midi_readstatus(char *buf, int *ptr, struct uio *uio);
   70 
   71 #define CDEV_MAJOR MIDI_CDEV_MAJOR
   72 static struct cdevsw midi_cdevsw = {
   73         .d_open =       midiopen,
   74         .d_close =      midiclose,
   75         .d_read =       midiread,
   76         .d_write =      midiwrite,
   77         .d_ioctl =      midiioctl,
   78         .d_poll =       midipoll,
   79         .d_name =       "midi",
   80         .d_maj =        CDEV_MAJOR,
   81 };
   82 
   83 /*
   84  * descriptors for active devices. also used as the public softc
   85  * of a device.
   86  */
   87 static TAILQ_HEAD(,_mididev_info)       midi_info;
   88 static int              nmidi, nsynth;
   89 /* Mutex to protect midi_info, nmidi and nsynth. */
   90 static struct mtx       midiinfo_mtx;
   91 static int              midiinfo_mtx_init;
   92 
   93 /* These make the buffer for /dev/midistat */
   94 static int              midistatbusy;
   95 static char             midistatbuf[4096];
   96 static int              midistatptr;
   97 
   98 SYSCTL_NODE(_hw, OID_AUTO, midi, CTLFLAG_RD, 0, "Midi driver");
   99 
  100 int                     midi_debug;
  101 SYSCTL_INT(_hw_midi, OID_AUTO, debug, CTLFLAG_RW, &midi_debug, 0, "");
  102 
  103 midi_cmdtab     cmdtab_midiioctl[] = {
  104         {SNDCTL_MIDI_PRETIME,   "SNDCTL_MIDI_PRETIME"},
  105         {SNDCTL_MIDI_MPUMODE,   "SNDCTL_MIDI_MPUMODE"},
  106         {SNDCTL_MIDI_MPUCMD,    "SNDCTL_MIDI_MPUCMD"},
  107         {SNDCTL_SYNTH_INFO,     "SNDCTL_SYNTH_INFO"},
  108         {SNDCTL_MIDI_INFO,      "SNDCTL_MIDI_INFO"},
  109         {SNDCTL_SYNTH_MEMAVL,   "SNDCTL_SYNTH_MEMAVL"},
  110         {SNDCTL_FM_LOAD_INSTR,  "SNDCTL_FM_LOAD_INSTR"},
  111         {SNDCTL_FM_4OP_ENABLE,  "SNDCTL_FM_4OP_ENABLE"},
  112         {MIOSPASSTHRU,          "MIOSPASSTHRU"},
  113         {MIOGPASSTHRU,          "MIOGPASSTHRU"},
  114         {AIONWRITE,             "AIONWRITE"},
  115         {AIOGSIZE,              "AIOGSIZE"},
  116         {AIOSSIZE,              "AIOSSIZE"},
  117         {AIOGFMT,               "AIOGFMT"},
  118         {AIOSFMT,               "AIOSFMT"},
  119         {AIOGMIX,               "AIOGMIX"},
  120         {AIOSMIX,               "AIOSMIX"},
  121         {AIOSTOP,               "AIOSTOP"},
  122         {AIOSYNC,               "AIOSYNC"},
  123         {AIOGCAP,               "AIOGCAP"},
  124         {-1,                    NULL},
  125 };
  126 
  127 /*
  128  * This is the generic init routine.
  129  * Must be called after device-specific init.
  130  */
  131 int
  132 midiinit(mididev_info *d, device_t dev)
  133 {
  134         int unit;
  135 
  136         /*
  137          * initialize standard parameters for the device. This can be
  138          * overridden by device-specific configurations but better do
  139          * here the generic things.
  140          */
  141 
  142         MIDI_DEBUG(printf("midiinit: unit %d.\n", d->unit));
  143 
  144         unit = d->unit;
  145         d->softc = device_get_softc(dev);
  146         d->dev = dev;
  147         d->magic = MAGIC(d->unit); /* debugging... */
  148         d->flags = 0;
  149         d->fflags = 0;
  150         d->midi_dbuf_in.unit_size = 1;
  151         d->midi_dbuf_out.unit_size = 1;
  152         d->midi_dbuf_passthru.unit_size = 1;
  153 
  154         mtx_unlock(&d->flagqueue_mtx);
  155 
  156         if (midi_devclass == NULL) {
  157                 midi_devclass = device_get_devclass(dev);
  158                 make_dev(&midi_cdevsw, MIDIMKMINOR(0, MIDI_DEV_STATUS),
  159                          UID_ROOT, GID_WHEEL, 0444, "midistat");
  160         }
  161         make_dev(&midi_cdevsw, MIDIMKMINOR(unit, MIDI_DEV_MIDIN),
  162                  UID_ROOT, GID_WHEEL, 0666, "midi%d", unit);
  163 
  164         return 0 ;
  165 }
  166 
  167 /*
  168  * a small utility function which, given a device number, returns
  169  * a pointer to the associated mididev_info struct, and sets the unit
  170  * number.
  171  */
  172 mididev_info *
  173 get_mididev_info(dev_t i_dev, int *unit)
  174 {
  175         int u;
  176 
  177         if (MIDIDEV(i_dev) != MIDI_DEV_MIDIN)
  178                 return NULL;
  179         u = MIDIUNIT(i_dev);
  180         if (unit)
  181                 *unit = u;
  182 
  183         return get_mididev_info_unit(u);
  184 }
  185 
  186 /*
  187  * a small utility function which, given a unit number, returns
  188  * a pointer to the associated mididev_info struct.
  189  */
  190 mididev_info *
  191 get_mididev_info_unit(int unit)
  192 {
  193         mididev_info *md;
  194 
  195         /* XXX */
  196         if (!midiinfo_mtx_init) {
  197                 midiinfo_mtx_init = 1;
  198                 mtx_init(&midiinfo_mtx, "midinf", NULL, MTX_DEF);
  199                 TAILQ_INIT(&midi_info);
  200         }
  201 
  202         mtx_lock(&midiinfo_mtx);
  203         TAILQ_FOREACH(md, &midi_info, md_link) {
  204                 if (md->unit == unit)
  205                         break;
  206         }
  207         mtx_unlock(&midiinfo_mtx);
  208 
  209         return md;
  210 }
  211 
  212 /*
  213  * a small utility function which, given a unit number, returns
  214  * a pointer to the associated mididev_info struct with MDT_MIDI.
  215  */
  216 mididev_info *
  217 get_mididev_midi_unit(int unit)
  218 {
  219         mididev_info *md;
  220 
  221         /* XXX */
  222         if (!midiinfo_mtx_init) {
  223                 midiinfo_mtx_init = 1;
  224                 mtx_init(&midiinfo_mtx, "midinf", NULL, MTX_DEF);
  225                 TAILQ_INIT(&midi_info);
  226         }
  227 
  228         mtx_lock(&midiinfo_mtx);
  229         TAILQ_FOREACH(md, &midi_info, md_link) {
  230                 if (md->midiunit == unit)
  231                         break;
  232         }
  233         mtx_unlock(&midiinfo_mtx);
  234 
  235         return md;
  236 }
  237 
  238 /*
  239  * a small utility function which, given a unit number, returns
  240  * a pointer to the associated mididev_info struct with MDT_SYNTH.
  241  */
  242 mididev_info *
  243 get_mididev_synth_unit(int unit)
  244 {
  245         mididev_info *md;
  246 
  247         /* XXX */
  248         if (!midiinfo_mtx_init) {
  249                 midiinfo_mtx_init = 1;
  250                 mtx_init(&midiinfo_mtx, "midinf", NULL, MTX_DEF);
  251                 TAILQ_INIT(&midi_info);
  252         }
  253 
  254         mtx_lock(&midiinfo_mtx);
  255         TAILQ_FOREACH(md, &midi_info, md_link) {
  256                 if (md->synthunit == unit)
  257                         break;
  258         }
  259         mtx_unlock(&midiinfo_mtx);
  260 
  261         return md;
  262 }
  263 
  264 /* Create a new midi device info structure. */
  265 /* TODO: lock md, then exit. */
  266 mididev_info *
  267 create_mididev_info_unit(int type, mididev_info *mdinf, synthdev_info *syninf)
  268 {
  269         int unit;
  270         mididev_info *md, *mdnew;
  271 
  272         /* XXX */
  273         if (!midiinfo_mtx_init) {
  274                 midiinfo_mtx_init = 1;
  275                 mtx_init(&midiinfo_mtx, "midinf", NULL, MTX_DEF);
  276                 TAILQ_INIT(&midi_info);
  277         }
  278 
  279         /* As malloc(9) might block, allocate mididev_info now. */
  280         mdnew = malloc(sizeof(mididev_info), M_DEVBUF, M_WAITOK | M_ZERO);
  281         if (mdnew == NULL)
  282                 return NULL;
  283         bcopy(mdinf, mdnew, sizeof(mididev_info));
  284         bcopy(syninf, &mdnew->synth, sizeof(synthdev_info));
  285         midibuf_init(&mdnew->midi_dbuf_in);
  286         midibuf_init(&mdnew->midi_dbuf_out);
  287         midibuf_init(&mdnew->midi_dbuf_passthru);
  288         mtx_init(&mdnew->flagqueue_mtx, "midflq", NULL, MTX_DEF);
  289         mtx_init(&mdnew->synth.vc_mtx, "synsvc", NULL, MTX_DEF);
  290         mtx_init(&mdnew->synth.status_mtx, "synsst", NULL, MTX_DEF);
  291 
  292         mtx_lock(&midiinfo_mtx);
  293 
  294         switch (type) {
  295         case MDT_MIDI:
  296                 mdnew->midiunit = nmidi;
  297                 mdnew->synthunit = nmidi;
  298                 nmidi++;
  299                 break;
  300         case MDT_SYNTH:
  301                 mdnew->midiunit = -1;
  302                 mdnew->synthunit = nsynth;
  303                 nsynth++;
  304                 break;
  305         default:
  306                 mtx_unlock(&midiinfo_mtx);
  307                 midibuf_destroy(&mdnew->midi_dbuf_in);
  308                 midibuf_destroy(&mdnew->midi_dbuf_out);
  309                 midibuf_destroy(&mdnew->midi_dbuf_passthru);
  310                 mtx_destroy(&mdnew->flagqueue_mtx);
  311                 mtx_destroy(&mdnew->synth.vc_mtx);
  312                 mtx_destroy(&mdnew->synth.status_mtx);
  313                 free(mdnew, M_DEVBUF);
  314                 panic("unsupported device type");
  315                 return NULL;
  316         }
  317         mdnew->mdtype = type;
  318 
  319         for (unit = 0 ; ; unit++) {
  320                 TAILQ_FOREACH(md, &midi_info, md_link) {
  321                         if (md->unit == unit)
  322                                 break;
  323                 }
  324                 if (md == NULL)
  325                         break;
  326         }
  327 
  328         mdnew->unit = unit;
  329         mtx_lock(&mdnew->flagqueue_mtx);
  330         TAILQ_INSERT_TAIL(&midi_info, mdnew, md_link);
  331 
  332         mtx_unlock(&midiinfo_mtx);
  333 
  334         return mdnew;
  335 }
  336 
  337 /* Return the number of configured devices. */
  338 int
  339 mididev_info_number(void)
  340 {
  341         return nmidi + nsynth;
  342 }
  343 
  344 /* Return the number of configured midi devices. */
  345 int
  346 mididev_midi_number(void)
  347 {
  348         return nmidi;
  349 }
  350 
  351 /* Return the number of configured synth devices. */
  352 int
  353 mididev_synth_number(void)
  354 {
  355         return nsynth;
  356 }
  357 
  358 /*
  359  * here are the switches for the main functions. The switches do
  360  * all necessary checks on the device number to make sure
  361  * that the device is configured. They also provide some default
  362  * functionalities so that device-specific drivers have to deal
  363  * only with special cases.
  364  */
  365 
  366 static int
  367 midiopen(dev_t i_dev, int flags, int mode, struct thread *td)
  368 {
  369         int ret;
  370 
  371         switch (MIDIDEV(i_dev)) {
  372         case MIDI_DEV_MIDIN:
  373                 ret = midi_open(i_dev, flags, mode, td);
  374                 break;
  375         case MIDI_DEV_STATUS:
  376                 ret = midistat_open(i_dev, flags, mode, td);
  377                 break;
  378         default:
  379                 ret = ENXIO;
  380                 break;
  381         }
  382 
  383         return (ret);
  384 }
  385 
  386 static int
  387 midiclose(dev_t i_dev, int flags, int mode, struct thread *td)
  388 {
  389         int ret;
  390 
  391         switch (MIDIDEV(i_dev)) {
  392         case MIDI_DEV_MIDIN:
  393                 ret = midi_close(i_dev, flags, mode, td);
  394                 break;
  395         case MIDI_DEV_STATUS:
  396                 ret = midistat_close(i_dev, flags, mode, td);
  397                 break;
  398         default:
  399                 ret = ENXIO;
  400                 break;
  401         }
  402 
  403         return (ret);
  404 }
  405 
  406 static int
  407 midiread(dev_t i_dev, struct uio * buf, int flag)
  408 {
  409         int ret;
  410 
  411         switch (MIDIDEV(i_dev)) {
  412         case MIDI_DEV_MIDIN:
  413                 ret = midi_read(i_dev, buf, flag);
  414                 break;
  415         case MIDI_DEV_STATUS:
  416                 ret = midistat_read(i_dev, buf, flag);
  417                 break;
  418         default:
  419                 ret = ENXIO;
  420                 break;
  421         }
  422 
  423         return (ret);
  424 }
  425 
  426 static int
  427 midiwrite(dev_t i_dev, struct uio * buf, int flag)
  428 {
  429         int ret;
  430 
  431         switch (MIDIDEV(i_dev)) {
  432         case MIDI_DEV_MIDIN:
  433                 ret = midi_write(i_dev, buf, flag);
  434                 break;
  435         default:
  436                 ret = ENXIO;
  437                 break;
  438         }
  439 
  440         return (ret);
  441 }
  442 
  443 static int
  444 midiioctl(dev_t i_dev, u_long cmd, caddr_t arg, int mode, struct thread *td)
  445 {
  446         int ret;
  447 
  448         switch (MIDIDEV(i_dev)) {
  449         case MIDI_DEV_MIDIN:
  450                 ret = midi_ioctl(i_dev, cmd, arg, mode, td);
  451                 break;
  452         default:
  453                 ret = ENXIO;
  454                 break;
  455         }
  456 
  457         return (ret);
  458 }
  459 
  460 static int
  461 midipoll(dev_t i_dev, int events, struct thread *td)
  462 {
  463         int ret;
  464 
  465         switch (MIDIDEV(i_dev)) {
  466         case MIDI_DEV_MIDIN:
  467                 ret = midi_poll(i_dev, events, td);
  468                 break;
  469         default:
  470                 ret = ENXIO;
  471                 break;
  472         }
  473 
  474         return (ret);
  475 }
  476 
  477 /*
  478  * Followings are the generic methods in midi drivers.
  479  */
  480 
  481 int
  482 midi_open(dev_t i_dev, int flags, int mode, struct thread *td)
  483 {
  484         int dev, unit, ret;
  485         mididev_info *d;
  486 
  487         dev = minor(i_dev);
  488         d = get_mididev_info(i_dev, &unit);
  489 
  490         MIDI_DEBUG(printf("midi_open: unit %d, flags 0x%x.\n", unit, flags));
  491 
  492         if (d == NULL)
  493                 return (ENXIO);
  494 
  495         /* Mark this device busy. */
  496         mtx_lock(&d->flagqueue_mtx);
  497         device_busy(d->dev);
  498         if ((d->flags & MIDI_F_BUSY) != 0) {
  499                 mtx_unlock(&d->flagqueue_mtx);
  500                 printf("midi_open: unit %d is busy.\n", unit);
  501                 return (EBUSY);
  502         }
  503         d->fflags = flags;
  504         d->flags |= MIDI_F_BUSY;
  505         d->flags &= ~(MIDI_F_READING | MIDI_F_WRITING);
  506         if ((d->fflags & O_NONBLOCK) != 0)
  507                 d->flags |= MIDI_F_NBIO;
  508 
  509         /* Init the queue. */
  510         if ((flags & FREAD) != 0)
  511                 midibuf_clear(&d->midi_dbuf_in);
  512         if ((flags & FWRITE) != 0) {
  513                 midibuf_clear(&d->midi_dbuf_out);
  514                 midibuf_clear(&d->midi_dbuf_passthru);
  515         }
  516 
  517         mtx_unlock(&d->flagqueue_mtx);
  518 
  519         if (d->open == NULL)
  520                 ret = 0;
  521         else
  522                 ret = d->open(i_dev, flags, mode, td);
  523 
  524         mtx_lock(&d->flagqueue_mtx);
  525 
  526         /* Begin recording if nonblocking. */
  527         if ((d->flags & (MIDI_F_READING | MIDI_F_NBIO)) == MIDI_F_NBIO && (d->fflags & FREAD) != 0)
  528         d->callback(d, MIDI_CB_START | MIDI_CB_RD);
  529 
  530         mtx_unlock(&d->flagqueue_mtx);
  531 
  532         MIDI_DEBUG(printf("midi_open: opened.\n"));
  533 
  534         return (ret);
  535 }
  536 
  537 int
  538 midi_close(dev_t i_dev, int flags, int mode, struct thread *td)
  539 {
  540         int dev, unit, ret;
  541         mididev_info *d;
  542 
  543         dev = minor(i_dev);
  544         d = get_mididev_info(i_dev, &unit);
  545 
  546         MIDI_DEBUG(printf("midi_close: unit %d.\n", unit));
  547 
  548         if (d == NULL)
  549                 return (ENXIO);
  550 
  551         mtx_lock(&d->flagqueue_mtx);
  552 
  553         /* Stop recording and playing. */
  554         if ((d->flags & MIDI_F_READING) != 0)
  555                 d->callback(d, MIDI_CB_ABORT | MIDI_CB_RD);
  556         if ((d->flags & MIDI_F_WRITING) != 0)
  557                 d->callback(d, MIDI_CB_ABORT | MIDI_CB_WR);
  558 
  559         /* Clear the queues. */
  560         if ((d->fflags & FREAD) != 0)
  561                 midibuf_clear(&d->midi_dbuf_in);
  562         if ((d->fflags & FWRITE) != 0) {
  563                 midibuf_clear(&d->midi_dbuf_out);
  564                 midibuf_clear(&d->midi_dbuf_passthru);
  565         }
  566 
  567         /* Stop playing and unmark this device busy. */
  568         d->flags &= ~MIDI_F_BUSY;
  569         d->fflags = 0;
  570 
  571         device_unbusy(d->dev);
  572 
  573         mtx_unlock(&d->flagqueue_mtx);
  574 
  575         if (d->close == NULL)
  576                 ret = 0;
  577         else
  578                 ret = d->close(i_dev, flags, mode, td);
  579 
  580         MIDI_DEBUG(printf("midi_close: closed.\n"));
  581 
  582         return (ret);
  583 }
  584 
  585 int
  586 midi_read(dev_t i_dev, struct uio * buf, int flag)
  587 {
  588         int dev, unit, len, lenr, ret;
  589         mididev_info *d ;
  590         u_char *uiobuf;
  591 
  592         dev = minor(i_dev);
  593 
  594         d = get_mididev_info(i_dev, &unit);
  595         MIDI_DEBUG(printf("midi_read: unit %d, resid %d.\n", unit, buf->uio_resid));
  596 
  597         if (d == NULL)
  598                 return (ENXIO);
  599 
  600         ret = 0;
  601 
  602         len = buf->uio_resid;
  603         lenr = 0;
  604 
  605         uiobuf = (u_char *)malloc(len, M_DEVBUF, M_WAITOK | M_ZERO);
  606         if (uiobuf == NULL)
  607                 return (ENOMEM);
  608 
  609         mtx_lock(&d->flagqueue_mtx);
  610 
  611         /* Begin recording. */
  612         d->callback(d, MIDI_CB_START | MIDI_CB_RD);
  613 
  614         /* Have we got the data to read? */
  615         if ((d->flags & MIDI_F_NBIO) != 0 && d->midi_dbuf_in.rl == 0)
  616                 ret = EAGAIN;
  617         else {
  618                 if ((d->flags & MIDI_F_NBIO) != 0 && len > d->midi_dbuf_in.rl)
  619                         len = d->midi_dbuf_in.rl;
  620                 ret = midibuf_seqread(&d->midi_dbuf_in, uiobuf, len, &lenr,
  621                                       d->callback, d, MIDI_CB_START | MIDI_CB_RD,
  622                                       &d->flagqueue_mtx);
  623         }
  624 
  625         mtx_unlock(&d->flagqueue_mtx);
  626 
  627         if (lenr > 0)
  628                 ret = uiomove(uiobuf, lenr, buf);
  629 
  630         free(uiobuf, M_DEVBUF);
  631 
  632         MIDI_DEBUG(printf("midi_read: ret %d, resid %d.\n", ret, buf->uio_resid));
  633 
  634         return (ret);
  635 }
  636 
  637 int
  638 midi_write(dev_t i_dev, struct uio * buf, int flag)
  639 {
  640         int dev, unit, len, len2, lenw, ret;
  641         mididev_info *d;
  642         u_char *uiobuf;
  643 
  644         dev = minor(i_dev);
  645         d = get_mididev_info(i_dev, &unit);
  646 
  647         MIDI_DEBUG(printf("midi_write: unit %d.\n", unit));
  648 
  649         if (d == NULL)
  650                 return (ENXIO);
  651 
  652         ret = 0;
  653 
  654         len = buf->uio_resid;
  655         lenw = 0;
  656 
  657         uiobuf = (u_char *)malloc(len, M_DEVBUF, M_WAITOK | M_ZERO);
  658         if (uiobuf == NULL)
  659                 return (ENOMEM);
  660 
  661         ret = uiomove(uiobuf, len, buf);
  662         if (ret != 0) {
  663                 free(uiobuf, M_DEVBUF);
  664                 return (ret);
  665         }
  666 
  667         mtx_lock(&d->flagqueue_mtx);
  668 
  669         /* Have we got the data to write? */
  670         if ((d->flags & MIDI_F_NBIO) != 0 && d->midi_dbuf_out.fl == 0) {
  671                 /* Begin playing. */
  672                 d->callback(d, MIDI_CB_START | MIDI_CB_WR);
  673                 ret = EAGAIN;
  674         } else {
  675                 len2 = len;
  676                 if ((d->flags & MIDI_F_NBIO) != 0 && len2 > d->midi_dbuf_out.fl)
  677                         len2 = d->midi_dbuf_out.fl;
  678                 ret = midibuf_seqwrite(&d->midi_dbuf_out, uiobuf, len2, &lenw,
  679                                        d->callback, d, MIDI_CB_START | MIDI_CB_WR,
  680                                        &d->flagqueue_mtx);
  681         }
  682 
  683         mtx_unlock(&d->flagqueue_mtx);
  684 
  685         free(uiobuf, M_DEVBUF);
  686         buf->uio_resid = len - lenw;
  687 
  688         return (ret);
  689 }
  690 
  691 /*
  692  * generic midi ioctl. Functions of the default driver can be
  693  * overridden by the device-specific ioctl call.
  694  * If a device-specific call returns ENOSYS (Function not implemented),
  695  * the default driver is called. Otherwise, the returned value
  696  * is passed up.
  697  *
  698  * The default handler, for many parameters, sets the value in the
  699  * descriptor, sets MIDI_F_INIT, and calls the callback function with
  700  * reason INIT. If successful, the callback returns 1 and the caller
  701  * can update the parameter.
  702  */
  703 
  704 int
  705 midi_ioctl(dev_t i_dev, u_long cmd, caddr_t arg, int mode, struct thread *td)
  706 {
  707         int ret = ENOSYS, dev, unit;
  708         mididev_info *d;
  709         struct snd_size *sndsize;
  710         snd_sync_parm *sp;
  711 
  712         dev = minor(i_dev);
  713         d = get_mididev_info(i_dev, &unit);
  714 
  715         if (d == NULL)
  716                 return (ENXIO);
  717 
  718         if (d->ioctl)
  719                 ret = d->ioctl(i_dev, cmd, arg, mode, td);
  720         if (ret != ENOSYS)
  721                 return ret;
  722 
  723         /*
  724          * pass control to the default ioctl handler. Set ret to 0 now.
  725          */
  726         ret = 0;
  727 
  728         MIDI_DEBUG(printf("midi_ioctl: unit %d, cmd %s.\n", unit, midi_cmdname(cmd, cmdtab_midiioctl)));
  729 
  730         /*
  731          * all routines are called with int. blocked. Make sure that
  732          * ints are re-enabled when calling slow or blocking functions!
  733          */
  734         switch(cmd) {
  735 
  736                 /*
  737                  * we start with the new ioctl interface.
  738                  */
  739         case AIONWRITE: /* how many bytes can write ? */
  740                 mtx_lock(&d->flagqueue_mtx);
  741                 *(int *)arg = d->midi_dbuf_out.fl;
  742                 mtx_unlock(&d->flagqueue_mtx);
  743                 MIDI_DEBUG(printf("midi_ioctl: fl %d.\n", *(int *)arg));
  744                 break;
  745 
  746         case AIOSSIZE:     /* set the current blocksize */
  747                 sndsize = (struct snd_size *)arg;
  748                 MIDI_DEBUG(printf("midi_ioctl: play %d, rec %d.\n", sndsize->play_size, sndsize->rec_size));
  749                 mtx_lock(&d->flagqueue_mtx);
  750                 if (sndsize->play_size <= d->midi_dbuf_out.unit_size && sndsize->rec_size <= d->midi_dbuf_in.unit_size) {
  751                         d->midi_dbuf_out.blocksize = d->midi_dbuf_out.unit_size;
  752                         d->midi_dbuf_in.blocksize = d->midi_dbuf_in.unit_size;
  753                         sndsize->play_size = d->midi_dbuf_out.blocksize;
  754                         sndsize->rec_size = d->midi_dbuf_in.blocksize;
  755                         d->flags &= ~MIDI_F_HAS_SIZE;
  756                         mtx_unlock(&d->flagqueue_mtx);
  757                 }
  758                 else {
  759                         if (sndsize->play_size > d->midi_dbuf_out.bufsize / 4)
  760                                 sndsize->play_size = d->midi_dbuf_out.bufsize / 4;
  761                         if (sndsize->rec_size > d->midi_dbuf_in.bufsize / 4)
  762                                 sndsize->rec_size = d->midi_dbuf_in.bufsize / 4;
  763                         /* Round up the size to the multiple of EV_SZ. */
  764                         d->midi_dbuf_out.blocksize =
  765                             ((sndsize->play_size + d->midi_dbuf_out.unit_size - 1)
  766                              / d->midi_dbuf_out.unit_size) * d->midi_dbuf_out.unit_size;
  767                         d->midi_dbuf_in.blocksize =
  768                             ((sndsize->rec_size + d->midi_dbuf_in.unit_size - 1)
  769                              / d->midi_dbuf_in.unit_size) * d->midi_dbuf_in.unit_size;
  770                         sndsize->play_size = d->midi_dbuf_out.blocksize;
  771                         sndsize->rec_size = d->midi_dbuf_in.blocksize;
  772                         d->flags |= MIDI_F_HAS_SIZE;
  773                         mtx_unlock(&d->flagqueue_mtx);
  774                 }
  775 
  776                 ret = 0;
  777                 break;
  778 
  779         case AIOGSIZE:  /* get the current blocksize */
  780                 sndsize = (struct snd_size *)arg;
  781                 mtx_lock(&d->flagqueue_mtx);
  782                 sndsize->play_size = d->midi_dbuf_out.blocksize;
  783                 sndsize->rec_size = d->midi_dbuf_in.blocksize;
  784                 mtx_unlock(&d->flagqueue_mtx);
  785                 MIDI_DEBUG(printf("midi_ioctl: play %d, rec %d.\n", sndsize->play_size, sndsize->rec_size));
  786 
  787                 ret = 0;
  788                 break;
  789 
  790         case AIOSTOP:
  791                 mtx_lock(&d->flagqueue_mtx);
  792                 if (*(int *)arg == AIOSYNC_PLAY) /* play */
  793                         *(int *)arg = d->callback(d, MIDI_CB_STOP | MIDI_CB_WR);
  794                 else if (*(int *)arg == AIOSYNC_CAPTURE)
  795                         *(int *)arg = d->callback(d, MIDI_CB_STOP | MIDI_CB_RD);
  796                 else {
  797                         MIDI_DEBUG(printf("midi_ioctl: bad channel 0x%x.\n", *(int *)arg));
  798                         *(int *)arg = 0 ;
  799                 }
  800                 mtx_unlock(&d->flagqueue_mtx);
  801                 break ;
  802 
  803         case AIOSYNC:
  804                 sp = (snd_sync_parm *)arg;
  805                 MIDI_DEBUG(printf("midi_ioctl: unimplemented, chan 0x%03lx pos %lu.\n",
  806                            sp->chan,
  807                            sp->pos));
  808                 break;
  809                 /*
  810                  * here follow the standard ioctls (filio.h etc.)
  811                  */
  812         case FIONREAD: /* get # bytes to read */
  813                 mtx_lock(&d->flagqueue_mtx);
  814                 *(int *)arg = d->midi_dbuf_in.rl;
  815                 mtx_unlock(&d->flagqueue_mtx);
  816                 MIDI_DEBUG(printf("midi_ioctl: rl %d.\n", *(int *)arg));
  817                 break;
  818 
  819         case FIOASYNC: /*set/clear async i/o */
  820                 MIDI_DEBUG(printf("FIOASYNC\n"));
  821                     break;
  822 
  823         case FIONBIO: /* set/clear non-blocking i/o */
  824                 mtx_lock(&d->flagqueue_mtx);
  825                 if (*(int *)arg == 0)
  826                         d->flags &= ~MIDI_F_NBIO ;
  827                 else
  828                         d->flags |= MIDI_F_NBIO ;
  829                 mtx_unlock(&d->flagqueue_mtx);
  830                 MIDI_DEBUG(printf("midi_ioctl: arg %d.\n", *(int *)arg));
  831                 break ;
  832 
  833         case MIOSPASSTHRU: /* set/clear passthru */
  834                 mtx_lock(&d->flagqueue_mtx);
  835                 if (*(int *)arg == 0)
  836                         d->flags &= ~MIDI_F_PASSTHRU ;
  837                 else
  838                         d->flags |= MIDI_F_PASSTHRU ;
  839 
  840                 /* Init the queue. */
  841                 midibuf_clear(&d->midi_dbuf_passthru);
  842 
  843                 mtx_unlock(&d->flagqueue_mtx);
  844                 MIDI_DEBUG(printf("midi_ioctl: passthru %d.\n", *(int *)arg));
  845 
  846                 /* FALLTHROUGH */
  847         case MIOGPASSTHRU: /* get passthru */
  848                 mtx_lock(&d->flagqueue_mtx);
  849                 if ((d->flags & MIDI_F_PASSTHRU) != 0)
  850                         *(int *)arg = 1;
  851                 else
  852                         *(int *)arg = 0;
  853                 mtx_unlock(&d->flagqueue_mtx);
  854                 MIDI_DEBUG(printf("midi_ioctl: passthru %d.\n", *(int *)arg));
  855                 break;
  856 
  857         default:
  858                 MIDI_DEBUG(printf("midi_ioctl: default ioctl midi%d subdev %d fn 0x%08lx fail\n",
  859                                   unit, dev & 0xf, cmd));
  860                 ret = EINVAL;
  861                 break ;
  862         }
  863         return ret ;
  864 }
  865 
  866 int
  867 midi_poll(dev_t i_dev, int events, struct thread *td)
  868 {
  869         int unit, dev, ret, lim;
  870         mididev_info *d;
  871 
  872         dev = minor(i_dev);
  873         d = get_mididev_info(i_dev, &unit);
  874 
  875         MIDI_DEBUG(printf("midi_poll: unit %d.\n", unit));
  876 
  877         if (d == NULL)
  878                 return (ENXIO);
  879 
  880         ret = 0;
  881 
  882         mtx_lock(&d->flagqueue_mtx);
  883 
  884         /* Look up the apropriate queue and select it. */
  885         if ((events & (POLLOUT | POLLWRNORM)) != 0) {
  886                 /* Start playing. */
  887                 d->callback(d, MIDI_CB_START | MIDI_CB_WR);
  888 
  889                 /* Find out the boundary. */
  890                 if ((d->flags & MIDI_F_HAS_SIZE) != 0)
  891                         lim = d->midi_dbuf_out.blocksize;
  892                 else
  893                         lim = d->midi_dbuf_out.unit_size;
  894                 if (d->midi_dbuf_out.fl < lim)
  895                         /* No enough space, record select. */
  896                         selrecord(td, &d->midi_dbuf_out.sel);
  897                 else
  898                         /* We can write now. */
  899                         ret |= events & (POLLOUT | POLLWRNORM);
  900         }
  901         if ((events & (POLLIN | POLLRDNORM)) != 0) {
  902                 /* Start recording. */
  903                 d->callback(d, MIDI_CB_START | MIDI_CB_RD);
  904 
  905                 /* Find out the boundary. */
  906                 if ((d->flags & MIDI_F_HAS_SIZE) != 0)
  907                         lim = d->midi_dbuf_in.blocksize;
  908                 else
  909                         lim = d->midi_dbuf_in.unit_size;
  910                 if (d->midi_dbuf_in.rl < lim)
  911                         /* No data ready, record select. */
  912                         selrecord(td, &d->midi_dbuf_in.sel);
  913                 else
  914                         /* We can write now. */
  915                         ret |= events & (POLLIN | POLLRDNORM);
  916         }
  917 
  918         mtx_unlock(&d->flagqueue_mtx);
  919 
  920         return (ret);
  921 }
  922 
  923 void
  924 midi_intr(mididev_info *d)
  925 {
  926         if (d->intr != NULL)
  927                 d->intr(d->intrarg, d);
  928 }
  929 
  930 /* Flush the output queue. */
  931 #define MIDI_SYNC_TIMEOUT 1
  932 int
  933 midi_sync(mididev_info *d)
  934 {
  935         int i, rl;
  936 
  937         mtx_assert(&d->flagqueue_mtx, MA_OWNED);
  938 
  939         MIDI_DEBUG(printf("midi_sync: unit %d.\n", d->unit));
  940 
  941         while (d->midi_dbuf_out.rl > 0) {
  942                 if ((d->flags & MIDI_F_WRITING) == 0)
  943                         d->callback(d, MIDI_CB_START | MIDI_CB_WR);
  944                 rl = d->midi_dbuf_out.rl;
  945                 i = cv_timedwait_sig(&d->midi_dbuf_out.cv_out,
  946                                      &d->flagqueue_mtx,
  947                                      (d->midi_dbuf_out.bufsize * 10 * hz / 38400)
  948                                      + MIDI_SYNC_TIMEOUT * hz);
  949                 if (i == EINTR || i == ERESTART) {
  950                         if (i == EINTR)
  951                                 d->callback(d, MIDI_CB_STOP | MIDI_CB_WR);
  952                         return (i);
  953                 }
  954                 if (i == EWOULDBLOCK && rl == d->midi_dbuf_out.rl) {
  955                         /* A queue seems to be stuck up. Give up and clear the queue. */
  956                         d->callback(d, MIDI_CB_STOP | MIDI_CB_WR);
  957                         midibuf_clear(&d->midi_dbuf_out);
  958                         return (0);
  959                 }
  960         }
  961 
  962         return 0;
  963 }
  964 
  965 /*
  966  * These handle the status message of the midi drivers.
  967  */
  968 
  969 int
  970 midistat_open(dev_t i_dev, int flags, int mode, struct thread *td)
  971 {
  972         if (midistatbusy)
  973                 return (EBUSY);
  974 
  975         bzero(midistatbuf, sizeof(midistatbuf));
  976         midistatptr = 0;
  977         if (midi_initstatus(midistatbuf, sizeof(midistatbuf) - 1))
  978                 return (ENOMEM);
  979 
  980         midistatbusy = 1;
  981 
  982         return (0);
  983 }
  984 
  985 int
  986 midistat_close(dev_t i_dev, int flags, int mode, struct thread *td)
  987 {
  988         midistatbusy = 0;
  989 
  990         return (0);
  991 }
  992 
  993 int
  994 midistat_read(dev_t i_dev, struct uio * buf, int flag)
  995 {
  996         return midi_readstatus(midistatbuf, &midistatptr, buf);
  997 }
  998 
  999 /*
 1000  * finally, some "libraries"
 1001  */
 1002 
 1003 /* Inits the buffer for /dev/midistat. */
 1004 static int
 1005 midi_initstatus(char *buf, int size)
 1006 {
 1007         int i, p;
 1008         device_t dev;
 1009         mididev_info *md;
 1010 
 1011         p = 0;
 1012         p += snprintf(buf, size, "FreeBSD Midi Driver (newmidi) %s %s\nInstalled devices:\n", __DATE__, __TIME__);
 1013         for (i = 0 ; i < mididev_info_number() ; i++) {
 1014                 md = get_mididev_info_unit(i);
 1015                 if (!MIDICONFED(md))
 1016                         continue;
 1017                 dev = devclass_get_device(midi_devclass, i);
 1018                 if (p < size)
 1019                         p += snprintf(&buf[p], size - p, "midi%d: <%s> %s\n", i, device_get_desc(dev), md->midistat);
 1020                 else
 1021                         return (1);
 1022         }
 1023 
 1024         return (0);
 1025 }
 1026 
 1027 /* Reads the status message. */
 1028 static int
 1029 midi_readstatus(char *buf, int *ptr, struct uio *uio)
 1030 {
 1031         int len;
 1032 
 1033         len = min(uio->uio_resid, strlen(&buf[*ptr]));
 1034         if (len > 0) {
 1035                 uiomove(&buf[*ptr], len, uio);
 1036                 *ptr += len;
 1037         }
 1038 
 1039         return (0);
 1040 }
 1041 
 1042 char
 1043 *midi_cmdname(int cmd, midi_cmdtab *tab)
 1044 {
 1045         while (tab->name != NULL) {
 1046                 if (cmd == tab->cmd)
 1047                         return (tab->name);
 1048                 tab++;
 1049         }
 1050 
 1051         return ("unknown");
 1052 }

Cache object: d087b6dfaff5e637a9bde411a21b7910


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