home *** CD-ROM | disk | FTP | other *** search
/ ftp.ee.lbl.gov / 2014.05.ftp.ee.lbl.gov.tar / ftp.ee.lbl.gov / bmd-1.0beta.tar.Z / bmd-1.0beta.tar / bmd-1.0beta / sundev / bmd.c next >
C/C++ Source or Header  |  1991-08-27  |  23KB  |  1,166 lines

  1. /*
  2.  * Copyright (c) 1990,1991 Regents of the University of California.
  3.  * All rights reserved.
  4.  *
  5.  * Redistribution and use in source and binary forms are permitted
  6.  * provided that the above copyright notice and this paragraph are
  7.  * duplicated in all such forms and that any documentation,
  8.  * advertising materials, and other materials related to such
  9.  * distribution and use acknowledge that the software was developed
  10.  * by the University of California, Lawrence Berkeley Laboratory,
  11.  * Berkeley, CA.  The name of the University may not be used to
  12.  * endorse or promote products derived from this software without
  13.  * specific prior written permission.
  14.  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
  15.  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
  16.  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  17.  */
  18. #include "bmd.h"
  19. #if NBMD > 0
  20. #ifndef lint
  21. static char rcsid[] =
  22.     "@(#) $Header: bmd.c,v 1.10 91/08/27 00:36:27 mccanne Exp $";
  23. #endif
  24.  
  25. #include <sys/types.h>
  26. #include <sys/errno.h>
  27. #include <sys/fcntl.h>
  28. #include <sys/uio.h>
  29. #include <sys/ioctl.h>
  30. #include <sys/param.h>
  31. #include <sys/systm.h>
  32. #include <sys/time.h>
  33. #include <sys/kernel.h>
  34. #include <sys/signal.h>
  35. #include <sys/user.h>
  36. #include <sys/acct.h>
  37. #include <sys/proc.h>
  38.  
  39. #include <sundev/midi.h>
  40. #include <sundev/bmdvar.h>
  41.  
  42. #include <machine/midiclock.h>
  43. #include <machine/intreg.h>
  44.  
  45. #ifndef NBMDFILES
  46. #define NBMDFILES 4
  47. #endif
  48.  
  49. #define NMDQ 512
  50. #define BMD_MAXNBUF    128
  51. #define BMD_MAXRBUF    (BMD_MAXNBUF+8)
  52. #define BMD_WHI        64
  53. #define BMD_WLO        16
  54.  
  55. struct mdq *mdqalloc();
  56. void mdqfreeq();
  57. void mdqfree();
  58. void mdqinit();
  59.  
  60. /*
  61.  * An interface structure for each hardware port.
  62.  */
  63. #define NPORTS 2
  64. struct midi_softc midi_softc[NPORTS];
  65. struct midid midid[NBMDFILES];
  66.  
  67. static struct midid *midisoft;
  68.  
  69. /*
  70.  * Forward declarations for the interrupt handlers.
  71.  */
  72. int midioutput();
  73. void midiinput();
  74.  
  75. /*
  76.  * The length of fixed length midi messages.
  77.  * Also, an input code for the dfa.  There are five classes:
  78.  *
  79.  *    (0) data
  80.  *    (1) one byte msgs
  81.  *    (2) two byte msgs
  82.  *    (3) three byte msgs
  83.  *    (4) sysexs
  84.  */
  85. u_char midi_msglen[] = {
  86.     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  87.     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  88.     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  89.     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  90.     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  91.     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  92.     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  93.     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  94.     3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, /* 0x80 */
  95.     3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, /* 0x90 */
  96.     3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, /* 0xa0 */
  97.     3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, /* 0xb0 */
  98.     2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, /* 0xc0 */
  99.     2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, /* 0xd0 */
  100.     3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, /* 0xe0 */
  101.     0xff, 1, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0xf0 */
  102. };
  103.  
  104. int bmdsoftintr();
  105. static void bmdwakeup();
  106. static int bmdsleep();
  107.  
  108. void
  109. bmdattach(unit)
  110.     int unit;
  111. {
  112.     register int i;
  113.     register struct midi_softc *sc;
  114.  
  115.     if (unit >= NBMD) {
  116.         printf("bmdattach: unit %d ignored\n", unit);
  117.         return;
  118.     }
  119.     printf("bmd%d: attached\n", unit);
  120.     sc = &midi_softc[unit];
  121.     bzero((char *)sc, sizeof(*sc));
  122.     sc->sc_p = &sc->sc_sp;
  123.     sc->sc_f = &sc->sc_sf;
  124.     sc->sc_unit = unit;
  125.     /*
  126.      * Return if not first time.
  127.      * Rest of initialization is one time only.
  128.      */
  129.     if (unit > 0)
  130.         return;
  131.  
  132.     /*
  133.      * Initialize free list.
  134.      */
  135.     mdqinit();
  136.  
  137.     /*
  138.      * Mark all descriptors free.
  139.      */
  140.     for (i = 0; i < NBMDFILES; ++i) {
  141.         midid[i].md_nxtr = &midid[i];
  142.         midid[i].md_nxtw = &midid[i];
  143.     }
  144.     addintr(4, bmdsoftintr, "bmd", 0);
  145. }
  146.  
  147. static int
  148. port_attach(md, port)
  149.     struct midid *md;
  150.     int port;
  151. {
  152.     int s;
  153.     register struct midi_softc *sc;
  154.     extern void *msl_init();
  155.  
  156.     if ((unsigned)port >= NPORTS)
  157.         return EINVAL;
  158.  
  159.     sc = &midi_softc[port];
  160.     s = splmidi();
  161.     if (md->md_flag & FWRITE) {
  162.         md->md_nxtw = sc->sc_writers;
  163.         sc->sc_writers = md;
  164.     }
  165.     md->md_sc = sc;
  166.     if (md->md_flag & FREAD) {
  167.         md->md_nxtr = sc->sc_readers;
  168.         sc->sc_readers = md;
  169.     }
  170.     if (sc->sc_refcnt++ == 0) {
  171.         splx(s);
  172.         sc->sc_msl = msl_init(port, (caddr_t)sc);
  173.         sc->sc_clkrate = midiclk_start();
  174.         sc->sc_stat = -1;
  175.     } else
  176.         splx(s);
  177.  
  178.     md->md_tz = midiclk.mt_now;
  179.  
  180.     return 0;
  181. }
  182.  
  183. /*
  184.  * Open a midi file.
  185.  */
  186. int
  187. bmdopen(dev, flag)
  188.     dev_t dev;
  189.     int flag;
  190. {
  191.     register int unit;
  192.     register struct midid *md;
  193.  
  194.     unit = minor(dev);
  195.     if ((unsigned)unit >= NBMDFILES)
  196.         return ENXIO;
  197.     md = &midid[unit];
  198.     if (md->md_nxtr != md)
  199.         return EBUSY;
  200.     bzero((char *)md, sizeof *md);
  201.     md->md_flag = flag;
  202.     md->md_filter = BMD_FILTER;
  203.     md->md_nxti = md;
  204.     md->md_wlo = BMD_WLO;
  205.     md->md_nbuf = 1;
  206.  
  207.     return 0;
  208. }
  209.  
  210.  
  211. static void
  212. bmdrmr(p, md)
  213.     register struct midid **p, *md;
  214. {
  215.     for (; *p != md; p = &(*p)->md_nxtr)
  216.         if (*p == 0)
  217.             panic("bmdrmr");
  218.     *p = (*p)->md_nxtr;
  219. }
  220.  
  221. static void
  222. bmdrmw(p, md)
  223.     register struct midid **p, *md;
  224. {
  225.     for (; *p != md; p = &(*p)->md_nxtw)
  226.         if (*p == 0)
  227.             panic("bmdrmw");
  228.     *p = (*p)->md_nxtw;
  229. }
  230.  
  231. static void
  232. bmdrmi(p, md)
  233.     register struct midid **p, *md;
  234. {
  235.     for (; *p != md; p = &(*p)->md_nxti)
  236.         if (*p == 0)
  237.             panic("bmdrmr");
  238.     *p = (*p)->md_nxti;
  239. }
  240.  
  241. /*
  242.  * Close a midi file.
  243.  */
  244. /* ARGSUSED */
  245. bmdclose(dev, flag)
  246.     dev_t dev;
  247.     int flag;
  248. {
  249.     register struct midi_softc *sc;
  250.     register struct midid *md;
  251.     register int s, drain = 0;
  252.     register int unit = minor(dev);
  253.  
  254.     md = &midid[unit];
  255.     sc = md->md_sc;
  256.     if (sc == 0)
  257.         goto out;
  258.  
  259.     s = splmidi();
  260.     if (md->md_flag & FREAD) {
  261.         mdqfreeq(md->md_rh, md->md_rt);
  262.         bmdrmr(&sc->sc_readers, md);
  263.     }
  264.     if (md->md_flag & FWRITE) {
  265.         /* 
  266.          * Block until output drained.  Delay wakeup until all
  267.          * output is gone by setting wlo to 0.  But block only if
  268.          * we're not:
  269.          *  1. in non-blocking mode, or
  270.          *  2. paused.
  271.          *
  272.          * We set drain to true if we want to additionally wait
  273.          * for the serial driver to drain.
  274.          */
  275.         md->md_wlo = 0;
  276.         if (!(md->md_nbio || midiclk.mt_pause)) {
  277.             drain = 1;
  278.             while (md->md_wcnt > 0)
  279.                 if (bmdsleep(&md->md_wchan)) {
  280.                     drain = 0;
  281.                     break;
  282.                 }
  283.         }
  284.         if (md->md_wh != 0)
  285.             mdqfreeq(md->md_wh, md->md_wt->mq_tail);
  286.         bmdrmw(&sc->sc_writers, md);
  287.     }
  288.     if (md->md_nxti != md) {
  289.         bmdrmi(&midisoft, md);
  290.         md->md_nxti = md;
  291.     }
  292.  
  293.     /*
  294.      * Deallocate clock and serial line resources.
  295.      */
  296.     if (--sc->sc_refcnt <= 0) {
  297.         midiclk_stop();
  298.         msl_disconnect(sc->sc_msl, drain);
  299.     }
  300.     splx(s);
  301.     /*
  302.      * Mark descriptor free.
  303.      */
  304.  out:
  305.     md->md_nxtr = md;
  306. }
  307.             
  308. /*
  309.  * Read data from the midi interface.  If in non-blocking mode, return
  310.  * if no data is available.  If in immediate mode, block until next byte
  311.  * arrives.  (XXX Maybe we should block until next midi *message* arrives.)
  312.  * Otherwise, block until data arrives.
  313.  */
  314. bmdread(dev, uio)
  315.     dev_t dev;
  316.     register struct uio *uio;
  317. {
  318.     register int s, error, len;
  319.     register struct midid *md = &midid[minor(dev)];
  320.     register struct midi_softc *sc = md->md_sc;
  321.     register struct mdq *q;
  322.     
  323.     if (sc == 0)
  324.         return EIO;
  325.  
  326.     s = splmidi();
  327.     /*
  328.      * Block until data arrives, if not already present.
  329.      */
  330.     while (md->md_rcnt < md->md_nbuf) {
  331.         if (md->md_nbio) {
  332.             /* non-blocking */
  333.             splx(s);
  334.             return 0;
  335.         }
  336.         if (bmdsleep(&md->md_rchan)) {
  337.             splx(s);
  338.             return EINTR;
  339.         }
  340.     }
  341.     error = 0;
  342.     while ((q = md->md_rh) != 0) {
  343.         len = q->mq_len + sizeof(q->mq_time);
  344.         len = BMDALIGN(len);
  345.         if (len > uio->uio_resid)
  346.             break;
  347.         md->md_rh = q->mq_next;
  348.         if (md->md_rh == 0)
  349.             md->md_rt = 0;
  350.         --md->md_rcnt;
  351.         q->mq_time -= md->md_tz;
  352.         splx(s);
  353.         error = uiomove((caddr_t)&q->mq_time, len, UIO_READ, uio);
  354.         s = splmidi();
  355.         mdqfree(q);
  356.         if (error != 0)
  357.             break;
  358.     }
  359.     if (md->md_sigioproc != 0) 
  360.         md->md_sigio.want = 1;
  361.  
  362.     splx(s);
  363.     return error;
  364. }
  365.  
  366. /*
  367.  * Read a sysex from uio into q and set q's length.
  368.  */
  369. static int
  370. bmdsysex(q, uio)
  371.     struct mdq *q;
  372.     struct uio *uio;
  373. {
  374.     register u_char *cp = q->mq_data, *ep;
  375.     register int n, error;
  376.  
  377.     cp = &q->mq_data[4];
  378.     ep = &cp[sizeof(q->mq_data) - 8];
  379.  
  380.     while (cp <= ep) {
  381.         if (uio->uio_resid < 8)
  382.             return EINVAL;
  383.         error = uiomove(cp, 8, UIO_WRITE, uio);
  384.         if (error != 0)
  385.             return error;
  386.         n = 8;
  387.         while (--n >= 0)
  388.             if (*cp++ == 0xf7) {
  389.                 q->mq_len = cp - q->mq_data;
  390.                 return 0;
  391.             }
  392.     }
  393.     return EINVAL;
  394. }
  395.  
  396. static struct mdq *
  397. mdqwrite(uio, errp)
  398.     register struct uio *uio;
  399.     register int *errp;
  400. {
  401.     register int error, s;
  402.     register struct mdq *q;
  403.  
  404.     s = splmidi();
  405.     q = mdqalloc();
  406.     splx(s);
  407.     if (q == 0) {
  408.         *errp = ENOBUFS;
  409.         return 0;
  410.     }
  411.     error = uiomove((caddr_t)&q->mq_time, 8, UIO_WRITE, uio);
  412.     if (error)
  413.         goto bad;
  414.  
  415.     if (q->mq_data[0] == 0xf0 && (error = bmdsysex(q, uio)) != 0)
  416.         goto bad;
  417.     else
  418.         q->mq_len = midi_msglen[q->mq_data[0]];
  419.  
  420.     q->mq_cp = q->mq_data;
  421.     q->mq_qlen = 1;
  422.     return q;
  423.  bad:
  424.     s = splmidi();
  425.     mdqfree(q);
  426.     splx(s);
  427.     *errp = error;
  428.     return 0;
  429. }
  430.  
  431.  
  432. static void
  433. mdqmerge(md, head, tail)
  434.     register struct midid *md;
  435.     register struct mdq *head;
  436.     register struct mdq *tail;
  437. {
  438.     register struct mdq **p, *n, *hh, *tt;
  439.  
  440.     for (p = &md->md_wh; head != 0; head = n) {
  441.         while (*p != 0 && head->mq_time > (*p)->mq_time)
  442.             p = &(*p)->mq_tail->mq_next;
  443.         hh = *p;
  444.         if (hh == 0) {
  445.             *p = head;
  446.             md->md_wt = tail;
  447.             return;
  448.         }
  449.         n = head->mq_tail->mq_next;
  450.         if (head->mq_time == hh->mq_time) {
  451.             tt = hh->mq_tail;
  452.             hh->mq_qlen += head->mq_qlen;
  453.             head->mq_tail->mq_next = tt->mq_next;
  454.             tt->mq_next = head;
  455.             hh->mq_tail = head->mq_tail;
  456.         } else {
  457.             head->mq_tail->mq_next = hh;
  458.             *p = head;
  459.         }
  460.     }
  461.     if (tail->mq_time > md->md_wt->mq_time)
  462.         md->md_wt = tail;
  463. }
  464.  
  465. /*
  466.  * Write to a midi file.
  467.  */
  468. bmdwrite(dev, uio)
  469.     dev_t dev;
  470.     register struct uio *uio;
  471. {
  472.     register struct midid *md = &midid[minor(dev)];
  473.     register struct midi_softc *sc = md->md_sc;
  474.     register struct mdq *head, *tail, *q, *wt;
  475.     register int s, n;
  476.     int error;
  477.  
  478.     if (sc == 0)
  479.         return EIO;
  480.  
  481.     if (uio->uio_resid == 0)
  482.         return 0;
  483.  
  484.     /*
  485.      * Build a list of mdqs (we assume timestamps are ordered in
  486.      * a given write call).  If time of first mdq is later than oldest
  487.      * mdq already buffered (common case), splice list onto end.
  488.      * Otherwise, merge the two lists.  Update the work time
  489.      * if necessary.
  490.      */
  491.     tail = 0;
  492.     n = 0;
  493.     error = 0;
  494.     while (uio->uio_resid >= sizeof(struct midi_msg)) {
  495.         s = splmidi();
  496.         if (md->md_wcnt >= BMD_WHI) {
  497.             if (md->md_nbio) {
  498.                 splx(s);                
  499.                 break;
  500.             }
  501.             while (md->md_wcnt > md->md_wlo) {
  502.                 if (bmdsleep(&md->md_wchan)) {
  503.                     splx(s);
  504.                     error = EINTR;
  505.                     goto out;
  506.                 }
  507.             }
  508.         }
  509.         splx(s);
  510.         q = mdqwrite(uio, &error);
  511.         if (q == 0)
  512.             break;
  513.         q->mq_time += md->md_tz;
  514.         if (tail == 0) {
  515.             head = tail = q;
  516.             tail->mq_tail = tail;
  517.             continue;
  518.         }
  519.         tail->mq_tail->mq_next = q;
  520.         if (q->mq_time == tail->mq_time) {
  521.             ++tail->mq_qlen;
  522.             tail->mq_tail = q;
  523.         } else {
  524.             n += tail->mq_qlen;
  525.             tail = q;
  526.             q->mq_tail = q;
  527.         }
  528.     }
  529.  out:
  530.     if (tail == 0)
  531.         return error;
  532.  
  533.     n += tail->mq_qlen;
  534.     s = splmidi();
  535.     md->md_wcnt += n;
  536.     tail->mq_tail->mq_next = 0;
  537.     wt = md->md_wt;
  538.     if (wt == 0) {
  539.         md->md_wh = head;
  540.         md->md_wt = tail;
  541.         if (BMD_TLT(head->mq_time, midiclk.mt_work))
  542.             midiclk.mt_work = head->mq_time;
  543.     } else if (BMD_TGT(head->mq_time, wt->mq_time)) {
  544.         wt->mq_tail->mq_next = head;
  545.         md->md_wt = tail;
  546.     } else if (head->mq_time == wt->mq_time) {
  547.         wt->mq_tail->mq_next = head;
  548.         wt->mq_qlen += head->mq_qlen;
  549.         wt->mq_tail = head->mq_tail;
  550.         if (tail != head)
  551.             md->md_wt = tail;
  552.     } else {
  553.         /* XXX this shouldn't be done at splmidi */
  554.         mdqmerge(md, head, tail);
  555.         head = md->md_wh;
  556.         if (BMD_TLT(head->mq_time, midiclk.mt_work))
  557.             midiclk.mt_work = head->mq_time;
  558.     }
  559.     splx(s);
  560.  
  561.     return 0;
  562. }
  563.  
  564. /*
  565.  * Select support.
  566.  */
  567. int
  568. bmdselect(dev, flag)
  569.     register dev_t dev;
  570.     int flag;
  571. {
  572.     struct midid *md = &midid[minor(dev)];
  573.     register struct proc *p;
  574.     register int s;
  575.     
  576.     if (md->md_sc == 0)
  577.         return EIO;
  578.  
  579.     if (flag == FREAD) {
  580.         if (md->md_rcnt >= md->md_nbuf)
  581.             /* Data ready. */
  582.             return 1;
  583.         /*
  584.          * No data ready.  If there's already a select() waiting on 
  585.          * this minor device then this is a collision.  This shouldn't
  586.          * happen because minors really should not be shared, but if 
  587.          * a process forks while one of these is open, it is possible 
  588.          * that both processes could select on the same descriptor.
  589.          */
  590.         s = splmidi();
  591.         p = (struct proc *)md->md_rsel.want;
  592.         if (p != 0 && p->p_wchan == (caddr_t)&selwait)
  593.             md->md_rcol = 1;
  594.         else
  595.             md->md_rsel.want = (int)u.u_procp;
  596.         splx(s);
  597.     } else {
  598.         if (md->md_wcnt < BMD_WHI)
  599.             return 1;
  600.         s = splmidi();
  601.         p = (struct proc *)md->md_wsel.want;
  602.         if (p != 0 && p->p_wchan == (caddr_t)&selwait)
  603.             md->md_wcol = 1;
  604.         else
  605.             md->md_wsel.want = (int)u.u_procp;
  606.         splx(s);
  607.     }
  608.     return 0;
  609. }
  610.  
  611. /*
  612.  * Flush the input buffer of md.  
  613.  */
  614. bmd_iflush(md)
  615.     struct midid *md;
  616. {
  617.     int s = splmidi();
  618.     struct mdq *q = md->md_rh;
  619.  
  620.     if (q != 0) {
  621.         mdqfreeq(q, md->md_rt);
  622.         md->md_rh = 0;
  623.         md->md_rt = 0;
  624.         md->md_rcnt = 0;
  625.     }
  626.     splx(s);
  627. }
  628.  
  629. /*
  630.  * Flush the output buffer of the interface that md is listening on.
  631.  * Called at "low" ipl.
  632.  */
  633. bmd_oflush(md)
  634.     struct midid *md;
  635. {
  636.     register struct mdq *q, *n;
  637.     register int s;
  638.     
  639.     s = splmidi();
  640.     q = md->md_wh;
  641.     md->md_wh = 0;
  642.     md->md_wt = 0;
  643.     md->md_wcnt = 0;
  644.     splx(s);
  645.     while (q != 0) {
  646.         s = splmidi();
  647.         n = q->mq_next;
  648.         mdqfree(q);
  649.         splx(s);
  650.         q = n;
  651.     }
  652.     /* msl_flush() */
  653. }
  654.  
  655. int
  656. bmd_rate(sc, newrate)
  657.     register struct midi_softc *sc;
  658.     register u_int newrate;
  659. {
  660.     register int s;
  661.     /*
  662.      * Only allow rates from 320us (max midi rate) to 1s.
  663.      */
  664.     if (newrate < 320 || newrate > 1000000)
  665.         return EINVAL;
  666.     s = splmidi();
  667.     sc->sc_clkrate = newrate;
  668.     midiclk_setrate(newrate);
  669.     splx(s);
  670.  
  671.     return 0;
  672. }
  673.     
  674. /*
  675.  * Process a midi ioctl.
  676.  */
  677. /* ARGSUSED */
  678. bmdioctl(dev, cmd, addr, flag)
  679.     dev_t dev;
  680.     int cmd;
  681.     caddr_t addr;
  682.     int flag;
  683. {
  684.     int error;
  685.     struct midid *md = &midid[minor(dev)];
  686.  
  687.     if (cmd == BMDATTACH)
  688.         return port_attach(md, *(u_int *)addr);
  689.  
  690.     if (md->md_sc == 0) 
  691.         return EINVAL;
  692.  
  693.     error = 0;
  694.     switch (cmd) {
  695.  
  696.     case FIONREAD:
  697.         *(int *)addr = md->md_rcnt;
  698.         break;
  699.  
  700.     case FIONBIO:
  701.         md->md_nbio = (*(int *)addr != 0) ? 1 : 0;
  702.         break;
  703.  
  704.     case FIOASYNC:
  705.         if (*(int *)addr != 0) {
  706.             if (md->md_sigioproc == 0) {
  707.                 md->md_sigioproc = u.u_procp;
  708.                 md->md_sigio.want = 1;
  709.             } else
  710.                 error = EINVAL;
  711.         } else {
  712.             md->md_sigioproc = 0;
  713.             md->md_sigio.want = 0;
  714.         }
  715.         break;
  716.  
  717.     case BMDGTIME:
  718.         *(u_long *)addr = midiclk.mt_now - md->md_tz;
  719.         break;
  720.  
  721.     case BMDSTIME:
  722.         midiclk_pause();
  723.         md->md_tz = midiclk.mt_now - *(u_long *)addr;
  724.         if (md->md_flag & FREAD)
  725.             bmd_iflush(md);
  726.         if (md->md_flag & FWRITE)
  727.             bmd_oflush(md);
  728.         midiclk_resume();
  729.         break;
  730.  
  731.     case BMDFLUSH:
  732.         if (md->md_flag & FREAD)
  733.             bmd_iflush(md);
  734.         if (md->md_flag & FWRITE)
  735.             bmd_oflush(md);
  736.         break;
  737.  
  738.     case BMDRATE:
  739.         if (*(u_int *)addr == 0)
  740.             *(u_int *)addr = md->md_sc->sc_clkrate;
  741.         else
  742.             error = bmd_rate(md->md_sc, *(u_int *)addr);
  743.         break;
  744.  
  745.     case BMDFILTER:
  746.         md->md_filter = *(u_long *)addr;
  747.         bmd_iflush(md);
  748.         break;
  749.  
  750.     case BMDPAUSE:
  751.         if (!md->md_pause) {
  752.             md->md_pause = 1;
  753.             midiclk_pause();
  754.         } else
  755.             error = EINVAL;
  756.         break;
  757.  
  758.     case BMDRESUME:
  759.         if (md->md_pause) {
  760.             md->md_pause = 0;
  761.             midiclk_resume();
  762.         } else
  763.             error = EINVAL;
  764.         break;
  765.  
  766.     case BMDNWRITE:
  767.         *(int *)addr = BMD_WHI - md->md_wcnt;
  768.         break;
  769.         
  770.     case BMDECHO:
  771.         if (*(u_int *)addr & 0xf > 15)
  772.             md->md_echo = 0;
  773.         else {
  774.             md->md_echan = *(u_int *)addr & 0xf;
  775.             md->md_echo = 1;
  776.         }
  777.         break;
  778.  
  779.     case BMDNBUF:
  780.         if (*(u_int *)addr > BMD_MAXNBUF)
  781.             *(u_int *)addr = BMD_MAXNBUF;
  782.         md->md_nbuf = *(u_int *)addr;
  783.         break;
  784.  
  785.     case BMDWLO:
  786.         if (*(u_int *)addr < BMD_WLO)
  787.             *(u_int *)addr = BMD_WLO;
  788.         else if (*(u_int *)addr > BMD_WHI / 2)
  789.             *(u_int *)addr = BMD_WHI / 2;
  790.         md->md_wlo = *(u_int *)addr;
  791.         break;
  792.  
  793.     default:
  794.         error = EINVAL;
  795.         break;
  796.     }
  797.     return error;
  798. }
  799.  
  800. static struct mdq *
  801. mdqcopy(q)
  802.     register struct mdq *q;
  803. {
  804.     register struct mdq *p;
  805.  
  806.     p = mdqalloc();
  807.     if (p != 0) {
  808.         p->mq_time = q->mq_time;
  809.         p->mq_len = q->mq_len;
  810.         bcopy((char *)q->mq_data, (char *)p->mq_data, p->mq_len);
  811.     }
  812.     return p;
  813. }
  814.  
  815. static void
  816. bmd_echo(sc, q, chan)
  817.     register struct midi_softc *sc;
  818.     register struct mdq *q;
  819.     register int chan;
  820. {
  821.     register struct mdq *p;
  822.  
  823.     if (q->mq_data[0] >= 0xf0)
  824.         return;
  825.  
  826.     p = mdqcopy(q);
  827.     if (p == 0)
  828.         return;
  829.     p->mq_data[0] = (p->mq_data[0] & 0xf0) | chan;
  830.     /*
  831.      * Put straight onto pending queue.
  832.      */
  833.     p->mq_cp = p->mq_data;
  834.     msl_output(sc->sc_msl, p, p);
  835. }
  836.  
  837. static int
  838. bmdfilter(filter, c)
  839.     int filter;
  840.     int c;
  841. {
  842.     if (filter & (1 << (c >> 4))) {
  843.         if ((c & 0xf0) != 0xf0)
  844.             return 1;
  845.         return (filter & (0x10000 << (c & 0xf)));
  846.     }
  847.     return 0;
  848. }
  849.  
  850. /*
  851.  * This doesn't quite work.  We rely on eox to terminate sysex.
  852.  */
  853. static struct mdq *
  854. bmdparse(sc, c)
  855.     register struct midi_softc *sc;
  856.     register int c;
  857. {
  858.     register int s;
  859.     register struct mdq *p;
  860.     register struct mdq *f;
  861.  
  862.     /*
  863.      * Use the f buffer for real time bytes, which don't
  864.      * affect any aspect of the stream.
  865.      */
  866.     if (c >= 0xf8) {
  867.         p = sc->sc_f;
  868.         p->mq_data[0] = c;
  869.         p->mq_len = 1;
  870.         p->mq_time = midiclk.mt_now;
  871.  
  872.         return p;
  873.     }
  874.     p = sc->sc_p;
  875.     if (c < 0x80) {
  876.         /*
  877.          * A data byte.  If we don't have a running status,
  878.          * ignore the byte.  If we need to timestamp the
  879.          * arriving byte, do it.
  880.          */
  881.         s = sc->sc_stat;
  882.         if (s < 0)
  883.             return 0;
  884.         else if (s > 0) {
  885.             p->mq_time = midiclk.mt_now;
  886.             p->mq_data[0] = s;
  887.             p->mq_len = 1;
  888.             sc->sc_stat = 0;
  889.         } else
  890.             s = p->mq_data[0];
  891.  
  892.         if (p->mq_len < sizeof(p->mq_data)) {
  893.             p->mq_data[p->mq_len++] = c;
  894.             if (p->mq_len >= midi_msglen[s]) {
  895.                 sc->sc_stat = s;
  896.                 return p;
  897.             }
  898.         }
  899.         return 0;
  900.     } else if (c == 0xf7) {
  901.         sc->sc_stat = -1;
  902.         if (p->mq_data[0] != 0xf0)
  903.             return 0;
  904.         if (p->mq_len < sizeof(p->mq_data))
  905.             p->mq_data[p->mq_len++] = c;
  906.         return p;
  907.     } else if (p->mq_data[0] == 0xf0 && sc->sc_stat == 0) {
  908.         /*
  909.          * Terminating a sysex with a status byte.
  910.          * Terminate the sysex (if room allows), and set
  911.          * up the next command.  If we are terminating
  912.          * with a one byte status message, it is dropped.
  913.          */
  914.         if (p->mq_len < sizeof(p->mq_data))
  915.             p->mq_data[p->mq_len++] = 0xf7;
  916.  
  917.         f = sc->sc_f;
  918.         sc->sc_f = p;
  919.         sc->sc_p = f;
  920.  
  921.         f->mq_time = midiclk.mt_now;
  922.         f->mq_data[0] = c;
  923.         f->mq_len = 1;
  924.         sc->sc_stat = 0;
  925.  
  926.         return p;
  927.     } else {
  928.         p->mq_time = midiclk.mt_now;
  929.         p->mq_data[0] = c;
  930.         p->mq_len = 1;
  931.         sc->sc_stat = 0;
  932.  
  933.         return (midi_msglen[c] == 1) ? p : 0;
  934.     }
  935.     /* NOTREACHED */
  936. }
  937.  
  938. /*
  939.  * Process byte received by serial driver.
  940.  * Called at splmidi.
  941.  */
  942. void
  943. bmdinput(csc, c)
  944.     caddr_t csc;
  945.     register int c;
  946. {
  947.     register struct midi_softc *sc = (struct midi_softc *)csc;
  948.     register struct midid *md;
  949.     register struct mdq *p, *q;
  950.  
  951.     q = bmdparse(sc, c);
  952.     if (q == 0)
  953.         return;
  954.  
  955.     for (md = sc->sc_readers; md != 0; md = md->md_nxtr) {
  956.         if (bmdfilter(md->md_filter, q->mq_data[0]))
  957.             continue;
  958.         if (md->md_echo)
  959.             bmd_echo(sc, q, md->md_echan);
  960.         if (md->md_rcnt >= BMD_MAXRBUF) {
  961.             ++md->md_idrops;
  962.             continue;
  963.         }
  964.         p = mdqcopy(q);
  965.         if (p == 0) {
  966.             ++md->md_idrops;
  967.             continue;
  968.         }
  969.         if (md->md_rt == 0)
  970.             md->md_rh = md->md_rt = p;
  971.         else {
  972.             md->md_rt->mq_next = p;
  973.             md->md_rt = p;
  974.         }
  975.         p->mq_next = 0;
  976.         if (++md->md_rcnt >= md->md_nbuf) {
  977.             if (md->md_rchan.want)
  978.                 bmdwakeup(md, &md->md_rchan);
  979.             if (md->md_sigio.want)
  980.                 bmdwakeup(md, &md->md_sigio);
  981.             if (md->md_rsel.want)
  982.                 bmdwakeup(md, &md->md_rsel);
  983.         }
  984.     }
  985. }
  986.  
  987. /*
  988.  * Called by level 14 interrupt handler.  The trap handler noted
  989.  * that we have work to do, so do it, and schedule the next work interval.
  990.  */
  991. int
  992. bmdupdate()
  993. {
  994.     register u_long t = midiclk.mt_now;
  995.     register u_long work = ~0;
  996.     register struct midid *md;
  997.     register struct mdq *head, *tail, *next;
  998.     register int i;
  999.     register struct midi_softc *sc = midi_softc;
  1000.  
  1001.     /*
  1002.      * Bring each port up to current time.
  1003.      */
  1004.     for (i = NPORTS; --i >= 0; ++sc) {
  1005.         for (md = sc->sc_writers; md != 0; md = md->md_nxtw) {
  1006.             head = md->md_wh;
  1007.             if (head != 0) {
  1008.                 if (BMD_TGT(head->mq_time, t)) {
  1009.                     if (BMD_TLT(head->mq_time, work))
  1010.                         work = head->mq_time;
  1011.                     continue;
  1012.                 }
  1013.                 tail = head->mq_tail;
  1014.                 next = tail->mq_next;
  1015.                 md->md_wcnt -= head->mq_qlen;
  1016.                 msl_output(sc->sc_msl, head, tail);
  1017.                 md->md_wh = next;
  1018.                 if (next == 0)
  1019.                     md->md_wt = 0;
  1020.                 else if (BMD_TLT(next->mq_time, work))
  1021.                     work = next->mq_time;
  1022.                 /* 
  1023.                  * Wake up anything waiting for output
  1024.                  * to happen.
  1025.                  */
  1026.                 if (md->md_wcnt <= md->md_wlo) {
  1027.                     if (md->md_wchan.want)
  1028.                         bmdwakeup(md, &md->md_wchan);
  1029.                     if (md->md_wsel.want)
  1030.                         bmdwakeup(md, &md->md_wsel);
  1031.                 }
  1032.             }
  1033.         }
  1034.     }
  1035.     midiclk.mt_work = work;
  1036. }
  1037.  
  1038. /*
  1039.  * Schedule a software interrupt for a bmd descriptor.  We must do various 
  1040.  * tasks at ipl lower than splmidi() because system data structures (i.e.,
  1041.  * the process queues) are serialized at such a lower level.
  1042.  * md is the descriptor and p is a pointer to a flag in the descriptor
  1043.  * that indicates the action.
  1044.  * If md points to itself (via md_nxti) then it is not in midisoft
  1045.  * and must be added.
  1046.  */
  1047. static void
  1048. bmdwakeup(md, p)
  1049.     struct midid *md;
  1050.     struct sleepchan *p;
  1051. {
  1052.     if (md->md_nxti == md) {
  1053.         md->md_nxti = midisoft;
  1054.         midisoft = md;
  1055.     }
  1056.     p->have = p->want;
  1057.     p->want = 0;
  1058.     set_intreg(IR_SOFT_INT4, 1);
  1059. }
  1060.  
  1061. static int        
  1062. bmdsleep(p)
  1063.     register struct sleepchan *p;
  1064. {
  1065.     register int st;
  1066.     p->want = 1;
  1067.     st = sleep((caddr_t)p, (PZERO+1)|PCATCH);
  1068.     p->want = 0;
  1069.  
  1070.     return st;
  1071. }
  1072.  
  1073. int
  1074. bmdsoftintr()
  1075. {
  1076.     register int s, st;
  1077.     register struct midid *md;
  1078.  
  1079.     s = splmidi();
  1080.     st = (int)midisoft;
  1081.     while ((md = midisoft) != 0) {
  1082.         midisoft = md->md_nxti;
  1083.         md->md_nxti = md;
  1084.         splx(s);
  1085.         if (md->md_sigio.have) {
  1086.             psignal(md->md_sigioproc, SIGIO);
  1087.             md->md_sigio.have = 0;
  1088.         }
  1089.         if (md->md_rsel.have) {
  1090.             selwakeup((struct proc *)md->md_rsel.have,
  1091.                   md->md_rcol);
  1092.             md->md_rsel.have = 0;
  1093.             md->md_rcol = 0;
  1094.         }
  1095.         if (md->md_wsel.have) {
  1096.             selwakeup((struct proc *)md->md_wsel.have,
  1097.                   md->md_wcol);
  1098.             md->md_wsel.have = 0;
  1099.             md->md_wcol = 0;
  1100.         }
  1101.         if (md->md_wchan.have) {
  1102.             wakeup((caddr_t)&md->md_wchan);
  1103.             md->md_wchan.have = 0;
  1104.         }
  1105.         if (md->md_rchan.have) {
  1106.             wakeup((caddr_t)&md->md_rchan);
  1107.             md->md_rchan.have = 0;
  1108.         }
  1109.         (void)splmidi();
  1110.     }
  1111.     splx(s);
  1112.  
  1113.     return st;
  1114. }
  1115.  
  1116. /*
  1117.  * Message allocator.  
  1118.  * XXX Should be replaced by kernel malloc.
  1119.  * Maintain free list, returning to malloc pool after last close.
  1120.  */
  1121. static struct mdq mpool[NMDQ];
  1122. static struct mdq *mdqfreelist;
  1123.  
  1124. struct mdq *
  1125. mdqalloc() 
  1126. {
  1127.     register struct mdq *q;
  1128.  
  1129.     q = mdqfreelist;
  1130.     if (q != 0) 
  1131.         mdqfreelist = q->mq_next;
  1132.     return q;
  1133. }
  1134.  
  1135. void
  1136. mdqinit()
  1137. {
  1138.     register int i;
  1139.     register struct mdq *m;
  1140.  
  1141.     mdqfreelist = m = mpool;
  1142.     for (i = NMDQ; --i > 0; ++m)
  1143.         m->mq_next = m + 1;
  1144.     m->mq_next = 0;
  1145. }
  1146.  
  1147. void
  1148. mdqfree(q)
  1149.     register struct mdq *q;
  1150. {
  1151.     q->mq_next = mdqfreelist;
  1152.     mdqfreelist = q;
  1153. }
  1154.  
  1155. void
  1156. mdqfreeq(head, tail)
  1157.     register struct mdq *head;
  1158.     register struct mdq *tail;
  1159. {
  1160.     if (head != 0) {
  1161.         tail->mq_next = mdqfreelist;
  1162.         mdqfreelist = head;
  1163.     }
  1164. }
  1165. #endif
  1166.