This diff adds support for midi ports certain envy-based cards have, tested on i386 only.
ok? -- Alexandre Index: share/man/man4/envy.4 =================================================================== RCS file: /cvs/src/share/man/man4/envy.4,v retrieving revision 1.13 diff -u -p -r1.13 envy.4 --- share/man/man4/envy.4 10 Sep 2010 07:44:15 -0000 1.13 +++ share/man/man4/envy.4 3 Oct 2010 22:02:50 -0000 @@ -23,6 +23,7 @@ .Sh SYNOPSIS .Cd "envy* at pci?" .Cd "audio* at envy?" +.Cd "midi* at envy?" .Sh DESCRIPTION The .Nm @@ -118,6 +119,7 @@ number of codecs physically present on t .Sh SEE ALSO .Xr audio 4 , .Xr intro 4 , +.Xr midi 4 , .Xr pci 4 .Sh HISTORY The @@ -125,7 +127,7 @@ The driver first appeared in .Ox 4.3 . .Sh BUGS -MIDI and S/PDIF transmitter/receivers are not yet supported. +S/PDIF transmitter/receiver is not supported. .Pp Ring buffer sizes are limited to 64kB, which can be limiting at high sample rates. Index: share/man/man4/midi.4 =================================================================== RCS file: /cvs/src/share/man/man4/midi.4,v retrieving revision 1.25 diff -u -p -r1.25 midi.4 --- share/man/man4/midi.4 31 Jul 2010 08:33:20 -0000 1.25 +++ share/man/man4/midi.4 3 Oct 2010 22:02:50 -0000 @@ -23,6 +23,7 @@ .Sh SYNOPSIS .Cd "midi* at autri?" .Cd "midi* at eap?" +.Cd "midi* at envy?" .Cd "midi* at mpu?" .Cd "midi* at sb?" .Cd "midi* at umidi?" @@ -219,6 +220,7 @@ The device is already open by another pr .Sh SEE ALSO .Xr autri 4 , .Xr eap 4 , +.Xr envy 4 , .Xr mpu 4 , .Xr sb 4 , .Xr sequencer 4 , Index: sys/arch/i386/conf/GENERIC =================================================================== RCS file: /cvs/src/sys/arch/i386/conf/GENERIC,v retrieving revision 1.698 diff -u -p -r1.698 GENERIC --- sys/arch/i386/conf/GENERIC 26 Sep 2010 20:39:08 -0000 1.698 +++ sys/arch/i386/conf/GENERIC 3 Oct 2010 22:02:52 -0000 @@ -742,6 +742,7 @@ midi* at ym? midi* at mpu? midi* at autri? midi* at eap? +midi* at envy? spkr0 at pcppi? # PC speaker Index: sys/arch/amd64/conf/GENERIC =================================================================== RCS file: /cvs/src/sys/arch/amd64/conf/GENERIC,v retrieving revision 1.304 diff -u -p -r1.304 GENERIC --- sys/arch/amd64/conf/GENERIC 26 Sep 2010 20:39:08 -0000 1.304 +++ sys/arch/amd64/conf/GENERIC 3 Oct 2010 22:02:52 -0000 @@ -558,6 +558,7 @@ mpu* at isa? port 0x330 # MIDI support #midi* at autri? midi* at eap? +midi* at envy? midi* at mpu? spkr0 at pcppi? # PC speaker Index: sys/dev/pci/envy.c =================================================================== RCS file: /cvs/src/sys/dev/pci/envy.c,v retrieving revision 1.41 diff -u -p -r1.41 envy.c --- sys/dev/pci/envy.c 8 Sep 2010 20:34:11 -0000 1.41 +++ sys/dev/pci/envy.c 3 Oct 2010 22:02:55 -0000 @@ -26,6 +26,7 @@ * */ +#include "midi.h" #include <sys/param.h> #include <sys/systm.h> #include <sys/device.h> @@ -34,6 +35,7 @@ #include <sys/malloc.h> #include <sys/kernel.h> #include <dev/audio_if.h> +#include <dev/midi_if.h> #include <dev/ic/ac97.h> #include <dev/pci/pcivar.h> #include <dev/pci/pcidevs.h> @@ -72,6 +74,7 @@ void envy_gpio_i2c_start_bit(struct envy void envy_gpio_i2c_stop_bit(struct envy_softc *, int, int); void envy_gpio_i2c_byte_out(struct envy_softc *, int, int, int); int envy_eeprom_gpioxxx(struct envy_softc *, int); +void envy_midi_wait(struct envy_softc *); void envy_reset(struct envy_softc *); int envy_codec_read(struct envy_softc *, int, int); void envy_codec_write(struct envy_softc *, int, int, int); @@ -105,6 +108,13 @@ int envy_query_devinfo(void *, struct mi int envy_get_port(void *, struct mixer_ctrl *); int envy_set_port(void *, struct mixer_ctrl *); int envy_get_props(void *); +#if NMIDI > 0 +int envy_midi_open(void *, int, void (*)(void *, int), + void (*)(void *), void *); +void envy_midi_close(void *); +int envy_midi_output(void *, int); +void envy_midi_getinfo(void *, struct midi_info *); +#endif int envy_ac97_wait(struct envy_softc *); int envy_ac97_attach_codec(void *, struct ac97_codec_if *); @@ -190,6 +200,17 @@ struct audio_hw_if envy_hw_if = { NULL }; +#if NMIDI > 0 +struct midi_hw_if envy_midi_hw_if = { + envy_midi_open, + envy_midi_close, + envy_midi_output, + NULL, /* flush */ + envy_midi_getinfo, + NULL /* ioctl */ +}; +#endif + struct pci_matchid envy_matchids[] = { { PCI_VENDOR_ICENSEMBLE, PCI_PRODUCT_ICENSEMBLE_ICE1712 }, { PCI_VENDOR_ICENSEMBLE, PCI_PRODUCT_ICENSEMBLE_VT172x } @@ -1229,6 +1250,23 @@ envy_ac97_flags_codec(void *hdl) } void +envy_midi_wait(struct envy_softc *sc) +{ + int i, st; + + for (i = 50;; i++) { + st = envy_ccs_read(sc, ENVY_CCS_MIDISTAT0); + if (!(st & ENVY_MIDISTAT_OBUSY(sc))) + break; + if (i == 0) { + printf("%s: midi wait timeout\n", DEVNAME(sc)); + break; + } + delay(10); + } +} + +void envy_reset(struct envy_softc *sc) { int i; @@ -1289,11 +1327,30 @@ envy_reset(struct envy_softc *sc) DPRINTF("%s: gpio_state = %02x\n", DEVNAME(sc), envy_gpio_getstate(sc)); + if (sc->isht) { + /* + * set water marks so we get an interrupt for each byte + */ + envy_ccs_write(sc, ENVY_CCS_MIDIWAT, 1); + envy_ccs_write(sc, ENVY_CCS_MIDIWAT, 1 | ENVY_CCS_MIDIWAT_RX); + } + + /* + * switch to UART mode + */ + envy_ccs_write(sc, ENVY_CCS_MIDISTAT0, 0xff); + envy_midi_wait(sc); + envy_ccs_write(sc, ENVY_CCS_MIDISTAT0, ENVY_MIDISTAT_UART); + envy_midi_wait(sc); + if (!sc->isht) + (void)envy_ccs_read(sc, ENVY_CCS_MIDIDATA0); + /* * clear all interrupts and unmask used ones */ envy_ccs_write(sc, ENVY_CCS_INTSTAT, 0xff); - envy_ccs_write(sc, ENVY_CCS_INTMASK, ~ENVY_CCS_INT_MT); + envy_ccs_write(sc, ENVY_CCS_INTMASK, + ~(ENVY_CCS_INT_MT | ENVY_CCS_INT_MIDI0)); if (sc->isht) { bus_space_write_1(sc->mt_iot, sc->mt_ioh, ENVY_MT_NSTREAM, 4 - sc->card->noch / 2); @@ -1551,6 +1608,11 @@ envyattach(struct device *parent, struct sc->card->name, sc->card->nich, sc->card->noch); envy_reset(sc); sc->audio = audio_attach_mi(&envy_hw_if, sc, &sc->dev); +#if NMIDI > 0 + if (!sc->isht || sc->eeprom[ENVY_EEPROM_CONF] & ENVY_CONF_MIDI) + sc->midi = midi_attach_mi(&envy_midi_hw_if, sc, &sc->dev); +#endif + } int @@ -1793,12 +1855,15 @@ int envy_intr(void *self) { struct envy_softc *sc = (struct envy_softc *)self; + int mintr, mstat, mdata; int st, err, ctl; - + int max; st = bus_space_read_1(sc->mt_iot, sc->mt_ioh, ENVY_MT_INTR); - if (st == 0) + mintr = envy_ccs_read(sc, ENVY_CCS_INTSTAT); + if (st == 0 && mintr == 0) return 0; + #ifdef ENVY_DEBUG if (sc->nintr < ENVY_NINTR) { sc->intrs[sc->nintr].iactive = sc->iactive; @@ -1816,6 +1881,19 @@ envy_intr(void *self) sc->nintr++; } #endif + envy_ccs_write(sc, ENVY_CCS_INTSTAT, mintr); + if (mintr & ENVY_CCS_INT_MIDI0) { + for (max = 128; max > 0; max--) { + mstat = envy_ccs_read(sc, ENVY_CCS_MIDISTAT0); + if (mstat & ENVY_MIDISTAT_IEMPTY(sc)) + break; + mdata = envy_ccs_read(sc, ENVY_CCS_MIDIDATA0); +#if NMIDI > 0 + if (sc->midi_in) + sc->midi_in(sc->midi_arg, mdata); +#endif + } + } if (st & ENVY_MT_INTR_PACK) { if (sc->oactive) sc->ointr(sc->oarg); @@ -2198,3 +2276,52 @@ envy_get_props(void *self) { return AUDIO_PROP_FULLDUPLEX | AUDIO_PROP_INDEPENDENT; } + +#if NMIDI > 0 +int +envy_midi_open(void *self, int flags, + void (*in)(void *, int), + void (*out)(void *), + void *arg) +{ + struct envy_softc *sc = (struct envy_softc *)self; + int s; + + s = splaudio(); + sc->midi_in = in; + sc->midi_out = out; + sc->midi_arg = arg; + splx(s); + return 0; +} + +void +envy_midi_close(void *self) +{ + struct envy_softc *sc = (struct envy_softc *)self; + int s; + + tsleep(sc, PWAIT, "envymid", hz / 10); + s = splaudio(); + sc->midi_in = NULL; + sc->midi_out = NULL; + splx(s); +} + +int +envy_midi_output(void *self, int data) +{ + struct envy_softc *sc = (struct envy_softc *)self; + + envy_midi_wait(sc); + envy_ccs_write(sc, ENVY_CCS_MIDIDATA0, data); + return 0; +} + +void +envy_midi_getinfo(void *self, struct midi_info *mi) +{ + mi->props = MIDI_PROP_CAN_INPUT; + mi->name = "Envy24 MIDI UART"; +} +#endif Index: sys/dev/pci/envyreg.h =================================================================== RCS file: /cvs/src/sys/dev/pci/envyreg.h,v retrieving revision 1.15 diff -u -p -r1.15 envyreg.h --- sys/dev/pci/envyreg.h 21 Jul 2010 07:11:55 -0000 1.15 +++ sys/dev/pci/envyreg.h 3 Oct 2010 22:02:55 -0000 @@ -32,14 +32,21 @@ #define ENVY_CTL_NATIVE 0x01 #define ENVY_CCS_INTMASK 0x01 #define ENVY_CCS_INT_MT 0x10 -#define ENVY_CCS_INT_MIDI1 0x80 -#define ENVY_CCS_INT_TMR 0x80 #define ENVY_CCS_INT_MIDI0 0x80 +#define ENVY_CCS_INT_MIDI1 0x20 /* Envy24 only */ #define ENVY_CCS_INTSTAT 0x02 #define ENVY_CCS_CONF 0x04 /* Envy24HT only */ #define ENVY_CCS_ACLINK 0x05 /* Envy24HT only */ #define ENVY_CCS_I2S 0x06 /* Envy24HT only */ #define ENVY_CCS_SPDIF 0x07 /* Envy24HT only */ +#define ENVY_CCS_MIDIDATA0 0x0c +#define ENVY_CCS_MIDISTAT0 0x0d +#define ENVY_CCS_MIDIDATA1 0x1c /* Envy24 only */ +#define ENVY_CCS_MIDISTAT1 0x1d /* Envy24 only */ +#define ENVY_CCS_MIDIWAT 0x0e /* Envy24HT only */ +#define ENVY_CCS_MIDIWAT_RX 0x20 +#define ENVY_CCS_MIDIDATA1 0x1c +#define ENVY_CCS_MIDISTAT1 0x1d #define ENVY_CCS_GPIODATA0 0x14 /* Envy24HT only */ #define ENVY_CCS_GPIODATA1 0x15 /* Envy24HT only */ #define ENVY_CCS_GPIODATA2 0x1e /* Envy24HT only */ @@ -79,12 +86,21 @@ * EEPROM bytes signification */ #define ENVY_EEPROM_CONF 6 +#define ENVY_CONF_MIDI 0x20 #define ENVY_EEPROM_ACLINK 7 #define ENVY_EEPROM_I2S 8 #define ENVY_EEPROM_SPDIF 9 #define ENVY_EEPROM_GPIOMASK(s) ((s)->isht ? 13 : 10) #define ENVY_EEPROM_GPIOST(s) ((s)->isht ? 16 : 11) #define ENVY_EEPROM_GPIODIR(s) ((s)->isht ? 10 : 12) + +/* + * MIDI status + */ +#define ENVY_MIDISTAT_IEMPTY(s) ((s)->isht ? 0x8 : 0x80) +#define ENVY_MIDISTAT_OBUSY(s) ((s)->isht ? 0x4 : 0x40) +#define ENVY_MIDISTAT_RESET 0xff +#define ENVY_MIDISTAT_UART 0x3f /* * MT registers for play/record params Index: sys/dev/pci/envyvar.h =================================================================== RCS file: /cvs/src/sys/dev/pci/envyvar.h,v retrieving revision 1.15 diff -u -p -r1.15 envyvar.h --- sys/dev/pci/envyvar.h 7 Mar 2010 18:55:45 -0000 1.15 +++ sys/dev/pci/envyvar.h 3 Oct 2010 22:02:55 -0000 @@ -22,6 +22,7 @@ #include <sys/device.h> #include <sys/time.h> #include <dev/audio_if.h> +#include <dev/midi_if.h> struct envy_softc; @@ -93,6 +94,12 @@ struct envy_softc { void *iarg; void (*ointr)(void *); void *oarg; +#if NMIDI > 0 + void (*midi_in)(void *, int); + void (*midi_out)(void *); + void *midi_arg; + struct device *midi; +#endif }; #define ENVY_MIX_CLASSIN 0 Index: sys/dev/pci/files.pci =================================================================== RCS file: /cvs/src/sys/dev/pci/files.pci,v retrieving revision 1.274 diff -u -p -r1.274 files.pci --- sys/dev/pci/files.pci 31 Jul 2010 08:33:20 -0000 1.274 +++ sys/dev/pci/files.pci 3 Oct 2010 22:02:56 -0000 @@ -133,7 +133,7 @@ file dev/pci/azalia.c azalia file dev/pci/azalia_codec.c azalia # VIA Envy24 (aka ICE1712) -device envy: audio, auconv, mulaw, ac97 +device envy: audio, auconv, mulaw, ac97, midibus attach envy at pci file dev/pci/envy.c envy