Commit the new (old) midi framework. It's based in parts on the NetBSD code,
but large parts are rewritten by matk and tanimura. This is old code, it's not maintained since 2003. We also don't have a maintainer for this! Yuriy Tsibizov took it and uses it in his emu10kx driver. Since the emu10kx driver will enter the tree "soon" (some bugs have to be fixed after Yuriy return from his holidays), I add it here already. This also contains some changes to emu10k1 and cmi, so if you're lucky, you can now make some kind of use of midi with those soundcards. To all those poor souls which don't have such a card: feel free to send patches, we don't have a maintainer for this. To those which miss a specific feature in the midi code: feel free to submit patches, we don't have a maintainer for this. Oh, did I already told that it would be nice if someone would take care of it? Maintainer with midi equipment wanted! :-) If you get LOR's, submit a PR and notify multimedia@ please. If you get panics, submit a PR with a backtrace (compile the sound system into your kernel instead of using modules in this case) and notify multimedia@ please. Written by: matk, tanimura Submitted by: "Yuriy Tsibizov" <Yuriy.Tsibizov@gfk.ru> Based upon: code from NetBSD
This commit is contained in:
parent
206b17d711
commit
f510d240d3
@ -48,8 +48,10 @@
|
||||
#include <dev/pci/pcivar.h>
|
||||
|
||||
#include <sys/sysctl.h>
|
||||
#include <dev/sound/midi/mpu401.h>
|
||||
|
||||
#include "mixer_if.h"
|
||||
#include "mpufoi_if.h"
|
||||
|
||||
SND_DECLARE_FILE("$FreeBSD$");
|
||||
|
||||
@ -112,6 +114,13 @@ struct sc_info {
|
||||
int spdif_enabled;
|
||||
unsigned int bufsz;
|
||||
struct sc_chinfo pch, rch;
|
||||
|
||||
struct mpu401 *mpu;
|
||||
mpu401_intr_t *mpu_intr;
|
||||
struct resource *mpu_reg;
|
||||
int mpu_regid;
|
||||
bus_space_tag_t mpu_bt;
|
||||
bus_space_handle_t mpu_bh;
|
||||
};
|
||||
|
||||
/* Channel caps */
|
||||
@ -551,6 +560,9 @@ cmi_intr(void *data)
|
||||
|
||||
}
|
||||
}
|
||||
if(sc->mpu_intr) {
|
||||
(sc->mpu_intr)(sc->mpu);
|
||||
}
|
||||
snd_mtxunlock(sc->lock);
|
||||
return;
|
||||
}
|
||||
@ -747,6 +759,74 @@ static kobj_method_t cmi_mixer_methods[] = {
|
||||
};
|
||||
MIXER_DECLARE(cmi_mixer);
|
||||
|
||||
/*
|
||||
* mpu401 functions
|
||||
*/
|
||||
|
||||
static unsigned char
|
||||
cmi_mread(void *arg, struct sc_info *sc, int reg)
|
||||
{
|
||||
unsigned int d;
|
||||
|
||||
d = bus_space_read_1(0,0, 0x330 + reg);
|
||||
/* printf("cmi_mread: reg %x %x\n",reg, d);
|
||||
*/
|
||||
return d;
|
||||
}
|
||||
|
||||
static void
|
||||
cmi_mwrite(void *arg, struct sc_info *sc, int reg, unsigned char b)
|
||||
{
|
||||
|
||||
bus_space_write_1(0,0,0x330 + reg , b);
|
||||
}
|
||||
|
||||
static int
|
||||
cmi_muninit(void *arg, struct sc_info *sc)
|
||||
{
|
||||
|
||||
snd_mtxlock(sc->lock);
|
||||
sc->mpu_intr = 0;
|
||||
sc->mpu = 0;
|
||||
snd_mtxunlock(sc->lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static kobj_method_t cmi_mpu_methods[] = {
|
||||
KOBJMETHOD(mpufoi_read, cmi_mread),
|
||||
KOBJMETHOD(mpufoi_write, cmi_mwrite),
|
||||
KOBJMETHOD(mpufoi_uninit, cmi_muninit),
|
||||
{ 0, 0 }
|
||||
};
|
||||
|
||||
DEFINE_CLASS(cmi_mpu, cmi_mpu_methods, 0);
|
||||
|
||||
static void
|
||||
cmi_midiattach(struct sc_info *sc) {
|
||||
/*
|
||||
const struct {
|
||||
int port,bits;
|
||||
} *p, ports[] = {
|
||||
{0x330,0},
|
||||
{0x320,1},
|
||||
{0x310,2},
|
||||
{0x300,3},
|
||||
{0,0} } ;
|
||||
Notes, CMPCI_REG_VMPUSEL sets the io port for the mpu. Does
|
||||
anyone know how to bus_space tag?
|
||||
*/
|
||||
cmi_clr4(sc, CMPCI_REG_FUNC_1, CMPCI_REG_UART_ENABLE);
|
||||
cmi_clr4(sc, CMPCI_REG_LEGACY_CTRL,
|
||||
CMPCI_REG_VMPUSEL_MASK << CMPCI_REG_VMPUSEL_SHIFT);
|
||||
cmi_set4(sc, CMPCI_REG_LEGACY_CTRL,
|
||||
0 << CMPCI_REG_VMPUSEL_SHIFT );
|
||||
cmi_set4(sc, CMPCI_REG_FUNC_1, CMPCI_REG_UART_ENABLE);
|
||||
sc->mpu = mpu401_init(&cmi_mpu_class, sc, cmi_intr, &sc->mpu_intr);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
/* Power and reset */
|
||||
|
||||
@ -802,6 +882,10 @@ cmi_uninit(struct sc_info *sc)
|
||||
CMPCI_REG_TDMA_INTR_ENABLE);
|
||||
cmi_clr4(sc, CMPCI_REG_FUNC_0,
|
||||
CMPCI_REG_CH0_ENABLE | CMPCI_REG_CH1_ENABLE);
|
||||
cmi_clr4(sc, CMPCI_REG_FUNC_1, CMPCI_REG_UART_ENABLE);
|
||||
|
||||
if( sc->mpu )
|
||||
sc->mpu_intr = 0;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
@ -857,6 +941,8 @@ cmi_attach(device_t dev)
|
||||
sc->st = rman_get_bustag(sc->reg);
|
||||
sc->sh = rman_get_bushandle(sc->reg);
|
||||
|
||||
cmi_midiattach(sc);
|
||||
|
||||
sc->irqid = 0;
|
||||
sc->irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &sc->irqid,
|
||||
RF_ACTIVE | RF_SHAREABLE);
|
||||
@ -936,7 +1022,12 @@ cmi_detach(device_t dev)
|
||||
bus_dma_tag_destroy(sc->parent_dmat);
|
||||
bus_teardown_intr(dev, sc->irq, sc->ih);
|
||||
bus_release_resource(dev, SYS_RES_IRQ, sc->irqid, sc->irq);
|
||||
if(sc->mpu)
|
||||
mpu401_uninit(sc->mpu);
|
||||
bus_release_resource(dev, SYS_RES_IOPORT, sc->regid, sc->reg);
|
||||
if (sc->mpu_reg)
|
||||
bus_release_resource(dev, SYS_RES_IOPORT, sc->mpu_regid, sc->mpu_reg);
|
||||
|
||||
snd_mtxfree(sc->lock);
|
||||
free(sc, M_DEVBUF);
|
||||
|
||||
@ -1007,4 +1098,5 @@ static driver_t cmi_driver = {
|
||||
|
||||
DRIVER_MODULE(snd_cmi, pci, cmi_driver, pcm_devclass, 0, 0);
|
||||
MODULE_DEPEND(snd_cmi, sound, SOUND_MINVER, SOUND_PREFVER, SOUND_MAXVER);
|
||||
MODULE_DEPEND(snd_cmi, midi, 1,1,1);
|
||||
MODULE_VERSION(snd_cmi, 1);
|
||||
|
@ -35,6 +35,9 @@
|
||||
#include <dev/pci/pcivar.h>
|
||||
#include <sys/queue.h>
|
||||
|
||||
#include <dev/sound/midi/mpu401.h>
|
||||
#include "mpufoi_if.h"
|
||||
|
||||
SND_DECLARE_FILE("$FreeBSD$");
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
@ -137,6 +140,9 @@ struct sc_info {
|
||||
struct emu_voice voice[64];
|
||||
struct sc_pchinfo pch[EMU_MAX_CHANS];
|
||||
struct sc_rchinfo rch[3];
|
||||
struct mpu401 *mpu;
|
||||
mpu401_intr_t *mpu_intr;
|
||||
int mputx;
|
||||
};
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
@ -1059,8 +1065,65 @@ static kobj_method_t emurchan_methods[] = {
|
||||
};
|
||||
CHANNEL_DECLARE(emurchan);
|
||||
|
||||
static unsigned char
|
||||
emu_mread(void *arg, struct sc_info *sc, int reg)
|
||||
{
|
||||
unsigned int d;
|
||||
|
||||
d = emu_rd(sc, 0x18 + reg, 1);
|
||||
return d;
|
||||
}
|
||||
|
||||
static void
|
||||
emu_mwrite(void *arg, struct sc_info *sc, int reg, unsigned char b)
|
||||
{
|
||||
|
||||
emu_wr(sc, 0x18 + reg, b, 1);
|
||||
}
|
||||
|
||||
static int
|
||||
emu_muninit(void *arg, struct sc_info *sc)
|
||||
{
|
||||
|
||||
snd_mtxlock(sc->lock);
|
||||
sc->mpu_intr = 0;
|
||||
snd_mtxunlock(sc->lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static kobj_method_t emu_mpu_methods[] = {
|
||||
KOBJMETHOD(mpufoi_read, emu_mread),
|
||||
KOBJMETHOD(mpufoi_write, emu_mwrite),
|
||||
KOBJMETHOD(mpufoi_uninit, emu_muninit),
|
||||
{ 0, 0 }
|
||||
};
|
||||
|
||||
DEFINE_CLASS(emu_mpu, emu_mpu_methods, 0);
|
||||
|
||||
static void
|
||||
emu_intr2(void *p)
|
||||
{
|
||||
struct sc_info *sc = (struct sc_info *)p;
|
||||
|
||||
if (sc->mpu_intr)
|
||||
(sc->mpu_intr)(sc->mpu);
|
||||
}
|
||||
|
||||
static void
|
||||
emu_midiattach(struct sc_info *sc)
|
||||
{
|
||||
int i;
|
||||
|
||||
i = emu_rd(sc, INTE, 4);
|
||||
i |= INTE_MIDIRXENABLE;
|
||||
emu_wr(sc, INTE, i, 4);
|
||||
|
||||
sc->mpu = mpu401_init(&emu_mpu_class, sc, emu_intr2, &sc->mpu_intr);
|
||||
}
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* The interrupt handler */
|
||||
|
||||
static void
|
||||
emu_intr(void *data)
|
||||
{
|
||||
@ -1100,6 +1163,11 @@ emu_intr(void *data)
|
||||
#endif
|
||||
}
|
||||
|
||||
if (stat & IPR_MIDIRECVBUFEMPTY)
|
||||
if (sc->mpu_intr) {
|
||||
(sc->mpu_intr)(sc->mpu);
|
||||
ack |= IPR_MIDIRECVBUFEMPTY | IPR_MIDITRANSBUFEMPTY;
|
||||
}
|
||||
if (stat & ~ack)
|
||||
device_printf(sc->dev, "dodgy irq: %x (harmless)\n",
|
||||
stat & ~ack);
|
||||
@ -1871,6 +1939,8 @@ emu_uninit(struct sc_info *sc)
|
||||
emu_free(sc, sc->mem.ptb_pages);
|
||||
emu_free(sc, sc->mem.silent_page);
|
||||
|
||||
if(sc->mpu)
|
||||
mpu401_uninit(sc->mpu);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -1963,6 +2033,8 @@ emu_pci_attach(device_t dev)
|
||||
gotmic = (ac97_getcaps(codec) & AC97_CAP_MICCHANNEL) ? 1 : 0;
|
||||
if (mixer_init(dev, ac97_getmixerclass(), codec) == -1) goto bad;
|
||||
|
||||
emu_midiattach(sc);
|
||||
|
||||
i = 0;
|
||||
sc->irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &i,
|
||||
RF_ACTIVE | RF_SHAREABLE);
|
||||
@ -2041,6 +2113,7 @@ DRIVER_MODULE(snd_emu10k1, pci, emu_driver, pcm_devclass, 0, 0);
|
||||
DRIVER_MODULE(snd_emu10k1, cardbus, emu_driver, pcm_devclass, 0, 0);
|
||||
MODULE_DEPEND(snd_emu10k1, sound, SOUND_MINVER, SOUND_PREFVER, SOUND_MAXVER);
|
||||
MODULE_VERSION(snd_emu10k1, 1);
|
||||
MODULE_DEPEND(snd_emu10k1, midi, 1, 1, 1);
|
||||
|
||||
/* dummy driver to silence the joystick device */
|
||||
static int
|
||||
|
Loading…
x
Reference in New Issue
Block a user