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/midibuf.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  * Copyright (C) 1999 Seigo Tanimura
    3  * All rights reserved.
    4  *
    5  * Redistribution and use in source and binary forms, with or
    6  * without modification, are permitted provided that the following
    7  * conditions are met:
    8  * 1. Redistributions of source code must retain the above copyright
    9  *    notice, this list of conditions and the following disclaimer.
   10  * 2. Redistributions in binary form must reproduce the above
   11  *    copyright notice, this list of conditions and the following
   12  *    disclaimer in the documentation and/or other materials provided
   13  *    with the distribution.
   14  *
   15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS
   16  * IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
   17  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
   18  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE
   19  * AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
   20  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
   21  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   22  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
   23  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
   24  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
   25  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
   26  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   27  *
   28  * $FreeBSD: releng/5.0/sys/dev/sound/midi/midibuf.c 92252 2002-03-14 01:32:30Z alfred $
   29  *
   30  */
   31 
   32 /*
   33  * This file implements a midi event/message queue. A midi
   34  * event/message queue holds midi events and messages to
   35  * transmit to or received from a midi interface.
   36  */
   37 
   38 #include <dev/sound/midi/midi.h>
   39 
   40 /* Some macros to handle the queue. */
   41 #define DATA_AVAIL(dbuf) ((dbuf)->rl)
   42 #define SPACE_AVAIL(dbuf) ((dbuf)->fl)
   43 
   44 static void queuerawdata(midi_dbuf *dbuf, char *data, int len);
   45 static void dequeuerawdata(midi_dbuf *dbuf, char *data, int len);
   46 static void copyrawdata(midi_dbuf *dbuf, int offset, char *data, int len);
   47 static void deleterawdata(midi_dbuf *dbuf, int len);
   48 
   49 /*
   50  * Here are the functions to interact to the midi device drivers.
   51  * These are called from midi device driver functions under sys/i386/isa/snd.
   52  */
   53 
   54 int
   55 midibuf_init(midi_dbuf *dbuf)
   56 {
   57         if (dbuf->buf == NULL) {
   58                 dbuf->buf = malloc(MIDI_BUFFSIZE, M_DEVBUF, M_WAITOK | M_ZERO);
   59                 cv_init(&dbuf->cv_in, "midi queue in");
   60                 cv_init(&dbuf->cv_out, "midi queue out");
   61         }
   62 
   63         return (midibuf_clear(dbuf));
   64 }
   65 
   66 int
   67 midibuf_destroy(midi_dbuf *dbuf)
   68 {
   69         if (dbuf->buf != NULL) {
   70                 free(dbuf->buf, M_DEVBUF);
   71                 cv_destroy(&dbuf->cv_in);
   72                 cv_destroy(&dbuf->cv_out);
   73         }
   74 
   75         return (0);
   76 }
   77 
   78 int
   79 midibuf_clear(midi_dbuf *dbuf)
   80 {
   81         bzero(dbuf->buf, MIDI_BUFFSIZE);
   82         dbuf->bufsize = MIDI_BUFFSIZE;
   83         dbuf->rp = dbuf->fp = 0;
   84         dbuf->dl = 0;
   85         dbuf->rl = 0;
   86         dbuf->fl = dbuf->bufsize;
   87         dbuf->int_count = 0;
   88         dbuf->chan = 0;
   89         /*dbuf->unit_size = 1;*/ /* The drivers are responsible. */
   90         bzero(&dbuf->sel, sizeof(dbuf->sel));
   91         dbuf->total = 0;
   92         dbuf->prev_total = 0;
   93         dbuf->blocksize = dbuf->bufsize / 4;
   94 
   95         return (0);
   96 }
   97 
   98 /* The sequencer calls this function to queue data. */
   99 int
  100 midibuf_seqwrite(midi_dbuf *dbuf, u_char* data, int len, int *lenw, midi_callback_t *cb, void *d, int reason, struct mtx *m)
  101 {
  102         int i, lwrt;
  103 
  104         if (m != NULL)
  105                 mtx_assert(m, MA_OWNED);
  106 
  107         if (lenw == NULL)
  108                 return (EINVAL);
  109         *lenw = 0;
  110 
  111         /* Is this a real queue? */
  112         if (dbuf == (midi_dbuf *)NULL)
  113                 return (EINVAL);
  114 
  115         /* Write down every single byte. */
  116         while (len > 0) {
  117                 /* Find out the number of bytes to write. */
  118                 lwrt = SPACE_AVAIL(dbuf);
  119                 if (lwrt > len)
  120                         lwrt = len;
  121                 if (lwrt > 0) {
  122                         /* We can write some now. Queue the data. */
  123                         queuerawdata(dbuf, data, lwrt);
  124 
  125                         *lenw += lwrt;
  126                         len -= lwrt;
  127                         data += lwrt;
  128                 }
  129 
  130                 if (cb != NULL)
  131                         (*cb)(d, reason);
  132 
  133                 /* Have we got still more data to write? */
  134                 if (len > 0) {
  135                         /* Sleep until we have enough space. */
  136                         i = cv_wait_sig(&dbuf->cv_out, m);
  137                         if (i == EINTR || i == ERESTART)
  138                                 return (i);
  139                 }
  140         }
  141 
  142         return (0);
  143 }
  144 
  145 int
  146 midibuf_output_intr(midi_dbuf *dbuf, u_char *data, int len, int *leno)
  147 {
  148         if (leno == NULL)
  149                 return (EINVAL);
  150         *leno = 0;
  151 
  152         /* Is this a real queue? */
  153         if (dbuf == (midi_dbuf *)NULL)
  154                 return (EINVAL);
  155 
  156         /* Have we got any data in the queue? */
  157         *leno = DATA_AVAIL(dbuf);
  158         if (*leno == 0)
  159                 return (EAGAIN);
  160 
  161         /* Dequeue the data. */
  162         if (*leno > len)
  163                 *leno = len;
  164         dequeuerawdata(dbuf, data, *leno);
  165 
  166         return (0);
  167 }
  168 
  169 int
  170 midibuf_input_intr(midi_dbuf *dbuf, u_char *data, int len, int *leni)
  171 {
  172         if (leni == NULL)
  173                 return (EINVAL);
  174         *leni = 0;
  175 
  176         /* Is this a real queue? */
  177         if (dbuf == (midi_dbuf *)NULL)
  178                 return (EINVAL);
  179 
  180         /* Have we got any data to write? */
  181         if (len == 0)
  182                 return (0);
  183         /* Can we write now? */
  184         if (SPACE_AVAIL(dbuf) < len)
  185                 return (EAGAIN);
  186 
  187         /* We can write some now. Queue the data. */
  188         queuerawdata(dbuf, data, len);
  189         *leni = len;
  190 
  191         return (0);
  192 }
  193 
  194 /* The sequencer calls this function to dequeue data. */
  195 int
  196 midibuf_seqread(midi_dbuf *dbuf, u_char* data, int len, int *lenr, midi_callback_t *cb, void *d, int reason, struct mtx *m)
  197 {
  198         int i, lrd;
  199 
  200         if (m != NULL)
  201                 mtx_assert(m, MA_OWNED);
  202 
  203         if (lenr == NULL)
  204                 return (EINVAL);
  205         *lenr = 0;
  206 
  207         /* Is this a real queue? */
  208         if (dbuf == (midi_dbuf *)NULL)
  209                 return (EINVAL);
  210 
  211         /* Write down every single byte. */
  212         while (len > 0) {
  213                 if (cb != NULL)
  214                         (*cb)(d, reason);
  215 
  216                 /* Have we got data to read? */
  217                 if ((lrd = DATA_AVAIL(dbuf)) == 0) {
  218                         /* Sleep until we have data ready to read. */
  219                         i = cv_wait_sig(&dbuf->cv_in, m);
  220                         if (i == EINTR || i == ERESTART)
  221                                 return (i);
  222                         /* Find out the number of bytes to read. */
  223                         lrd = DATA_AVAIL(dbuf);
  224                 }
  225 
  226                 if (lrd > len)
  227                         lrd = len;
  228                 if (lrd > 0) {
  229                         /* We can read some data now. Dequeue the data. */
  230                         dequeuerawdata(dbuf, data, lrd);
  231 
  232                         *lenr += lrd;
  233                         len -= lrd;
  234                         data += lrd;
  235                 }
  236         }
  237 
  238         return (0);
  239 }
  240 
  241 /* The sequencer calls this function to copy data without dequeueing. */
  242 int
  243 midibuf_seqcopy(midi_dbuf *dbuf, u_char* data, int len, int *lenc, midi_callback_t *cb, void *d, int reason, struct mtx *m)
  244 {
  245         int i, lrd;
  246 
  247         if (m != NULL)
  248                 mtx_assert(m, MA_OWNED);
  249 
  250         if (lenc == NULL)
  251                 return (EINVAL);
  252         *lenc = 0;
  253 
  254         /* Is this a real queue? */
  255         if (dbuf == (midi_dbuf *)NULL)
  256                 return (EINVAL);
  257 
  258         /* Write down every single byte. */
  259         while (len > 0) {
  260                 if (cb != NULL)
  261                         (*cb)(d, reason);
  262 
  263                 /* Have we got data to read? */
  264                 if ((lrd = DATA_AVAIL(dbuf)) == 0) {
  265                         /* Sleep until we have data ready to read. */
  266                         i = cv_wait_sig(&dbuf->cv_in, m);
  267                         if (i == EINTR || i == ERESTART)
  268                                 return (i);
  269                         /* Find out the number of bytes to read. */
  270                         lrd = DATA_AVAIL(dbuf);
  271                 }
  272 
  273                 if (lrd > len)
  274                         lrd = len;
  275                 if (lrd > 0) {
  276                         /* We can read some data now. Copy the data. */
  277                         copyrawdata(dbuf, *lenc, data, lrd);
  278 
  279                         *lenc += lrd;
  280                         len -= lrd;
  281                         data += lrd;
  282                 }
  283         }
  284 
  285         return (0);
  286 }
  287 
  288 /*
  289  * The sequencer calls this function to delete the data
  290  * that the sequencer has already read.
  291  */
  292 int
  293 midibuf_seqdelete(midi_dbuf *dbuf, int len, int *lenr, midi_callback_t *cb, void *d, int reason, struct mtx *m)
  294 {
  295         int i, lrd;
  296 
  297         if (m != NULL)
  298                 mtx_assert(m, MA_OWNED);
  299 
  300         if (lenr == NULL)
  301                 return (EINVAL);
  302         *lenr = 0;
  303 
  304         /* Is this a real queue? */
  305         if (dbuf == (midi_dbuf *)NULL)
  306                 return (EINVAL);
  307 
  308         /* Write down every single byte. */
  309         while (len > 0) {
  310                 if (cb != NULL)
  311                         (*cb)(d, reason);
  312 
  313                 /* Have we got data to read? */
  314                 if ((lrd = DATA_AVAIL(dbuf)) == 0) {
  315                         /* Sleep until we have data ready to read. */
  316                         i = cv_wait_sig(&dbuf->cv_in, m);
  317                         if (i == EINTR || i == ERESTART)
  318                                 return (i);
  319                         /* Find out the number of bytes to read. */
  320                         lrd = DATA_AVAIL(dbuf);
  321                 }
  322 
  323                 if (lrd > len)
  324                         lrd = len;
  325                 if (lrd > 0) {
  326                         /* We can read some data now. Delete the data. */
  327                         deleterawdata(dbuf, lrd);
  328 
  329                         *lenr += lrd;
  330                         len -= lrd;
  331                 }
  332         }
  333 
  334         return (0);
  335 }
  336 
  337 /*
  338  * The functions below here are the libraries for the above ones.
  339  */
  340 
  341 static void
  342 queuerawdata(midi_dbuf *dbuf, char *data, int len)
  343 {
  344         /* dbuf->fp might wrap around dbuf->bufsize. */
  345         if (dbuf->bufsize - dbuf->fp < len) {
  346                 /* The new data wraps, copy them twice. */
  347                 bcopy(data, dbuf->buf + dbuf->fp, dbuf->bufsize - dbuf->fp);
  348                 bcopy(data + dbuf->bufsize - dbuf->fp, dbuf->buf, len - (dbuf->bufsize - dbuf->fp));
  349         } else
  350                 /* The new data do not wrap, once is enough. */
  351                 bcopy(data, dbuf->buf + dbuf->fp, len);
  352 
  353         /* Adjust the pointer and the length counters. */
  354         dbuf->fp = (dbuf->fp + len) % dbuf->bufsize;
  355         dbuf->fl -= len;
  356         dbuf->rl += len;
  357 
  358         /* Wake up the processes sleeping on input data. */
  359         cv_broadcast(&dbuf->cv_in);
  360         if (SEL_WAITING(&dbuf->sel) && dbuf->rl >= dbuf->blocksize)
  361                 selwakeup(&dbuf->sel);
  362 }
  363 
  364 static void
  365 dequeuerawdata(midi_dbuf *dbuf, char *data, int len)
  366 {
  367         /* Copy the data. */
  368         copyrawdata(dbuf, 0, data, len);
  369 
  370         /* Delete the data. */
  371         deleterawdata(dbuf, len);
  372 }
  373 
  374 static void
  375 copyrawdata(midi_dbuf *dbuf, int offset, char *data, int len)
  376 {
  377         int rp;
  378 
  379         rp = (dbuf->rp + offset) % dbuf->bufsize;
  380 
  381         /* dbuf->rp might wrap around dbuf->bufsize. */
  382         if (dbuf->bufsize - rp < len) {
  383                 /* The data to be read wraps, copy them twice. */
  384                 bcopy(dbuf->buf + rp, data, dbuf->bufsize - rp);
  385                 bcopy(dbuf->buf, data + dbuf->bufsize - rp, len - (dbuf->bufsize - rp));
  386         } else
  387                 /* The new data do not wrap, once is enough. */
  388                 bcopy(dbuf->buf + rp, data, len);
  389 }
  390 
  391 static void
  392 deleterawdata(midi_dbuf *dbuf, int len)
  393 {
  394         /* Adjust the pointer and the length counters. */
  395         dbuf->rp = (dbuf->rp + len) % dbuf->bufsize;
  396         dbuf->rl -= len;
  397         dbuf->fl += len;
  398 
  399         /* Wake up the processes sleeping on queueing. */
  400         cv_broadcast(&dbuf->cv_out);
  401         if (SEL_WAITING(&dbuf->sel) && dbuf->fl >= dbuf->blocksize)
  402                 selwakeup(&dbuf->sel);
  403 }

Cache object: 3d25eb101d239ba91254b08e092a92b8


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