Home | History | Annotate | Line # | Download | only in dev
midi.c revision 1.3
      1  1.3  augustss /*	$NetBSD: midi.c,v 1.3 1998/08/13 00:13:56 augustss Exp $	*/
      2  1.1  augustss 
      3  1.1  augustss /*
      4  1.1  augustss  * Copyright (c) 1998 The NetBSD Foundation, Inc.
      5  1.1  augustss  * All rights reserved.
      6  1.1  augustss  *
      7  1.1  augustss  * Author: Lennart Augustsson
      8  1.1  augustss  *
      9  1.1  augustss  * Redistribution and use in source and binary forms, with or without
     10  1.1  augustss  * modification, are permitted provided that the following conditions
     11  1.1  augustss  * are met:
     12  1.1  augustss  * 1. Redistributions of source code must retain the above copyright
     13  1.1  augustss  *    notice, this list of conditions and the following disclaimer.
     14  1.1  augustss  * 2. Redistributions in binary form must reproduce the above copyright
     15  1.1  augustss  *    notice, this list of conditions and the following disclaimer in the
     16  1.1  augustss  *    documentation and/or other materials provided with the distribution.
     17  1.1  augustss  * 3. All advertising materials mentioning features or use of this software
     18  1.1  augustss  *    must display the following acknowledgement:
     19  1.1  augustss  *        This product includes software developed by the NetBSD
     20  1.1  augustss  *        Foundation, Inc. and its contributors.
     21  1.1  augustss  * 4. Neither the name of The NetBSD Foundation nor the names of its
     22  1.1  augustss  *    contributors may be used to endorse or promote products derived
     23  1.1  augustss  *    from this software without specific prior written permission.
     24  1.1  augustss  *
     25  1.1  augustss  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
     26  1.1  augustss  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     27  1.1  augustss  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     28  1.1  augustss  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
     29  1.1  augustss  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     30  1.1  augustss  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     31  1.1  augustss  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     32  1.1  augustss  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     33  1.1  augustss  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     34  1.1  augustss  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     35  1.1  augustss  * POSSIBILITY OF SUCH DAMAGE.
     36  1.1  augustss  */
     37  1.1  augustss 
     38  1.1  augustss #include "midi.h"
     39  1.1  augustss #if NMIDI > 0
     40  1.1  augustss 
     41  1.1  augustss #include "sequencer.h"
     42  1.1  augustss 
     43  1.1  augustss #include <sys/param.h>
     44  1.1  augustss #include <sys/ioctl.h>
     45  1.1  augustss #include <sys/fcntl.h>
     46  1.1  augustss #include <sys/vnode.h>
     47  1.1  augustss #include <sys/select.h>
     48  1.1  augustss #include <sys/poll.h>
     49  1.1  augustss #include <sys/malloc.h>
     50  1.1  augustss #include <sys/proc.h>
     51  1.1  augustss #include <sys/systm.h>
     52  1.1  augustss #include <sys/syslog.h>
     53  1.1  augustss #include <sys/kernel.h>
     54  1.1  augustss #include <sys/signalvar.h>
     55  1.1  augustss #include <sys/conf.h>
     56  1.1  augustss #include <sys/audioio.h>
     57  1.1  augustss #include <sys/midiio.h>
     58  1.1  augustss #include <sys/device.h>
     59  1.1  augustss 
     60  1.1  augustss #include <dev/audio_if.h>
     61  1.1  augustss #include <dev/midivar.h>
     62  1.1  augustss 
     63  1.1  augustss #ifdef AUDIO_DEBUG
     64  1.1  augustss #define DPRINTF(x)	if (mididebug) printf x
     65  1.1  augustss #define DPRINTFN(n,x)	if (mididebug >= (n)) printf x
     66  1.1  augustss int	mididebug = 0;
     67  1.1  augustss #else
     68  1.1  augustss #define DPRINTF(x)
     69  1.1  augustss #define DPRINTFN(n,x)
     70  1.1  augustss #endif
     71  1.1  augustss 
     72  1.1  augustss int midi_wait;
     73  1.1  augustss 
     74  1.2  augustss void	midi_in __P((void *, int));
     75  1.2  augustss void	midi_out __P((void *));
     76  1.2  augustss int	midi_start_output __P((struct midi_softc *, int));
     77  1.2  augustss int	midi_sleep_timo __P((int *, char *, int));
     78  1.2  augustss int	midi_sleep __P((int *, char *));
     79  1.2  augustss void	midi_wakeup __P((int *));
     80  1.2  augustss void	midi_initbuf __P((struct midi_buffer *));
     81  1.2  augustss void	midi_timeout __P((void *));
     82  1.1  augustss 
     83  1.1  augustss int	midiprobe __P((struct device *, struct cfdata *, void *));
     84  1.1  augustss void	midiattach __P((struct device *, struct device *, void *));
     85  1.1  augustss 
     86  1.1  augustss struct cfattach midi_ca = {
     87  1.1  augustss 	sizeof(struct midi_softc), midiprobe, midiattach
     88  1.1  augustss };
     89  1.1  augustss 
     90  1.1  augustss extern struct cfdriver midi_cd;
     91  1.1  augustss 
     92  1.1  augustss int
     93  1.1  augustss midiprobe(parent, match, aux)
     94  1.1  augustss 	struct device *parent;
     95  1.1  augustss 	struct cfdata *match;
     96  1.1  augustss 	void *aux;
     97  1.1  augustss {
     98  1.1  augustss 	struct audio_attach_args *sa = aux;
     99  1.1  augustss 
    100  1.1  augustss 	DPRINTFN(6,("midiprobe: type=%d sa=%p hw=%p\n",
    101  1.1  augustss 		 sa->type, sa, sa->hwif));
    102  1.1  augustss 	return (sa->type == AUDIODEV_TYPE_MIDI) ? 1 : 0;
    103  1.1  augustss }
    104  1.1  augustss 
    105  1.1  augustss void
    106  1.1  augustss midiattach(parent, self, aux)
    107  1.1  augustss 	struct device *parent, *self;
    108  1.1  augustss 	void *aux;
    109  1.1  augustss {
    110  1.1  augustss 	struct midi_softc *sc = (void *)self;
    111  1.1  augustss 	struct audio_attach_args *sa = aux;
    112  1.1  augustss 	struct midi_hw_if *hwp = sa->hwif;
    113  1.1  augustss 	void *hdlp = sa->hdl;
    114  1.1  augustss 
    115  1.1  augustss 	DPRINTFN(6, ("MIDI attach\n"));
    116  1.1  augustss 
    117  1.1  augustss #ifdef DIAGNOSTIC
    118  1.1  augustss 	if (hwp == 0 ||
    119  1.1  augustss 	    hwp->open == 0 ||
    120  1.1  augustss 	    hwp->close == 0 ||
    121  1.1  augustss 	    hwp->output == 0 ||
    122  1.1  augustss 	    hwp->getinfo == 0) {
    123  1.1  augustss 		printf("midi: missing method\n");
    124  1.1  augustss 		return;
    125  1.1  augustss 	}
    126  1.1  augustss #endif
    127  1.1  augustss 	sc->hw_if = hwp;
    128  1.1  augustss 	sc->hw_hdl = hdlp;
    129  1.2  augustss 	midi_attach(sc, parent);
    130  1.2  augustss }
    131  1.2  augustss 
    132  1.2  augustss void
    133  1.2  augustss midi_attach(sc, parent)
    134  1.2  augustss 	struct midi_softc *sc;
    135  1.2  augustss 	struct device *parent;
    136  1.2  augustss {
    137  1.2  augustss 	struct midi_info mi;
    138  1.2  augustss 
    139  1.1  augustss 	sc->isopen = 0;
    140  1.1  augustss 
    141  1.1  augustss 	midi_initbuf(&sc->outbuf);
    142  1.1  augustss 	midi_initbuf(&sc->inbuf);
    143  1.1  augustss 
    144  1.1  augustss 	midi_wait = MIDI_WAIT * hz / 1000000;
    145  1.1  augustss 	if (midi_wait == 0)
    146  1.1  augustss 		midi_wait = 1;
    147  1.1  augustss 
    148  1.2  augustss 	sc->sc_dev = parent;
    149  1.2  augustss 	sc->hw_if->getinfo(sc->hw_hdl, &mi);
    150  1.1  augustss 	sc->props = mi.props;
    151  1.2  augustss 	printf(": <%s>\n", mi.name);
    152  1.1  augustss }
    153  1.1  augustss 
    154  1.1  augustss int
    155  1.1  augustss midi_unit_count()
    156  1.1  augustss {
    157  1.1  augustss 	return midi_cd.cd_ndevs;
    158  1.1  augustss }
    159  1.1  augustss 
    160  1.1  augustss void
    161  1.1  augustss midi_initbuf(mb)
    162  1.1  augustss 	struct midi_buffer *mb;
    163  1.1  augustss {
    164  1.1  augustss 	mb->used = 0;
    165  1.1  augustss 	mb->usedhigh = MIDI_BUFSIZE;
    166  1.1  augustss 	mb->end = mb->start + mb->usedhigh;
    167  1.1  augustss 	mb->inp = mb->outp = mb->start;
    168  1.1  augustss }
    169  1.1  augustss 
    170  1.2  augustss int
    171  1.1  augustss midi_sleep_timo(chan, label, timo)
    172  1.1  augustss 	int *chan;
    173  1.1  augustss 	char *label;
    174  1.1  augustss 	int timo;
    175  1.1  augustss {
    176  1.1  augustss 	int st;
    177  1.1  augustss 
    178  1.1  augustss 	if (!label)
    179  1.1  augustss 		label = "midi";
    180  1.1  augustss 
    181  1.1  augustss 	DPRINTFN(5, ("midi_sleep_timo: %p %s %d\n", chan, label, timo));
    182  1.1  augustss 	*chan = 1;
    183  1.1  augustss 	st = tsleep(chan, PWAIT | PCATCH, label, timo);
    184  1.1  augustss 	*chan = 0;
    185  1.1  augustss #ifdef MIDI_DEBUG
    186  1.1  augustss 	if (st != 0)
    187  1.1  augustss 		printf("midi_sleep: %d\n", st);
    188  1.1  augustss #endif
    189  1.1  augustss 	return st;
    190  1.1  augustss }
    191  1.1  augustss 
    192  1.2  augustss int
    193  1.1  augustss midi_sleep(chan, label)
    194  1.1  augustss 	int *chan;
    195  1.1  augustss 	char *label;
    196  1.1  augustss {
    197  1.1  augustss 	return midi_sleep_timo(chan, label, 0);
    198  1.1  augustss }
    199  1.1  augustss 
    200  1.2  augustss void
    201  1.1  augustss midi_wakeup(chan)
    202  1.1  augustss 	int *chan;
    203  1.1  augustss {
    204  1.1  augustss 	if (*chan) {
    205  1.1  augustss 		DPRINTFN(5, ("midi_wakeup: %p\n", chan));
    206  1.1  augustss 		wakeup(chan);
    207  1.1  augustss 		*chan = 0;
    208  1.1  augustss 	}
    209  1.1  augustss }
    210  1.1  augustss 
    211  1.1  augustss static int midi_lengths[] = { 2,2,2,2,1,1,2,0 };
    212  1.1  augustss /* Number of bytes in a MIDI command */
    213  1.1  augustss #define MIDI_LENGTH(d) (midi_lengths[((d) >> 4) & 7])
    214  1.1  augustss 
    215  1.1  augustss void
    216  1.1  augustss midi_in(addr, data)
    217  1.1  augustss 	void *addr;
    218  1.1  augustss 	int data;
    219  1.1  augustss {
    220  1.1  augustss 	struct midi_softc *sc = addr;
    221  1.1  augustss 	struct midi_buffer *mb = &sc->inbuf;
    222  1.1  augustss 	int i;
    223  1.1  augustss 
    224  1.3  augustss 	if (!sc->isopen)
    225  1.3  augustss 		return;
    226  1.1  augustss 	if (data == MIDI_ACK)
    227  1.1  augustss 		return;
    228  1.1  augustss 	DPRINTFN(3, ("midi_in: %p 0x%02x\n", sc, data));
    229  1.1  augustss 	if (!(sc->flags & FREAD))
    230  1.1  augustss 		return;		/* discard data if not reading */
    231  1.1  augustss 
    232  1.1  augustss 	switch(sc->in_state) {
    233  1.1  augustss 	case MIDI_IN_START:
    234  1.1  augustss 		if (MIDI_IS_STATUS(data)) {
    235  1.1  augustss 			switch(data) {
    236  1.1  augustss 			case 0xf0: /* Sysex */
    237  1.1  augustss 				sc->in_state = MIDI_IN_SYSEX;
    238  1.1  augustss 				break;
    239  1.1  augustss 			case 0xf1: /* MTC quarter frame */
    240  1.1  augustss 			case 0xf3: /* Song select */
    241  1.1  augustss 				sc->in_state = MIDI_IN_DATA;
    242  1.1  augustss 				sc->in_msg[0] = data;
    243  1.1  augustss 				sc->in_pos = 1;
    244  1.1  augustss 				sc->in_left = 1;
    245  1.1  augustss 				break;
    246  1.1  augustss 			case 0xf2: /* Song position pointer */
    247  1.1  augustss 				sc->in_state = MIDI_IN_DATA;
    248  1.1  augustss 				sc->in_msg[0] = data;
    249  1.1  augustss 				sc->in_pos = 1;
    250  1.1  augustss 				sc->in_left = 2;
    251  1.1  augustss 				break;
    252  1.1  augustss 			default:
    253  1.1  augustss 				if (MIDI_IS_COMMON(data)) {
    254  1.1  augustss 					sc->in_msg[0] = data;
    255  1.1  augustss 					sc->in_pos = 1;
    256  1.1  augustss 					goto deliver;
    257  1.1  augustss 				} else {
    258  1.1  augustss 					sc->in_state = MIDI_IN_DATA;
    259  1.1  augustss 					sc->in_msg[0] = sc->in_status = data;
    260  1.1  augustss 					sc->in_pos = 1;
    261  1.1  augustss 					sc->in_left = MIDI_LENGTH(sc->in_status);
    262  1.1  augustss 				}
    263  1.1  augustss 				break;
    264  1.1  augustss 			}
    265  1.1  augustss 		} else {
    266  1.1  augustss 			if (MIDI_IS_STATUS(sc->in_status)) {
    267  1.1  augustss 				sc->in_state = MIDI_IN_DATA;
    268  1.1  augustss 				sc->in_msg[0] = sc->in_status;
    269  1.1  augustss 				sc->in_msg[1] = data;
    270  1.1  augustss 				sc->in_pos = 2;
    271  1.1  augustss 				sc->in_left = MIDI_LENGTH(sc->in_status) - 1;
    272  1.1  augustss 			}
    273  1.1  augustss 		}
    274  1.1  augustss 		return;
    275  1.1  augustss 	case MIDI_IN_DATA:
    276  1.1  augustss 		sc->in_msg[sc->in_pos++] = data;
    277  1.1  augustss 		if (--sc->in_left <= 0)
    278  1.1  augustss 			break;	/* deliver data */
    279  1.1  augustss 		return;
    280  1.1  augustss 	case MIDI_IN_SYSEX:
    281  1.1  augustss 		if (data == MIDI_SYSEX_END)
    282  1.1  augustss 			sc->in_state = MIDI_IN_START;
    283  1.1  augustss 		return;
    284  1.1  augustss 	}
    285  1.1  augustss deliver:
    286  1.1  augustss 	sc->in_state = MIDI_IN_START;
    287  1.1  augustss #if NSEQUENCER > 0
    288  1.1  augustss 	if (sc->seqopen) {
    289  1.2  augustss 		extern void midiseq_in __P((struct midi_softc *,u_char *,int));
    290  1.2  augustss 		midiseq_in(sc, sc->in_msg, sc->in_pos);
    291  1.1  augustss 		return;
    292  1.1  augustss 	}
    293  1.1  augustss #endif
    294  1.1  augustss 
    295  1.1  augustss 	if (mb->used + sc->in_pos > mb->usedhigh) {
    296  1.1  augustss 		DPRINTF(("midi_in: buffer full, discard data=0x%02x\n",
    297  1.1  augustss 			 sc->in_msg[0]));
    298  1.1  augustss 		return;
    299  1.1  augustss 	}
    300  1.1  augustss 	for (i = 0; i < sc->in_pos; i++) {
    301  1.1  augustss 		*mb->inp++ = sc->in_msg[i];
    302  1.1  augustss 		if (mb->inp >= mb->end)
    303  1.1  augustss 			mb->inp = mb->start;
    304  1.1  augustss 		mb->used++;
    305  1.1  augustss 	}
    306  1.1  augustss 	midi_wakeup(&sc->rchan);
    307  1.1  augustss 	selwakeup(&sc->rsel);
    308  1.1  augustss 	if (sc->async)
    309  1.1  augustss 		psignal(sc->async, SIGIO);
    310  1.1  augustss }
    311  1.1  augustss 
    312  1.1  augustss void
    313  1.1  augustss midi_out(addr)
    314  1.1  augustss 	void *addr;
    315  1.1  augustss {
    316  1.1  augustss 	struct midi_softc *sc = addr;
    317  1.3  augustss 
    318  1.3  augustss 	if (!sc->isopen)
    319  1.3  augustss 		return;
    320  1.1  augustss 	DPRINTFN(3, ("midi_out: %p\n", sc));
    321  1.1  augustss 	midi_start_output(sc, 1);
    322  1.1  augustss }
    323  1.1  augustss 
    324  1.1  augustss int
    325  1.1  augustss midiopen(dev, flags, ifmt, p)
    326  1.1  augustss 	dev_t dev;
    327  1.1  augustss 	int flags, ifmt;
    328  1.1  augustss 	struct proc *p;
    329  1.1  augustss {
    330  1.1  augustss 	int unit = MIDIUNIT(dev);
    331  1.1  augustss 	struct midi_softc *sc;
    332  1.1  augustss 	struct midi_hw_if *hw;
    333  1.1  augustss 	int error;
    334  1.1  augustss 
    335  1.1  augustss 	if (unit >= midi_cd.cd_ndevs ||
    336  1.1  augustss 	    (sc = midi_cd.cd_devs[unit]) == NULL)
    337  1.1  augustss 		return ENXIO;
    338  1.1  augustss 	DPRINTF(("midiopen %p\n", sc));
    339  1.1  augustss 
    340  1.1  augustss 	hw = sc->hw_if;
    341  1.1  augustss 	if (!hw)
    342  1.1  augustss 		return ENXIO;
    343  1.1  augustss 	if (sc->isopen)
    344  1.1  augustss 		return EBUSY;
    345  1.1  augustss 	sc->in_state = MIDI_IN_START;
    346  1.1  augustss 	sc->in_status = 0;
    347  1.1  augustss 	error = hw->open(sc->hw_hdl, flags, midi_in, midi_out, sc);
    348  1.1  augustss 	if (error)
    349  1.1  augustss 		return error;
    350  1.1  augustss 	sc->isopen++;
    351  1.1  augustss 	sc->flags = flags;
    352  1.1  augustss 	sc->rchan = 0;
    353  1.1  augustss 	sc->wchan = 0;
    354  1.1  augustss 	sc->pbus = 0;
    355  1.1  augustss 	sc->async = 0;
    356  1.1  augustss 
    357  1.1  augustss 	return 0;
    358  1.1  augustss }
    359  1.1  augustss 
    360  1.1  augustss int
    361  1.1  augustss midiclose(dev, flags, ifmt, p)
    362  1.1  augustss 	dev_t dev;
    363  1.1  augustss 	int flags, ifmt;
    364  1.1  augustss 	struct proc *p;
    365  1.1  augustss {
    366  1.1  augustss 	int unit = MIDIUNIT(dev);
    367  1.1  augustss 	struct midi_softc *sc = midi_cd.cd_devs[unit];
    368  1.1  augustss 	struct midi_hw_if *hw = sc->hw_if;
    369  1.1  augustss 	int s, error;
    370  1.1  augustss 
    371  1.1  augustss 	DPRINTF(("midiclose %p\n", sc));
    372  1.1  augustss 
    373  1.1  augustss 	midi_start_output(sc, 0);
    374  1.1  augustss 	error = 0;
    375  1.1  augustss 	s = splaudio();
    376  1.1  augustss 	while (sc->outbuf.used > 0 && !error) {
    377  1.1  augustss 		DPRINTFN(2,("midiclose sleep used=%d\n", sc->outbuf.used));
    378  1.3  augustss 		error = midi_sleep_timo(&sc->wchan, "mid_dr", 30*hz);
    379  1.1  augustss 	}
    380  1.3  augustss 	sc->isopen = 0;
    381  1.1  augustss 	splx(s);
    382  1.1  augustss 	hw->close(sc->hw_hdl);
    383  1.1  augustss #if NSEQUENCER > 0
    384  1.1  augustss 	sc->seqopen = 0;
    385  1.1  augustss #endif
    386  1.1  augustss 	return 0;
    387  1.1  augustss }
    388  1.1  augustss 
    389  1.1  augustss int
    390  1.1  augustss midiread(dev, uio, ioflag)
    391  1.1  augustss 	dev_t dev;
    392  1.1  augustss 	struct uio *uio;
    393  1.1  augustss 	int ioflag;
    394  1.1  augustss {
    395  1.1  augustss 	int unit = MIDIUNIT(dev);
    396  1.1  augustss 	struct midi_softc *sc = midi_cd.cd_devs[unit];
    397  1.1  augustss 	struct midi_buffer *mb = &sc->inbuf;
    398  1.1  augustss 	int error;
    399  1.1  augustss 	u_char *outp;
    400  1.1  augustss 	int used, cc, n, resid;
    401  1.1  augustss 	int s;
    402  1.1  augustss 
    403  1.1  augustss 	DPRINTF(("midiread: %p, count=%d\n", sc, uio->uio_resid));
    404  1.1  augustss 
    405  1.1  augustss 	error = 0;
    406  1.1  augustss 	resid = uio->uio_resid;
    407  1.1  augustss 	while (uio->uio_resid == resid && !error) {
    408  1.1  augustss 		s = splaudio();
    409  1.1  augustss 		while (mb->used <= 0) {
    410  1.1  augustss 			if (ioflag & IO_NDELAY) {
    411  1.1  augustss 				splx(s);
    412  1.1  augustss 				return EWOULDBLOCK;
    413  1.1  augustss 			}
    414  1.1  augustss 			error = midi_sleep(&sc->rchan, "mid rd");
    415  1.1  augustss 			if (error) {
    416  1.1  augustss 				splx(s);
    417  1.1  augustss 				return error;
    418  1.1  augustss 			}
    419  1.1  augustss 		}
    420  1.1  augustss 		used = mb->used;
    421  1.1  augustss 		outp = mb->outp;
    422  1.1  augustss 		splx(s);
    423  1.1  augustss 		cc = used;	/* maximum to read */
    424  1.1  augustss 		n = mb->end - outp;
    425  1.1  augustss 		if (n < cc)
    426  1.1  augustss 			cc = n;	/* don't read beyond end of buffer */
    427  1.1  augustss 		if (uio->uio_resid < cc)
    428  1.1  augustss 			cc = uio->uio_resid; /* and no more than we want */
    429  1.1  augustss 		DPRINTFN(3, ("midiread: uiomove cc=%d\n", cc));
    430  1.1  augustss 		error = uiomove(outp, cc, uio);
    431  1.1  augustss 		if (error)
    432  1.1  augustss 			break;
    433  1.1  augustss 		used -= cc;
    434  1.1  augustss 		outp += cc;
    435  1.1  augustss 		if (outp >= mb->end)
    436  1.1  augustss 			outp = mb->start;
    437  1.1  augustss 		s = splaudio();
    438  1.1  augustss 		mb->outp = outp;
    439  1.1  augustss 		mb->used = used;
    440  1.1  augustss 		splx(s);
    441  1.1  augustss 	}
    442  1.1  augustss 	return error;
    443  1.1  augustss }
    444  1.1  augustss 
    445  1.1  augustss void
    446  1.1  augustss midi_timeout(arg)
    447  1.1  augustss 	void *arg;
    448  1.1  augustss {
    449  1.1  augustss 	struct midi_softc *sc = arg;
    450  1.1  augustss 
    451  1.1  augustss 	DPRINTFN(3,("midi_timeout: %p\n", sc));
    452  1.1  augustss 	midi_start_output(sc, 1);
    453  1.1  augustss }
    454  1.1  augustss 
    455  1.1  augustss int
    456  1.1  augustss midi_start_output(sc, intr)
    457  1.1  augustss 	struct midi_softc *sc;
    458  1.1  augustss 	int intr;
    459  1.1  augustss {
    460  1.1  augustss 	struct midi_buffer *mb = &sc->outbuf;
    461  1.1  augustss 	u_char *outp;
    462  1.1  augustss 	int error;
    463  1.1  augustss 	int s;
    464  1.1  augustss 	int i, mmax;
    465  1.1  augustss 
    466  1.1  augustss 	error = 0;
    467  1.1  augustss 	mmax = sc->props & MIDI_PROP_OUT_INTR ? 1 : MIDI_MAX_WRITE;
    468  1.1  augustss 	s = splaudio();
    469  1.1  augustss 	if (sc->pbus && !intr) {
    470  1.1  augustss 		DPRINTFN(4, ("midi_start_output: busy\n"));
    471  1.1  augustss 		splx(s);
    472  1.1  augustss 		return 0;
    473  1.1  augustss 	}
    474  1.1  augustss 	sc->pbus = 1;
    475  1.1  augustss 	for (i = 0; i < mmax && mb->used > 0 && !error; i++) {
    476  1.1  augustss 		outp = mb->outp;
    477  1.1  augustss 		splx(s);
    478  1.1  augustss 		DPRINTFN(4, ("midi_start_output: %p i=%d, data=0x%02x\n",
    479  1.1  augustss 			     sc, i, *outp));
    480  1.1  augustss 		error = sc->hw_if->output(sc->hw_hdl, *outp++);
    481  1.1  augustss 		if (outp >= mb->end)
    482  1.1  augustss 			outp = mb->start;
    483  1.1  augustss 		s = splaudio();
    484  1.1  augustss 		mb->outp = outp;
    485  1.1  augustss 		mb->used--;
    486  1.1  augustss 	}
    487  1.1  augustss 	midi_wakeup(&sc->wchan);
    488  1.1  augustss 	selwakeup(&sc->wsel);
    489  1.1  augustss 	if (sc->async)
    490  1.1  augustss 		psignal(sc->async, SIGIO);
    491  1.1  augustss 	if (mb->used > 0) {
    492  1.1  augustss 		if (!(sc->props & MIDI_PROP_OUT_INTR))
    493  1.1  augustss 			timeout(midi_timeout, sc, midi_wait);
    494  1.1  augustss 	} else
    495  1.1  augustss 		sc->pbus = 0;
    496  1.1  augustss 	splx(s);
    497  1.1  augustss 	return error;
    498  1.1  augustss }
    499  1.1  augustss 
    500  1.1  augustss int
    501  1.1  augustss midiwrite(dev, uio, ioflag)
    502  1.1  augustss 	dev_t dev;
    503  1.1  augustss 	struct uio *uio;
    504  1.1  augustss 	int ioflag;
    505  1.1  augustss {
    506  1.1  augustss 	int unit = MIDIUNIT(dev);
    507  1.1  augustss 	struct midi_softc *sc = midi_cd.cd_devs[unit];
    508  1.1  augustss 	struct midi_buffer *mb = &sc->outbuf;
    509  1.1  augustss 	int error;
    510  1.1  augustss 	u_char *inp;
    511  1.1  augustss 	int used, cc, n;
    512  1.1  augustss 	int s;
    513  1.1  augustss 
    514  1.1  augustss 	DPRINTFN(2, ("midiwrite: %p, unit=%d, count=%d\n", sc, unit,
    515  1.1  augustss 		     uio->uio_resid));
    516  1.1  augustss 
    517  1.1  augustss 	error = 0;
    518  1.1  augustss 	while (uio->uio_resid > 0 && !error) {
    519  1.1  augustss 		s = splaudio();
    520  1.1  augustss 		if (mb->used >= mb->usedhigh) {
    521  1.1  augustss 			DPRINTFN(3,("midi_write: sleep used=%d hiwat=%d\n",
    522  1.1  augustss 				 mb->used, mb->usedhigh));
    523  1.1  augustss 			if (ioflag & IO_NDELAY) {
    524  1.1  augustss 				splx(s);
    525  1.1  augustss 				return EWOULDBLOCK;
    526  1.1  augustss 			}
    527  1.1  augustss 			error = midi_sleep(&sc->wchan, "mid wr");
    528  1.1  augustss 			if (error) {
    529  1.1  augustss 				splx(s);
    530  1.1  augustss 				return error;
    531  1.1  augustss 			}
    532  1.1  augustss 		}
    533  1.1  augustss 		used = mb->used;
    534  1.1  augustss 		inp = mb->inp;
    535  1.1  augustss 		splx(s);
    536  1.1  augustss 		cc = mb->usedhigh - used; 	/* maximum to write */
    537  1.1  augustss 		n = mb->end - inp;
    538  1.1  augustss 		if (n < cc)
    539  1.1  augustss 			cc = n;			/* don't write beyond end of buffer */
    540  1.1  augustss 		if (uio->uio_resid < cc)
    541  1.1  augustss 			cc = uio->uio_resid; 	/* and no more than we have */
    542  1.1  augustss 		error = uiomove(inp, cc, uio);
    543  1.1  augustss #ifdef MIDI_DEBUG
    544  1.1  augustss 		if (error)
    545  1.1  augustss 		        printf("midi_write:(1) uiomove failed %d; cc=%d inp=%p\n",
    546  1.1  augustss 			       error, cc, inp);
    547  1.1  augustss #endif
    548  1.1  augustss 		if (error)
    549  1.1  augustss 			break;
    550  1.1  augustss 		inp = mb->inp + cc;
    551  1.1  augustss 		if (inp >= mb->end)
    552  1.1  augustss 			inp = mb->start;
    553  1.1  augustss 		s = splaudio();
    554  1.1  augustss 		mb->inp = inp;
    555  1.1  augustss 		mb->used += cc;
    556  1.1  augustss 		splx(s);
    557  1.1  augustss 		error = midi_start_output(sc, 0);
    558  1.1  augustss 	}
    559  1.1  augustss 	return error;
    560  1.1  augustss }
    561  1.1  augustss 
    562  1.1  augustss int
    563  1.1  augustss midiioctl(dev, cmd, addr, flag, p)
    564  1.1  augustss 	dev_t dev;
    565  1.1  augustss 	u_long cmd;
    566  1.1  augustss 	caddr_t addr;
    567  1.1  augustss 	int flag;
    568  1.1  augustss 	struct proc *p;
    569  1.1  augustss {
    570  1.1  augustss 	int unit = MIDIUNIT(dev);
    571  1.1  augustss 	struct midi_softc *sc = midi_cd.cd_devs[unit];
    572  1.1  augustss 	struct midi_hw_if *hw = sc->hw_if;
    573  1.1  augustss 	int error;
    574  1.1  augustss 
    575  1.1  augustss 	DPRINTF(("midiioctl: %p cmd=0x%08lx\n", sc, cmd));
    576  1.1  augustss 	error = 0;
    577  1.1  augustss 	switch (cmd) {
    578  1.1  augustss 	case FIONBIO:
    579  1.1  augustss 		/* All handled in the upper FS layer. */
    580  1.1  augustss 		break;
    581  1.1  augustss 
    582  1.1  augustss 	case FIOASYNC:
    583  1.1  augustss 		if (*(int *)addr) {
    584  1.1  augustss 			if (sc->async)
    585  1.1  augustss 				return EBUSY;
    586  1.1  augustss 			sc->async = p;
    587  1.1  augustss 			DPRINTF(("midi_ioctl: FIOASYNC %p\n", p));
    588  1.1  augustss 		} else
    589  1.1  augustss 			sc->async = 0;
    590  1.1  augustss 		break;
    591  1.1  augustss 
    592  1.1  augustss #if 0
    593  1.1  augustss 	case MIDI_PRETIME:
    594  1.1  augustss 		/* XXX OSS
    595  1.1  augustss 		 * This should set up a read timeout, but that's
    596  1.1  augustss 		 * why we have poll(), so there's nothing yet. */
    597  1.1  augustss 		error = EINVAL;
    598  1.1  augustss 		break;
    599  1.1  augustss #endif
    600  1.1  augustss 
    601  1.1  augustss 	default:
    602  1.1  augustss 		if (hw->ioctl)
    603  1.2  augustss 			error = hw->ioctl(sc->hw_hdl, cmd, addr, flag, p);
    604  1.1  augustss 		else
    605  1.1  augustss 			error = EINVAL;
    606  1.1  augustss 		break;
    607  1.1  augustss 	}
    608  1.1  augustss 	return error;
    609  1.1  augustss }
    610  1.1  augustss 
    611  1.1  augustss int
    612  1.1  augustss midipoll(dev, events, p)
    613  1.1  augustss 	dev_t dev;
    614  1.1  augustss 	int events;
    615  1.1  augustss 	struct proc *p;
    616  1.1  augustss {
    617  1.1  augustss 	int unit = MIDIUNIT(dev);
    618  1.1  augustss 	struct midi_softc *sc = midi_cd.cd_devs[unit];
    619  1.1  augustss 	int revents = 0;
    620  1.1  augustss 	int s = splaudio();
    621  1.1  augustss 
    622  1.1  augustss 	DPRINTF(("midipoll: %p events=0x%x\n", sc, events));
    623  1.1  augustss 
    624  1.1  augustss 	if (events & (POLLIN | POLLRDNORM))
    625  1.1  augustss 		if (sc->inbuf.used > 0)
    626  1.1  augustss 			revents |= events & (POLLIN | POLLRDNORM);
    627  1.1  augustss 
    628  1.1  augustss 	if (events & (POLLOUT | POLLWRNORM))
    629  1.1  augustss 		if (sc->outbuf.used < sc->outbuf.usedhigh)
    630  1.1  augustss 			revents |= events & (POLLOUT | POLLWRNORM);
    631  1.1  augustss 
    632  1.1  augustss 	if (revents == 0) {
    633  1.1  augustss 		if (events & (POLLIN | POLLRDNORM))
    634  1.1  augustss 			selrecord(p, &sc->rsel);
    635  1.1  augustss 
    636  1.1  augustss 		if (events & (POLLOUT | POLLWRNORM))
    637  1.1  augustss 			selrecord(p, &sc->wsel);
    638  1.1  augustss 	}
    639  1.1  augustss 
    640  1.1  augustss 	splx(s);
    641  1.1  augustss 	return revents;
    642  1.1  augustss }
    643  1.1  augustss 
    644  1.1  augustss void
    645  1.1  augustss midi_getinfo(dev, mi)
    646  1.1  augustss 	dev_t dev;
    647  1.1  augustss 	struct midi_info *mi;
    648  1.1  augustss {
    649  1.1  augustss 	int unit = MIDIUNIT(dev);
    650  1.1  augustss 	struct midi_softc *sc;
    651  1.1  augustss 
    652  1.1  augustss 	if (unit >= midi_cd.cd_ndevs ||
    653  1.1  augustss 	    (sc = midi_cd.cd_devs[unit]) == NULL)
    654  1.1  augustss 		return;
    655  1.1  augustss 	sc->hw_if->getinfo(sc->hw_hdl, mi);
    656  1.1  augustss }
    657  1.1  augustss 
    658  1.1  augustss #endif /* NMIDI > 0 */
    659