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