diff options
author | Jonathan Gray <jsg@cvs.openbsd.org> | 2004-12-17 08:04:46 +0000 |
---|---|---|
committer | Jonathan Gray <jsg@cvs.openbsd.org> | 2004-12-17 08:04:46 +0000 |
commit | 2fc82003bd2a62998b3b16fa611b838c653b7c7f (patch) | |
tree | 6438353f47cc6d4242137321ae1dede45d1d57b7 /sys/dev/pci/eap.c | |
parent | 92c57630e3134659657a1da7cf05129313db750f (diff) |
Support for the eap MIDI UART from NetBSD.
Tested by serveral people. ok millert@, mickey@
Diffstat (limited to 'sys/dev/pci/eap.c')
-rw-r--r-- | sys/dev/pci/eap.c | 112 |
1 files changed, 111 insertions, 1 deletions
diff --git a/sys/dev/pci/eap.c b/sys/dev/pci/eap.c index 552909c9c7c..f53a41bec41 100644 --- a/sys/dev/pci/eap.c +++ b/sys/dev/pci/eap.c @@ -1,4 +1,4 @@ -/* $OpenBSD: eap.c,v 1.22 2004/12/07 03:17:42 jsg Exp $ */ +/* $OpenBSD: eap.c,v 1.23 2004/12/17 08:04:45 jsg Exp $ */ /* $NetBSD: eap.c,v 1.46 2001/09/03 15:07:37 reinoud Exp $ */ /* @@ -54,9 +54,12 @@ * ftp://ftp.alsa-project.org/pub/manuals/asahi_kasei/4531.pdf */ +#include "midi.h" + #include <sys/param.h> #include <sys/systm.h> #include <sys/kernel.h> +#include <sys/fcntl.h> #include <sys/malloc.h> #include <sys/device.h> #include <sys/proc.h> @@ -66,6 +69,7 @@ #include <sys/audioio.h> #include <dev/audio_if.h> +#include <dev/midi_if.h> #include <dev/mulaw.h> #include <dev/auconv.h> #include <dev/ic/ac97.h> @@ -127,6 +131,13 @@ struct eap_softc { char sc_rrun; #endif +#if NMIDI > 0 + void (*sc_iintr)(void *, int); /* midi input ready handler */ + void (*sc_ointr)(void *); /* midi output ready handler */ + void *sc_arg; + struct device *sc_mididev; +#endif + u_short sc_port[AK_NPORTS]; /* mirror of the hardware setting */ u_int sc_record_source; /* recording source mask */ u_int sc_output_source; /* output source mask */ @@ -143,8 +154,10 @@ enum ac97_host_flags eap_flags_codec(void *); int eap_allocmem(struct eap_softc *, size_t, size_t, struct eap_dma *); int eap_freemem(struct eap_softc *, struct eap_dma *); +#define EWRITE1(sc, r, x) bus_space_write_1((sc)->iot, (sc)->ioh, (r), (x)) #define EWRITE2(sc, r, x) bus_space_write_2((sc)->iot, (sc)->ioh, (r), (x)) #define EWRITE4(sc, r, x) bus_space_write_4((sc)->iot, (sc)->ioh, (r), (x)) +#define EREAD1(sc, r) bus_space_read_1((sc)->iot, (sc)->ioh, (r)) #define EREAD2(sc, r) bus_space_read_2((sc)->iot, (sc)->ioh, (r)) #define EREAD4(sc, r) bus_space_read_4((sc)->iot, (sc)->ioh, (r)) @@ -189,6 +202,13 @@ int eap1371_write_codec(void *sc, u_int8_t a, u_int16_t d); void eap1371_reset_codec(void *sc); int eap1371_get_portnum_by_name(struct eap_softc *, char *, char *, char *); +#if NMIDI > 0 +void eap_midi_close(void *); +void eap_midi_getinfo(void *, struct midi_info *); +int eap_midi_open(void *, int, void (*)(void *, int), + void (*)(void *), void *); +int eap_midi_output(void *, int); +#endif struct audio_hw_if eap1370_hw_if = { eap_open, @@ -248,6 +268,16 @@ struct audio_hw_if eap1371_hw_if = { eap_trigger_input, }; +#if NMIDI > 0 +struct midi_hw_if eap_midi_hw_if = { + eap_midi_open, + eap_midi_close, + eap_midi_output, + eap_midi_getinfo, + 0, /* ioctl */ +}; +#endif + struct audio_device eap_device = { "Ensoniq AudioPCI", "", @@ -689,6 +719,9 @@ eap_attach(struct device *parent, struct device *self, void *aux) } audio_attach_mi(eap_hw_if, sc, &sc->sc_dev); +#if NMIDI > 0 + sc->sc_mididev = midi_attach_mi(&eap_midi_hw_if, sc, &sc->sc_dev); +#endif } int @@ -764,6 +797,18 @@ eap_intr(void *p) if (sc->sc_pintr) sc->sc_pintr(sc->sc_parg); } +#if NMIDI > 0 + if ((intr & EAP_I_UART) && sc->sc_iintr != NULL) { + u_int32_t data; + + if (EREAD1(sc, EAP_UART_STATUS) & EAP_US_RXINT) { + while (EREAD1(sc, EAP_UART_STATUS) & EAP_US_RXRDY) { + data = EREAD1(sc, EAP_UART_DATA); + sc->sc_iintr(sc->sc_arg, data); + } + } + } +#endif return (1); } @@ -1640,3 +1685,68 @@ eap_flags_codec(void *v) return (sc->flags); } +#if NMIDI > 0 +int +eap_midi_open(void *addr, int flags, + void (*iintr)(void *, int), + void (*ointr)(void *), + void *arg) +{ + struct eap_softc *sc = addr; + u_int32_t uctrl; + + sc->sc_iintr = iintr; + sc->sc_ointr = ointr; + sc->sc_arg = arg; + + EWRITE4(sc, EAP_ICSC, EREAD4(sc, EAP_ICSC) | EAP_UART_EN); + uctrl = 0; + if (flags & FREAD) + uctrl |= EAP_UC_RXINTEN; +#if 0 + /* I don't understand ../midi.c well enough to use output interrupts */ + if (flags & FWRITE) + uctrl |= EAP_UC_TXINTEN; */ +#endif + EWRITE1(sc, EAP_UART_CONTROL, uctrl); + + return (0); +} + +void +eap_midi_close(void *addr) +{ + struct eap_softc *sc = addr; + + tsleep(sc, PWAIT, "eapclm", hz/10); /* give uart a chance to drain */ + EWRITE1(sc, EAP_UART_CONTROL, 0); + EWRITE4(sc, EAP_ICSC, EREAD4(sc, EAP_ICSC) & ~EAP_UART_EN); + + sc->sc_iintr = 0; + sc->sc_ointr = 0; +} + +int +eap_midi_output(void *addr, int d) +{ + struct eap_softc *sc = addr; + int x; + + for (x = 0; x != MIDI_BUSY_WAIT; x++) { + if (EREAD1(sc, EAP_UART_STATUS) & EAP_US_TXRDY) { + EWRITE1(sc, EAP_UART_DATA, d); + return (0); + } + delay(MIDI_BUSY_DELAY); + } + return (EIO); +} + +void +eap_midi_getinfo(void *addr, struct midi_info *mi) +{ + mi->name = "AudioPCI MIDI UART"; + mi->props = MIDI_PROP_CAN_INPUT; +} + +#endif |