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:
Alexander Leidinger 2006-05-27 16:51:37 +00:00
parent 206b17d711
commit f510d240d3
2 changed files with 165 additions and 0 deletions

View File

@ -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);

View File

@ -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