[BACK]Return to midi.c CVS log [TXT][DIR] Up to [local] / sys / dev

Annotation of sys/dev/midi.c, Revision 1.1.1.1

1.1       nbrk        1: /*     $OpenBSD: midi.c,v 1.16 2006/12/21 02:28:47 krw Exp $   */
                      2:
                      3: /*
                      4:  * Copyright (c) 2003, 2004 Alexandre Ratchov
                      5:  *
                      6:  * Permission to use, copy, modify, and distribute this software for any
                      7:  * purpose with or without fee is hereby granted, provided that the above
                      8:  * copyright notice and this permission notice appear in all copies.
                      9:  *
                     10:  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
                     11:  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
                     12:  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
                     13:  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
                     14:  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
                     15:  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
                     16:  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
                     17:  */
                     18:
                     19: /*
                     20:  * TODO
                     21:  *     - put the sequencer stuff in sequencer.c and sequencervar.h
                     22:  *       there is no reason to have it here. The sequencer
                     23:  *       driver need only to open the midi hw_if thus it does not
                     24:  *       need this driver
                     25:  */
                     26:
                     27: #include "midi.h"
                     28: #include "sequencer.h"
                     29: #if NMIDI > 0
                     30:
                     31: #include <sys/param.h>
                     32: #include <sys/fcntl.h>
                     33: #include <sys/systm.h>
                     34: #include <sys/ioctl.h>
                     35: #include <sys/exec.h>
                     36: #include <sys/conf.h>
                     37: #include <sys/lkm.h>
                     38: #include <sys/proc.h>
                     39: #include <sys/poll.h>
                     40: #include <sys/kernel.h>
                     41: #include <sys/timeout.h>
                     42: #include <sys/vnode.h>
                     43: #include <sys/signalvar.h>
                     44: #include <sys/malloc.h>
                     45: #include <sys/device.h>
                     46:
                     47: #include <dev/midi_if.h>
                     48: #include <dev/audio_if.h>
                     49: #include <dev/midivar.h>
                     50:
                     51:
                     52: int     midiopen(dev_t, int, int, struct proc *);
                     53: int     midiclose(dev_t, int, int, struct proc *);
                     54: int     midiread(dev_t, struct uio *, int);
                     55: int     midiwrite(dev_t, struct uio *, int);
                     56: int     midipoll(dev_t, int, struct proc *);
                     57: int    midiioctl(dev_t, u_long, caddr_t, int, struct proc *);
                     58: int    midiprobe(struct device *, void *, void *);
                     59: void   midiattach(struct device *, struct device *, void *);
                     60: int    mididetach(struct device *, int);
                     61: int    midiprint(void *, const char *);
                     62:
                     63: void   midi_iintr(void *, int);
                     64: void   midi_ointr(void *);
                     65: void   midi_out_start(struct midi_softc *);
                     66: void   midi_out_stop(struct midi_softc *);
                     67: void   midi_out_do(struct midi_softc *);
                     68: void   midi_attach(struct midi_softc *, struct device *);
                     69:
                     70:
                     71: #if NSEQUENCER > 0
                     72: int               midi_unit_count(void);
                     73: struct midi_hw_if *midi_get_hwif(int);
                     74: void              midi_toevent(struct midi_softc *, int);
                     75: int               midi_writebytes(int, u_char *, int);
                     76: void              midiseq_in(struct midi_dev *, u_char *, int);
                     77: #endif
                     78:
                     79: struct cfattach midi_ca = {
                     80:        sizeof(struct midi_softc), midiprobe, midiattach, mididetach
                     81: };
                     82:
                     83: struct cfdriver midi_cd = {
                     84:        NULL, "midi", DV_DULL
                     85: };
                     86:
                     87:
                     88: void
                     89: midi_iintr(void *addr, int data)
                     90: {
                     91:        struct midi_softc  *sc = (struct midi_softc *)addr;
                     92:        struct midi_buffer *mb = &sc->inbuf;
                     93:
                     94:        if (sc->isdying || !sc->isopen || !(sc->flags & FREAD)) return;
                     95:
                     96: #if NSEQUENCER > 0
                     97:        if (sc->seqopen) {
                     98:                midi_toevent(sc, data);
                     99:                return;
                    100:        }
                    101: #endif
                    102:        if (MIDIBUF_ISFULL(mb))
                    103:                return; /* discard data */
                    104:        if (MIDIBUF_ISEMPTY(mb)) {
                    105:                if (sc->rchan) {
                    106:                        sc->rchan = 0;
                    107:                        wakeup(&sc->rchan);
                    108:                }
                    109:                selwakeup(&sc->rsel);
                    110:                if (sc->async)
                    111:                        psignal(sc->async, SIGIO);
                    112:        }
                    113:        MIDIBUF_WRITE(mb, data);
                    114: }
                    115:
                    116:
                    117: int
                    118: midiread(dev_t dev, struct uio *uio, int ioflag)
                    119: {
                    120:        struct midi_softc  *sc = MIDI_DEV2SC(dev);
                    121:        struct midi_buffer *mb = &sc->inbuf;
                    122:        unsigned            count;
                    123:        int                 s, error;
                    124:
                    125:        if (!(sc->flags & FREAD))
                    126:                return ENXIO;
                    127:
                    128:        /* if there is no data then sleep (unless IO_NDELAY flag is set) */
                    129:
                    130:        s = splaudio();
                    131:        while(MIDIBUF_ISEMPTY(mb)) {
                    132:                if (sc->isdying) {
                    133:                        splx(s);
                    134:                        return EIO;
                    135:                }
                    136:                if (ioflag & IO_NDELAY) {
                    137:                        splx(s);
                    138:                        return EWOULDBLOCK;
                    139:                }
                    140:                sc->rchan = 1;
                    141:                error = tsleep(&sc->rchan, PWAIT|PCATCH, "mid_rd", 0);
                    142:                if (error) {
                    143:                        splx(s);
                    144:                        return error;
                    145:                }
                    146:        }
                    147:
                    148:        /* at this stage, there is at least 1 byte */
                    149:
                    150:        while (uio->uio_resid > 0  &&  mb->used > 0) {
                    151:                count = MIDIBUF_SIZE - mb->start;
                    152:                if (count > mb->used)
                    153:                        count = mb->used;
                    154:                if (count > uio->uio_resid)
                    155:                        count = uio->uio_resid;
                    156:                error = uiomove(mb->data + mb->start, count, uio);
                    157:                if (error) {
                    158:                        splx(s);
                    159:                        return error;
                    160:                }
                    161:                MIDIBUF_REMOVE(mb, count);
                    162:        }
                    163:        splx(s);
                    164:        return 0;
                    165: }
                    166:
                    167:
                    168: void
                    169: midi_ointr(void *addr)
                    170: {
                    171:        struct midi_softc  *sc = (struct midi_softc *)addr;
                    172:        struct midi_buffer *mb;
                    173:        int                s;
                    174:
                    175:        if (sc->isopen && !sc->isdying) {
                    176: #ifdef MIDI_DEBUG
                    177:                if (!sc->isbusy) {
                    178:                        printf("midi_ointr: output should be busy\n");
                    179:                }
                    180: #endif
                    181:                mb = &sc->outbuf;
                    182:                s = splaudio();
                    183:                if (mb->used == 0)
                    184:                        midi_out_stop(sc);
                    185:                else
                    186:                        midi_out_do(sc); /* restart output */
                    187:                splx(s);
                    188:        }
                    189: }
                    190:
                    191:
                    192: void
                    193: midi_out_start(struct midi_softc *sc)
                    194: {
                    195:        if (!sc->isbusy) {
                    196:                sc->isbusy = 1;
                    197:                midi_out_do(sc);
                    198:        }
                    199: }
                    200:
                    201: void
                    202: midi_out_stop(struct midi_softc *sc)
                    203: {
                    204:        sc->isbusy = 0;
                    205:        if (sc->wchan) {
                    206:                sc->wchan = 0;
                    207:                wakeup(&sc->wchan);
                    208:        }
                    209:        selwakeup(&sc->wsel);
                    210:        if (sc->async)
                    211:                psignal(sc->async, SIGIO);
                    212: }
                    213:
                    214:
                    215:        /*
                    216:         * drain output buffer, must be called with
                    217:         * interrupts disabled
                    218:         */
                    219: void
                    220: midi_out_do(struct midi_softc *sc)
                    221: {
                    222:        struct midi_buffer *mb = &sc->outbuf;
                    223:        unsigned            i, max;
                    224:        int                 error;
                    225:
                    226:        /*
                    227:         * If output interrupts are not supported then we write MIDI_MAXWRITE
                    228:         * bytes instead of 1, and then we wait sc->wait
                    229:         */
                    230:
                    231:        max = sc->props & MIDI_PROP_OUT_INTR ? 1 : MIDI_MAXWRITE;
                    232:        for (i = max; i != 0;) {
                    233:                if (mb->used == 0)
                    234:                        break;
                    235:                error = sc->hw_if->output(sc->hw_hdl, mb->data[mb->start]);
                    236:                /*
                    237:                 * 0 means that data is being sent, an interrupt will
                    238:                 * be generated when the interface becomes ready again
                    239:                 *
                    240:                 * EINPROGRESS means that data has been queued, but
                    241:                 * will not be sent immediately and thus will not
                    242:                 * generate interrupt, in this case we can send
                    243:                 * another byte. The flush() method can be called
                    244:                 * to force the transfer.
                    245:                 *
                    246:                 * EAGAIN means that data cannot be queued or sent;
                    247:                 * because the interface isn't ready. An interrupt
                    248:                 * will be generated once the interface is ready again
                    249:                 *
                    250:                 * any other (fatal) error code means that data couldn't
                    251:                 * be sent and was lost, interrupt will not be generated
                    252:                 */
                    253:                if (error == EINPROGRESS) {
                    254:                        MIDIBUF_REMOVE(mb, 1);
                    255:                        if (MIDIBUF_ISEMPTY(mb)) {
                    256:                                if (sc->hw_if->flush != NULL)
                    257:                                        sc->hw_if->flush(sc->hw_hdl);
                    258:                                midi_out_stop(sc);
                    259:                                return;
                    260:                        }
                    261:                } else if (error == 0) {
                    262:                        MIDIBUF_REMOVE(mb, 1);
                    263:                        i--;
                    264:                } else if (error == EAGAIN) {
                    265:                        break;
                    266:                } else {
                    267:                        MIDIBUF_INIT(mb);
                    268:                        midi_out_stop(sc);
                    269:                        return;
                    270:                }
                    271:        }
                    272:
                    273:        if (!(sc->props & MIDI_PROP_OUT_INTR)) {
                    274:                if (MIDIBUF_ISEMPTY(mb))
                    275:                        midi_out_stop(sc);
                    276:                else
                    277:                        timeout_add(&sc->timeo, sc->wait);
                    278:        }
                    279: }
                    280:
                    281:
                    282: int
                    283: midiwrite(dev_t dev, struct uio *uio, int ioflag)
                    284: {
                    285:        struct midi_softc  *sc = MIDI_DEV2SC(dev);
                    286:        struct midi_buffer *mb = &sc->outbuf;
                    287:        unsigned            count;
                    288:        int                 s, error;
                    289:
                    290:        if (!(sc->flags & FWRITE))
                    291:                return ENXIO;
                    292:        if (sc->isdying)
                    293:                return EIO;
                    294:
                    295:        /*
                    296:         * If IO_NDELAY flag is set then check if there is enough room
                    297:         * in the buffer to store at least one byte. If not then dont
                    298:         * start the write process.
                    299:         */
                    300:
                    301:        if ((ioflag & IO_NDELAY) &&  MIDIBUF_ISFULL(mb)  &&
                    302:            (uio->uio_resid > 0))
                    303:                return EWOULDBLOCK;
                    304:
                    305:        while (uio->uio_resid > 0) {
                    306:                s = splaudio();
                    307:                while (MIDIBUF_ISFULL(mb)) {
                    308:                        if (ioflag & IO_NDELAY) {
                    309:                                /*
                    310:                                 * At this stage at least one byte is already
                    311:                                 * moved so we do not return EWOULDBLOCK
                    312:                                 */
                    313:                                splx(s);
                    314:                                return 0;
                    315:                        }
                    316:                        sc->wchan = 1;
                    317:                        error = tsleep(&sc->wchan, PWAIT|PCATCH, "mid_wr", 0);
                    318:                        if (error) {
                    319:                                splx(s);
                    320:                                return error;
                    321:                        }
                    322:                        if (sc->isdying) {
                    323:                                splx(s);
                    324:                                return EIO;
                    325:                        }
                    326:                }
                    327:
                    328:                count = MIDIBUF_SIZE - MIDIBUF_END(mb);
                    329:                if (count > MIDIBUF_AVAIL(mb))
                    330:                        count = MIDIBUF_AVAIL(mb);
                    331:                if (count > uio->uio_resid)
                    332:                        count = uio->uio_resid;
                    333:                error = uiomove(mb->data + MIDIBUF_END(mb), count, uio);
                    334:                if (error) {
                    335:                        splx(s);
                    336:                        return error;
                    337:                }
                    338:                mb->used += count;
                    339:                midi_out_start(sc);
                    340:                splx(s);
                    341:        }
                    342:        return 0;
                    343: }
                    344:
                    345:
                    346: int
                    347: midipoll(dev_t dev, int events, struct proc *p)
                    348: {
                    349:        struct midi_softc *sc = MIDI_DEV2SC(dev);
                    350:        int                s, revents;
                    351:
                    352:        if (sc->isdying)
                    353:                return POLLERR;
                    354:
                    355:        revents = 0;
                    356:        s = splaudio();
                    357:        if (events & (POLLIN | POLLRDNORM)) {
                    358:                if (!MIDIBUF_ISEMPTY(&sc->inbuf))
                    359:                        revents |= events & (POLLIN | POLLRDNORM);
                    360:        }
                    361:        if (events & (POLLOUT | POLLWRNORM)) {
                    362:                if (!MIDIBUF_ISFULL(&sc->outbuf))
                    363:                        revents |= events & (POLLOUT | POLLWRNORM);
                    364:        }
                    365:        if (revents == 0) {
                    366:                if (events & (POLLIN | POLLRDNORM))
                    367:                        selrecord(p, &sc->rsel);
                    368:                if (events & (POLLOUT | POLLWRNORM))
                    369:                        selrecord(p, &sc->wsel);
                    370:        }
                    371:        splx(s);
                    372:        return (revents);
                    373: }
                    374:
                    375:
                    376: int
                    377: midiioctl(dev_t dev, u_long cmd, caddr_t addr, int flag, struct proc *p)
                    378: {
                    379:        struct midi_softc *sc = MIDI_DEV2SC(dev);
                    380:
                    381:        if (sc->isdying) return EIO;
                    382:
                    383:        switch(cmd) {
                    384:        case FIONBIO:
                    385:                /* All handled in the upper FS layer */
                    386:                break;
                    387:        case FIOASYNC:
                    388:                if (*(int *)addr) {
                    389:                        if (sc->async) return EBUSY;
                    390:                        sc->async = p;
                    391:                } else
                    392:                        sc->async = 0;
                    393:                break;
                    394:        default:
                    395:                return ENOTTY;
                    396:                break;
                    397:        }
                    398:        return 0;
                    399: }
                    400:
                    401:
                    402: int
                    403: midiopen(dev_t dev, int flags, int mode, struct proc *p)
                    404: {
                    405:        struct midi_softc *sc;
                    406:        int                err;
                    407:
                    408:        if (MIDI_UNIT(dev) >= midi_cd.cd_ndevs)
                    409:                return ENXIO;
                    410:        sc = MIDI_DEV2SC(dev);
                    411:        if (sc == NULL)         /* there may be more units than devices */
                    412:                return ENXIO;
                    413:        if (sc->isdying)
                    414:                return EIO;
                    415:        if (sc->isopen)
                    416:                return EBUSY;
                    417:
                    418:        MIDIBUF_INIT(&sc->inbuf);
                    419:        MIDIBUF_INIT(&sc->outbuf);
                    420:        sc->isbusy = 0;
                    421:        sc->rchan = sc->wchan = 0;
                    422:        sc->async = 0;
                    423:        sc->flags = flags;
                    424:
                    425:        err = sc->hw_if->open(sc->hw_hdl, flags, midi_iintr, midi_ointr, sc);
                    426:        if (err)
                    427:                return err;
                    428:        sc->isopen = 1;
                    429: #if NSEQUENCER > 0
                    430:        sc->seq_md = 0;
                    431:        sc->seqopen = 0;
                    432:        sc->evstatus = 0xff;
                    433: #endif
                    434:        return 0;
                    435: }
                    436:
                    437:
                    438: int
                    439: midiclose(dev_t dev, int fflag, int devtype, struct proc *p)
                    440: {
                    441:        struct midi_softc  *sc = MIDI_DEV2SC(dev);
                    442:        struct midi_buffer *mb;
                    443:        int                 error;
                    444:        int                 s;
                    445:
                    446:        mb = &sc->outbuf;
                    447:        if (!sc->isdying) {
                    448:                /* start draining output buffer */
                    449:                s = splaudio();
                    450:                if (!MIDIBUF_ISEMPTY(mb))
                    451:                        midi_out_start(sc);
                    452:                while (sc->isbusy) {
                    453:                        sc->wchan = 1;
                    454:                        error = tsleep(&sc->wchan, PWAIT|PCATCH, "mid_dr", 0);
                    455:                        if (error || sc->isdying)
                    456:                                break;
                    457:                }
                    458:                splx(s);
                    459:        }
                    460:
                    461:        /*
                    462:         * some hw_if->close() reset immediately the midi uart
                    463:         * which flushes the internal buffer of the uart device,
                    464:         * so we may lose some (important) data. To avoid this, we sleep 2*wait,
                    465:         * which gives the time to the uart to drain its internal buffers.
                    466:         *
                    467:         * Note: we'd better sleep in the corresponding hw_if->close()
                    468:         */
                    469:
                    470:        tsleep(&sc->wchan, PWAIT|PCATCH, "mid_cl", 2 * sc->wait);
                    471:        sc->hw_if->close(sc->hw_hdl);
                    472:        sc->isopen = 0;
                    473:        return 0;
                    474: }
                    475:
                    476:
                    477: int
                    478: midiprobe(struct device *parent, void *match, void *aux)
                    479: {
                    480:        struct audio_attach_args *sa = aux;
                    481:        return (sa != NULL && (sa->type == AUDIODEV_TYPE_MIDI) ? 1 : 0);
                    482: }
                    483:
                    484:
                    485: void
                    486: midi_attach(struct midi_softc *sc, struct device *parent)
                    487: {
                    488:        struct midi_info          mi;
                    489:
                    490:        sc->isdying = 0;
                    491:        sc->wait = (hz * MIDI_MAXWRITE) /  MIDI_RATE;
                    492:        if (sc->wait == 0)
                    493:                sc->wait = 1;
                    494:        sc->hw_if->getinfo(sc->hw_hdl, &mi);
                    495:        sc->props = mi.props;
                    496:        sc->isopen = 0;
                    497:        timeout_set(&sc->timeo, midi_ointr, sc);
                    498:        printf(": <%s>\n", mi.name);
                    499: }
                    500:
                    501:
                    502: void
                    503: midiattach(struct device *parent, struct device *self, void *aux)
                    504: {
                    505:        struct midi_softc        *sc = (struct midi_softc *)self;
                    506:        struct audio_attach_args *sa = (struct audio_attach_args *)aux;
                    507:        struct midi_hw_if        *hwif = sa->hwif;
                    508:        void                     *hdl = sa->hdl;
                    509:
                    510: #ifdef DIAGNOSTIC
                    511:        if (hwif == 0 ||
                    512:            hwif->open == 0 ||
                    513:            hwif->close == 0 ||
                    514:            hwif->output == 0 ||
                    515:            hwif->getinfo == 0) {
                    516:                printf("midi: missing method\n");
                    517:                return;
                    518:        }
                    519: #endif
                    520:        sc->hw_if = hwif;
                    521:        sc->hw_hdl = hdl;
                    522:        midi_attach(sc, parent);
                    523: }
                    524:
                    525:
                    526: int
                    527: mididetach(struct device *self, int flags)
                    528: {
                    529:        struct midi_softc *sc = (struct midi_softc *)self;
                    530:        int    maj, mn;
                    531:
                    532:        sc->isdying = 1;
                    533:        if (sc->wchan) {
                    534:                sc->wchan = 0;
                    535:                wakeup(&sc->wchan);
                    536:        }
                    537:        if (sc->rchan) {
                    538:                sc->rchan = 0;
                    539:                wakeup(&sc->rchan);
                    540:        }
                    541:
                    542:        /* locate the major number */
                    543:         for (maj = 0; maj < nchrdev; maj++)
                    544:                 if (cdevsw[maj].d_open == midiopen)
                    545:                         break;
                    546:
                    547:         /* Nuke the vnodes for any open instances (calls close). */
                    548:         mn = self->dv_unit;
                    549:         vdevgone(maj, mn, mn, VCHR);
                    550:
                    551:        return 0;
                    552: }
                    553:
                    554:
                    555: int
                    556: midiprint(void *aux, const char *pnp)
                    557: {
                    558:        if (pnp)
                    559:                printf("midi at %s", pnp);
                    560:        return (UNCONF);
                    561: }
                    562:
                    563:
                    564: void
                    565: midi_getinfo(dev_t dev, struct midi_info *mi)
                    566: {
                    567:        struct midi_softc *sc = MIDI_DEV2SC(dev);
                    568:        if (MIDI_UNIT(dev) >= midi_cd.cd_ndevs || sc == NULL || sc->isdying) {
                    569:                mi->name = "unconfigured";
                    570:                mi->props = 0;
                    571:                return;
                    572:        }
                    573:        sc->hw_if->getinfo(sc->hw_hdl, mi);
                    574: }
                    575:
                    576:
                    577: struct device *
                    578: midi_attach_mi(struct midi_hw_if *hwif, void *hdl, struct device *dev)
                    579: {
                    580:        struct audio_attach_args arg;
                    581:
                    582:        arg.type = AUDIODEV_TYPE_MIDI;
                    583:        arg.hwif = hwif;
                    584:        arg.hdl = hdl;
                    585:        return config_found(dev, &arg, midiprint);
                    586: }
                    587:
                    588:
                    589: int
                    590: midi_unit_count(void)
                    591: {
                    592:        return midi_cd.cd_ndevs;
                    593: }
                    594:
                    595:
                    596: #if NSEQUENCER > 0
                    597: #define MIDI_EVLEN(status)     (midi_evlen[((status) >> 4) & 7])
                    598: unsigned midi_evlen[] = { 2, 2, 2, 2, 1, 1, 2 };
                    599:
                    600: void
                    601: midi_toevent(struct midi_softc *sc, int data)
                    602: {
                    603:        unsigned char mesg[3];
                    604:
                    605:        if (data >= 0xf8) {             /* is it a realtime message ? */
                    606:                switch(data) {
                    607:                case 0xf8:              /* midi timer tic */
                    608:                case 0xfa:              /* midi timer start */
                    609:                case 0xfb:              /* midi timer continue (after stop) */
                    610:                case 0xfc:              /* midi timer stop */
                    611:                        mesg[0] = data;
                    612:                        midiseq_in(sc->seq_md, mesg, 1);
                    613:                        break;
                    614:                default:
                    615:                        break;
                    616:                }
                    617:        } else if (data >= 0x80) {      /* is it a common or voice message ? */
                    618:                sc->evstatus = data;
                    619:                sc->evindex = 0;
                    620:        } else {                        /* else it is a data byte */
                    621:                /* strip common messages and bogus data */
                    622:                if (sc->evstatus >= 0xf0 || sc->evstatus < 0x80)
                    623:                        return;
                    624:
                    625:                sc->evdata[sc->evindex++] = data;
                    626:                if (sc->evindex == MIDI_EVLEN(sc->evstatus)) {
                    627:                        sc->evindex = 0;
                    628:                        mesg[0] = sc->evstatus;
                    629:                        mesg[1] = sc->evdata[0];
                    630:                        mesg[2] = sc->evdata[1];
                    631:                        midiseq_in(sc->seq_md, mesg, 1 + MIDI_EVLEN(sc->evstatus));
                    632:                }
                    633:        }
                    634: }
                    635:
                    636:
                    637: int
                    638: midi_writebytes(int unit, unsigned char *mesg, int mesglen)
                    639: {
                    640:        struct midi_softc  *sc = midi_cd.cd_devs[unit];
                    641:        struct midi_buffer *mb = &sc->outbuf;
                    642:        unsigned            count;
                    643:        int                 s;
                    644:
                    645:        s = splaudio();
                    646:        if (mesglen > MIDIBUF_AVAIL(mb)) {
                    647:                splx(s);
                    648:                return EWOULDBLOCK;
                    649:        }
                    650:
                    651:        while (mesglen > 0) {
                    652:                count = MIDIBUF_SIZE - MIDIBUF_END(mb);
                    653:                if (count > MIDIBUF_AVAIL(mb)) count = MIDIBUF_AVAIL(mb);
                    654:                if (count > mesglen) count = mesglen;
                    655:                bcopy(mesg, mb->data + MIDIBUF_END(mb), count);
                    656:                mb->used += count;
                    657:                mesg += count;
                    658:                mesglen -= count;
                    659:                midi_out_start(sc);
                    660:        }
                    661:        splx(s);
                    662:        return 0;
                    663: }
                    664:
                    665: #endif /* NSEQUENCER > 0 */
                    666: #endif /* NMIDI > 0 */

CVSweb