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

Reply via email to