[Midnightbsd-cvs] src: dev/sound: Update sound code
laffer1 at midnightbsd.org
laffer1 at midnightbsd.org
Tue Dec 2 22:05:16 EST 2008
Log Message:
-----------
Update sound code
Modified Files:
--------------
src/sys/dev/sound:
chip.h (r1.2 -> r1.3)
driver.c (r1.2 -> r1.3)
src/sys/dev/sound/isa:
ad1816.c (r1.3 -> r1.4)
ad1816.h (r1.2 -> r1.3)
ess.c (r1.2 -> r1.3)
gusc.c (r1.2 -> r1.3)
mss.c (r1.3 -> r1.4)
mss.h (r1.2 -> r1.3)
sb.h (r1.2 -> r1.3)
sb16.c (r1.2 -> r1.3)
sb8.c (r1.2 -> r1.3)
sbc.c (r1.2 -> r1.3)
sndbuf_dma.c (r1.2 -> r1.3)
src/sys/dev/sound/pci:
als4000.c (r1.2 -> r1.3)
als4000.h (r1.2 -> r1.3)
atiixp.c (r1.3 -> r1.4)
atiixp.h (r1.3 -> r1.4)
au88x0.c (r1.2 -> r1.3)
au88x0.h (r1.2 -> r1.3)
aureal.c (r1.2 -> r1.3)
aureal.h (r1.2 -> r1.3)
cmi.c (r1.2 -> r1.3)
cmireg.h (r1.2 -> r1.3)
cs4281.c (r1.2 -> r1.3)
cs4281.h (r1.2 -> r1.3)
csa.c (r1.2 -> r1.3)
csapcm.c (r1.3 -> r1.4)
csareg.h (r1.2 -> r1.3)
csavar.h (r1.2 -> r1.3)
ds1-fw.h (r1.2 -> r1.3)
ds1.c (r1.2 -> r1.3)
ds1.h (r1.2 -> r1.3)
emu10k1.c (r1.2 -> r1.3)
es137x.c (r1.2 -> r1.3)
es137x.h (r1.2 -> r1.3)
fm801.c (r1.2 -> r1.3)
ich.c (r1.3 -> r1.4)
ich.h (r1.2 -> r1.3)
maestro.c (r1.2 -> r1.3)
maestro3.c (r1.2 -> r1.3)
maestro_reg.h (r1.2 -> r1.3)
neomagic-coeff.h (r1.2 -> r1.3)
neomagic.c (r1.2 -> r1.3)
neomagic.h (r1.2 -> r1.3)
solo.c (r1.2 -> r1.3)
t4dwave.c (r1.2 -> r1.3)
t4dwave.h (r1.2 -> r1.3)
via8233.c (r1.3 -> r1.4)
via8233.h (r1.2 -> r1.3)
via82c686.c (r1.2 -> r1.3)
via82c686.h (r1.2 -> r1.3)
vibes.c (r1.2 -> r1.3)
vibes.h (r1.2 -> r1.3)
src/sys/dev/sound/pci/hda:
hda_reg.h (r1.1 -> r1.2)
hdac.c (r1.1 -> r1.2)
hdac.h (r1.1 -> r1.2)
hdac_private.h (r1.1 -> r1.2)
hdac_reg.h (r1.1 -> r1.2)
src/sys/dev/sound/pcm:
ac97.c (r1.2 -> r1.3)
ac97.h (r1.2 -> r1.3)
ac97_if.m (r1.2 -> r1.3)
ac97_patch.c (r1.2 -> r1.3)
ac97_patch.h (r1.2 -> r1.3)
buffer.c (r1.2 -> r1.3)
buffer.h (r1.2 -> r1.3)
channel.c (r1.3 -> r1.4)
channel.h (r1.2 -> r1.3)
channel_if.m (r1.2 -> r1.3)
dsp.c (r1.3 -> r1.4)
dsp.h (r1.2 -> r1.3)
fake.c (r1.2 -> r1.3)
feeder.c (r1.3 -> r1.4)
feeder.h (r1.2 -> r1.3)
feeder_fmt.c (r1.2 -> r1.3)
feeder_if.m (r1.2 -> r1.3)
feeder_rate.c (r1.2 -> r1.3)
feeder_volume.c (r1.2 -> r1.3)
mixer.c (r1.3 -> r1.4)
mixer.h (r1.2 -> r1.3)
mixer_if.m (r1.2 -> r1.3)
sndstat.c (r1.2 -> r1.3)
sound.c (r1.3 -> r1.4)
sound.h (r1.3 -> r1.4)
vchan.c (r1.3 -> r1.4)
vchan.h (r1.2 -> r1.3)
src/sys/dev/sound/sbus:
apcdmareg.h (r1.2 -> r1.3)
cs4231.c (r1.2 -> r1.3)
cs4231.h (r1.2 -> r1.3)
src/sys/dev/sound/usb:
uaudio.c (r1.3 -> r1.4)
uaudio.h (r1.2 -> r1.3)
uaudio_pcm.c (r1.2 -> r1.3)
uaudioreg.h (r1.2 -> r1.3)
Added Files:
-----------
src/sys/dev/sound/pci:
emu10kx-midi.c (r1.1)
emu10kx-pcm.c (r1.1)
emu10kx.c (r1.1)
emu10kx.h (r1.1)
envy24.c (r1.1)
envy24.h (r1.1)
envy24ht.c (r1.1)
envy24ht.h (r1.1)
spicds.c (r1.1)
spicds.h (r1.1)
-------------- next part --------------
Index: ds1.c
===================================================================
RCS file: /home/cvs/src/sys/dev/sound/pci/ds1.c,v
retrieving revision 1.2
retrieving revision 1.3
diff -L sys/dev/sound/pci/ds1.c -L sys/dev/sound/pci/ds1.c -u -r1.2 -r1.3
--- sys/dev/sound/pci/ds1.c
+++ sys/dev/sound/pci/ds1.c
@@ -1,28 +1,28 @@
/*-
-* Copyright (c) 2000 Cameron Grant <cg at freebsd.org>
-* All rights reserved.
-*
-* Redistribution and use in source and binary forms, with or without
-* modification, are permitted provided that the following conditions
-* are met:
-* 1. Redistributions of source code must retain the above copyright
-* notice, this list of conditions and the following disclaimer.
-* 2. Redistributions in binary form must reproduce the above copyright
-* notice, this list of conditions and the following disclaimer in the
-* documentation and/or other materials provided with the distribution.
-*
-* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
-* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
-* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
-* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
-* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHERIN CONTRACT, STRICT
-* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
-* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THEPOSSIBILITY OF
-* SUCH DAMAGE.
-*/
+ * Copyright (c) 2000 Cameron Grant <cg at freebsd.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHERIN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THEPOSSIBILITY OF
+ * SUCH DAMAGE.
+ */
#include <dev/sound/pcm/sound.h>
#include <dev/sound/pcm/ac97.h>
@@ -33,7 +33,7 @@
#include <dev/sound/pci/ds1.h>
#include <dev/sound/pci/ds1-fw.h>
-SND_DECLARE_FILE("$MidnightBSD$");
+SND_DECLARE_FILE("$FreeBSD: src/sys/dev/sound/pci/ds1.c,v 1.52 2007/06/17 06:10:41 ariff Exp $");
/* -------------------------------------------------------------------- */
@@ -43,118 +43,118 @@
#define DS1_BUFFSIZE 4096
struct pbank {
-volatile u_int32_t Format;
-volatile u_int32_t LoopDefault;
-volatile u_int32_t PgBase;
-volatile u_int32_t PgLoop;
-volatile u_int32_t PgLoopEnd;
-volatile u_int32_t PgLoopFrac;
-volatile u_int32_t PgDeltaEnd;
-volatile u_int32_t LpfKEnd;
-volatile u_int32_t EgGainEnd;
-volatile u_int32_t LchGainEnd;
-volatile u_int32_t RchGainEnd;
-volatile u_int32_t Effect1GainEnd;
-volatile u_int32_t Effect2GainEnd;
-volatile u_int32_t Effect3GainEnd;
-volatile u_int32_t LpfQ;
-volatile u_int32_t Status;
-volatile u_int32_t NumOfFrames;
-volatile u_int32_t LoopCount;
-volatile u_int32_t PgStart;
-volatile u_int32_t PgStartFrac;
-volatile u_int32_t PgDelta;
-volatile u_int32_t LpfK;
-volatile u_int32_t EgGain;
-volatile u_int32_t LchGain;
-volatile u_int32_t RchGain;
-volatile u_int32_t Effect1Gain;
-volatile u_int32_t Effect2Gain;
-volatile u_int32_t Effect3Gain;
-volatile u_int32_t LpfD1;
-volatile u_int32_t LpfD2;
+ volatile u_int32_t Format;
+ volatile u_int32_t LoopDefault;
+ volatile u_int32_t PgBase;
+ volatile u_int32_t PgLoop;
+ volatile u_int32_t PgLoopEnd;
+ volatile u_int32_t PgLoopFrac;
+ volatile u_int32_t PgDeltaEnd;
+ volatile u_int32_t LpfKEnd;
+ volatile u_int32_t EgGainEnd;
+ volatile u_int32_t LchGainEnd;
+ volatile u_int32_t RchGainEnd;
+ volatile u_int32_t Effect1GainEnd;
+ volatile u_int32_t Effect2GainEnd;
+ volatile u_int32_t Effect3GainEnd;
+ volatile u_int32_t LpfQ;
+ volatile u_int32_t Status;
+ volatile u_int32_t NumOfFrames;
+ volatile u_int32_t LoopCount;
+ volatile u_int32_t PgStart;
+ volatile u_int32_t PgStartFrac;
+ volatile u_int32_t PgDelta;
+ volatile u_int32_t LpfK;
+ volatile u_int32_t EgGain;
+ volatile u_int32_t LchGain;
+ volatile u_int32_t RchGain;
+ volatile u_int32_t Effect1Gain;
+ volatile u_int32_t Effect2Gain;
+ volatile u_int32_t Effect3Gain;
+ volatile u_int32_t LpfD1;
+ volatile u_int32_t LpfD2;
};
struct rbank {
-volatile u_int32_t PgBase;
-volatile u_int32_t PgLoopEnd;
-volatile u_int32_t PgStart;
-volatile u_int32_t NumOfLoops;
+ volatile u_int32_t PgBase;
+ volatile u_int32_t PgLoopEnd;
+ volatile u_int32_t PgStart;
+ volatile u_int32_t NumOfLoops;
};
struct sc_info;
/* channel registers */
struct sc_pchinfo {
-int run, spd, dir, fmt;
-struct snd_dbuf *buffer;
-struct pcm_channel *channel;
-volatile struct pbank *lslot, *rslot;
-int lsnum, rsnum;
-struct sc_info *parent;
+ int run, spd, dir, fmt;
+ struct snd_dbuf *buffer;
+ struct pcm_channel *channel;
+ volatile struct pbank *lslot, *rslot;
+ int lsnum, rsnum;
+ struct sc_info *parent;
};
struct sc_rchinfo {
-int run, spd, dir, fmt, num;
-struct snd_dbuf *buffer;
-struct pcm_channel *channel;
-volatile struct rbank *slot;
-struct sc_info *parent;
+ int run, spd, dir, fmt, num;
+ struct snd_dbuf *buffer;
+ struct pcm_channel *channel;
+ volatile struct rbank *slot;
+ struct sc_info *parent;
};
/* device private data */
struct sc_info {
-device_t dev;
-u_int32_t type, rev;
-u_int32_t cd2id, ctrlbase;
-
-bus_space_tag_t st;
-bus_space_handle_t sh;
-bus_dma_tag_t buffer_dmat, control_dmat;
-bus_dmamap_t map;
-
-struct resource *reg, *irq;
-int regid, irqid;
-void *ih;
-struct mtx *lock;
-
-void *regbase;
-u_int32_t *pbase, pbankbase, pbanksize;
-volatile struct pbank *pbank[2 * 64];
-volatile struct rbank *rbank;
-int pslotfree, currbank, pchn, rchn;
-unsigned int bufsz;
+ device_t dev;
+ u_int32_t type, rev;
+ u_int32_t cd2id, ctrlbase;
+
+ bus_space_tag_t st;
+ bus_space_handle_t sh;
+ bus_dma_tag_t buffer_dmat, control_dmat;
+ bus_dmamap_t map;
+
+ struct resource *reg, *irq;
+ int regid, irqid;
+ void *ih;
+ struct mtx *lock;
+
+ void *regbase;
+ u_int32_t *pbase, pbankbase, pbanksize;
+ volatile struct pbank *pbank[2 * 64];
+ volatile struct rbank *rbank;
+ int pslotfree, currbank, pchn, rchn;
+ unsigned int bufsz;
-struct sc_pchinfo pch[DS1_CHANS];
-struct sc_rchinfo rch[2];
+ struct sc_pchinfo pch[DS1_CHANS];
+ struct sc_rchinfo rch[2];
};
struct {
-u_int32_t dev, subdev;
-char *name;
-u_int32_t *mcode;
+ u_int32_t dev, subdev;
+ char *name;
+ u_int32_t *mcode;
} ds_devs[] = {
-{0x00041073, 0, "Yamaha DS-1 (YMF724)", CntrlInst},
-{0x000d1073, 0, "Yamaha DS-1E (YMF724F)", CntrlInst1E},
-{0x00051073, 0, "Yamaha DS-1? (YMF734)", CntrlInst},
-{0x00081073, 0, "Yamaha DS-1? (YMF737)", CntrlInst},
-{0x00201073, 0, "Yamaha DS-1? (YMF738)", CntrlInst},
-{0x00061073, 0, "Yamaha DS-1? (YMF738_TEG)", CntrlInst},
-{0x000a1073, 0x00041073, "Yamaha DS-1 (YMF740)", CntrlInst},
-{0x000a1073, 0x000a1073, "Yamaha DS-1 (YMF740B)", CntrlInst},
-{0x000a1073, 0x53328086, "Yamaha DS-1 (YMF740I)", CntrlInst},
-{0x000a1073, 0, "Yamaha DS-1 (YMF740?)", CntrlInst},
-{0x000c1073, 0, "Yamaha DS-1E (YMF740C)", CntrlInst1E},
-{0x00101073, 0, "Yamaha DS-1E (YMF744)", CntrlInst1E},
-{0x00121073, 0, "Yamaha DS-1E (YMF754)", CntrlInst1E},
-{0, 0, NULL, NULL}
+ {0x00041073, 0, "Yamaha DS-1 (YMF724)", CntrlInst},
+ {0x000d1073, 0, "Yamaha DS-1E (YMF724F)", CntrlInst1E},
+ {0x00051073, 0, "Yamaha DS-1? (YMF734)", CntrlInst},
+ {0x00081073, 0, "Yamaha DS-1? (YMF737)", CntrlInst},
+ {0x00201073, 0, "Yamaha DS-1? (YMF738)", CntrlInst},
+ {0x00061073, 0, "Yamaha DS-1? (YMF738_TEG)", CntrlInst},
+ {0x000a1073, 0x00041073, "Yamaha DS-1 (YMF740)", CntrlInst},
+ {0x000a1073, 0x000a1073, "Yamaha DS-1 (YMF740B)", CntrlInst},
+ {0x000a1073, 0x53328086, "Yamaha DS-1 (YMF740I)", CntrlInst},
+ {0x000a1073, 0, "Yamaha DS-1 (YMF740?)", CntrlInst},
+ {0x000c1073, 0, "Yamaha DS-1E (YMF740C)", CntrlInst1E},
+ {0x00101073, 0, "Yamaha DS-1E (YMF744)", CntrlInst1E},
+ {0x00121073, 0, "Yamaha DS-1E (YMF754)", CntrlInst1E},
+ {0, 0, NULL, NULL}
};
/* -------------------------------------------------------------------- */
/*
-* prototypes
-*/
+ * prototypes
+ */
/* stuff */
static int ds_init(struct sc_info *);
@@ -167,24 +167,24 @@
/* -------------------------------------------------------------------- */
static u_int32_t ds_recfmt[] = {
-AFMT_U8,
-AFMT_STEREO | AFMT_U8,
-AFMT_S8,
-AFMT_STEREO | AFMT_S8,
-AFMT_S16_LE,
-AFMT_STEREO | AFMT_S16_LE,
-AFMT_U16_LE,
-AFMT_STEREO | AFMT_U16_LE,
-0
+ AFMT_U8,
+ AFMT_STEREO | AFMT_U8,
+ AFMT_S8,
+ AFMT_STEREO | AFMT_S8,
+ AFMT_S16_LE,
+ AFMT_STEREO | AFMT_S16_LE,
+ AFMT_U16_LE,
+ AFMT_STEREO | AFMT_U16_LE,
+ 0
};
static struct pcmchan_caps ds_reccaps = {4000, 48000, ds_recfmt, 0};
static u_int32_t ds_playfmt[] = {
-AFMT_U8,
-AFMT_STEREO | AFMT_U8,
-/* AFMT_S16_LE, */
-AFMT_STEREO | AFMT_S16_LE,
-0
+ AFMT_U8,
+ AFMT_STEREO | AFMT_U8,
+ /* AFMT_S16_LE, */
+ AFMT_STEREO | AFMT_S16_LE,
+ 0
};
static struct pcmchan_caps ds_playcaps = {4000, 96000, ds_playfmt, 0};
@@ -193,39 +193,39 @@
static u_int32_t
ds_rd(struct sc_info *sc, int regno, int size)
{
-switch (size) {
-case 1:
-return bus_space_read_1(sc->st, sc->sh, regno);
-case 2:
-return bus_space_read_2(sc->st, sc->sh, regno);
-case 4:
-return bus_space_read_4(sc->st, sc->sh, regno);
-default:
-return 0xffffffff;
-}
+ switch (size) {
+ case 1:
+ return bus_space_read_1(sc->st, sc->sh, regno);
+ case 2:
+ return bus_space_read_2(sc->st, sc->sh, regno);
+ case 4:
+ return bus_space_read_4(sc->st, sc->sh, regno);
+ default:
+ return 0xffffffff;
+ }
}
static void
ds_wr(struct sc_info *sc, int regno, u_int32_t data, int size)
{
-switch (size) {
-case 1:
-bus_space_write_1(sc->st, sc->sh, regno, data);
-break;
-case 2:
-bus_space_write_2(sc->st, sc->sh, regno, data);
-break;
-case 4:
-bus_space_write_4(sc->st, sc->sh, regno, data);
-break;
-}
+ switch (size) {
+ case 1:
+ bus_space_write_1(sc->st, sc->sh, regno, data);
+ break;
+ case 2:
+ bus_space_write_2(sc->st, sc->sh, regno, data);
+ break;
+ case 4:
+ bus_space_write_4(sc->st, sc->sh, regno, data);
+ break;
+ }
}
static void
wrl(struct sc_info *sc, u_int32_t *ptr, u_int32_t val)
{
-*(volatile u_int32_t *)ptr = val;
-bus_space_barrier(sc->st, sc->sh, 0, 0, BUS_SPACE_BARRIER_WRITE);
+ *(volatile u_int32_t *)ptr = val;
+ bus_space_barrier(sc->st, sc->sh, 0, 0, BUS_SPACE_BARRIER_WRITE);
}
/* -------------------------------------------------------------------- */
@@ -233,97 +233,97 @@
static int
ds_cdbusy(struct sc_info *sc, int sec)
{
-int i, reg;
+ int i, reg;
-reg = sec? YDSXGR_SECSTATUSADR : YDSXGR_PRISTATUSADR;
-i = YDSXG_AC97TIMEOUT;
-while (i > 0) {
-if (!(ds_rd(sc, reg, 2) & 0x8000))
-return 0;
-i--;
-}
-return ETIMEDOUT;
+ reg = sec? YDSXGR_SECSTATUSADR : YDSXGR_PRISTATUSADR;
+ i = YDSXG_AC97TIMEOUT;
+ while (i > 0) {
+ if (!(ds_rd(sc, reg, 2) & 0x8000))
+ return 0;
+ i--;
+ }
+ return ETIMEDOUT;
}
static u_int32_t
ds_initcd(kobj_t obj, void *devinfo)
{
-struct sc_info *sc = (struct sc_info *)devinfo;
-u_int32_t x;
+ struct sc_info *sc = (struct sc_info *)devinfo;
+ u_int32_t x;
-x = pci_read_config(sc->dev, PCIR_DSXGCTRL, 1);
-if (x & 0x03) {
-pci_write_config(sc->dev, PCIR_DSXGCTRL, x & ~0x03, 1);
-pci_write_config(sc->dev, PCIR_DSXGCTRL, x | 0x03, 1);
-pci_write_config(sc->dev, PCIR_DSXGCTRL, x & ~0x03, 1);
-/*
-* The YMF740 on some Intel motherboards requires a pretty
-* hefty delay after this reset for some reason... Otherwise:
-* "pcm0: ac97 codec init failed"
-* Maybe this is needed for all YMF740's?
-* 400ms and 500ms here seem to work, 300ms does not.
-*
-* do it for all chips -cg
-*/
-DELAY(500000);
-}
+ x = pci_read_config(sc->dev, PCIR_DSXGCTRL, 1);
+ if (x & 0x03) {
+ pci_write_config(sc->dev, PCIR_DSXGCTRL, x & ~0x03, 1);
+ pci_write_config(sc->dev, PCIR_DSXGCTRL, x | 0x03, 1);
+ pci_write_config(sc->dev, PCIR_DSXGCTRL, x & ~0x03, 1);
+ /*
+ * The YMF740 on some Intel motherboards requires a pretty
+ * hefty delay after this reset for some reason... Otherwise:
+ * "pcm0: ac97 codec init failed"
+ * Maybe this is needed for all YMF740's?
+ * 400ms and 500ms here seem to work, 300ms does not.
+ *
+ * do it for all chips -cg
+ */
+ DELAY(500000);
+ }
-return ds_cdbusy(sc, 0)? 0 : 1;
+ return ds_cdbusy(sc, 0)? 0 : 1;
}
static int
ds_rdcd(kobj_t obj, void *devinfo, int regno)
{
-struct sc_info *sc = (struct sc_info *)devinfo;
-int sec, cid, i;
-u_int32_t cmd, reg;
-
-sec = regno & 0x100;
-regno &= 0xff;
-cid = sec? (sc->cd2id << 8) : 0;
-reg = sec? YDSXGR_SECSTATUSDATA : YDSXGR_PRISTATUSDATA;
-if (sec && cid == 0)
-return 0xffffffff;
-
-cmd = YDSXG_AC97READCMD | cid | regno;
-ds_wr(sc, YDSXGR_AC97CMDADR, cmd, 2);
-
-if (ds_cdbusy(sc, sec))
-return 0xffffffff;
-
-if (sc->type == 11 && sc->rev < 2)
-for (i = 0; i < 600; i++)
-ds_rd(sc, reg, 2);
+ struct sc_info *sc = (struct sc_info *)devinfo;
+ int sec, cid, i;
+ u_int32_t cmd, reg;
+
+ sec = regno & 0x100;
+ regno &= 0xff;
+ cid = sec? (sc->cd2id << 8) : 0;
+ reg = sec? YDSXGR_SECSTATUSDATA : YDSXGR_PRISTATUSDATA;
+ if (sec && cid == 0)
+ return 0xffffffff;
+
+ cmd = YDSXG_AC97READCMD | cid | regno;
+ ds_wr(sc, YDSXGR_AC97CMDADR, cmd, 2);
+
+ if (ds_cdbusy(sc, sec))
+ return 0xffffffff;
+
+ if (sc->type == 11 && sc->rev < 2)
+ for (i = 0; i < 600; i++)
+ ds_rd(sc, reg, 2);
-return ds_rd(sc, reg, 2);
+ return ds_rd(sc, reg, 2);
}
static int
ds_wrcd(kobj_t obj, void *devinfo, int regno, u_int32_t data)
{
-struct sc_info *sc = (struct sc_info *)devinfo;
-int sec, cid;
-u_int32_t cmd;
-
-sec = regno & 0x100;
-regno &= 0xff;
-cid = sec? (sc->cd2id << 8) : 0;
-if (sec && cid == 0)
-return ENXIO;
-
-cmd = YDSXG_AC97WRITECMD | cid | regno;
-cmd <<= 16;
-cmd |= data;
-ds_wr(sc, YDSXGR_AC97CMDDATA, cmd, 4);
+ struct sc_info *sc = (struct sc_info *)devinfo;
+ int sec, cid;
+ u_int32_t cmd;
+
+ sec = regno & 0x100;
+ regno &= 0xff;
+ cid = sec? (sc->cd2id << 8) : 0;
+ if (sec && cid == 0)
+ return ENXIO;
+
+ cmd = YDSXG_AC97WRITECMD | cid | regno;
+ cmd <<= 16;
+ cmd |= data;
+ ds_wr(sc, YDSXGR_AC97CMDDATA, cmd, 4);
-return ds_cdbusy(sc, sec);
+ return ds_cdbusy(sc, sec);
}
static kobj_method_t ds_ac97_methods[] = {
-KOBJMETHOD(ac97_init, ds_initcd),
-KOBJMETHOD(ac97_read, ds_rdcd),
-KOBJMETHOD(ac97_write, ds_wrcd),
-{ 0, 0 }
+ KOBJMETHOD(ac97_init, ds_initcd),
+ KOBJMETHOD(ac97_read, ds_rdcd),
+ KOBJMETHOD(ac97_write, ds_wrcd),
+ { 0, 0 }
};
AC97_DECLARE(ds_ac97);
@@ -332,144 +332,144 @@
static void
ds_enadsp(struct sc_info *sc, int on)
{
-u_int32_t v, i;
+ u_int32_t v, i;
-v = on? 1 : 0;
-if (on) {
-ds_wr(sc, YDSXGR_CONFIG, 0x00000001, 4);
-} else {
-if (ds_rd(sc, YDSXGR_CONFIG, 4))
-ds_wr(sc, YDSXGR_CONFIG, 0x00000000, 4);
-i = YDSXG_WORKBITTIMEOUT;
-while (i > 0) {
-if (!(ds_rd(sc, YDSXGR_CONFIG, 4) & 0x00000002))
-break;
-i--;
-}
-}
+ v = on? 1 : 0;
+ if (on) {
+ ds_wr(sc, YDSXGR_CONFIG, 0x00000001, 4);
+ } else {
+ if (ds_rd(sc, YDSXGR_CONFIG, 4))
+ ds_wr(sc, YDSXGR_CONFIG, 0x00000000, 4);
+ i = YDSXG_WORKBITTIMEOUT;
+ while (i > 0) {
+ if (!(ds_rd(sc, YDSXGR_CONFIG, 4) & 0x00000002))
+ break;
+ i--;
+ }
+ }
}
static volatile struct pbank *
ds_allocpslot(struct sc_info *sc)
{
-int slot;
+ int slot;
-if (sc->pslotfree > 63)
-return NULL;
-slot = sc->pslotfree++;
-return sc->pbank[slot * 2];
+ if (sc->pslotfree > 63)
+ return NULL;
+ slot = sc->pslotfree++;
+ return sc->pbank[slot * 2];
}
static int
ds_initpbank(volatile struct pbank *pb, int ch, int b16, int stereo, u_int32_t rate, bus_addr_t base, u_int32_t len)
{
-u_int32_t lv[] = {1, 1, 0, 0, 0};
-u_int32_t rv[] = {1, 0, 1, 0, 0};
-u_int32_t e1[] = {0, 0, 0, 0, 0};
-u_int32_t e2[] = {1, 0, 0, 1, 0};
-u_int32_t e3[] = {1, 0, 0, 0, 1};
-int ss, i;
-u_int32_t delta;
-
-struct {
-int rate, fK, fQ;
-} speedinfo[] = {
-{ 100, 0x00570000, 0x35280000},
-{ 2000, 0x06aa0000, 0x34a70000},
-{ 8000, 0x18b20000, 0x32020000},
-{11025, 0x20930000, 0x31770000},
-{16000, 0x2b9a0000, 0x31390000},
-{22050, 0x35a10000, 0x31c90000},
-{32000, 0x3eaa0000, 0x33d00000},
+ u_int32_t lv[] = {1, 1, 0, 0, 0};
+ u_int32_t rv[] = {1, 0, 1, 0, 0};
+ u_int32_t e1[] = {0, 0, 0, 0, 0};
+ u_int32_t e2[] = {1, 0, 0, 1, 0};
+ u_int32_t e3[] = {1, 0, 0, 0, 1};
+ int ss, i;
+ u_int32_t delta;
+
+ struct {
+ int rate, fK, fQ;
+ } speedinfo[] = {
+ { 100, 0x00570000, 0x35280000},
+ { 2000, 0x06aa0000, 0x34a70000},
+ { 8000, 0x18b20000, 0x32020000},
+ {11025, 0x20930000, 0x31770000},
+ {16000, 0x2b9a0000, 0x31390000},
+ {22050, 0x35a10000, 0x31c90000},
+ {32000, 0x3eaa0000, 0x33d00000},
/* {44100, 0x04646000, 0x370a0000},
*/ {48000, 0x40000000, 0x40000000},
-};
+ };
-ss = b16? 1 : 0;
-ss += stereo? 1 : 0;
-delta = (65536 * rate) / 48000;
-i = 0;
-while (i < 7 && speedinfo[i].rate < rate)
-i++;
-
-pb->Format = stereo? 0x00010000 : 0;
-pb->Format |= b16? 0 : 0x80000000;
-pb->Format |= (stereo && (ch == 2 || ch == 4))? 0x00000001 : 0;
-pb->LoopDefault = 0;
-pb->PgBase = base? base : 0;
-pb->PgLoop = 0;
-pb->PgLoopEnd = len >> ss;
-pb->PgLoopFrac = 0;
-pb->Status = 0;
-pb->NumOfFrames = 0;
-pb->LoopCount = 0;
-pb->PgStart = 0;
-pb->PgStartFrac = 0;
-pb->PgDelta = pb->PgDeltaEnd = delta << 12;
-pb->LpfQ = speedinfo[i].fQ;
-pb->LpfK = pb->LpfKEnd = speedinfo[i].fK;
-pb->LpfD1 = pb->LpfD2 = 0;
-pb->EgGain = pb->EgGainEnd = 0x40000000;
-pb->LchGain = pb->LchGainEnd = lv[ch] * 0x40000000;
-pb->RchGain = pb->RchGainEnd = rv[ch] * 0x40000000;
-pb->Effect1Gain = pb->Effect1GainEnd = e1[ch] * 0x40000000;
-pb->Effect2Gain = pb->Effect2GainEnd = e2[ch] * 0x40000000;
-pb->Effect3Gain = pb->Effect3GainEnd = e3[ch] * 0x40000000;
+ ss = b16? 1 : 0;
+ ss += stereo? 1 : 0;
+ delta = (65536 * rate) / 48000;
+ i = 0;
+ while (i < 7 && speedinfo[i].rate < rate)
+ i++;
+
+ pb->Format = stereo? 0x00010000 : 0;
+ pb->Format |= b16? 0 : 0x80000000;
+ pb->Format |= (stereo && (ch == 2 || ch == 4))? 0x00000001 : 0;
+ pb->LoopDefault = 0;
+ pb->PgBase = base? base : 0;
+ pb->PgLoop = 0;
+ pb->PgLoopEnd = len >> ss;
+ pb->PgLoopFrac = 0;
+ pb->Status = 0;
+ pb->NumOfFrames = 0;
+ pb->LoopCount = 0;
+ pb->PgStart = 0;
+ pb->PgStartFrac = 0;
+ pb->PgDelta = pb->PgDeltaEnd = delta << 12;
+ pb->LpfQ = speedinfo[i].fQ;
+ pb->LpfK = pb->LpfKEnd = speedinfo[i].fK;
+ pb->LpfD1 = pb->LpfD2 = 0;
+ pb->EgGain = pb->EgGainEnd = 0x40000000;
+ pb->LchGain = pb->LchGainEnd = lv[ch] * 0x40000000;
+ pb->RchGain = pb->RchGainEnd = rv[ch] * 0x40000000;
+ pb->Effect1Gain = pb->Effect1GainEnd = e1[ch] * 0x40000000;
+ pb->Effect2Gain = pb->Effect2GainEnd = e2[ch] * 0x40000000;
+ pb->Effect3Gain = pb->Effect3GainEnd = e3[ch] * 0x40000000;
-return 0;
+ return 0;
}
static void
ds_enapslot(struct sc_info *sc, int slot, int go)
{
-wrl(sc, &sc->pbase[slot + 1], go? (sc->pbankbase + 2 * slot * sc->pbanksize) : 0);
-/* printf("pbase[%d] = 0x%xn", slot + 1, go? (sc->pbankbase + 2 * slot * sc->pbanksize) : 0); */
+ wrl(sc, &sc->pbase[slot + 1], go? (sc->pbankbase + 2 * slot * sc->pbanksize) : 0);
+ /* printf("pbase[%d] = 0x%x\n", slot + 1, go? (sc->pbankbase + 2 * slot * sc->pbanksize) : 0); */
}
static void
ds_setuppch(struct sc_pchinfo *ch)
{
-int stereo, b16, c, sz;
-bus_addr_t addr;
+ int stereo, b16, c, sz;
+ bus_addr_t addr;
-stereo = (ch->fmt & AFMT_STEREO)? 1 : 0;
-b16 = (ch->fmt & AFMT_16BIT)? 1 : 0;
-c = stereo? 1 : 0;
-addr = sndbuf_getbufaddr(ch->buffer);
-sz = sndbuf_getsize(ch->buffer);
-
-ds_initpbank(ch->lslot, c, stereo, b16, ch->spd, addr, sz);
-ds_initpbank(ch->lslot + 1, c, stereo, b16, ch->spd, addr, sz);
-ds_initpbank(ch->rslot, 2, stereo, b16, ch->spd, addr, sz);
-ds_initpbank(ch->rslot + 1, 2, stereo, b16, ch->spd, addr, sz);
+ stereo = (ch->fmt & AFMT_STEREO)? 1 : 0;
+ b16 = (ch->fmt & AFMT_16BIT)? 1 : 0;
+ c = stereo? 1 : 0;
+ addr = sndbuf_getbufaddr(ch->buffer);
+ sz = sndbuf_getsize(ch->buffer);
+
+ ds_initpbank(ch->lslot, c, stereo, b16, ch->spd, addr, sz);
+ ds_initpbank(ch->lslot + 1, c, stereo, b16, ch->spd, addr, sz);
+ ds_initpbank(ch->rslot, 2, stereo, b16, ch->spd, addr, sz);
+ ds_initpbank(ch->rslot + 1, 2, stereo, b16, ch->spd, addr, sz);
}
static void
ds_setuprch(struct sc_rchinfo *ch)
{
-struct sc_info *sc = ch->parent;
-int stereo, b16, i, sz, pri;
-u_int32_t x, y;
-bus_addr_t addr;
-
-stereo = (ch->fmt & AFMT_STEREO)? 1 : 0;
-b16 = (ch->fmt & AFMT_16BIT)? 1 : 0;
-addr = sndbuf_getbufaddr(ch->buffer);
-sz = sndbuf_getsize(ch->buffer);
-pri = (ch->num == DS1_RECPRIMARY)? 1 : 0;
-
-for (i = 0; i < 2; i++) {
-ch->slot[i].PgBase = addr;
-ch->slot[i].PgLoopEnd = sz;
-ch->slot[i].PgStart = 0;
-ch->slot[i].NumOfLoops = 0;
-}
-x = (b16? 0x00 : 0x01) | (stereo? 0x02 : 0x00);
-y = (48000 * 4096) / ch->spd;
-y--;
-/* printf("pri = %d, x = %d, y = %dn", pri, x, y); */
-ds_wr(sc, pri? YDSXGR_ADCFORMAT : YDSXGR_RECFORMAT, x, 4);
-ds_wr(sc, pri? YDSXGR_ADCSLOTSR : YDSXGR_RECSLOTSR, y, 4);
+ struct sc_info *sc = ch->parent;
+ int stereo, b16, i, sz, pri;
+ u_int32_t x, y;
+ bus_addr_t addr;
+
+ stereo = (ch->fmt & AFMT_STEREO)? 1 : 0;
+ b16 = (ch->fmt & AFMT_16BIT)? 1 : 0;
+ addr = sndbuf_getbufaddr(ch->buffer);
+ sz = sndbuf_getsize(ch->buffer);
+ pri = (ch->num == DS1_RECPRIMARY)? 1 : 0;
+
+ for (i = 0; i < 2; i++) {
+ ch->slot[i].PgBase = addr;
+ ch->slot[i].PgLoopEnd = sz;
+ ch->slot[i].PgStart = 0;
+ ch->slot[i].NumOfLoops = 0;
+ }
+ x = (b16? 0x00 : 0x01) | (stereo? 0x02 : 0x00);
+ y = (48000 * 4096) / ch->spd;
+ y--;
+ /* printf("pri = %d, x = %d, y = %d\n", pri, x, y); */
+ ds_wr(sc, pri? YDSXGR_ADCFORMAT : YDSXGR_RECFORMAT, x, 4);
+ ds_wr(sc, pri? YDSXGR_ADCSLOTSR : YDSXGR_RECSLOTSR, y, 4);
}
/* -------------------------------------------------------------------- */
@@ -477,129 +477,129 @@
static void *
ds1pchan_init(kobj_t obj, void *devinfo, struct snd_dbuf *b, struct pcm_channel *c, int dir)
{
-struct sc_info *sc = devinfo;
-struct sc_pchinfo *ch;
+ struct sc_info *sc = devinfo;
+ struct sc_pchinfo *ch;
-KASSERT(dir == PCMDIR_PLAY, ("ds1pchan_init: bad direction"));
+ KASSERT(dir == PCMDIR_PLAY, ("ds1pchan_init: bad direction"));
-ch = &sc->pch[sc->pchn++];
-ch->buffer = b;
-ch->parent = sc;
-ch->channel = c;
-ch->dir = dir;
-ch->fmt = AFMT_U8;
-ch->spd = 8000;
-ch->run = 0;
-if (sndbuf_alloc(ch->buffer, sc->buffer_dmat, sc->bufsz) != 0)
-return NULL;
-else {
-ch->lsnum = sc->pslotfree;
-ch->lslot = ds_allocpslot(sc);
-ch->rsnum = sc->pslotfree;
-ch->rslot = ds_allocpslot(sc);
-ds_setuppch(ch);
-return ch;
-}
+ ch = &sc->pch[sc->pchn++];
+ ch->buffer = b;
+ ch->parent = sc;
+ ch->channel = c;
+ ch->dir = dir;
+ ch->fmt = AFMT_U8;
+ ch->spd = 8000;
+ ch->run = 0;
+ if (sndbuf_alloc(ch->buffer, sc->buffer_dmat, 0, sc->bufsz) != 0)
+ return NULL;
+ else {
+ ch->lsnum = sc->pslotfree;
+ ch->lslot = ds_allocpslot(sc);
+ ch->rsnum = sc->pslotfree;
+ ch->rslot = ds_allocpslot(sc);
+ ds_setuppch(ch);
+ return ch;
+ }
}
static int
ds1pchan_setformat(kobj_t obj, void *data, u_int32_t format)
{
-struct sc_pchinfo *ch = data;
+ struct sc_pchinfo *ch = data;
-ch->fmt = format;
+ ch->fmt = format;
-return 0;
+ return 0;
}
static int
ds1pchan_setspeed(kobj_t obj, void *data, u_int32_t speed)
{
-struct sc_pchinfo *ch = data;
+ struct sc_pchinfo *ch = data;
-ch->spd = speed;
+ ch->spd = speed;
-return speed;
+ return speed;
}
static int
ds1pchan_setblocksize(kobj_t obj, void *data, u_int32_t blocksize)
{
-struct sc_pchinfo *ch = data;
-struct sc_info *sc = ch->parent;
-int drate;
-
-/* irq rate is fixed at 187.5hz */
-drate = ch->spd * sndbuf_getbps(ch->buffer);
-blocksize = roundup2((drate << 8) / DS1_IRQHZ, 4);
-sndbuf_resize(ch->buffer, sc->bufsz / blocksize, blocksize);
+ struct sc_pchinfo *ch = data;
+ struct sc_info *sc = ch->parent;
+ int drate;
+
+ /* irq rate is fixed at 187.5hz */
+ drate = ch->spd * sndbuf_getbps(ch->buffer);
+ blocksize = roundup2((drate << 8) / DS1_IRQHZ, 4);
+ sndbuf_resize(ch->buffer, sc->bufsz / blocksize, blocksize);
-return blocksize;
+ return blocksize;
}
/* semantic note: must start at beginning of buffer */
static int
ds1pchan_trigger(kobj_t obj, void *data, int go)
{
-struct sc_pchinfo *ch = data;
-struct sc_info *sc = ch->parent;
-int stereo;
-
-if (go == PCMTRIG_EMLDMAWR || go == PCMTRIG_EMLDMARD)
-return 0;
-stereo = (ch->fmt & AFMT_STEREO)? 1 : 0;
-if (go == PCMTRIG_START) {
-ch->run = 1;
-ds_setuppch(ch);
-ds_enapslot(sc, ch->lsnum, 1);
-ds_enapslot(sc, ch->rsnum, stereo);
-snd_mtxlock(sc->lock);
-ds_wr(sc, YDSXGR_MODE, 0x00000003, 4);
-snd_mtxunlock(sc->lock);
-} else {
-ch->run = 0;
-/* ds_setuppch(ch); */
-ds_enapslot(sc, ch->lsnum, 0);
-ds_enapslot(sc, ch->rsnum, 0);
-}
+ struct sc_pchinfo *ch = data;
+ struct sc_info *sc = ch->parent;
+ int stereo;
+
+ if (!PCMTRIG_COMMON(go))
+ return 0;
+ stereo = (ch->fmt & AFMT_STEREO)? 1 : 0;
+ if (go == PCMTRIG_START) {
+ ch->run = 1;
+ ds_setuppch(ch);
+ ds_enapslot(sc, ch->lsnum, 1);
+ ds_enapslot(sc, ch->rsnum, stereo);
+ snd_mtxlock(sc->lock);
+ ds_wr(sc, YDSXGR_MODE, 0x00000003, 4);
+ snd_mtxunlock(sc->lock);
+ } else {
+ ch->run = 0;
+ /* ds_setuppch(ch); */
+ ds_enapslot(sc, ch->lsnum, 0);
+ ds_enapslot(sc, ch->rsnum, 0);
+ }
-return 0;
+ return 0;
}
static int
ds1pchan_getptr(kobj_t obj, void *data)
{
-struct sc_pchinfo *ch = data;
-struct sc_info *sc = ch->parent;
-volatile struct pbank *bank;
-int ss;
-u_int32_t ptr;
-
-ss = (ch->fmt & AFMT_STEREO)? 1 : 0;
-ss += (ch->fmt & AFMT_16BIT)? 1 : 0;
-
-bank = ch->lslot + sc->currbank;
-/* printf("getptr: %dn", bank->PgStart << ss); */
-ptr = bank->PgStart;
-ptr <<= ss;
-return ptr;
+ struct sc_pchinfo *ch = data;
+ struct sc_info *sc = ch->parent;
+ volatile struct pbank *bank;
+ int ss;
+ u_int32_t ptr;
+
+ ss = (ch->fmt & AFMT_STEREO)? 1 : 0;
+ ss += (ch->fmt & AFMT_16BIT)? 1 : 0;
+
+ bank = ch->lslot + sc->currbank;
+ /* printf("getptr: %d\n", bank->PgStart << ss); */
+ ptr = bank->PgStart;
+ ptr <<= ss;
+ return ptr;
}
static struct pcmchan_caps *
ds1pchan_getcaps(kobj_t obj, void *data)
{
-return &ds_playcaps;
+ return &ds_playcaps;
}
static kobj_method_t ds1pchan_methods[] = {
-KOBJMETHOD(channel_init, ds1pchan_init),
-KOBJMETHOD(channel_setformat, ds1pchan_setformat),
-KOBJMETHOD(channel_setspeed, ds1pchan_setspeed),
-KOBJMETHOD(channel_setblocksize, ds1pchan_setblocksize),
-KOBJMETHOD(channel_trigger, ds1pchan_trigger),
-KOBJMETHOD(channel_getptr, ds1pchan_getptr),
-KOBJMETHOD(channel_getcaps, ds1pchan_getcaps),
-{ 0, 0 }
+ KOBJMETHOD(channel_init, ds1pchan_init),
+ KOBJMETHOD(channel_setformat, ds1pchan_setformat),
+ KOBJMETHOD(channel_setspeed, ds1pchan_setspeed),
+ KOBJMETHOD(channel_setblocksize, ds1pchan_setblocksize),
+ KOBJMETHOD(channel_trigger, ds1pchan_trigger),
+ KOBJMETHOD(channel_getptr, ds1pchan_getptr),
+ KOBJMETHOD(channel_getcaps, ds1pchan_getcaps),
+ { 0, 0 }
};
CHANNEL_DECLARE(ds1pchan);
@@ -608,118 +608,118 @@
static void *
ds1rchan_init(kobj_t obj, void *devinfo, struct snd_dbuf *b, struct pcm_channel *c, int dir)
{
-struct sc_info *sc = devinfo;
-struct sc_rchinfo *ch;
+ struct sc_info *sc = devinfo;
+ struct sc_rchinfo *ch;
-KASSERT(dir == PCMDIR_REC, ("ds1rchan_init: bad direction"));
+ KASSERT(dir == PCMDIR_REC, ("ds1rchan_init: bad direction"));
-ch = &sc->rch[sc->rchn];
-ch->num = sc->rchn++;
-ch->buffer = b;
-ch->parent = sc;
-ch->channel = c;
-ch->dir = dir;
-ch->fmt = AFMT_U8;
-ch->spd = 8000;
-if (sndbuf_alloc(ch->buffer, sc->buffer_dmat, sc->bufsz) != 0)
-return NULL;
-else {
-ch->slot = (ch->num == DS1_RECPRIMARY)? sc->rbank + 2: sc->rbank;
-ds_setuprch(ch);
-return ch;
-}
+ ch = &sc->rch[sc->rchn];
+ ch->num = sc->rchn++;
+ ch->buffer = b;
+ ch->parent = sc;
+ ch->channel = c;
+ ch->dir = dir;
+ ch->fmt = AFMT_U8;
+ ch->spd = 8000;
+ if (sndbuf_alloc(ch->buffer, sc->buffer_dmat, 0, sc->bufsz) != 0)
+ return NULL;
+ else {
+ ch->slot = (ch->num == DS1_RECPRIMARY)? sc->rbank + 2: sc->rbank;
+ ds_setuprch(ch);
+ return ch;
+ }
}
static int
ds1rchan_setformat(kobj_t obj, void *data, u_int32_t format)
{
-struct sc_rchinfo *ch = data;
+ struct sc_rchinfo *ch = data;
-ch->fmt = format;
+ ch->fmt = format;
-return 0;
+ return 0;
}
static int
ds1rchan_setspeed(kobj_t obj, void *data, u_int32_t speed)
{
-struct sc_rchinfo *ch = data;
+ struct sc_rchinfo *ch = data;
-ch->spd = speed;
+ ch->spd = speed;
-return speed;
+ return speed;
}
static int
ds1rchan_setblocksize(kobj_t obj, void *data, u_int32_t blocksize)
{
-struct sc_rchinfo *ch = data;
-struct sc_info *sc = ch->parent;
-int drate;
-
-/* irq rate is fixed at 187.5hz */
-drate = ch->spd * sndbuf_getbps(ch->buffer);
-blocksize = roundup2((drate << 8) / DS1_IRQHZ, 4);
-sndbuf_resize(ch->buffer, sc->bufsz / blocksize, blocksize);
+ struct sc_rchinfo *ch = data;
+ struct sc_info *sc = ch->parent;
+ int drate;
+
+ /* irq rate is fixed at 187.5hz */
+ drate = ch->spd * sndbuf_getbps(ch->buffer);
+ blocksize = roundup2((drate << 8) / DS1_IRQHZ, 4);
+ sndbuf_resize(ch->buffer, sc->bufsz / blocksize, blocksize);
-return blocksize;
+ return blocksize;
}
/* semantic note: must start at beginning of buffer */
static int
ds1rchan_trigger(kobj_t obj, void *data, int go)
{
-struct sc_rchinfo *ch = data;
-struct sc_info *sc = ch->parent;
-u_int32_t x;
-
-if (go == PCMTRIG_EMLDMAWR || go == PCMTRIG_EMLDMARD)
-return 0;
-if (go == PCMTRIG_START) {
-ch->run = 1;
-ds_setuprch(ch);
-snd_mtxlock(sc->lock);
-x = ds_rd(sc, YDSXGR_MAPOFREC, 4);
-x |= (ch->num == DS1_RECPRIMARY)? 0x02 : 0x01;
-ds_wr(sc, YDSXGR_MAPOFREC, x, 4);
-ds_wr(sc, YDSXGR_MODE, 0x00000003, 4);
-snd_mtxunlock(sc->lock);
-} else {
-ch->run = 0;
-snd_mtxlock(sc->lock);
-x = ds_rd(sc, YDSXGR_MAPOFREC, 4);
-x &= ~((ch->num == DS1_RECPRIMARY)? 0x02 : 0x01);
-ds_wr(sc, YDSXGR_MAPOFREC, x, 4);
-snd_mtxunlock(sc->lock);
-}
+ struct sc_rchinfo *ch = data;
+ struct sc_info *sc = ch->parent;
+ u_int32_t x;
+
+ if (!PCMTRIG_COMMON(go))
+ return 0;
+ if (go == PCMTRIG_START) {
+ ch->run = 1;
+ ds_setuprch(ch);
+ snd_mtxlock(sc->lock);
+ x = ds_rd(sc, YDSXGR_MAPOFREC, 4);
+ x |= (ch->num == DS1_RECPRIMARY)? 0x02 : 0x01;
+ ds_wr(sc, YDSXGR_MAPOFREC, x, 4);
+ ds_wr(sc, YDSXGR_MODE, 0x00000003, 4);
+ snd_mtxunlock(sc->lock);
+ } else {
+ ch->run = 0;
+ snd_mtxlock(sc->lock);
+ x = ds_rd(sc, YDSXGR_MAPOFREC, 4);
+ x &= ~((ch->num == DS1_RECPRIMARY)? 0x02 : 0x01);
+ ds_wr(sc, YDSXGR_MAPOFREC, x, 4);
+ snd_mtxunlock(sc->lock);
+ }
-return 0;
+ return 0;
}
static int
ds1rchan_getptr(kobj_t obj, void *data)
{
-struct sc_rchinfo *ch = data;
-struct sc_info *sc = ch->parent;
+ struct sc_rchinfo *ch = data;
+ struct sc_info *sc = ch->parent;
-return ch->slot[sc->currbank].PgStart;
+ return ch->slot[sc->currbank].PgStart;
}
static struct pcmchan_caps *
ds1rchan_getcaps(kobj_t obj, void *data)
{
-return &ds_reccaps;
+ return &ds_reccaps;
}
static kobj_method_t ds1rchan_methods[] = {
-KOBJMETHOD(channel_init, ds1rchan_init),
-KOBJMETHOD(channel_setformat, ds1rchan_setformat),
-KOBJMETHOD(channel_setspeed, ds1rchan_setspeed),
-KOBJMETHOD(channel_setblocksize, ds1rchan_setblocksize),
-KOBJMETHOD(channel_trigger, ds1rchan_trigger),
-KOBJMETHOD(channel_getptr, ds1rchan_getptr),
-KOBJMETHOD(channel_getcaps, ds1rchan_getcaps),
-{ 0, 0 }
+ KOBJMETHOD(channel_init, ds1rchan_init),
+ KOBJMETHOD(channel_setformat, ds1rchan_setformat),
+ KOBJMETHOD(channel_setspeed, ds1rchan_setspeed),
+ KOBJMETHOD(channel_setblocksize, ds1rchan_setblocksize),
+ KOBJMETHOD(channel_trigger, ds1rchan_trigger),
+ KOBJMETHOD(channel_getptr, ds1rchan_getptr),
+ KOBJMETHOD(channel_getcaps, ds1rchan_getcaps),
+ { 0, 0 }
};
CHANNEL_DECLARE(ds1rchan);
@@ -728,374 +728,373 @@
static void
ds_intr(void *p)
{
-struct sc_info *sc = (struct sc_info *)p;
-u_int32_t i, x;
+ struct sc_info *sc = (struct sc_info *)p;
+ u_int32_t i, x;
-snd_mtxlock(sc->lock);
-i = ds_rd(sc, YDSXGR_STATUS, 4);
-if (i & 0x00008000)
-device_printf(sc->dev, "timeout irqn");
-if (i & 0x80008000) {
-ds_wr(sc, YDSXGR_STATUS, i & 0x80008000, 4);
-sc->currbank = ds_rd(sc, YDSXGR_CTRLSELECT, 4) & 0x00000001;
-
-x = 0;
-for (i = 0; i < DS1_CHANS; i++) {
-if (sc->pch[i].run) {
-x = 1;
-snd_mtxunlock(sc->lock);
-chn_intr(sc->pch[i].channel);
-snd_mtxlock(sc->lock);
-}
-}
-for (i = 0; i < 2; i++) {
-if (sc->rch[i].run) {
-x = 1;
-snd_mtxunlock(sc->lock);
-chn_intr(sc->rch[i].channel);
-snd_mtxlock(sc->lock);
-}
-}
-i = ds_rd(sc, YDSXGR_MODE, 4);
-if (x)
-ds_wr(sc, YDSXGR_MODE, i | 0x00000002, 4);
+ snd_mtxlock(sc->lock);
+ i = ds_rd(sc, YDSXGR_STATUS, 4);
+ if (i & 0x00008000)
+ device_printf(sc->dev, "timeout irq\n");
+ if (i & 0x80008000) {
+ ds_wr(sc, YDSXGR_STATUS, i & 0x80008000, 4);
+ sc->currbank = ds_rd(sc, YDSXGR_CTRLSELECT, 4) & 0x00000001;
+
+ x = 0;
+ for (i = 0; i < DS1_CHANS; i++) {
+ if (sc->pch[i].run) {
+ x = 1;
+ snd_mtxunlock(sc->lock);
+ chn_intr(sc->pch[i].channel);
+ snd_mtxlock(sc->lock);
+ }
+ }
+ for (i = 0; i < 2; i++) {
+ if (sc->rch[i].run) {
+ x = 1;
+ snd_mtxunlock(sc->lock);
+ chn_intr(sc->rch[i].channel);
+ snd_mtxlock(sc->lock);
+ }
+ }
+ i = ds_rd(sc, YDSXGR_MODE, 4);
+ if (x)
+ ds_wr(sc, YDSXGR_MODE, i | 0x00000002, 4);
-}
-snd_mtxunlock(sc->lock);
+ }
+ snd_mtxunlock(sc->lock);
}
/* -------------------------------------------------------------------- */
/*
-* Probe and attach the card
-*/
+ * Probe and attach the card
+ */
static void
ds_setmap(void *arg, bus_dma_segment_t *segs, int nseg, int error)
{
-struct sc_info *sc = arg;
+ struct sc_info *sc = arg;
-sc->ctrlbase = error? 0 : (u_int32_t)segs->ds_addr;
+ sc->ctrlbase = error? 0 : (u_int32_t)segs->ds_addr;
-if (bootverbose) {
-printf("ds1: setmap (%lx, %lx), nseg=%d, error=%dn",
-(unsigned long)segs->ds_addr, (unsigned long)segs->ds_len,
-nseg, error);
-}
+ if (bootverbose) {
+ printf("ds1: setmap (%lx, %lx), nseg=%d, error=%d\n",
+ (unsigned long)segs->ds_addr, (unsigned long)segs->ds_len,
+ nseg, error);
+ }
}
static int
ds_init(struct sc_info *sc)
{
-int i;
-u_int32_t *ci, r, pcs, rcs, ecs, ws, memsz, cb;
-u_int8_t *t;
-void *buf;
-
-ci = ds_devs[sc->type].mcode;
-
-ds_wr(sc, YDSXGR_NATIVEDACOUTVOL, 0x00000000, 4);
-ds_enadsp(sc, 0);
-ds_wr(sc, YDSXGR_MODE, 0x00010000, 4);
-ds_wr(sc, YDSXGR_MODE, 0x00000000, 4);
-ds_wr(sc, YDSXGR_MAPOFREC, 0x00000000, 4);
-ds_wr(sc, YDSXGR_MAPOFEFFECT, 0x00000000, 4);
-ds_wr(sc, YDSXGR_PLAYCTRLBASE, 0x00000000, 4);
-ds_wr(sc, YDSXGR_RECCTRLBASE, 0x00000000, 4);
-ds_wr(sc, YDSXGR_EFFCTRLBASE, 0x00000000, 4);
-r = ds_rd(sc, YDSXGR_GLOBALCTRL, 2);
-ds_wr(sc, YDSXGR_GLOBALCTRL, r & ~0x0007, 2);
-
-for (i = 0; i < YDSXG_DSPLENGTH; i += 4)
-ds_wr(sc, YDSXGR_DSPINSTRAM + i, DspInst[i >> 2], 4);
-
-for (i = 0; i < YDSXG_CTRLLENGTH; i += 4)
-ds_wr(sc, YDSXGR_CTRLINSTRAM + i, ci[i >> 2], 4);
-
-ds_enadsp(sc, 1);
-
-pcs = 0;
-for (i = 100; i > 0; i--) {
-pcs = ds_rd(sc, YDSXGR_PLAYCTRLSIZE, 4) << 2;
-if (pcs == sizeof(struct pbank))
-break;
-DELAY(1000);
-}
-if (pcs != sizeof(struct pbank)) {
-device_printf(sc->dev, "preposterous playctrlsize (%d)n", pcs);
-return -1;
-}
-rcs = ds_rd(sc, YDSXGR_RECCTRLSIZE, 4) << 2;
-ecs = ds_rd(sc, YDSXGR_EFFCTRLSIZE, 4) << 2;
-ws = ds_rd(sc, YDSXGR_WORKSIZE, 4) << 2;
-
-memsz = 64 * 2 * pcs + 2 * 2 * rcs + 5 * 2 * ecs + ws;
-memsz += (64 + 1) * 4;
-
-if (sc->regbase == NULL) {
-if (bus_dma_tag_create(NULL, 2, 0, BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR,
-NULL, NULL, memsz, 1, memsz, 0, NULL,
-NULL, &sc->control_dmat))
-return -1;
-if (bus_dmamem_alloc(sc->control_dmat, &buf, BUS_DMA_NOWAIT, &sc->map))
-return -1;
-if (bus_dmamap_load(sc->control_dmat, sc->map, buf, memsz, ds_setmap, sc, 0) || !sc->ctrlbase) {
-device_printf(sc->dev, "pcs=%d, rcs=%d, ecs=%d, ws=%d, memsz=%dn",
-pcs, rcs, ecs, ws, memsz);
-return -1;
-}
-sc->regbase = buf;
-} else
-buf = sc->regbase;
-
-cb = 0;
-t = buf;
-ds_wr(sc, YDSXGR_WORKBASE, sc->ctrlbase + cb, 4);
-cb += ws;
-sc->pbase = (u_int32_t *)(t + cb);
-/* printf("pbase = %p -> 0x%xn", sc->pbase, sc->ctrlbase + cb); */
-ds_wr(sc, YDSXGR_PLAYCTRLBASE, sc->ctrlbase + cb, 4);
-cb += (64 + 1) * 4;
-sc->rbank = (struct rbank *)(t + cb);
-ds_wr(sc, YDSXGR_RECCTRLBASE, sc->ctrlbase + cb, 4);
-cb += 2 * 2 * rcs;
-ds_wr(sc, YDSXGR_EFFCTRLBASE, sc->ctrlbase + cb, 4);
-cb += 5 * 2 * ecs;
-
-sc->pbankbase = sc->ctrlbase + cb;
-sc->pbanksize = pcs;
-for (i = 0; i < 64; i++) {
-wrl(sc, &sc->pbase[i + 1], 0);
-sc->pbank[i * 2] = (struct pbank *)(t + cb);
-/* printf("pbank[%d] = %p -> 0x%x; ", i * 2, (struct pbank *)(t + cb), sc->ctrlbase + cb - vtophys(t + cb)); */
-cb += pcs;
-sc->pbank[i * 2 + 1] = (struct pbank *)(t + cb);
-/* printf("pbank[%d] = %p -> 0x%xn", i * 2 + 1, (struct pbank *)(t + cb), sc->ctrlbase + cb - vtophys(t + cb)); */
-cb += pcs;
-}
-wrl(sc, &sc->pbase[0], DS1_CHANS * 2);
-
-sc->pchn = sc->rchn = 0;
-ds_wr(sc, YDSXGR_NATIVEDACOUTVOL, 0x3fff3fff, 4);
-ds_wr(sc, YDSXGR_NATIVEADCINVOL, 0x3fff3fff, 4);
-ds_wr(sc, YDSXGR_NATIVEDACINVOL, 0x3fff3fff, 4);
+ int i;
+ u_int32_t *ci, r, pcs, rcs, ecs, ws, memsz, cb;
+ u_int8_t *t;
+ void *buf;
+
+ ci = ds_devs[sc->type].mcode;
+
+ ds_wr(sc, YDSXGR_NATIVEDACOUTVOL, 0x00000000, 4);
+ ds_enadsp(sc, 0);
+ ds_wr(sc, YDSXGR_MODE, 0x00010000, 4);
+ ds_wr(sc, YDSXGR_MODE, 0x00000000, 4);
+ ds_wr(sc, YDSXGR_MAPOFREC, 0x00000000, 4);
+ ds_wr(sc, YDSXGR_MAPOFEFFECT, 0x00000000, 4);
+ ds_wr(sc, YDSXGR_PLAYCTRLBASE, 0x00000000, 4);
+ ds_wr(sc, YDSXGR_RECCTRLBASE, 0x00000000, 4);
+ ds_wr(sc, YDSXGR_EFFCTRLBASE, 0x00000000, 4);
+ r = ds_rd(sc, YDSXGR_GLOBALCTRL, 2);
+ ds_wr(sc, YDSXGR_GLOBALCTRL, r & ~0x0007, 2);
+
+ for (i = 0; i < YDSXG_DSPLENGTH; i += 4)
+ ds_wr(sc, YDSXGR_DSPINSTRAM + i, DspInst[i >> 2], 4);
+
+ for (i = 0; i < YDSXG_CTRLLENGTH; i += 4)
+ ds_wr(sc, YDSXGR_CTRLINSTRAM + i, ci[i >> 2], 4);
+
+ ds_enadsp(sc, 1);
+
+ pcs = 0;
+ for (i = 100; i > 0; i--) {
+ pcs = ds_rd(sc, YDSXGR_PLAYCTRLSIZE, 4) << 2;
+ if (pcs == sizeof(struct pbank))
+ break;
+ DELAY(1000);
+ }
+ if (pcs != sizeof(struct pbank)) {
+ device_printf(sc->dev, "preposterous playctrlsize (%d)\n", pcs);
+ return -1;
+ }
+ rcs = ds_rd(sc, YDSXGR_RECCTRLSIZE, 4) << 2;
+ ecs = ds_rd(sc, YDSXGR_EFFCTRLSIZE, 4) << 2;
+ ws = ds_rd(sc, YDSXGR_WORKSIZE, 4) << 2;
+
+ memsz = 64 * 2 * pcs + 2 * 2 * rcs + 5 * 2 * ecs + ws;
+ memsz += (64 + 1) * 4;
+
+ if (sc->regbase == NULL) {
+ if (bus_dma_tag_create(bus_get_dma_tag(sc->dev), 2, 0,
+ BUS_SPACE_MAXADDR_32BIT,
+ BUS_SPACE_MAXADDR,
+ NULL, NULL, memsz, 1, memsz, 0, NULL,
+ NULL, &sc->control_dmat))
+ return -1;
+ if (bus_dmamem_alloc(sc->control_dmat, &buf, BUS_DMA_NOWAIT, &sc->map))
+ return -1;
+ if (bus_dmamap_load(sc->control_dmat, sc->map, buf, memsz, ds_setmap, sc, 0) || !sc->ctrlbase) {
+ device_printf(sc->dev, "pcs=%d, rcs=%d, ecs=%d, ws=%d, memsz=%d\n",
+ pcs, rcs, ecs, ws, memsz);
+ return -1;
+ }
+ sc->regbase = buf;
+ } else
+ buf = sc->regbase;
+
+ cb = 0;
+ t = buf;
+ ds_wr(sc, YDSXGR_WORKBASE, sc->ctrlbase + cb, 4);
+ cb += ws;
+ sc->pbase = (u_int32_t *)(t + cb);
+ /* printf("pbase = %p -> 0x%x\n", sc->pbase, sc->ctrlbase + cb); */
+ ds_wr(sc, YDSXGR_PLAYCTRLBASE, sc->ctrlbase + cb, 4);
+ cb += (64 + 1) * 4;
+ sc->rbank = (struct rbank *)(t + cb);
+ ds_wr(sc, YDSXGR_RECCTRLBASE, sc->ctrlbase + cb, 4);
+ cb += 2 * 2 * rcs;
+ ds_wr(sc, YDSXGR_EFFCTRLBASE, sc->ctrlbase + cb, 4);
+ cb += 5 * 2 * ecs;
+
+ sc->pbankbase = sc->ctrlbase + cb;
+ sc->pbanksize = pcs;
+ for (i = 0; i < 64; i++) {
+ wrl(sc, &sc->pbase[i + 1], 0);
+ sc->pbank[i * 2] = (struct pbank *)(t + cb);
+ /* printf("pbank[%d] = %p -> 0x%x; ", i * 2, (struct pbank *)(t + cb), sc->ctrlbase + cb - vtophys(t + cb)); */
+ cb += pcs;
+ sc->pbank[i * 2 + 1] = (struct pbank *)(t + cb);
+ /* printf("pbank[%d] = %p -> 0x%x\n", i * 2 + 1, (struct pbank *)(t + cb), sc->ctrlbase + cb - vtophys(t + cb)); */
+ cb += pcs;
+ }
+ wrl(sc, &sc->pbase[0], DS1_CHANS * 2);
+
+ sc->pchn = sc->rchn = 0;
+ ds_wr(sc, YDSXGR_NATIVEDACOUTVOL, 0x3fff3fff, 4);
+ ds_wr(sc, YDSXGR_NATIVEADCINVOL, 0x3fff3fff, 4);
+ ds_wr(sc, YDSXGR_NATIVEDACINVOL, 0x3fff3fff, 4);
-return 0;
+ return 0;
}
static int
ds_uninit(struct sc_info *sc)
{
-ds_wr(sc, YDSXGR_NATIVEDACOUTVOL, 0x00000000, 4);
-ds_wr(sc, YDSXGR_NATIVEADCINVOL, 0, 4);
-ds_wr(sc, YDSXGR_NATIVEDACINVOL, 0, 4);
-ds_enadsp(sc, 0);
-ds_wr(sc, YDSXGR_MODE, 0x00010000, 4);
-ds_wr(sc, YDSXGR_MAPOFREC, 0x00000000, 4);
-ds_wr(sc, YDSXGR_MAPOFEFFECT, 0x00000000, 4);
-ds_wr(sc, YDSXGR_PLAYCTRLBASE, 0x00000000, 4);
-ds_wr(sc, YDSXGR_RECCTRLBASE, 0x00000000, 4);
-ds_wr(sc, YDSXGR_EFFCTRLBASE, 0x00000000, 4);
-ds_wr(sc, YDSXGR_GLOBALCTRL, 0, 2);
+ ds_wr(sc, YDSXGR_NATIVEDACOUTVOL, 0x00000000, 4);
+ ds_wr(sc, YDSXGR_NATIVEADCINVOL, 0, 4);
+ ds_wr(sc, YDSXGR_NATIVEDACINVOL, 0, 4);
+ ds_enadsp(sc, 0);
+ ds_wr(sc, YDSXGR_MODE, 0x00010000, 4);
+ ds_wr(sc, YDSXGR_MAPOFREC, 0x00000000, 4);
+ ds_wr(sc, YDSXGR_MAPOFEFFECT, 0x00000000, 4);
+ ds_wr(sc, YDSXGR_PLAYCTRLBASE, 0x00000000, 4);
+ ds_wr(sc, YDSXGR_RECCTRLBASE, 0x00000000, 4);
+ ds_wr(sc, YDSXGR_EFFCTRLBASE, 0x00000000, 4);
+ ds_wr(sc, YDSXGR_GLOBALCTRL, 0, 2);
-bus_dmamap_unload(sc->control_dmat, sc->map);
-bus_dmamem_free(sc->control_dmat, sc->regbase, sc->map);
+ bus_dmamap_unload(sc->control_dmat, sc->map);
+ bus_dmamem_free(sc->control_dmat, sc->regbase, sc->map);
-return 0;
+ return 0;
}
static int
ds_finddev(u_int32_t dev, u_int32_t subdev)
{
-int i;
+ int i;
-for (i = 0; ds_devs[i].dev; i++) {
-if (ds_devs[i].dev == dev &&
-(ds_devs[i].subdev == subdev || ds_devs[i].subdev == 0))
-return i;
-}
-return -1;
+ for (i = 0; ds_devs[i].dev; i++) {
+ if (ds_devs[i].dev == dev &&
+ (ds_devs[i].subdev == subdev || ds_devs[i].subdev == 0))
+ return i;
+ }
+ return -1;
}
static int
ds_pci_probe(device_t dev)
{
-int i;
-u_int32_t subdev;
+ int i;
+ u_int32_t subdev;
-subdev = (pci_get_subdevice(dev) << 16) | pci_get_subvendor(dev);
-i = ds_finddev(pci_get_devid(dev), subdev);
-if (i >= 0) {
-device_set_desc(dev, ds_devs[i].name);
-return BUS_PROBE_DEFAULT;
-} else
-return ENXIO;
+ subdev = (pci_get_subdevice(dev) << 16) | pci_get_subvendor(dev);
+ i = ds_finddev(pci_get_devid(dev), subdev);
+ if (i >= 0) {
+ device_set_desc(dev, ds_devs[i].name);
+ return BUS_PROBE_DEFAULT;
+ } else
+ return ENXIO;
}
static int
ds_pci_attach(device_t dev)
{
-u_int32_t data;
-u_int32_t subdev, i;
-struct sc_info *sc;
-struct ac97_info *codec = NULL;
-char status[SND_STATUSLEN];
-
-if ((sc = malloc(sizeof(*sc), M_DEVBUF, M_WAITOK | M_ZERO)) == NULL) {
-device_printf(dev, "cannot allocate softcn");
-return ENXIO;
-}
-
-sc->lock = snd_mtxcreate(device_get_nameunit(dev), "sound softc");
-sc->dev = dev;
-subdev = (pci_get_subdevice(dev) << 16) | pci_get_subvendor(dev);
-sc->type = ds_finddev(pci_get_devid(dev), subdev);
-sc->rev = pci_get_revid(dev);
-
-data = pci_read_config(dev, PCIR_COMMAND, 2);
-data |= (PCIM_CMD_PORTEN|PCIM_CMD_MEMEN|PCIM_CMD_BUSMASTEREN);
-pci_write_config(dev, PCIR_COMMAND, data, 2);
-data = pci_read_config(dev, PCIR_COMMAND, 2);
-
-sc->regid = PCIR_BAR(0);
-sc->reg = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &sc->regid,
-RF_ACTIVE);
-if (!sc->reg) {
-device_printf(dev, "unable to map register spacen");
-goto bad;
-}
-
-sc->st = rman_get_bustag(sc->reg);
-sc->sh = rman_get_bushandle(sc->reg);
-
-sc->bufsz = pcm_getbuffersize(dev, 4096, DS1_BUFFSIZE, 65536);
-
-if (bus_dma_tag_create(/*parent*/NULL, /*alignment*/2, /*boundary*/0,
-/*lowaddr*/BUS_SPACE_MAXADDR_32BIT,
-/*highaddr*/BUS_SPACE_MAXADDR,
-/*filter*/NULL, /*filterarg*/NULL,
-/*maxsize*/sc->bufsz, /*nsegments*/1, /*maxsegz*/0x3ffff,
-/*flags*/0, /*lockfunc*/NULL,
-/*lockarg*/NULL, &sc->buffer_dmat) != 0) {
-device_printf(dev, "unable to create dma tagn");
-goto bad;
-}
-
-sc->regbase = NULL;
-if (ds_init(sc) == -1) {
-device_printf(dev, "unable to initialize the cardn");
-goto bad;
-}
-
-codec = AC97_CREATE(dev, sc, ds_ac97);
-if (codec == NULL)
-goto bad;
-/*
-* Turn on inverted external amplifier sense flags for few
-* 'special' boards.
-*/
-switch (subdev) {
-case 0x81171033: /* NEC ValueStar (VT550/0) */
-ac97_setflags(codec, ac97_getflags(codec) | AC97_F_EAPD_INV);
-break;
-default:
-break;
-}
-mixer_init(dev, ac97_getmixerclass(), codec);
-
-sc->irqid = 0;
-sc->irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &sc->irqid,
-RF_ACTIVE | RF_SHAREABLE);
-if (!sc->irq || snd_setup_intr(dev, sc->irq, INTR_MPSAFE, ds_intr, sc, &sc->ih)) {
-device_printf(dev, "unable to map interruptn");
-goto bad;
-}
-
-snprintf(status, SND_STATUSLEN, "at memory 0x%lx irq %ld %s",
-rman_get_start(sc->reg), rman_get_start(sc->irq),PCM_KLDSTRING(snd_ds1));
-
-if (pcm_register(dev, sc, DS1_CHANS, 2))
-goto bad;
-for (i = 0; i < DS1_CHANS; i++)
-pcm_addchan(dev, PCMDIR_PLAY, &ds1pchan_class, sc);
-for (i = 0; i < 2; i++)
-pcm_addchan(dev, PCMDIR_REC, &ds1rchan_class, sc);
-pcm_setstatus(dev, status);
+ u_int32_t data;
+ u_int32_t subdev, i;
+ struct sc_info *sc;
+ struct ac97_info *codec = NULL;
+ char status[SND_STATUSLEN];
+
+ sc = malloc(sizeof(*sc), M_DEVBUF, M_WAITOK | M_ZERO);
+ sc->lock = snd_mtxcreate(device_get_nameunit(dev), "snd_ds1 softc");
+ sc->dev = dev;
+ subdev = (pci_get_subdevice(dev) << 16) | pci_get_subvendor(dev);
+ sc->type = ds_finddev(pci_get_devid(dev), subdev);
+ sc->rev = pci_get_revid(dev);
+
+ data = pci_read_config(dev, PCIR_COMMAND, 2);
+ data |= (PCIM_CMD_PORTEN|PCIM_CMD_MEMEN|PCIM_CMD_BUSMASTEREN);
+ pci_write_config(dev, PCIR_COMMAND, data, 2);
+ data = pci_read_config(dev, PCIR_COMMAND, 2);
+
+ sc->regid = PCIR_BAR(0);
+ sc->reg = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &sc->regid,
+ RF_ACTIVE);
+ if (!sc->reg) {
+ device_printf(dev, "unable to map register space\n");
+ goto bad;
+ }
+
+ sc->st = rman_get_bustag(sc->reg);
+ sc->sh = rman_get_bushandle(sc->reg);
+
+ sc->bufsz = pcm_getbuffersize(dev, 4096, DS1_BUFFSIZE, 65536);
+
+ if (bus_dma_tag_create(/*parent*/bus_get_dma_tag(dev), /*alignment*/2,
+ /*boundary*/0,
+ /*lowaddr*/BUS_SPACE_MAXADDR_32BIT,
+ /*highaddr*/BUS_SPACE_MAXADDR,
+ /*filter*/NULL, /*filterarg*/NULL,
+ /*maxsize*/sc->bufsz, /*nsegments*/1, /*maxsegz*/0x3ffff,
+ /*flags*/0, /*lockfunc*/NULL,
+ /*lockarg*/NULL, &sc->buffer_dmat) != 0) {
+ device_printf(dev, "unable to create dma tag\n");
+ goto bad;
+ }
+
+ sc->regbase = NULL;
+ if (ds_init(sc) == -1) {
+ device_printf(dev, "unable to initialize the card\n");
+ goto bad;
+ }
+
+ codec = AC97_CREATE(dev, sc, ds_ac97);
+ if (codec == NULL)
+ goto bad;
+ /*
+ * Turn on inverted external amplifier sense flags for few
+ * 'special' boards.
+ */
+ switch (subdev) {
+ case 0x81171033: /* NEC ValueStar (VT550/0) */
+ ac97_setflags(codec, ac97_getflags(codec) | AC97_F_EAPD_INV);
+ break;
+ default:
+ break;
+ }
+ mixer_init(dev, ac97_getmixerclass(), codec);
+
+ sc->irqid = 0;
+ sc->irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &sc->irqid,
+ RF_ACTIVE | RF_SHAREABLE);
+ if (!sc->irq || snd_setup_intr(dev, sc->irq, INTR_MPSAFE, ds_intr, sc, &sc->ih)) {
+ device_printf(dev, "unable to map interrupt\n");
+ goto bad;
+ }
+
+ snprintf(status, SND_STATUSLEN, "at memory 0x%lx irq %ld %s",
+ rman_get_start(sc->reg), rman_get_start(sc->irq),PCM_KLDSTRING(snd_ds1));
+
+ if (pcm_register(dev, sc, DS1_CHANS, 2))
+ goto bad;
+ for (i = 0; i < DS1_CHANS; i++)
+ pcm_addchan(dev, PCMDIR_PLAY, &ds1pchan_class, sc);
+ for (i = 0; i < 2; i++)
+ pcm_addchan(dev, PCMDIR_REC, &ds1rchan_class, sc);
+ pcm_setstatus(dev, status);
-return 0;
+ return 0;
bad:
-if (codec)
-ac97_destroy(codec);
-if (sc->reg)
-bus_release_resource(dev, SYS_RES_MEMORY, sc->regid, sc->reg);
-if (sc->ih)
-bus_teardown_intr(dev, sc->irq, sc->ih);
-if (sc->irq)
-bus_release_resource(dev, SYS_RES_IRQ, sc->irqid, sc->irq);
-if (sc->buffer_dmat)
-bus_dma_tag_destroy(sc->buffer_dmat);
-if (sc->control_dmat)
-bus_dma_tag_destroy(sc->control_dmat);
-if (sc->lock)
-snd_mtxfree(sc->lock);
-free(sc, M_DEVBUF);
-return ENXIO;
+ if (codec)
+ ac97_destroy(codec);
+ if (sc->reg)
+ bus_release_resource(dev, SYS_RES_MEMORY, sc->regid, sc->reg);
+ if (sc->ih)
+ bus_teardown_intr(dev, sc->irq, sc->ih);
+ if (sc->irq)
+ bus_release_resource(dev, SYS_RES_IRQ, sc->irqid, sc->irq);
+ if (sc->buffer_dmat)
+ bus_dma_tag_destroy(sc->buffer_dmat);
+ if (sc->control_dmat)
+ bus_dma_tag_destroy(sc->control_dmat);
+ if (sc->lock)
+ snd_mtxfree(sc->lock);
+ free(sc, M_DEVBUF);
+ return ENXIO;
}
static int
ds_pci_resume(device_t dev)
{
-struct sc_info *sc;
+ struct sc_info *sc;
-sc = pcm_getdevinfo(dev);
+ sc = pcm_getdevinfo(dev);
-if (ds_init(sc) == -1) {
-device_printf(dev, "unable to reinitialize the cardn");
-return ENXIO;
-}
-if (mixer_reinit(dev) == -1) {
-device_printf(dev, "unable to reinitialize the mixern");
-return ENXIO;
-}
-return 0;
+ if (ds_init(sc) == -1) {
+ device_printf(dev, "unable to reinitialize the card\n");
+ return ENXIO;
+ }
+ if (mixer_reinit(dev) == -1) {
+ device_printf(dev, "unable to reinitialize the mixer\n");
+ return ENXIO;
+ }
+ return 0;
}
static int
ds_pci_detach(device_t dev)
{
-int r;
-struct sc_info *sc;
+ int r;
+ struct sc_info *sc;
-r = pcm_unregister(dev);
-if (r)
-return r;
-
-sc = pcm_getdevinfo(dev);
-ds_uninit(sc);
-bus_release_resource(dev, SYS_RES_MEMORY, sc->regid, sc->reg);
-bus_teardown_intr(dev, sc->irq, sc->ih);
-bus_release_resource(dev, SYS_RES_IRQ, sc->irqid, sc->irq);
-bus_dma_tag_destroy(sc->buffer_dmat);
-bus_dma_tag_destroy(sc->control_dmat);
-snd_mtxfree(sc->lock);
-free(sc, M_DEVBUF);
-return 0;
+ r = pcm_unregister(dev);
+ if (r)
+ return r;
+
+ sc = pcm_getdevinfo(dev);
+ ds_uninit(sc);
+ bus_release_resource(dev, SYS_RES_MEMORY, sc->regid, sc->reg);
+ bus_teardown_intr(dev, sc->irq, sc->ih);
+ bus_release_resource(dev, SYS_RES_IRQ, sc->irqid, sc->irq);
+ bus_dma_tag_destroy(sc->buffer_dmat);
+ bus_dma_tag_destroy(sc->control_dmat);
+ snd_mtxfree(sc->lock);
+ free(sc, M_DEVBUF);
+ return 0;
}
static device_method_t ds1_methods[] = {
-/* Device interface */
-DEVMETHOD(device_probe, ds_pci_probe),
-DEVMETHOD(device_attach, ds_pci_attach),
-DEVMETHOD(device_detach, ds_pci_detach),
-DEVMETHOD(device_resume, ds_pci_resume),
-{ 0, 0 }
+ /* Device interface */
+ DEVMETHOD(device_probe, ds_pci_probe),
+ DEVMETHOD(device_attach, ds_pci_attach),
+ DEVMETHOD(device_detach, ds_pci_detach),
+ DEVMETHOD(device_resume, ds_pci_resume),
+ { 0, 0 }
};
static driver_t ds1_driver = {
-"pcm",
-ds1_methods,
-PCM_SOFTC_SIZE,
+ "pcm",
+ ds1_methods,
+ PCM_SOFTC_SIZE,
};
DRIVER_MODULE(snd_ds1, pci, ds1_driver, pcm_devclass, 0, 0);
Index: via82c686.h
===================================================================
RCS file: /home/cvs/src/sys/dev/sound/pci/via82c686.h,v
retrieving revision 1.2
retrieving revision 1.3
diff -L sys/dev/sound/pci/via82c686.h -L sys/dev/sound/pci/via82c686.h -u -r1.2 -r1.3
--- sys/dev/sound/pci/via82c686.h
+++ sys/dev/sound/pci/via82c686.h
@@ -1,54 +1,53 @@
/*-
-* Copyright (c) 2000 The NetBSD Foundation, Inc.
-* All rights reserved.
-*
-* This code is derived from software contributed to The NetBSD Foundation
-* by Tyler C. Sarna.
-*
-* Redistribution and use in source and binary forms, with or without
-* modification, are permitted provided that the following conditions
-* are met:
-* 1. Redistributions of source code must retain the above copyright
-* notice, this list of conditions and the following disclaimer.
-* 2. Redistributions in binary form must reproduce the above copyright
-* notice, this list of conditions and the following disclaimer in the
-* documentation and/or other materials provided with the distribution.
-* 3. All advertising materials mentioning features or use of this software
-* must display the following acknowledgement:
-* This product includes software developed by the NetBSD
-* Foundation, Inc. and its contributors.
-* 4. Neither the name of The NetBSD Foundation nor the names of its
-* contributors may be used to endorse or promote products derived
-* from this software without specific prior written permission.
-*
-* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
-* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
-* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
-* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
-* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-* POSSIBILITY OF SUCH DAMAGE.
-*
-* $MidnightBSD$
-* $FreeBSD: src/sys/dev/sound/pci/via82c686.h,v 1.6 2003/03/26 05:35:38 orion Exp $
-*/
+ * Copyright (c) 2000 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Tyler C. Sarna.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the NetBSD
+ * Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD: src/sys/dev/sound/pci/via82c686.h,v 1.6 2003/03/26 05:35:38 orion Exp $
+ */
#ifndef _VIA_H
#define _VIA_H
/*
-* VIA Technologies VT82C686A Southbridge Audio Driver
-*
-* Documentation links:
-*
-* ftp://ftp.alsa-project.org/pub/manuals/via/686a.pdf
-* ftp://ftp.alsa-project.org/pub/manuals/general/ac97r21.pdf
-* ftp://ftp.alsa-project.org/pub/manuals/ad/AD1881_0.pdf (example AC'97 codec)
-*/
+ * VIA Technologies VT82C686A Southbridge Audio Driver
+ *
+ * Documentation links:
+ *
+ * ftp://ftp.alsa-project.org/pub/manuals/via/686a.pdf
+ * ftp://ftp.alsa-project.org/pub/manuals/general/ac97r21.pdf
+ * ftp://ftp.alsa-project.org/pub/manuals/ad/AD1881_0.pdf (example AC'97 codec)
+ */
#define VIA_AC97STATUS 0x40
#define VIA_AC97STATUS_RDY 0x01
Index: cs4281.c
===================================================================
RCS file: /home/cvs/src/sys/dev/sound/pci/cs4281.c,v
retrieving revision 1.2
retrieving revision 1.3
diff -L sys/dev/sound/pci/cs4281.c -L sys/dev/sound/pci/cs4281.c -u -r1.2 -r1.3
--- sys/dev/sound/pci/cs4281.c
+++ sys/dev/sound/pci/cs4281.c
@@ -1,33 +1,33 @@
/*-
-* Copyright (c) 2000 Orion Hodson <O.Hodson at cs.ucl.ac.uk>
-* All rights reserved.
-*
-* Redistribution and use in source and binary forms, with or without
-* modification, are permitted provided that the following conditions
-* are met:
-* 1. Redistributions of source code must retain the above copyright
-* notice, this list of conditions and the following disclaimer.
-* 2. Redistributions in binary form must reproduce the above copyright
-* notice, this list of conditions and the following disclaimer in the
-* documentation and/or other materials provided with the distribution.
-*
-* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
-* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
-* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
-* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
-* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHERIN CONTRACT, STRICT
-* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
-* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THEPOSSIBILITY OF
-* SUCH DAMAGE.
-*
-* The order of pokes in the initiation sequence is based on Linux
-* driver by Thomas Sailer, gw boynton (wesb at crystal.cirrus.com), tom
-* woller (twoller at crystal.cirrus.com). Shingo Watanabe (nabe at nabechan.org)
-* contributed towards power management.
-*/
+ * Copyright (c) 2000 Orion Hodson <O.Hodson at cs.ucl.ac.uk>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHERIN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THEPOSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The order of pokes in the initiation sequence is based on Linux
+ * driver by Thomas Sailer, gw boynton (wesb at crystal.cirrus.com), tom
+ * woller (twoller at crystal.cirrus.com). Shingo Watanabe (nabe at nabechan.org)
+ * contributed towards power management.
+ */
#include <dev/sound/pcm/sound.h>
#include <dev/sound/pcm/ac97.h>
@@ -37,7 +37,7 @@
#include <dev/sound/pci/cs4281.h>
-SND_DECLARE_FILE("$MidnightBSD$");
+SND_DECLARE_FILE("$FreeBSD: src/sys/dev/sound/pci/cs4281.c,v 1.26 2007/06/17 06:10:41 ariff Exp $");
#define CS4281_DEFAULT_BUFSZ 16384
@@ -63,33 +63,33 @@
/* channel registers */
struct sc_chinfo {
-struct sc_info *parent;
+ struct sc_info *parent;
-struct snd_dbuf *buffer;
-struct pcm_channel *channel;
+ struct snd_dbuf *buffer;
+ struct pcm_channel *channel;
-u_int32_t spd, fmt, bps, blksz;
+ u_int32_t spd, fmt, bps, blksz;
-int dma_setup, dma_active, dma_chan;
+ int dma_setup, dma_active, dma_chan;
};
/* device private data */
struct sc_info {
-device_t dev;
-u_int32_t type;
+ device_t dev;
+ u_int32_t type;
-bus_space_tag_t st;
-bus_space_handle_t sh;
-bus_dma_tag_t parent_dmat;
-
-struct resource *reg, *irq, *mem;
-int regtype, regid, irqid, memid;
-void *ih;
-
-int power;
-unsigned long bufsz;
-struct sc_chinfo pch;
-struct sc_chinfo rch;
+ bus_space_tag_t st;
+ bus_space_handle_t sh;
+ bus_dma_tag_t parent_dmat;
+
+ struct resource *reg, *irq, *mem;
+ int regtype, regid, irqid, memid;
+ void *ih;
+
+ int power;
+ unsigned long bufsz;
+ struct sc_chinfo pch;
+ struct sc_chinfo rch;
};
/* -------------------------------------------------------------------- */
@@ -117,19 +117,19 @@
/* formats (do not add formats without editing cs_fmt_tab) */
static u_int32_t cs4281_fmts[] = {
-AFMT_U8,
-AFMT_U8 | AFMT_STEREO,
-AFMT_S8,
-AFMT_S8 | AFMT_STEREO,
-AFMT_S16_LE,
-AFMT_S16_LE | AFMT_STEREO,
-AFMT_U16_LE,
-AFMT_U16_LE | AFMT_STEREO,
-AFMT_S16_BE,
-AFMT_S16_BE | AFMT_STEREO,
-AFMT_U16_BE,
-AFMT_U16_BE | AFMT_STEREO,
-0
+ AFMT_U8,
+ AFMT_U8 | AFMT_STEREO,
+ AFMT_S8,
+ AFMT_S8 | AFMT_STEREO,
+ AFMT_S16_LE,
+ AFMT_S16_LE | AFMT_STEREO,
+ AFMT_U16_LE,
+ AFMT_U16_LE | AFMT_STEREO,
+ AFMT_S16_BE,
+ AFMT_S16_BE | AFMT_STEREO,
+ AFMT_U16_BE,
+ AFMT_U16_BE | AFMT_STEREO,
+ 0
};
static struct pcmchan_caps cs4281_caps = {6024, 48000, cs4281_fmts, 0};
@@ -140,58 +140,58 @@
static inline u_int32_t
cs4281_rd(struct sc_info *sc, int regno)
{
-return bus_space_read_4(sc->st, sc->sh, regno);
+ return bus_space_read_4(sc->st, sc->sh, regno);
}
static inline void
cs4281_wr(struct sc_info *sc, int regno, u_int32_t data)
{
-bus_space_write_4(sc->st, sc->sh, regno, data);
-DELAY(100);
+ bus_space_write_4(sc->st, sc->sh, regno, data);
+ DELAY(100);
}
static inline void
cs4281_clr4(struct sc_info *sc, int regno, u_int32_t mask)
{
-u_int32_t r;
-r = cs4281_rd(sc, regno);
-cs4281_wr(sc, regno, r & ~mask);
+ u_int32_t r;
+ r = cs4281_rd(sc, regno);
+ cs4281_wr(sc, regno, r & ~mask);
}
static inline void
cs4281_set4(struct sc_info *sc, int regno, u_int32_t mask)
{
-u_int32_t v;
-v = cs4281_rd(sc, regno);
-cs4281_wr(sc, regno, v | mask);
+ u_int32_t v;
+ v = cs4281_rd(sc, regno);
+ cs4281_wr(sc, regno, v | mask);
}
static int
cs4281_waitset(struct sc_info *sc, int regno, u_int32_t mask, int tries)
{
-u_int32_t v;
+ u_int32_t v;
-while(tries > 0) {
-DELAY(100);
-v = cs4281_rd(sc, regno);
-if ((v & mask) == mask) break;
-tries --;
-}
-return tries;
+ while(tries > 0) {
+ DELAY(100);
+ v = cs4281_rd(sc, regno);
+ if ((v & mask) == mask) break;
+ tries --;
+ }
+ return tries;
}
static int
cs4281_waitclr(struct sc_info *sc, int regno, u_int32_t mask, int tries)
{
-u_int32_t v;
+ u_int32_t v;
-while(tries > 0) {
-DELAY(100);
-v = ~ cs4281_rd(sc, regno);
-if (v & mask) break;
-tries --;
-}
-return tries;
+ while(tries > 0) {
+ DELAY(100);
+ v = ~ cs4281_rd(sc, regno);
+ if (v & mask) break;
+ tries --;
+ }
+ return tries;
}
/* ------------------------------------------------------------------------- */
@@ -203,42 +203,42 @@
static u_int8_t
cs4281_rate_to_rv(u_int32_t rate)
{
-u_int32_t v;
-
-for (v = 0; v < CS4281_NUM_RATES; v++) {
-if (rate == cs4281_rates[v]) return v;
-}
+ u_int32_t v;
-v = 1536000 / rate;
-if (v > 255 || v < 32) v = 5; /* default to 8k */
-return v;
+ for (v = 0; v < CS4281_NUM_RATES; v++) {
+ if (rate == cs4281_rates[v]) return v;
+ }
+
+ v = 1536000 / rate;
+ if (v > 255 || v < 32) v = 5; /* default to 8k */
+ return v;
}
static u_int32_t
cs4281_rv_to_rate(u_int8_t rv)
{
-u_int32_t r;
+ u_int32_t r;
-if (rv < CS4281_NUM_RATES) return cs4281_rates[rv];
-r = 1536000 / rv;
-return r;
+ if (rv < CS4281_NUM_RATES) return cs4281_rates[rv];
+ r = 1536000 / rv;
+ return r;
}
static inline u_int32_t
cs4281_format_to_dmr(u_int32_t format)
{
-u_int32_t dmr = 0;
-if (AFMT_8BIT & format) dmr |= CS4281PCI_DMR_SIZE8;
-if (!(AFMT_STEREO & format)) dmr |= CS4281PCI_DMR_MONO;
-if (AFMT_BIGENDIAN & format) dmr |= CS4281PCI_DMR_BEND;
-if (!(AFMT_SIGNED & format)) dmr |= CS4281PCI_DMR_USIGN;
-return dmr;
+ u_int32_t dmr = 0;
+ if (AFMT_8BIT & format) dmr |= CS4281PCI_DMR_SIZE8;
+ if (!(AFMT_STEREO & format)) dmr |= CS4281PCI_DMR_MONO;
+ if (AFMT_BIGENDIAN & format) dmr |= CS4281PCI_DMR_BEND;
+ if (!(AFMT_SIGNED & format)) dmr |= CS4281PCI_DMR_USIGN;
+ return dmr;
}
static inline u_int32_t
cs4281_format_to_bps(u_int32_t format)
{
-return ((AFMT_8BIT & format) ? 1 : 2) * ((AFMT_STEREO & format) ? 2 : 1);
+ return ((AFMT_8BIT & format) ? 1 : 2) * ((AFMT_STEREO & format) ? 2 : 1);
}
/* -------------------------------------------------------------------- */
@@ -247,60 +247,60 @@
static u_int32_t
cs4281_rdcd(kobj_t obj, void *devinfo, int regno)
{
-struct sc_info *sc = (struct sc_info *)devinfo;
-int codecno;
+ struct sc_info *sc = (struct sc_info *)devinfo;
+ int codecno;
-codecno = regno >> 8;
-regno &= 0xff;
+ codecno = regno >> 8;
+ regno &= 0xff;
-/* Remove old state */
-cs4281_rd(sc, CS4281PCI_ACSDA);
+ /* Remove old state */
+ cs4281_rd(sc, CS4281PCI_ACSDA);
-/* Fill in AC97 register value request form */
-cs4281_wr(sc, CS4281PCI_ACCAD, regno);
-cs4281_wr(sc, CS4281PCI_ACCDA, 0);
-cs4281_wr(sc, CS4281PCI_ACCTL, CS4281PCI_ACCTL_ESYN |
-CS4281PCI_ACCTL_VFRM | CS4281PCI_ACCTL_DCV |
-CS4281PCI_ACCTL_CRW);
+ /* Fill in AC97 register value request form */
+ cs4281_wr(sc, CS4281PCI_ACCAD, regno);
+ cs4281_wr(sc, CS4281PCI_ACCDA, 0);
+ cs4281_wr(sc, CS4281PCI_ACCTL, CS4281PCI_ACCTL_ESYN |
+ CS4281PCI_ACCTL_VFRM | CS4281PCI_ACCTL_DCV |
+ CS4281PCI_ACCTL_CRW);
+
+ /* Wait for read to complete */
+ if (cs4281_waitclr(sc, CS4281PCI_ACCTL, CS4281PCI_ACCTL_DCV, 250) == 0) {
+ device_printf(sc->dev, "cs4281_rdcd: DCV did not go\n");
+ return 0xffffffff;
+ }
+
+ /* Wait for valid status */
+ if (cs4281_waitset(sc, CS4281PCI_ACSTS, CS4281PCI_ACSTS_VSTS, 250) == 0) {
+ device_printf(sc->dev,"cs4281_rdcd: VSTS did not come\n");
+ return 0xffffffff;
+ }
-/* Wait for read to complete */
-if (cs4281_waitclr(sc, CS4281PCI_ACCTL, CS4281PCI_ACCTL_DCV, 250) == 0) {
-device_printf(sc->dev, "cs4281_rdcd: DCV did not gon");
-return 0xffffffff;
-}
-
-/* Wait for valid status */
-if (cs4281_waitset(sc, CS4281PCI_ACSTS, CS4281PCI_ACSTS_VSTS, 250) == 0) {
-device_printf(sc->dev,"cs4281_rdcd: VSTS did not comen");
-return 0xffffffff;
-}
-
-return cs4281_rd(sc, CS4281PCI_ACSDA);
+ return cs4281_rd(sc, CS4281PCI_ACSDA);
}
static void
cs4281_wrcd(kobj_t obj, void *devinfo, int regno, u_int32_t data)
{
-struct sc_info *sc = (struct sc_info *)devinfo;
-int codecno;
-
-codecno = regno >> 8;
-regno &= 0xff;
+ struct sc_info *sc = (struct sc_info *)devinfo;
+ int codecno;
-cs4281_wr(sc, CS4281PCI_ACCAD, regno);
-cs4281_wr(sc, CS4281PCI_ACCDA, data);
-cs4281_wr(sc, CS4281PCI_ACCTL, CS4281PCI_ACCTL_ESYN |
-CS4281PCI_ACCTL_VFRM | CS4281PCI_ACCTL_DCV);
+ codecno = regno >> 8;
+ regno &= 0xff;
-if (cs4281_waitclr(sc, CS4281PCI_ACCTL, CS4281PCI_ACCTL_DCV, 250) == 0) {
-device_printf(sc->dev,"cs4281_wrcd: DCV did not gon");
-}
+ cs4281_wr(sc, CS4281PCI_ACCAD, regno);
+ cs4281_wr(sc, CS4281PCI_ACCDA, data);
+ cs4281_wr(sc, CS4281PCI_ACCTL, CS4281PCI_ACCTL_ESYN |
+ CS4281PCI_ACCTL_VFRM | CS4281PCI_ACCTL_DCV);
+
+ if (cs4281_waitclr(sc, CS4281PCI_ACCTL, CS4281PCI_ACCTL_DCV, 250) == 0) {
+ device_printf(sc->dev,"cs4281_wrcd: DCV did not go\n");
+ }
}
static kobj_method_t cs4281_ac97_methods[] = {
-KOBJMETHOD(ac97_read, cs4281_rdcd),
-KOBJMETHOD(ac97_write, cs4281_wrcd),
-{ 0, 0 }
+ KOBJMETHOD(ac97_read, cs4281_rdcd),
+ KOBJMETHOD(ac97_write, cs4281_wrcd),
+ { 0, 0 }
};
AC97_DECLARE(cs4281_ac97);
@@ -310,147 +310,148 @@
static void *
cs4281chan_init(kobj_t obj, void *devinfo, struct snd_dbuf *b, struct pcm_channel *c, int dir)
{
-struct sc_info *sc = devinfo;
-struct sc_chinfo *ch = (dir == PCMDIR_PLAY) ? &sc->pch : &sc->rch;
+ struct sc_info *sc = devinfo;
+ struct sc_chinfo *ch = (dir == PCMDIR_PLAY) ? &sc->pch : &sc->rch;
-ch->buffer = b;
-if (sndbuf_alloc(ch->buffer, sc->parent_dmat, sc->bufsz) != 0) {
-return NULL;
-}
-ch->parent = sc;
-ch->channel = c;
-
-ch->fmt = AFMT_U8;
-ch->spd = DSP_DEFAULT_SPEED;
-ch->bps = 1;
-ch->blksz = sndbuf_getsize(ch->buffer);
+ ch->buffer = b;
+ if (sndbuf_alloc(ch->buffer, sc->parent_dmat, 0, sc->bufsz) != 0) {
+ return NULL;
+ }
+ ch->parent = sc;
+ ch->channel = c;
+
+ ch->fmt = AFMT_U8;
+ ch->spd = DSP_DEFAULT_SPEED;
+ ch->bps = 1;
+ ch->blksz = sndbuf_getsize(ch->buffer);
-ch->dma_chan = (dir == PCMDIR_PLAY) ? CS4281_DMA_PLAY : CS4281_DMA_REC;
-ch->dma_setup = 0;
+ ch->dma_chan = (dir == PCMDIR_PLAY) ? CS4281_DMA_PLAY : CS4281_DMA_REC;
+ ch->dma_setup = 0;
-adcdac_go(ch, 0);
-adcdac_prog(ch);
+ adcdac_go(ch, 0);
+ adcdac_prog(ch);
-return ch;
+ return ch;
}
static int
cs4281chan_setblocksize(kobj_t obj, void *data, u_int32_t blocksize)
{
-struct sc_chinfo *ch = data;
-struct sc_info *sc = ch->parent;
-u_int32_t go;
-
-go = adcdac_go(ch, 0);
-
-/* 2 interrupts are possible and used in buffer (half-empty,empty),
-* hence factor of 2. */
-ch->blksz = MIN(blocksize, sc->bufsz / 2);
-sndbuf_resize(ch->buffer, 2, ch->blksz);
-ch->dma_setup = 0;
-adcdac_prog(ch);
-adcdac_go(ch, go);
+ struct sc_chinfo *ch = data;
+ struct sc_info *sc = ch->parent;
+ u_int32_t go;
+
+ go = adcdac_go(ch, 0);
+
+ /* 2 interrupts are possible and used in buffer (half-empty,empty),
+ * hence factor of 2. */
+ ch->blksz = MIN(blocksize, sc->bufsz / 2);
+ sndbuf_resize(ch->buffer, 2, ch->blksz);
+ ch->dma_setup = 0;
+ adcdac_prog(ch);
+ adcdac_go(ch, go);
-DEB(printf("cs4281chan_setblocksize: blksz %d Setting %dn", blocksize, ch->blksz));
+ DEB(printf("cs4281chan_setblocksize: blksz %d Setting %d\n", blocksize, ch->blksz));
-return ch->blksz;
+ return ch->blksz;
}
static int
cs4281chan_setspeed(kobj_t obj, void *data, u_int32_t speed)
{
-struct sc_chinfo *ch = data;
-struct sc_info *sc = ch->parent;
-u_int32_t go, v, r;
-
-go = adcdac_go(ch, 0); /* pause */
-r = (ch->dma_chan == CS4281_DMA_PLAY) ? CS4281PCI_DACSR : CS4281PCI_ADCSR;
-v = cs4281_rate_to_rv(speed);
-cs4281_wr(sc, r, v);
-adcdac_go(ch, go); /* unpause */
+ struct sc_chinfo *ch = data;
+ struct sc_info *sc = ch->parent;
+ u_int32_t go, v, r;
+
+ go = adcdac_go(ch, 0); /* pause */
+ r = (ch->dma_chan == CS4281_DMA_PLAY) ? CS4281PCI_DACSR : CS4281PCI_ADCSR;
+ v = cs4281_rate_to_rv(speed);
+ cs4281_wr(sc, r, v);
+ adcdac_go(ch, go); /* unpause */
-ch->spd = cs4281_rv_to_rate(v);
-return ch->spd;
+ ch->spd = cs4281_rv_to_rate(v);
+ return ch->spd;
}
static int
cs4281chan_setformat(kobj_t obj, void *data, u_int32_t format)
{
-struct sc_chinfo *ch = data;
-struct sc_info *sc = ch->parent;
-u_int32_t v, go;
-
-go = adcdac_go(ch, 0); /* pause */
-
-if (ch->dma_chan == CS4281_DMA_PLAY)
-v = CS4281PCI_DMR_TR_PLAY;
-else
-v = CS4281PCI_DMR_TR_REC;
-v |= CS4281PCI_DMR_DMA | CS4281PCI_DMR_AUTO;
-v |= cs4281_format_to_dmr(format);
-cs4281_wr(sc, CS4281PCI_DMR(ch->dma_chan), v);
-
-adcdac_go(ch, go); /* unpause */
-
-ch->fmt = format;
-ch->bps = cs4281_format_to_bps(format);
-ch->dma_setup = 0;
+ struct sc_chinfo *ch = data;
+ struct sc_info *sc = ch->parent;
+ u_int32_t v, go;
+
+ go = adcdac_go(ch, 0); /* pause */
+
+ if (ch->dma_chan == CS4281_DMA_PLAY)
+ v = CS4281PCI_DMR_TR_PLAY;
+ else
+ v = CS4281PCI_DMR_TR_REC;
+ v |= CS4281PCI_DMR_DMA | CS4281PCI_DMR_AUTO;
+ v |= cs4281_format_to_dmr(format);
+ cs4281_wr(sc, CS4281PCI_DMR(ch->dma_chan), v);
+
+ adcdac_go(ch, go); /* unpause */
+
+ ch->fmt = format;
+ ch->bps = cs4281_format_to_bps(format);
+ ch->dma_setup = 0;
-return 0;
+ return 0;
}
static int
cs4281chan_getptr(kobj_t obj, void *data)
{
-struct sc_chinfo *ch = data;
-struct sc_info *sc = ch->parent;
-u_int32_t dba, dca, ptr;
-int sz;
-
-sz = sndbuf_getsize(ch->buffer);
-dba = cs4281_rd(sc, CS4281PCI_DBA(ch->dma_chan));
-dca = cs4281_rd(sc, CS4281PCI_DCA(ch->dma_chan));
-ptr = (dca - dba + sz) % sz;
+ struct sc_chinfo *ch = data;
+ struct sc_info *sc = ch->parent;
+ u_int32_t dba, dca, ptr;
+ int sz;
+
+ sz = sndbuf_getsize(ch->buffer);
+ dba = cs4281_rd(sc, CS4281PCI_DBA(ch->dma_chan));
+ dca = cs4281_rd(sc, CS4281PCI_DCA(ch->dma_chan));
+ ptr = (dca - dba + sz) % sz;
-return ptr;
+ return ptr;
}
static int
cs4281chan_trigger(kobj_t obj, void *data, int go)
{
-struct sc_chinfo *ch = data;
+ struct sc_chinfo *ch = data;
-switch(go) {
-case PCMTRIG_START:
-adcdac_prog(ch);
-adcdac_go(ch, 1);
-break;
-case PCMTRIG_ABORT:
-adcdac_go(ch, 0);
-break;
-default:
-break;
-}
+ switch(go) {
+ case PCMTRIG_START:
+ adcdac_prog(ch);
+ adcdac_go(ch, 1);
+ break;
+ case PCMTRIG_STOP:
+ case PCMTRIG_ABORT:
+ adcdac_go(ch, 0);
+ break;
+ default:
+ break;
+ }
-/* return 0 if ok */
-return 0;
+ /* return 0 if ok */
+ return 0;
}
static struct pcmchan_caps *
cs4281chan_getcaps(kobj_t obj, void *data)
{
-return &cs4281_caps;
+ return &cs4281_caps;
}
static kobj_method_t cs4281chan_methods[] = {
-KOBJMETHOD(channel_init, cs4281chan_init),
-KOBJMETHOD(channel_setformat, cs4281chan_setformat),
-KOBJMETHOD(channel_setspeed, cs4281chan_setspeed),
-KOBJMETHOD(channel_setblocksize, cs4281chan_setblocksize),
-KOBJMETHOD(channel_trigger, cs4281chan_trigger),
-KOBJMETHOD(channel_getptr, cs4281chan_getptr),
-KOBJMETHOD(channel_getcaps, cs4281chan_getcaps),
-{ 0, 0 }
+ KOBJMETHOD(channel_init, cs4281chan_init),
+ KOBJMETHOD(channel_setformat, cs4281chan_setformat),
+ KOBJMETHOD(channel_setspeed, cs4281chan_setspeed),
+ KOBJMETHOD(channel_setblocksize, cs4281chan_setblocksize),
+ KOBJMETHOD(channel_trigger, cs4281chan_trigger),
+ KOBJMETHOD(channel_getptr, cs4281chan_getptr),
+ KOBJMETHOD(channel_getcaps, cs4281chan_getcaps),
+ { 0, 0 }
};
CHANNEL_DECLARE(cs4281chan);
@@ -458,41 +459,41 @@
/* ADC/DAC control */
/* adcdac_go enables/disable DMA channel, returns non-zero if DMA was
-* active before call */
+ * active before call */
static u_int32_t
adcdac_go(struct sc_chinfo *ch, u_int32_t go)
{
-struct sc_info *sc = ch->parent;
-u_int32_t going;
+ struct sc_info *sc = ch->parent;
+ u_int32_t going;
-going = !(cs4281_rd(sc, CS4281PCI_DCR(ch->dma_chan)) & CS4281PCI_DCR_MSK);
+ going = !(cs4281_rd(sc, CS4281PCI_DCR(ch->dma_chan)) & CS4281PCI_DCR_MSK);
-if (go)
-cs4281_clr4(sc, CS4281PCI_DCR(ch->dma_chan), CS4281PCI_DCR_MSK);
-else
-cs4281_set4(sc, CS4281PCI_DCR(ch->dma_chan), CS4281PCI_DCR_MSK);
+ if (go)
+ cs4281_clr4(sc, CS4281PCI_DCR(ch->dma_chan), CS4281PCI_DCR_MSK);
+ else
+ cs4281_set4(sc, CS4281PCI_DCR(ch->dma_chan), CS4281PCI_DCR_MSK);
-cs4281_wr(sc, CS4281PCI_HICR, CS4281PCI_HICR_EOI);
+ cs4281_wr(sc, CS4281PCI_HICR, CS4281PCI_HICR_EOI);
-return going;
+ return going;
}
static void
adcdac_prog(struct sc_chinfo *ch)
{
-struct sc_info *sc = ch->parent;
-u_int32_t go;
+ struct sc_info *sc = ch->parent;
+ u_int32_t go;
-if (!ch->dma_setup) {
-go = adcdac_go(ch, 0);
-cs4281_wr(sc, CS4281PCI_DBA(ch->dma_chan),
-sndbuf_getbufaddr(ch->buffer));
-cs4281_wr(sc, CS4281PCI_DBC(ch->dma_chan),
-sndbuf_getsize(ch->buffer) / ch->bps - 1);
-ch->dma_setup = 1;
-adcdac_go(ch, go);
-}
+ if (!ch->dma_setup) {
+ go = adcdac_go(ch, 0);
+ cs4281_wr(sc, CS4281PCI_DBA(ch->dma_chan),
+ sndbuf_getbufaddr(ch->buffer));
+ cs4281_wr(sc, CS4281PCI_DBC(ch->dma_chan),
+ sndbuf_getsize(ch->buffer) / ch->bps - 1);
+ ch->dma_setup = 1;
+ adcdac_go(ch, go);
+ }
}
/* -------------------------------------------------------------------- */
@@ -501,25 +502,25 @@
static void
cs4281_intr(void *p)
{
-struct sc_info *sc = (struct sc_info *)p;
-u_int32_t hisr;
+ struct sc_info *sc = (struct sc_info *)p;
+ u_int32_t hisr;
-hisr = cs4281_rd(sc, CS4281PCI_HISR);
+ hisr = cs4281_rd(sc, CS4281PCI_HISR);
-if (hisr == 0) return;
+ if (hisr == 0) return;
-if (hisr & CS4281PCI_HISR_DMA(CS4281_DMA_PLAY)) {
-chn_intr(sc->pch.channel);
-cs4281_rd(sc, CS4281PCI_HDSR(CS4281_DMA_PLAY)); /* Clear interrupt */
-}
+ if (hisr & CS4281PCI_HISR_DMA(CS4281_DMA_PLAY)) {
+ chn_intr(sc->pch.channel);
+ cs4281_rd(sc, CS4281PCI_HDSR(CS4281_DMA_PLAY)); /* Clear interrupt */
+ }
-if (hisr & CS4281PCI_HISR_DMA(CS4281_DMA_REC)) {
-chn_intr(sc->rch.channel);
-cs4281_rd(sc, CS4281PCI_HDSR(CS4281_DMA_REC)); /* Clear interrupt */
-}
+ if (hisr & CS4281PCI_HISR_DMA(CS4281_DMA_REC)) {
+ chn_intr(sc->rch.channel);
+ cs4281_rd(sc, CS4281PCI_HDSR(CS4281_DMA_REC)); /* Clear interrupt */
+ }
-/* Signal End-of-Interrupt */
-cs4281_wr(sc, CS4281PCI_HICR, CS4281PCI_HICR_EOI);
+ /* Signal End-of-Interrupt */
+ cs4281_wr(sc, CS4281PCI_HICR, CS4281PCI_HICR_EOI);
}
/* -------------------------------------------------------------------- */
@@ -529,201 +530,201 @@
cs4281_power(struct sc_info *sc, int state)
{
-switch (state) {
-case 0:
-/* Permit r/w access to all BA0 registers */
-cs4281_wr(sc, CS4281PCI_CWPR, CS4281PCI_CWPR_MAGIC);
-/* Power on */
-cs4281_clr4(sc, CS4281PCI_EPPMC, CS4281PCI_EPPMC_FPDN);
-break;
-case 3:
-/* Power off card and codec */
-cs4281_set4(sc, CS4281PCI_EPPMC, CS4281PCI_EPPMC_FPDN);
-cs4281_clr4(sc, CS4281PCI_SPMC, CS4281PCI_SPMC_RSTN);
-break;
-}
+ switch (state) {
+ case 0:
+ /* Permit r/w access to all BA0 registers */
+ cs4281_wr(sc, CS4281PCI_CWPR, CS4281PCI_CWPR_MAGIC);
+ /* Power on */
+ cs4281_clr4(sc, CS4281PCI_EPPMC, CS4281PCI_EPPMC_FPDN);
+ break;
+ case 3:
+ /* Power off card and codec */
+ cs4281_set4(sc, CS4281PCI_EPPMC, CS4281PCI_EPPMC_FPDN);
+ cs4281_clr4(sc, CS4281PCI_SPMC, CS4281PCI_SPMC_RSTN);
+ break;
+ }
-DEB(printf("cs4281_power %d -> %dn", sc->power, state));
-sc->power = state;
+ DEB(printf("cs4281_power %d -> %d\n", sc->power, state));
+ sc->power = state;
-return 0;
+ return 0;
}
static int
cs4281_init(struct sc_info *sc)
{
-u_int32_t i, v;
+ u_int32_t i, v;
-/* (0) Blast clock register and serial port */
-cs4281_wr(sc, CS4281PCI_CLKCR1, 0);
-cs4281_wr(sc, CS4281PCI_SERMC, 0);
-
-/* (1) Make ESYN 0 to turn sync pulse on AC97 link */
-cs4281_wr(sc, CS4281PCI_ACCTL, 0);
-DELAY(50);
-
-/* (2) Effect Reset */
-cs4281_wr(sc, CS4281PCI_SPMC, 0);
-DELAY(100);
-cs4281_wr(sc, CS4281PCI_SPMC, CS4281PCI_SPMC_RSTN);
-/* Wait 50ms for ABITCLK to become stable */
-DELAY(50000);
-
-/* (3) Enable Sound System Clocks */
-cs4281_wr(sc, CS4281PCI_CLKCR1, CS4281PCI_CLKCR1_DLLP);
-DELAY(50000); /* Wait for PLL to stabilize */
-cs4281_wr(sc, CS4281PCI_CLKCR1,
-CS4281PCI_CLKCR1_DLLP | CS4281PCI_CLKCR1_SWCE);
-
-/* (4) Power Up - this combination is essential. */
-cs4281_set4(sc, CS4281PCI_SSPM,
-CS4281PCI_SSPM_ACLEN | CS4281PCI_SSPM_PSRCEN |
-CS4281PCI_SSPM_CSRCEN | CS4281PCI_SSPM_MIXEN);
-
-/* (5) Wait for clock stabilization */
-if (cs4281_waitset(sc,
-CS4281PCI_CLKCR1,
-CS4281PCI_CLKCR1_DLLRDY,
-250) == 0) {
-device_printf(sc->dev, "Clock stabilization failedn");
-return -1;
-}
-
-/* (6) Enable ASYNC generation. */
-cs4281_wr(sc, CS4281PCI_ACCTL,CS4281PCI_ACCTL_ESYN);
-
-/* Wait to allow AC97 to start generating clock bit */
-DELAY(50000);
-
-/* Set AC97 timing */
-cs4281_wr(sc, CS4281PCI_SERMC, CS4281PCI_SERMC_PTC_AC97);
-
-/* (7) Wait for AC97 ready signal */
-if (cs4281_waitset(sc, CS4281PCI_ACSTS, CS4281PCI_ACSTS_CRDY, 250) == 0) {
-device_printf(sc->dev, "codec did not availn");
-return -1;
-}
-
-/* (8) Assert valid frame signal to begin sending commands to
-* AC97 codec */
-cs4281_wr(sc,
-CS4281PCI_ACCTL,
-CS4281PCI_ACCTL_VFRM | CS4281PCI_ACCTL_ESYN);
-
-/* (9) Wait for codec calibration */
-for(i = 0 ; i < 1000; i++) {
-DELAY(10000);
-v = cs4281_rdcd(0, sc, AC97_REG_POWER);
-if ((v & 0x0f) == 0x0f) {
-break;
-}
-}
-if (i == 1000) {
-device_printf(sc->dev, "codec failed to calibraten");
-return -1;
-}
-
-/* (10) Set AC97 timing */
-cs4281_wr(sc, CS4281PCI_SERMC, CS4281PCI_SERMC_PTC_AC97);
-
-/* (11) Wait for valid data to arrive */
-if (cs4281_waitset(sc,
-CS4281PCI_ACISV,
-CS4281PCI_ACISV_ISV(3) | CS4281PCI_ACISV_ISV(4),
-10000) == 0) {
-device_printf(sc->dev, "cs4281 never got valid datan");
-return -1;
-}
-
-/* (12) Start digital data transfer of audio data to codec */
-cs4281_wr(sc,
-CS4281PCI_ACOSV,
-CS4281PCI_ACOSV_SLV(3) | CS4281PCI_ACOSV_SLV(4));
-
-/* Set Master and headphone to max */
-cs4281_wrcd(0, sc, AC97_MIX_AUXOUT, 0);
-cs4281_wrcd(0, sc, AC97_MIX_MASTER, 0);
-
-/* Power on the DAC */
-v = cs4281_rdcd(0, sc, AC97_REG_POWER) & 0xfdff;
-cs4281_wrcd(0, sc, AC97_REG_POWER, v);
-
-/* Wait until DAC state ready */
-for(i = 0; i < 320; i++) {
-DELAY(100);
-v = cs4281_rdcd(0, sc, AC97_REG_POWER);
-if (v & 0x02) break;
-}
-
-/* Power on the ADC */
-v = cs4281_rdcd(0, sc, AC97_REG_POWER) & 0xfeff;
-cs4281_wrcd(0, sc, AC97_REG_POWER, v);
-
-/* Wait until ADC state ready */
-for(i = 0; i < 320; i++) {
-DELAY(100);
-v = cs4281_rdcd(0, sc, AC97_REG_POWER);
-if (v & 0x01) break;
-}
-
-/* FIFO configuration (driver is DMA orientated, implicit FIFO) */
-/* Play FIFO */
-
-v = CS4281PCI_FCR_RS(CS4281PCI_RPCM_PLAY_SLOT) |
-CS4281PCI_FCR_LS(CS4281PCI_LPCM_PLAY_SLOT) |
-CS4281PCI_FCR_SZ(CS4281_FIFO_SIZE)|
-CS4281PCI_FCR_OF(0);
-cs4281_wr(sc, CS4281PCI_FCR(CS4281_DMA_PLAY), v);
-
-cs4281_wr(sc, CS4281PCI_FCR(CS4281_DMA_PLAY), v | CS4281PCI_FCR_FEN);
-
-/* Record FIFO */
-v = CS4281PCI_FCR_RS(CS4281PCI_RPCM_REC_SLOT) |
-CS4281PCI_FCR_LS(CS4281PCI_LPCM_REC_SLOT) |
-CS4281PCI_FCR_SZ(CS4281_FIFO_SIZE)|
-CS4281PCI_FCR_OF(CS4281_FIFO_SIZE + 1);
-cs4281_wr(sc, CS4281PCI_FCR(CS4281_DMA_REC), v | CS4281PCI_FCR_PSH);
-cs4281_wr(sc, CS4281PCI_FCR(CS4281_DMA_REC), v | CS4281PCI_FCR_FEN);
-
-/* Match AC97 slots to FIFOs */
-v = CS4281PCI_SRCSA_PLSS(CS4281PCI_LPCM_PLAY_SLOT) |
-CS4281PCI_SRCSA_PRSS(CS4281PCI_RPCM_PLAY_SLOT) |
-CS4281PCI_SRCSA_CLSS(CS4281PCI_LPCM_REC_SLOT) |
-CS4281PCI_SRCSA_CRSS(CS4281PCI_RPCM_REC_SLOT);
-cs4281_wr(sc, CS4281PCI_SRCSA, v);
-
-/* Set Auto-Initialize and set directions */
-cs4281_wr(sc,
-CS4281PCI_DMR(CS4281_DMA_PLAY),
-CS4281PCI_DMR_DMA |
-CS4281PCI_DMR_AUTO |
-CS4281PCI_DMR_TR_PLAY);
-cs4281_wr(sc,
-CS4281PCI_DMR(CS4281_DMA_REC),
-CS4281PCI_DMR_DMA |
-CS4281PCI_DMR_AUTO |
-CS4281PCI_DMR_TR_REC);
-
-/* Enable half and empty buffer interrupts keeping DMA paused */
-cs4281_wr(sc,
-CS4281PCI_DCR(CS4281_DMA_PLAY),
-CS4281PCI_DCR_TCIE | CS4281PCI_DCR_HTCIE | CS4281PCI_DCR_MSK);
-cs4281_wr(sc,
-CS4281PCI_DCR(CS4281_DMA_REC),
-CS4281PCI_DCR_TCIE | CS4281PCI_DCR_HTCIE | CS4281PCI_DCR_MSK);
-
-/* Enable Interrupts */
-cs4281_clr4(sc,
-CS4281PCI_HIMR,
-CS4281PCI_HIMR_DMAI |
-CS4281PCI_HIMR_DMA(CS4281_DMA_PLAY) |
-CS4281PCI_HIMR_DMA(CS4281_DMA_REC));
-
-/* Set playback volume */
-cs4281_wr(sc, CS4281PCI_PPLVC, 7);
-cs4281_wr(sc, CS4281PCI_PPRVC, 7);
+ /* (0) Blast clock register and serial port */
+ cs4281_wr(sc, CS4281PCI_CLKCR1, 0);
+ cs4281_wr(sc, CS4281PCI_SERMC, 0);
+
+ /* (1) Make ESYN 0 to turn sync pulse on AC97 link */
+ cs4281_wr(sc, CS4281PCI_ACCTL, 0);
+ DELAY(50);
+
+ /* (2) Effect Reset */
+ cs4281_wr(sc, CS4281PCI_SPMC, 0);
+ DELAY(100);
+ cs4281_wr(sc, CS4281PCI_SPMC, CS4281PCI_SPMC_RSTN);
+ /* Wait 50ms for ABITCLK to become stable */
+ DELAY(50000);
+
+ /* (3) Enable Sound System Clocks */
+ cs4281_wr(sc, CS4281PCI_CLKCR1, CS4281PCI_CLKCR1_DLLP);
+ DELAY(50000); /* Wait for PLL to stabilize */
+ cs4281_wr(sc, CS4281PCI_CLKCR1,
+ CS4281PCI_CLKCR1_DLLP | CS4281PCI_CLKCR1_SWCE);
+
+ /* (4) Power Up - this combination is essential. */
+ cs4281_set4(sc, CS4281PCI_SSPM,
+ CS4281PCI_SSPM_ACLEN | CS4281PCI_SSPM_PSRCEN |
+ CS4281PCI_SSPM_CSRCEN | CS4281PCI_SSPM_MIXEN);
+
+ /* (5) Wait for clock stabilization */
+ if (cs4281_waitset(sc,
+ CS4281PCI_CLKCR1,
+ CS4281PCI_CLKCR1_DLLRDY,
+ 250) == 0) {
+ device_printf(sc->dev, "Clock stabilization failed\n");
+ return -1;
+ }
+
+ /* (6) Enable ASYNC generation. */
+ cs4281_wr(sc, CS4281PCI_ACCTL,CS4281PCI_ACCTL_ESYN);
+
+ /* Wait to allow AC97 to start generating clock bit */
+ DELAY(50000);
+
+ /* Set AC97 timing */
+ cs4281_wr(sc, CS4281PCI_SERMC, CS4281PCI_SERMC_PTC_AC97);
+
+ /* (7) Wait for AC97 ready signal */
+ if (cs4281_waitset(sc, CS4281PCI_ACSTS, CS4281PCI_ACSTS_CRDY, 250) == 0) {
+ device_printf(sc->dev, "codec did not avail\n");
+ return -1;
+ }
+
+ /* (8) Assert valid frame signal to begin sending commands to
+ * AC97 codec */
+ cs4281_wr(sc,
+ CS4281PCI_ACCTL,
+ CS4281PCI_ACCTL_VFRM | CS4281PCI_ACCTL_ESYN);
+
+ /* (9) Wait for codec calibration */
+ for(i = 0 ; i < 1000; i++) {
+ DELAY(10000);
+ v = cs4281_rdcd(0, sc, AC97_REG_POWER);
+ if ((v & 0x0f) == 0x0f) {
+ break;
+ }
+ }
+ if (i == 1000) {
+ device_printf(sc->dev, "codec failed to calibrate\n");
+ return -1;
+ }
+
+ /* (10) Set AC97 timing */
+ cs4281_wr(sc, CS4281PCI_SERMC, CS4281PCI_SERMC_PTC_AC97);
+
+ /* (11) Wait for valid data to arrive */
+ if (cs4281_waitset(sc,
+ CS4281PCI_ACISV,
+ CS4281PCI_ACISV_ISV(3) | CS4281PCI_ACISV_ISV(4),
+ 10000) == 0) {
+ device_printf(sc->dev, "cs4281 never got valid data\n");
+ return -1;
+ }
+
+ /* (12) Start digital data transfer of audio data to codec */
+ cs4281_wr(sc,
+ CS4281PCI_ACOSV,
+ CS4281PCI_ACOSV_SLV(3) | CS4281PCI_ACOSV_SLV(4));
+
+ /* Set Master and headphone to max */
+ cs4281_wrcd(0, sc, AC97_MIX_AUXOUT, 0);
+ cs4281_wrcd(0, sc, AC97_MIX_MASTER, 0);
+
+ /* Power on the DAC */
+ v = cs4281_rdcd(0, sc, AC97_REG_POWER) & 0xfdff;
+ cs4281_wrcd(0, sc, AC97_REG_POWER, v);
+
+ /* Wait until DAC state ready */
+ for(i = 0; i < 320; i++) {
+ DELAY(100);
+ v = cs4281_rdcd(0, sc, AC97_REG_POWER);
+ if (v & 0x02) break;
+ }
+
+ /* Power on the ADC */
+ v = cs4281_rdcd(0, sc, AC97_REG_POWER) & 0xfeff;
+ cs4281_wrcd(0, sc, AC97_REG_POWER, v);
+
+ /* Wait until ADC state ready */
+ for(i = 0; i < 320; i++) {
+ DELAY(100);
+ v = cs4281_rdcd(0, sc, AC97_REG_POWER);
+ if (v & 0x01) break;
+ }
+
+ /* FIFO configuration (driver is DMA orientated, implicit FIFO) */
+ /* Play FIFO */
+
+ v = CS4281PCI_FCR_RS(CS4281PCI_RPCM_PLAY_SLOT) |
+ CS4281PCI_FCR_LS(CS4281PCI_LPCM_PLAY_SLOT) |
+ CS4281PCI_FCR_SZ(CS4281_FIFO_SIZE)|
+ CS4281PCI_FCR_OF(0);
+ cs4281_wr(sc, CS4281PCI_FCR(CS4281_DMA_PLAY), v);
+
+ cs4281_wr(sc, CS4281PCI_FCR(CS4281_DMA_PLAY), v | CS4281PCI_FCR_FEN);
+
+ /* Record FIFO */
+ v = CS4281PCI_FCR_RS(CS4281PCI_RPCM_REC_SLOT) |
+ CS4281PCI_FCR_LS(CS4281PCI_LPCM_REC_SLOT) |
+ CS4281PCI_FCR_SZ(CS4281_FIFO_SIZE)|
+ CS4281PCI_FCR_OF(CS4281_FIFO_SIZE + 1);
+ cs4281_wr(sc, CS4281PCI_FCR(CS4281_DMA_REC), v | CS4281PCI_FCR_PSH);
+ cs4281_wr(sc, CS4281PCI_FCR(CS4281_DMA_REC), v | CS4281PCI_FCR_FEN);
+
+ /* Match AC97 slots to FIFOs */
+ v = CS4281PCI_SRCSA_PLSS(CS4281PCI_LPCM_PLAY_SLOT) |
+ CS4281PCI_SRCSA_PRSS(CS4281PCI_RPCM_PLAY_SLOT) |
+ CS4281PCI_SRCSA_CLSS(CS4281PCI_LPCM_REC_SLOT) |
+ CS4281PCI_SRCSA_CRSS(CS4281PCI_RPCM_REC_SLOT);
+ cs4281_wr(sc, CS4281PCI_SRCSA, v);
+
+ /* Set Auto-Initialize and set directions */
+ cs4281_wr(sc,
+ CS4281PCI_DMR(CS4281_DMA_PLAY),
+ CS4281PCI_DMR_DMA |
+ CS4281PCI_DMR_AUTO |
+ CS4281PCI_DMR_TR_PLAY);
+ cs4281_wr(sc,
+ CS4281PCI_DMR(CS4281_DMA_REC),
+ CS4281PCI_DMR_DMA |
+ CS4281PCI_DMR_AUTO |
+ CS4281PCI_DMR_TR_REC);
+
+ /* Enable half and empty buffer interrupts keeping DMA paused */
+ cs4281_wr(sc,
+ CS4281PCI_DCR(CS4281_DMA_PLAY),
+ CS4281PCI_DCR_TCIE | CS4281PCI_DCR_HTCIE | CS4281PCI_DCR_MSK);
+ cs4281_wr(sc,
+ CS4281PCI_DCR(CS4281_DMA_REC),
+ CS4281PCI_DCR_TCIE | CS4281PCI_DCR_HTCIE | CS4281PCI_DCR_MSK);
+
+ /* Enable Interrupts */
+ cs4281_clr4(sc,
+ CS4281PCI_HIMR,
+ CS4281PCI_HIMR_DMAI |
+ CS4281PCI_HIMR_DMA(CS4281_DMA_PLAY) |
+ CS4281PCI_HIMR_DMA(CS4281_DMA_REC));
+
+ /* Set playback volume */
+ cs4281_wr(sc, CS4281PCI_PPLVC, 7);
+ cs4281_wr(sc, CS4281PCI_PPRVC, 7);
-return 0;
+ return 0;
}
/* -------------------------------------------------------------------- */
@@ -732,247 +733,244 @@
static int
cs4281_pci_probe(device_t dev)
{
-char *s = NULL;
+ char *s = NULL;
-switch (pci_get_devid(dev)) {
-case CS4281_PCI_ID:
-s = "Crystal Semiconductor CS4281";
-break;
-}
-
-if (s)
-device_set_desc(dev, s);
-return s ? BUS_PROBE_DEFAULT : ENXIO;
+ switch (pci_get_devid(dev)) {
+ case CS4281_PCI_ID:
+ s = "Crystal Semiconductor CS4281";
+ break;
+ }
+
+ if (s)
+ device_set_desc(dev, s);
+ return s ? BUS_PROBE_DEFAULT : ENXIO;
}
static int
cs4281_pci_attach(device_t dev)
{
-struct sc_info *sc;
-struct ac97_info *codec = NULL;
-u_int32_t data;
-char status[SND_STATUSLEN];
-
-if ((sc = malloc(sizeof(*sc), M_DEVBUF, M_NOWAIT | M_ZERO)) == NULL) {
-device_printf(dev, "cannot allocate softcn");
-return ENXIO;
-}
-
-sc->dev = dev;
-sc->type = pci_get_devid(dev);
-
-data = pci_read_config(dev, PCIR_COMMAND, 2);
-data |= (PCIM_CMD_PORTEN | PCIM_CMD_MEMEN | PCIM_CMD_BUSMASTEREN);
-pci_write_config(dev, PCIR_COMMAND, data, 2);
+ struct sc_info *sc;
+ struct ac97_info *codec = NULL;
+ u_int32_t data;
+ char status[SND_STATUSLEN];
+
+ sc = malloc(sizeof(*sc), M_DEVBUF, M_WAITOK | M_ZERO);
+ sc->dev = dev;
+ sc->type = pci_get_devid(dev);
+
+ data = pci_read_config(dev, PCIR_COMMAND, 2);
+ data |= (PCIM_CMD_PORTEN | PCIM_CMD_MEMEN | PCIM_CMD_BUSMASTEREN);
+ pci_write_config(dev, PCIR_COMMAND, data, 2);
#if __FreeBSD_version > 500000
-if (pci_get_powerstate(dev) != PCI_POWERSTATE_D0) {
-/* Reset the power state. */
-device_printf(dev, "chip is in D%d power mode "
-"-- setting to D0n", pci_get_powerstate(dev));
+ if (pci_get_powerstate(dev) != PCI_POWERSTATE_D0) {
+ /* Reset the power state. */
+ device_printf(dev, "chip is in D%d power mode "
+ "-- setting to D0\n", pci_get_powerstate(dev));
-pci_set_powerstate(dev, PCI_POWERSTATE_D0);
-}
+ pci_set_powerstate(dev, PCI_POWERSTATE_D0);
+ }
#else
-data = pci_read_config(dev, CS4281PCI_PMCS_OFFSET, 4);
-if (data & CS4281PCI_PMCS_PS_MASK) {
-/* Reset the power state. */
-device_printf(dev, "chip is in D%d power mode "
-"-- setting to D0n",
-data & CS4281PCI_PMCS_PS_MASK);
-pci_write_config(dev, CS4281PCI_PMCS_OFFSET,
-data & ~CS4281PCI_PMCS_PS_MASK, 4);
-}
+ data = pci_read_config(dev, CS4281PCI_PMCS_OFFSET, 4);
+ if (data & CS4281PCI_PMCS_PS_MASK) {
+ /* Reset the power state. */
+ device_printf(dev, "chip is in D%d power mode "
+ "-- setting to D0\n",
+ data & CS4281PCI_PMCS_PS_MASK);
+ pci_write_config(dev, CS4281PCI_PMCS_OFFSET,
+ data & ~CS4281PCI_PMCS_PS_MASK, 4);
+ }
#endif
-sc->regid = PCIR_BAR(0);
-sc->regtype = SYS_RES_MEMORY;
-sc->reg = bus_alloc_resource(dev, sc->regtype, &sc->regid,
-0, ~0, CS4281PCI_BA0_SIZE, RF_ACTIVE);
-if (!sc->reg) {
-sc->regtype = SYS_RES_IOPORT;
-sc->reg = bus_alloc_resource(dev, sc->regtype, &sc->regid,
-0, ~0, CS4281PCI_BA0_SIZE, RF_ACTIVE);
-if (!sc->reg) {
-device_printf(dev, "unable to allocate register spacen");
-goto bad;
-}
-}
-sc->st = rman_get_bustag(sc->reg);
-sc->sh = rman_get_bushandle(sc->reg);
-
-sc->memid = PCIR_BAR(1);
-sc->mem = bus_alloc_resource(dev, SYS_RES_MEMORY, &sc->memid, 0,
-~0, CS4281PCI_BA1_SIZE, RF_ACTIVE);
-if (sc->mem == NULL) {
-device_printf(dev, "unable to allocate fifo spacen");
-goto bad;
-}
-
-sc->irqid = 0;
-sc->irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &sc->irqid,
-RF_ACTIVE | RF_SHAREABLE);
-if (!sc->irq) {
-device_printf(dev, "unable to allocate interruptn");
-goto bad;
-}
-
-if (snd_setup_intr(dev, sc->irq, 0, cs4281_intr, sc, &sc->ih)) {
-device_printf(dev, "unable to setup interruptn");
-goto bad;
-}
-
-sc->bufsz = pcm_getbuffersize(dev, 4096, CS4281_DEFAULT_BUFSZ, 65536);
-
-if (bus_dma_tag_create(/*parent*/NULL, /*alignment*/2, /*boundary*/0,
-/*lowaddr*/BUS_SPACE_MAXADDR_32BIT,
-/*highaddr*/BUS_SPACE_MAXADDR,
-/*filter*/NULL, /*filterarg*/NULL,
-/*maxsize*/sc->bufsz, /*nsegments*/1,
-/*maxsegz*/0x3ffff,
-/*flags*/0, /*lockfunc*/busdma_lock_mutex,
-/*lockarg*/&Giant, &sc->parent_dmat) != 0) {
-device_printf(dev, "unable to create dma tagn");
-goto bad;
-}
-
-/* power up */
-cs4281_power(sc, 0);
-
-/* init chip */
-if (cs4281_init(sc) == -1) {
-device_printf(dev, "unable to initialize the cardn");
-goto bad;
-}
-
-/* create/init mixer */
-codec = AC97_CREATE(dev, sc, cs4281_ac97);
-if (codec == NULL)
-goto bad;
-
-mixer_init(dev, ac97_getmixerclass(), codec);
-
-if (pcm_register(dev, sc, 1, 1))
-goto bad;
-
-pcm_addchan(dev, PCMDIR_PLAY, &cs4281chan_class, sc);
-pcm_addchan(dev, PCMDIR_REC, &cs4281chan_class, sc);
-
-snprintf(status, SND_STATUSLEN, "at %s 0x%lx irq %ld %s",
-(sc->regtype == SYS_RES_IOPORT)? "io" : "memory",
-rman_get_start(sc->reg), rman_get_start(sc->irq),PCM_KLDSTRING(snd_cs4281));
-pcm_setstatus(dev, status);
-
-return 0;
-
-bad:
-if (codec)
-ac97_destroy(codec);
-if (sc->reg)
-bus_release_resource(dev, sc->regtype, sc->regid, sc->reg);
-if (sc->mem)
-bus_release_resource(dev, SYS_RES_MEMORY, sc->memid, sc->mem);
-if (sc->ih)
-bus_teardown_intr(dev, sc->irq, sc->ih);
-if (sc->irq)
-bus_release_resource(dev, SYS_RES_IRQ, sc->irqid, sc->irq);
-if (sc->parent_dmat)
-bus_dma_tag_destroy(sc->parent_dmat);
-free(sc, M_DEVBUF);
+ sc->regid = PCIR_BAR(0);
+ sc->regtype = SYS_RES_MEMORY;
+ sc->reg = bus_alloc_resource(dev, sc->regtype, &sc->regid,
+ 0, ~0, CS4281PCI_BA0_SIZE, RF_ACTIVE);
+ if (!sc->reg) {
+ sc->regtype = SYS_RES_IOPORT;
+ sc->reg = bus_alloc_resource(dev, sc->regtype, &sc->regid,
+ 0, ~0, CS4281PCI_BA0_SIZE, RF_ACTIVE);
+ if (!sc->reg) {
+ device_printf(dev, "unable to allocate register space\n");
+ goto bad;
+ }
+ }
+ sc->st = rman_get_bustag(sc->reg);
+ sc->sh = rman_get_bushandle(sc->reg);
+
+ sc->memid = PCIR_BAR(1);
+ sc->mem = bus_alloc_resource(dev, SYS_RES_MEMORY, &sc->memid, 0,
+ ~0, CS4281PCI_BA1_SIZE, RF_ACTIVE);
+ if (sc->mem == NULL) {
+ device_printf(dev, "unable to allocate fifo space\n");
+ goto bad;
+ }
+
+ sc->irqid = 0;
+ sc->irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &sc->irqid,
+ RF_ACTIVE | RF_SHAREABLE);
+ if (!sc->irq) {
+ device_printf(dev, "unable to allocate interrupt\n");
+ goto bad;
+ }
+
+ if (snd_setup_intr(dev, sc->irq, 0, cs4281_intr, sc, &sc->ih)) {
+ device_printf(dev, "unable to setup interrupt\n");
+ goto bad;
+ }
+
+ sc->bufsz = pcm_getbuffersize(dev, 4096, CS4281_DEFAULT_BUFSZ, 65536);
+
+ if (bus_dma_tag_create(/*parent*/bus_get_dma_tag(dev), /*alignment*/2,
+ /*boundary*/0,
+ /*lowaddr*/BUS_SPACE_MAXADDR_32BIT,
+ /*highaddr*/BUS_SPACE_MAXADDR,
+ /*filter*/NULL, /*filterarg*/NULL,
+ /*maxsize*/sc->bufsz, /*nsegments*/1,
+ /*maxsegz*/0x3ffff,
+ /*flags*/0, /*lockfunc*/busdma_lock_mutex,
+ /*lockarg*/&Giant, &sc->parent_dmat) != 0) {
+ device_printf(dev, "unable to create dma tag\n");
+ goto bad;
+ }
+
+ /* power up */
+ cs4281_power(sc, 0);
+
+ /* init chip */
+ if (cs4281_init(sc) == -1) {
+ device_printf(dev, "unable to initialize the card\n");
+ goto bad;
+ }
+
+ /* create/init mixer */
+ codec = AC97_CREATE(dev, sc, cs4281_ac97);
+ if (codec == NULL)
+ goto bad;
+
+ mixer_init(dev, ac97_getmixerclass(), codec);
+
+ if (pcm_register(dev, sc, 1, 1))
+ goto bad;
+
+ pcm_addchan(dev, PCMDIR_PLAY, &cs4281chan_class, sc);
+ pcm_addchan(dev, PCMDIR_REC, &cs4281chan_class, sc);
+
+ snprintf(status, SND_STATUSLEN, "at %s 0x%lx irq %ld %s",
+ (sc->regtype == SYS_RES_IOPORT)? "io" : "memory",
+ rman_get_start(sc->reg), rman_get_start(sc->irq),PCM_KLDSTRING(snd_cs4281));
+ pcm_setstatus(dev, status);
+
+ return 0;
+
+ bad:
+ if (codec)
+ ac97_destroy(codec);
+ if (sc->reg)
+ bus_release_resource(dev, sc->regtype, sc->regid, sc->reg);
+ if (sc->mem)
+ bus_release_resource(dev, SYS_RES_MEMORY, sc->memid, sc->mem);
+ if (sc->ih)
+ bus_teardown_intr(dev, sc->irq, sc->ih);
+ if (sc->irq)
+ bus_release_resource(dev, SYS_RES_IRQ, sc->irqid, sc->irq);
+ if (sc->parent_dmat)
+ bus_dma_tag_destroy(sc->parent_dmat);
+ free(sc, M_DEVBUF);
-return ENXIO;
+ return ENXIO;
}
static int
cs4281_pci_detach(device_t dev)
{
-int r;
-struct sc_info *sc;
+ int r;
+ struct sc_info *sc;
-r = pcm_unregister(dev);
-if (r)
-return r;
-
-sc = pcm_getdevinfo(dev);
-
-/* power off */
-cs4281_power(sc, 3);
-
-bus_release_resource(dev, sc->regtype, sc->regid, sc->reg);
-bus_release_resource(dev, SYS_RES_MEMORY, sc->memid, sc->mem);
-bus_teardown_intr(dev, sc->irq, sc->ih);
-bus_release_resource(dev, SYS_RES_IRQ, sc->irqid, sc->irq);
-bus_dma_tag_destroy(sc->parent_dmat);
-free(sc, M_DEVBUF);
+ r = pcm_unregister(dev);
+ if (r)
+ return r;
+
+ sc = pcm_getdevinfo(dev);
+
+ /* power off */
+ cs4281_power(sc, 3);
+
+ bus_release_resource(dev, sc->regtype, sc->regid, sc->reg);
+ bus_release_resource(dev, SYS_RES_MEMORY, sc->memid, sc->mem);
+ bus_teardown_intr(dev, sc->irq, sc->ih);
+ bus_release_resource(dev, SYS_RES_IRQ, sc->irqid, sc->irq);
+ bus_dma_tag_destroy(sc->parent_dmat);
+ free(sc, M_DEVBUF);
-return 0;
+ return 0;
}
static int
cs4281_pci_suspend(device_t dev)
{
-struct sc_info *sc;
+ struct sc_info *sc;
-sc = pcm_getdevinfo(dev);
+ sc = pcm_getdevinfo(dev);
-sc->rch.dma_active = adcdac_go(&sc->rch, 0);
-sc->pch.dma_active = adcdac_go(&sc->pch, 0);
+ sc->rch.dma_active = adcdac_go(&sc->rch, 0);
+ sc->pch.dma_active = adcdac_go(&sc->pch, 0);
-cs4281_power(sc, 3);
+ cs4281_power(sc, 3);
-return 0;
+ return 0;
}
static int
cs4281_pci_resume(device_t dev)
{
-struct sc_info *sc;
-
-sc = pcm_getdevinfo(dev);
-
-/* power up */
-cs4281_power(sc, 0);
+ struct sc_info *sc;
-/* initialize chip */
-if (cs4281_init(sc) == -1) {
-device_printf(dev, "unable to reinitialize the cardn");
-return ENXIO;
-}
-
-/* restore mixer state */
-if (mixer_reinit(dev) == -1) {
-device_printf(dev, "unable to reinitialize the mixern");
-return ENXIO;
-}
+ sc = pcm_getdevinfo(dev);
-/* restore chip state */
-cs4281chan_setspeed(NULL, &sc->rch, sc->rch.spd);
-cs4281chan_setblocksize(NULL, &sc->rch, sc->rch.blksz);
-cs4281chan_setformat(NULL, &sc->rch, sc->rch.fmt);
-adcdac_go(&sc->rch, sc->rch.dma_active);
+ /* power up */
+ cs4281_power(sc, 0);
-cs4281chan_setspeed(NULL, &sc->pch, sc->pch.spd);
-cs4281chan_setblocksize(NULL, &sc->pch, sc->pch.blksz);
-cs4281chan_setformat(NULL, &sc->pch, sc->pch.fmt);
-adcdac_go(&sc->pch, sc->pch.dma_active);
+ /* initialize chip */
+ if (cs4281_init(sc) == -1) {
+ device_printf(dev, "unable to reinitialize the card\n");
+ return ENXIO;
+ }
+
+ /* restore mixer state */
+ if (mixer_reinit(dev) == -1) {
+ device_printf(dev, "unable to reinitialize the mixer\n");
+ return ENXIO;
+ }
+
+ /* restore chip state */
+ cs4281chan_setspeed(NULL, &sc->rch, sc->rch.spd);
+ cs4281chan_setblocksize(NULL, &sc->rch, sc->rch.blksz);
+ cs4281chan_setformat(NULL, &sc->rch, sc->rch.fmt);
+ adcdac_go(&sc->rch, sc->rch.dma_active);
+
+ cs4281chan_setspeed(NULL, &sc->pch, sc->pch.spd);
+ cs4281chan_setblocksize(NULL, &sc->pch, sc->pch.blksz);
+ cs4281chan_setformat(NULL, &sc->pch, sc->pch.fmt);
+ adcdac_go(&sc->pch, sc->pch.dma_active);
-return 0;
+ return 0;
}
static device_method_t cs4281_methods[] = {
-/* Device interface */
-DEVMETHOD(device_probe, cs4281_pci_probe),
-DEVMETHOD(device_attach, cs4281_pci_attach),
-DEVMETHOD(device_detach, cs4281_pci_detach),
-DEVMETHOD(device_suspend, cs4281_pci_suspend),
-DEVMETHOD(device_resume, cs4281_pci_resume),
-{ 0, 0 }
+ /* Device interface */
+ DEVMETHOD(device_probe, cs4281_pci_probe),
+ DEVMETHOD(device_attach, cs4281_pci_attach),
+ DEVMETHOD(device_detach, cs4281_pci_detach),
+ DEVMETHOD(device_suspend, cs4281_pci_suspend),
+ DEVMETHOD(device_resume, cs4281_pci_resume),
+ { 0, 0 }
};
static driver_t cs4281_driver = {
-"pcm",
-cs4281_methods,
-PCM_SOFTC_SIZE,
+ "pcm",
+ cs4281_methods,
+ PCM_SOFTC_SIZE,
};
DRIVER_MODULE(snd_cs4281, pci, cs4281_driver, pcm_devclass, 0, 0);
Index: als4000.c
===================================================================
RCS file: /home/cvs/src/sys/dev/sound/pci/als4000.c,v
retrieving revision 1.2
retrieving revision 1.3
diff -L sys/dev/sound/pci/als4000.c -L sys/dev/sound/pci/als4000.c -u -r1.2 -r1.3
--- sys/dev/sound/pci/als4000.c
+++ sys/dev/sound/pci/als4000.c
@@ -1,37 +1,37 @@
/*-
-* Copyright (c) 2001 Orion Hodson <oho at acm.org>
-* All rights reserved.
-*
-* Redistribution and use in source and binary forms, with or without
-* modification, are permitted provided that the following conditions
-* are met:
-* 1. Redistributions of source code must retain the above copyright
-* notice, this list of conditions and the following disclaimer.
-* 2. Redistributions in binary form must reproduce the above copyright
-* notice, this list of conditions and the following disclaimer in the
-* documentation and/or other materials provided with the distribution.
-*
-* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
-* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
-* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
-* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
-* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHERIN CONTRACT, STRICT
-* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
-* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THEPOSSIBILITY OF
-* SUCH DAMAGE.
-*/
+ * Copyright (c) 2001 Orion Hodson <oho at acm.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHERIN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THEPOSSIBILITY OF
+ * SUCH DAMAGE.
+ */
/*
-* als4000.c - driver for the Avance Logic ALS 4000 chipset.
-*
-* The ALS4000 is effectively an SB16 with a PCI interface.
-*
-* This driver derives from ALS4000a.PDF, Bart Hartgers alsa driver, and
-* SB16 register descriptions.
-*/
+ * als4000.c - driver for the Avance Logic ALS 4000 chipset.
+ *
+ * The ALS4000 is effectively an SB16 with a PCI interface.
+ *
+ * This driver derives from ALS4000a.PDF, Bart Hartgers alsa driver, and
+ * SB16 register descriptions.
+ */
#include <dev/sound/pcm/sound.h>
#include <dev/sound/isa/sb.h>
@@ -42,7 +42,7 @@
#include "mixer_if.h"
-SND_DECLARE_FILE("$MidnightBSD$");
+SND_DECLARE_FILE("$FreeBSD: src/sys/dev/sound/pci/als4000.c,v 1.27 2007/06/17 06:10:41 ariff Exp $");
/* Debugging macro's */
#undef DEB
@@ -58,43 +58,43 @@
struct sc_info;
struct sc_chinfo {
-struct sc_info *parent;
-struct pcm_channel *channel;
-struct snd_dbuf *buffer;
-u_int32_t format, speed, phys_buf, bps;
-u_int32_t dma_active:1, dma_was_active:1;
-u_int8_t gcr_fifo_status;
-int dir;
+ struct sc_info *parent;
+ struct pcm_channel *channel;
+ struct snd_dbuf *buffer;
+ u_int32_t format, speed, phys_buf, bps;
+ u_int32_t dma_active:1, dma_was_active:1;
+ u_int8_t gcr_fifo_status;
+ int dir;
};
struct sc_info {
-device_t dev;
-bus_space_tag_t st;
-bus_space_handle_t sh;
-bus_dma_tag_t parent_dmat;
-struct resource *reg, *irq;
-int regid, irqid;
-void *ih;
-struct mtx *lock;
+ device_t dev;
+ bus_space_tag_t st;
+ bus_space_handle_t sh;
+ bus_dma_tag_t parent_dmat;
+ struct resource *reg, *irq;
+ int regid, irqid;
+ void *ih;
+ struct mtx *lock;
-unsigned int bufsz;
-struct sc_chinfo pch, rch;
+ unsigned int bufsz;
+ struct sc_chinfo pch, rch;
};
/* Channel caps */
static u_int32_t als_format[] = {
-AFMT_U8,
-AFMT_STEREO | AFMT_U8,
-AFMT_S16_LE,
-AFMT_STEREO | AFMT_S16_LE,
-0
+ AFMT_U8,
+ AFMT_STEREO | AFMT_U8,
+ AFMT_S16_LE,
+ AFMT_STEREO | AFMT_S16_LE,
+ 0
};
/*
-* I don't believe this rotten soundcard can do 48k, really,
-* trust me.
-*/
+ * I don't believe this rotten soundcard can do 48k, really,
+ * trust me.
+ */
static struct pcmchan_caps als_caps = { 4000, 44100, als_format, 0 };
/* ------------------------------------------------------------------------- */
@@ -103,95 +103,95 @@
static u_int32_t
als_gcr_rd(struct sc_info *sc, int index)
{
-bus_space_write_1(sc->st, sc->sh, ALS_GCR_INDEX, index);
-return bus_space_read_4(sc->st, sc->sh, ALS_GCR_DATA);
+ bus_space_write_1(sc->st, sc->sh, ALS_GCR_INDEX, index);
+ return bus_space_read_4(sc->st, sc->sh, ALS_GCR_DATA);
}
static void
als_gcr_wr(struct sc_info *sc, int index, int data)
{
-bus_space_write_1(sc->st, sc->sh, ALS_GCR_INDEX, index);
-bus_space_write_4(sc->st, sc->sh, ALS_GCR_DATA, data);
+ bus_space_write_1(sc->st, sc->sh, ALS_GCR_INDEX, index);
+ bus_space_write_4(sc->st, sc->sh, ALS_GCR_DATA, data);
}
static u_int8_t
als_intr_rd(struct sc_info *sc)
{
-return bus_space_read_1(sc->st, sc->sh, ALS_SB_MPU_IRQ);
+ return bus_space_read_1(sc->st, sc->sh, ALS_SB_MPU_IRQ);
}
static void
als_intr_wr(struct sc_info *sc, u_int8_t data)
{
-bus_space_write_1(sc->st, sc->sh, ALS_SB_MPU_IRQ, data);
+ bus_space_write_1(sc->st, sc->sh, ALS_SB_MPU_IRQ, data);
}
static u_int8_t
als_mix_rd(struct sc_info *sc, u_int8_t index)
{
-bus_space_write_1(sc->st, sc->sh, ALS_MIXER_INDEX, index);
-return bus_space_read_1(sc->st, sc->sh, ALS_MIXER_DATA);
+ bus_space_write_1(sc->st, sc->sh, ALS_MIXER_INDEX, index);
+ return bus_space_read_1(sc->st, sc->sh, ALS_MIXER_DATA);
}
static void
als_mix_wr(struct sc_info *sc, u_int8_t index, u_int8_t data)
{
-bus_space_write_1(sc->st, sc->sh, ALS_MIXER_INDEX, index);
-bus_space_write_1(sc->st, sc->sh, ALS_MIXER_DATA, data);
+ bus_space_write_1(sc->st, sc->sh, ALS_MIXER_INDEX, index);
+ bus_space_write_1(sc->st, sc->sh, ALS_MIXER_DATA, data);
}
static void
als_esp_wr(struct sc_info *sc, u_int8_t data)
{
-u_int32_t tries, v;
+ u_int32_t tries, v;
-tries = 1000;
-do {
-v = bus_space_read_1(sc->st, sc->sh, ALS_ESP_WR_STATUS);
-if (~v & 0x80)
-break;
-DELAY(20);
-} while (--tries != 0);
+ tries = 1000;
+ do {
+ v = bus_space_read_1(sc->st, sc->sh, ALS_ESP_WR_STATUS);
+ if (~v & 0x80)
+ break;
+ DELAY(20);
+ } while (--tries != 0);
-if (tries == 0)
-device_printf(sc->dev, "als_esp_wr timeout");
+ if (tries == 0)
+ device_printf(sc->dev, "als_esp_wr timeout");
-bus_space_write_1(sc->st, sc->sh, ALS_ESP_WR_DATA, data);
+ bus_space_write_1(sc->st, sc->sh, ALS_ESP_WR_DATA, data);
}
static int
als_esp_reset(struct sc_info *sc)
{
-u_int32_t tries, u, v;
+ u_int32_t tries, u, v;
-bus_space_write_1(sc->st, sc->sh, ALS_ESP_RST, 1);
-DELAY(10);
-bus_space_write_1(sc->st, sc->sh, ALS_ESP_RST, 0);
-DELAY(30);
-
-tries = 1000;
-do {
-u = bus_space_read_1(sc->st, sc->sh, ALS_ESP_RD_STATUS8);
-if (u & 0x80) {
-v = bus_space_read_1(sc->st, sc->sh, ALS_ESP_RD_DATA);
-if (v == 0xaa)
-return 0;
-else
-break;
-}
-DELAY(20);
-} while (--tries != 0);
-
-if (tries == 0)
-device_printf(sc->dev, "als_esp_reset timeout");
-return 1;
+ bus_space_write_1(sc->st, sc->sh, ALS_ESP_RST, 1);
+ DELAY(10);
+ bus_space_write_1(sc->st, sc->sh, ALS_ESP_RST, 0);
+ DELAY(30);
+
+ tries = 1000;
+ do {
+ u = bus_space_read_1(sc->st, sc->sh, ALS_ESP_RD_STATUS8);
+ if (u & 0x80) {
+ v = bus_space_read_1(sc->st, sc->sh, ALS_ESP_RD_DATA);
+ if (v == 0xaa)
+ return 0;
+ else
+ break;
+ }
+ DELAY(20);
+ } while (--tries != 0);
+
+ if (tries == 0)
+ device_printf(sc->dev, "als_esp_reset timeout");
+ return 1;
}
static u_int8_t
als_ack_read(struct sc_info *sc, u_int8_t addr)
{
-u_int8_t r = bus_space_read_1(sc->st, sc->sh, addr);
-return r;
+ u_int8_t r = bus_space_read_1(sc->st, sc->sh, addr);
+ return r;
}
/* ------------------------------------------------------------------------- */
@@ -199,109 +199,109 @@
static void *
alschan_init(kobj_t obj, void *devinfo,
-struct snd_dbuf *b, struct pcm_channel *c, int dir)
+ struct snd_dbuf *b, struct pcm_channel *c, int dir)
{
-struct sc_info *sc = devinfo;
-struct sc_chinfo *ch;
+ struct sc_info *sc = devinfo;
+ struct sc_chinfo *ch;
-snd_mtxlock(sc->lock);
-if (dir == PCMDIR_PLAY) {
-ch = &sc->pch;
-ch->gcr_fifo_status = ALS_GCR_FIFO0_STATUS;
-} else {
-ch = &sc->rch;
-ch->gcr_fifo_status = ALS_GCR_FIFO1_STATUS;
-}
-ch->dir = dir;
-ch->parent = sc;
-ch->channel = c;
-ch->bps = 1;
-ch->format = AFMT_U8;
-ch->speed = DSP_DEFAULT_SPEED;
-ch->buffer = b;
-snd_mtxunlock(sc->lock);
+ snd_mtxlock(sc->lock);
+ if (dir == PCMDIR_PLAY) {
+ ch = &sc->pch;
+ ch->gcr_fifo_status = ALS_GCR_FIFO0_STATUS;
+ } else {
+ ch = &sc->rch;
+ ch->gcr_fifo_status = ALS_GCR_FIFO1_STATUS;
+ }
+ ch->dir = dir;
+ ch->parent = sc;
+ ch->channel = c;
+ ch->bps = 1;
+ ch->format = AFMT_U8;
+ ch->speed = DSP_DEFAULT_SPEED;
+ ch->buffer = b;
+ snd_mtxunlock(sc->lock);
-if (sndbuf_alloc(ch->buffer, sc->parent_dmat, sc->bufsz) != 0)
-return NULL;
+ if (sndbuf_alloc(ch->buffer, sc->parent_dmat, 0, sc->bufsz) != 0)
+ return NULL;
-return ch;
+ return ch;
}
static int
alschan_setformat(kobj_t obj, void *data, u_int32_t format)
{
-struct sc_chinfo *ch = data;
+ struct sc_chinfo *ch = data;
-ch->format = format;
-return 0;
+ ch->format = format;
+ return 0;
}
static int
alschan_setspeed(kobj_t obj, void *data, u_int32_t speed)
{
-struct sc_chinfo *ch = data, *other;
-struct sc_info *sc = ch->parent;
+ struct sc_chinfo *ch = data, *other;
+ struct sc_info *sc = ch->parent;
-other = (ch->dir == PCMDIR_PLAY) ? &sc->rch : &sc->pch;
+ other = (ch->dir == PCMDIR_PLAY) ? &sc->rch : &sc->pch;
-/* Deny request if other dma channel is active */
-if (other->dma_active) {
-ch->speed = other->speed;
-return other->speed;
-}
+ /* Deny request if other dma channel is active */
+ if (other->dma_active) {
+ ch->speed = other->speed;
+ return other->speed;
+ }
-ch->speed = speed;
-return speed;
+ ch->speed = speed;
+ return speed;
}
static int
alschan_setblocksize(kobj_t obj, void *data, u_int32_t blocksize)
{
-struct sc_chinfo *ch = data;
-struct sc_info *sc = ch->parent;
+ struct sc_chinfo *ch = data;
+ struct sc_info *sc = ch->parent;
-if (blocksize > sc->bufsz / 2) {
-blocksize = sc->bufsz / 2;
-}
-sndbuf_resize(ch->buffer, 2, blocksize);
-return blocksize;
+ if (blocksize > sc->bufsz / 2) {
+ blocksize = sc->bufsz / 2;
+ }
+ sndbuf_resize(ch->buffer, 2, blocksize);
+ return blocksize;
}
static int
alschan_getptr(kobj_t obj, void *data)
{
-struct sc_chinfo *ch = data;
-struct sc_info *sc = ch->parent;
-int32_t pos, sz;
-
-snd_mtxlock(sc->lock);
-pos = als_gcr_rd(ch->parent, ch->gcr_fifo_status) & 0xffff;
-snd_mtxunlock(sc->lock);
-sz = sndbuf_getsize(ch->buffer);
-return (2 * sz - pos - 1) % sz;
+ struct sc_chinfo *ch = data;
+ struct sc_info *sc = ch->parent;
+ int32_t pos, sz;
+
+ snd_mtxlock(sc->lock);
+ pos = als_gcr_rd(ch->parent, ch->gcr_fifo_status) & 0xffff;
+ snd_mtxunlock(sc->lock);
+ sz = sndbuf_getsize(ch->buffer);
+ return (2 * sz - pos - 1) % sz;
}
static struct pcmchan_caps*
alschan_getcaps(kobj_t obj, void *data)
{
-return &als_caps;
+ return &als_caps;
}
static void
als_set_speed(struct sc_chinfo *ch)
{
-struct sc_info *sc = ch->parent;
-struct sc_chinfo *other;
+ struct sc_info *sc = ch->parent;
+ struct sc_chinfo *other;
-other = (ch->dir == PCMDIR_PLAY) ? &sc->rch : &sc->pch;
-if (other->dma_active == 0) {
-als_esp_wr(sc, ALS_ESP_SAMPLE_RATE);
-als_esp_wr(sc, ch->speed >> 8);
-als_esp_wr(sc, ch->speed & 0xff);
-} else {
-DEB(printf("speed locked at %d (tried %d)n",
-other->speed, ch->speed));
-}
+ other = (ch->dir == PCMDIR_PLAY) ? &sc->rch : &sc->pch;
+ if (other->dma_active == 0) {
+ als_esp_wr(sc, ALS_ESP_SAMPLE_RATE);
+ als_esp_wr(sc, ch->speed >> 8);
+ als_esp_wr(sc, ch->speed & 0xff);
+ } else {
+ DEB(printf("speed locked at %d (tried %d)\n",
+ other->speed, ch->speed));
+ }
}
/* ------------------------------------------------------------------------- */
@@ -311,108 +311,114 @@
#define ALS_16BIT_CMD(x, y) { (x), (y), DSP_DMA16, DSP_CMD_DMAPAUSE_16 }
struct playback_command {
-u_int32_t pcm_format; /* newpcm format */
-u_int8_t format_val; /* sb16 format value */
-u_int8_t dma_prog; /* sb16 dma program */
-u_int8_t dma_stop; /* sb16 stop register */
+ u_int32_t pcm_format; /* newpcm format */
+ u_int8_t format_val; /* sb16 format value */
+ u_int8_t dma_prog; /* sb16 dma program */
+ u_int8_t dma_stop; /* sb16 stop register */
} static const playback_cmds[] = {
-ALS_8BIT_CMD(AFMT_U8, DSP_MODE_U8MONO),
-ALS_8BIT_CMD(AFMT_U8 | AFMT_STEREO, DSP_MODE_U8STEREO),
-ALS_16BIT_CMD(AFMT_S16_LE, DSP_MODE_S16MONO),
-ALS_16BIT_CMD(AFMT_S16_LE | AFMT_STEREO, DSP_MODE_S16STEREO),
+ ALS_8BIT_CMD(AFMT_U8, DSP_MODE_U8MONO),
+ ALS_8BIT_CMD(AFMT_U8 | AFMT_STEREO, DSP_MODE_U8STEREO),
+ ALS_16BIT_CMD(AFMT_S16_LE, DSP_MODE_S16MONO),
+ ALS_16BIT_CMD(AFMT_S16_LE | AFMT_STEREO, DSP_MODE_S16STEREO),
};
static const struct playback_command*
als_get_playback_command(u_int32_t format)
{
-u_int32_t i, n;
+ u_int32_t i, n;
-n = sizeof(playback_cmds) / sizeof(playback_cmds[0]);
-for (i = 0; i < n; i++) {
-if (playback_cmds[i].pcm_format == format) {
-return &playback_cmds[i];
-}
-}
-DEB(printf("als_get_playback_command: invalid format 0x%08xn",
-format));
-return &playback_cmds[0];
+ n = sizeof(playback_cmds) / sizeof(playback_cmds[0]);
+ for (i = 0; i < n; i++) {
+ if (playback_cmds[i].pcm_format == format) {
+ return &playback_cmds[i];
+ }
+ }
+ DEB(printf("als_get_playback_command: invalid format 0x%08x\n",
+ format));
+ return &playback_cmds[0];
}
static void
als_playback_start(struct sc_chinfo *ch)
{
-const struct playback_command *p;
-struct sc_info *sc = ch->parent;
-u_int32_t buf, bufsz, count, dma_prog;
-
-buf = sndbuf_getbufaddr(ch->buffer);
-bufsz = sndbuf_getsize(ch->buffer);
-count = bufsz / 2;
-if (ch->format & AFMT_16BIT)
-count /= 2;
-count--;
-
-als_esp_wr(sc, DSP_CMD_SPKON);
-als_set_speed(ch);
-
-als_gcr_wr(sc, ALS_GCR_DMA0_START, buf);
-als_gcr_wr(sc, ALS_GCR_DMA0_MODE, (bufsz - 1) | 0x180000);
-
-p = als_get_playback_command(ch->format);
-dma_prog = p->dma_prog | DSP_F16_DAC | DSP_F16_AUTO | DSP_F16_FIFO_ON;
-
-als_esp_wr(sc, dma_prog);
-als_esp_wr(sc, p->format_val);
-als_esp_wr(sc, count & 0xff);
-als_esp_wr(sc, count >> 8);
+ const struct playback_command *p;
+ struct sc_info *sc = ch->parent;
+ u_int32_t buf, bufsz, count, dma_prog;
+
+ buf = sndbuf_getbufaddr(ch->buffer);
+ bufsz = sndbuf_getsize(ch->buffer);
+ count = bufsz / 2;
+ if (ch->format & AFMT_16BIT)
+ count /= 2;
+ count--;
+
+ als_esp_wr(sc, DSP_CMD_SPKON);
+ als_set_speed(ch);
+
+ als_gcr_wr(sc, ALS_GCR_DMA0_START, buf);
+ als_gcr_wr(sc, ALS_GCR_DMA0_MODE, (bufsz - 1) | 0x180000);
+
+ p = als_get_playback_command(ch->format);
+ dma_prog = p->dma_prog | DSP_F16_DAC | DSP_F16_AUTO | DSP_F16_FIFO_ON;
+
+ als_esp_wr(sc, dma_prog);
+ als_esp_wr(sc, p->format_val);
+ als_esp_wr(sc, count & 0xff);
+ als_esp_wr(sc, count >> 8);
-ch->dma_active = 1;
+ ch->dma_active = 1;
}
static int
als_playback_stop(struct sc_chinfo *ch)
{
-const struct playback_command *p;
-struct sc_info *sc = ch->parent;
-u_int32_t active;
-
-active = ch->dma_active;
-if (active) {
-p = als_get_playback_command(ch->format);
-als_esp_wr(sc, p->dma_stop);
-}
-ch->dma_active = 0;
-return active;
+ const struct playback_command *p;
+ struct sc_info *sc = ch->parent;
+ u_int32_t active;
+
+ active = ch->dma_active;
+ if (active) {
+ p = als_get_playback_command(ch->format);
+ als_esp_wr(sc, p->dma_stop);
+ }
+ ch->dma_active = 0;
+ return active;
}
static int
alspchan_trigger(kobj_t obj, void *data, int go)
{
-struct sc_chinfo *ch = data;
-struct sc_info *sc = ch->parent;
+ struct sc_chinfo *ch = data;
+ struct sc_info *sc = ch->parent;
-snd_mtxlock(sc->lock);
-switch(go) {
-case PCMTRIG_START:
-als_playback_start(ch);
-break;
-case PCMTRIG_ABORT:
-als_playback_stop(ch);
-break;
-}
-snd_mtxunlock(sc->lock);
-return 0;
+ if (!PCMTRIG_COMMON(go))
+ return 0;
+
+ snd_mtxlock(sc->lock);
+ switch(go) {
+ case PCMTRIG_START:
+ als_playback_start(ch);
+ break;
+ case PCMTRIG_STOP:
+ case PCMTRIG_ABORT:
+ als_playback_stop(ch);
+ break;
+ default:
+ break;
+ }
+ snd_mtxunlock(sc->lock);
+ return 0;
}
static kobj_method_t alspchan_methods[] = {
-KOBJMETHOD(channel_init, alschan_init),
-KOBJMETHOD(channel_setformat, alschan_setformat),
-KOBJMETHOD(channel_setspeed, alschan_setspeed),
-KOBJMETHOD(channel_setblocksize, alschan_setblocksize),
-KOBJMETHOD(channel_trigger, alspchan_trigger),
-KOBJMETHOD(channel_getptr, alschan_getptr),
-KOBJMETHOD(channel_getcaps, alschan_getcaps),
-{ 0, 0 }
+ KOBJMETHOD(channel_init, alschan_init),
+ KOBJMETHOD(channel_setformat, alschan_setformat),
+ KOBJMETHOD(channel_setspeed, alschan_setspeed),
+ KOBJMETHOD(channel_setblocksize, alschan_setblocksize),
+ KOBJMETHOD(channel_trigger, alspchan_trigger),
+ KOBJMETHOD(channel_getptr, alschan_getptr),
+ KOBJMETHOD(channel_getcaps, alschan_getcaps),
+ { 0, 0 }
};
CHANNEL_DECLARE(alspchan);
@@ -422,90 +428,91 @@
static u_int8_t
als_get_fifo_format(struct sc_info *sc, u_int32_t format)
{
-switch (format) {
-case AFMT_U8:
-return ALS_FIFO1_8BIT;
-case AFMT_U8 | AFMT_STEREO:
-return ALS_FIFO1_8BIT | ALS_FIFO1_STEREO;
-case AFMT_S16_LE:
-return ALS_FIFO1_SIGNED;
-case AFMT_S16_LE | AFMT_STEREO:
-return ALS_FIFO1_SIGNED | ALS_FIFO1_STEREO;
-}
-device_printf(sc->dev, "format not found: 0x%08xn", format);
-return ALS_FIFO1_8BIT;
+ switch (format) {
+ case AFMT_U8:
+ return ALS_FIFO1_8BIT;
+ case AFMT_U8 | AFMT_STEREO:
+ return ALS_FIFO1_8BIT | ALS_FIFO1_STEREO;
+ case AFMT_S16_LE:
+ return ALS_FIFO1_SIGNED;
+ case AFMT_S16_LE | AFMT_STEREO:
+ return ALS_FIFO1_SIGNED | ALS_FIFO1_STEREO;
+ }
+ device_printf(sc->dev, "format not found: 0x%08x\n", format);
+ return ALS_FIFO1_8BIT;
}
static void
als_capture_start(struct sc_chinfo *ch)
{
-struct sc_info *sc = ch->parent;
-u_int32_t buf, bufsz, count, dma_prog;
+ struct sc_info *sc = ch->parent;
+ u_int32_t buf, bufsz, count, dma_prog;
-buf = sndbuf_getbufaddr(ch->buffer);
-bufsz = sndbuf_getsize(ch->buffer);
-count = bufsz / 2;
-if (ch->format & AFMT_16BIT)
-count /= 2;
-count--;
+ buf = sndbuf_getbufaddr(ch->buffer);
+ bufsz = sndbuf_getsize(ch->buffer);
+ count = bufsz / 2;
+ if (ch->format & AFMT_16BIT)
+ count /= 2;
+ count--;
-als_esp_wr(sc, DSP_CMD_SPKON);
-als_set_speed(ch);
+ als_esp_wr(sc, DSP_CMD_SPKON);
+ als_set_speed(ch);
-als_gcr_wr(sc, ALS_GCR_FIFO1_START, buf);
-als_gcr_wr(sc, ALS_GCR_FIFO1_COUNT, (bufsz - 1));
+ als_gcr_wr(sc, ALS_GCR_FIFO1_START, buf);
+ als_gcr_wr(sc, ALS_GCR_FIFO1_COUNT, (bufsz - 1));
-als_mix_wr(sc, ALS_FIFO1_LENGTH_LO, count & 0xff);
-als_mix_wr(sc, ALS_FIFO1_LENGTH_HI, count >> 8);
+ als_mix_wr(sc, ALS_FIFO1_LENGTH_LO, count & 0xff);
+ als_mix_wr(sc, ALS_FIFO1_LENGTH_HI, count >> 8);
-dma_prog = ALS_FIFO1_RUN | als_get_fifo_format(sc, ch->format);
-als_mix_wr(sc, ALS_FIFO1_CONTROL, dma_prog);
+ dma_prog = ALS_FIFO1_RUN | als_get_fifo_format(sc, ch->format);
+ als_mix_wr(sc, ALS_FIFO1_CONTROL, dma_prog);
-ch->dma_active = 1;
+ ch->dma_active = 1;
}
static int
als_capture_stop(struct sc_chinfo *ch)
{
-struct sc_info *sc = ch->parent;
-u_int32_t active;
+ struct sc_info *sc = ch->parent;
+ u_int32_t active;
-active = ch->dma_active;
-if (active) {
-als_mix_wr(sc, ALS_FIFO1_CONTROL, ALS_FIFO1_STOP);
-}
-ch->dma_active = 0;
-return active;
+ active = ch->dma_active;
+ if (active) {
+ als_mix_wr(sc, ALS_FIFO1_CONTROL, ALS_FIFO1_STOP);
+ }
+ ch->dma_active = 0;
+ return active;
}
static int
alsrchan_trigger(kobj_t obj, void *data, int go)
{
-struct sc_chinfo *ch = data;
-struct sc_info *sc = ch->parent;
+ struct sc_chinfo *ch = data;
+ struct sc_info *sc = ch->parent;
-snd_mtxlock(sc->lock);
-switch(go) {
-case PCMTRIG_START:
-als_capture_start(ch);
-break;
-case PCMTRIG_ABORT:
-als_capture_stop(ch);
-break;
-}
-snd_mtxunlock(sc->lock);
-return 0;
+ snd_mtxlock(sc->lock);
+ switch(go) {
+ case PCMTRIG_START:
+ als_capture_start(ch);
+ break;
+ case PCMTRIG_STOP:
+ case PCMTRIG_ABORT:
+ als_capture_stop(ch);
+ break;
+ }
+ snd_mtxunlock(sc->lock);
+ return 0;
}
static kobj_method_t alsrchan_methods[] = {
-KOBJMETHOD(channel_init, alschan_init),
-KOBJMETHOD(channel_setformat, alschan_setformat),
-KOBJMETHOD(channel_setspeed, alschan_setspeed),
-KOBJMETHOD(channel_setblocksize, alschan_setblocksize),
-KOBJMETHOD(channel_trigger, alsrchan_trigger),
-KOBJMETHOD(channel_getptr, alschan_getptr),
-KOBJMETHOD(channel_getcaps, alschan_getcaps),
-{ 0, 0 }
+ KOBJMETHOD(channel_init, alschan_init),
+ KOBJMETHOD(channel_setformat, alschan_setformat),
+ KOBJMETHOD(channel_setspeed, alschan_setspeed),
+ KOBJMETHOD(channel_setblocksize, alschan_setblocksize),
+ KOBJMETHOD(channel_trigger, alsrchan_trigger),
+ KOBJMETHOD(channel_getptr, alschan_getptr),
+ KOBJMETHOD(channel_getcaps, alschan_getcaps),
+ { 0, 0 }
};
CHANNEL_DECLARE(alsrchan);
@@ -513,108 +520,108 @@
/* Mixer related */
/*
-* ALS4000 has an sb16 mixer, with some additional controls that we do
-* not yet a means to support.
-*/
+ * ALS4000 has an sb16 mixer, with some additional controls that we do
+ * not yet a means to support.
+ */
struct sb16props {
-u_int8_t lreg;
-u_int8_t rreg;
-u_int8_t bits;
-u_int8_t oselect;
-u_int8_t iselect; /* left input mask */
+ u_int8_t lreg;
+ u_int8_t rreg;
+ u_int8_t bits;
+ u_int8_t oselect;
+ u_int8_t iselect; /* left input mask */
} static const amt[SOUND_MIXER_NRDEVICES] = {
-[SOUND_MIXER_VOLUME] = { 0x30, 0x31, 5, 0x00, 0x00 },
-[SOUND_MIXER_PCM] = { 0x32, 0x33, 5, 0x00, 0x00 },
-[SOUND_MIXER_SYNTH] = { 0x34, 0x35, 5, 0x60, 0x40 },
-[SOUND_MIXER_CD] = { 0x36, 0x37, 5, 0x06, 0x04 },
-[SOUND_MIXER_LINE] = { 0x38, 0x39, 5, 0x18, 0x10 },
-[SOUND_MIXER_MIC] = { 0x3a, 0x00, 5, 0x01, 0x01 },
-[SOUND_MIXER_SPEAKER] = { 0x3b, 0x00, 2, 0x00, 0x00 },
-[SOUND_MIXER_IGAIN] = { 0x3f, 0x40, 2, 0x00, 0x00 },
-[SOUND_MIXER_OGAIN] = { 0x41, 0x42, 2, 0x00, 0x00 },
-/* The following have register values but no h/w implementation */
-[SOUND_MIXER_TREBLE] = { 0x44, 0x45, 4, 0x00, 0x00 },
-[SOUND_MIXER_BASS] = { 0x46, 0x47, 4, 0x00, 0x00 }
+ [SOUND_MIXER_VOLUME] = { 0x30, 0x31, 5, 0x00, 0x00 },
+ [SOUND_MIXER_PCM] = { 0x32, 0x33, 5, 0x00, 0x00 },
+ [SOUND_MIXER_SYNTH] = { 0x34, 0x35, 5, 0x60, 0x40 },
+ [SOUND_MIXER_CD] = { 0x36, 0x37, 5, 0x06, 0x04 },
+ [SOUND_MIXER_LINE] = { 0x38, 0x39, 5, 0x18, 0x10 },
+ [SOUND_MIXER_MIC] = { 0x3a, 0x00, 5, 0x01, 0x01 },
+ [SOUND_MIXER_SPEAKER] = { 0x3b, 0x00, 2, 0x00, 0x00 },
+ [SOUND_MIXER_IGAIN] = { 0x3f, 0x40, 2, 0x00, 0x00 },
+ [SOUND_MIXER_OGAIN] = { 0x41, 0x42, 2, 0x00, 0x00 },
+ /* The following have register values but no h/w implementation */
+ [SOUND_MIXER_TREBLE] = { 0x44, 0x45, 4, 0x00, 0x00 },
+ [SOUND_MIXER_BASS] = { 0x46, 0x47, 4, 0x00, 0x00 }
};
static int
alsmix_init(struct snd_mixer *m)
{
-u_int32_t i, v;
+ u_int32_t i, v;
-for (i = v = 0; i < SOUND_MIXER_NRDEVICES; i++) {
-if (amt[i].bits) v |= 1 << i;
-}
-mix_setdevs(m, v);
-
-for (i = v = 0; i < SOUND_MIXER_NRDEVICES; i++) {
-if (amt[i].iselect) v |= 1 << i;
-}
-mix_setrecdevs(m, v);
-return 0;
+ for (i = v = 0; i < SOUND_MIXER_NRDEVICES; i++) {
+ if (amt[i].bits) v |= 1 << i;
+ }
+ mix_setdevs(m, v);
+
+ for (i = v = 0; i < SOUND_MIXER_NRDEVICES; i++) {
+ if (amt[i].iselect) v |= 1 << i;
+ }
+ mix_setrecdevs(m, v);
+ return 0;
}
static int
alsmix_set(struct snd_mixer *m, unsigned dev, unsigned left, unsigned right)
{
-struct sc_info *sc = mix_getdevinfo(m);
-u_int32_t r, l, v, mask;
+ struct sc_info *sc = mix_getdevinfo(m);
+ u_int32_t r, l, v, mask;
-/* Fill upper n bits in mask with 1's */
-mask = ((1 << amt[dev].bits) - 1) << (8 - amt[dev].bits);
+ /* Fill upper n bits in mask with 1's */
+ mask = ((1 << amt[dev].bits) - 1) << (8 - amt[dev].bits);
-l = (left * mask / 100) & mask;
-v = als_mix_rd(sc, amt[dev].lreg) & ~mask;
-als_mix_wr(sc, amt[dev].lreg, l | v);
-
-if (amt[dev].rreg) {
-r = (right * mask / 100) & mask;
-v = als_mix_rd(sc, amt[dev].rreg) & ~mask;
-als_mix_wr(sc, amt[dev].rreg, r | v);
-} else {
-r = 0;
-}
-
-/* Zero gain does not mute channel from output, but this does. */
-v = als_mix_rd(sc, SB16_OMASK);
-if (l == 0 && r == 0) {
-v &= ~amt[dev].oselect;
-} else {
-v |= amt[dev].oselect;
-}
-als_mix_wr(sc, SB16_OMASK, v);
-return 0;
+ l = (left * mask / 100) & mask;
+ v = als_mix_rd(sc, amt[dev].lreg) & ~mask;
+ als_mix_wr(sc, amt[dev].lreg, l | v);
+
+ if (amt[dev].rreg) {
+ r = (right * mask / 100) & mask;
+ v = als_mix_rd(sc, amt[dev].rreg) & ~mask;
+ als_mix_wr(sc, amt[dev].rreg, r | v);
+ } else {
+ r = 0;
+ }
+
+ /* Zero gain does not mute channel from output, but this does. */
+ v = als_mix_rd(sc, SB16_OMASK);
+ if (l == 0 && r == 0) {
+ v &= ~amt[dev].oselect;
+ } else {
+ v |= amt[dev].oselect;
+ }
+ als_mix_wr(sc, SB16_OMASK, v);
+ return 0;
}
static int
alsmix_setrecsrc(struct snd_mixer *m, u_int32_t src)
{
-struct sc_info *sc = mix_getdevinfo(m);
-u_int32_t i, l, r;
+ struct sc_info *sc = mix_getdevinfo(m);
+ u_int32_t i, l, r;
-for (i = l = r = 0; i < SOUND_MIXER_NRDEVICES; i++) {
-if (src & (1 << i)) {
-if (amt[i].iselect == 1) { /* microphone */
-l |= amt[i].iselect;
-r |= amt[i].iselect;
-} else {
-l |= amt[i].iselect;
-r |= amt[i].iselect >> 1;
-}
-}
-}
-
-als_mix_wr(sc, SB16_IMASK_L, l);
-als_mix_wr(sc, SB16_IMASK_R, r);
-return src;
+ for (i = l = r = 0; i < SOUND_MIXER_NRDEVICES; i++) {
+ if (src & (1 << i)) {
+ if (amt[i].iselect == 1) { /* microphone */
+ l |= amt[i].iselect;
+ r |= amt[i].iselect;
+ } else {
+ l |= amt[i].iselect;
+ r |= amt[i].iselect >> 1;
+ }
+ }
+ }
+
+ als_mix_wr(sc, SB16_IMASK_L, l);
+ als_mix_wr(sc, SB16_IMASK_R, r);
+ return src;
}
static kobj_method_t als_mixer_methods[] = {
-KOBJMETHOD(mixer_init, alsmix_init),
-KOBJMETHOD(mixer_set, alsmix_set),
-KOBJMETHOD(mixer_setrecsrc, alsmix_setrecsrc),
-{ 0, 0 }
+ KOBJMETHOD(mixer_init, alsmix_init),
+ KOBJMETHOD(mixer_set, alsmix_set),
+ KOBJMETHOD(mixer_setrecsrc, alsmix_setrecsrc),
+ { 0, 0 }
};
MIXER_DECLARE(als_mixer);
@@ -624,41 +631,41 @@
static void
als_intr(void *p)
{
-struct sc_info *sc = (struct sc_info *)p;
-u_int8_t intr, sb_status;
+ struct sc_info *sc = (struct sc_info *)p;
+ u_int8_t intr, sb_status;
-snd_mtxlock(sc->lock);
-intr = als_intr_rd(sc);
+ snd_mtxlock(sc->lock);
+ intr = als_intr_rd(sc);
-if (intr & 0x80) {
-snd_mtxunlock(sc->lock);
-chn_intr(sc->pch.channel);
-snd_mtxlock(sc->lock);
-}
+ if (intr & 0x80) {
+ snd_mtxunlock(sc->lock);
+ chn_intr(sc->pch.channel);
+ snd_mtxlock(sc->lock);
+ }
+
+ if (intr & 0x40) {
+ snd_mtxunlock(sc->lock);
+ chn_intr(sc->rch.channel);
+ snd_mtxlock(sc->lock);
+ }
+
+ /* ACK interrupt in PCI core */
+ als_intr_wr(sc, intr);
+
+ /* ACK interrupt in SB core */
+ sb_status = als_mix_rd(sc, IRQ_STAT);
+
+ if (sb_status & ALS_IRQ_STATUS8)
+ als_ack_read(sc, ALS_ESP_RD_STATUS8);
+ if (sb_status & ALS_IRQ_STATUS16)
+ als_ack_read(sc, ALS_ESP_RD_STATUS16);
+ if (sb_status & ALS_IRQ_MPUIN)
+ als_ack_read(sc, ALS_MIDI_DATA);
+ if (sb_status & ALS_IRQ_CR1E)
+ als_ack_read(sc, ALS_CR1E_ACK_PORT);
-if (intr & 0x40) {
-snd_mtxunlock(sc->lock);
-chn_intr(sc->rch.channel);
-snd_mtxlock(sc->lock);
-}
-
-/* ACK interrupt in PCI core */
-als_intr_wr(sc, intr);
-
-/* ACK interrupt in SB core */
-sb_status = als_mix_rd(sc, IRQ_STAT);
-
-if (sb_status & ALS_IRQ_STATUS8)
-als_ack_read(sc, ALS_ESP_RD_STATUS8);
-if (sb_status & ALS_IRQ_STATUS16)
-als_ack_read(sc, ALS_ESP_RD_STATUS16);
-if (sb_status & ALS_IRQ_MPUIN)
-als_ack_read(sc, ALS_MIDI_DATA);
-if (sb_status & ALS_IRQ_CR1E)
-als_ack_read(sc, ALS_CR1E_ACK_PORT);
-
-snd_mtxunlock(sc->lock);
-return;
+ snd_mtxunlock(sc->lock);
+ return;
}
/* ------------------------------------------------------------------------- */
@@ -667,44 +674,44 @@
static int
als_init(struct sc_info *sc)
{
-u_int32_t i, v;
+ u_int32_t i, v;
-/* Reset Chip */
-if (als_esp_reset(sc)) {
-return 1;
-}
-
-/* Enable write on DMA_SETUP register */
-v = als_mix_rd(sc, ALS_SB16_CONFIG);
-als_mix_wr(sc, ALS_SB16_CONFIG, v | 0x80);
-
-/* Select DMA0 */
-als_mix_wr(sc, ALS_SB16_DMA_SETUP, 0x01);
-
-/* Disable write on DMA_SETUP register */
-als_mix_wr(sc, ALS_SB16_CONFIG, v & 0x7f);
-
-/* Enable interrupts */
-v = als_gcr_rd(sc, ALS_GCR_MISC);
-als_gcr_wr(sc, ALS_GCR_MISC, v | 0x28000);
-
-/* Black out GCR DMA registers */
-for (i = 0x91; i <= 0x96; i++) {
-als_gcr_wr(sc, i, 0);
-}
-
-/* Emulation mode */
-v = als_gcr_rd(sc, ALS_GCR_DMA_EMULATION);
-als_gcr_wr(sc, ALS_GCR_DMA_EMULATION, v);
-DEB(printf("GCR_DMA_EMULATION 0x%08xn", v));
-return 0;
+ /* Reset Chip */
+ if (als_esp_reset(sc)) {
+ return 1;
+ }
+
+ /* Enable write on DMA_SETUP register */
+ v = als_mix_rd(sc, ALS_SB16_CONFIG);
+ als_mix_wr(sc, ALS_SB16_CONFIG, v | 0x80);
+
+ /* Select DMA0 */
+ als_mix_wr(sc, ALS_SB16_DMA_SETUP, 0x01);
+
+ /* Disable write on DMA_SETUP register */
+ als_mix_wr(sc, ALS_SB16_CONFIG, v & 0x7f);
+
+ /* Enable interrupts */
+ v = als_gcr_rd(sc, ALS_GCR_MISC);
+ als_gcr_wr(sc, ALS_GCR_MISC, v | 0x28000);
+
+ /* Black out GCR DMA registers */
+ for (i = 0x91; i <= 0x96; i++) {
+ als_gcr_wr(sc, i, 0);
+ }
+
+ /* Emulation mode */
+ v = als_gcr_rd(sc, ALS_GCR_DMA_EMULATION);
+ als_gcr_wr(sc, ALS_GCR_DMA_EMULATION, v);
+ DEB(printf("GCR_DMA_EMULATION 0x%08x\n", v));
+ return 0;
}
static void
als_uninit(struct sc_info *sc)
{
-/* Disable interrupts */
-als_gcr_wr(sc, ALS_GCR_MISC, 0);
+ /* Disable interrupts */
+ als_gcr_wr(sc, ALS_GCR_MISC, 0);
}
/* ------------------------------------------------------------------------- */
@@ -713,233 +720,229 @@
static int
als_pci_probe(device_t dev)
{
-if (pci_get_devid(dev) == ALS_PCI_ID0) {
-device_set_desc(dev, "Avance Logic ALS4000");
-return BUS_PROBE_DEFAULT;
-}
-return ENXIO;
+ if (pci_get_devid(dev) == ALS_PCI_ID0) {
+ device_set_desc(dev, "Avance Logic ALS4000");
+ return BUS_PROBE_DEFAULT;
+ }
+ return ENXIO;
}
static void
als_resource_free(device_t dev, struct sc_info *sc)
{
-if (sc->reg) {
-bus_release_resource(dev, SYS_RES_IOPORT, sc->regid, sc->reg);
-sc->reg = 0;
-}
-if (sc->ih) {
-bus_teardown_intr(dev, sc->irq, sc->ih);
-sc->ih = 0;
-}
-if (sc->irq) {
-bus_release_resource(dev, SYS_RES_IRQ, sc->irqid, sc->irq);
-sc->irq = 0;
-}
-if (sc->parent_dmat) {
-bus_dma_tag_destroy(sc->parent_dmat);
-sc->parent_dmat = 0;
-}
-if (sc->lock) {
-snd_mtxfree(sc->lock);
-sc->lock = NULL;
-}
+ if (sc->reg) {
+ bus_release_resource(dev, SYS_RES_IOPORT, sc->regid, sc->reg);
+ sc->reg = 0;
+ }
+ if (sc->ih) {
+ bus_teardown_intr(dev, sc->irq, sc->ih);
+ sc->ih = 0;
+ }
+ if (sc->irq) {
+ bus_release_resource(dev, SYS_RES_IRQ, sc->irqid, sc->irq);
+ sc->irq = 0;
+ }
+ if (sc->parent_dmat) {
+ bus_dma_tag_destroy(sc->parent_dmat);
+ sc->parent_dmat = 0;
+ }
+ if (sc->lock) {
+ snd_mtxfree(sc->lock);
+ sc->lock = NULL;
+ }
}
static int
als_resource_grab(device_t dev, struct sc_info *sc)
{
-sc->regid = PCIR_BAR(0);
-sc->reg = bus_alloc_resource(dev, SYS_RES_IOPORT, &sc->regid, 0, ~0,
-ALS_CONFIG_SPACE_BYTES, RF_ACTIVE);
-if (sc->reg == 0) {
-device_printf(dev, "unable to allocate register spacen");
-goto bad;
-}
-sc->st = rman_get_bustag(sc->reg);
-sc->sh = rman_get_bushandle(sc->reg);
-
-sc->irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &sc->irqid,
-RF_ACTIVE | RF_SHAREABLE);
-if (sc->irq == 0) {
-device_printf(dev, "unable to allocate interruptn");
-goto bad;
-}
-
-if (snd_setup_intr(dev, sc->irq, INTR_MPSAFE, als_intr,
-sc, &sc->ih)) {
-device_printf(dev, "unable to setup interruptn");
-goto bad;
-}
-
-sc->bufsz = pcm_getbuffersize(dev, 4096, ALS_DEFAULT_BUFSZ, 65536);
-
-if (bus_dma_tag_create(/*parent*/NULL,
-/*alignment*/2, /*boundary*/0,
-/*lowaddr*/BUS_SPACE_MAXADDR_24BIT,
-/*highaddr*/BUS_SPACE_MAXADDR,
-/*filter*/NULL, /*filterarg*/NULL,
-/*maxsize*/sc->bufsz,
-/*nsegments*/1, /*maxsegz*/0x3ffff,
-/*flags*/0, /*lockfunc*/NULL,
-/*lockarg*/NULL, &sc->parent_dmat) != 0) {
-device_printf(dev, "unable to create dma tagn");
-goto bad;
-}
-return 0;
-bad:
-als_resource_free(dev, sc);
-return ENXIO;
+ sc->regid = PCIR_BAR(0);
+ sc->reg = bus_alloc_resource(dev, SYS_RES_IOPORT, &sc->regid, 0, ~0,
+ ALS_CONFIG_SPACE_BYTES, RF_ACTIVE);
+ if (sc->reg == 0) {
+ device_printf(dev, "unable to allocate register space\n");
+ goto bad;
+ }
+ sc->st = rman_get_bustag(sc->reg);
+ sc->sh = rman_get_bushandle(sc->reg);
+
+ sc->irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &sc->irqid,
+ RF_ACTIVE | RF_SHAREABLE);
+ if (sc->irq == 0) {
+ device_printf(dev, "unable to allocate interrupt\n");
+ goto bad;
+ }
+
+ if (snd_setup_intr(dev, sc->irq, INTR_MPSAFE, als_intr,
+ sc, &sc->ih)) {
+ device_printf(dev, "unable to setup interrupt\n");
+ goto bad;
+ }
+
+ sc->bufsz = pcm_getbuffersize(dev, 4096, ALS_DEFAULT_BUFSZ, 65536);
+
+ if (bus_dma_tag_create(/*parent*/bus_get_dma_tag(dev),
+ /*alignment*/2, /*boundary*/0,
+ /*lowaddr*/BUS_SPACE_MAXADDR_24BIT,
+ /*highaddr*/BUS_SPACE_MAXADDR,
+ /*filter*/NULL, /*filterarg*/NULL,
+ /*maxsize*/sc->bufsz,
+ /*nsegments*/1, /*maxsegz*/0x3ffff,
+ /*flags*/0, /*lockfunc*/NULL,
+ /*lockarg*/NULL, &sc->parent_dmat) != 0) {
+ device_printf(dev, "unable to create dma tag\n");
+ goto bad;
+ }
+ return 0;
+ bad:
+ als_resource_free(dev, sc);
+ return ENXIO;
}
static int
als_pci_attach(device_t dev)
{
-struct sc_info *sc;
-u_int32_t data;
-char status[SND_STATUSLEN];
-
-if ((sc = malloc(sizeof(*sc), M_DEVBUF, M_NOWAIT | M_ZERO)) == NULL) {
-device_printf(dev, "cannot allocate softcn");
-return ENXIO;
-}
-
-sc->lock = snd_mtxcreate(device_get_nameunit(dev), "sound softc");
-sc->dev = dev;
-
-data = pci_read_config(dev, PCIR_COMMAND, 2);
-data |= (PCIM_CMD_PORTEN | PCIM_CMD_MEMEN | PCIM_CMD_BUSMASTEREN);
-pci_write_config(dev, PCIR_COMMAND, data, 2);
-/*
-* By default the power to the various components on the
-* ALS4000 is entirely controlled by the pci powerstate. We
-* could attempt finer grained control by setting GCR6.31.
-*/
+ struct sc_info *sc;
+ u_int32_t data;
+ char status[SND_STATUSLEN];
+
+ sc = malloc(sizeof(*sc), M_DEVBUF, M_WAITOK | M_ZERO);
+ sc->lock = snd_mtxcreate(device_get_nameunit(dev), "snd_als4000 softc");
+ sc->dev = dev;
+
+ data = pci_read_config(dev, PCIR_COMMAND, 2);
+ data |= (PCIM_CMD_PORTEN | PCIM_CMD_MEMEN | PCIM_CMD_BUSMASTEREN);
+ pci_write_config(dev, PCIR_COMMAND, data, 2);
+ /*
+ * By default the power to the various components on the
+ * ALS4000 is entirely controlled by the pci powerstate. We
+ * could attempt finer grained control by setting GCR6.31.
+ */
#if __FreeBSD_version > 500000
-if (pci_get_powerstate(dev) != PCI_POWERSTATE_D0) {
-/* Reset the power state. */
-device_printf(dev, "chip is in D%d power mode "
-"-- setting to D0n", pci_get_powerstate(dev));
-pci_set_powerstate(dev, PCI_POWERSTATE_D0);
-}
+ if (pci_get_powerstate(dev) != PCI_POWERSTATE_D0) {
+ /* Reset the power state. */
+ device_printf(dev, "chip is in D%d power mode "
+ "-- setting to D0\n", pci_get_powerstate(dev));
+ pci_set_powerstate(dev, PCI_POWERSTATE_D0);
+ }
#else
-data = pci_read_config(dev, ALS_PCI_POWERREG, 2);
-if ((data & 0x03) != 0) {
-device_printf(dev, "chip is in D%d power mode "
-"-- setting to D0n", data & 0x03);
-data &= ~0x03;
-pci_write_config(dev, ALS_PCI_POWERREG, data, 2);
-}
+ data = pci_read_config(dev, ALS_PCI_POWERREG, 2);
+ if ((data & 0x03) != 0) {
+ device_printf(dev, "chip is in D%d power mode "
+ "-- setting to D0\n", data & 0x03);
+ data &= ~0x03;
+ pci_write_config(dev, ALS_PCI_POWERREG, data, 2);
+ }
#endif
-if (als_resource_grab(dev, sc)) {
-device_printf(dev, "failed to allocate resourcesn");
-goto bad_attach;
-}
-
-if (als_init(sc)) {
-device_printf(dev, "failed to initialize hardwaren");
-goto bad_attach;
-}
-
-if (mixer_init(dev, &als_mixer_class, sc)) {
-device_printf(dev, "failed to initialize mixern");
-goto bad_attach;
-}
-
-if (pcm_register(dev, sc, 1, 1)) {
-device_printf(dev, "failed to register pcm entriesn");
-goto bad_attach;
-}
-
-pcm_addchan(dev, PCMDIR_PLAY, &alspchan_class, sc);
-pcm_addchan(dev, PCMDIR_REC, &alsrchan_class, sc);
-
-snprintf(status, SND_STATUSLEN, "at io 0x%lx irq %ld %s",
-rman_get_start(sc->reg), rman_get_start(sc->irq),PCM_KLDSTRING(snd_als4000));
-pcm_setstatus(dev, status);
-return 0;
-
-bad_attach:
-als_resource_free(dev, sc);
-free(sc, M_DEVBUF);
-return ENXIO;
+ if (als_resource_grab(dev, sc)) {
+ device_printf(dev, "failed to allocate resources\n");
+ goto bad_attach;
+ }
+
+ if (als_init(sc)) {
+ device_printf(dev, "failed to initialize hardware\n");
+ goto bad_attach;
+ }
+
+ if (mixer_init(dev, &als_mixer_class, sc)) {
+ device_printf(dev, "failed to initialize mixer\n");
+ goto bad_attach;
+ }
+
+ if (pcm_register(dev, sc, 1, 1)) {
+ device_printf(dev, "failed to register pcm entries\n");
+ goto bad_attach;
+ }
+
+ pcm_addchan(dev, PCMDIR_PLAY, &alspchan_class, sc);
+ pcm_addchan(dev, PCMDIR_REC, &alsrchan_class, sc);
+
+ snprintf(status, SND_STATUSLEN, "at io 0x%lx irq %ld %s",
+ rman_get_start(sc->reg), rman_get_start(sc->irq),PCM_KLDSTRING(snd_als4000));
+ pcm_setstatus(dev, status);
+ return 0;
+
+ bad_attach:
+ als_resource_free(dev, sc);
+ free(sc, M_DEVBUF);
+ return ENXIO;
}
static int
als_pci_detach(device_t dev)
{
-struct sc_info *sc;
-int r;
+ struct sc_info *sc;
+ int r;
-r = pcm_unregister(dev);
-if (r)
-return r;
-
-sc = pcm_getdevinfo(dev);
-als_uninit(sc);
-als_resource_free(dev, sc);
-free(sc, M_DEVBUF);
-return 0;
+ r = pcm_unregister(dev);
+ if (r)
+ return r;
+
+ sc = pcm_getdevinfo(dev);
+ als_uninit(sc);
+ als_resource_free(dev, sc);
+ free(sc, M_DEVBUF);
+ return 0;
}
static int
als_pci_suspend(device_t dev)
{
-struct sc_info *sc = pcm_getdevinfo(dev);
+ struct sc_info *sc = pcm_getdevinfo(dev);
-snd_mtxlock(sc->lock);
-sc->pch.dma_was_active = als_playback_stop(&sc->pch);
-sc->rch.dma_was_active = als_capture_stop(&sc->rch);
-als_uninit(sc);
-snd_mtxunlock(sc->lock);
-return 0;
+ snd_mtxlock(sc->lock);
+ sc->pch.dma_was_active = als_playback_stop(&sc->pch);
+ sc->rch.dma_was_active = als_capture_stop(&sc->rch);
+ als_uninit(sc);
+ snd_mtxunlock(sc->lock);
+ return 0;
}
static int
als_pci_resume(device_t dev)
{
-struct sc_info *sc = pcm_getdevinfo(dev);
+ struct sc_info *sc = pcm_getdevinfo(dev);
-snd_mtxlock(sc->lock);
-if (als_init(sc) != 0) {
-device_printf(dev, "unable to reinitialize the cardn");
-snd_mtxunlock(sc->lock);
-return ENXIO;
-}
-
-if (mixer_reinit(dev) != 0) {
-device_printf(dev, "unable to reinitialize the mixern");
-snd_mtxunlock(sc->lock);
-return ENXIO;
-}
-
-if (sc->pch.dma_was_active) {
-als_playback_start(&sc->pch);
-}
-
-if (sc->rch.dma_was_active) {
-als_capture_start(&sc->rch);
-}
-snd_mtxunlock(sc->lock);
+ snd_mtxlock(sc->lock);
+ if (als_init(sc) != 0) {
+ device_printf(dev, "unable to reinitialize the card\n");
+ snd_mtxunlock(sc->lock);
+ return ENXIO;
+ }
+
+ if (mixer_reinit(dev) != 0) {
+ device_printf(dev, "unable to reinitialize the mixer\n");
+ snd_mtxunlock(sc->lock);
+ return ENXIO;
+ }
+
+ if (sc->pch.dma_was_active) {
+ als_playback_start(&sc->pch);
+ }
+
+ if (sc->rch.dma_was_active) {
+ als_capture_start(&sc->rch);
+ }
+ snd_mtxunlock(sc->lock);
-return 0;
+ return 0;
}
static device_method_t als_methods[] = {
-/* Device interface */
-DEVMETHOD(device_probe, als_pci_probe),
-DEVMETHOD(device_attach, als_pci_attach),
-DEVMETHOD(device_detach, als_pci_detach),
-DEVMETHOD(device_suspend, als_pci_suspend),
-DEVMETHOD(device_resume, als_pci_resume),
-{ 0, 0 }
+ /* Device interface */
+ DEVMETHOD(device_probe, als_pci_probe),
+ DEVMETHOD(device_attach, als_pci_attach),
+ DEVMETHOD(device_detach, als_pci_detach),
+ DEVMETHOD(device_suspend, als_pci_suspend),
+ DEVMETHOD(device_resume, als_pci_resume),
+ { 0, 0 }
};
static driver_t als_driver = {
-"pcm",
-als_methods,
-PCM_SOFTC_SIZE,
+ "pcm",
+ als_methods,
+ PCM_SOFTC_SIZE,
};
DRIVER_MODULE(snd_als4000, pci, als_driver, pcm_devclass, 0, 0);
--- /dev/null
+++ sys/dev/sound/pci/emu10kx.h
@@ -0,0 +1,183 @@
+/*-
+ * Copyright (c) 1999 Cameron Grant <gandalf at vilnya.demon.co.uk>
+ * Copyright (c) 2003-2006 Yuriy Tsibizov <yuriy.tsibizov at gfk.ru>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHERIN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD: src/sys/dev/sound/pci/emu10kx.h,v 1.4 2007/09/12 07:43:42 ariff Exp $
+ */
+
+#ifndef EMU10KX_H
+#define EMU10KX_H
+
+#define SND_EMU10KX_MINVER 1
+#define SND_EMU10KX_PREFVER 1
+#define SND_EMU10KX_MAXVER 1
+
+#ifdef _KERNEL
+
+#define EMUPAGESIZE 4096
+#define NUM_G 64
+/* XXX some (empty) samples are played when play buffer is > EMUPAGESIZE */
+#define EMU_PLAY_BUFSZ EMUPAGESIZE
+/* Recording is limited by EMUPAGESIZE*16=64K buffer */
+#define EMU_REC_BUFSZ EMUPAGESIZE*16
+#define EMU_MAX_BUFSZ EMUPAGESIZE*16
+#define EMU_MAXPAGES 8192
+
+
+#define EMU_VAR_FUNC 0
+#define EMU_VAR_ROUTE 1
+#define EMU_VAR_ISEMU10K1 2
+#define EMU_VAR_MCH_DISABLED 3
+#define EMU_VAR_MCH_REC 4
+
+#define RT_FRONT 0
+#define RT_REAR 1
+#define RT_CENTER 2
+#define RT_SUB 3
+#define RT_SIDE 4
+#define RT_MCHRECORD 5
+#define RT_COUNT 6
+
+/* mixer controls */
+/* fx play */
+#define M_FX0_FRONT_L 0
+#define M_FX1_FRONT_R 1
+#define M_FX2_REAR_L 2
+#define M_FX3_REAR_R 3
+#define M_FX4_CENTER 4
+#define M_FX5_SUBWOOFER 5
+#define M_FX6_SIDE_L 6
+#define M_FX7_SIDE_R 7
+/* fx rec */
+#define M_FX0_REC_L 8
+#define M_FX1_REC_R 9
+/* inputs play */
+#define M_IN0_FRONT_L 10
+#define M_IN0_FRONT_R 11
+#define M_IN1_FRONT_L 12
+#define M_IN1_FRONT_R 13
+#define M_IN2_FRONT_L 14
+#define M_IN2_FRONT_R 15
+#define M_IN3_FRONT_L 16
+#define M_IN3_FRONT_R 17
+#define M_IN4_FRONT_L 18
+#define M_IN4_FRONT_R 19
+#define M_IN5_FRONT_L 20
+#define M_IN5_FRONT_R 21
+#define M_IN6_FRONT_L 22
+#define M_IN6_FRONT_R 23
+#define M_IN7_FRONT_L 24
+#define M_IN7_FRONT_R 25
+/* inputs rec */
+#define M_IN0_REC_L 26
+#define M_IN0_REC_R 27
+#define M_IN1_REC_L 28
+#define M_IN1_REC_R 29
+#define M_IN2_REC_L 30
+#define M_IN2_REC_R 31
+#define M_IN3_REC_L 32
+#define M_IN3_REC_R 33
+#define M_IN4_REC_L 34
+#define M_IN4_REC_R 35
+#define M_IN5_REC_L 36
+#define M_IN5_REC_R 37
+#define M_IN6_REC_L 38
+#define M_IN6_REC_R 39
+#define M_IN7_REC_L 40
+#define M_IN7_REC_R 41
+/* master volume */
+#define M_MASTER_FRONT_L 42
+#define M_MASTER_FRONT_R 43
+#define M_MASTER_REAR_L 44
+#define M_MASTER_REAR_R 45
+#define M_MASTER_CENTER 46
+#define M_MASTER_SUBWOOFER 47
+#define M_MASTER_SIDE_L 48
+#define M_MASTER_SIDE_R 49
+/* master rec volume */
+#define M_MASTER_REC_L 50
+#define M_MASTER_REC_R 51
+
+#define NUM_MIXERS 52
+
+struct emu_sc_info;
+
+/* MIDI device parameters */
+struct emu_midiinfo {
+ struct emu_sc_info *card;
+ int port;
+ int portnr;
+};
+
+/* PCM device parameters */
+struct emu_pcminfo {
+ struct emu_sc_info *card;
+ int route;
+};
+
+int emu_intr_register(struct emu_sc_info *sc, uint32_t inte_mask, uint32_t intr_mask, uint32_t(*func) (void *softc, uint32_t irq), void *isc);
+int emu_intr_unregister(struct emu_sc_info *sc, int ihandle);
+
+uint32_t emu_rd(struct emu_sc_info *sc, unsigned int regno, unsigned int size);
+void emu_wr(struct emu_sc_info *sc, unsigned int regno, uint32_t data, unsigned int size);
+
+uint32_t emu_rdptr(struct emu_sc_info *sc, unsigned int chn, unsigned int reg);
+void emu_wrptr(struct emu_sc_info *sc, unsigned int chn, unsigned int reg, uint32_t data);
+
+uint32_t emu_rd_p16vptr(struct emu_sc_info *sc, uint16_t chn, uint16_t reg);
+void emu_wr_p16vptr(struct emu_sc_info *sc, uint16_t chn, uint16_t reg, uint32_t data);
+
+int emu_timer_create(struct emu_sc_info *sc);
+int emu_timer_set(struct emu_sc_info *sc, int timer, int delay);
+int emu_timer_enable(struct emu_sc_info *sc, int timer, int go);
+int emu_timer_clear(struct emu_sc_info *sc, int timer);
+
+struct emu_voice;
+
+struct emu_route {
+ int routing_left[8];
+ int amounts_left[8];
+ int routing_right[8];
+ int amounts_right[8];
+};
+
+struct emu_voice* emu_valloc(struct emu_sc_info *sc);
+void emu_vfree(struct emu_sc_info *sc, struct emu_voice *v);
+int emu_vinit(struct emu_sc_info *sc, struct emu_voice *m, struct emu_voice *s,
+ uint32_t sz, struct snd_dbuf *b);
+void emu_vroute(struct emu_sc_info *sc, struct emu_route *rt, struct emu_voice *v);
+void emu_vsetup(struct emu_voice *v, int fmt, int spd);
+void emu_vwrite(struct emu_sc_info *sc, struct emu_voice *v);
+void emu_vtrigger(struct emu_sc_info *sc, struct emu_voice *v, int go);
+int emu_vpos(struct emu_sc_info *sc, struct emu_voice *v);
+
+bus_dma_tag_t emu_gettag(struct emu_sc_info *sc);
+
+void emumix_set_volume(struct emu_sc_info *sc, int mixer_idx, int volume);
+int emumix_get_volume(struct emu_sc_info *sc, int mixer_idx);
+
+void emu_enable_ir(struct emu_sc_info *sc);
+#endif /* _KERNEL */
+#endif /* EMU10K1_H */
Index: cs4281.h
===================================================================
RCS file: /home/cvs/src/sys/dev/sound/pci/cs4281.h,v
retrieving revision 1.2
retrieving revision 1.3
diff -L sys/dev/sound/pci/cs4281.h -L sys/dev/sound/pci/cs4281.h -u -r1.2 -r1.3
--- sys/dev/sound/pci/cs4281.h
+++ sys/dev/sound/pci/cs4281.h
@@ -1,31 +1,30 @@
/*-
-* Copyright (c) 2000 Orion Hodson <O.Hodson at cs.ucl.ac.uk>
-* All rights reserved.
-*
-* Redistribution and use in source and binary forms, with or without
-* modification, are permitted provided that the following conditions
-* are met:
-* 1. Redistributions of source code must retain the above copyright
-* notice, this list of conditions and the following disclaimer.
-* 2. Redistributions in binary form must reproduce the above copyright
-* notice, this list of conditions and the following disclaimer in the
-* documentation and/or other materials provided with the distribution.
-*
-* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
-* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
-* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
-* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
-* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHERIN CONTRACT, STRICT
-* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
-* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THEPOSSIBILITY OF
-* SUCH DAMAGE.
-*
-* $MidnightBSD$
-* $FreeBSD: src/sys/dev/sound/pci/cs4281.h,v 1.4 2005/01/06 01:43:19 imp Exp $
-*/
+ * Copyright (c) 2000 Orion Hodson <O.Hodson at cs.ucl.ac.uk>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHERIN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THEPOSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD: src/sys/dev/sound/pci/cs4281.h,v 1.4 2005/01/06 01:43:19 imp Exp $
+ */
#ifndef _CS4281_H_
#define _CS4281_H_
Index: cmi.c
===================================================================
RCS file: /home/cvs/src/sys/dev/sound/pci/cmi.c,v
retrieving revision 1.2
retrieving revision 1.3
diff -L sys/dev/sound/pci/cmi.c -L sys/dev/sound/pci/cmi.c -u -r1.2 -r1.3
--- sys/dev/sound/pci/cmi.c
+++ sys/dev/sound/pci/cmi.c
@@ -1,44 +1,44 @@
/*-
-* Copyright (c) 2000 Orion Hodson <O.Hodson at cs.ucl.ac.uk>
-* All rights reserved.
-*
-* Redistribution and use in source and binary forms, with or without
-* modification, are permitted provided that the following conditions
-* are met:
-* 1. Redistributions of source code must retain the above copyright
-* notice, this list of conditions and the following disclaimer.
-* 2. Redistributions in binary form must reproduce the above copyright
-* notice, this list of conditions and the following disclaimer in the
-* documentation and/or other materials provided with the distribution.
-*
-* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
-* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
-* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
-* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
-* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHERIN CONTRACT, STRICT
-* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
-* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THEPOSSIBILITY OF
-* SUCH DAMAGE.
-*
-* This driver exists largely as a result of other people's efforts.
-* Much of register handling is based on NetBSD CMI8x38 audio driver
-* by Takuya Shiozaki <AoiMoe at imou.to>. Chen-Li Tien
-* <cltien at cmedia.com.tw> clarified points regarding the DMA related
-* registers and the 8738 mixer devices. His Linux driver was also a
-* useful reference point.
-*
-* TODO: MIDI
-*
-* SPDIF contributed by Gerhard Gonter <gonter at whisky.wu-wien.ac.at>.
-*
-* This card/code does not always manage to sample at 44100 - actual
-* rate drifts slightly between recordings (usually 0-3%). No
-* differences visible in register dumps between times that work and
-* those that don't.
-*/
+ * Copyright (c) 2000 Orion Hodson <O.Hodson at cs.ucl.ac.uk>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHERIN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THEPOSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * This driver exists largely as a result of other people's efforts.
+ * Much of register handling is based on NetBSD CMI8x38 audio driver
+ * by Takuya Shiozaki <AoiMoe at imou.to>. Chen-Li Tien
+ * <cltien at cmedia.com.tw> clarified points regarding the DMA related
+ * registers and the 8738 mixer devices. His Linux driver was also a
+ * useful reference point.
+ *
+ * TODO: MIDI
+ *
+ * SPDIF contributed by Gerhard Gonter <gonter at whisky.wu-wien.ac.at>.
+ *
+ * This card/code does not always manage to sample at 44100 - actual
+ * rate drifts slightly between recordings (usually 0-3%). No
+ * differences visible in register dumps between times that work and
+ * those that don't.
+ */
#include <dev/sound/pcm/sound.h>
#include <dev/sound/pci/cmireg.h>
@@ -48,10 +48,12 @@
#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("$MidnightBSD$");
+SND_DECLARE_FILE("$FreeBSD: src/sys/dev/sound/pci/cmi.c,v 1.44 2007/06/17 06:10:41 ariff Exp $");
/* Supported chip ID's */
#define CMI8338A_PCI_ID 0x010013f6
@@ -90,38 +92,45 @@
struct sc_info;
struct sc_chinfo {
-struct sc_info *parent;
-struct pcm_channel *channel;
-struct snd_dbuf *buffer;
-u_int32_t fmt, spd, phys_buf, bps;
-u_int32_t dma_active:1, dma_was_active:1;
-int dir;
+ struct sc_info *parent;
+ struct pcm_channel *channel;
+ struct snd_dbuf *buffer;
+ u_int32_t fmt, spd, phys_buf, bps;
+ u_int32_t dma_active:1, dma_was_active:1;
+ int dir;
};
struct sc_info {
-device_t dev;
+ device_t dev;
-bus_space_tag_t st;
-bus_space_handle_t sh;
-bus_dma_tag_t parent_dmat;
-struct resource *reg, *irq;
-int regid, irqid;
-void *ih;
-struct mtx *lock;
-
-int spdif_enabled;
-unsigned int bufsz;
-struct sc_chinfo pch, rch;
+ bus_space_tag_t st;
+ bus_space_handle_t sh;
+ bus_dma_tag_t parent_dmat;
+ struct resource *reg, *irq;
+ int regid, irqid;
+ void *ih;
+ struct mtx *lock;
+
+ 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 */
static u_int32_t cmi_fmt[] = {
-AFMT_U8,
-AFMT_STEREO | AFMT_U8,
-AFMT_S16_LE,
-AFMT_STEREO | AFMT_S16_LE,
-0
+ AFMT_U8,
+ AFMT_STEREO | AFMT_U8,
+ AFMT_S16_LE,
+ AFMT_STEREO | AFMT_S16_LE,
+ 0
};
static struct pcmchan_caps cmi_caps = {5512, 48000, cmi_fmt, 0};
@@ -132,195 +141,195 @@
static u_int32_t
cmi_rd(struct sc_info *sc, int regno, int size)
{
-switch (size) {
-case 1:
-return bus_space_read_1(sc->st, sc->sh, regno);
-case 2:
-return bus_space_read_2(sc->st, sc->sh, regno);
-case 4:
-return bus_space_read_4(sc->st, sc->sh, regno);
-default:
-DEB(printf("cmi_rd: failed 0x%04x %dn", regno, size));
-return 0xFFFFFFFF;
-}
+ switch (size) {
+ case 1:
+ return bus_space_read_1(sc->st, sc->sh, regno);
+ case 2:
+ return bus_space_read_2(sc->st, sc->sh, regno);
+ case 4:
+ return bus_space_read_4(sc->st, sc->sh, regno);
+ default:
+ DEB(printf("cmi_rd: failed 0x%04x %d\n", regno, size));
+ return 0xFFFFFFFF;
+ }
}
static void
cmi_wr(struct sc_info *sc, int regno, u_int32_t data, int size)
{
-switch (size) {
-case 1:
-bus_space_write_1(sc->st, sc->sh, regno, data);
-break;
-case 2:
-bus_space_write_2(sc->st, sc->sh, regno, data);
-break;
-case 4:
-bus_space_write_4(sc->st, sc->sh, regno, data);
-break;
-}
+ switch (size) {
+ case 1:
+ bus_space_write_1(sc->st, sc->sh, regno, data);
+ break;
+ case 2:
+ bus_space_write_2(sc->st, sc->sh, regno, data);
+ break;
+ case 4:
+ bus_space_write_4(sc->st, sc->sh, regno, data);
+ break;
+ }
}
static void
cmi_partial_wr4(struct sc_info *sc,
-int reg, int shift, u_int32_t mask, u_int32_t val)
+ int reg, int shift, u_int32_t mask, u_int32_t val)
{
-u_int32_t r;
+ u_int32_t r;
-r = cmi_rd(sc, reg, 4);
-r &= ~(mask << shift);
-r |= val << shift;
-cmi_wr(sc, reg, r, 4);
+ r = cmi_rd(sc, reg, 4);
+ r &= ~(mask << shift);
+ r |= val << shift;
+ cmi_wr(sc, reg, r, 4);
}
static void
cmi_clr4(struct sc_info *sc, int reg, u_int32_t mask)
{
-u_int32_t r;
+ u_int32_t r;
-r = cmi_rd(sc, reg, 4);
-r &= ~mask;
-cmi_wr(sc, reg, r, 4);
+ r = cmi_rd(sc, reg, 4);
+ r &= ~mask;
+ cmi_wr(sc, reg, r, 4);
}
static void
cmi_set4(struct sc_info *sc, int reg, u_int32_t mask)
{
-u_int32_t r;
+ u_int32_t r;
-r = cmi_rd(sc, reg, 4);
-r |= mask;
-cmi_wr(sc, reg, r, 4);
+ r = cmi_rd(sc, reg, 4);
+ r |= mask;
+ cmi_wr(sc, reg, r, 4);
}
/* ------------------------------------------------------------------------- */
/* Rate Mapping */
static int cmi_rates[] = {5512, 8000, 11025, 16000,
-22050, 32000, 44100, 48000};
+ 22050, 32000, 44100, 48000};
#define NUM_CMI_RATES (sizeof(cmi_rates)/sizeof(cmi_rates[0]))
/* cmpci_rate_to_regvalue returns sampling freq selector for FCR1
-* register - reg order is 5k,11k,22k,44k,8k,16k,32k,48k */
+ * register - reg order is 5k,11k,22k,44k,8k,16k,32k,48k */
static u_int32_t
cmpci_rate_to_regvalue(int rate)
{
-int i, r;
+ int i, r;
-for(i = 0; i < NUM_CMI_RATES - 1; i++) {
-if (rate < ((cmi_rates[i] + cmi_rates[i + 1]) / 2)) {
-break;
-}
-}
+ for(i = 0; i < NUM_CMI_RATES - 1; i++) {
+ if (rate < ((cmi_rates[i] + cmi_rates[i + 1]) / 2)) {
+ break;
+ }
+ }
-DEB(printf("cmpci_rate_to_regvalue: %d -> %dn", rate, cmi_rates[i]));
+ DEB(printf("cmpci_rate_to_regvalue: %d -> %d\n", rate, cmi_rates[i]));
-r = ((i >> 1) | (i << 2)) & 0x07;
-return r;
+ r = ((i >> 1) | (i << 2)) & 0x07;
+ return r;
}
static int
cmpci_regvalue_to_rate(u_int32_t r)
{
-int i;
+ int i;
-i = ((r << 1) | (r >> 2)) & 0x07;
-DEB(printf("cmpci_regvalue_to_rate: %d -> %dn", r, i));
-return cmi_rates[i];
+ i = ((r << 1) | (r >> 2)) & 0x07;
+ DEB(printf("cmpci_regvalue_to_rate: %d -> %d\n", r, i));
+ return cmi_rates[i];
}
/* ------------------------------------------------------------------------- */
/* ADC/DAC control - there are 2 dma channels on 8738, either can be
-* playback or capture. We use ch0 for playback and ch1 for capture. */
+ * playback or capture. We use ch0 for playback and ch1 for capture. */
static void
cmi_dma_prog(struct sc_info *sc, struct sc_chinfo *ch, u_int32_t base)
{
-u_int32_t s, i, sz;
+ u_int32_t s, i, sz;
-ch->phys_buf = sndbuf_getbufaddr(ch->buffer);
+ ch->phys_buf = sndbuf_getbufaddr(ch->buffer);
-cmi_wr(sc, base, ch->phys_buf, 4);
-sz = (u_int32_t)sndbuf_getsize(ch->buffer);
+ cmi_wr(sc, base, ch->phys_buf, 4);
+ sz = (u_int32_t)sndbuf_getsize(ch->buffer);
-s = sz / ch->bps - 1;
-cmi_wr(sc, base + 4, s, 2);
+ s = sz / ch->bps - 1;
+ cmi_wr(sc, base + 4, s, 2);
-i = sz / (ch->bps * CMI_INTR_PER_BUFFER) - 1;
-cmi_wr(sc, base + 6, i, 2);
+ i = sz / (ch->bps * CMI_INTR_PER_BUFFER) - 1;
+ cmi_wr(sc, base + 6, i, 2);
}
static void
cmi_ch0_start(struct sc_info *sc, struct sc_chinfo *ch)
{
-cmi_dma_prog(sc, ch, CMPCI_REG_DMA0_BASE);
+ cmi_dma_prog(sc, ch, CMPCI_REG_DMA0_BASE);
-cmi_set4(sc, CMPCI_REG_FUNC_0, CMPCI_REG_CH0_ENABLE);
-cmi_set4(sc, CMPCI_REG_INTR_CTRL,
-CMPCI_REG_CH0_INTR_ENABLE);
+ cmi_set4(sc, CMPCI_REG_FUNC_0, CMPCI_REG_CH0_ENABLE);
+ cmi_set4(sc, CMPCI_REG_INTR_CTRL,
+ CMPCI_REG_CH0_INTR_ENABLE);
-ch->dma_active = 1;
+ ch->dma_active = 1;
}
static u_int32_t
cmi_ch0_stop(struct sc_info *sc, struct sc_chinfo *ch)
{
-u_int32_t r = ch->dma_active;
+ u_int32_t r = ch->dma_active;
-cmi_clr4(sc, CMPCI_REG_INTR_CTRL, CMPCI_REG_CH0_INTR_ENABLE);
-cmi_clr4(sc, CMPCI_REG_FUNC_0, CMPCI_REG_CH0_ENABLE);
-cmi_set4(sc, CMPCI_REG_FUNC_0, CMPCI_REG_CH0_RESET);
-cmi_clr4(sc, CMPCI_REG_FUNC_0, CMPCI_REG_CH0_RESET);
-ch->dma_active = 0;
-return r;
+ cmi_clr4(sc, CMPCI_REG_INTR_CTRL, CMPCI_REG_CH0_INTR_ENABLE);
+ cmi_clr4(sc, CMPCI_REG_FUNC_0, CMPCI_REG_CH0_ENABLE);
+ cmi_set4(sc, CMPCI_REG_FUNC_0, CMPCI_REG_CH0_RESET);
+ cmi_clr4(sc, CMPCI_REG_FUNC_0, CMPCI_REG_CH0_RESET);
+ ch->dma_active = 0;
+ return r;
}
static void
cmi_ch1_start(struct sc_info *sc, struct sc_chinfo *ch)
{
-cmi_dma_prog(sc, ch, CMPCI_REG_DMA1_BASE);
-cmi_set4(sc, CMPCI_REG_FUNC_0, CMPCI_REG_CH1_ENABLE);
-/* Enable Interrupts */
-cmi_set4(sc, CMPCI_REG_INTR_CTRL,
-CMPCI_REG_CH1_INTR_ENABLE);
-DEB(printf("cmi_ch1_start: dma progn"));
-ch->dma_active = 1;
+ cmi_dma_prog(sc, ch, CMPCI_REG_DMA1_BASE);
+ cmi_set4(sc, CMPCI_REG_FUNC_0, CMPCI_REG_CH1_ENABLE);
+ /* Enable Interrupts */
+ cmi_set4(sc, CMPCI_REG_INTR_CTRL,
+ CMPCI_REG_CH1_INTR_ENABLE);
+ DEB(printf("cmi_ch1_start: dma prog\n"));
+ ch->dma_active = 1;
}
static u_int32_t
cmi_ch1_stop(struct sc_info *sc, struct sc_chinfo *ch)
{
-u_int32_t r = ch->dma_active;
+ u_int32_t r = ch->dma_active;
-cmi_clr4(sc, CMPCI_REG_INTR_CTRL, CMPCI_REG_CH1_INTR_ENABLE);
-cmi_clr4(sc, CMPCI_REG_FUNC_0, CMPCI_REG_CH1_ENABLE);
-cmi_set4(sc, CMPCI_REG_FUNC_0, CMPCI_REG_CH1_RESET);
-cmi_clr4(sc, CMPCI_REG_FUNC_0, CMPCI_REG_CH1_RESET);
-ch->dma_active = 0;
-return r;
+ cmi_clr4(sc, CMPCI_REG_INTR_CTRL, CMPCI_REG_CH1_INTR_ENABLE);
+ cmi_clr4(sc, CMPCI_REG_FUNC_0, CMPCI_REG_CH1_ENABLE);
+ cmi_set4(sc, CMPCI_REG_FUNC_0, CMPCI_REG_CH1_RESET);
+ cmi_clr4(sc, CMPCI_REG_FUNC_0, CMPCI_REG_CH1_RESET);
+ ch->dma_active = 0;
+ return r;
}
static void
cmi_spdif_speed(struct sc_info *sc, int speed) {
-u_int32_t fcr1, lcr, mcr;
+ u_int32_t fcr1, lcr, mcr;
-if (speed >= 44100) {
-fcr1 = CMPCI_REG_SPDIF0_ENABLE;
-lcr = CMPCI_REG_XSPDIF_ENABLE;
-mcr = (speed == 48000) ?
-CMPCI_REG_W_SPDIF_48L | CMPCI_REG_SPDIF_48K : 0;
-} else {
-fcr1 = mcr = lcr = 0;
-}
-
-cmi_partial_wr4(sc, CMPCI_REG_MISC, 0,
-CMPCI_REG_W_SPDIF_48L | CMPCI_REG_SPDIF_48K, mcr);
-cmi_partial_wr4(sc, CMPCI_REG_FUNC_1, 0,
-CMPCI_REG_SPDIF0_ENABLE, fcr1);
-cmi_partial_wr4(sc, CMPCI_REG_LEGACY_CTRL, 0,
-CMPCI_REG_XSPDIF_ENABLE, lcr);
+ if (speed >= 44100) {
+ fcr1 = CMPCI_REG_SPDIF0_ENABLE;
+ lcr = CMPCI_REG_XSPDIF_ENABLE;
+ mcr = (speed == 48000) ?
+ CMPCI_REG_W_SPDIF_48L | CMPCI_REG_SPDIF_48K : 0;
+ } else {
+ fcr1 = mcr = lcr = 0;
+ }
+
+ cmi_partial_wr4(sc, CMPCI_REG_MISC, 0,
+ CMPCI_REG_W_SPDIF_48L | CMPCI_REG_SPDIF_48K, mcr);
+ cmi_partial_wr4(sc, CMPCI_REG_FUNC_1, 0,
+ CMPCI_REG_SPDIF0_ENABLE, fcr1);
+ cmi_partial_wr4(sc, CMPCI_REG_LEGACY_CTRL, 0,
+ CMPCI_REG_XSPDIF_ENABLE, lcr);
}
/* ------------------------------------------------------------------------- */
@@ -328,248 +337,256 @@
static void *
cmichan_init(kobj_t obj, void *devinfo,
-struct snd_dbuf *b, struct pcm_channel *c, int dir)
+ struct snd_dbuf *b, struct pcm_channel *c, int dir)
{
-struct sc_info *sc = devinfo;
-struct sc_chinfo *ch = (dir == PCMDIR_PLAY) ? &sc->pch : &sc->rch;
+ struct sc_info *sc = devinfo;
+ struct sc_chinfo *ch = (dir == PCMDIR_PLAY) ? &sc->pch : &sc->rch;
-ch->parent = sc;
-ch->channel = c;
-ch->bps = 1;
-ch->fmt = AFMT_U8;
-ch->spd = DSP_DEFAULT_SPEED;
-ch->buffer = b;
-ch->dma_active = 0;
-if (sndbuf_alloc(ch->buffer, sc->parent_dmat, sc->bufsz) != 0) {
-DEB(printf("cmichan_init failedn"));
-return NULL;
-}
-
-ch->dir = dir;
-snd_mtxlock(sc->lock);
-if (ch->dir == PCMDIR_PLAY) {
-cmi_dma_prog(sc, ch, CMPCI_REG_DMA0_BASE);
-} else {
-cmi_dma_prog(sc, ch, CMPCI_REG_DMA1_BASE);
-}
-snd_mtxunlock(sc->lock);
+ ch->parent = sc;
+ ch->channel = c;
+ ch->bps = 1;
+ ch->fmt = AFMT_U8;
+ ch->spd = DSP_DEFAULT_SPEED;
+ ch->buffer = b;
+ ch->dma_active = 0;
+ if (sndbuf_alloc(ch->buffer, sc->parent_dmat, 0, sc->bufsz) != 0) {
+ DEB(printf("cmichan_init failed\n"));
+ return NULL;
+ }
+
+ ch->dir = dir;
+ snd_mtxlock(sc->lock);
+ if (ch->dir == PCMDIR_PLAY) {
+ cmi_dma_prog(sc, ch, CMPCI_REG_DMA0_BASE);
+ } else {
+ cmi_dma_prog(sc, ch, CMPCI_REG_DMA1_BASE);
+ }
+ snd_mtxunlock(sc->lock);
-return ch;
+ return ch;
}
static int
cmichan_setformat(kobj_t obj, void *data, u_int32_t format)
{
-struct sc_chinfo *ch = data;
-struct sc_info *sc = ch->parent;
-u_int32_t f;
-
-if (format & AFMT_S16_LE) {
-f = CMPCI_REG_FORMAT_16BIT;
-ch->bps = 2;
-} else {
-f = CMPCI_REG_FORMAT_8BIT;
-ch->bps = 1;
-}
-
-if (format & AFMT_STEREO) {
-f |= CMPCI_REG_FORMAT_STEREO;
-ch->bps *= 2;
-} else {
-f |= CMPCI_REG_FORMAT_MONO;
-}
-
-snd_mtxlock(sc->lock);
-if (ch->dir == PCMDIR_PLAY) {
-cmi_partial_wr4(ch->parent,
-CMPCI_REG_CHANNEL_FORMAT,
-CMPCI_REG_CH0_FORMAT_SHIFT,
-CMPCI_REG_CH0_FORMAT_MASK,
-f);
-} else {
-cmi_partial_wr4(ch->parent,
-CMPCI_REG_CHANNEL_FORMAT,
-CMPCI_REG_CH1_FORMAT_SHIFT,
-CMPCI_REG_CH1_FORMAT_MASK,
-f);
-}
-snd_mtxunlock(sc->lock);
-ch->fmt = format;
+ struct sc_chinfo *ch = data;
+ struct sc_info *sc = ch->parent;
+ u_int32_t f;
+
+ if (format & AFMT_S16_LE) {
+ f = CMPCI_REG_FORMAT_16BIT;
+ ch->bps = 2;
+ } else {
+ f = CMPCI_REG_FORMAT_8BIT;
+ ch->bps = 1;
+ }
+
+ if (format & AFMT_STEREO) {
+ f |= CMPCI_REG_FORMAT_STEREO;
+ ch->bps *= 2;
+ } else {
+ f |= CMPCI_REG_FORMAT_MONO;
+ }
+
+ snd_mtxlock(sc->lock);
+ if (ch->dir == PCMDIR_PLAY) {
+ cmi_partial_wr4(ch->parent,
+ CMPCI_REG_CHANNEL_FORMAT,
+ CMPCI_REG_CH0_FORMAT_SHIFT,
+ CMPCI_REG_CH0_FORMAT_MASK,
+ f);
+ } else {
+ cmi_partial_wr4(ch->parent,
+ CMPCI_REG_CHANNEL_FORMAT,
+ CMPCI_REG_CH1_FORMAT_SHIFT,
+ CMPCI_REG_CH1_FORMAT_MASK,
+ f);
+ }
+ snd_mtxunlock(sc->lock);
+ ch->fmt = format;
-return 0;
+ return 0;
}
static int
cmichan_setspeed(kobj_t obj, void *data, u_int32_t speed)
{
-struct sc_chinfo *ch = data;
-struct sc_info *sc = ch->parent;
-u_int32_t r, rsp;
-
-r = cmpci_rate_to_regvalue(speed);
-snd_mtxlock(sc->lock);
-if (ch->dir == PCMDIR_PLAY) {
-if (speed < 44100) {
-/* disable if req before rate change */
-cmi_spdif_speed(ch->parent, speed);
-}
-cmi_partial_wr4(ch->parent,
-CMPCI_REG_FUNC_1,
-CMPCI_REG_DAC_FS_SHIFT,
-CMPCI_REG_DAC_FS_MASK,
-r);
-if (speed >= 44100 && ch->parent->spdif_enabled) {
-/* enable if req after rate change */
-cmi_spdif_speed(ch->parent, speed);
-}
-rsp = cmi_rd(ch->parent, CMPCI_REG_FUNC_1, 4);
-rsp >>= CMPCI_REG_DAC_FS_SHIFT;
-rsp &= CMPCI_REG_DAC_FS_MASK;
-} else {
-cmi_partial_wr4(ch->parent,
-CMPCI_REG_FUNC_1,
-CMPCI_REG_ADC_FS_SHIFT,
-CMPCI_REG_ADC_FS_MASK,
-r);
-rsp = cmi_rd(ch->parent, CMPCI_REG_FUNC_1, 4);
-rsp >>= CMPCI_REG_ADC_FS_SHIFT;
-rsp &= CMPCI_REG_ADC_FS_MASK;
-}
-snd_mtxunlock(sc->lock);
-ch->spd = cmpci_regvalue_to_rate(r);
-
-DEB(printf("cmichan_setspeed (%s) %d -> %d (%d)n",
-(ch->dir == PCMDIR_PLAY) ? "play" : "rec",
-speed, ch->spd, cmpci_regvalue_to_rate(rsp)));
+ struct sc_chinfo *ch = data;
+ struct sc_info *sc = ch->parent;
+ u_int32_t r, rsp;
+
+ r = cmpci_rate_to_regvalue(speed);
+ snd_mtxlock(sc->lock);
+ if (ch->dir == PCMDIR_PLAY) {
+ if (speed < 44100) {
+ /* disable if req before rate change */
+ cmi_spdif_speed(ch->parent, speed);
+ }
+ cmi_partial_wr4(ch->parent,
+ CMPCI_REG_FUNC_1,
+ CMPCI_REG_DAC_FS_SHIFT,
+ CMPCI_REG_DAC_FS_MASK,
+ r);
+ if (speed >= 44100 && ch->parent->spdif_enabled) {
+ /* enable if req after rate change */
+ cmi_spdif_speed(ch->parent, speed);
+ }
+ rsp = cmi_rd(ch->parent, CMPCI_REG_FUNC_1, 4);
+ rsp >>= CMPCI_REG_DAC_FS_SHIFT;
+ rsp &= CMPCI_REG_DAC_FS_MASK;
+ } else {
+ cmi_partial_wr4(ch->parent,
+ CMPCI_REG_FUNC_1,
+ CMPCI_REG_ADC_FS_SHIFT,
+ CMPCI_REG_ADC_FS_MASK,
+ r);
+ rsp = cmi_rd(ch->parent, CMPCI_REG_FUNC_1, 4);
+ rsp >>= CMPCI_REG_ADC_FS_SHIFT;
+ rsp &= CMPCI_REG_ADC_FS_MASK;
+ }
+ snd_mtxunlock(sc->lock);
+ ch->spd = cmpci_regvalue_to_rate(r);
+
+ DEB(printf("cmichan_setspeed (%s) %d -> %d (%d)\n",
+ (ch->dir == PCMDIR_PLAY) ? "play" : "rec",
+ speed, ch->spd, cmpci_regvalue_to_rate(rsp)));
-return ch->spd;
+ return ch->spd;
}
static int
cmichan_setblocksize(kobj_t obj, void *data, u_int32_t blocksize)
{
-struct sc_chinfo *ch = data;
-struct sc_info *sc = ch->parent;
+ struct sc_chinfo *ch = data;
+ struct sc_info *sc = ch->parent;
-/* user has requested interrupts every blocksize bytes */
-if (blocksize > sc->bufsz / CMI_INTR_PER_BUFFER) {
-blocksize = sc->bufsz / CMI_INTR_PER_BUFFER;
-}
-sndbuf_resize(ch->buffer, CMI_INTR_PER_BUFFER, blocksize);
+ /* user has requested interrupts every blocksize bytes */
+ if (blocksize > sc->bufsz / CMI_INTR_PER_BUFFER) {
+ blocksize = sc->bufsz / CMI_INTR_PER_BUFFER;
+ }
+ sndbuf_resize(ch->buffer, CMI_INTR_PER_BUFFER, blocksize);
-return blocksize;
+ return blocksize;
}
static int
cmichan_trigger(kobj_t obj, void *data, int go)
{
-struct sc_chinfo *ch = data;
-struct sc_info *sc = ch->parent;
+ struct sc_chinfo *ch = data;
+ struct sc_info *sc = ch->parent;
-snd_mtxlock(sc->lock);
-if (ch->dir == PCMDIR_PLAY) {
-switch(go) {
-case PCMTRIG_START:
-cmi_ch0_start(sc, ch);
-break;
-case PCMTRIG_ABORT:
-cmi_ch0_stop(sc, ch);
-break;
-}
-} else {
-switch(go) {
-case PCMTRIG_START:
-cmi_ch1_start(sc, ch);
-break;
-case PCMTRIG_ABORT:
-cmi_ch1_stop(sc, ch);
-break;
-}
-}
-snd_mtxunlock(sc->lock);
-return 0;
+ if (!PCMTRIG_COMMON(go))
+ return 0;
+
+ snd_mtxlock(sc->lock);
+ if (ch->dir == PCMDIR_PLAY) {
+ switch(go) {
+ case PCMTRIG_START:
+ cmi_ch0_start(sc, ch);
+ break;
+ case PCMTRIG_STOP:
+ case PCMTRIG_ABORT:
+ cmi_ch0_stop(sc, ch);
+ break;
+ }
+ } else {
+ switch(go) {
+ case PCMTRIG_START:
+ cmi_ch1_start(sc, ch);
+ break;
+ case PCMTRIG_STOP:
+ case PCMTRIG_ABORT:
+ cmi_ch1_stop(sc, ch);
+ break;
+ }
+ }
+ snd_mtxunlock(sc->lock);
+ return 0;
}
static int
cmichan_getptr(kobj_t obj, void *data)
{
-struct sc_chinfo *ch = data;
-struct sc_info *sc = ch->parent;
-u_int32_t physptr, bufptr, sz;
-
-snd_mtxlock(sc->lock);
-if (ch->dir == PCMDIR_PLAY) {
-physptr = cmi_rd(sc, CMPCI_REG_DMA0_BASE, 4);
-} else {
-physptr = cmi_rd(sc, CMPCI_REG_DMA1_BASE, 4);
-}
-snd_mtxunlock(sc->lock);
+ struct sc_chinfo *ch = data;
+ struct sc_info *sc = ch->parent;
+ u_int32_t physptr, bufptr, sz;
+
+ snd_mtxlock(sc->lock);
+ if (ch->dir == PCMDIR_PLAY) {
+ physptr = cmi_rd(sc, CMPCI_REG_DMA0_BASE, 4);
+ } else {
+ physptr = cmi_rd(sc, CMPCI_REG_DMA1_BASE, 4);
+ }
+ snd_mtxunlock(sc->lock);
-sz = sndbuf_getsize(ch->buffer);
-bufptr = (physptr - ch->phys_buf + sz - ch->bps) % sz;
+ sz = sndbuf_getsize(ch->buffer);
+ bufptr = (physptr - ch->phys_buf + sz - ch->bps) % sz;
-return bufptr;
+ return bufptr;
}
static void
cmi_intr(void *data)
{
-struct sc_info *sc = data;
-u_int32_t intrstat;
-u_int32_t toclear;
-
-snd_mtxlock(sc->lock);
-intrstat = cmi_rd(sc, CMPCI_REG_INTR_STATUS, 4);
-if ((intrstat & CMPCI_REG_ANY_INTR) != 0) {
-
-toclear = 0;
-if (intrstat & CMPCI_REG_CH0_INTR) {
-toclear |= CMPCI_REG_CH0_INTR_ENABLE;
-//cmi_clr4(sc, CMPCI_REG_INTR_CTRL, CMPCI_REG_CH0_INTR_ENABLE);
-}
-
-if (intrstat & CMPCI_REG_CH1_INTR) {
-toclear |= CMPCI_REG_CH1_INTR_ENABLE;
-//cmi_clr4(sc, CMPCI_REG_INTR_CTRL, CMPCI_REG_CH1_INTR_ENABLE);
-}
-
-if (toclear) {
-cmi_clr4(sc, CMPCI_REG_INTR_CTRL, toclear);
-snd_mtxunlock(sc->lock);
-
-/* Signal interrupts to channel */
-if (intrstat & CMPCI_REG_CH0_INTR) {
-chn_intr(sc->pch.channel);
-}
-
-if (intrstat & CMPCI_REG_CH1_INTR) {
-chn_intr(sc->rch.channel);
-}
-
-snd_mtxlock(sc->lock);
-cmi_set4(sc, CMPCI_REG_INTR_CTRL, toclear);
-
-}
-}
-snd_mtxunlock(sc->lock);
-return;
+ struct sc_info *sc = data;
+ u_int32_t intrstat;
+ u_int32_t toclear;
+
+ snd_mtxlock(sc->lock);
+ intrstat = cmi_rd(sc, CMPCI_REG_INTR_STATUS, 4);
+ if ((intrstat & CMPCI_REG_ANY_INTR) != 0) {
+
+ toclear = 0;
+ if (intrstat & CMPCI_REG_CH0_INTR) {
+ toclear |= CMPCI_REG_CH0_INTR_ENABLE;
+ //cmi_clr4(sc, CMPCI_REG_INTR_CTRL, CMPCI_REG_CH0_INTR_ENABLE);
+ }
+
+ if (intrstat & CMPCI_REG_CH1_INTR) {
+ toclear |= CMPCI_REG_CH1_INTR_ENABLE;
+ //cmi_clr4(sc, CMPCI_REG_INTR_CTRL, CMPCI_REG_CH1_INTR_ENABLE);
+ }
+
+ if (toclear) {
+ cmi_clr4(sc, CMPCI_REG_INTR_CTRL, toclear);
+ snd_mtxunlock(sc->lock);
+
+ /* Signal interrupts to channel */
+ if (intrstat & CMPCI_REG_CH0_INTR) {
+ chn_intr(sc->pch.channel);
+ }
+
+ if (intrstat & CMPCI_REG_CH1_INTR) {
+ chn_intr(sc->rch.channel);
+ }
+
+ snd_mtxlock(sc->lock);
+ cmi_set4(sc, CMPCI_REG_INTR_CTRL, toclear);
+
+ }
+ }
+ if(sc->mpu_intr) {
+ (sc->mpu_intr)(sc->mpu);
+ }
+ snd_mtxunlock(sc->lock);
+ return;
}
static struct pcmchan_caps *
cmichan_getcaps(kobj_t obj, void *data)
{
-return &cmi_caps;
+ return &cmi_caps;
}
static kobj_method_t cmichan_methods[] = {
-KOBJMETHOD(channel_init, cmichan_init),
-KOBJMETHOD(channel_setformat, cmichan_setformat),
-KOBJMETHOD(channel_setspeed, cmichan_setspeed),
-KOBJMETHOD(channel_setblocksize, cmichan_setblocksize),
-KOBJMETHOD(channel_trigger, cmichan_trigger),
-KOBJMETHOD(channel_getptr, cmichan_getptr),
-KOBJMETHOD(channel_getcaps, cmichan_getcaps),
-{ 0, 0 }
+ KOBJMETHOD(channel_init, cmichan_init),
+ KOBJMETHOD(channel_setformat, cmichan_setformat),
+ KOBJMETHOD(channel_setspeed, cmichan_setspeed),
+ KOBJMETHOD(channel_setblocksize, cmichan_setblocksize),
+ KOBJMETHOD(channel_trigger, cmichan_trigger),
+ KOBJMETHOD(channel_getptr, cmichan_getptr),
+ KOBJMETHOD(channel_getcaps, cmichan_getcaps),
+ { 0, 0 }
};
CHANNEL_DECLARE(cmichan);
@@ -579,47 +596,47 @@
static void
cmimix_wr(struct sc_info *sc, u_int8_t port, u_int8_t val)
{
-cmi_wr(sc, CMPCI_REG_SBADDR, port, 1);
-cmi_wr(sc, CMPCI_REG_SBDATA, val, 1);
+ cmi_wr(sc, CMPCI_REG_SBADDR, port, 1);
+ cmi_wr(sc, CMPCI_REG_SBDATA, val, 1);
}
static u_int8_t
cmimix_rd(struct sc_info *sc, u_int8_t port)
{
-cmi_wr(sc, CMPCI_REG_SBADDR, port, 1);
-return (u_int8_t)cmi_rd(sc, CMPCI_REG_SBDATA, 1);
+ cmi_wr(sc, CMPCI_REG_SBADDR, port, 1);
+ return (u_int8_t)cmi_rd(sc, CMPCI_REG_SBDATA, 1);
}
struct sb16props {
-u_int8_t rreg; /* right reg chan register */
-u_int8_t stereo:1; /* (no explanation needed, honest) */
-u_int8_t rec:1; /* recording source */
-u_int8_t bits:3; /* num bits to represent maximum gain rep */
-u_int8_t oselect; /* output select mask */
-u_int8_t iselect; /* right input select mask */
+ u_int8_t rreg; /* right reg chan register */
+ u_int8_t stereo:1; /* (no explanation needed, honest) */
+ u_int8_t rec:1; /* recording source */
+ u_int8_t bits:3; /* num bits to represent maximum gain rep */
+ u_int8_t oselect; /* output select mask */
+ u_int8_t iselect; /* right input select mask */
} static const cmt[SOUND_MIXER_NRDEVICES] = {
-[SOUND_MIXER_SYNTH] = {CMPCI_SB16_MIXER_FM_R, 1, 1, 5,
-CMPCI_SB16_SW_FM, CMPCI_SB16_MIXER_FM_SRC_R},
-[SOUND_MIXER_CD] = {CMPCI_SB16_MIXER_CDDA_R, 1, 1, 5,
-CMPCI_SB16_SW_CD, CMPCI_SB16_MIXER_CD_SRC_R},
-[SOUND_MIXER_LINE] = {CMPCI_SB16_MIXER_LINE_R, 1, 1, 5,
-CMPCI_SB16_SW_LINE, CMPCI_SB16_MIXER_LINE_SRC_R},
-[SOUND_MIXER_MIC] = {CMPCI_SB16_MIXER_MIC, 0, 1, 5,
-CMPCI_SB16_SW_MIC, CMPCI_SB16_MIXER_MIC_SRC},
-[SOUND_MIXER_SPEAKER] = {CMPCI_SB16_MIXER_SPEAKER, 0, 0, 2, 0, 0},
-[SOUND_MIXER_PCM] = {CMPCI_SB16_MIXER_VOICE_R, 1, 0, 5, 0, 0},
-[SOUND_MIXER_VOLUME] = {CMPCI_SB16_MIXER_MASTER_R, 1, 0, 5, 0, 0},
-/* These controls are not implemented in CMI8738, but maybe at a
-future date. They are not documented in C-Media documentation,
-though appear in other drivers for future h/w (ALSA, Linux, NetBSD).
-*/
-[SOUND_MIXER_IGAIN] = {CMPCI_SB16_MIXER_INGAIN_R, 1, 0, 2, 0, 0},
-[SOUND_MIXER_OGAIN] = {CMPCI_SB16_MIXER_OUTGAIN_R, 1, 0, 2, 0, 0},
-[SOUND_MIXER_BASS] = {CMPCI_SB16_MIXER_BASS_R, 1, 0, 4, 0, 0},
-[SOUND_MIXER_TREBLE] = {CMPCI_SB16_MIXER_TREBLE_R, 1, 0, 4, 0, 0},
-/* The mic pre-amp is implemented with non-SB16 compatible
-registers. */
-[SOUND_MIXER_MONITOR] = {CMPCI_NON_SB16_CONTROL, 0, 1, 4, 0},
+ [SOUND_MIXER_SYNTH] = {CMPCI_SB16_MIXER_FM_R, 1, 1, 5,
+ CMPCI_SB16_SW_FM, CMPCI_SB16_MIXER_FM_SRC_R},
+ [SOUND_MIXER_CD] = {CMPCI_SB16_MIXER_CDDA_R, 1, 1, 5,
+ CMPCI_SB16_SW_CD, CMPCI_SB16_MIXER_CD_SRC_R},
+ [SOUND_MIXER_LINE] = {CMPCI_SB16_MIXER_LINE_R, 1, 1, 5,
+ CMPCI_SB16_SW_LINE, CMPCI_SB16_MIXER_LINE_SRC_R},
+ [SOUND_MIXER_MIC] = {CMPCI_SB16_MIXER_MIC, 0, 1, 5,
+ CMPCI_SB16_SW_MIC, CMPCI_SB16_MIXER_MIC_SRC},
+ [SOUND_MIXER_SPEAKER] = {CMPCI_SB16_MIXER_SPEAKER, 0, 0, 2, 0, 0},
+ [SOUND_MIXER_PCM] = {CMPCI_SB16_MIXER_VOICE_R, 1, 0, 5, 0, 0},
+ [SOUND_MIXER_VOLUME] = {CMPCI_SB16_MIXER_MASTER_R, 1, 0, 5, 0, 0},
+ /* These controls are not implemented in CMI8738, but maybe at a
+ future date. They are not documented in C-Media documentation,
+ though appear in other drivers for future h/w (ALSA, Linux, NetBSD).
+ */
+ [SOUND_MIXER_IGAIN] = {CMPCI_SB16_MIXER_INGAIN_R, 1, 0, 2, 0, 0},
+ [SOUND_MIXER_OGAIN] = {CMPCI_SB16_MIXER_OUTGAIN_R, 1, 0, 2, 0, 0},
+ [SOUND_MIXER_BASS] = {CMPCI_SB16_MIXER_BASS_R, 1, 0, 4, 0, 0},
+ [SOUND_MIXER_TREBLE] = {CMPCI_SB16_MIXER_TREBLE_R, 1, 0, 4, 0, 0},
+ /* The mic pre-amp is implemented with non-SB16 compatible
+ registers. */
+ [SOUND_MIXER_MONITOR] = {CMPCI_NON_SB16_CONTROL, 0, 1, 4, 0},
};
#define MIXER_GAIN_REG_RTOL(r) (r - 1)
@@ -627,98 +644,100 @@
static int
cmimix_init(struct snd_mixer *m)
{
-struct sc_info *sc = mix_getdevinfo(m);
-u_int32_t i,v;
-
-for(i = v = 0; i < SOUND_MIXER_NRDEVICES; i++) {
-if (cmt[i].bits) v |= 1 << i;
-}
-mix_setdevs(m, v);
-
-for(i = v = 0; i < SOUND_MIXER_NRDEVICES; i++) {
-if (cmt[i].rec) v |= 1 << i;
-}
-mix_setrecdevs(m, v);
+ struct sc_info *sc = mix_getdevinfo(m);
+ u_int32_t i,v;
-cmimix_wr(sc, CMPCI_SB16_MIXER_RESET, 0);
-cmimix_wr(sc, CMPCI_SB16_MIXER_ADCMIX_L, 0);
-cmimix_wr(sc, CMPCI_SB16_MIXER_ADCMIX_R, 0);
-cmimix_wr(sc, CMPCI_SB16_MIXER_OUTMIX,
-CMPCI_SB16_SW_CD | CMPCI_SB16_SW_MIC | CMPCI_SB16_SW_LINE);
-return 0;
+ for(i = v = 0; i < SOUND_MIXER_NRDEVICES; i++) {
+ if (cmt[i].bits) v |= 1 << i;
+ }
+ mix_setdevs(m, v);
+
+ for(i = v = 0; i < SOUND_MIXER_NRDEVICES; i++) {
+ if (cmt[i].rec) v |= 1 << i;
+ }
+ mix_setrecdevs(m, v);
+
+ cmimix_wr(sc, CMPCI_SB16_MIXER_RESET, 0);
+ cmimix_wr(sc, CMPCI_SB16_MIXER_ADCMIX_L, 0);
+ cmimix_wr(sc, CMPCI_SB16_MIXER_ADCMIX_R, 0);
+ cmimix_wr(sc, CMPCI_SB16_MIXER_OUTMIX,
+ CMPCI_SB16_SW_CD | CMPCI_SB16_SW_MIC | CMPCI_SB16_SW_LINE);
+ return 0;
}
static int
cmimix_set(struct snd_mixer *m, unsigned dev, unsigned left, unsigned right)
{
-struct sc_info *sc = mix_getdevinfo(m);
-u_int32_t r, l, max;
-u_int8_t v;
-
-max = (1 << cmt[dev].bits) - 1;
-
-if (cmt[dev].rreg == CMPCI_NON_SB16_CONTROL) {
-/* For time being this can only be one thing (mic in
-* mic/aux reg) */
-v = cmi_rd(sc, CMPCI_REG_AUX_MIC, 1) & 0xf0;
-l = left * max / 100;
-/* 3 bit gain with LSB MICGAIN off(1),on(1) -> 4 bit value */
-v |= ((l << 1) | (~l >> 3)) & 0x0f;
-cmi_wr(sc, CMPCI_REG_AUX_MIC, v, 1);
-return 0;
-}
-
-l = (left * max / 100) << (8 - cmt[dev].bits);
-if (cmt[dev].stereo) {
-r = (right * max / 100) << (8 - cmt[dev].bits);
-cmimix_wr(sc, MIXER_GAIN_REG_RTOL(cmt[dev].rreg), l);
-cmimix_wr(sc, cmt[dev].rreg, r);
-DEBMIX(printf("Mixer stereo write dev %d reg 0x%02x " "value 0x%02x:0x%02xn",
-dev, MIXER_GAIN_REG_RTOL(cmt[dev].rreg), l, r));
-} else {
-r = l;
-cmimix_wr(sc, cmt[dev].rreg, l);
-DEBMIX(printf("Mixer mono write dev %d reg 0x%02x " "value 0x%02x:0x%02xn",
-dev, cmt[dev].rreg, l, l));
-}
-
-/* Zero gain does not mute channel from output, but this does... */
-v = cmimix_rd(sc, CMPCI_SB16_MIXER_OUTMIX);
-if (l == 0 && r == 0) {
-v &= ~cmt[dev].oselect;
-} else {
-v |= cmt[dev].oselect;
-}
-cmimix_wr(sc, CMPCI_SB16_MIXER_OUTMIX, v);
+ struct sc_info *sc = mix_getdevinfo(m);
+ u_int32_t r, l, max;
+ u_int8_t v;
+
+ max = (1 << cmt[dev].bits) - 1;
+
+ if (cmt[dev].rreg == CMPCI_NON_SB16_CONTROL) {
+ /* For time being this can only be one thing (mic in
+ * mic/aux reg) */
+ v = cmi_rd(sc, CMPCI_REG_AUX_MIC, 1) & 0xf0;
+ l = left * max / 100;
+ /* 3 bit gain with LSB MICGAIN off(1),on(1) -> 4 bit value */
+ v |= ((l << 1) | (~l >> 3)) & 0x0f;
+ cmi_wr(sc, CMPCI_REG_AUX_MIC, v, 1);
+ return 0;
+ }
+
+ l = (left * max / 100) << (8 - cmt[dev].bits);
+ if (cmt[dev].stereo) {
+ r = (right * max / 100) << (8 - cmt[dev].bits);
+ cmimix_wr(sc, MIXER_GAIN_REG_RTOL(cmt[dev].rreg), l);
+ cmimix_wr(sc, cmt[dev].rreg, r);
+ DEBMIX(printf("Mixer stereo write dev %d reg 0x%02x "\
+ "value 0x%02x:0x%02x\n",
+ dev, MIXER_GAIN_REG_RTOL(cmt[dev].rreg), l, r));
+ } else {
+ r = l;
+ cmimix_wr(sc, cmt[dev].rreg, l);
+ DEBMIX(printf("Mixer mono write dev %d reg 0x%02x " \
+ "value 0x%02x:0x%02x\n",
+ dev, cmt[dev].rreg, l, l));
+ }
+
+ /* Zero gain does not mute channel from output, but this does... */
+ v = cmimix_rd(sc, CMPCI_SB16_MIXER_OUTMIX);
+ if (l == 0 && r == 0) {
+ v &= ~cmt[dev].oselect;
+ } else {
+ v |= cmt[dev].oselect;
+ }
+ cmimix_wr(sc, CMPCI_SB16_MIXER_OUTMIX, v);
-return 0;
+ return 0;
}
static int
cmimix_setrecsrc(struct snd_mixer *m, u_int32_t src)
{
-struct sc_info *sc = mix_getdevinfo(m);
-u_int32_t i, ml, sl;
+ struct sc_info *sc = mix_getdevinfo(m);
+ u_int32_t i, ml, sl;
-ml = sl = 0;
-for(i = 0; i < SOUND_MIXER_NRDEVICES; i++) {
-if ((1<<i) & src) {
-if (cmt[i].stereo) {
-sl |= cmt[i].iselect;
-} else {
-ml |= cmt[i].iselect;
-}
-}
-}
-cmimix_wr(sc, CMPCI_SB16_MIXER_ADCMIX_R, sl|ml);
-DEBMIX(printf("cmimix_setrecsrc: reg 0x%02x val 0x%02xn",
-CMPCI_SB16_MIXER_ADCMIX_R, sl|ml));
-ml = CMPCI_SB16_MIXER_SRC_R_TO_L(ml);
-cmimix_wr(sc, CMPCI_SB16_MIXER_ADCMIX_L, sl|ml);
-DEBMIX(printf("cmimix_setrecsrc: reg 0x%02x val 0x%02xn",
-CMPCI_SB16_MIXER_ADCMIX_L, sl|ml));
+ ml = sl = 0;
+ for(i = 0; i < SOUND_MIXER_NRDEVICES; i++) {
+ if ((1<<i) & src) {
+ if (cmt[i].stereo) {
+ sl |= cmt[i].iselect;
+ } else {
+ ml |= cmt[i].iselect;
+ }
+ }
+ }
+ cmimix_wr(sc, CMPCI_SB16_MIXER_ADCMIX_R, sl|ml);
+ DEBMIX(printf("cmimix_setrecsrc: reg 0x%02x val 0x%02x\n",
+ CMPCI_SB16_MIXER_ADCMIX_R, sl|ml));
+ ml = CMPCI_SB16_MIXER_SRC_R_TO_L(ml);
+ cmimix_wr(sc, CMPCI_SB16_MIXER_ADCMIX_L, sl|ml);
+ DEBMIX(printf("cmimix_setrecsrc: reg 0x%02x val 0x%02x\n",
+ CMPCI_SB16_MIXER_ADCMIX_L, sl|ml));
-return src;
+ return src;
}
/* Optional SPDIF support. */
@@ -727,79 +746,156 @@
cmi_initsys(struct sc_info* sc)
{
#ifdef SND_DYNSYSCTL
-SYSCTL_ADD_INT(snd_sysctl_tree(sc->dev),
-SYSCTL_CHILDREN(snd_sysctl_tree_top(sc->dev)),
-OID_AUTO, "spdif_enabled", CTLFLAG_RW,
-&sc->spdif_enabled, 0,
-"enable SPDIF output at 44.1 kHz and above");
+ /* XXX: an user should be able to set this with a control tool,
+ if not done before 7.0-RELEASE, this needs to be converted
+ to a device specific sysctl "dev.pcm.X.yyy" via
+ device_get_sysctl_*() as discussed on multimedia@ in msg-id
+ <861wujij2q.fsf at xps.des.no> */
+ SYSCTL_ADD_INT(device_get_sysctl_ctx(sc->dev),
+ SYSCTL_CHILDREN(device_get_sysctl_tree(sc->dev)),
+ OID_AUTO, "spdif_enabled", CTLFLAG_RW,
+ &sc->spdif_enabled, 0,
+ "enable SPDIF output at 44.1 kHz and above");
#endif /* SND_DYNSYSCTL */
-return 0;
+ return 0;
}
/* ------------------------------------------------------------------------- */
static kobj_method_t cmi_mixer_methods[] = {
-KOBJMETHOD(mixer_init, cmimix_init),
-KOBJMETHOD(mixer_set, cmimix_set),
-KOBJMETHOD(mixer_setrecsrc, cmimix_setrecsrc),
-{ 0, 0 }
+ KOBJMETHOD(mixer_init, cmimix_init),
+ KOBJMETHOD(mixer_set, cmimix_set),
+ KOBJMETHOD(mixer_setrecsrc, cmimix_setrecsrc),
+ { 0, 0 }
};
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 }
+};
+
+static 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 */
static void
cmi_power(struct sc_info *sc, int state)
{
-switch (state) {
-case 0: /* full power */
-cmi_clr4(sc, CMPCI_REG_MISC, CMPCI_REG_POWER_DOWN);
-break;
-default:
-/* power off */
-cmi_set4(sc, CMPCI_REG_MISC, CMPCI_REG_POWER_DOWN);
-break;
-}
+ switch (state) {
+ case 0: /* full power */
+ cmi_clr4(sc, CMPCI_REG_MISC, CMPCI_REG_POWER_DOWN);
+ break;
+ default:
+ /* power off */
+ cmi_set4(sc, CMPCI_REG_MISC, CMPCI_REG_POWER_DOWN);
+ break;
+ }
}
static int
cmi_init(struct sc_info *sc)
{
-/* Effect reset */
-cmi_set4(sc, CMPCI_REG_MISC, CMPCI_REG_BUS_AND_DSP_RESET);
-DELAY(100);
-cmi_clr4(sc, CMPCI_REG_MISC, CMPCI_REG_BUS_AND_DSP_RESET);
-
-/* Disable interrupts and channels */
-cmi_clr4(sc, CMPCI_REG_FUNC_0,
-CMPCI_REG_CH0_ENABLE | CMPCI_REG_CH1_ENABLE);
-cmi_clr4(sc, CMPCI_REG_INTR_CTRL,
-CMPCI_REG_CH0_INTR_ENABLE | CMPCI_REG_CH1_INTR_ENABLE);
-
-/* Configure DMA channels, ch0 = play, ch1 = capture */
-cmi_clr4(sc, CMPCI_REG_FUNC_0, CMPCI_REG_CH0_DIR);
-cmi_set4(sc, CMPCI_REG_FUNC_0, CMPCI_REG_CH1_DIR);
-
-/* Attempt to enable 4 Channel output */
-cmi_set4(sc, CMPCI_REG_MISC, CMPCI_REG_N4SPK3D);
-
-/* Disable SPDIF1 - not compatible with config */
-cmi_clr4(sc, CMPCI_REG_FUNC_1, CMPCI_REG_SPDIF1_ENABLE);
-cmi_clr4(sc, CMPCI_REG_FUNC_1, CMPCI_REG_SPDIF_LOOP);
+ /* Effect reset */
+ cmi_set4(sc, CMPCI_REG_MISC, CMPCI_REG_BUS_AND_DSP_RESET);
+ DELAY(100);
+ cmi_clr4(sc, CMPCI_REG_MISC, CMPCI_REG_BUS_AND_DSP_RESET);
+
+ /* Disable interrupts and channels */
+ cmi_clr4(sc, CMPCI_REG_FUNC_0,
+ CMPCI_REG_CH0_ENABLE | CMPCI_REG_CH1_ENABLE);
+ cmi_clr4(sc, CMPCI_REG_INTR_CTRL,
+ CMPCI_REG_CH0_INTR_ENABLE | CMPCI_REG_CH1_INTR_ENABLE);
+
+ /* Configure DMA channels, ch0 = play, ch1 = capture */
+ cmi_clr4(sc, CMPCI_REG_FUNC_0, CMPCI_REG_CH0_DIR);
+ cmi_set4(sc, CMPCI_REG_FUNC_0, CMPCI_REG_CH1_DIR);
+
+ /* Attempt to enable 4 Channel output */
+ cmi_set4(sc, CMPCI_REG_MISC, CMPCI_REG_N4SPK3D);
+
+ /* Disable SPDIF1 - not compatible with config */
+ cmi_clr4(sc, CMPCI_REG_FUNC_1, CMPCI_REG_SPDIF1_ENABLE);
+ cmi_clr4(sc, CMPCI_REG_FUNC_1, CMPCI_REG_SPDIF_LOOP);
-return 0;
+ return 0;
}
static void
cmi_uninit(struct sc_info *sc)
{
-/* Disable interrupts and channels */
-cmi_clr4(sc, CMPCI_REG_INTR_CTRL,
-CMPCI_REG_CH0_INTR_ENABLE |
-CMPCI_REG_CH1_INTR_ENABLE |
-CMPCI_REG_TDMA_INTR_ENABLE);
-cmi_clr4(sc, CMPCI_REG_FUNC_0,
-CMPCI_REG_CH0_ENABLE | CMPCI_REG_CH1_ENABLE);
+ /* Disable interrupts and channels */
+ cmi_clr4(sc, CMPCI_REG_INTR_CTRL,
+ CMPCI_REG_CH0_INTR_ENABLE |
+ CMPCI_REG_CH1_INTR_ENABLE |
+ 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;
}
/* ------------------------------------------------------------------------- */
@@ -807,202 +903,207 @@
static int
cmi_probe(device_t dev)
{
-switch(pci_get_devid(dev)) {
-case CMI8338A_PCI_ID:
-device_set_desc(dev, "CMedia CMI8338A");
-return BUS_PROBE_DEFAULT;
-case CMI8338B_PCI_ID:
-device_set_desc(dev, "CMedia CMI8338B");
-return BUS_PROBE_DEFAULT;
-case CMI8738_PCI_ID:
-device_set_desc(dev, "CMedia CMI8738");
-return BUS_PROBE_DEFAULT;
-case CMI8738B_PCI_ID:
-device_set_desc(dev, "CMedia CMI8738B");
-return BUS_PROBE_DEFAULT;
-default:
-return ENXIO;
-}
+ switch(pci_get_devid(dev)) {
+ case CMI8338A_PCI_ID:
+ device_set_desc(dev, "CMedia CMI8338A");
+ return BUS_PROBE_DEFAULT;
+ case CMI8338B_PCI_ID:
+ device_set_desc(dev, "CMedia CMI8338B");
+ return BUS_PROBE_DEFAULT;
+ case CMI8738_PCI_ID:
+ device_set_desc(dev, "CMedia CMI8738");
+ return BUS_PROBE_DEFAULT;
+ case CMI8738B_PCI_ID:
+ device_set_desc(dev, "CMedia CMI8738B");
+ return BUS_PROBE_DEFAULT;
+ default:
+ return ENXIO;
+ }
}
static int
cmi_attach(device_t dev)
{
-struct sc_info *sc;
-u_int32_t data;
-char status[SND_STATUSLEN];
-
-sc = malloc(sizeof(struct sc_info), M_DEVBUF, M_NOWAIT | M_ZERO);
-if (sc == NULL) {
-device_printf(dev, "cannot allocate softcn");
-return ENXIO;
-}
-
-sc->lock = snd_mtxcreate(device_get_nameunit(dev), "sound softc");
-data = pci_read_config(dev, PCIR_COMMAND, 2);
-data |= (PCIM_CMD_PORTEN|PCIM_CMD_BUSMASTEREN);
-pci_write_config(dev, PCIR_COMMAND, data, 2);
-data = pci_read_config(dev, PCIR_COMMAND, 2);
-
-sc->dev = dev;
-sc->regid = PCIR_BAR(0);
-sc->reg = bus_alloc_resource_any(dev, SYS_RES_IOPORT, &sc->regid,
-RF_ACTIVE);
-if (!sc->reg) {
-device_printf(dev, "cmi_attach: Cannot allocate bus resourcen");
-goto bad;
-}
-sc->st = rman_get_bustag(sc->reg);
-sc->sh = rman_get_bushandle(sc->reg);
-
-sc->irqid = 0;
-sc->irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &sc->irqid,
-RF_ACTIVE | RF_SHAREABLE);
-if (!sc->irq ||
-snd_setup_intr(dev, sc->irq, INTR_MPSAFE, cmi_intr, sc, &sc->ih)) {
-device_printf(dev, "cmi_attach: Unable to map interruptn");
-goto bad;
-}
-
-sc->bufsz = pcm_getbuffersize(dev, 4096, CMI_DEFAULT_BUFSZ, 65536);
-
-if (bus_dma_tag_create(/*parent*/NULL, /*alignment*/2, /*boundary*/0,
-/*lowaddr*/BUS_SPACE_MAXADDR_32BIT,
-/*highaddr*/BUS_SPACE_MAXADDR,
-/*filter*/NULL, /*filterarg*/NULL,
-/*maxsize*/sc->bufsz, /*nsegments*/1,
-/*maxsegz*/0x3ffff, /*flags*/0,
-/*lockfunc*/NULL,
-/*lockfunc*/NULL,
-&sc->parent_dmat) != 0) {
-device_printf(dev, "cmi_attach: Unable to create dma tagn");
-goto bad;
-}
-
-cmi_power(sc, 0);
-if (cmi_init(sc))
-goto bad;
-
-if (mixer_init(dev, &cmi_mixer_class, sc))
-goto bad;
-
-if (pcm_register(dev, sc, 1, 1))
-goto bad;
-
-cmi_initsys(sc);
-
-pcm_addchan(dev, PCMDIR_PLAY, &cmichan_class, sc);
-pcm_addchan(dev, PCMDIR_REC, &cmichan_class, sc);
-
-snprintf(status, SND_STATUSLEN, "at io 0x%lx irq %ld %s",
-rman_get_start(sc->reg), rman_get_start(sc->irq),PCM_KLDSTRING(snd_cmi));
-pcm_setstatus(dev, status);
-
-DEB(printf("cmi_attach: succeededn"));
-return 0;
-
-bad:
-if (sc->parent_dmat)
-bus_dma_tag_destroy(sc->parent_dmat);
-if (sc->ih)
-bus_teardown_intr(dev, sc->irq, sc->ih);
-if (sc->irq)
-bus_release_resource(dev, SYS_RES_IRQ, sc->irqid, sc->irq);
-if (sc->reg)
-bus_release_resource(dev, SYS_RES_IOPORT, sc->regid, sc->reg);
-if (sc->lock)
-snd_mtxfree(sc->lock);
-if (sc)
-free(sc, M_DEVBUF);
+ struct sc_info *sc;
+ u_int32_t data;
+ char status[SND_STATUSLEN];
+
+ sc = malloc(sizeof(*sc), M_DEVBUF, M_WAITOK | M_ZERO);
+ sc->lock = snd_mtxcreate(device_get_nameunit(dev), "snd_cmi softc");
+ data = pci_read_config(dev, PCIR_COMMAND, 2);
+ data |= (PCIM_CMD_PORTEN|PCIM_CMD_BUSMASTEREN);
+ pci_write_config(dev, PCIR_COMMAND, data, 2);
+ data = pci_read_config(dev, PCIR_COMMAND, 2);
+
+ sc->dev = dev;
+ sc->regid = PCIR_BAR(0);
+ sc->reg = bus_alloc_resource_any(dev, SYS_RES_IOPORT, &sc->regid,
+ RF_ACTIVE);
+ if (!sc->reg) {
+ device_printf(dev, "cmi_attach: Cannot allocate bus resource\n");
+ goto bad;
+ }
+ sc->st = rman_get_bustag(sc->reg);
+ sc->sh = rman_get_bushandle(sc->reg);
+
+ if (0)
+ cmi_midiattach(sc);
+
+ sc->irqid = 0;
+ sc->irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &sc->irqid,
+ RF_ACTIVE | RF_SHAREABLE);
+ if (!sc->irq ||
+ snd_setup_intr(dev, sc->irq, INTR_MPSAFE, cmi_intr, sc, &sc->ih)) {
+ device_printf(dev, "cmi_attach: Unable to map interrupt\n");
+ goto bad;
+ }
+
+ sc->bufsz = pcm_getbuffersize(dev, 4096, CMI_DEFAULT_BUFSZ, 65536);
+
+ if (bus_dma_tag_create(/*parent*/bus_get_dma_tag(dev), /*alignment*/2,
+ /*boundary*/0,
+ /*lowaddr*/BUS_SPACE_MAXADDR_32BIT,
+ /*highaddr*/BUS_SPACE_MAXADDR,
+ /*filter*/NULL, /*filterarg*/NULL,
+ /*maxsize*/sc->bufsz, /*nsegments*/1,
+ /*maxsegz*/0x3ffff, /*flags*/0,
+ /*lockfunc*/NULL,
+ /*lockfunc*/NULL,
+ &sc->parent_dmat) != 0) {
+ device_printf(dev, "cmi_attach: Unable to create dma tag\n");
+ goto bad;
+ }
+
+ cmi_power(sc, 0);
+ if (cmi_init(sc))
+ goto bad;
+
+ if (mixer_init(dev, &cmi_mixer_class, sc))
+ goto bad;
+
+ if (pcm_register(dev, sc, 1, 1))
+ goto bad;
+
+ cmi_initsys(sc);
+
+ pcm_addchan(dev, PCMDIR_PLAY, &cmichan_class, sc);
+ pcm_addchan(dev, PCMDIR_REC, &cmichan_class, sc);
+
+ snprintf(status, SND_STATUSLEN, "at io 0x%lx irq %ld %s",
+ rman_get_start(sc->reg), rman_get_start(sc->irq),PCM_KLDSTRING(snd_cmi));
+ pcm_setstatus(dev, status);
+
+ DEB(printf("cmi_attach: succeeded\n"));
+ return 0;
+
+ bad:
+ if (sc->parent_dmat)
+ bus_dma_tag_destroy(sc->parent_dmat);
+ if (sc->ih)
+ bus_teardown_intr(dev, sc->irq, sc->ih);
+ if (sc->irq)
+ bus_release_resource(dev, SYS_RES_IRQ, sc->irqid, sc->irq);
+ if (sc->reg)
+ bus_release_resource(dev, SYS_RES_IOPORT, sc->regid, sc->reg);
+ if (sc->lock)
+ snd_mtxfree(sc->lock);
+ if (sc)
+ free(sc, M_DEVBUF);
-return ENXIO;
+ return ENXIO;
}
static int
cmi_detach(device_t dev)
{
-struct sc_info *sc;
-int r;
+ struct sc_info *sc;
+ int r;
-r = pcm_unregister(dev);
-if (r) return r;
+ r = pcm_unregister(dev);
+ if (r) return r;
-sc = pcm_getdevinfo(dev);
-cmi_uninit(sc);
-cmi_power(sc, 3);
-
-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);
-bus_release_resource(dev, SYS_RES_IOPORT, sc->regid, sc->reg);
-snd_mtxfree(sc->lock);
-free(sc, M_DEVBUF);
+ sc = pcm_getdevinfo(dev);
+ cmi_uninit(sc);
+ cmi_power(sc, 3);
+
+ 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);
-return 0;
+ snd_mtxfree(sc->lock);
+ free(sc, M_DEVBUF);
+
+ return 0;
}
static int
cmi_suspend(device_t dev)
{
-struct sc_info *sc = pcm_getdevinfo(dev);
+ struct sc_info *sc = pcm_getdevinfo(dev);
-snd_mtxlock(sc->lock);
-sc->pch.dma_was_active = cmi_ch0_stop(sc, &sc->pch);
-sc->rch.dma_was_active = cmi_ch1_stop(sc, &sc->rch);
-cmi_power(sc, 3);
-snd_mtxunlock(sc->lock);
-return 0;
+ snd_mtxlock(sc->lock);
+ sc->pch.dma_was_active = cmi_ch0_stop(sc, &sc->pch);
+ sc->rch.dma_was_active = cmi_ch1_stop(sc, &sc->rch);
+ cmi_power(sc, 3);
+ snd_mtxunlock(sc->lock);
+ return 0;
}
static int
cmi_resume(device_t dev)
{
-struct sc_info *sc = pcm_getdevinfo(dev);
-
-snd_mtxlock(sc->lock);
-cmi_power(sc, 0);
-if (cmi_init(sc) != 0) {
-device_printf(dev, "unable to reinitialize the cardn");
-snd_mtxunlock(sc->lock);
-return ENXIO;
-}
-
-if (mixer_reinit(dev) == -1) {
-device_printf(dev, "unable to reinitialize the mixern");
-snd_mtxunlock(sc->lock);
-return ENXIO;
-}
-
-if (sc->pch.dma_was_active) {
-cmichan_setspeed(NULL, &sc->pch, sc->pch.spd);
-cmichan_setformat(NULL, &sc->pch, sc->pch.fmt);
-cmi_ch0_start(sc, &sc->pch);
-}
+ struct sc_info *sc = pcm_getdevinfo(dev);
-if (sc->rch.dma_was_active) {
-cmichan_setspeed(NULL, &sc->rch, sc->rch.spd);
-cmichan_setformat(NULL, &sc->rch, sc->rch.fmt);
-cmi_ch1_start(sc, &sc->rch);
-}
-snd_mtxunlock(sc->lock);
-return 0;
+ snd_mtxlock(sc->lock);
+ cmi_power(sc, 0);
+ if (cmi_init(sc) != 0) {
+ device_printf(dev, "unable to reinitialize the card\n");
+ snd_mtxunlock(sc->lock);
+ return ENXIO;
+ }
+
+ if (mixer_reinit(dev) == -1) {
+ device_printf(dev, "unable to reinitialize the mixer\n");
+ snd_mtxunlock(sc->lock);
+ return ENXIO;
+ }
+
+ if (sc->pch.dma_was_active) {
+ cmichan_setspeed(NULL, &sc->pch, sc->pch.spd);
+ cmichan_setformat(NULL, &sc->pch, sc->pch.fmt);
+ cmi_ch0_start(sc, &sc->pch);
+ }
+
+ if (sc->rch.dma_was_active) {
+ cmichan_setspeed(NULL, &sc->rch, sc->rch.spd);
+ cmichan_setformat(NULL, &sc->rch, sc->rch.fmt);
+ cmi_ch1_start(sc, &sc->rch);
+ }
+ snd_mtxunlock(sc->lock);
+ return 0;
}
static device_method_t cmi_methods[] = {
-DEVMETHOD(device_probe, cmi_probe),
-DEVMETHOD(device_attach, cmi_attach),
-DEVMETHOD(device_detach, cmi_detach),
-DEVMETHOD(device_resume, cmi_resume),
-DEVMETHOD(device_suspend, cmi_suspend),
-{ 0, 0 }
+ DEVMETHOD(device_probe, cmi_probe),
+ DEVMETHOD(device_attach, cmi_attach),
+ DEVMETHOD(device_detach, cmi_detach),
+ DEVMETHOD(device_resume, cmi_resume),
+ DEVMETHOD(device_suspend, cmi_suspend),
+ { 0, 0 }
};
static driver_t cmi_driver = {
-"pcm",
-cmi_methods,
-PCM_SOFTC_SIZE
+ "pcm",
+ cmi_methods,
+ PCM_SOFTC_SIZE
};
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);
--- /dev/null
+++ sys/dev/sound/pci/envy24ht.c
@@ -0,0 +1,2601 @@
+/*
+ * Copyright (c) 2006 Konstantin Dimitrov <kosio.dimitrov at gmail.com>
+ * Copyright (c) 2001 Katsurajima Naoto <raven at katsurajima.seya.yokohama.jp>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHERIN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+
+/*
+ * Konstantin Dimitrov's thanks list:
+ *
+ * A huge thanks goes to Spas Filipov for his friendship, support and his
+ * generous gift - an 'Audiotrak Prodigy HD2' audio card! I also want to
+ * thank Keiichi Iwasaki and his parents, because they helped Spas to get
+ * the card from Japan! Having hardware sample of Prodigy HD2 made adding
+ * support for that great card very easy and real fun and pleasure.
+ *
+ */
+
+#include <dev/sound/pcm/sound.h>
+#include <dev/sound/pcm/ac97.h>
+#include <dev/sound/pci/spicds.h>
+#include <dev/sound/pci/envy24ht.h>
+
+#include <dev/pci/pcireg.h>
+#include <dev/pci/pcivar.h>
+
+#include "mixer_if.h"
+
+SND_DECLARE_FILE("$FreeBSD: src/sys/dev/sound/pci/envy24ht.c,v 1.15 2007/06/02 17:28:26 ariff Exp $");
+
+MALLOC_DEFINE(M_ENVY24HT, "envy24ht", "envy24ht audio");
+
+/* -------------------------------------------------------------------- */
+
+struct sc_info;
+
+#define ENVY24HT_PLAY_CHNUM 8
+#define ENVY24HT_REC_CHNUM 2
+#define ENVY24HT_PLAY_BUFUNIT (4 /* byte/sample */ * 8 /* channel */)
+#define ENVY24HT_REC_BUFUNIT (4 /* byte/sample */ * 2 /* channel */)
+#define ENVY24HT_SAMPLE_NUM 4096
+
+#define ENVY24HT_TIMEOUT 1000
+
+#define ENVY24HT_DEFAULT_FORMAT (AFMT_STEREO | AFMT_S16_LE)
+
+#define ENVY24HT_NAMELEN 32
+
+struct envy24ht_sample {
+ volatile u_int32_t buffer;
+};
+
+typedef struct envy24ht_sample sample32_t;
+
+/* channel registers */
+struct sc_chinfo {
+ struct snd_dbuf *buffer;
+ struct pcm_channel *channel;
+ struct sc_info *parent;
+ int dir;
+ unsigned num; /* hw channel number */
+
+ /* channel information */
+ u_int32_t format;
+ u_int32_t speed;
+ u_int32_t blk; /* hw block size(dword) */
+
+ /* format conversion structure */
+ u_int8_t *data;
+ unsigned int size; /* data buffer size(byte) */
+ int unit; /* sample size(byte) */
+ unsigned int offset; /* samples number offset */
+ void (*emldma)(struct sc_chinfo *);
+
+ /* flags */
+ int run;
+};
+
+/* codec interface entrys */
+struct codec_entry {
+ void *(*create)(device_t dev, void *devinfo, int dir, int num);
+ void (*destroy)(void *codec);
+ void (*init)(void *codec);
+ void (*reinit)(void *codec);
+ void (*setvolume)(void *codec, int dir, unsigned int left, unsigned int right);
+ void (*setrate)(void *codec, int which, int rate);
+};
+
+/* system configuration information */
+struct cfg_info {
+ char *name;
+ u_int16_t subvendor, subdevice;
+ u_int8_t scfg, acl, i2s, spdif;
+ u_int32_t gpiomask, gpiostate, gpiodir;
+ u_int32_t cdti, cclk, cs;
+ u_int8_t cif, type, free;
+ struct codec_entry *codec;
+};
+
+/* device private data */
+struct sc_info {
+ device_t dev;
+ struct mtx *lock;
+
+ /* Control/Status registor */
+ struct resource *cs;
+ int csid;
+ bus_space_tag_t cst;
+ bus_space_handle_t csh;
+ /* MultiTrack registor */
+ struct resource *mt;
+ int mtid;
+ bus_space_tag_t mtt;
+ bus_space_handle_t mth;
+ /* DMA tag */
+ bus_dma_tag_t dmat;
+ /* IRQ resource */
+ struct resource *irq;
+ int irqid;
+ void *ih;
+
+ /* system configuration data */
+ struct cfg_info *cfg;
+
+ /* ADC/DAC number and info */
+ int adcn, dacn;
+ void *adc[4], *dac[4];
+
+ /* mixer control data */
+ u_int32_t src;
+ u_int8_t left[ENVY24HT_CHAN_NUM];
+ u_int8_t right[ENVY24HT_CHAN_NUM];
+
+ /* Play/Record DMA fifo */
+ sample32_t *pbuf;
+ sample32_t *rbuf;
+ u_int32_t psize, rsize; /* DMA buffer size(byte) */
+ u_int16_t blk[2]; /* transfer check blocksize(dword) */
+ bus_dmamap_t pmap, rmap;
+
+ /* current status */
+ u_int32_t speed;
+ int run[2];
+ u_int16_t intr[2];
+ struct pcmchan_caps caps[2];
+
+ /* channel info table */
+ unsigned chnum;
+ struct sc_chinfo chan[11];
+};
+
+/* -------------------------------------------------------------------- */
+
+/*
+ * prototypes
+ */
+
+/* DMA emulator */
+static void envy24ht_p8u(struct sc_chinfo *);
+static void envy24ht_p16sl(struct sc_chinfo *);
+static void envy24ht_p32sl(struct sc_chinfo *);
+static void envy24ht_r16sl(struct sc_chinfo *);
+static void envy24ht_r32sl(struct sc_chinfo *);
+
+/* channel interface */
+static void *envy24htchan_init(kobj_t, void *, struct snd_dbuf *, struct pcm_channel *, int);
+static int envy24htchan_setformat(kobj_t, void *, u_int32_t);
+static int envy24htchan_setspeed(kobj_t, void *, u_int32_t);
+static int envy24htchan_setblocksize(kobj_t, void *, u_int32_t);
+static int envy24htchan_trigger(kobj_t, void *, int);
+static int envy24htchan_getptr(kobj_t, void *);
+static struct pcmchan_caps *envy24htchan_getcaps(kobj_t, void *);
+
+/* mixer interface */
+static int envy24htmixer_init(struct snd_mixer *);
+static int envy24htmixer_reinit(struct snd_mixer *);
+static int envy24htmixer_uninit(struct snd_mixer *);
+static int envy24htmixer_set(struct snd_mixer *, unsigned, unsigned, unsigned);
+static u_int32_t envy24htmixer_setrecsrc(struct snd_mixer *, u_int32_t);
+
+/* SPI codec access interface */
+static void *envy24ht_spi_create(device_t, void *, int, int);
+static void envy24ht_spi_destroy(void *);
+static void envy24ht_spi_init(void *);
+static void envy24ht_spi_reinit(void *);
+static void envy24ht_spi_setvolume(void *, int, unsigned int, unsigned int);
+
+/* -------------------------------------------------------------------- */
+
+/*
+ system constant tables
+*/
+
+/* API -> hardware channel map */
+static unsigned envy24ht_chanmap[ENVY24HT_CHAN_NUM] = {
+ ENVY24HT_CHAN_PLAY_DAC1, /* 1 */
+ ENVY24HT_CHAN_PLAY_DAC2, /* 2 */
+ ENVY24HT_CHAN_PLAY_DAC3, /* 3 */
+ ENVY24HT_CHAN_PLAY_DAC4, /* 4 */
+ ENVY24HT_CHAN_PLAY_SPDIF, /* 0 */
+ ENVY24HT_CHAN_REC_MIX, /* 5 */
+ ENVY24HT_CHAN_REC_SPDIF, /* 6 */
+ ENVY24HT_CHAN_REC_ADC1, /* 7 */
+ ENVY24HT_CHAN_REC_ADC2, /* 8 */
+ ENVY24HT_CHAN_REC_ADC3, /* 9 */
+ ENVY24HT_CHAN_REC_ADC4, /* 10 */
+};
+
+/* mixer -> API channel map. see above */
+static int envy24ht_mixmap[] = {
+ -1, /* Master output level. It is depend on codec support */
+ -1, /* Treble level of all output channels */
+ -1, /* Bass level of all output channels */
+ -1, /* Volume of synthesier input */
+ 0, /* Output level for the audio device */
+ -1, /* Output level for the PC speaker */
+ 7, /* line in jack */
+ -1, /* microphone jack */
+ -1, /* CD audio input */
+ -1, /* Recording monitor */
+ 1, /* alternative codec */
+ -1, /* global recording level */
+ -1, /* Input gain */
+ -1, /* Output gain */
+ 8, /* Input source 1 */
+ 9, /* Input source 2 */
+ 10, /* Input source 3 */
+ 6, /* Digital (input) 1 */
+ -1, /* Digital (input) 2 */
+ -1, /* Digital (input) 3 */
+ -1, /* Phone input */
+ -1, /* Phone output */
+ -1, /* Video/TV (audio) in */
+ -1, /* Radio in */
+ -1, /* Monitor volume */
+};
+
+/* variable rate audio */
+static u_int32_t envy24ht_speed[] = {
+ 192000, 176400, 96000, 88200, 64000, 48000, 44100, 32000, 24000, 22050, 16000,
+ 12000, 11025, 9600, 8000, 0
+};
+
+/* known boards configuration */
+static struct codec_entry spi_codec = {
+ envy24ht_spi_create,
+ envy24ht_spi_destroy,
+ envy24ht_spi_init,
+ envy24ht_spi_reinit,
+ envy24ht_spi_setvolume,
+ NULL, /* setrate */
+};
+
+static struct cfg_info cfg_table[] = {
+ {
+ "Envy24HT audio (Terratec Aureon 7.1 Space)",
+ 0x153b, 0x1145,
+ 0x0b, 0x80, 0xfc, 0xc3,
+ 0x21efff, 0x7fffff, 0x5e1000,
+ 0x40000, 0x80000, 0x1000, 0x00, 0x02,
+ 0,
+ &spi_codec,
+ },
+ {
+ "Envy24HT audio (Terratec Aureon 5.1 Sky)",
+ 0x153b, 0x1147,
+ 0x0a, 0x80, 0xfc, 0xc3,
+ 0x21efff, 0x7fffff, 0x5e1000,
+ 0x40000, 0x80000, 0x1000, 0x00, 0x02,
+ 0,
+ &spi_codec,
+ },
+ {
+ "Envy24HT audio (Terratec Aureon 7.1 Universe)",
+ 0x153b, 0x1153,
+ 0x0b, 0x80, 0xfc, 0xc3,
+ 0x21efff, 0x7fffff, 0x5e1000,
+ 0x40000, 0x80000, 0x1000, 0x00, 0x02,
+ 0,
+ &spi_codec,
+ },
+ {
+ "Envy24HT audio (AudioTrak Prodigy 7.1)",
+ 0x4933, 0x4553,
+ 0x0b, 0x80, 0xfc, 0xc3,
+ 0x21efff, 0x7fffff, 0x5e1000,
+ 0x40000, 0x80000, 0x1000, 0x00, 0x02,
+ 0,
+ &spi_codec,
+ },
+ {
+ "Envy24HT audio (Terratec PHASE 28)",
+ 0x153b, 0x1149,
+ 0x0b, 0x80, 0xfc, 0xc3,
+ 0x21efff, 0x7fffff, 0x5e1000,
+ 0x40000, 0x80000, 0x1000, 0x00, 0x02,
+ 0,
+ &spi_codec,
+ },
+ {
+ "Envy24HT-S audio (Terratec PHASE 22)",
+ 0x153b, 0x1150,
+ 0x10, 0x80, 0xf0, 0xc3,
+ 0x7ffbc7, 0x7fffff, 0x438,
+ 0x20, 0x10, 0x400, 0x00, 0x00,
+ 0,
+ &spi_codec,
+ },
+ {
+ "Envy24HT audio (AudioTrak Prodigy 7.1 LT)",
+ 0x3132, 0x4154,
+ 0x4b, 0x80, 0xfc, 0xc3,
+ 0x7ff8ff, 0x7fffff, 0x700,
+ 0x400, 0x200, 0x100, 0x00, 0x02,
+ 0,
+ &spi_codec,
+ },
+ {
+ "Envy24HT audio (AudioTrak Prodigy 7.1 XT)",
+ 0x3136, 0x4154,
+ 0x4b, 0x80, 0xfc, 0xc3,
+ 0x7ff8ff, 0x7fffff, 0x700,
+ 0x400, 0x200, 0x100, 0x00, 0x02,
+ 0,
+ &spi_codec,
+ },
+ {
+ "Envy24HT audio (M-Audio Revolution 7.1)",
+ 0x1412, 0x3630,
+ 0x43, 0x80, 0xf8, 0xc1,
+ 0x3fff85, 0x72, 0x4000fa,
+ 0x08, 0x02, 0x20, 0x00, 0x04,
+ 0,
+ &spi_codec,
+ },
+ {
+ "Envy24GT audio (M-Audio Revolution 5.1)",
+ 0x1412, 0x3631,
+ 0x42, 0x80, 0xf8, 0xc1,
+ 0x3fff85, 0x72, 0x4000fa,
+ 0x08, 0x02, 0x10, 0x00, 0x03,
+ 0,
+ &spi_codec,
+ },
+ {
+ "Envy24HT audio (M-Audio Audiophile 192)",
+ 0x1412, 0x3632,
+ 0x68, 0x80, 0xf8, 0xc3,
+ 0x45, 0x4000b5, 0x7fffba,
+ 0x08, 0x02, 0x10, 0x00, 0x03,
+ 0,
+ &spi_codec,
+ },
+ {
+ "Envy24HT audio (AudioTrak Prodigy HD2)",
+ 0x3137, 0x4154,
+ 0x68, 0x80, 0x78, 0xc3,
+ 0xfff8ff, 0x200700, 0xdfffff,
+ 0x400, 0x200, 0x100, 0x00, 0x05,
+ 0,
+ &spi_codec,
+ },
+ {
+ "Envy24HT audio (ESI Juli@)",
+ 0x3031, 0x4553,
+ 0x20, 0x80, 0xf8, 0xc3,
+ 0x7fff9f, 0x8016, 0x7fff9f,
+ 0x08, 0x02, 0x10, 0x00, 0x03,
+ 0,
+ &spi_codec,
+ },
+ {
+ "Envy24HT audio (Generic)",
+ 0, 0,
+ 0x0b, 0x80, 0xfc, 0xc3,
+ 0x21efff, 0x7fffff, 0x5e1000,
+ 0x40000, 0x80000, 0x1000, 0x00, 0x02,
+ 0,
+ &spi_codec, /* default codec routines */
+ }
+};
+
+static u_int32_t envy24ht_recfmt[] = {
+ AFMT_STEREO | AFMT_S16_LE,
+ AFMT_STEREO | AFMT_S32_LE,
+ 0
+};
+static struct pcmchan_caps envy24ht_reccaps = {8000, 96000, envy24ht_recfmt, 0};
+
+static u_int32_t envy24ht_playfmt[] = {
+ AFMT_STEREO | AFMT_U8,
+ AFMT_STEREO | AFMT_S16_LE,
+ AFMT_STEREO | AFMT_S32_LE,
+ 0
+};
+
+static struct pcmchan_caps envy24ht_playcaps = {8000, 192000, envy24ht_playfmt, 0};
+
+struct envy24ht_emldma {
+ u_int32_t format;
+ void (*emldma)(struct sc_chinfo *);
+ int unit;
+};
+
+static struct envy24ht_emldma envy24ht_pemltab[] = {
+ {AFMT_STEREO | AFMT_U8, envy24ht_p8u, 2},
+ {AFMT_STEREO | AFMT_S16_LE, envy24ht_p16sl, 4},
+ {AFMT_STEREO | AFMT_S32_LE, envy24ht_p32sl, 8},
+ {0, NULL, 0}
+};
+
+static struct envy24ht_emldma envy24ht_remltab[] = {
+ {AFMT_STEREO | AFMT_S16_LE, envy24ht_r16sl, 4},
+ {AFMT_STEREO | AFMT_S32_LE, envy24ht_r32sl, 8},
+ {0, NULL, 0}
+};
+
+/* -------------------------------------------------------------------- */
+
+/* common routines */
+static u_int32_t
+envy24ht_rdcs(struct sc_info *sc, int regno, int size)
+{
+ switch (size) {
+ case 1:
+ return bus_space_read_1(sc->cst, sc->csh, regno);
+ case 2:
+ return bus_space_read_2(sc->cst, sc->csh, regno);
+ case 4:
+ return bus_space_read_4(sc->cst, sc->csh, regno);
+ default:
+ return 0xffffffff;
+ }
+}
+
+static void
+envy24ht_wrcs(struct sc_info *sc, int regno, u_int32_t data, int size)
+{
+ switch (size) {
+ case 1:
+ bus_space_write_1(sc->cst, sc->csh, regno, data);
+ break;
+ case 2:
+ bus_space_write_2(sc->cst, sc->csh, regno, data);
+ break;
+ case 4:
+ bus_space_write_4(sc->cst, sc->csh, regno, data);
+ break;
+ }
+}
+
+static u_int32_t
+envy24ht_rdmt(struct sc_info *sc, int regno, int size)
+{
+ switch (size) {
+ case 1:
+ return bus_space_read_1(sc->mtt, sc->mth, regno);
+ case 2:
+ return bus_space_read_2(sc->mtt, sc->mth, regno);
+ case 4:
+ return bus_space_read_4(sc->mtt, sc->mth, regno);
+ default:
+ return 0xffffffff;
+ }
+}
+
+static void
+envy24ht_wrmt(struct sc_info *sc, int regno, u_int32_t data, int size)
+{
+ switch (size) {
+ case 1:
+ bus_space_write_1(sc->mtt, sc->mth, regno, data);
+ break;
+ case 2:
+ bus_space_write_2(sc->mtt, sc->mth, regno, data);
+ break;
+ case 4:
+ bus_space_write_4(sc->mtt, sc->mth, regno, data);
+ break;
+ }
+}
+
+/* -------------------------------------------------------------------- */
+
+/* I2C port/E2PROM access routines */
+
+static int
+envy24ht_rdi2c(struct sc_info *sc, u_int32_t dev, u_int32_t addr)
+{
+ u_int32_t data;
+ int i;
+
+#if(0)
+ device_printf(sc->dev, "envy24ht_rdi2c(sc, 0x%02x, 0x%02x)\n", dev, addr);
+#endif
+ for (i = 0; i < ENVY24HT_TIMEOUT; i++) {
+ data = envy24ht_rdcs(sc, ENVY24HT_CCS_I2CSTAT, 1);
+ if ((data & ENVY24HT_CCS_I2CSTAT_BSY) == 0)
+ break;
+ DELAY(32); /* 31.25kHz */
+ }
+ if (i == ENVY24HT_TIMEOUT) {
+ return -1;
+ }
+ envy24ht_wrcs(sc, ENVY24HT_CCS_I2CADDR, addr, 1);
+ envy24ht_wrcs(sc, ENVY24HT_CCS_I2CDEV,
+ (dev & ENVY24HT_CCS_I2CDEV_ADDR) | ENVY24HT_CCS_I2CDEV_RD, 1);
+ for (i = 0; i < ENVY24HT_TIMEOUT; i++) {
+ data = envy24ht_rdcs(sc, ENVY24HT_CCS_I2CSTAT, 1);
+ if ((data & ENVY24HT_CCS_I2CSTAT_BSY) == 0)
+ break;
+ DELAY(32); /* 31.25kHz */
+ }
+ if (i == ENVY24HT_TIMEOUT) {
+ return -1;
+ }
+ data = envy24ht_rdcs(sc, ENVY24HT_CCS_I2CDATA, 1);
+
+#if(0)
+ device_printf(sc->dev, "envy24ht_rdi2c(): return 0x%x\n", data);
+#endif
+ return (int)data;
+}
+
+static int
+envy24ht_wri2c(struct sc_info *sc, u_int32_t dev, u_int32_t addr, u_int32_t data)
+{
+ u_int32_t tmp;
+ int i;
+
+#if(0)
+ device_printf(sc->dev, "envy24ht_rdi2c(sc, 0x%02x, 0x%02x)\n", dev, addr);
+#endif
+ for (i = 0; i < ENVY24HT_TIMEOUT; i++) {
+ tmp = envy24ht_rdcs(sc, ENVY24HT_CCS_I2CSTAT, 1);
+ if ((tmp & ENVY24HT_CCS_I2CSTAT_BSY) == 0)
+ break;
+ DELAY(32); /* 31.25kHz */
+ }
+ if (i == ENVY24HT_TIMEOUT) {
+ return -1;
+ }
+ envy24ht_wrcs(sc, ENVY24HT_CCS_I2CADDR, addr, 1);
+ envy24ht_wrcs(sc, ENVY24HT_CCS_I2CDATA, data, 1);
+ envy24ht_wrcs(sc, ENVY24HT_CCS_I2CDEV,
+ (dev & ENVY24HT_CCS_I2CDEV_ADDR) | ENVY24HT_CCS_I2CDEV_WR, 1);
+ for (i = 0; i < ENVY24HT_TIMEOUT; i++) {
+ data = envy24ht_rdcs(sc, ENVY24HT_CCS_I2CSTAT, 1);
+ if ((data & ENVY24HT_CCS_I2CSTAT_BSY) == 0)
+ break;
+ DELAY(32); /* 31.25kHz */
+ }
+ if (i == ENVY24HT_TIMEOUT) {
+ return -1;
+ }
+
+ return 0;
+}
+
+static int
+envy24ht_rdrom(struct sc_info *sc, u_int32_t addr)
+{
+ u_int32_t data;
+
+#if(0)
+ device_printf(sc->dev, "envy24ht_rdrom(sc, 0x%02x)\n", addr);
+#endif
+ data = envy24ht_rdcs(sc, ENVY24HT_CCS_I2CSTAT, 1);
+ if ((data & ENVY24HT_CCS_I2CSTAT_ROM) == 0) {
+#if(0)
+ device_printf(sc->dev, "envy24ht_rdrom(): E2PROM not presented\n");
+#endif
+ return -1;
+ }
+
+ return envy24ht_rdi2c(sc, ENVY24HT_CCS_I2CDEV_ROM, addr);
+}
+
+static struct cfg_info *
+envy24ht_rom2cfg(struct sc_info *sc)
+{
+ struct cfg_info *buff;
+ int size;
+ int i;
+
+#if(0)
+ device_printf(sc->dev, "envy24ht_rom2cfg(sc)\n");
+#endif
+ size = envy24ht_rdrom(sc, ENVY24HT_E2PROM_SIZE);
+ if ((size < ENVY24HT_E2PROM_GPIOSTATE + 3) || (size == 0x78)) {
+#if(0)
+ device_printf(sc->dev, "envy24ht_rom2cfg(): ENVY24HT_E2PROM_SIZE-->%d\n", size);
+#endif
+ buff = malloc(sizeof(*buff), M_ENVY24HT, M_NOWAIT);
+ if (buff == NULL) {
+#if(0)
+ device_printf(sc->dev, "envy24ht_rom2cfg(): malloc()\n");
+#endif
+ return NULL;
+ }
+ buff->free = 1;
+
+ /* no valid e2prom, using default values */
+ buff->subvendor = envy24ht_rdrom(sc, ENVY24HT_E2PROM_SUBVENDOR) << 8;
+ buff->subvendor += envy24ht_rdrom(sc, ENVY24HT_E2PROM_SUBVENDOR + 1);
+ buff->subdevice = envy24ht_rdrom(sc, ENVY24HT_E2PROM_SUBDEVICE) << 8;
+ buff->subdevice += envy24ht_rdrom(sc, ENVY24HT_E2PROM_SUBDEVICE + 1);
+ buff->scfg = 0x0b;
+ buff->acl = 0x80;
+ buff->i2s = 0xfc;
+ buff->spdif = 0xc3;
+ buff->gpiomask = 0x21efff;
+ buff->gpiostate = 0x7fffff;
+ buff->gpiodir = 0x5e1000;
+ buff->cdti = 0x40000;
+ buff->cclk = 0x80000;
+ buff->cs = 0x1000;
+ buff->cif = 0x00;
+ buff->type = 0x02;
+
+ for (i = 0; cfg_table[i].subvendor != 0 || cfg_table[i].subdevice != 0;
+i++)
+ if (cfg_table[i].subvendor == buff->subvendor &&
+ cfg_table[i].subdevice == buff->subdevice)
+ break;
+ buff->name = cfg_table[i].name;
+ buff->codec = cfg_table[i].codec;
+
+ return buff;
+#if 0
+ return NULL;
+#endif
+ }
+ buff = malloc(sizeof(*buff), M_ENVY24HT, M_NOWAIT);
+ if (buff == NULL) {
+#if(0)
+ device_printf(sc->dev, "envy24ht_rom2cfg(): malloc()\n");
+#endif
+ return NULL;
+ }
+ buff->free = 1;
+
+ buff->subvendor = envy24ht_rdrom(sc, ENVY24HT_E2PROM_SUBVENDOR) << 8;
+ buff->subvendor += envy24ht_rdrom(sc, ENVY24HT_E2PROM_SUBVENDOR + 1);
+ buff->subdevice = envy24ht_rdrom(sc, ENVY24HT_E2PROM_SUBDEVICE) << 8;
+ buff->subdevice += envy24ht_rdrom(sc, ENVY24HT_E2PROM_SUBDEVICE + 1);
+ buff->scfg = envy24ht_rdrom(sc, ENVY24HT_E2PROM_SCFG);
+ buff->acl = envy24ht_rdrom(sc, ENVY24HT_E2PROM_ACL);
+ buff->i2s = envy24ht_rdrom(sc, ENVY24HT_E2PROM_I2S);
+ buff->spdif = envy24ht_rdrom(sc, ENVY24HT_E2PROM_SPDIF);
+ buff->gpiomask = envy24ht_rdrom(sc, ENVY24HT_E2PROM_GPIOMASK) | \
+ envy24ht_rdrom(sc, ENVY24HT_E2PROM_GPIOMASK + 1) << 8 | \
+ envy24ht_rdrom(sc, ENVY24HT_E2PROM_GPIOMASK + 2) << 16;
+ buff->gpiostate = envy24ht_rdrom(sc, ENVY24HT_E2PROM_GPIOSTATE) | \
+ envy24ht_rdrom(sc, ENVY24HT_E2PROM_GPIOSTATE + 1) << 8 | \
+ envy24ht_rdrom(sc, ENVY24HT_E2PROM_GPIOSTATE + 2) << 16;
+ buff->gpiodir = envy24ht_rdrom(sc, ENVY24HT_E2PROM_GPIODIR) | \
+ envy24ht_rdrom(sc, ENVY24HT_E2PROM_GPIODIR + 1) << 8 | \
+ envy24ht_rdrom(sc, ENVY24HT_E2PROM_GPIODIR + 2) << 16;
+
+ for (i = 0; cfg_table[i].subvendor != 0 || cfg_table[i].subdevice != 0; i++)
+ if (cfg_table[i].subvendor == buff->subvendor &&
+ cfg_table[i].subdevice == buff->subdevice)
+ break;
+ buff->name = cfg_table[i].name;
+ buff->codec = cfg_table[i].codec;
+
+ return buff;
+}
+
+static void
+envy24ht_cfgfree(struct cfg_info *cfg) {
+ if (cfg == NULL)
+ return;
+ if (cfg->free)
+ free(cfg, M_ENVY24HT);
+ return;
+}
+
+/* -------------------------------------------------------------------- */
+
+/* AC'97 codec access routines */
+
+#if 0
+static int
+envy24ht_coldcd(struct sc_info *sc)
+{
+ u_int32_t data;
+ int i;
+
+#if(0)
+ device_printf(sc->dev, "envy24ht_coldcd()\n");
+#endif
+ envy24ht_wrmt(sc, ENVY24HT_MT_AC97CMD, ENVY24HT_MT_AC97CMD_CLD, 1);
+ DELAY(10);
+ envy24ht_wrmt(sc, ENVY24HT_MT_AC97CMD, 0, 1);
+ DELAY(1000);
+ for (i = 0; i < ENVY24HT_TIMEOUT; i++) {
+ data = envy24ht_rdmt(sc, ENVY24HT_MT_AC97CMD, 1);
+ if (data & ENVY24HT_MT_AC97CMD_RDY) {
+ return 0;
+ }
+ }
+
+ return -1;
+}
+
+static int
+envy24ht_slavecd(struct sc_info *sc)
+{
+ u_int32_t data;
+ int i;
+
+#if(0)
+ device_printf(sc->dev, "envy24ht_slavecd()\n");
+#endif
+ envy24ht_wrmt(sc, ENVY24HT_MT_AC97CMD,
+ ENVY24HT_MT_AC97CMD_CLD | ENVY24HT_MT_AC97CMD_WRM, 1);
+ DELAY(10);
+ envy24ht_wrmt(sc, ENVY24HT_MT_AC97CMD, 0, 1);
+ DELAY(1000);
+ for (i = 0; i < ENVY24HT_TIMEOUT; i++) {
+ data = envy24ht_rdmt(sc, ENVY24HT_MT_AC97CMD, 1);
+ if (data & ENVY24HT_MT_AC97CMD_RDY) {
+ return 0;
+ }
+ }
+
+ return -1;
+}
+
+static int
+envy24ht_rdcd(kobj_t obj, void *devinfo, int regno)
+{
+ struct sc_info *sc = (struct sc_info *)devinfo;
+ u_int32_t data;
+ int i;
+
+#if(0)
+ device_printf(sc->dev, "envy24ht_rdcd(obj, sc, 0x%02x)\n", regno);
+#endif
+ envy24ht_wrmt(sc, ENVY24HT_MT_AC97IDX, (u_int32_t)regno, 1);
+ envy24ht_wrmt(sc, ENVY24HT_MT_AC97CMD, ENVY24HT_MT_AC97CMD_RD, 1);
+ for (i = 0; i < ENVY24HT_TIMEOUT; i++) {
+ data = envy24ht_rdmt(sc, ENVY24HT_MT_AC97CMD, 1);
+ if ((data & ENVY24HT_MT_AC97CMD_RD) == 0)
+ break;
+ }
+ data = envy24ht_rdmt(sc, ENVY24HT_MT_AC97DLO, 2);
+
+#if(0)
+ device_printf(sc->dev, "envy24ht_rdcd(): return 0x%x\n", data);
+#endif
+ return (int)data;
+}
+
+static int
+envy24ht_wrcd(kobj_t obj, void *devinfo, int regno, u_int16_t data)
+{
+ struct sc_info *sc = (struct sc_info *)devinfo;
+ u_int32_t cmd;
+ int i;
+
+#if(0)
+ device_printf(sc->dev, "envy24ht_wrcd(obj, sc, 0x%02x, 0x%04x)\n", regno, data);
+#endif
+ envy24ht_wrmt(sc, ENVY24HT_MT_AC97IDX, (u_int32_t)regno, 1);
+ envy24ht_wrmt(sc, ENVY24HT_MT_AC97DLO, (u_int32_t)data, 2);
+ envy24ht_wrmt(sc, ENVY24HT_MT_AC97CMD, ENVY24HT_MT_AC97CMD_WR, 1);
+ for (i = 0; i < ENVY24HT_TIMEOUT; i++) {
+ cmd = envy24ht_rdmt(sc, ENVY24HT_MT_AC97CMD, 1);
+ if ((cmd & ENVY24HT_MT_AC97CMD_WR) == 0)
+ break;
+ }
+
+ return 0;
+}
+
+static kobj_method_t envy24ht_ac97_methods[] = {
+ KOBJMETHOD(ac97_read, envy24ht_rdcd),
+ KOBJMETHOD(ac97_write, envy24ht_wrcd),
+ {0, 0}
+};
+AC97_DECLARE(envy24ht_ac97);
+#endif
+
+/* -------------------------------------------------------------------- */
+
+/* GPIO access routines */
+
+static u_int32_t
+envy24ht_gpiord(struct sc_info *sc)
+{
+ if (sc->cfg->subvendor == 0x153b && sc->cfg->subdevice == 0x1150)
+ return envy24ht_rdcs(sc, ENVY24HT_CCS_GPIO_LDATA, 2);
+ else
+ return (envy24ht_rdcs(sc, ENVY24HT_CCS_GPIO_HDATA, 1) << 16 | envy24ht_rdcs(sc, ENVY24HT_CCS_GPIO_LDATA, 2));
+}
+
+static void
+envy24ht_gpiowr(struct sc_info *sc, u_int32_t data)
+{
+#if(0)
+ device_printf(sc->dev, "envy24ht_gpiowr(sc, 0x%02x)\n", data & 0x7FFFFF);
+ return;
+#endif
+ envy24ht_wrcs(sc, ENVY24HT_CCS_GPIO_LDATA, data, 2);
+ if (sc->cfg->subdevice != 0x1150)
+ envy24ht_wrcs(sc, ENVY24HT_CCS_GPIO_HDATA, data >> 16, 1);
+ return;
+}
+
+#if 0
+static u_int32_t
+envy24ht_gpiogetmask(struct sc_info *sc)
+{
+ return (envy24ht_rdcs(sc, ENVY24HT_CCS_GPIO_HMASK, 1) << 16 | envy24ht_rdcs(sc, ENVY24HT_CCS_GPIO_LMASK, 2));
+}
+#endif
+
+static void
+envy24ht_gpiosetmask(struct sc_info *sc, u_int32_t mask)
+{
+ envy24ht_wrcs(sc, ENVY24HT_CCS_GPIO_LMASK, mask, 2);
+ if (sc->cfg->subdevice != 0x1150)
+ envy24ht_wrcs(sc, ENVY24HT_CCS_GPIO_HMASK, mask >> 16, 1);
+ return;
+}
+
+#if 0
+static u_int32_t
+envy24ht_gpiogetdir(struct sc_info *sc)
+{
+ return envy24ht_rdcs(sc, ENVY24HT_CCS_GPIO_CTLDIR, 4);
+}
+#endif
+
+static void
+envy24ht_gpiosetdir(struct sc_info *sc, u_int32_t dir)
+{
+ if (sc->cfg->subvendor == 0x153b && sc->cfg->subdevice == 0x1150)
+ envy24ht_wrcs(sc, ENVY24HT_CCS_GPIO_CTLDIR, dir, 2);
+ else
+ envy24ht_wrcs(sc, ENVY24HT_CCS_GPIO_CTLDIR, dir, 4);
+ return;
+}
+
+/* -------------------------------------------------------------------- */
+
+/* SPI codec access interface routine */
+
+struct envy24ht_spi_codec {
+ struct spicds_info *info;
+ struct sc_info *parent;
+ int dir;
+ int num;
+ int cs, cclk, cdti;
+};
+
+static void
+envy24ht_spi_ctl(void *codec, unsigned int cs, unsigned int cclk, unsigned int cdti)
+{
+ u_int32_t data = 0;
+ struct envy24ht_spi_codec *ptr = codec;
+
+#if(0)
+ device_printf(ptr->parent->dev, "--> %d, %d, %d\n", cs, cclk, cdti);
+#endif
+ data = envy24ht_gpiord(ptr->parent);
+ data &= ~(ptr->cs | ptr->cclk | ptr->cdti);
+ if (cs) data += ptr->cs;
+ if (cclk) data += ptr->cclk;
+ if (cdti) data += ptr->cdti;
+ envy24ht_gpiowr(ptr->parent, data);
+ return;
+}
+
+static void *
+envy24ht_spi_create(device_t dev, void *info, int dir, int num)
+{
+ struct sc_info *sc = info;
+ struct envy24ht_spi_codec *buff = NULL;
+
+#if(0)
+ device_printf(sc->dev, "envy24ht_spi_create(dev, sc, %d, %d)\n", dir, num);
+#endif
+
+ buff = malloc(sizeof(*buff), M_ENVY24HT, M_NOWAIT);
+ if (buff == NULL)
+ return NULL;
+
+ if (dir == PCMDIR_REC && sc->adc[num] != NULL)
+ buff->info = ((struct envy24ht_spi_codec *)sc->adc[num])->info;
+ else if (dir == PCMDIR_PLAY && sc->dac[num] != NULL)
+ buff->info = ((struct envy24ht_spi_codec *)sc->dac[num])->info;
+ else
+ buff->info = spicds_create(dev, buff, num, envy24ht_spi_ctl);
+ if (buff->info == NULL) {
+ free(buff, M_ENVY24HT);
+ return NULL;
+ }
+
+ buff->parent = sc;
+ buff->dir = dir;
+ buff->num = num;
+
+ return (void *)buff;
+}
+
+static void
+envy24ht_spi_destroy(void *codec)
+{
+ struct envy24ht_spi_codec *ptr = codec;
+ if (ptr == NULL)
+ return;
+#if(0)
+ device_printf(ptr->parent->dev, "envy24ht_spi_destroy()\n");
+#endif
+
+ if (ptr->dir == PCMDIR_PLAY) {
+ if (ptr->parent->dac[ptr->num] != NULL)
+ spicds_destroy(ptr->info);
+ }
+ else {
+ if (ptr->parent->adc[ptr->num] != NULL)
+ spicds_destroy(ptr->info);
+ }
+
+ free(codec, M_ENVY24HT);
+}
+
+static void
+envy24ht_spi_init(void *codec)
+{
+ struct envy24ht_spi_codec *ptr = codec;
+ if (ptr == NULL)
+ return;
+#if(0)
+ device_printf(ptr->parent->dev, "envy24ht_spicds_init()\n");
+#endif
+ ptr->cs = ptr->parent->cfg->cs;
+ ptr->cclk = ptr->parent->cfg->cclk;
+ ptr->cdti = ptr->parent->cfg->cdti;
+ spicds_settype(ptr->info, ptr->parent->cfg->type);
+ spicds_setcif(ptr->info, ptr->parent->cfg->cif);
+ if (ptr->parent->cfg->type == SPICDS_TYPE_AK4524 || \
+ ptr->parent->cfg->type == SPICDS_TYPE_AK4528) {
+ spicds_setformat(ptr->info,
+ AK452X_FORMAT_I2S | AK452X_FORMAT_256FSN | AK452X_FORMAT_1X);
+ spicds_setdvc(ptr->info, AK452X_DVC_DEMOFF);
+ }
+
+ /* for the time being, init only first codec */
+ if (ptr->num == 0)
+ spicds_init(ptr->info);
+}
+
+static void
+envy24ht_spi_reinit(void *codec)
+{
+ struct envy24ht_spi_codec *ptr = codec;
+ if (ptr == NULL)
+ return;
+#if(0)
+ device_printf(ptr->parent->dev, "envy24ht_spi_reinit()\n");
+#endif
+
+ spicds_reinit(ptr->info);
+}
+
+static void
+envy24ht_spi_setvolume(void *codec, int dir, unsigned int left, unsigned int right)
+{
+ struct envy24ht_spi_codec *ptr = codec;
+ if (ptr == NULL)
+ return;
+#if(0)
+ device_printf(ptr->parent->dev, "envy24ht_spi_set()\n");
+#endif
+
+ spicds_set(ptr->info, dir, left, right);
+}
+
+/* -------------------------------------------------------------------- */
+
+/* hardware access routeines */
+
+static struct {
+ u_int32_t speed;
+ u_int32_t code;
+} envy24ht_speedtab[] = {
+ {48000, ENVY24HT_MT_RATE_48000},
+ {24000, ENVY24HT_MT_RATE_24000},
+ {12000, ENVY24HT_MT_RATE_12000},
+ {9600, ENVY24HT_MT_RATE_9600},
+ {32000, ENVY24HT_MT_RATE_32000},
+ {16000, ENVY24HT_MT_RATE_16000},
+ {8000, ENVY24HT_MT_RATE_8000},
+ {96000, ENVY24HT_MT_RATE_96000},
+ {192000, ENVY24HT_MT_RATE_192000},
+ {64000, ENVY24HT_MT_RATE_64000},
+ {44100, ENVY24HT_MT_RATE_44100},
+ {22050, ENVY24HT_MT_RATE_22050},
+ {11025, ENVY24HT_MT_RATE_11025},
+ {88200, ENVY24HT_MT_RATE_88200},
+ {176400, ENVY24HT_MT_RATE_176400},
+ {0, 0x10}
+};
+
+static int
+envy24ht_setspeed(struct sc_info *sc, u_int32_t speed) {
+ u_int32_t code, i2sfmt;
+ int i = 0;
+
+#if(0)
+ device_printf(sc->dev, "envy24ht_setspeed(sc, %d)\n", speed);
+ if (speed == 0) {
+ code = ENVY24HT_MT_RATE_SPDIF; /* external master clock */
+ envy24ht_slavecd(sc);
+ }
+ else {
+#endif
+ for (i = 0; envy24ht_speedtab[i].speed != 0; i++) {
+ if (envy24ht_speedtab[i].speed == speed)
+ break;
+ }
+ code = envy24ht_speedtab[i].code;
+#if 0
+ }
+ device_printf(sc->dev, "envy24ht_setspeed(): speed %d/code 0x%04x\n", envy24ht_speedtab[i].speed, code);
+#endif
+ if (code < 0x10) {
+ envy24ht_wrmt(sc, ENVY24HT_MT_RATE, code, 1);
+ if ((((sc->cfg->scfg & ENVY24HT_CCSM_SCFG_XIN2) == 0x00) && (code == ENVY24HT_MT_RATE_192000)) || \
+ (code == ENVY24HT_MT_RATE_176400)) {
+ i2sfmt = envy24ht_rdmt(sc, ENVY24HT_MT_I2S, 1);
+ i2sfmt |= ENVY24HT_MT_I2S_MLR128;
+ envy24ht_wrmt(sc, ENVY24HT_MT_I2S, i2sfmt, 1);
+ }
+ else {
+ i2sfmt = envy24ht_rdmt(sc, ENVY24HT_MT_I2S, 1);
+ i2sfmt &= ~ENVY24HT_MT_I2S_MLR128;
+ envy24ht_wrmt(sc, ENVY24HT_MT_I2S, i2sfmt, 1);
+ }
+ code = envy24ht_rdmt(sc, ENVY24HT_MT_RATE, 1);
+ code &= ENVY24HT_MT_RATE_MASK;
+ for (i = 0; envy24ht_speedtab[i].code < 0x10; i++) {
+ if (envy24ht_speedtab[i].code == code)
+ break;
+ }
+ speed = envy24ht_speedtab[i].speed;
+ }
+ else
+ speed = 0;
+
+#if(0)
+ device_printf(sc->dev, "envy24ht_setspeed(): return %d\n", speed);
+#endif
+ return speed;
+}
+
+static void
+envy24ht_setvolume(struct sc_info *sc, unsigned ch)
+{
+#if(0)
+ device_printf(sc->dev, "envy24ht_setvolume(sc, %d)\n", ch);
+ envy24ht_wrmt(sc, ENVY24HT_MT_VOLIDX, ch * 2, 1);
+ envy24ht_wrmt(sc, ENVY24HT_MT_VOLUME, 0x7f00 | sc->left[ch], 2);
+ envy24ht_wrmt(sc, ENVY24HT_MT_VOLIDX, ch * 2 + 1, 1);
+ envy24ht_wrmt(sc, ENVY24HT_MT_VOLUME, (sc->right[ch] << 8) | 0x7f, 2);
+#endif
+}
+
+static void
+envy24ht_mutevolume(struct sc_info *sc, unsigned ch)
+{
+#if 0
+ u_int32_t vol;
+
+ device_printf(sc->dev, "envy24ht_mutevolume(sc, %d)\n", ch);
+ vol = ENVY24HT_VOL_MUTE << 8 | ENVY24HT_VOL_MUTE;
+ envy24ht_wrmt(sc, ENVY24HT_MT_VOLIDX, ch * 2, 1);
+ envy24ht_wrmt(sc, ENVY24HT_MT_VOLUME, vol, 2);
+ envy24ht_wrmt(sc, ENVY24HT_MT_VOLIDX, ch * 2 + 1, 1);
+ envy24ht_wrmt(sc, ENVY24HT_MT_VOLUME, vol, 2);
+#endif
+}
+
+static u_int32_t
+envy24ht_gethwptr(struct sc_info *sc, int dir)
+{
+ int unit, regno;
+ u_int32_t ptr, rtn;
+
+#if(0)
+ device_printf(sc->dev, "envy24ht_gethwptr(sc, %d)\n", dir);
+#endif
+ if (dir == PCMDIR_PLAY) {
+ rtn = sc->psize / 4;
+ unit = ENVY24HT_PLAY_BUFUNIT / 4;
+ regno = ENVY24HT_MT_PCNT;
+ }
+ else {
+ rtn = sc->rsize / 4;
+ unit = ENVY24HT_REC_BUFUNIT / 4;
+ regno = ENVY24HT_MT_RCNT;
+ }
+
+ ptr = envy24ht_rdmt(sc, regno, 2);
+ rtn -= (ptr + 1);
+ rtn /= unit;
+
+#if(0)
+ device_printf(sc->dev, "envy24ht_gethwptr(): return %d\n", rtn);
+#endif
+ return rtn;
+}
+
+static void
+envy24ht_updintr(struct sc_info *sc, int dir)
+{
+ int regptr, regintr;
+ u_int32_t mask, intr;
+ u_int32_t ptr, size, cnt;
+ u_int16_t blk;
+
+#if(0)
+ device_printf(sc->dev, "envy24ht_updintr(sc, %d)\n", dir);
+#endif
+ if (dir == PCMDIR_PLAY) {
+ blk = sc->blk[0];
+ size = sc->psize / 4;
+ regptr = ENVY24HT_MT_PCNT;
+ regintr = ENVY24HT_MT_PTERM;
+ mask = ~ENVY24HT_MT_INT_PMASK;
+ }
+ else {
+ blk = sc->blk[1];
+ size = sc->rsize / 4;
+ regptr = ENVY24HT_MT_RCNT;
+ regintr = ENVY24HT_MT_RTERM;
+ mask = ~ENVY24HT_MT_INT_RMASK;
+ }
+
+ ptr = size - envy24ht_rdmt(sc, regptr, 2) - 1;
+ /*
+ cnt = blk - ptr % blk - 1;
+ if (cnt == 0)
+ cnt = blk - 1;
+ */
+ cnt = blk - 1;
+#if(0)
+ device_printf(sc->dev, "envy24ht_updintr():ptr = %d, blk = %d, cnt = %d\n", ptr, blk, cnt);
+#endif
+ envy24ht_wrmt(sc, regintr, cnt, 2);
+ intr = envy24ht_rdmt(sc, ENVY24HT_MT_INT_MASK, 1);
+#if(0)
+ device_printf(sc->dev, "envy24ht_updintr():intr = 0x%02x, mask = 0x%02x\n", intr, mask);
+#endif
+ envy24ht_wrmt(sc, ENVY24HT_MT_INT_MASK, intr & mask, 1);
+#if(0)
+ device_printf(sc->dev, "envy24ht_updintr():INT-->0x%02x\n",
+ envy24ht_rdmt(sc, ENVY24HT_MT_INT_MASK, 1));
+#endif
+
+ return;
+}
+
+#if 0
+static void
+envy24ht_maskintr(struct sc_info *sc, int dir)
+{
+ u_int32_t mask, intr;
+
+#if(0)
+ device_printf(sc->dev, "envy24ht_maskintr(sc, %d)\n", dir);
+#endif
+ if (dir == PCMDIR_PLAY)
+ mask = ENVY24HT_MT_INT_PMASK;
+ else
+ mask = ENVY24HT_MT_INT_RMASK;
+ intr = envy24ht_rdmt(sc, ENVY24HT_MT_INT, 1);
+ envy24ht_wrmt(sc, ENVY24HT_MT_INT, intr | mask, 1);
+
+ return;
+}
+#endif
+
+static int
+envy24ht_checkintr(struct sc_info *sc, int dir)
+{
+ u_int32_t mask, stat, intr, rtn;
+
+#if(0)
+ device_printf(sc->dev, "envy24ht_checkintr(sc, %d)\n", dir);
+#endif
+ intr = envy24ht_rdmt(sc, ENVY24HT_MT_INT_STAT, 1);
+ if (dir == PCMDIR_PLAY) {
+ if ((rtn = intr & ENVY24HT_MT_INT_PSTAT) != 0) {
+ mask = ~ENVY24HT_MT_INT_RSTAT;
+ envy24ht_wrmt(sc, 0x1a, 0x01, 1);
+ envy24ht_wrmt(sc, ENVY24HT_MT_INT_STAT, (intr & mask) | ENVY24HT_MT_INT_PSTAT | 0x08, 1);
+ stat = envy24ht_rdmt(sc, ENVY24HT_MT_INT_MASK, 1);
+ envy24ht_wrmt(sc, ENVY24HT_MT_INT_MASK, stat | ENVY24HT_MT_INT_PMASK, 1);
+ }
+ }
+ else {
+ if ((rtn = intr & ENVY24HT_MT_INT_RSTAT) != 0) {
+ mask = ~ENVY24HT_MT_INT_PSTAT;
+#if 0
+ stat = ENVY24HT_MT_INT_RSTAT | ENVY24HT_MT_INT_RMASK;
+#endif
+ envy24ht_wrmt(sc, ENVY24HT_MT_INT_STAT, (intr & mask) | ENVY24HT_MT_INT_RSTAT, 1);
+ stat = envy24ht_rdmt(sc, ENVY24HT_MT_INT_MASK, 1);
+ envy24ht_wrmt(sc, ENVY24HT_MT_INT_MASK, stat | ENVY24HT_MT_INT_RMASK, 1);
+ }
+ }
+
+ return rtn;
+}
+
+static void
+envy24ht_start(struct sc_info *sc, int dir)
+{
+ u_int32_t stat, sw;
+
+#if(0)
+ device_printf(sc->dev, "envy24ht_start(sc, %d)\n", dir);
+#endif
+ if (dir == PCMDIR_PLAY)
+ sw = ENVY24HT_MT_PCTL_PSTART;
+ else
+ sw = ENVY24HT_MT_PCTL_RSTART;
+
+ stat = envy24ht_rdmt(sc, ENVY24HT_MT_PCTL, 1);
+ envy24ht_wrmt(sc, ENVY24HT_MT_PCTL, stat | sw, 1);
+#if(0)
+ DELAY(100);
+ device_printf(sc->dev, "PADDR:0x%08x\n", envy24ht_rdmt(sc, ENVY24HT_MT_PADDR, 4));
+ device_printf(sc->dev, "PCNT:%ld\n", envy24ht_rdmt(sc, ENVY24HT_MT_PCNT, 2));
+#endif
+
+ return;
+}
+
+static void
+envy24ht_stop(struct sc_info *sc, int dir)
+{
+ u_int32_t stat, sw;
+
+#if(0)
+ device_printf(sc->dev, "envy24ht_stop(sc, %d)\n", dir);
+#endif
+ if (dir == PCMDIR_PLAY)
+ sw = ~ENVY24HT_MT_PCTL_PSTART;
+ else
+ sw = ~ENVY24HT_MT_PCTL_RSTART;
+
+ stat = envy24ht_rdmt(sc, ENVY24HT_MT_PCTL, 1);
+ envy24ht_wrmt(sc, ENVY24HT_MT_PCTL, stat & sw, 1);
+
+ return;
+}
+
+#if 0
+static int
+envy24ht_route(struct sc_info *sc, int dac, int class, int adc, int rev)
+{
+ return 0;
+}
+#endif
+
+/* -------------------------------------------------------------------- */
+
+/* buffer copy routines */
+static void
+envy24ht_p32sl(struct sc_chinfo *ch)
+{
+ int length;
+ sample32_t *dmabuf;
+ u_int32_t *data;
+ int src, dst, ssize, dsize, slot;
+ int i;
+
+ length = sndbuf_getready(ch->buffer) / 8;
+ dmabuf = ch->parent->pbuf;
+ data = (u_int32_t *)ch->data;
+ src = sndbuf_getreadyptr(ch->buffer) / 4;
+ dst = src / 2 + ch->offset;
+ ssize = ch->size / 4;
+ dsize = ch->size / 8;
+ slot = ch->num * 2;
+
+ for (i = 0; i < length; i++) {
+ dmabuf[dst * ENVY24HT_PLAY_CHNUM + slot].buffer = data[src];
+ dmabuf[dst * ENVY24HT_PLAY_CHNUM + slot + 1].buffer = data[src + 1];
+ dst++;
+ dst %= dsize;
+ src += 2;
+ src %= ssize;
+ }
+
+ return;
+}
+
+static void
+envy24ht_p16sl(struct sc_chinfo *ch)
+{
+ int length;
+ sample32_t *dmabuf;
+ u_int16_t *data;
+ int src, dst, ssize, dsize, slot;
+ int i;
+
+#if(0)
+ device_printf(ch->parent->dev, "envy24ht_p16sl()\n");
+#endif
+ length = sndbuf_getready(ch->buffer) / 4;
+ dmabuf = ch->parent->pbuf;
+ data = (u_int16_t *)ch->data;
+ src = sndbuf_getreadyptr(ch->buffer) / 2;
+ dst = src / 2 + ch->offset;
+ ssize = ch->size / 2;
+ dsize = ch->size / 4;
+ slot = ch->num * 2;
+#if(0)
+ device_printf(ch->parent->dev, "envy24ht_p16sl():%lu-->%lu(%lu)\n", src, dst, length);
+#endif
+
+ for (i = 0; i < length; i++) {
+ dmabuf[dst * ENVY24HT_PLAY_CHNUM + slot].buffer = (u_int32_t)data[src] << 16;
+ dmabuf[dst * ENVY24HT_PLAY_CHNUM + slot + 1].buffer = (u_int32_t)data[src + 1] << 16;
+#if(0)
+ if (i < 16) {
+ printf("%08x", dmabuf[dst * ENVY24HT_PLAY_CHNUM + slot]);
+ printf("%08x", dmabuf[dst * ENVY24HT_PLAY_CHNUM + slot + 1]);
+ }
+#endif
+ dst++;
+ dst %= dsize;
+ src += 2;
+ src %= ssize;
+ }
+#if(0)
+ printf("\n");
+#endif
+
+ return;
+}
+
+static void
+envy24ht_p8u(struct sc_chinfo *ch)
+{
+ int length;
+ sample32_t *dmabuf;
+ u_int8_t *data;
+ int src, dst, ssize, dsize, slot;
+ int i;
+
+ length = sndbuf_getready(ch->buffer) / 2;
+ dmabuf = ch->parent->pbuf;
+ data = (u_int8_t *)ch->data;
+ src = sndbuf_getreadyptr(ch->buffer);
+ dst = src / 2 + ch->offset;
+ ssize = ch->size;
+ dsize = ch->size / 4;
+ slot = ch->num * 2;
+
+ for (i = 0; i < length; i++) {
+ dmabuf[dst * ENVY24HT_PLAY_CHNUM + slot].buffer = ((u_int32_t)data[src] ^ 0x80) << 24;
+ dmabuf[dst * ENVY24HT_PLAY_CHNUM + slot + 1].buffer = ((u_int32_t)data[src + 1] ^ 0x80) << 24;
+ dst++;
+ dst %= dsize;
+ src += 2;
+ src %= ssize;
+ }
+
+ return;
+}
+
+static void
+envy24ht_r32sl(struct sc_chinfo *ch)
+{
+ int length;
+ sample32_t *dmabuf;
+ u_int32_t *data;
+ int src, dst, ssize, dsize, slot;
+ int i;
+
+ length = sndbuf_getfree(ch->buffer) / 8;
+ dmabuf = ch->parent->rbuf;
+ data = (u_int32_t *)ch->data;
+ dst = sndbuf_getfreeptr(ch->buffer) / 4;
+ src = dst / 2 + ch->offset;
+ dsize = ch->size / 4;
+ ssize = ch->size / 8;
+ slot = (ch->num - ENVY24HT_CHAN_REC_ADC1) * 2;
+
+ for (i = 0; i < length; i++) {
+ data[dst] = dmabuf[src * ENVY24HT_REC_CHNUM + slot].buffer;
+ data[dst + 1] = dmabuf[src * ENVY24HT_REC_CHNUM + slot + 1].buffer;
+ dst += 2;
+ dst %= dsize;
+ src++;
+ src %= ssize;
+ }
+
+ return;
+}
+
+static void
+envy24ht_r16sl(struct sc_chinfo *ch)
+{
+ int length;
+ sample32_t *dmabuf;
+ u_int16_t *data;
+ int src, dst, ssize, dsize, slot;
+ int i;
+
+ length = sndbuf_getfree(ch->buffer) / 4;
+ dmabuf = ch->parent->rbuf;
+ data = (u_int16_t *)ch->data;
+ dst = sndbuf_getfreeptr(ch->buffer) / 2;
+ src = dst / 2 + ch->offset;
+ dsize = ch->size / 2;
+ ssize = ch->size / 8;
+ slot = (ch->num - ENVY24HT_CHAN_REC_ADC1) * 2;
+
+ for (i = 0; i < length; i++) {
+ data[dst] = dmabuf[src * ENVY24HT_REC_CHNUM + slot].buffer;
+ data[dst + 1] = dmabuf[src * ENVY24HT_REC_CHNUM + slot + 1].buffer;
+ dst += 2;
+ dst %= dsize;
+ src++;
+ src %= ssize;
+ }
+
+ return;
+}
+
+/* -------------------------------------------------------------------- */
+
+/* channel interface */
+static void *
+envy24htchan_init(kobj_t obj, void *devinfo, struct snd_dbuf *b, struct pcm_channel *c, int dir)
+{
+ struct sc_info *sc = (struct sc_info *)devinfo;
+ struct sc_chinfo *ch;
+ unsigned num;
+
+#if(0)
+ device_printf(sc->dev, "envy24htchan_init(obj, devinfo, b, c, %d)\n", dir);
+#endif
+ snd_mtxlock(sc->lock);
+#if 0
+ if ((sc->chnum > ENVY24HT_CHAN_PLAY_SPDIF && dir != PCMDIR_REC) ||
+ (sc->chnum < ENVY24HT_CHAN_REC_ADC1 && dir != PCMDIR_PLAY)) {
+ snd_mtxunlock(sc->lock);
+ return NULL;
+ }
+#endif
+ num = sc->chnum;
+
+ ch = &sc->chan[num];
+ ch->size = 8 * ENVY24HT_SAMPLE_NUM;
+ ch->data = malloc(ch->size, M_ENVY24HT, M_NOWAIT);
+ if (ch->data == NULL) {
+ ch->size = 0;
+ ch = NULL;
+ }
+ else {
+ ch->buffer = b;
+ ch->channel = c;
+ ch->parent = sc;
+ ch->dir = dir;
+ /* set channel map */
+ ch->num = envy24ht_chanmap[num];
+ snd_mtxunlock(sc->lock);
+ sndbuf_setup(ch->buffer, ch->data, ch->size);
+ snd_mtxlock(sc->lock);
+ /* these 2 values are dummy */
+ ch->unit = 4;
+ ch->blk = 10240;
+ }
+ snd_mtxunlock(sc->lock);
+
+ return ch;
+}
+
+static int
+envy24htchan_free(kobj_t obj, void *data)
+{
+ struct sc_chinfo *ch = data;
+ struct sc_info *sc = ch->parent;
+
+#if(0)
+ device_printf(sc->dev, "envy24htchan_free()\n");
+#endif
+ snd_mtxlock(sc->lock);
+ if (ch->data != NULL) {
+ free(ch->data, M_ENVY24HT);
+ ch->data = NULL;
+ }
+ snd_mtxunlock(sc->lock);
+
+ return 0;
+}
+
+static int
+envy24htchan_setformat(kobj_t obj, void *data, u_int32_t format)
+{
+ struct sc_chinfo *ch = data;
+ struct sc_info *sc = ch->parent;
+ struct envy24ht_emldma *emltab;
+ /* unsigned int bcnt, bsize; */
+ int i;
+
+#if(0)
+ device_printf(sc->dev, "envy24htchan_setformat(obj, data, 0x%08x)\n", format);
+#endif
+ snd_mtxlock(sc->lock);
+ /* check and get format related information */
+ if (ch->dir == PCMDIR_PLAY)
+ emltab = envy24ht_pemltab;
+ else
+ emltab = envy24ht_remltab;
+ if (emltab == NULL) {
+ snd_mtxunlock(sc->lock);
+ return -1;
+ }
+ for (i = 0; emltab[i].format != 0; i++)
+ if (emltab[i].format == format)
+ break;
+ if (emltab[i].format == 0) {
+ snd_mtxunlock(sc->lock);
+ return -1;
+ }
+
+ /* set format information */
+ ch->format = format;
+ ch->emldma = emltab[i].emldma;
+ if (ch->unit > emltab[i].unit)
+ ch->blk *= ch->unit / emltab[i].unit;
+ else
+ ch->blk /= emltab[i].unit / ch->unit;
+ ch->unit = emltab[i].unit;
+
+ /* set channel buffer information */
+ ch->size = ch->unit * ENVY24HT_SAMPLE_NUM;
+#if 0
+ if (ch->dir == PCMDIR_PLAY)
+ bsize = ch->blk * 4 / ENVY24HT_PLAY_BUFUNIT;
+ else
+ bsize = ch->blk * 4 / ENVY24HT_REC_BUFUNIT;
+ bsize *= ch->unit;
+ bcnt = ch->size / bsize;
+ sndbuf_resize(ch->buffer, bcnt, bsize);
+#endif
+ snd_mtxunlock(sc->lock);
+
+#if(0)
+ device_printf(sc->dev, "envy24htchan_setformat(): return 0x%08x\n", 0);
+#endif
+ return 0;
+}
+
+/*
+ IMPLEMENT NOTICE: In this driver, setspeed function only do setting
+ of speed information value. And real hardware speed setting is done
+ at start triggered(see envy24htchan_trigger()). So, at this function
+ is called, any value that ENVY24 can use is able to set. But, at
+ start triggerd, some other channel is running, and that channel's
+ speed isn't same with, then trigger function will fail.
+*/
+static int
+envy24htchan_setspeed(kobj_t obj, void *data, u_int32_t speed)
+{
+ struct sc_chinfo *ch = data;
+ u_int32_t val, prev;
+ int i;
+
+#if(0)
+ device_printf(ch->parent->dev, "envy24htchan_setspeed(obj, data, %d)\n", speed);
+#endif
+ prev = 0x7fffffff;
+ for (i = 0; (val = envy24ht_speed[i]) != 0; i++) {
+ if (abs(val - speed) < abs(prev - speed))
+ prev = val;
+ else
+ break;
+ }
+ ch->speed = prev;
+
+#if(0)
+ device_printf(ch->parent->dev, "envy24htchan_setspeed(): return %d\n", ch->speed);
+#endif
+ return ch->speed;
+}
+
+static int
+envy24htchan_setblocksize(kobj_t obj, void *data, u_int32_t blocksize)
+{
+ struct sc_chinfo *ch = data;
+ /* struct sc_info *sc = ch->parent; */
+ u_int32_t size, prev;
+ unsigned int bcnt, bsize;
+
+#if(0)
+ device_printf(sc->dev, "envy24htchan_setblocksize(obj, data, %d)\n", blocksize);
+#endif
+ prev = 0x7fffffff;
+ /* snd_mtxlock(sc->lock); */
+ for (size = ch->size / 2; size > 0; size /= 2) {
+ if (abs(size - blocksize) < abs(prev - blocksize))
+ prev = size;
+ else
+ break;
+ }
+
+ ch->blk = prev / ch->unit;
+ if (ch->dir == PCMDIR_PLAY)
+ ch->blk *= ENVY24HT_PLAY_BUFUNIT / 4;
+ else
+ ch->blk *= ENVY24HT_REC_BUFUNIT / 4;
+ /* set channel buffer information */
+ /* ch->size = ch->unit * ENVY24HT_SAMPLE_NUM; */
+ if (ch->dir == PCMDIR_PLAY)
+ bsize = ch->blk * 4 / ENVY24HT_PLAY_BUFUNIT;
+ else
+ bsize = ch->blk * 4 / ENVY24HT_REC_BUFUNIT;
+ bsize *= ch->unit;
+ bcnt = ch->size / bsize;
+ sndbuf_resize(ch->buffer, bcnt, bsize);
+ /* snd_mtxunlock(sc->lock); */
+
+#if(0)
+ device_printf(sc->dev, "envy24htchan_setblocksize(): return %d\n", prev);
+#endif
+ return prev;
+}
+
+/* semantic note: must start at beginning of buffer */
+static int
+envy24htchan_trigger(kobj_t obj, void *data, int go)
+{
+ struct sc_chinfo *ch = data;
+ struct sc_info *sc = ch->parent;
+ u_int32_t ptr;
+ int slot;
+#if 0
+ int i;
+
+ device_printf(sc->dev, "envy24htchan_trigger(obj, data, %d)\n", go);
+#endif
+ snd_mtxlock(sc->lock);
+ if (ch->dir == PCMDIR_PLAY)
+ slot = 0;
+ else
+ slot = 1;
+ switch (go) {
+ case PCMTRIG_START:
+#if(0)
+ device_printf(sc->dev, "envy24htchan_trigger(): start\n");
+#endif
+ /* check or set channel speed */
+ if (sc->run[0] == 0 && sc->run[1] == 0) {
+ sc->speed = envy24ht_setspeed(sc, ch->speed);
+ sc->caps[0].minspeed = sc->caps[0].maxspeed = sc->speed;
+ sc->caps[1].minspeed = sc->caps[1].maxspeed = sc->speed;
+ }
+ else if (ch->speed != 0 && ch->speed != sc->speed)
+ return -1;
+ if (ch->speed == 0)
+ ch->channel->speed = sc->speed;
+ /* start or enable channel */
+ sc->run[slot]++;
+ if (sc->run[slot] == 1) {
+ /* first channel */
+ ch->offset = 0;
+ sc->blk[slot] = ch->blk;
+ }
+ else {
+ ptr = envy24ht_gethwptr(sc, ch->dir);
+ ch->offset = ((ptr / ch->blk + 1) * ch->blk %
+ (ch->size / 4)) * 4 / ch->unit;
+ if (ch->blk < sc->blk[slot])
+ sc->blk[slot] = ch->blk;
+ }
+ if (ch->dir == PCMDIR_PLAY) {
+ ch->emldma(ch);
+ envy24ht_setvolume(sc, ch->num);
+ }
+ envy24ht_updintr(sc, ch->dir);
+ if (sc->run[slot] == 1)
+ envy24ht_start(sc, ch->dir);
+ ch->run = 1;
+ break;
+ case PCMTRIG_EMLDMAWR:
+#if(0)
+ device_printf(sc->dev, "envy24htchan_trigger(): emldmawr\n");
+#endif
+ if (ch->run != 1)
+ return -1;
+ ch->emldma(ch);
+ break;
+ case PCMTRIG_EMLDMARD:
+#if(0)
+ device_printf(sc->dev, "envy24htchan_trigger(): emldmard\n");
+#endif
+ if (ch->run != 1)
+ return -1;
+ ch->emldma(ch);
+ break;
+ case PCMTRIG_ABORT:
+ if (ch->run) {
+#if(0)
+ device_printf(sc->dev, "envy24htchan_trigger(): abort\n");
+#endif
+ ch->run = 0;
+ sc->run[slot]--;
+ if (ch->dir == PCMDIR_PLAY)
+ envy24ht_mutevolume(sc, ch->num);
+ if (sc->run[slot] == 0) {
+ envy24ht_stop(sc, ch->dir);
+ sc->intr[slot] = 0;
+ }
+/* else if (ch->blk == sc->blk[slot]) {
+ sc->blk[slot] = ENVY24HT_SAMPLE_NUM / 2;
+ for (i = 0; i < ENVY24HT_CHAN_NUM; i++) {
+ if (sc->chan[i].dir == ch->dir &&
+ sc->chan[i].run == 1 &&
+ sc->chan[i].blk < sc->blk[slot])
+ sc->blk[slot] = sc->chan[i].blk;
+ }
+ if (ch->blk != sc->blk[slot])
+ envy24ht_updintr(sc, ch->dir);
+ }*/
+ }
+ break;
+ }
+ snd_mtxunlock(sc->lock);
+
+ return 0;
+}
+
+static int
+envy24htchan_getptr(kobj_t obj, void *data)
+{
+ struct sc_chinfo *ch = data;
+ struct sc_info *sc = ch->parent;
+ u_int32_t ptr;
+ int rtn;
+
+#if(0)
+ device_printf(sc->dev, "envy24htchan_getptr()\n");
+#endif
+ snd_mtxlock(sc->lock);
+ ptr = envy24ht_gethwptr(sc, ch->dir);
+ rtn = ptr * ch->unit;
+ snd_mtxunlock(sc->lock);
+
+#if(0)
+ device_printf(sc->dev, "envy24htchan_getptr(): return %d\n",
+ rtn);
+#endif
+ return rtn;
+}
+
+static struct pcmchan_caps *
+envy24htchan_getcaps(kobj_t obj, void *data)
+{
+ struct sc_chinfo *ch = data;
+ struct sc_info *sc = ch->parent;
+ struct pcmchan_caps *rtn;
+
+#if(0)
+ device_printf(sc->dev, "envy24htchan_getcaps()\n");
+#endif
+ snd_mtxlock(sc->lock);
+ if (ch->dir == PCMDIR_PLAY) {
+ if (sc->run[0] == 0)
+ rtn = &envy24ht_playcaps;
+ else
+ rtn = &sc->caps[0];
+ }
+ else {
+ if (sc->run[1] == 0)
+ rtn = &envy24ht_reccaps;
+ else
+ rtn = &sc->caps[1];
+ }
+ snd_mtxunlock(sc->lock);
+
+ return rtn;
+}
+
+static kobj_method_t envy24htchan_methods[] = {
+ KOBJMETHOD(channel_init, envy24htchan_init),
+ KOBJMETHOD(channel_free, envy24htchan_free),
+ KOBJMETHOD(channel_setformat, envy24htchan_setformat),
+ KOBJMETHOD(channel_setspeed, envy24htchan_setspeed),
+ KOBJMETHOD(channel_setblocksize, envy24htchan_setblocksize),
+ KOBJMETHOD(channel_trigger, envy24htchan_trigger),
+ KOBJMETHOD(channel_getptr, envy24htchan_getptr),
+ KOBJMETHOD(channel_getcaps, envy24htchan_getcaps),
+ { 0, 0 }
+};
+CHANNEL_DECLARE(envy24htchan);
+
+/* -------------------------------------------------------------------- */
+
+/* mixer interface */
+
+static int
+envy24htmixer_init(struct snd_mixer *m)
+{
+ struct sc_info *sc = mix_getdevinfo(m);
+
+#if(0)
+ device_printf(sc->dev, "envy24htmixer_init()\n");
+#endif
+ if (sc == NULL)
+ return -1;
+
+ /* set volume control rate */
+ snd_mtxlock(sc->lock);
+#if 0
+ envy24ht_wrmt(sc, ENVY24HT_MT_VOLRATE, 0x30, 1); /* 0x30 is default value */
+#endif
+
+ pcm_setflags(sc->dev, pcm_getflags(sc->dev) | SD_F_SOFTPCMVOL);
+
+ mix_setdevs(m, ENVY24HT_MIX_MASK);
+ mix_setrecdevs(m, ENVY24HT_MIX_REC_MASK);
+
+ snd_mtxunlock(sc->lock);
+
+ return 0;
+}
+
+static int
+envy24htmixer_reinit(struct snd_mixer *m)
+{
+ struct sc_info *sc = mix_getdevinfo(m);
+
+ if (sc == NULL)
+ return -1;
+#if(0)
+ device_printf(sc->dev, "envy24htmixer_reinit()\n");
+#endif
+
+ return 0;
+}
+
+static int
+envy24htmixer_uninit(struct snd_mixer *m)
+{
+ struct sc_info *sc = mix_getdevinfo(m);
+
+ if (sc == NULL)
+ return -1;
+#if(0)
+ device_printf(sc->dev, "envy24htmixer_uninit()\n");
+#endif
+
+ return 0;
+}
+
+static int
+envy24htmixer_set(struct snd_mixer *m, unsigned dev, unsigned left, unsigned right)
+{
+ struct sc_info *sc = mix_getdevinfo(m);
+ int ch = envy24ht_mixmap[dev];
+ int hwch;
+ int i;
+
+ if (sc == NULL)
+ return -1;
+ if (dev == 0 && sc->cfg->codec->setvolume == NULL)
+ return -1;
+ if (dev != 0 && ch == -1)
+ return -1;
+ hwch = envy24ht_chanmap[ch];
+#if(0)
+ device_printf(sc->dev, "envy24htmixer_set(m, %d, %d, %d)\n",
+ dev, left, right);
+#endif
+
+ snd_mtxlock(sc->lock);
+ if (dev == 0) {
+ for (i = 0; i < sc->dacn; i++) {
+ sc->cfg->codec->setvolume(sc->dac[i], PCMDIR_PLAY, left, right);
+ }
+ }
+ else {
+ /* set volume value for hardware */
+ if ((sc->left[hwch] = 100 - left) > ENVY24HT_VOL_MIN)
+ sc->left[hwch] = ENVY24HT_VOL_MUTE;
+ if ((sc->right[hwch] = 100 - right) > ENVY24HT_VOL_MIN)
+ sc->right[hwch] = ENVY24HT_VOL_MUTE;
+
+ /* set volume for record channel and running play channel */
+ if (hwch > ENVY24HT_CHAN_PLAY_SPDIF || sc->chan[ch].run)
+ envy24ht_setvolume(sc, hwch);
+ }
+ snd_mtxunlock(sc->lock);
+
+ return right << 8 | left;
+}
+
+static u_int32_t
+envy24htmixer_setrecsrc(struct snd_mixer *m, u_int32_t src)
+{
+ struct sc_info *sc = mix_getdevinfo(m);
+ int ch = envy24ht_mixmap[src];
+#if(0)
+ device_printf(sc->dev, "envy24htmixer_setrecsrc(m, %d)\n", src);
+#endif
+
+ if (ch > ENVY24HT_CHAN_PLAY_SPDIF)
+ sc->src = ch;
+ return src;
+}
+
+static kobj_method_t envy24htmixer_methods[] = {
+ KOBJMETHOD(mixer_init, envy24htmixer_init),
+ KOBJMETHOD(mixer_reinit, envy24htmixer_reinit),
+ KOBJMETHOD(mixer_uninit, envy24htmixer_uninit),
+ KOBJMETHOD(mixer_set, envy24htmixer_set),
+ KOBJMETHOD(mixer_setrecsrc, envy24htmixer_setrecsrc),
+ { 0, 0 }
+};
+MIXER_DECLARE(envy24htmixer);
+
+/* -------------------------------------------------------------------- */
+
+/* The interrupt handler */
+static void
+envy24ht_intr(void *p)
+{
+ struct sc_info *sc = (struct sc_info *)p;
+ struct sc_chinfo *ch;
+ u_int32_t ptr, dsize, feed;
+ int i;
+
+#if(0)
+ device_printf(sc->dev, "envy24ht_intr()\n");
+#endif
+ snd_mtxlock(sc->lock);
+ if (envy24ht_checkintr(sc, PCMDIR_PLAY)) {
+#if(0)
+ device_printf(sc->dev, "envy24ht_intr(): play\n");
+#endif
+ dsize = sc->psize / 4;
+ ptr = dsize - envy24ht_rdmt(sc, ENVY24HT_MT_PCNT, 2) - 1;
+#if(0)
+ device_printf(sc->dev, "envy24ht_intr(): ptr = %d-->", ptr);
+#endif
+ ptr -= ptr % sc->blk[0];
+ feed = (ptr + dsize - sc->intr[0]) % dsize;
+#if(0)
+ printf("%d intr = %d feed = %d\n", ptr, sc->intr[0], feed);
+#endif
+ for (i = ENVY24HT_CHAN_PLAY_DAC1; i <= ENVY24HT_CHAN_PLAY_SPDIF; i++) {
+ ch = &sc->chan[i];
+#if(0)
+ if (ch->run)
+ device_printf(sc->dev, "envy24ht_intr(): chan[%d].blk = %d\n", i, ch->blk);
+#endif
+ if (ch->run && ch->blk <= feed) {
+ snd_mtxunlock(sc->lock);
+ chn_intr(ch->channel);
+ snd_mtxlock(sc->lock);
+ }
+ }
+ sc->intr[0] = ptr;
+ envy24ht_updintr(sc, PCMDIR_PLAY);
+ }
+ if (envy24ht_checkintr(sc, PCMDIR_REC)) {
+#if(0)
+ device_printf(sc->dev, "envy24ht_intr(): rec\n");
+#endif
+ dsize = sc->rsize / 4;
+ ptr = dsize - envy24ht_rdmt(sc, ENVY24HT_MT_RCNT, 2) - 1;
+ ptr -= ptr % sc->blk[1];
+ feed = (ptr + dsize - sc->intr[1]) % dsize;
+ for (i = ENVY24HT_CHAN_REC_ADC1; i <= ENVY24HT_CHAN_REC_SPDIF; i++) {
+ ch = &sc->chan[i];
+ if (ch->run && ch->blk <= feed) {
+ snd_mtxunlock(sc->lock);
+ chn_intr(ch->channel);
+ snd_mtxlock(sc->lock);
+ }
+ }
+ sc->intr[1] = ptr;
+ envy24ht_updintr(sc, PCMDIR_REC);
+ }
+ snd_mtxunlock(sc->lock);
+
+ return;
+}
+
+/*
+ * Probe and attach the card
+ */
+
+static int
+envy24ht_pci_probe(device_t dev)
+{
+ u_int16_t sv, sd;
+ int i;
+
+#if(0)
+ printf("envy24ht_pci_probe()\n");
+#endif
+ if (pci_get_device(dev) == PCID_ENVY24HT &&
+ pci_get_vendor(dev) == PCIV_ENVY24) {
+ sv = pci_get_subvendor(dev);
+ sd = pci_get_subdevice(dev);
+ for (i = 0; cfg_table[i].subvendor != 0 || cfg_table[i].subdevice != 0; i++) {
+ if (cfg_table[i].subvendor == sv &&
+ cfg_table[i].subdevice == sd) {
+ break;
+ }
+ }
+ device_set_desc(dev, cfg_table[i].name);
+#if(0)
+ printf("envy24ht_pci_probe(): return 0\n");
+#endif
+ return 0;
+ }
+ else {
+#if(0)
+ printf("envy24ht_pci_probe(): return ENXIO\n");
+#endif
+ return ENXIO;
+ }
+}
+
+static void
+envy24ht_dmapsetmap(void *arg, bus_dma_segment_t *segs, int nseg, int error)
+{
+ /* struct sc_info *sc = (struct sc_info *)arg; */
+
+#if(0)
+ device_printf(sc->dev, "envy24ht_dmapsetmap()\n");
+ if (bootverbose) {
+ printf("envy24ht(play): setmap %lx, %lx; ",
+ (unsigned long)segs->ds_addr,
+ (unsigned long)segs->ds_len);
+ printf("%p -> %lx\n", sc->pmap, (unsigned long)vtophys(sc->pmap));
+ }
+#endif
+}
+
+static void
+envy24ht_dmarsetmap(void *arg, bus_dma_segment_t *segs, int nseg, int error)
+{
+ /* struct sc_info *sc = (struct sc_info *)arg; */
+
+#if(0)
+ device_printf(sc->dev, "envy24ht_dmarsetmap()\n");
+ if (bootverbose) {
+ printf("envy24ht(record): setmap %lx, %lx; ",
+ (unsigned long)segs->ds_addr,
+ (unsigned long)segs->ds_len);
+ printf("%p -> %lx\n", sc->rmap, (unsigned long)vtophys(sc->pmap));
+ }
+#endif
+}
+
+static void
+envy24ht_dmafree(struct sc_info *sc)
+{
+#if(0)
+ device_printf(sc->dev, "envy24ht_dmafree():");
+ if (sc->rmap) printf(" sc->rmap(0x%08x)", (u_int32_t)sc->rmap);
+ else printf(" sc->rmap(null)");
+ if (sc->pmap) printf(" sc->pmap(0x%08x)", (u_int32_t)sc->pmap);
+ else printf(" sc->pmap(null)");
+ if (sc->rbuf) printf(" sc->rbuf(0x%08x)", (u_int32_t)sc->rbuf);
+ else printf(" sc->rbuf(null)");
+ if (sc->pbuf) printf(" sc->pbuf(0x%08x)\n", (u_int32_t)sc->pbuf);
+ else printf(" sc->pbuf(null)\n");
+#endif
+#if(0)
+ if (sc->rmap)
+ bus_dmamap_unload(sc->dmat, sc->rmap);
+ if (sc->pmap)
+ bus_dmamap_unload(sc->dmat, sc->pmap);
+ if (sc->rbuf)
+ bus_dmamem_free(sc->dmat, sc->rbuf, sc->rmap);
+ if (sc->pbuf)
+ bus_dmamem_free(sc->dmat, sc->pbuf, sc->pmap);
+#else
+ bus_dmamap_unload(sc->dmat, sc->rmap);
+ bus_dmamap_unload(sc->dmat, sc->pmap);
+ bus_dmamem_free(sc->dmat, sc->rbuf, sc->rmap);
+ bus_dmamem_free(sc->dmat, sc->pbuf, sc->pmap);
+#endif
+
+ sc->rmap = sc->pmap = NULL;
+ sc->pbuf = NULL;
+ sc->rbuf = NULL;
+
+ return;
+}
+
+static int
+envy24ht_dmainit(struct sc_info *sc)
+{
+ u_int32_t addr;
+
+#if(0)
+ device_printf(sc->dev, "envy24ht_dmainit()\n");
+#endif
+ /* init values */
+ sc->psize = ENVY24HT_PLAY_BUFUNIT * ENVY24HT_SAMPLE_NUM;
+ sc->rsize = ENVY24HT_REC_BUFUNIT * ENVY24HT_SAMPLE_NUM;
+ sc->pbuf = NULL;
+ sc->rbuf = NULL;
+ sc->pmap = sc->rmap = NULL;
+ sc->blk[0] = sc->blk[1] = 0;
+
+ /* allocate DMA buffer */
+#if(0)
+ device_printf(sc->dev, "envy24ht_dmainit(): bus_dmamem_alloc(): sc->pbuf\n");
+#endif
+ if (bus_dmamem_alloc(sc->dmat, (void **)&sc->pbuf, BUS_DMA_NOWAIT, &sc->pmap))
+ goto bad;
+#if(0)
+ device_printf(sc->dev, "envy24ht_dmainit(): bus_dmamem_alloc(): sc->rbuf\n");
+#endif
+ if (bus_dmamem_alloc(sc->dmat, (void **)&sc->rbuf, BUS_DMA_NOWAIT, &sc->rmap))
+ goto bad;
+#if(0)
+ device_printf(sc->dev, "envy24ht_dmainit(): bus_dmamem_load(): sc->pmap\n");
+#endif
+ if (bus_dmamap_load(sc->dmat, sc->pmap, sc->pbuf, sc->psize, envy24ht_dmapsetmap, sc, 0))
+ goto bad;
+#if(0)
+ device_printf(sc->dev, "envy24ht_dmainit(): bus_dmamem_load(): sc->rmap\n");
+#endif
+ if (bus_dmamap_load(sc->dmat, sc->rmap, sc->rbuf, sc->rsize, envy24ht_dmarsetmap, sc, 0))
+ goto bad;
+ bzero(sc->pbuf, sc->psize);
+ bzero(sc->rbuf, sc->rsize);
+
+ /* set values to register */
+ addr = vtophys(sc->pbuf);
+#if(0)
+ device_printf(sc->dev, "pbuf(0x%08x)\n", addr);
+#endif
+ envy24ht_wrmt(sc, ENVY24HT_MT_PADDR, addr, 4);
+#if(0)
+ device_printf(sc->dev, "PADDR-->(0x%08x)\n", envy24ht_rdmt(sc, ENVY24HT_MT_PADDR, 4));
+ device_printf(sc->dev, "psize(%ld)\n", sc->psize / 4 - 1);
+#endif
+ envy24ht_wrmt(sc, ENVY24HT_MT_PCNT, sc->psize / 4 - 1, 2);
+#if(0)
+ device_printf(sc->dev, "PCNT-->(%ld)\n", envy24ht_rdmt(sc, ENVY24HT_MT_PCNT, 2));
+#endif
+ addr = vtophys(sc->rbuf);
+ envy24ht_wrmt(sc, ENVY24HT_MT_RADDR, addr, 4);
+ envy24ht_wrmt(sc, ENVY24HT_MT_RCNT, sc->rsize / 4 - 1, 2);
+
+ return 0;
+ bad:
+ envy24ht_dmafree(sc);
+ return ENOSPC;
+}
+
+static void
+envy24ht_putcfg(struct sc_info *sc)
+{
+ device_printf(sc->dev, "system configuration\n");
+ printf(" SubVendorID: 0x%04x, SubDeviceID: 0x%04x\n",
+ sc->cfg->subvendor, sc->cfg->subdevice);
+ printf(" XIN2 Clock Source: ");
+ switch (sc->cfg->scfg & ENVY24HT_CCSM_SCFG_XIN2) {
+ case 0x00:
+ printf("24.576MHz(96kHz*256)\n");
+ break;
+ case 0x40:
+ printf("49.152MHz(192kHz*256)\n");
+ break;
+ case 0x80:
+ printf("reserved\n");
+ break;
+ default:
+ printf("illeagal system setting\n");
+ }
+ printf(" MPU-401 UART(s) #: ");
+ if (sc->cfg->scfg & ENVY24HT_CCSM_SCFG_MPU)
+ printf("1\n");
+ else
+ printf("not implemented\n");
+ switch (sc->adcn) {
+ case 0x01 || 0x02:
+ printf(" ADC #: ");
+ printf("%d\n", sc->adcn);
+ break;
+ case 0x03:
+ printf(" ADC #: ");
+ printf("%d", 1);
+ printf(" and SPDIF receiver connected\n");
+ break;
+ default:
+ printf(" no physical inputs\n");
+ }
+ printf(" DAC #: ");
+ printf("%d\n", sc->dacn);
+ printf(" Multi-track converter type: ");
+ if ((sc->cfg->acl & ENVY24HT_CCSM_ACL_MTC) == 0) {
+ printf("AC'97(SDATA_OUT:");
+ if (sc->cfg->acl & ENVY24HT_CCSM_ACL_OMODE)
+ printf("packed");
+ else
+ printf("split");
+ printf(")\n");
+ }
+ else {
+ printf("I2S(");
+ if (sc->cfg->i2s & ENVY24HT_CCSM_I2S_VOL)
+ printf("with volume, ");
+ if (sc->cfg->i2s & ENVY24HT_CCSM_I2S_192KHZ)
+ printf("192KHz support, ");
+ else
+ if (sc->cfg->i2s & ENVY24HT_CCSM_I2S_96KHZ)
+ printf("192KHz support, ");
+ else
+ printf("48KHz support, ");
+ switch (sc->cfg->i2s & ENVY24HT_CCSM_I2S_RES) {
+ case ENVY24HT_CCSM_I2S_16BIT:
+ printf("16bit resolution, ");
+ break;
+ case ENVY24HT_CCSM_I2S_18BIT:
+ printf("18bit resolution, ");
+ break;
+ case ENVY24HT_CCSM_I2S_20BIT:
+ printf("20bit resolution, ");
+ break;
+ case ENVY24HT_CCSM_I2S_24BIT:
+ printf("24bit resolution, ");
+ break;
+ }
+ printf("ID#0x%x)\n", sc->cfg->i2s & ENVY24HT_CCSM_I2S_ID);
+ }
+ printf(" S/PDIF(IN/OUT): ");
+ if (sc->cfg->spdif & ENVY24HT_CCSM_SPDIF_IN)
+ printf("1/");
+ else
+ printf("0/");
+ if (sc->cfg->spdif & ENVY24HT_CCSM_SPDIF_OUT)
+ printf("1 ");
+ else
+ printf("0 ");
+ if (sc->cfg->spdif & (ENVY24HT_CCSM_SPDIF_IN | ENVY24HT_CCSM_SPDIF_OUT))
+ printf("ID# 0x%02x\n", (sc->cfg->spdif & ENVY24HT_CCSM_SPDIF_ID) >> 2);
+ printf(" GPIO(mask/dir/state): 0x%02x/0x%02x/0x%02x\n",
+ sc->cfg->gpiomask, sc->cfg->gpiodir, sc->cfg->gpiostate);
+}
+
+static int
+envy24ht_init(struct sc_info *sc)
+{
+ u_int32_t data;
+#if(0)
+ int rtn;
+#endif
+ int i;
+ u_int32_t sv, sd;
+
+
+#if(0)
+ device_printf(sc->dev, "envy24ht_init()\n");
+#endif
+
+ /* reset chip */
+#if 0
+ envy24ht_wrcs(sc, ENVY24HT_CCS_CTL, ENVY24HT_CCS_CTL_RESET, 1);
+ DELAY(200);
+ envy24ht_wrcs(sc, ENVY24HT_CCS_CTL, ENVY24HT_CCS_CTL_NATIVE, 1);
+ DELAY(200);
+
+ /* legacy hardware disable */
+ data = pci_read_config(sc->dev, PCIR_LAC, 2);
+ data |= PCIM_LAC_DISABLE;
+ pci_write_config(sc->dev, PCIR_LAC, data, 2);
+#endif
+
+ /* check system configuration */
+ sc->cfg = NULL;
+ for (i = 0; cfg_table[i].subvendor != 0 || cfg_table[i].subdevice != 0; i++) {
+ /* 1st: search configuration from table */
+ sv = pci_get_subvendor(sc->dev);
+ sd = pci_get_subdevice(sc->dev);
+ if (sv == cfg_table[i].subvendor && sd == cfg_table[i].subdevice) {
+#if(0)
+ device_printf(sc->dev, "Set configuration from table\n");
+#endif
+ sc->cfg = &cfg_table[i];
+ break;
+ }
+ }
+ if (sc->cfg == NULL) {
+ /* 2nd: read configuration from table */
+ sc->cfg = envy24ht_rom2cfg(sc);
+ }
+ sc->adcn = ((sc->cfg->scfg & ENVY24HT_CCSM_SCFG_ADC) >> 2) + 1; /* need to be fixed */
+ sc->dacn = (sc->cfg->scfg & ENVY24HT_CCSM_SCFG_DAC) + 1;
+
+ if (1 /* bootverbose */) {
+ envy24ht_putcfg(sc);
+ }
+
+ /* set system configuration */
+ envy24ht_wrcs(sc, ENVY24HT_CCS_SCFG, sc->cfg->scfg, 1);
+ envy24ht_wrcs(sc, ENVY24HT_CCS_ACL, sc->cfg->acl, 1);
+ envy24ht_wrcs(sc, ENVY24HT_CCS_I2S, sc->cfg->i2s, 1);
+ envy24ht_wrcs(sc, ENVY24HT_CCS_SPDIF, sc->cfg->spdif, 1);
+ envy24ht_gpiosetmask(sc, sc->cfg->gpiomask);
+ envy24ht_gpiosetdir(sc, sc->cfg->gpiodir);
+ envy24ht_gpiowr(sc, sc->cfg->gpiostate);
+
+ if ((sc->cfg->subvendor == 0x3031) && (sc->cfg->subdevice == 0x4553)) {
+ envy24ht_wri2c(sc, 0x22, 0x00, 0x07);
+ envy24ht_wri2c(sc, 0x22, 0x04, 0x5f | 0x80);
+ envy24ht_wri2c(sc, 0x22, 0x05, 0x5f | 0x80);
+ }
+
+ for (i = 0; i < sc->adcn; i++) {
+ sc->adc[i] = sc->cfg->codec->create(sc->dev, sc, PCMDIR_REC, i);
+ sc->cfg->codec->init(sc->adc[i]);
+ }
+ for (i = 0; i < sc->dacn; i++) {
+ sc->dac[i] = sc->cfg->codec->create(sc->dev, sc, PCMDIR_PLAY, i);
+ sc->cfg->codec->init(sc->dac[i]);
+ }
+
+ /* initialize DMA buffer */
+#if(0)
+ device_printf(sc->dev, "envy24ht_init(): initialize DMA buffer\n");
+#endif
+ if (envy24ht_dmainit(sc))
+ return ENOSPC;
+
+ /* initialize status */
+ sc->run[0] = sc->run[1] = 0;
+ sc->intr[0] = sc->intr[1] = 0;
+ sc->speed = 0;
+ sc->caps[0].fmtlist = envy24ht_playfmt;
+ sc->caps[1].fmtlist = envy24ht_recfmt;
+
+ /* set channel router */
+#if 0
+ envy24ht_route(sc, ENVY24HT_ROUTE_DAC_1, ENVY24HT_ROUTE_CLASS_MIX, 0, 0);
+ envy24ht_route(sc, ENVY24HT_ROUTE_DAC_SPDIF, ENVY24HT_ROUTE_CLASS_DMA, 0, 0);
+ envy24ht_route(sc, ENVY24HT_ROUTE_DAC_SPDIF, ENVY24HT_ROUTE_CLASS_MIX, 0, 0);
+#endif
+
+ /* set macro interrupt mask */
+ data = envy24ht_rdcs(sc, ENVY24HT_CCS_IMASK, 1);
+ envy24ht_wrcs(sc, ENVY24HT_CCS_IMASK, data & ~ENVY24HT_CCS_IMASK_PMT, 1);
+ data = envy24ht_rdcs(sc, ENVY24HT_CCS_IMASK, 1);
+#if(0)
+ device_printf(sc->dev, "envy24ht_init(): CCS_IMASK-->0x%02x\n", data);
+#endif
+
+ return 0;
+}
+
+static int
+envy24ht_alloc_resource(struct sc_info *sc)
+{
+ /* allocate I/O port resource */
+ sc->csid = PCIR_CCS;
+ sc->cs = bus_alloc_resource(sc->dev, SYS_RES_IOPORT,
+ &sc->csid, 0, ~0, 1, RF_ACTIVE);
+ sc->mtid = ENVY24HT_PCIR_MT;
+ sc->mt = bus_alloc_resource(sc->dev, SYS_RES_IOPORT,
+ &sc->mtid, 0, ~0, 1, RF_ACTIVE);
+ if (!sc->cs || !sc->mt) {
+ device_printf(sc->dev, "unable to map IO port space\n");
+ return ENXIO;
+ }
+ sc->cst = rman_get_bustag(sc->cs);
+ sc->csh = rman_get_bushandle(sc->cs);
+ sc->mtt = rman_get_bustag(sc->mt);
+ sc->mth = rman_get_bushandle(sc->mt);
+#if(0)
+ device_printf(sc->dev,
+ "IO port register values\nCCS: 0x%lx\nMT: 0x%lx\n",
+ pci_read_config(sc->dev, PCIR_CCS, 4),
+ pci_read_config(sc->dev, PCIR_MT, 4));
+#endif
+
+ /* allocate interupt resource */
+ sc->irqid = 0;
+ sc->irq = bus_alloc_resource(sc->dev, SYS_RES_IRQ, &sc->irqid,
+ 0, ~0, 1, RF_ACTIVE | RF_SHAREABLE);
+ if (!sc->irq ||
+ snd_setup_intr(sc->dev, sc->irq, 0, envy24ht_intr, sc, &sc->ih)) {
+ device_printf(sc->dev, "unable to map interrupt\n");
+ return ENXIO;
+ }
+
+ /* allocate DMA resource */
+ if (bus_dma_tag_create(/*parent*/bus_get_dma_tag(sc->dev),
+ /*alignment*/4,
+ /*boundary*/0,
+ /*lowaddr*/BUS_SPACE_MAXADDR_ENVY24,
+ /*highaddr*/BUS_SPACE_MAXADDR_ENVY24,
+ /*filter*/NULL, /*filterarg*/NULL,
+ /*maxsize*/BUS_SPACE_MAXSIZE_ENVY24,
+ /*nsegments*/1, /*maxsegsz*/0x3ffff,
+ /*flags*/0, /*lockfunc*/busdma_lock_mutex,
+ /*lockarg*/&Giant, &sc->dmat) != 0) {
+ device_printf(sc->dev, "unable to create dma tag\n");
+ return ENXIO;
+ }
+
+ return 0;
+}
+
+static int
+envy24ht_pci_attach(device_t dev)
+{
+ u_int32_t data;
+ struct sc_info *sc;
+ char status[SND_STATUSLEN];
+ int err = 0;
+ int i;
+
+#if(0)
+ device_printf(dev, "envy24ht_pci_attach()\n");
+#endif
+ /* get sc_info data area */
+ if ((sc = malloc(sizeof(*sc), M_ENVY24HT, M_NOWAIT)) == NULL) {
+ device_printf(dev, "cannot allocate softc\n");
+ return ENXIO;
+ }
+
+ bzero(sc, sizeof(*sc));
+ sc->lock = snd_mtxcreate(device_get_nameunit(dev),
+ "snd_envy24ht softc");
+ sc->dev = dev;
+
+ /* initialize PCI interface */
+ data = pci_read_config(dev, PCIR_COMMAND, 2);
+ data |= (PCIM_CMD_PORTEN | PCIM_CMD_BUSMASTEREN);
+ pci_write_config(dev, PCIR_COMMAND, data, 2);
+ data = pci_read_config(dev, PCIR_COMMAND, 2);
+
+ /* allocate resources */
+ err = envy24ht_alloc_resource(sc);
+ if (err) {
+ device_printf(dev, "unable to allocate system resources\n");
+ goto bad;
+ }
+
+ /* initialize card */
+ err = envy24ht_init(sc);
+ if (err) {
+ device_printf(dev, "unable to initialize the card\n");
+ goto bad;
+ }
+
+ /* set multi track mixer */
+ mixer_init(dev, &envy24htmixer_class, sc);
+
+ /* set channel information */
+ /* err = pcm_register(dev, sc, 5, 2 + sc->adcn); */
+ err = pcm_register(dev, sc, 1, 2 + sc->adcn);
+ if (err)
+ goto bad;
+ sc->chnum = 0;
+ /* for (i = 0; i < 5; i++) { */
+ pcm_addchan(dev, PCMDIR_PLAY, &envy24htchan_class, sc);
+ sc->chnum++;
+ /* } */
+ for (i = 0; i < 2 + sc->adcn; i++) {
+ pcm_addchan(dev, PCMDIR_REC, &envy24htchan_class, sc);
+ sc->chnum++;
+ }
+
+ /* set status iformation */
+ snprintf(status, SND_STATUSLEN,
+ "at io 0x%lx:%ld,0x%lx:%ld irq %ld",
+ rman_get_start(sc->cs),
+ rman_get_end(sc->cs) - rman_get_start(sc->cs) + 1,
+ rman_get_start(sc->mt),
+ rman_get_end(sc->mt) - rman_get_start(sc->mt) + 1,
+ rman_get_start(sc->irq));
+ pcm_setstatus(dev, status);
+
+ return 0;
+
+bad:
+ if (sc->ih)
+ bus_teardown_intr(dev, sc->irq, sc->ih);
+ if (sc->irq)
+ bus_release_resource(dev, SYS_RES_IRQ, sc->irqid, sc->irq);
+ envy24ht_dmafree(sc);
+ if (sc->dmat)
+ bus_dma_tag_destroy(sc->dmat);
+ if (sc->cfg->codec->destroy != NULL) {
+ for (i = 0; i < sc->adcn; i++)
+ sc->cfg->codec->destroy(sc->adc[i]);
+ for (i = 0; i < sc->dacn; i++)
+ sc->cfg->codec->destroy(sc->dac[i]);
+ }
+ envy24ht_cfgfree(sc->cfg);
+ if (sc->cs)
+ bus_release_resource(dev, SYS_RES_IOPORT, sc->csid, sc->cs);
+ if (sc->mt)
+ bus_release_resource(dev, SYS_RES_IOPORT, sc->mtid, sc->mt);
+ if (sc->lock)
+ snd_mtxfree(sc->lock);
+ free(sc, M_ENVY24HT);
+ return err;
+}
+
+static int
+envy24ht_pci_detach(device_t dev)
+{
+ struct sc_info *sc;
+ int r;
+ int i;
+
+#if(0)
+ device_printf(dev, "envy24ht_pci_detach()\n");
+#endif
+ sc = pcm_getdevinfo(dev);
+ if (sc == NULL)
+ return 0;
+ r = pcm_unregister(dev);
+ if (r)
+ return r;
+
+ envy24ht_dmafree(sc);
+ if (sc->cfg->codec->destroy != NULL) {
+ for (i = 0; i < sc->adcn; i++)
+ sc->cfg->codec->destroy(sc->adc[i]);
+ for (i = 0; i < sc->dacn; i++)
+ sc->cfg->codec->destroy(sc->dac[i]);
+ }
+ envy24ht_cfgfree(sc->cfg);
+ bus_dma_tag_destroy(sc->dmat);
+ bus_teardown_intr(dev, sc->irq, sc->ih);
+ bus_release_resource(dev, SYS_RES_IRQ, sc->irqid, sc->irq);
+ bus_release_resource(dev, SYS_RES_IOPORT, sc->csid, sc->cs);
+ bus_release_resource(dev, SYS_RES_IOPORT, sc->mtid, sc->mt);
+ snd_mtxfree(sc->lock);
+ free(sc, M_ENVY24HT);
+ return 0;
+}
+
+static device_method_t envy24ht_methods[] = {
+ /* Device interface */
+ DEVMETHOD(device_probe, envy24ht_pci_probe),
+ DEVMETHOD(device_attach, envy24ht_pci_attach),
+ DEVMETHOD(device_detach, envy24ht_pci_detach),
+ { 0, 0 }
+};
+
+static driver_t envy24ht_driver = {
+ "pcm",
+ envy24ht_methods,
+#if __FreeBSD_version > 500000
+ PCM_SOFTC_SIZE,
+#else
+ sizeof(struct snddev_info),
+#endif
+};
+
+DRIVER_MODULE(snd_envy24ht, pci, envy24ht_driver, pcm_devclass, 0, 0);
+MODULE_DEPEND(snd_envy24ht, sound, SOUND_MINVER, SOUND_PREFVER, SOUND_MAXVER);
+MODULE_DEPEND(snd_envy24ht, snd_spicds, 1, 1, 1);
+MODULE_VERSION(snd_envy24ht, 1);
Index: ds1-fw.h
===================================================================
RCS file: /home/cvs/src/sys/dev/sound/pci/ds1-fw.h,v
retrieving revision 1.2
retrieving revision 1.3
diff -L sys/dev/sound/pci/ds1-fw.h -L sys/dev/sound/pci/ds1-fw.h -u -r1.2 -r1.3
--- sys/dev/sound/pci/ds1-fw.h
+++ sys/dev/sound/pci/ds1-fw.h
@@ -1,1602 +1,1601 @@
/*-
-* =============================================================================
-* Copyright (c) 1997-1999 Yamaha Corporation. All Rights Reserved.
-*
-* Title:
-* hwmcode.c
-* Desc:
-* micro-code for CTRL & DSP
-* =============================================================================
-*
-* Redistribution and use in source and binary forms, with or without
-* modification, are permitted provided that the following conditions
-* are met:
-* 1. Redistributions of source code must retain the above copyright
-* notice, this list of conditions and the following disclaimer.
-* 2. Redistributions in binary form must reproduce the above copyright
-* notice, this list of conditions and the following disclaimer in the
-* documentation and/or other materials provided with the distribution.
-* 3. This file may not be used in a commercial product not based on FreeBSD.
-*
-* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
-* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
-* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
-* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
-* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHERIN CONTRACT, STRICT
-* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
-* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
-* SUCH DAMAGE.
-*
-* $MidnightBSD$
-* $FreeBSD: src/sys/dev/sound/pci/ds1-fw.h,v 1.4 2005/01/06 01:43:19 imp Exp $
-*/
+ * =============================================================================
+ * Copyright (c) 1997-1999 Yamaha Corporation. All Rights Reserved.
+ *
+ * Title:
+ * hwmcode.c
+ * Desc:
+ * micro-code for CTRL & DSP
+ * =============================================================================
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. This file may not be used in a commercial product not based on FreeBSD.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHERIN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD: src/sys/dev/sound/pci/ds1-fw.h,v 1.4 2005/01/06 01:43:19 imp Exp $
+ */
#ifndef _HWMCODE_
#define _HWMCODE_
static u_int32_t DspInst[] = {
-0x00000081, 0x000001a4, 0x0000000a, 0x0000002f,
-0x00080253, 0x01800317, 0x0000407b, 0x0000843f,
-0x0001483c, 0x0001943c, 0x0005d83c, 0x00001c3c,
-0x0000c07b, 0x00050c3f, 0x0121503c, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000
+ 0x00000081, 0x000001a4, 0x0000000a, 0x0000002f,
+ 0x00080253, 0x01800317, 0x0000407b, 0x0000843f,
+ 0x0001483c, 0x0001943c, 0x0005d83c, 0x00001c3c,
+ 0x0000c07b, 0x00050c3f, 0x0121503c, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000
};
static u_int32_t CntrlInst[] = {
-0x000007, 0x240007, 0x0C0007, 0x1C0007,
-0x060007, 0x700002, 0x000020, 0x030040,
-0x007104, 0x004286, 0x030040, 0x000F0D,
-0x000810, 0x20043A, 0x000282, 0x00020D,
-0x000810, 0x20043A, 0x001282, 0x200E82,
-0x001A82, 0x032D0D, 0x000810, 0x10043A,
-0x02D38D, 0x000810, 0x18043A, 0x00010D,
-0x020015, 0x0000FD, 0x000020, 0x038860,
-0x039060, 0x038060, 0x038040, 0x038040,
-0x038040, 0x018040, 0x000A7D, 0x038040,
-0x038040, 0x018040, 0x200402, 0x000882,
-0x08001A, 0x000904, 0x015986, 0x000007,
-0x260007, 0x000007, 0x000007, 0x018A06,
-0x000007, 0x030C8D, 0x000810, 0x18043A,
-0x260007, 0x00087D, 0x018042, 0x00160A,
-0x04A206, 0x000007, 0x00218D, 0x000810,
-0x08043A, 0x21C206, 0x000007, 0x0007FD,
-0x018042, 0x08000A, 0x000904, 0x029386,
-0x000195, 0x090D04, 0x000007, 0x000820,
-0x0000F5, 0x000B7D, 0x01F060, 0x0000FD,
-0x032206, 0x018040, 0x000A7D, 0x038042,
-0x13804A, 0x18000A, 0x001820, 0x059060,
-0x058860, 0x018040, 0x0000FD, 0x018042,
-0x70000A, 0x000115, 0x071144, 0x032386,
-0x030000, 0x007020, 0x034A06, 0x018040,
-0x00348D, 0x000810, 0x08043A, 0x21EA06,
-0x000007, 0x02D38D, 0x000810, 0x18043A,
-0x018206, 0x000007, 0x240007, 0x000F8D,
-0x000810, 0x00163A, 0x002402, 0x005C02,
-0x0028FD, 0x000020, 0x018040, 0x08000D,
-0x000815, 0x510984, 0x000007, 0x00004D,
-0x000E5D, 0x000E02, 0x00418D, 0x000810,
-0x08043A, 0x2C8A06, 0x000007, 0x00008D,
-0x000924, 0x000F02, 0x00458D, 0x000810,
-0x08043A, 0x2C8A06, 0x000007, 0x00387D,
-0x018042, 0x08000A, 0x001015, 0x010984,
-0x018386, 0x000007, 0x01AA06, 0x000007,
-0x0008FD, 0x018042, 0x18000A, 0x001904,
-0x218086, 0x280007, 0x001810, 0x28043A,
-0x280C02, 0x00000D, 0x000810, 0x28143A,
-0x08808D, 0x000820, 0x0002FD, 0x018040,
-0x200007, 0x00020D, 0x189904, 0x000007,
-0x00402D, 0x0000BD, 0x0002FD, 0x018042,
-0x08000A, 0x000904, 0x055A86, 0x000007,
-0x000100, 0x000A20, 0x00047D, 0x018040,
-0x018042, 0x20000A, 0x003015, 0x012144,
-0x034986, 0x000007, 0x002104, 0x034986,
-0x000007, 0x000F8D, 0x000810, 0x280C3A,
-0x023944, 0x06C986, 0x000007, 0x001810,
-0x28043A, 0x08810D, 0x000820, 0x0002FD,
-0x018040, 0x200007, 0x002810, 0x78003A,
-0x00688D, 0x000810, 0x08043A, 0x288A06,
-0x000007, 0x00400D, 0x001015, 0x189904,
-0x292904, 0x393904, 0x000007, 0x060206,
-0x000007, 0x0004F5, 0x00007D, 0x000020,
-0x00008D, 0x010860, 0x018040, 0x00047D,
-0x038042, 0x21804A, 0x18000A, 0x021944,
-0x215886, 0x000007, 0x004075, 0x71F104,
-0x000007, 0x010042, 0x28000A, 0x002904,
-0x212086, 0x000007, 0x003C0D, 0x30A904,
-0x000007, 0x00077D, 0x018042, 0x08000A,
-0x000904, 0x07DA86, 0x00057D, 0x002820,
-0x03B060, 0x07F206, 0x018040, 0x003020,
-0x03A860, 0x018040, 0x0002FD, 0x018042,
-0x08000A, 0x000904, 0x07FA86, 0x000007,
-0x00057D, 0x018042, 0x28040A, 0x000E8D,
-0x000810, 0x280C3A, 0x00000D, 0x000810,
-0x28143A, 0x09000D, 0x000820, 0x0002FD,
-0x018040, 0x200007, 0x003DFD, 0x000020,
-0x018040, 0x00107D, 0x008D8D, 0x000810,
-0x08043A, 0x288A06, 0x000007, 0x000815,
-0x08001A, 0x010984, 0x095186, 0x00137D,
-0x200500, 0x280F20, 0x338F60, 0x3B8F60,
-0x438F60, 0x4B8F60, 0x538F60, 0x5B8F60,
-0x038A60, 0x018040, 0x007FBD, 0x383DC4,
-0x000007, 0x001A7D, 0x001375, 0x018042,
-0x09004A, 0x10000A, 0x0B8D04, 0x139504,
-0x000007, 0x000820, 0x019060, 0x001104,
-0x212086, 0x010040, 0x0017FD, 0x018042,
-0x08000A, 0x000904, 0x212286, 0x000007,
-0x00197D, 0x038042, 0x09804A, 0x10000A,
-0x000924, 0x001664, 0x0011FD, 0x038042,
-0x2B804A, 0x19804A, 0x00008D, 0x218944,
-0x000007, 0x002244, 0x0AE186, 0x000007,
-0x001A64, 0x002A24, 0x00197D, 0x080102,
-0x100122, 0x000820, 0x039060, 0x018040,
-0x003DFD, 0x00008D, 0x000820, 0x018040,
-0x001375, 0x001A7D, 0x010042, 0x09804A,
-0x10000A, 0x00021D, 0x0189E4, 0x2992E4,
-0x309144, 0x000007, 0x00060D, 0x000A15,
-0x000C1D, 0x001025, 0x00A9E4, 0x012BE4,
-0x000464, 0x01B3E4, 0x0232E4, 0x000464,
-0x000464, 0x000464, 0x000464, 0x00040D,
-0x08B1C4, 0x000007, 0x000820, 0x000BF5,
-0x030040, 0x00197D, 0x038042, 0x09804A,
-0x000A24, 0x08000A, 0x080E64, 0x000007,
-0x100122, 0x000820, 0x031060, 0x010040,
-0x0064AC, 0x00027D, 0x000020, 0x018040,
-0x00107D, 0x018042, 0x0011FD, 0x3B804A,
-0x09804A, 0x20000A, 0x000095, 0x1A1144,
-0x00A144, 0x0D2086, 0x00040D, 0x00B984,
-0x0D2186, 0x0018FD, 0x018042, 0x0010FD,
-0x09804A, 0x28000A, 0x000095, 0x010924,
-0x002A64, 0x0D1186, 0x000007, 0x002904,
-0x0D2286, 0x000007, 0x0D2A06, 0x080002,
-0x00008D, 0x00387D, 0x000820, 0x018040,
-0x00127D, 0x018042, 0x10000A, 0x003904,
-0x0DD186, 0x00080D, 0x7FFFB5, 0x00B984,
-0x0DA186, 0x000025, 0x0E7A06, 0x00002D,
-0x000015, 0x00082D, 0x02C78D, 0x000820,
-0x0EC206, 0x00000D, 0x7F8035, 0x00B984,
-0x0E7186, 0x400025, 0x00008D, 0x110944,
-0x000007, 0x00018D, 0x109504, 0x000007,
-0x009164, 0x000424, 0x000424, 0x000424,
-0x100102, 0x280002, 0x02C68D, 0x000820,
-0x0EC206, 0x00018D, 0x00042D, 0x00008D,
-0x109504, 0x000007, 0x00020D, 0x109184,
-0x000007, 0x02C70D, 0x000820, 0x00008D,
-0x0038FD, 0x018040, 0x003BFD, 0x001020,
-0x03A860, 0x000815, 0x313184, 0x212184,
-0x000007, 0x03B060, 0x03A060, 0x018040,
-0x0022FD, 0x000095, 0x010924, 0x000424,
-0x000424, 0x001264, 0x100102, 0x000820,
-0x039060, 0x018040, 0x001924, 0x00FB8D,
-0x00397D, 0x000820, 0x058040, 0x038042,
-0x09844A, 0x000606, 0x08040A, 0x000424,
-0x000424, 0x00117D, 0x018042, 0x08000A,
-0x000A24, 0x280502, 0x280C02, 0x09800D,
-0x000820, 0x0002FD, 0x018040, 0x200007,
-0x0022FD, 0x018042, 0x08000A, 0x000095,
-0x280DC4, 0x011924, 0x00197D, 0x018042,
-0x0011FD, 0x09804A, 0x10000A, 0x0000B5,
-0x113144, 0x0A8D04, 0x000007, 0x080A44,
-0x129504, 0x000007, 0x0023FD, 0x001020,
-0x038040, 0x101244, 0x000007, 0x000820,
-0x039060, 0x018040, 0x0002FD, 0x018042,
-0x08000A, 0x000904, 0x10FA86, 0x000007,
-0x003BFD, 0x000100, 0x000A10, 0x0B807A,
-0x13804A, 0x090984, 0x000007, 0x000095,
-0x013D04, 0x118086, 0x10000A, 0x100002,
-0x090984, 0x000007, 0x038042, 0x11804A,
-0x090D04, 0x000007, 0x10000A, 0x090D84,
-0x000007, 0x00257D, 0x000820, 0x018040,
-0x00010D, 0x000810, 0x28143A, 0x00127D,
-0x018042, 0x20000A, 0x00197D, 0x018042,
-0x00117D, 0x31804A, 0x10000A, 0x003124,
-0x01280D, 0x00397D, 0x000820, 0x058040,
-0x038042, 0x09844A, 0x000606, 0x08040A,
-0x300102, 0x003124, 0x000424, 0x000424,
-0x001224, 0x280502, 0x001A4C, 0x130186,
-0x700002, 0x00002D, 0x030000, 0x00387D,
-0x018042, 0x10000A, 0x132A06, 0x002124,
-0x0000AD, 0x100002, 0x00010D, 0x000924,
-0x006B24, 0x01368D, 0x00397D, 0x000820,
-0x058040, 0x038042, 0x09844A, 0x000606,
-0x08040A, 0x003264, 0x00008D, 0x000A24,
-0x001020, 0x00227D, 0x018040, 0x013C0D,
-0x000810, 0x08043A, 0x29D206, 0x000007,
-0x002820, 0x00207D, 0x018040, 0x00117D,
-0x038042, 0x13804A, 0x33800A, 0x00387D,
-0x018042, 0x08000A, 0x000904, 0x163A86,
-0x000007, 0x00008D, 0x030964, 0x01478D,
-0x00397D, 0x000820, 0x058040, 0x038042,
-0x09844A, 0x000606, 0x08040A, 0x380102,
-0x000424, 0x000424, 0x001224, 0x0002FD,
-0x018042, 0x08000A, 0x000904, 0x14A286,
-0x000007, 0x280502, 0x001A4C, 0x163986,
-0x000007, 0x032164, 0x00632C, 0x003DFD,
-0x018042, 0x08000A, 0x000095, 0x090904,
-0x000007, 0x000820, 0x001A4C, 0x156186,
-0x018040, 0x030000, 0x157A06, 0x002124,
-0x00010D, 0x000924, 0x006B24, 0x015B8D,
-0x00397D, 0x000820, 0x058040, 0x038042,
-0x09844A, 0x000606, 0x08040A, 0x003A64,
-0x000095, 0x001224, 0x0002FD, 0x018042,
-0x08000A, 0x000904, 0x15DA86, 0x000007,
-0x01628D, 0x000810, 0x08043A, 0x29D206,
-0x000007, 0x14D206, 0x000007, 0x007020,
-0x08010A, 0x10012A, 0x0020FD, 0x038860,
-0x039060, 0x018040, 0x00227D, 0x018042,
-0x003DFD, 0x08000A, 0x31844A, 0x000904,
-0x16D886, 0x18008B, 0x00008D, 0x189904,
-0x00312C, 0x17AA06, 0x000007, 0x00324C,
-0x173386, 0x000007, 0x001904, 0x173086,
-0x000007, 0x000095, 0x199144, 0x00222C,
-0x003124, 0x00636C, 0x000E3D, 0x001375,
-0x000BFD, 0x010042, 0x09804A, 0x10000A,
-0x038AEC, 0x0393EC, 0x00224C, 0x17A986,
-0x000007, 0x00008D, 0x189904, 0x00226C,
-0x00322C, 0x30050A, 0x301DAB, 0x002083,
-0x0018FD, 0x018042, 0x08000A, 0x018924,
-0x300502, 0x001083, 0x001875, 0x010042,
-0x10000A, 0x00008D, 0x010924, 0x001375,
-0x330542, 0x330CCB, 0x332CCB, 0x3334CB,
-0x333CCB, 0x3344CB, 0x334CCB, 0x3354CB,
-0x305C8B, 0x006083, 0x0002F5, 0x010042,
-0x08000A, 0x000904, 0x187A86, 0x000007,
-0x001E2D, 0x0005FD, 0x018042, 0x08000A,
-0x028924, 0x280502, 0x00060D, 0x000810,
-0x280C3A, 0x00008D, 0x000810, 0x28143A,
-0x0A808D, 0x000820, 0x0002F5, 0x010040,
-0x220007, 0x001275, 0x030042, 0x21004A,
-0x00008D, 0x1A0944, 0x000007, 0x01980D,
-0x000810, 0x08043A, 0x2B2206, 0x000007,
-0x0001F5, 0x030042, 0x0D004A, 0x10000A,
-0x089144, 0x000007, 0x000820, 0x010040,
-0x0025F5, 0x0A3144, 0x000007, 0x000820,
-0x032860, 0x030040, 0x00217D, 0x038042,
-0x0B804A, 0x10000A, 0x000820, 0x031060,
-0x030040, 0x00008D, 0x000124, 0x00012C,
-0x000E64, 0x001A64, 0x00636C, 0x08010A,
-0x10012A, 0x000820, 0x031060, 0x030040,
-0x0020FD, 0x018042, 0x08000A, 0x00227D,
-0x018042, 0x10000A, 0x000820, 0x031060,
-0x030040, 0x00197D, 0x018042, 0x08000A,
-0x0022FD, 0x038042, 0x10000A, 0x000820,
-0x031060, 0x030040, 0x090D04, 0x000007,
-0x000820, 0x030040, 0x038042, 0x0B804A,
-0x10000A, 0x000820, 0x031060, 0x030040,
-0x038042, 0x13804A, 0x19804A, 0x110D04,
-0x198D04, 0x000007, 0x08000A, 0x001020,
-0x031860, 0x030860, 0x030040, 0x00008D,
-0x0B0944, 0x000007, 0x000820, 0x010040,
-0x0005F5, 0x030042, 0x08000A, 0x000820,
-0x010040, 0x0000F5, 0x010042, 0x08000A,
-0x000904, 0x1C6086, 0x001E75, 0x030042,
-0x01044A, 0x000C0A, 0x1C7206, 0x000007,
-0x000402, 0x000C02, 0x00177D, 0x001AF5,
-0x018042, 0x03144A, 0x031C4A, 0x03244A,
-0x032C4A, 0x03344A, 0x033C4A, 0x03444A,
-0x004C0A, 0x00043D, 0x0013F5, 0x001AFD,
-0x030042, 0x0B004A, 0x1B804A, 0x13804A,
-0x20000A, 0x089144, 0x19A144, 0x0389E4,
-0x0399EC, 0x005502, 0x005D0A, 0x030042,
-0x0B004A, 0x1B804A, 0x13804A, 0x20000A,
-0x089144, 0x19A144, 0x0389E4, 0x0399EC,
-0x006502, 0x006D0A, 0x030042, 0x0B004A,
-0x19004A, 0x2B804A, 0x13804A, 0x21804A,
-0x30000A, 0x089144, 0x19A144, 0x2AB144,
-0x0389E4, 0x0399EC, 0x007502, 0x007D0A,
-0x03A9E4, 0x000702, 0x00107D, 0x000415,
-0x018042, 0x08000A, 0x0109E4, 0x000F02,
-0x002AF5, 0x0019FD, 0x010042, 0x09804A,
-0x10000A, 0x000934, 0x001674, 0x0029F5,
-0x010042, 0x10000A, 0x00917C, 0x002075,
-0x010042, 0x08000A, 0x000904, 0x1ED286,
-0x0026F5, 0x0027F5, 0x030042, 0x09004A,
-0x10000A, 0x000A3C, 0x00167C, 0x001A75,
-0x000BFD, 0x010042, 0x51804A, 0x48000A,
-0x160007, 0x001075, 0x010042, 0x282C0A,
-0x281D12, 0x282512, 0x001F32, 0x1E0007,
-0x0E0007, 0x001975, 0x010042, 0x002DF5,
-0x0D004A, 0x10000A, 0x009144, 0x1FB286,
-0x010042, 0x28340A, 0x000E5D, 0x00008D,
-0x000375, 0x000820, 0x010040, 0x05D2F4,
-0x54D104, 0x00735C, 0x205386, 0x000007,
-0x0C0007, 0x080007, 0x0A0007, 0x02040D,
-0x000810, 0x08043A, 0x332206, 0x000007,
-0x205A06, 0x000007, 0x080007, 0x002275,
-0x010042, 0x20000A, 0x002104, 0x212086,
-0x001E2D, 0x0002F5, 0x010042, 0x08000A,
-0x000904, 0x209286, 0x000007, 0x002010,
-0x30043A, 0x00057D, 0x0180C3, 0x08000A,
-0x028924, 0x280502, 0x280C02, 0x0A810D,
-0x000820, 0x0002F5, 0x010040, 0x220007,
-0x0004FD, 0x018042, 0x70000A, 0x030000,
-0x007020, 0x06FA06, 0x018040, 0x02180D,
-0x000810, 0x08043A, 0x2B2206, 0x000007,
-0x0002FD, 0x018042, 0x08000A, 0x000904,
-0x218A86, 0x000007, 0x01F206, 0x000007,
-0x000875, 0x0009FD, 0x00010D, 0x220A06,
-0x000295, 0x000B75, 0x00097D, 0x00000D,
-0x000515, 0x010042, 0x18000A, 0x001904,
-0x287886, 0x0006F5, 0x001020, 0x010040,
-0x0004F5, 0x000820, 0x010040, 0x000775,
-0x010042, 0x09804A, 0x10000A, 0x001124,
-0x000904, 0x22BA86, 0x000815, 0x080102,
-0x101204, 0x22DA06, 0x000575, 0x081204,
-0x000007, 0x100102, 0x000575, 0x000425,
-0x021124, 0x100102, 0x000820, 0x031060,
-0x010040, 0x001924, 0x287886, 0x00008D,
-0x000464, 0x009D04, 0x278886, 0x180102,
-0x000575, 0x010042, 0x28040A, 0x00018D,
-0x000924, 0x280D02, 0x00000D, 0x000924,
-0x281502, 0x10000D, 0x000820, 0x0002F5,
-0x010040, 0x200007, 0x001175, 0x0002FD,
-0x018042, 0x08000A, 0x000904, 0x23C286,
-0x000007, 0x000100, 0x080B20, 0x130B60,
-0x1B0B60, 0x030A60, 0x010040, 0x050042,
-0x3D004A, 0x35004A, 0x2D004A, 0x20000A,
-0x0006F5, 0x010042, 0x28140A, 0x0004F5,
-0x010042, 0x08000A, 0x000315, 0x010D04,
-0x24CA86, 0x004015, 0x000095, 0x010D04,
-0x24B886, 0x100022, 0x10002A, 0x24E206,
-0x000007, 0x333104, 0x2AA904, 0x000007,
-0x032124, 0x280502, 0x001124, 0x000424,
-0x000424, 0x003224, 0x00292C, 0x00636C,
-0x25F386, 0x000007, 0x02B164, 0x000464,
-0x000464, 0x00008D, 0x000A64, 0x280D02,
-0x10008D, 0x000820, 0x0002F5, 0x010040,
-0x220007, 0x00008D, 0x38B904, 0x000007,
-0x03296C, 0x30010A, 0x0002F5, 0x010042,
-0x08000A, 0x000904, 0x25BA86, 0x000007,
-0x02312C, 0x28050A, 0x00008D, 0x01096C,
-0x280D0A, 0x10010D, 0x000820, 0x0002F5,
-0x010040, 0x220007, 0x001124, 0x000424,
-0x000424, 0x003224, 0x300102, 0x032944,
-0x267A86, 0x000007, 0x300002, 0x0004F5,
-0x010042, 0x08000A, 0x000315, 0x010D04,
-0x26C086, 0x003124, 0x000464, 0x300102,
-0x0002F5, 0x010042, 0x08000A, 0x000904,
-0x26CA86, 0x000007, 0x003124, 0x300502,
-0x003924, 0x300583, 0x000883, 0x0005F5,
-0x010042, 0x28040A, 0x00008D, 0x008124,
-0x280D02, 0x00008D, 0x008124, 0x281502,
-0x10018D, 0x000820, 0x0002F5, 0x010040,
-0x220007, 0x001025, 0x000575, 0x030042,
-0x09004A, 0x10000A, 0x0A0904, 0x121104,
-0x000007, 0x001020, 0x050860, 0x050040,
-0x0006FD, 0x018042, 0x09004A, 0x10000A,
-0x0000A5, 0x0A0904, 0x121104, 0x000007,
-0x000820, 0x019060, 0x010040, 0x0002F5,
-0x010042, 0x08000A, 0x000904, 0x284286,
-0x000007, 0x230A06, 0x000007, 0x000606,
-0x000007, 0x0002F5, 0x010042, 0x08000A,
-0x000904, 0x289286, 0x000007, 0x000100,
-0x080B20, 0x138B60, 0x1B8B60, 0x238B60,
-0x2B8B60, 0x338B60, 0x3B8B60, 0x438B60,
-0x4B8B60, 0x538B60, 0x5B8B60, 0x638B60,
-0x6B8B60, 0x738B60, 0x7B8B60, 0x038F60,
-0x0B8F60, 0x138F60, 0x1B8F60, 0x238F60,
-0x2B8F60, 0x338F60, 0x3B8F60, 0x438F60,
-0x4B8F60, 0x538F60, 0x5B8F60, 0x638F60,
-0x6B8F60, 0x738F60, 0x7B8F60, 0x038A60,
-0x000606, 0x018040, 0x00008D, 0x000A64,
-0x280D02, 0x000A24, 0x00027D, 0x018042,
-0x10000A, 0x001224, 0x0003FD, 0x018042,
-0x08000A, 0x000904, 0x2A8286, 0x000007,
-0x00018D, 0x000A24, 0x000464, 0x000464,
-0x080102, 0x000924, 0x000424, 0x000424,
-0x100102, 0x02000D, 0x009144, 0x2AD986,
-0x000007, 0x0001FD, 0x018042, 0x08000A,
-0x000A44, 0x2ABB86, 0x018042, 0x0A000D,
-0x000820, 0x0002FD, 0x018040, 0x200007,
-0x00027D, 0x001020, 0x000606, 0x018040,
-0x0002F5, 0x010042, 0x08000A, 0x000904,
-0x2B2A86, 0x000007, 0x00037D, 0x018042,
-0x08000A, 0x000904, 0x2B5A86, 0x000007,
-0x000075, 0x002E7D, 0x010042, 0x0B804A,
-0x000020, 0x000904, 0x000686, 0x010040,
-0x31844A, 0x30048B, 0x000883, 0x00008D,
-0x000810, 0x28143A, 0x00008D, 0x000810,
-0x280C3A, 0x000675, 0x010042, 0x08000A,
-0x003815, 0x010924, 0x280502, 0x0B000D,
-0x000820, 0x0002F5, 0x010040, 0x000606,
-0x220007, 0x000464, 0x000464, 0x000606,
-0x000007, 0x000134, 0x007F8D, 0x00093C,
-0x281D12, 0x282512, 0x001F32, 0x0E0007,
-0x00010D, 0x00037D, 0x000820, 0x018040,
-0x05D2F4, 0x000007, 0x080007, 0x00037D,
-0x018042, 0x08000A, 0x000904, 0x2D0286,
-0x000007, 0x000606, 0x000007, 0x000007,
-0x000012, 0x100007, 0x320007, 0x600007,
-0x100080, 0x48001A, 0x004904, 0x2D6186,
-0x000007, 0x001210, 0x58003A, 0x000145,
-0x5C5D04, 0x000007, 0x000080, 0x48001A,
-0x004904, 0x2DB186, 0x000007, 0x001210,
-0x50003A, 0x005904, 0x2E0886, 0x000045,
-0x0000C5, 0x7FFFF5, 0x7FFF7D, 0x07D524,
-0x004224, 0x500102, 0x200502, 0x000082,
-0x40001A, 0x004104, 0x2E3986, 0x000007,
-0x003865, 0x40001A, 0x004020, 0x00104D,
-0x04C184, 0x301B86, 0x000040, 0x040007,
-0x000165, 0x000145, 0x004020, 0x000040,
-0x000765, 0x080080, 0x40001A, 0x004104,
-0x2EC986, 0x000007, 0x001210, 0x40003A,
-0x004104, 0x2F2286, 0x00004D, 0x0000CD,
-0x004810, 0x20043A, 0x000882, 0x40001A,
-0x004104, 0x2F3186, 0x000007, 0x004820,
-0x005904, 0x300886, 0x000040, 0x0007E5,
-0x200480, 0x2816A0, 0x3216E0, 0x3A16E0,
-0x4216E0, 0x021260, 0x000040, 0x000032,
-0x400075, 0x00007D, 0x07D574, 0x200512,
-0x000082, 0x40001A, 0x004104, 0x2FE186,
-0x000007, 0x037206, 0x640007, 0x060007,
-0x0000E5, 0x000020, 0x000040, 0x000A65,
-0x000020, 0x020040, 0x020040, 0x000040,
-0x000165, 0x000042, 0x70000A, 0x007104,
-0x30A286, 0x000007, 0x018206, 0x640007,
-0x050000, 0x007020, 0x000040, 0x037206,
-0x640007, 0x000007, 0x00306D, 0x028860,
-0x029060, 0x08000A, 0x028860, 0x008040,
-0x100012, 0x00100D, 0x009184, 0x314186,
-0x000E0D, 0x009184, 0x325186, 0x000007,
-0x300007, 0x001020, 0x003B6D, 0x008040,
-0x000080, 0x08001A, 0x000904, 0x316186,
-0x000007, 0x001220, 0x000DED, 0x008040,
-0x008042, 0x10000A, 0x40000D, 0x109544,
-0x000007, 0x001020, 0x000DED, 0x008040,
-0x008042, 0x20040A, 0x000082, 0x08001A,
-0x000904, 0x31F186, 0x000007, 0x003B6D,
-0x008042, 0x08000A, 0x000E15, 0x010984,
-0x329B86, 0x600007, 0x08001A, 0x000C15,
-0x010984, 0x328386, 0x000020, 0x1A0007,
-0x0002ED, 0x008040, 0x620007, 0x00306D,
-0x028042, 0x0A804A, 0x000820, 0x0A804A,
-0x000606, 0x10804A, 0x000007, 0x282512,
-0x001F32, 0x05D2F4, 0x54D104, 0x00735C,
-0x000786, 0x000007, 0x0C0007, 0x0A0007,
-0x1C0007, 0x003465, 0x020040, 0x004820,
-0x025060, 0x40000A, 0x024060, 0x000040,
-0x454944, 0x000007, 0x004020, 0x003AE5,
-0x000040, 0x0028E5, 0x000042, 0x48000A,
-0x004904, 0x386886, 0x002C65, 0x000042,
-0x40000A, 0x0000D5, 0x454104, 0x000007,
-0x000655, 0x054504, 0x34F286, 0x0001D5,
-0x054504, 0x34F086, 0x002B65, 0x000042,
-0x003AE5, 0x50004A, 0x40000A, 0x45C3D4,
-0x000007, 0x454504, 0x000007, 0x0000CD,
-0x444944, 0x000007, 0x454504, 0x000007,
-0x00014D, 0x554944, 0x000007, 0x045144,
-0x34E986, 0x002C65, 0x000042, 0x48000A,
-0x4CD104, 0x000007, 0x04C144, 0x34F386,
-0x000007, 0x160007, 0x002CE5, 0x040042,
-0x40000A, 0x004020, 0x000040, 0x002965,
-0x000042, 0x40000A, 0x004104, 0x356086,
-0x000007, 0x002402, 0x36A206, 0x005C02,
-0x0025E5, 0x000042, 0x40000A, 0x004274,
-0x002AE5, 0x000042, 0x40000A, 0x004274,
-0x500112, 0x0029E5, 0x000042, 0x40000A,
-0x004234, 0x454104, 0x000007, 0x004020,
-0x000040, 0x003EE5, 0x000020, 0x000040,
-0x002DE5, 0x400152, 0x50000A, 0x045144,
-0x364A86, 0x0000C5, 0x003EE5, 0x004020,
-0x000040, 0x002BE5, 0x000042, 0x40000A,
-0x404254, 0x000007, 0x002AE5, 0x004020,
-0x000040, 0x500132, 0x040134, 0x005674,
-0x0029E5, 0x020042, 0x42000A, 0x000042,
-0x50000A, 0x05417C, 0x0028E5, 0x000042,
-0x48000A, 0x0000C5, 0x4CC144, 0x371086,
-0x0026E5, 0x0027E5, 0x020042, 0x40004A,
-0x50000A, 0x00423C, 0x00567C, 0x0028E5,
-0x004820, 0x000040, 0x281D12, 0x282512,
-0x001F72, 0x002965, 0x000042, 0x40000A,
-0x004104, 0x37AA86, 0x0E0007, 0x160007,
-0x1E0007, 0x003EE5, 0x000042, 0x40000A,
-0x004104, 0x37E886, 0x002D65, 0x000042,
-0x28340A, 0x003465, 0x020042, 0x42004A,
-0x004020, 0x4A004A, 0x50004A, 0x05D2F4,
-0x54D104, 0x00735C, 0x385186, 0x000007,
-0x000606, 0x080007, 0x0C0007, 0x080007,
-0x0A0007, 0x0001E5, 0x020045, 0x004020,
-0x000060, 0x000365, 0x000040, 0x002E65,
-0x001A20, 0x0A1A60, 0x000040, 0x003465,
-0x020042, 0x42004A, 0x004020, 0x4A004A,
-0x000606, 0x50004A, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000
+ 0x000007, 0x240007, 0x0C0007, 0x1C0007,
+ 0x060007, 0x700002, 0x000020, 0x030040,
+ 0x007104, 0x004286, 0x030040, 0x000F0D,
+ 0x000810, 0x20043A, 0x000282, 0x00020D,
+ 0x000810, 0x20043A, 0x001282, 0x200E82,
+ 0x001A82, 0x032D0D, 0x000810, 0x10043A,
+ 0x02D38D, 0x000810, 0x18043A, 0x00010D,
+ 0x020015, 0x0000FD, 0x000020, 0x038860,
+ 0x039060, 0x038060, 0x038040, 0x038040,
+ 0x038040, 0x018040, 0x000A7D, 0x038040,
+ 0x038040, 0x018040, 0x200402, 0x000882,
+ 0x08001A, 0x000904, 0x015986, 0x000007,
+ 0x260007, 0x000007, 0x000007, 0x018A06,
+ 0x000007, 0x030C8D, 0x000810, 0x18043A,
+ 0x260007, 0x00087D, 0x018042, 0x00160A,
+ 0x04A206, 0x000007, 0x00218D, 0x000810,
+ 0x08043A, 0x21C206, 0x000007, 0x0007FD,
+ 0x018042, 0x08000A, 0x000904, 0x029386,
+ 0x000195, 0x090D04, 0x000007, 0x000820,
+ 0x0000F5, 0x000B7D, 0x01F060, 0x0000FD,
+ 0x032206, 0x018040, 0x000A7D, 0x038042,
+ 0x13804A, 0x18000A, 0x001820, 0x059060,
+ 0x058860, 0x018040, 0x0000FD, 0x018042,
+ 0x70000A, 0x000115, 0x071144, 0x032386,
+ 0x030000, 0x007020, 0x034A06, 0x018040,
+ 0x00348D, 0x000810, 0x08043A, 0x21EA06,
+ 0x000007, 0x02D38D, 0x000810, 0x18043A,
+ 0x018206, 0x000007, 0x240007, 0x000F8D,
+ 0x000810, 0x00163A, 0x002402, 0x005C02,
+ 0x0028FD, 0x000020, 0x018040, 0x08000D,
+ 0x000815, 0x510984, 0x000007, 0x00004D,
+ 0x000E5D, 0x000E02, 0x00418D, 0x000810,
+ 0x08043A, 0x2C8A06, 0x000007, 0x00008D,
+ 0x000924, 0x000F02, 0x00458D, 0x000810,
+ 0x08043A, 0x2C8A06, 0x000007, 0x00387D,
+ 0x018042, 0x08000A, 0x001015, 0x010984,
+ 0x018386, 0x000007, 0x01AA06, 0x000007,
+ 0x0008FD, 0x018042, 0x18000A, 0x001904,
+ 0x218086, 0x280007, 0x001810, 0x28043A,
+ 0x280C02, 0x00000D, 0x000810, 0x28143A,
+ 0x08808D, 0x000820, 0x0002FD, 0x018040,
+ 0x200007, 0x00020D, 0x189904, 0x000007,
+ 0x00402D, 0x0000BD, 0x0002FD, 0x018042,
+ 0x08000A, 0x000904, 0x055A86, 0x000007,
+ 0x000100, 0x000A20, 0x00047D, 0x018040,
+ 0x018042, 0x20000A, 0x003015, 0x012144,
+ 0x034986, 0x000007, 0x002104, 0x034986,
+ 0x000007, 0x000F8D, 0x000810, 0x280C3A,
+ 0x023944, 0x06C986, 0x000007, 0x001810,
+ 0x28043A, 0x08810D, 0x000820, 0x0002FD,
+ 0x018040, 0x200007, 0x002810, 0x78003A,
+ 0x00688D, 0x000810, 0x08043A, 0x288A06,
+ 0x000007, 0x00400D, 0x001015, 0x189904,
+ 0x292904, 0x393904, 0x000007, 0x060206,
+ 0x000007, 0x0004F5, 0x00007D, 0x000020,
+ 0x00008D, 0x010860, 0x018040, 0x00047D,
+ 0x038042, 0x21804A, 0x18000A, 0x021944,
+ 0x215886, 0x000007, 0x004075, 0x71F104,
+ 0x000007, 0x010042, 0x28000A, 0x002904,
+ 0x212086, 0x000007, 0x003C0D, 0x30A904,
+ 0x000007, 0x00077D, 0x018042, 0x08000A,
+ 0x000904, 0x07DA86, 0x00057D, 0x002820,
+ 0x03B060, 0x07F206, 0x018040, 0x003020,
+ 0x03A860, 0x018040, 0x0002FD, 0x018042,
+ 0x08000A, 0x000904, 0x07FA86, 0x000007,
+ 0x00057D, 0x018042, 0x28040A, 0x000E8D,
+ 0x000810, 0x280C3A, 0x00000D, 0x000810,
+ 0x28143A, 0x09000D, 0x000820, 0x0002FD,
+ 0x018040, 0x200007, 0x003DFD, 0x000020,
+ 0x018040, 0x00107D, 0x008D8D, 0x000810,
+ 0x08043A, 0x288A06, 0x000007, 0x000815,
+ 0x08001A, 0x010984, 0x095186, 0x00137D,
+ 0x200500, 0x280F20, 0x338F60, 0x3B8F60,
+ 0x438F60, 0x4B8F60, 0x538F60, 0x5B8F60,
+ 0x038A60, 0x018040, 0x007FBD, 0x383DC4,
+ 0x000007, 0x001A7D, 0x001375, 0x018042,
+ 0x09004A, 0x10000A, 0x0B8D04, 0x139504,
+ 0x000007, 0x000820, 0x019060, 0x001104,
+ 0x212086, 0x010040, 0x0017FD, 0x018042,
+ 0x08000A, 0x000904, 0x212286, 0x000007,
+ 0x00197D, 0x038042, 0x09804A, 0x10000A,
+ 0x000924, 0x001664, 0x0011FD, 0x038042,
+ 0x2B804A, 0x19804A, 0x00008D, 0x218944,
+ 0x000007, 0x002244, 0x0AE186, 0x000007,
+ 0x001A64, 0x002A24, 0x00197D, 0x080102,
+ 0x100122, 0x000820, 0x039060, 0x018040,
+ 0x003DFD, 0x00008D, 0x000820, 0x018040,
+ 0x001375, 0x001A7D, 0x010042, 0x09804A,
+ 0x10000A, 0x00021D, 0x0189E4, 0x2992E4,
+ 0x309144, 0x000007, 0x00060D, 0x000A15,
+ 0x000C1D, 0x001025, 0x00A9E4, 0x012BE4,
+ 0x000464, 0x01B3E4, 0x0232E4, 0x000464,
+ 0x000464, 0x000464, 0x000464, 0x00040D,
+ 0x08B1C4, 0x000007, 0x000820, 0x000BF5,
+ 0x030040, 0x00197D, 0x038042, 0x09804A,
+ 0x000A24, 0x08000A, 0x080E64, 0x000007,
+ 0x100122, 0x000820, 0x031060, 0x010040,
+ 0x0064AC, 0x00027D, 0x000020, 0x018040,
+ 0x00107D, 0x018042, 0x0011FD, 0x3B804A,
+ 0x09804A, 0x20000A, 0x000095, 0x1A1144,
+ 0x00A144, 0x0D2086, 0x00040D, 0x00B984,
+ 0x0D2186, 0x0018FD, 0x018042, 0x0010FD,
+ 0x09804A, 0x28000A, 0x000095, 0x010924,
+ 0x002A64, 0x0D1186, 0x000007, 0x002904,
+ 0x0D2286, 0x000007, 0x0D2A06, 0x080002,
+ 0x00008D, 0x00387D, 0x000820, 0x018040,
+ 0x00127D, 0x018042, 0x10000A, 0x003904,
+ 0x0DD186, 0x00080D, 0x7FFFB5, 0x00B984,
+ 0x0DA186, 0x000025, 0x0E7A06, 0x00002D,
+ 0x000015, 0x00082D, 0x02C78D, 0x000820,
+ 0x0EC206, 0x00000D, 0x7F8035, 0x00B984,
+ 0x0E7186, 0x400025, 0x00008D, 0x110944,
+ 0x000007, 0x00018D, 0x109504, 0x000007,
+ 0x009164, 0x000424, 0x000424, 0x000424,
+ 0x100102, 0x280002, 0x02C68D, 0x000820,
+ 0x0EC206, 0x00018D, 0x00042D, 0x00008D,
+ 0x109504, 0x000007, 0x00020D, 0x109184,
+ 0x000007, 0x02C70D, 0x000820, 0x00008D,
+ 0x0038FD, 0x018040, 0x003BFD, 0x001020,
+ 0x03A860, 0x000815, 0x313184, 0x212184,
+ 0x000007, 0x03B060, 0x03A060, 0x018040,
+ 0x0022FD, 0x000095, 0x010924, 0x000424,
+ 0x000424, 0x001264, 0x100102, 0x000820,
+ 0x039060, 0x018040, 0x001924, 0x00FB8D,
+ 0x00397D, 0x000820, 0x058040, 0x038042,
+ 0x09844A, 0x000606, 0x08040A, 0x000424,
+ 0x000424, 0x00117D, 0x018042, 0x08000A,
+ 0x000A24, 0x280502, 0x280C02, 0x09800D,
+ 0x000820, 0x0002FD, 0x018040, 0x200007,
+ 0x0022FD, 0x018042, 0x08000A, 0x000095,
+ 0x280DC4, 0x011924, 0x00197D, 0x018042,
+ 0x0011FD, 0x09804A, 0x10000A, 0x0000B5,
+ 0x113144, 0x0A8D04, 0x000007, 0x080A44,
+ 0x129504, 0x000007, 0x0023FD, 0x001020,
+ 0x038040, 0x101244, 0x000007, 0x000820,
+ 0x039060, 0x018040, 0x0002FD, 0x018042,
+ 0x08000A, 0x000904, 0x10FA86, 0x000007,
+ 0x003BFD, 0x000100, 0x000A10, 0x0B807A,
+ 0x13804A, 0x090984, 0x000007, 0x000095,
+ 0x013D04, 0x118086, 0x10000A, 0x100002,
+ 0x090984, 0x000007, 0x038042, 0x11804A,
+ 0x090D04, 0x000007, 0x10000A, 0x090D84,
+ 0x000007, 0x00257D, 0x000820, 0x018040,
+ 0x00010D, 0x000810, 0x28143A, 0x00127D,
+ 0x018042, 0x20000A, 0x00197D, 0x018042,
+ 0x00117D, 0x31804A, 0x10000A, 0x003124,
+ 0x01280D, 0x00397D, 0x000820, 0x058040,
+ 0x038042, 0x09844A, 0x000606, 0x08040A,
+ 0x300102, 0x003124, 0x000424, 0x000424,
+ 0x001224, 0x280502, 0x001A4C, 0x130186,
+ 0x700002, 0x00002D, 0x030000, 0x00387D,
+ 0x018042, 0x10000A, 0x132A06, 0x002124,
+ 0x0000AD, 0x100002, 0x00010D, 0x000924,
+ 0x006B24, 0x01368D, 0x00397D, 0x000820,
+ 0x058040, 0x038042, 0x09844A, 0x000606,
+ 0x08040A, 0x003264, 0x00008D, 0x000A24,
+ 0x001020, 0x00227D, 0x018040, 0x013C0D,
+ 0x000810, 0x08043A, 0x29D206, 0x000007,
+ 0x002820, 0x00207D, 0x018040, 0x00117D,
+ 0x038042, 0x13804A, 0x33800A, 0x00387D,
+ 0x018042, 0x08000A, 0x000904, 0x163A86,
+ 0x000007, 0x00008D, 0x030964, 0x01478D,
+ 0x00397D, 0x000820, 0x058040, 0x038042,
+ 0x09844A, 0x000606, 0x08040A, 0x380102,
+ 0x000424, 0x000424, 0x001224, 0x0002FD,
+ 0x018042, 0x08000A, 0x000904, 0x14A286,
+ 0x000007, 0x280502, 0x001A4C, 0x163986,
+ 0x000007, 0x032164, 0x00632C, 0x003DFD,
+ 0x018042, 0x08000A, 0x000095, 0x090904,
+ 0x000007, 0x000820, 0x001A4C, 0x156186,
+ 0x018040, 0x030000, 0x157A06, 0x002124,
+ 0x00010D, 0x000924, 0x006B24, 0x015B8D,
+ 0x00397D, 0x000820, 0x058040, 0x038042,
+ 0x09844A, 0x000606, 0x08040A, 0x003A64,
+ 0x000095, 0x001224, 0x0002FD, 0x018042,
+ 0x08000A, 0x000904, 0x15DA86, 0x000007,
+ 0x01628D, 0x000810, 0x08043A, 0x29D206,
+ 0x000007, 0x14D206, 0x000007, 0x007020,
+ 0x08010A, 0x10012A, 0x0020FD, 0x038860,
+ 0x039060, 0x018040, 0x00227D, 0x018042,
+ 0x003DFD, 0x08000A, 0x31844A, 0x000904,
+ 0x16D886, 0x18008B, 0x00008D, 0x189904,
+ 0x00312C, 0x17AA06, 0x000007, 0x00324C,
+ 0x173386, 0x000007, 0x001904, 0x173086,
+ 0x000007, 0x000095, 0x199144, 0x00222C,
+ 0x003124, 0x00636C, 0x000E3D, 0x001375,
+ 0x000BFD, 0x010042, 0x09804A, 0x10000A,
+ 0x038AEC, 0x0393EC, 0x00224C, 0x17A986,
+ 0x000007, 0x00008D, 0x189904, 0x00226C,
+ 0x00322C, 0x30050A, 0x301DAB, 0x002083,
+ 0x0018FD, 0x018042, 0x08000A, 0x018924,
+ 0x300502, 0x001083, 0x001875, 0x010042,
+ 0x10000A, 0x00008D, 0x010924, 0x001375,
+ 0x330542, 0x330CCB, 0x332CCB, 0x3334CB,
+ 0x333CCB, 0x3344CB, 0x334CCB, 0x3354CB,
+ 0x305C8B, 0x006083, 0x0002F5, 0x010042,
+ 0x08000A, 0x000904, 0x187A86, 0x000007,
+ 0x001E2D, 0x0005FD, 0x018042, 0x08000A,
+ 0x028924, 0x280502, 0x00060D, 0x000810,
+ 0x280C3A, 0x00008D, 0x000810, 0x28143A,
+ 0x0A808D, 0x000820, 0x0002F5, 0x010040,
+ 0x220007, 0x001275, 0x030042, 0x21004A,
+ 0x00008D, 0x1A0944, 0x000007, 0x01980D,
+ 0x000810, 0x08043A, 0x2B2206, 0x000007,
+ 0x0001F5, 0x030042, 0x0D004A, 0x10000A,
+ 0x089144, 0x000007, 0x000820, 0x010040,
+ 0x0025F5, 0x0A3144, 0x000007, 0x000820,
+ 0x032860, 0x030040, 0x00217D, 0x038042,
+ 0x0B804A, 0x10000A, 0x000820, 0x031060,
+ 0x030040, 0x00008D, 0x000124, 0x00012C,
+ 0x000E64, 0x001A64, 0x00636C, 0x08010A,
+ 0x10012A, 0x000820, 0x031060, 0x030040,
+ 0x0020FD, 0x018042, 0x08000A, 0x00227D,
+ 0x018042, 0x10000A, 0x000820, 0x031060,
+ 0x030040, 0x00197D, 0x018042, 0x08000A,
+ 0x0022FD, 0x038042, 0x10000A, 0x000820,
+ 0x031060, 0x030040, 0x090D04, 0x000007,
+ 0x000820, 0x030040, 0x038042, 0x0B804A,
+ 0x10000A, 0x000820, 0x031060, 0x030040,
+ 0x038042, 0x13804A, 0x19804A, 0x110D04,
+ 0x198D04, 0x000007, 0x08000A, 0x001020,
+ 0x031860, 0x030860, 0x030040, 0x00008D,
+ 0x0B0944, 0x000007, 0x000820, 0x010040,
+ 0x0005F5, 0x030042, 0x08000A, 0x000820,
+ 0x010040, 0x0000F5, 0x010042, 0x08000A,
+ 0x000904, 0x1C6086, 0x001E75, 0x030042,
+ 0x01044A, 0x000C0A, 0x1C7206, 0x000007,
+ 0x000402, 0x000C02, 0x00177D, 0x001AF5,
+ 0x018042, 0x03144A, 0x031C4A, 0x03244A,
+ 0x032C4A, 0x03344A, 0x033C4A, 0x03444A,
+ 0x004C0A, 0x00043D, 0x0013F5, 0x001AFD,
+ 0x030042, 0x0B004A, 0x1B804A, 0x13804A,
+ 0x20000A, 0x089144, 0x19A144, 0x0389E4,
+ 0x0399EC, 0x005502, 0x005D0A, 0x030042,
+ 0x0B004A, 0x1B804A, 0x13804A, 0x20000A,
+ 0x089144, 0x19A144, 0x0389E4, 0x0399EC,
+ 0x006502, 0x006D0A, 0x030042, 0x0B004A,
+ 0x19004A, 0x2B804A, 0x13804A, 0x21804A,
+ 0x30000A, 0x089144, 0x19A144, 0x2AB144,
+ 0x0389E4, 0x0399EC, 0x007502, 0x007D0A,
+ 0x03A9E4, 0x000702, 0x00107D, 0x000415,
+ 0x018042, 0x08000A, 0x0109E4, 0x000F02,
+ 0x002AF5, 0x0019FD, 0x010042, 0x09804A,
+ 0x10000A, 0x000934, 0x001674, 0x0029F5,
+ 0x010042, 0x10000A, 0x00917C, 0x002075,
+ 0x010042, 0x08000A, 0x000904, 0x1ED286,
+ 0x0026F5, 0x0027F5, 0x030042, 0x09004A,
+ 0x10000A, 0x000A3C, 0x00167C, 0x001A75,
+ 0x000BFD, 0x010042, 0x51804A, 0x48000A,
+ 0x160007, 0x001075, 0x010042, 0x282C0A,
+ 0x281D12, 0x282512, 0x001F32, 0x1E0007,
+ 0x0E0007, 0x001975, 0x010042, 0x002DF5,
+ 0x0D004A, 0x10000A, 0x009144, 0x1FB286,
+ 0x010042, 0x28340A, 0x000E5D, 0x00008D,
+ 0x000375, 0x000820, 0x010040, 0x05D2F4,
+ 0x54D104, 0x00735C, 0x205386, 0x000007,
+ 0x0C0007, 0x080007, 0x0A0007, 0x02040D,
+ 0x000810, 0x08043A, 0x332206, 0x000007,
+ 0x205A06, 0x000007, 0x080007, 0x002275,
+ 0x010042, 0x20000A, 0x002104, 0x212086,
+ 0x001E2D, 0x0002F5, 0x010042, 0x08000A,
+ 0x000904, 0x209286, 0x000007, 0x002010,
+ 0x30043A, 0x00057D, 0x0180C3, 0x08000A,
+ 0x028924, 0x280502, 0x280C02, 0x0A810D,
+ 0x000820, 0x0002F5, 0x010040, 0x220007,
+ 0x0004FD, 0x018042, 0x70000A, 0x030000,
+ 0x007020, 0x06FA06, 0x018040, 0x02180D,
+ 0x000810, 0x08043A, 0x2B2206, 0x000007,
+ 0x0002FD, 0x018042, 0x08000A, 0x000904,
+ 0x218A86, 0x000007, 0x01F206, 0x000007,
+ 0x000875, 0x0009FD, 0x00010D, 0x220A06,
+ 0x000295, 0x000B75, 0x00097D, 0x00000D,
+ 0x000515, 0x010042, 0x18000A, 0x001904,
+ 0x287886, 0x0006F5, 0x001020, 0x010040,
+ 0x0004F5, 0x000820, 0x010040, 0x000775,
+ 0x010042, 0x09804A, 0x10000A, 0x001124,
+ 0x000904, 0x22BA86, 0x000815, 0x080102,
+ 0x101204, 0x22DA06, 0x000575, 0x081204,
+ 0x000007, 0x100102, 0x000575, 0x000425,
+ 0x021124, 0x100102, 0x000820, 0x031060,
+ 0x010040, 0x001924, 0x287886, 0x00008D,
+ 0x000464, 0x009D04, 0x278886, 0x180102,
+ 0x000575, 0x010042, 0x28040A, 0x00018D,
+ 0x000924, 0x280D02, 0x00000D, 0x000924,
+ 0x281502, 0x10000D, 0x000820, 0x0002F5,
+ 0x010040, 0x200007, 0x001175, 0x0002FD,
+ 0x018042, 0x08000A, 0x000904, 0x23C286,
+ 0x000007, 0x000100, 0x080B20, 0x130B60,
+ 0x1B0B60, 0x030A60, 0x010040, 0x050042,
+ 0x3D004A, 0x35004A, 0x2D004A, 0x20000A,
+ 0x0006F5, 0x010042, 0x28140A, 0x0004F5,
+ 0x010042, 0x08000A, 0x000315, 0x010D04,
+ 0x24CA86, 0x004015, 0x000095, 0x010D04,
+ 0x24B886, 0x100022, 0x10002A, 0x24E206,
+ 0x000007, 0x333104, 0x2AA904, 0x000007,
+ 0x032124, 0x280502, 0x001124, 0x000424,
+ 0x000424, 0x003224, 0x00292C, 0x00636C,
+ 0x25F386, 0x000007, 0x02B164, 0x000464,
+ 0x000464, 0x00008D, 0x000A64, 0x280D02,
+ 0x10008D, 0x000820, 0x0002F5, 0x010040,
+ 0x220007, 0x00008D, 0x38B904, 0x000007,
+ 0x03296C, 0x30010A, 0x0002F5, 0x010042,
+ 0x08000A, 0x000904, 0x25BA86, 0x000007,
+ 0x02312C, 0x28050A, 0x00008D, 0x01096C,
+ 0x280D0A, 0x10010D, 0x000820, 0x0002F5,
+ 0x010040, 0x220007, 0x001124, 0x000424,
+ 0x000424, 0x003224, 0x300102, 0x032944,
+ 0x267A86, 0x000007, 0x300002, 0x0004F5,
+ 0x010042, 0x08000A, 0x000315, 0x010D04,
+ 0x26C086, 0x003124, 0x000464, 0x300102,
+ 0x0002F5, 0x010042, 0x08000A, 0x000904,
+ 0x26CA86, 0x000007, 0x003124, 0x300502,
+ 0x003924, 0x300583, 0x000883, 0x0005F5,
+ 0x010042, 0x28040A, 0x00008D, 0x008124,
+ 0x280D02, 0x00008D, 0x008124, 0x281502,
+ 0x10018D, 0x000820, 0x0002F5, 0x010040,
+ 0x220007, 0x001025, 0x000575, 0x030042,
+ 0x09004A, 0x10000A, 0x0A0904, 0x121104,
+ 0x000007, 0x001020, 0x050860, 0x050040,
+ 0x0006FD, 0x018042, 0x09004A, 0x10000A,
+ 0x0000A5, 0x0A0904, 0x121104, 0x000007,
+ 0x000820, 0x019060, 0x010040, 0x0002F5,
+ 0x010042, 0x08000A, 0x000904, 0x284286,
+ 0x000007, 0x230A06, 0x000007, 0x000606,
+ 0x000007, 0x0002F5, 0x010042, 0x08000A,
+ 0x000904, 0x289286, 0x000007, 0x000100,
+ 0x080B20, 0x138B60, 0x1B8B60, 0x238B60,
+ 0x2B8B60, 0x338B60, 0x3B8B60, 0x438B60,
+ 0x4B8B60, 0x538B60, 0x5B8B60, 0x638B60,
+ 0x6B8B60, 0x738B60, 0x7B8B60, 0x038F60,
+ 0x0B8F60, 0x138F60, 0x1B8F60, 0x238F60,
+ 0x2B8F60, 0x338F60, 0x3B8F60, 0x438F60,
+ 0x4B8F60, 0x538F60, 0x5B8F60, 0x638F60,
+ 0x6B8F60, 0x738F60, 0x7B8F60, 0x038A60,
+ 0x000606, 0x018040, 0x00008D, 0x000A64,
+ 0x280D02, 0x000A24, 0x00027D, 0x018042,
+ 0x10000A, 0x001224, 0x0003FD, 0x018042,
+ 0x08000A, 0x000904, 0x2A8286, 0x000007,
+ 0x00018D, 0x000A24, 0x000464, 0x000464,
+ 0x080102, 0x000924, 0x000424, 0x000424,
+ 0x100102, 0x02000D, 0x009144, 0x2AD986,
+ 0x000007, 0x0001FD, 0x018042, 0x08000A,
+ 0x000A44, 0x2ABB86, 0x018042, 0x0A000D,
+ 0x000820, 0x0002FD, 0x018040, 0x200007,
+ 0x00027D, 0x001020, 0x000606, 0x018040,
+ 0x0002F5, 0x010042, 0x08000A, 0x000904,
+ 0x2B2A86, 0x000007, 0x00037D, 0x018042,
+ 0x08000A, 0x000904, 0x2B5A86, 0x000007,
+ 0x000075, 0x002E7D, 0x010042, 0x0B804A,
+ 0x000020, 0x000904, 0x000686, 0x010040,
+ 0x31844A, 0x30048B, 0x000883, 0x00008D,
+ 0x000810, 0x28143A, 0x00008D, 0x000810,
+ 0x280C3A, 0x000675, 0x010042, 0x08000A,
+ 0x003815, 0x010924, 0x280502, 0x0B000D,
+ 0x000820, 0x0002F5, 0x010040, 0x000606,
+ 0x220007, 0x000464, 0x000464, 0x000606,
+ 0x000007, 0x000134, 0x007F8D, 0x00093C,
+ 0x281D12, 0x282512, 0x001F32, 0x0E0007,
+ 0x00010D, 0x00037D, 0x000820, 0x018040,
+ 0x05D2F4, 0x000007, 0x080007, 0x00037D,
+ 0x018042, 0x08000A, 0x000904, 0x2D0286,
+ 0x000007, 0x000606, 0x000007, 0x000007,
+ 0x000012, 0x100007, 0x320007, 0x600007,
+ 0x100080, 0x48001A, 0x004904, 0x2D6186,
+ 0x000007, 0x001210, 0x58003A, 0x000145,
+ 0x5C5D04, 0x000007, 0x000080, 0x48001A,
+ 0x004904, 0x2DB186, 0x000007, 0x001210,
+ 0x50003A, 0x005904, 0x2E0886, 0x000045,
+ 0x0000C5, 0x7FFFF5, 0x7FFF7D, 0x07D524,
+ 0x004224, 0x500102, 0x200502, 0x000082,
+ 0x40001A, 0x004104, 0x2E3986, 0x000007,
+ 0x003865, 0x40001A, 0x004020, 0x00104D,
+ 0x04C184, 0x301B86, 0x000040, 0x040007,
+ 0x000165, 0x000145, 0x004020, 0x000040,
+ 0x000765, 0x080080, 0x40001A, 0x004104,
+ 0x2EC986, 0x000007, 0x001210, 0x40003A,
+ 0x004104, 0x2F2286, 0x00004D, 0x0000CD,
+ 0x004810, 0x20043A, 0x000882, 0x40001A,
+ 0x004104, 0x2F3186, 0x000007, 0x004820,
+ 0x005904, 0x300886, 0x000040, 0x0007E5,
+ 0x200480, 0x2816A0, 0x3216E0, 0x3A16E0,
+ 0x4216E0, 0x021260, 0x000040, 0x000032,
+ 0x400075, 0x00007D, 0x07D574, 0x200512,
+ 0x000082, 0x40001A, 0x004104, 0x2FE186,
+ 0x000007, 0x037206, 0x640007, 0x060007,
+ 0x0000E5, 0x000020, 0x000040, 0x000A65,
+ 0x000020, 0x020040, 0x020040, 0x000040,
+ 0x000165, 0x000042, 0x70000A, 0x007104,
+ 0x30A286, 0x000007, 0x018206, 0x640007,
+ 0x050000, 0x007020, 0x000040, 0x037206,
+ 0x640007, 0x000007, 0x00306D, 0x028860,
+ 0x029060, 0x08000A, 0x028860, 0x008040,
+ 0x100012, 0x00100D, 0x009184, 0x314186,
+ 0x000E0D, 0x009184, 0x325186, 0x000007,
+ 0x300007, 0x001020, 0x003B6D, 0x008040,
+ 0x000080, 0x08001A, 0x000904, 0x316186,
+ 0x000007, 0x001220, 0x000DED, 0x008040,
+ 0x008042, 0x10000A, 0x40000D, 0x109544,
+ 0x000007, 0x001020, 0x000DED, 0x008040,
+ 0x008042, 0x20040A, 0x000082, 0x08001A,
+ 0x000904, 0x31F186, 0x000007, 0x003B6D,
+ 0x008042, 0x08000A, 0x000E15, 0x010984,
+ 0x329B86, 0x600007, 0x08001A, 0x000C15,
+ 0x010984, 0x328386, 0x000020, 0x1A0007,
+ 0x0002ED, 0x008040, 0x620007, 0x00306D,
+ 0x028042, 0x0A804A, 0x000820, 0x0A804A,
+ 0x000606, 0x10804A, 0x000007, 0x282512,
+ 0x001F32, 0x05D2F4, 0x54D104, 0x00735C,
+ 0x000786, 0x000007, 0x0C0007, 0x0A0007,
+ 0x1C0007, 0x003465, 0x020040, 0x004820,
+ 0x025060, 0x40000A, 0x024060, 0x000040,
+ 0x454944, 0x000007, 0x004020, 0x003AE5,
+ 0x000040, 0x0028E5, 0x000042, 0x48000A,
+ 0x004904, 0x386886, 0x002C65, 0x000042,
+ 0x40000A, 0x0000D5, 0x454104, 0x000007,
+ 0x000655, 0x054504, 0x34F286, 0x0001D5,
+ 0x054504, 0x34F086, 0x002B65, 0x000042,
+ 0x003AE5, 0x50004A, 0x40000A, 0x45C3D4,
+ 0x000007, 0x454504, 0x000007, 0x0000CD,
+ 0x444944, 0x000007, 0x454504, 0x000007,
+ 0x00014D, 0x554944, 0x000007, 0x045144,
+ 0x34E986, 0x002C65, 0x000042, 0x48000A,
+ 0x4CD104, 0x000007, 0x04C144, 0x34F386,
+ 0x000007, 0x160007, 0x002CE5, 0x040042,
+ 0x40000A, 0x004020, 0x000040, 0x002965,
+ 0x000042, 0x40000A, 0x004104, 0x356086,
+ 0x000007, 0x002402, 0x36A206, 0x005C02,
+ 0x0025E5, 0x000042, 0x40000A, 0x004274,
+ 0x002AE5, 0x000042, 0x40000A, 0x004274,
+ 0x500112, 0x0029E5, 0x000042, 0x40000A,
+ 0x004234, 0x454104, 0x000007, 0x004020,
+ 0x000040, 0x003EE5, 0x000020, 0x000040,
+ 0x002DE5, 0x400152, 0x50000A, 0x045144,
+ 0x364A86, 0x0000C5, 0x003EE5, 0x004020,
+ 0x000040, 0x002BE5, 0x000042, 0x40000A,
+ 0x404254, 0x000007, 0x002AE5, 0x004020,
+ 0x000040, 0x500132, 0x040134, 0x005674,
+ 0x0029E5, 0x020042, 0x42000A, 0x000042,
+ 0x50000A, 0x05417C, 0x0028E5, 0x000042,
+ 0x48000A, 0x0000C5, 0x4CC144, 0x371086,
+ 0x0026E5, 0x0027E5, 0x020042, 0x40004A,
+ 0x50000A, 0x00423C, 0x00567C, 0x0028E5,
+ 0x004820, 0x000040, 0x281D12, 0x282512,
+ 0x001F72, 0x002965, 0x000042, 0x40000A,
+ 0x004104, 0x37AA86, 0x0E0007, 0x160007,
+ 0x1E0007, 0x003EE5, 0x000042, 0x40000A,
+ 0x004104, 0x37E886, 0x002D65, 0x000042,
+ 0x28340A, 0x003465, 0x020042, 0x42004A,
+ 0x004020, 0x4A004A, 0x50004A, 0x05D2F4,
+ 0x54D104, 0x00735C, 0x385186, 0x000007,
+ 0x000606, 0x080007, 0x0C0007, 0x080007,
+ 0x0A0007, 0x0001E5, 0x020045, 0x004020,
+ 0x000060, 0x000365, 0x000040, 0x002E65,
+ 0x001A20, 0x0A1A60, 0x000040, 0x003465,
+ 0x020042, 0x42004A, 0x004020, 0x4A004A,
+ 0x000606, 0x50004A, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000
};
/* --------------------------------------------
-DS-1E Controller InstructionRAM Code
-1999/06/21
-Buf441 slot is Enabled.
---------------------------------------------
-04/09@creat
-04/12 stop nise fix
-06/21@WorkingOff timming
+ DS-1E Controller InstructionRAM Code
+ 1999/06/21
+ Buf441 slot is Enabled.
+ --------------------------------------------
+ 04/09@creat
+ 04/12 stop nise fix
+ 06/21@WorkingOff timming
*/
static u_int32_t CntrlInst1E[] = {
-0x000007, 0x240007, 0x0C0007, 0x1C0007,
-0x060007, 0x700002, 0x000020, 0x030040,
-0x007104, 0x004286, 0x030040, 0x000F0D,
-0x000810, 0x20043A, 0x000282, 0x00020D,
-0x000810, 0x20043A, 0x001282, 0x200E82,
-0x00800D, 0x000810, 0x20043A, 0x001A82,
-0x03460D, 0x000810, 0x10043A, 0x02EC0D,
-0x000810, 0x18043A, 0x00010D, 0x020015,
-0x0000FD, 0x000020, 0x038860, 0x039060,
-0x038060, 0x038040, 0x038040, 0x038040,
-0x018040, 0x000A7D, 0x038040, 0x038040,
-0x018040, 0x200402, 0x000882, 0x08001A,
-0x000904, 0x017186, 0x000007, 0x260007,
-0x400007, 0x000007, 0x03258D, 0x000810,
-0x18043A, 0x260007, 0x284402, 0x00087D,
-0x018042, 0x00160A, 0x05A206, 0x000007,
-0x440007, 0x00230D, 0x000810, 0x08043A,
-0x22FA06, 0x000007, 0x0007FD, 0x018042,
-0x08000A, 0x000904, 0x02AB86, 0x000195,
-0x090D04, 0x000007, 0x000820, 0x0000F5,
-0x000B7D, 0x01F060, 0x0000FD, 0x033A06,
-0x018040, 0x000A7D, 0x038042, 0x13804A,
-0x18000A, 0x001820, 0x059060, 0x058860,
-0x018040, 0x0000FD, 0x018042, 0x70000A,
-0x000115, 0x071144, 0x033B86, 0x030000,
-0x007020, 0x036206, 0x018040, 0x00360D,
-0x000810, 0x08043A, 0x232206, 0x000007,
-0x02EC0D, 0x000810, 0x18043A, 0x019A06,
-0x000007, 0x240007, 0x000F8D, 0x000810,
-0x00163A, 0x002402, 0x005C02, 0x0028FD,
-0x000020, 0x018040, 0x08000D, 0x000815,
-0x510984, 0x000007, 0x00004D, 0x000E5D,
-0x000E02, 0x00430D, 0x000810, 0x08043A,
-0x2E1206, 0x000007, 0x00008D, 0x000924,
-0x000F02, 0x00470D, 0x000810, 0x08043A,
-0x2E1206, 0x000007, 0x480480, 0x001210,
-0x28043A, 0x00778D, 0x000810, 0x280C3A,
-0x00068D, 0x000810, 0x28143A, 0x284402,
-0x03258D, 0x000810, 0x18043A, 0x07FF8D,
-0x000820, 0x0002FD, 0x018040, 0x260007,
-0x200007, 0x0002FD, 0x018042, 0x08000A,
-0x000904, 0x051286, 0x000007, 0x240007,
-0x02EC0D, 0x000810, 0x18043A, 0x00387D,
-0x018042, 0x08000A, 0x001015, 0x010984,
-0x019B86, 0x000007, 0x01B206, 0x000007,
-0x0008FD, 0x018042, 0x18000A, 0x001904,
-0x22B886, 0x280007, 0x001810, 0x28043A,
-0x280C02, 0x00000D, 0x000810, 0x28143A,
-0x08808D, 0x000820, 0x0002FD, 0x018040,
-0x200007, 0x00020D, 0x189904, 0x000007,
-0x00402D, 0x0000BD, 0x0002FD, 0x018042,
-0x08000A, 0x000904, 0x065A86, 0x000007,
-0x000100, 0x000A20, 0x00047D, 0x018040,
-0x018042, 0x20000A, 0x003015, 0x012144,
-0x036186, 0x000007, 0x002104, 0x036186,
-0x000007, 0x000F8D, 0x000810, 0x280C3A,
-0x023944, 0x07C986, 0x000007, 0x001810,
-0x28043A, 0x08810D, 0x000820, 0x0002FD,
-0x018040, 0x200007, 0x002810, 0x78003A,
-0x00788D, 0x000810, 0x08043A, 0x2A1206,
-0x000007, 0x00400D, 0x001015, 0x189904,
-0x292904, 0x393904, 0x000007, 0x070206,
-0x000007, 0x0004F5, 0x00007D, 0x000020,
-0x00008D, 0x010860, 0x018040, 0x00047D,
-0x038042, 0x21804A, 0x18000A, 0x021944,
-0x229086, 0x000007, 0x004075, 0x71F104,
-0x000007, 0x010042, 0x28000A, 0x002904,
-0x225886, 0x000007, 0x003C0D, 0x30A904,
-0x000007, 0x00077D, 0x018042, 0x08000A,
-0x000904, 0x08DA86, 0x00057D, 0x002820,
-0x03B060, 0x08F206, 0x018040, 0x003020,
-0x03A860, 0x018040, 0x0002FD, 0x018042,
-0x08000A, 0x000904, 0x08FA86, 0x000007,
-0x00057D, 0x018042, 0x28040A, 0x000E8D,
-0x000810, 0x280C3A, 0x00000D, 0x000810,
-0x28143A, 0x09000D, 0x000820, 0x0002FD,
-0x018040, 0x200007, 0x003DFD, 0x000020,
-0x018040, 0x00107D, 0x009D8D, 0x000810,
-0x08043A, 0x2A1206, 0x000007, 0x000815,
-0x08001A, 0x010984, 0x0A5186, 0x00137D,
-0x200500, 0x280F20, 0x338F60, 0x3B8F60,
-0x438F60, 0x4B8F60, 0x538F60, 0x5B8F60,
-0x038A60, 0x018040, 0x00107D, 0x018042,
-0x08000A, 0x000215, 0x010984, 0x3A8186,
-0x000007, 0x007FBD, 0x383DC4, 0x000007,
-0x001A7D, 0x001375, 0x018042, 0x09004A,
-0x10000A, 0x0B8D04, 0x139504, 0x000007,
-0x000820, 0x019060, 0x001104, 0x225886,
-0x010040, 0x0017FD, 0x018042, 0x08000A,
-0x000904, 0x225A86, 0x000007, 0x00197D,
-0x038042, 0x09804A, 0x10000A, 0x000924,
-0x001664, 0x0011FD, 0x038042, 0x2B804A,
-0x19804A, 0x00008D, 0x218944, 0x000007,
-0x002244, 0x0C1986, 0x000007, 0x001A64,
-0x002A24, 0x00197D, 0x080102, 0x100122,
-0x000820, 0x039060, 0x018040, 0x003DFD,
-0x00008D, 0x000820, 0x018040, 0x001375,
-0x001A7D, 0x010042, 0x09804A, 0x10000A,
-0x00021D, 0x0189E4, 0x2992E4, 0x309144,
-0x000007, 0x00060D, 0x000A15, 0x000C1D,
-0x001025, 0x00A9E4, 0x012BE4, 0x000464,
-0x01B3E4, 0x0232E4, 0x000464, 0x000464,
-0x000464, 0x000464, 0x00040D, 0x08B1C4,
-0x000007, 0x000820, 0x000BF5, 0x030040,
-0x00197D, 0x038042, 0x09804A, 0x000A24,
-0x08000A, 0x080E64, 0x000007, 0x100122,
-0x000820, 0x031060, 0x010040, 0x0064AC,
-0x00027D, 0x000020, 0x018040, 0x00107D,
-0x018042, 0x0011FD, 0x3B804A, 0x09804A,
-0x20000A, 0x000095, 0x1A1144, 0x00A144,
-0x0E5886, 0x00040D, 0x00B984, 0x0E5986,
-0x0018FD, 0x018042, 0x0010FD, 0x09804A,
-0x28000A, 0x000095, 0x010924, 0x002A64,
-0x0E4986, 0x000007, 0x002904, 0x0E5A86,
-0x000007, 0x0E6206, 0x080002, 0x00008D,
-0x00387D, 0x000820, 0x018040, 0x00127D,
-0x018042, 0x10000A, 0x003904, 0x0F0986,
-0x00080D, 0x7FFFB5, 0x00B984, 0x0ED986,
-0x000025, 0x0FB206, 0x00002D, 0x000015,
-0x00082D, 0x02E00D, 0x000820, 0x0FFA06,
-0x00000D, 0x7F8035, 0x00B984, 0x0FA986,
-0x400025, 0x00008D, 0x110944, 0x000007,
-0x00018D, 0x109504, 0x000007, 0x009164,
-0x000424, 0x000424, 0x000424, 0x100102,
-0x280002, 0x02DF0D, 0x000820, 0x0FFA06,
-0x00018D, 0x00042D, 0x00008D, 0x109504,
-0x000007, 0x00020D, 0x109184, 0x000007,
-0x02DF8D, 0x000820, 0x00008D, 0x0038FD,
-0x018040, 0x003BFD, 0x001020, 0x03A860,
-0x000815, 0x313184, 0x212184, 0x000007,
-0x03B060, 0x03A060, 0x018040, 0x0022FD,
-0x000095, 0x010924, 0x000424, 0x000424,
-0x001264, 0x100102, 0x000820, 0x039060,
-0x018040, 0x001924, 0x010F0D, 0x00397D,
-0x000820, 0x058040, 0x038042, 0x09844A,
-0x000606, 0x08040A, 0x000424, 0x000424,
-0x00117D, 0x018042, 0x08000A, 0x000A24,
-0x280502, 0x280C02, 0x09800D, 0x000820,
-0x0002FD, 0x018040, 0x200007, 0x0022FD,
-0x018042, 0x08000A, 0x000095, 0x280DC4,
-0x011924, 0x00197D, 0x018042, 0x0011FD,
-0x09804A, 0x10000A, 0x0000B5, 0x113144,
-0x0A8D04, 0x000007, 0x080A44, 0x129504,
-0x000007, 0x0023FD, 0x001020, 0x038040,
-0x101244, 0x000007, 0x000820, 0x039060,
-0x018040, 0x0002FD, 0x018042, 0x08000A,
-0x000904, 0x123286, 0x000007, 0x003BFD,
-0x000100, 0x000A10, 0x0B807A, 0x13804A,
-0x090984, 0x000007, 0x000095, 0x013D04,
-0x12B886, 0x10000A, 0x100002, 0x090984,
-0x000007, 0x038042, 0x11804A, 0x090D04,
-0x000007, 0x10000A, 0x090D84, 0x000007,
-0x00257D, 0x000820, 0x018040, 0x00010D,
-0x000810, 0x28143A, 0x00127D, 0x018042,
-0x20000A, 0x00197D, 0x018042, 0x00117D,
-0x31804A, 0x10000A, 0x003124, 0x013B8D,
-0x00397D, 0x000820, 0x058040, 0x038042,
-0x09844A, 0x000606, 0x08040A, 0x300102,
-0x003124, 0x000424, 0x000424, 0x001224,
-0x280502, 0x001A4C, 0x143986, 0x700002,
-0x00002D, 0x030000, 0x00387D, 0x018042,
-0x10000A, 0x146206, 0x002124, 0x0000AD,
-0x100002, 0x00010D, 0x000924, 0x006B24,
-0x014A0D, 0x00397D, 0x000820, 0x058040,
-0x038042, 0x09844A, 0x000606, 0x08040A,
-0x003264, 0x00008D, 0x000A24, 0x001020,
-0x00227D, 0x018040, 0x014F8D, 0x000810,
-0x08043A, 0x2B5A06, 0x000007, 0x002820,
-0x00207D, 0x018040, 0x00117D, 0x038042,
-0x13804A, 0x33800A, 0x00387D, 0x018042,
-0x08000A, 0x000904, 0x177286, 0x000007,
-0x00008D, 0x030964, 0x015B0D, 0x00397D,
-0x000820, 0x058040, 0x038042, 0x09844A,
-0x000606, 0x08040A, 0x380102, 0x000424,
-0x000424, 0x001224, 0x0002FD, 0x018042,
-0x08000A, 0x000904, 0x15DA86, 0x000007,
-0x280502, 0x001A4C, 0x177186, 0x000007,
-0x032164, 0x00632C, 0x003DFD, 0x018042,
-0x08000A, 0x000095, 0x090904, 0x000007,
-0x000820, 0x001A4C, 0x169986, 0x018040,
-0x030000, 0x16B206, 0x002124, 0x00010D,
-0x000924, 0x006B24, 0x016F0D, 0x00397D,
-0x000820, 0x058040, 0x038042, 0x09844A,
-0x000606, 0x08040A, 0x003A64, 0x000095,
-0x001224, 0x0002FD, 0x018042, 0x08000A,
-0x000904, 0x171286, 0x000007, 0x01760D,
-0x000810, 0x08043A, 0x2B5A06, 0x000007,
-0x160A06, 0x000007, 0x007020, 0x08010A,
-0x10012A, 0x0020FD, 0x038860, 0x039060,
-0x018040, 0x00227D, 0x018042, 0x003DFD,
-0x08000A, 0x31844A, 0x000904, 0x181086,
-0x18008B, 0x00008D, 0x189904, 0x00312C,
-0x18E206, 0x000007, 0x00324C, 0x186B86,
-0x000007, 0x001904, 0x186886, 0x000007,
-0x000095, 0x199144, 0x00222C, 0x003124,
-0x00636C, 0x000E3D, 0x001375, 0x000BFD,
-0x010042, 0x09804A, 0x10000A, 0x038AEC,
-0x0393EC, 0x00224C, 0x18E186, 0x000007,
-0x00008D, 0x189904, 0x00226C, 0x00322C,
-0x30050A, 0x301DAB, 0x002083, 0x0018FD,
-0x018042, 0x08000A, 0x018924, 0x300502,
-0x001083, 0x001875, 0x010042, 0x10000A,
-0x00008D, 0x010924, 0x001375, 0x330542,
-0x330CCB, 0x332CCB, 0x3334CB, 0x333CCB,
-0x3344CB, 0x334CCB, 0x3354CB, 0x305C8B,
-0x006083, 0x0002F5, 0x010042, 0x08000A,
-0x000904, 0x19B286, 0x000007, 0x001E2D,
-0x0005FD, 0x018042, 0x08000A, 0x028924,
-0x280502, 0x00060D, 0x000810, 0x280C3A,
-0x00008D, 0x000810, 0x28143A, 0x0A808D,
-0x000820, 0x0002F5, 0x010040, 0x220007,
-0x001275, 0x030042, 0x21004A, 0x00008D,
-0x1A0944, 0x000007, 0x01AB8D, 0x000810,
-0x08043A, 0x2CAA06, 0x000007, 0x0001F5,
-0x030042, 0x0D004A, 0x10000A, 0x089144,
-0x000007, 0x000820, 0x010040, 0x0025F5,
-0x0A3144, 0x000007, 0x000820, 0x032860,
-0x030040, 0x00217D, 0x038042, 0x0B804A,
-0x10000A, 0x000820, 0x031060, 0x030040,
-0x00008D, 0x000124, 0x00012C, 0x000E64,
-0x001A64, 0x00636C, 0x08010A, 0x10012A,
-0x000820, 0x031060, 0x030040, 0x0020FD,
-0x018042, 0x08000A, 0x00227D, 0x018042,
-0x10000A, 0x000820, 0x031060, 0x030040,
-0x00197D, 0x018042, 0x08000A, 0x0022FD,
-0x038042, 0x10000A, 0x000820, 0x031060,
-0x030040, 0x090D04, 0x000007, 0x000820,
-0x030040, 0x038042, 0x0B804A, 0x10000A,
-0x000820, 0x031060, 0x030040, 0x038042,
-0x13804A, 0x19804A, 0x110D04, 0x198D04,
-0x000007, 0x08000A, 0x001020, 0x031860,
-0x030860, 0x030040, 0x00008D, 0x0B0944,
-0x000007, 0x000820, 0x010040, 0x0005F5,
-0x030042, 0x08000A, 0x000820, 0x010040,
-0x0000F5, 0x010042, 0x08000A, 0x000904,
-0x1D9886, 0x001E75, 0x030042, 0x01044A,
-0x000C0A, 0x1DAA06, 0x000007, 0x000402,
-0x000C02, 0x00177D, 0x001AF5, 0x018042,
-0x03144A, 0x031C4A, 0x03244A, 0x032C4A,
-0x03344A, 0x033C4A, 0x03444A, 0x004C0A,
-0x00043D, 0x0013F5, 0x001AFD, 0x030042,
-0x0B004A, 0x1B804A, 0x13804A, 0x20000A,
-0x089144, 0x19A144, 0x0389E4, 0x0399EC,
-0x005502, 0x005D0A, 0x030042, 0x0B004A,
-0x1B804A, 0x13804A, 0x20000A, 0x089144,
-0x19A144, 0x0389E4, 0x0399EC, 0x006502,
-0x006D0A, 0x030042, 0x0B004A, 0x19004A,
-0x2B804A, 0x13804A, 0x21804A, 0x30000A,
-0x089144, 0x19A144, 0x2AB144, 0x0389E4,
-0x0399EC, 0x007502, 0x007D0A, 0x03A9E4,
-0x000702, 0x00107D, 0x000415, 0x018042,
-0x08000A, 0x0109E4, 0x000F02, 0x002AF5,
-0x0019FD, 0x010042, 0x09804A, 0x10000A,
-0x000934, 0x001674, 0x0029F5, 0x010042,
-0x10000A, 0x00917C, 0x002075, 0x010042,
-0x08000A, 0x000904, 0x200A86, 0x0026F5,
-0x0027F5, 0x030042, 0x09004A, 0x10000A,
-0x000A3C, 0x00167C, 0x001A75, 0x000BFD,
-0x010042, 0x51804A, 0x48000A, 0x160007,
-0x001075, 0x010042, 0x282C0A, 0x281D12,
-0x282512, 0x001F32, 0x1E0007, 0x0E0007,
-0x001975, 0x010042, 0x002DF5, 0x0D004A,
-0x10000A, 0x009144, 0x20EA86, 0x010042,
-0x28340A, 0x000E5D, 0x00008D, 0x000375,
-0x000820, 0x010040, 0x05D2F4, 0x54D104,
-0x00735C, 0x218B86, 0x000007, 0x0C0007,
-0x080007, 0x0A0007, 0x02178D, 0x000810,
-0x08043A, 0x34B206, 0x000007, 0x219206,
-0x000007, 0x080007, 0x002275, 0x010042,
-0x20000A, 0x002104, 0x225886, 0x001E2D,
-0x0002F5, 0x010042, 0x08000A, 0x000904,
-0x21CA86, 0x000007, 0x002010, 0x30043A,
-0x00057D, 0x0180C3, 0x08000A, 0x028924,
-0x280502, 0x280C02, 0x0A810D, 0x000820,
-0x0002F5, 0x010040, 0x220007, 0x0004FD,
-0x018042, 0x70000A, 0x030000, 0x007020,
-0x07FA06, 0x018040, 0x022B8D, 0x000810,
-0x08043A, 0x2CAA06, 0x000007, 0x0002FD,
-0x018042, 0x08000A, 0x000904, 0x22C286,
-0x000007, 0x020206, 0x000007, 0x000875,
-0x0009FD, 0x00010D, 0x234206, 0x000295,
-0x000B75, 0x00097D, 0x00000D, 0x000515,
-0x010042, 0x18000A, 0x001904, 0x2A0086,
-0x0006F5, 0x001020, 0x010040, 0x0004F5,
-0x000820, 0x010040, 0x000775, 0x010042,
-0x09804A, 0x10000A, 0x001124, 0x000904,
-0x23F286, 0x000815, 0x080102, 0x101204,
-0x241206, 0x000575, 0x081204, 0x000007,
-0x100102, 0x000575, 0x000425, 0x021124,
-0x100102, 0x000820, 0x031060, 0x010040,
-0x001924, 0x2A0086, 0x00008D, 0x000464,
-0x009D04, 0x291086, 0x180102, 0x000575,
-0x010042, 0x28040A, 0x00018D, 0x000924,
-0x280D02, 0x00000D, 0x000924, 0x281502,
-0x10000D, 0x000820, 0x0002F5, 0x010040,
-0x200007, 0x001175, 0x0002FD, 0x018042,
-0x08000A, 0x000904, 0x24FA86, 0x000007,
-0x000100, 0x080B20, 0x130B60, 0x1B0B60,
-0x030A60, 0x010040, 0x050042, 0x3D004A,
-0x35004A, 0x2D004A, 0x20000A, 0x0006F5,
-0x010042, 0x28140A, 0x0004F5, 0x010042,
-0x08000A, 0x000315, 0x010D04, 0x260286,
-0x004015, 0x000095, 0x010D04, 0x25F086,
-0x100022, 0x10002A, 0x261A06, 0x000007,
-0x333104, 0x2AA904, 0x000007, 0x032124,
-0x280502, 0x284402, 0x001124, 0x400102,
-0x000424, 0x000424, 0x003224, 0x00292C,
-0x00636C, 0x277386, 0x000007, 0x02B164,
-0x000464, 0x000464, 0x00008D, 0x000A64,
-0x280D02, 0x10008D, 0x000820, 0x0002F5,
-0x010040, 0x220007, 0x00008D, 0x38B904,
-0x000007, 0x03296C, 0x30010A, 0x0002F5,
-0x010042, 0x08000A, 0x000904, 0x270286,
-0x000007, 0x00212C, 0x28050A, 0x00316C,
-0x00046C, 0x00046C, 0x28450A, 0x001124,
-0x006B64, 0x100102, 0x00008D, 0x01096C,
-0x280D0A, 0x10010D, 0x000820, 0x0002F5,
-0x010040, 0x220007, 0x004124, 0x000424,
-0x000424, 0x003224, 0x300102, 0x032944,
-0x27FA86, 0x000007, 0x300002, 0x0004F5,
-0x010042, 0x08000A, 0x000315, 0x010D04,
-0x284086, 0x003124, 0x000464, 0x300102,
-0x0002F5, 0x010042, 0x08000A, 0x000904,
-0x284A86, 0x000007, 0x284402, 0x003124,
-0x300502, 0x003924, 0x300583, 0x000883,
-0x0005F5, 0x010042, 0x28040A, 0x00008D,
-0x008124, 0x280D02, 0x00008D, 0x008124,
-0x281502, 0x10018D, 0x000820, 0x0002F5,
-0x010040, 0x220007, 0x001025, 0x000575,
-0x030042, 0x09004A, 0x10000A, 0x0A0904,
-0x121104, 0x000007, 0x001020, 0x050860,
-0x050040, 0x0006FD, 0x018042, 0x09004A,
-0x10000A, 0x0000A5, 0x0A0904, 0x121104,
-0x000007, 0x000820, 0x019060, 0x010040,
-0x0002F5, 0x010042, 0x08000A, 0x000904,
-0x29CA86, 0x000007, 0x244206, 0x000007,
-0x000606, 0x000007, 0x0002F5, 0x010042,
-0x08000A, 0x000904, 0x2A1A86, 0x000007,
-0x000100, 0x080B20, 0x138B60, 0x1B8B60,
-0x238B60, 0x2B8B60, 0x338B60, 0x3B8B60,
-0x438B60, 0x4B8B60, 0x538B60, 0x5B8B60,
-0x638B60, 0x6B8B60, 0x738B60, 0x7B8B60,
-0x038F60, 0x0B8F60, 0x138F60, 0x1B8F60,
-0x238F60, 0x2B8F60, 0x338F60, 0x3B8F60,
-0x438F60, 0x4B8F60, 0x538F60, 0x5B8F60,
-0x638F60, 0x6B8F60, 0x738F60, 0x7B8F60,
-0x038A60, 0x000606, 0x018040, 0x00008D,
-0x000A64, 0x280D02, 0x000A24, 0x00027D,
-0x018042, 0x10000A, 0x001224, 0x0003FD,
-0x018042, 0x08000A, 0x000904, 0x2C0A86,
-0x000007, 0x00018D, 0x000A24, 0x000464,
-0x000464, 0x080102, 0x000924, 0x000424,
-0x000424, 0x100102, 0x02000D, 0x009144,
-0x2C6186, 0x000007, 0x0001FD, 0x018042,
-0x08000A, 0x000A44, 0x2C4386, 0x018042,
-0x0A000D, 0x000820, 0x0002FD, 0x018040,
-0x200007, 0x00027D, 0x001020, 0x000606,
-0x018040, 0x0002F5, 0x010042, 0x08000A,
-0x000904, 0x2CB286, 0x000007, 0x00037D,
-0x018042, 0x08000A, 0x000904, 0x2CE286,
-0x000007, 0x000075, 0x002E7D, 0x010042,
-0x0B804A, 0x000020, 0x000904, 0x000686,
-0x010040, 0x31844A, 0x30048B, 0x000883,
-0x00008D, 0x000810, 0x28143A, 0x00008D,
-0x000810, 0x280C3A, 0x000675, 0x010042,
-0x08000A, 0x003815, 0x010924, 0x280502,
-0x0B000D, 0x000820, 0x0002F5, 0x010040,
-0x000606, 0x220007, 0x000464, 0x000464,
-0x000606, 0x000007, 0x000134, 0x007F8D,
-0x00093C, 0x281D12, 0x282512, 0x001F32,
-0x0E0007, 0x00010D, 0x00037D, 0x000820,
-0x018040, 0x05D2F4, 0x000007, 0x080007,
-0x00037D, 0x018042, 0x08000A, 0x000904,
-0x2E8A86, 0x000007, 0x000606, 0x000007,
-0x000007, 0x000012, 0x100007, 0x320007,
-0x600007, 0x460007, 0x100080, 0x48001A,
-0x004904, 0x2EF186, 0x000007, 0x001210,
-0x58003A, 0x000145, 0x5C5D04, 0x000007,
-0x000080, 0x48001A, 0x004904, 0x2F4186,
-0x000007, 0x001210, 0x50003A, 0x005904,
-0x2F9886, 0x000045, 0x0000C5, 0x7FFFF5,
-0x7FFF7D, 0x07D524, 0x004224, 0x500102,
-0x200502, 0x000082, 0x40001A, 0x004104,
-0x2FC986, 0x000007, 0x003865, 0x40001A,
-0x004020, 0x00104D, 0x04C184, 0x31AB86,
-0x000040, 0x040007, 0x000165, 0x000145,
-0x004020, 0x000040, 0x000765, 0x080080,
-0x40001A, 0x004104, 0x305986, 0x000007,
-0x001210, 0x40003A, 0x004104, 0x30B286,
-0x00004D, 0x0000CD, 0x004810, 0x20043A,
-0x000882, 0x40001A, 0x004104, 0x30C186,
-0x000007, 0x004820, 0x005904, 0x319886,
-0x000040, 0x0007E5, 0x200480, 0x2816A0,
-0x3216E0, 0x3A16E0, 0x4216E0, 0x021260,
-0x000040, 0x000032, 0x400075, 0x00007D,
-0x07D574, 0x200512, 0x000082, 0x40001A,
-0x004104, 0x317186, 0x000007, 0x038A06,
-0x640007, 0x0000E5, 0x000020, 0x000040,
-0x000A65, 0x000020, 0x020040, 0x020040,
-0x000040, 0x000165, 0x000042, 0x70000A,
-0x007104, 0x323286, 0x000007, 0x060007,
-0x019A06, 0x640007, 0x050000, 0x007020,
-0x000040, 0x038A06, 0x640007, 0x000007,
-0x00306D, 0x028860, 0x029060, 0x08000A,
-0x028860, 0x008040, 0x100012, 0x00100D,
-0x009184, 0x32D186, 0x000E0D, 0x009184,
-0x33E186, 0x000007, 0x300007, 0x001020,
-0x003B6D, 0x008040, 0x000080, 0x08001A,
-0x000904, 0x32F186, 0x000007, 0x001220,
-0x000DED, 0x008040, 0x008042, 0x10000A,
-0x40000D, 0x109544, 0x000007, 0x001020,
-0x000DED, 0x008040, 0x008042, 0x20040A,
-0x000082, 0x08001A, 0x000904, 0x338186,
-0x000007, 0x003B6D, 0x008042, 0x08000A,
-0x000E15, 0x010984, 0x342B86, 0x600007,
-0x08001A, 0x000C15, 0x010984, 0x341386,
-0x000020, 0x1A0007, 0x0002ED, 0x008040,
-0x620007, 0x00306D, 0x028042, 0x0A804A,
-0x000820, 0x0A804A, 0x000606, 0x10804A,
-0x000007, 0x282512, 0x001F32, 0x05D2F4,
-0x54D104, 0x00735C, 0x000786, 0x000007,
-0x0C0007, 0x0A0007, 0x1C0007, 0x003465,
-0x020040, 0x004820, 0x025060, 0x40000A,
-0x024060, 0x000040, 0x454944, 0x000007,
-0x004020, 0x003AE5, 0x000040, 0x0028E5,
-0x000042, 0x48000A, 0x004904, 0x39F886,
-0x002C65, 0x000042, 0x40000A, 0x0000D5,
-0x454104, 0x000007, 0x000655, 0x054504,
-0x368286, 0x0001D5, 0x054504, 0x368086,
-0x002B65, 0x000042, 0x003AE5, 0x50004A,
-0x40000A, 0x45C3D4, 0x000007, 0x454504,
-0x000007, 0x0000CD, 0x444944, 0x000007,
-0x454504, 0x000007, 0x00014D, 0x554944,
-0x000007, 0x045144, 0x367986, 0x002C65,
-0x000042, 0x48000A, 0x4CD104, 0x000007,
-0x04C144, 0x368386, 0x000007, 0x160007,
-0x002CE5, 0x040042, 0x40000A, 0x004020,
-0x000040, 0x002965, 0x000042, 0x40000A,
-0x004104, 0x36F086, 0x000007, 0x002402,
-0x383206, 0x005C02, 0x0025E5, 0x000042,
-0x40000A, 0x004274, 0x002AE5, 0x000042,
-0x40000A, 0x004274, 0x500112, 0x0029E5,
-0x000042, 0x40000A, 0x004234, 0x454104,
-0x000007, 0x004020, 0x000040, 0x003EE5,
-0x000020, 0x000040, 0x002DE5, 0x400152,
-0x50000A, 0x045144, 0x37DA86, 0x0000C5,
-0x003EE5, 0x004020, 0x000040, 0x002BE5,
-0x000042, 0x40000A, 0x404254, 0x000007,
-0x002AE5, 0x004020, 0x000040, 0x500132,
-0x040134, 0x005674, 0x0029E5, 0x020042,
-0x42000A, 0x000042, 0x50000A, 0x05417C,
-0x0028E5, 0x000042, 0x48000A, 0x0000C5,
-0x4CC144, 0x38A086, 0x0026E5, 0x0027E5,
-0x020042, 0x40004A, 0x50000A, 0x00423C,
-0x00567C, 0x0028E5, 0x004820, 0x000040,
-0x281D12, 0x282512, 0x001F72, 0x002965,
-0x000042, 0x40000A, 0x004104, 0x393A86,
-0x0E0007, 0x160007, 0x1E0007, 0x003EE5,
-0x000042, 0x40000A, 0x004104, 0x397886,
-0x002D65, 0x000042, 0x28340A, 0x003465,
-0x020042, 0x42004A, 0x004020, 0x4A004A,
-0x50004A, 0x05D2F4, 0x54D104, 0x00735C,
-0x39E186, 0x000007, 0x000606, 0x080007,
-0x0C0007, 0x080007, 0x0A0007, 0x0001E5,
-0x020045, 0x004020, 0x000060, 0x000365,
-0x000040, 0x002E65, 0x001A20, 0x0A1A60,
-0x000040, 0x003465, 0x020042, 0x42004A,
-0x004020, 0x4A004A, 0x000606, 0x50004A,
-0x0017FD, 0x018042, 0x08000A, 0x000904,
-0x225A86, 0x000007, 0x00107D, 0x018042,
-0x0011FD, 0x33804A, 0x19804A, 0x20000A,
-0x000095, 0x2A1144, 0x01A144, 0x3B9086,
-0x00040D, 0x00B184, 0x3B9186, 0x0018FD,
-0x018042, 0x0010FD, 0x09804A, 0x38000A,
-0x000095, 0x010924, 0x003A64, 0x3B8186,
-0x000007, 0x003904, 0x3B9286, 0x000007,
-0x3B9A06, 0x00000D, 0x00008D, 0x000820,
-0x00387D, 0x018040, 0x700002, 0x00117D,
-0x018042, 0x00197D, 0x29804A, 0x30000A,
-0x380002, 0x003124, 0x000424, 0x000424,
-0x002A24, 0x280502, 0x00068D, 0x000810,
-0x28143A, 0x00750D, 0x00B124, 0x002264,
-0x3D0386, 0x284402, 0x000810, 0x280C3A,
-0x0B800D, 0x000820, 0x0002FD, 0x018040,
-0x200007, 0x00758D, 0x00B124, 0x100102,
-0x012144, 0x3E4986, 0x001810, 0x10003A,
-0x00387D, 0x018042, 0x08000A, 0x000904,
-0x3E4886, 0x030000, 0x3E4A06, 0x0000BD,
-0x00008D, 0x023164, 0x000A64, 0x280D02,
-0x0B808D, 0x000820, 0x0002FD, 0x018040,
-0x200007, 0x00387D, 0x018042, 0x08000A,
-0x000904, 0x3E3286, 0x030000, 0x0002FD,
-0x018042, 0x08000A, 0x000904, 0x3D8286,
-0x000007, 0x002810, 0x28043A, 0x00750D,
-0x030924, 0x002264, 0x280D02, 0x02316C,
-0x28450A, 0x0B810D, 0x000820, 0x0002FD,
-0x018040, 0x200007, 0x00008D, 0x000A24,
-0x3E4A06, 0x100102, 0x001810, 0x10003A,
-0x0000BD, 0x003810, 0x30043A, 0x00187D,
-0x018042, 0x0018FD, 0x09804A, 0x20000A,
-0x0000AD, 0x028924, 0x07212C, 0x001010,
-0x300583, 0x300D8B, 0x3014BB, 0x301C83,
-0x002083, 0x00137D, 0x038042, 0x33844A,
-0x33ACCB, 0x33B4CB, 0x33BCCB, 0x33C4CB,
-0x33CCCB, 0x33D4CB, 0x305C8B, 0x006083,
-0x001E0D, 0x0005FD, 0x018042, 0x20000A,
-0x020924, 0x00068D, 0x00A96C, 0x00009D,
-0x0002FD, 0x018042, 0x08000A, 0x000904,
-0x3F6A86, 0x000007, 0x280502, 0x280D0A,
-0x284402, 0x001810, 0x28143A, 0x0C008D,
-0x000820, 0x0002FD, 0x018040, 0x220007,
-0x003904, 0x225886, 0x001E0D, 0x00057D,
-0x018042, 0x20000A, 0x020924, 0x0000A5,
-0x0002FD, 0x018042, 0x08000A, 0x000904,
-0x402A86, 0x000007, 0x280502, 0x280C02,
-0x002010, 0x28143A, 0x0C010D, 0x000820,
-0x0002FD, 0x018040, 0x225A06, 0x220007,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000,
-0x000000, 0x000000, 0x000000, 0x000000
+ 0x000007, 0x240007, 0x0C0007, 0x1C0007,
+ 0x060007, 0x700002, 0x000020, 0x030040,
+ 0x007104, 0x004286, 0x030040, 0x000F0D,
+ 0x000810, 0x20043A, 0x000282, 0x00020D,
+ 0x000810, 0x20043A, 0x001282, 0x200E82,
+ 0x00800D, 0x000810, 0x20043A, 0x001A82,
+ 0x03460D, 0x000810, 0x10043A, 0x02EC0D,
+ 0x000810, 0x18043A, 0x00010D, 0x020015,
+ 0x0000FD, 0x000020, 0x038860, 0x039060,
+ 0x038060, 0x038040, 0x038040, 0x038040,
+ 0x018040, 0x000A7D, 0x038040, 0x038040,
+ 0x018040, 0x200402, 0x000882, 0x08001A,
+ 0x000904, 0x017186, 0x000007, 0x260007,
+ 0x400007, 0x000007, 0x03258D, 0x000810,
+ 0x18043A, 0x260007, 0x284402, 0x00087D,
+ 0x018042, 0x00160A, 0x05A206, 0x000007,
+ 0x440007, 0x00230D, 0x000810, 0x08043A,
+ 0x22FA06, 0x000007, 0x0007FD, 0x018042,
+ 0x08000A, 0x000904, 0x02AB86, 0x000195,
+ 0x090D04, 0x000007, 0x000820, 0x0000F5,
+ 0x000B7D, 0x01F060, 0x0000FD, 0x033A06,
+ 0x018040, 0x000A7D, 0x038042, 0x13804A,
+ 0x18000A, 0x001820, 0x059060, 0x058860,
+ 0x018040, 0x0000FD, 0x018042, 0x70000A,
+ 0x000115, 0x071144, 0x033B86, 0x030000,
+ 0x007020, 0x036206, 0x018040, 0x00360D,
+ 0x000810, 0x08043A, 0x232206, 0x000007,
+ 0x02EC0D, 0x000810, 0x18043A, 0x019A06,
+ 0x000007, 0x240007, 0x000F8D, 0x000810,
+ 0x00163A, 0x002402, 0x005C02, 0x0028FD,
+ 0x000020, 0x018040, 0x08000D, 0x000815,
+ 0x510984, 0x000007, 0x00004D, 0x000E5D,
+ 0x000E02, 0x00430D, 0x000810, 0x08043A,
+ 0x2E1206, 0x000007, 0x00008D, 0x000924,
+ 0x000F02, 0x00470D, 0x000810, 0x08043A,
+ 0x2E1206, 0x000007, 0x480480, 0x001210,
+ 0x28043A, 0x00778D, 0x000810, 0x280C3A,
+ 0x00068D, 0x000810, 0x28143A, 0x284402,
+ 0x03258D, 0x000810, 0x18043A, 0x07FF8D,
+ 0x000820, 0x0002FD, 0x018040, 0x260007,
+ 0x200007, 0x0002FD, 0x018042, 0x08000A,
+ 0x000904, 0x051286, 0x000007, 0x240007,
+ 0x02EC0D, 0x000810, 0x18043A, 0x00387D,
+ 0x018042, 0x08000A, 0x001015, 0x010984,
+ 0x019B86, 0x000007, 0x01B206, 0x000007,
+ 0x0008FD, 0x018042, 0x18000A, 0x001904,
+ 0x22B886, 0x280007, 0x001810, 0x28043A,
+ 0x280C02, 0x00000D, 0x000810, 0x28143A,
+ 0x08808D, 0x000820, 0x0002FD, 0x018040,
+ 0x200007, 0x00020D, 0x189904, 0x000007,
+ 0x00402D, 0x0000BD, 0x0002FD, 0x018042,
+ 0x08000A, 0x000904, 0x065A86, 0x000007,
+ 0x000100, 0x000A20, 0x00047D, 0x018040,
+ 0x018042, 0x20000A, 0x003015, 0x012144,
+ 0x036186, 0x000007, 0x002104, 0x036186,
+ 0x000007, 0x000F8D, 0x000810, 0x280C3A,
+ 0x023944, 0x07C986, 0x000007, 0x001810,
+ 0x28043A, 0x08810D, 0x000820, 0x0002FD,
+ 0x018040, 0x200007, 0x002810, 0x78003A,
+ 0x00788D, 0x000810, 0x08043A, 0x2A1206,
+ 0x000007, 0x00400D, 0x001015, 0x189904,
+ 0x292904, 0x393904, 0x000007, 0x070206,
+ 0x000007, 0x0004F5, 0x00007D, 0x000020,
+ 0x00008D, 0x010860, 0x018040, 0x00047D,
+ 0x038042, 0x21804A, 0x18000A, 0x021944,
+ 0x229086, 0x000007, 0x004075, 0x71F104,
+ 0x000007, 0x010042, 0x28000A, 0x002904,
+ 0x225886, 0x000007, 0x003C0D, 0x30A904,
+ 0x000007, 0x00077D, 0x018042, 0x08000A,
+ 0x000904, 0x08DA86, 0x00057D, 0x002820,
+ 0x03B060, 0x08F206, 0x018040, 0x003020,
+ 0x03A860, 0x018040, 0x0002FD, 0x018042,
+ 0x08000A, 0x000904, 0x08FA86, 0x000007,
+ 0x00057D, 0x018042, 0x28040A, 0x000E8D,
+ 0x000810, 0x280C3A, 0x00000D, 0x000810,
+ 0x28143A, 0x09000D, 0x000820, 0x0002FD,
+ 0x018040, 0x200007, 0x003DFD, 0x000020,
+ 0x018040, 0x00107D, 0x009D8D, 0x000810,
+ 0x08043A, 0x2A1206, 0x000007, 0x000815,
+ 0x08001A, 0x010984, 0x0A5186, 0x00137D,
+ 0x200500, 0x280F20, 0x338F60, 0x3B8F60,
+ 0x438F60, 0x4B8F60, 0x538F60, 0x5B8F60,
+ 0x038A60, 0x018040, 0x00107D, 0x018042,
+ 0x08000A, 0x000215, 0x010984, 0x3A8186,
+ 0x000007, 0x007FBD, 0x383DC4, 0x000007,
+ 0x001A7D, 0x001375, 0x018042, 0x09004A,
+ 0x10000A, 0x0B8D04, 0x139504, 0x000007,
+ 0x000820, 0x019060, 0x001104, 0x225886,
+ 0x010040, 0x0017FD, 0x018042, 0x08000A,
+ 0x000904, 0x225A86, 0x000007, 0x00197D,
+ 0x038042, 0x09804A, 0x10000A, 0x000924,
+ 0x001664, 0x0011FD, 0x038042, 0x2B804A,
+ 0x19804A, 0x00008D, 0x218944, 0x000007,
+ 0x002244, 0x0C1986, 0x000007, 0x001A64,
+ 0x002A24, 0x00197D, 0x080102, 0x100122,
+ 0x000820, 0x039060, 0x018040, 0x003DFD,
+ 0x00008D, 0x000820, 0x018040, 0x001375,
+ 0x001A7D, 0x010042, 0x09804A, 0x10000A,
+ 0x00021D, 0x0189E4, 0x2992E4, 0x309144,
+ 0x000007, 0x00060D, 0x000A15, 0x000C1D,
+ 0x001025, 0x00A9E4, 0x012BE4, 0x000464,
+ 0x01B3E4, 0x0232E4, 0x000464, 0x000464,
+ 0x000464, 0x000464, 0x00040D, 0x08B1C4,
+ 0x000007, 0x000820, 0x000BF5, 0x030040,
+ 0x00197D, 0x038042, 0x09804A, 0x000A24,
+ 0x08000A, 0x080E64, 0x000007, 0x100122,
+ 0x000820, 0x031060, 0x010040, 0x0064AC,
+ 0x00027D, 0x000020, 0x018040, 0x00107D,
+ 0x018042, 0x0011FD, 0x3B804A, 0x09804A,
+ 0x20000A, 0x000095, 0x1A1144, 0x00A144,
+ 0x0E5886, 0x00040D, 0x00B984, 0x0E5986,
+ 0x0018FD, 0x018042, 0x0010FD, 0x09804A,
+ 0x28000A, 0x000095, 0x010924, 0x002A64,
+ 0x0E4986, 0x000007, 0x002904, 0x0E5A86,
+ 0x000007, 0x0E6206, 0x080002, 0x00008D,
+ 0x00387D, 0x000820, 0x018040, 0x00127D,
+ 0x018042, 0x10000A, 0x003904, 0x0F0986,
+ 0x00080D, 0x7FFFB5, 0x00B984, 0x0ED986,
+ 0x000025, 0x0FB206, 0x00002D, 0x000015,
+ 0x00082D, 0x02E00D, 0x000820, 0x0FFA06,
+ 0x00000D, 0x7F8035, 0x00B984, 0x0FA986,
+ 0x400025, 0x00008D, 0x110944, 0x000007,
+ 0x00018D, 0x109504, 0x000007, 0x009164,
+ 0x000424, 0x000424, 0x000424, 0x100102,
+ 0x280002, 0x02DF0D, 0x000820, 0x0FFA06,
+ 0x00018D, 0x00042D, 0x00008D, 0x109504,
+ 0x000007, 0x00020D, 0x109184, 0x000007,
+ 0x02DF8D, 0x000820, 0x00008D, 0x0038FD,
+ 0x018040, 0x003BFD, 0x001020, 0x03A860,
+ 0x000815, 0x313184, 0x212184, 0x000007,
+ 0x03B060, 0x03A060, 0x018040, 0x0022FD,
+ 0x000095, 0x010924, 0x000424, 0x000424,
+ 0x001264, 0x100102, 0x000820, 0x039060,
+ 0x018040, 0x001924, 0x010F0D, 0x00397D,
+ 0x000820, 0x058040, 0x038042, 0x09844A,
+ 0x000606, 0x08040A, 0x000424, 0x000424,
+ 0x00117D, 0x018042, 0x08000A, 0x000A24,
+ 0x280502, 0x280C02, 0x09800D, 0x000820,
+ 0x0002FD, 0x018040, 0x200007, 0x0022FD,
+ 0x018042, 0x08000A, 0x000095, 0x280DC4,
+ 0x011924, 0x00197D, 0x018042, 0x0011FD,
+ 0x09804A, 0x10000A, 0x0000B5, 0x113144,
+ 0x0A8D04, 0x000007, 0x080A44, 0x129504,
+ 0x000007, 0x0023FD, 0x001020, 0x038040,
+ 0x101244, 0x000007, 0x000820, 0x039060,
+ 0x018040, 0x0002FD, 0x018042, 0x08000A,
+ 0x000904, 0x123286, 0x000007, 0x003BFD,
+ 0x000100, 0x000A10, 0x0B807A, 0x13804A,
+ 0x090984, 0x000007, 0x000095, 0x013D04,
+ 0x12B886, 0x10000A, 0x100002, 0x090984,
+ 0x000007, 0x038042, 0x11804A, 0x090D04,
+ 0x000007, 0x10000A, 0x090D84, 0x000007,
+ 0x00257D, 0x000820, 0x018040, 0x00010D,
+ 0x000810, 0x28143A, 0x00127D, 0x018042,
+ 0x20000A, 0x00197D, 0x018042, 0x00117D,
+ 0x31804A, 0x10000A, 0x003124, 0x013B8D,
+ 0x00397D, 0x000820, 0x058040, 0x038042,
+ 0x09844A, 0x000606, 0x08040A, 0x300102,
+ 0x003124, 0x000424, 0x000424, 0x001224,
+ 0x280502, 0x001A4C, 0x143986, 0x700002,
+ 0x00002D, 0x030000, 0x00387D, 0x018042,
+ 0x10000A, 0x146206, 0x002124, 0x0000AD,
+ 0x100002, 0x00010D, 0x000924, 0x006B24,
+ 0x014A0D, 0x00397D, 0x000820, 0x058040,
+ 0x038042, 0x09844A, 0x000606, 0x08040A,
+ 0x003264, 0x00008D, 0x000A24, 0x001020,
+ 0x00227D, 0x018040, 0x014F8D, 0x000810,
+ 0x08043A, 0x2B5A06, 0x000007, 0x002820,
+ 0x00207D, 0x018040, 0x00117D, 0x038042,
+ 0x13804A, 0x33800A, 0x00387D, 0x018042,
+ 0x08000A, 0x000904, 0x177286, 0x000007,
+ 0x00008D, 0x030964, 0x015B0D, 0x00397D,
+ 0x000820, 0x058040, 0x038042, 0x09844A,
+ 0x000606, 0x08040A, 0x380102, 0x000424,
+ 0x000424, 0x001224, 0x0002FD, 0x018042,
+ 0x08000A, 0x000904, 0x15DA86, 0x000007,
+ 0x280502, 0x001A4C, 0x177186, 0x000007,
+ 0x032164, 0x00632C, 0x003DFD, 0x018042,
+ 0x08000A, 0x000095, 0x090904, 0x000007,
+ 0x000820, 0x001A4C, 0x169986, 0x018040,
+ 0x030000, 0x16B206, 0x002124, 0x00010D,
+ 0x000924, 0x006B24, 0x016F0D, 0x00397D,
+ 0x000820, 0x058040, 0x038042, 0x09844A,
+ 0x000606, 0x08040A, 0x003A64, 0x000095,
+ 0x001224, 0x0002FD, 0x018042, 0x08000A,
+ 0x000904, 0x171286, 0x000007, 0x01760D,
+ 0x000810, 0x08043A, 0x2B5A06, 0x000007,
+ 0x160A06, 0x000007, 0x007020, 0x08010A,
+ 0x10012A, 0x0020FD, 0x038860, 0x039060,
+ 0x018040, 0x00227D, 0x018042, 0x003DFD,
+ 0x08000A, 0x31844A, 0x000904, 0x181086,
+ 0x18008B, 0x00008D, 0x189904, 0x00312C,
+ 0x18E206, 0x000007, 0x00324C, 0x186B86,
+ 0x000007, 0x001904, 0x186886, 0x000007,
+ 0x000095, 0x199144, 0x00222C, 0x003124,
+ 0x00636C, 0x000E3D, 0x001375, 0x000BFD,
+ 0x010042, 0x09804A, 0x10000A, 0x038AEC,
+ 0x0393EC, 0x00224C, 0x18E186, 0x000007,
+ 0x00008D, 0x189904, 0x00226C, 0x00322C,
+ 0x30050A, 0x301DAB, 0x002083, 0x0018FD,
+ 0x018042, 0x08000A, 0x018924, 0x300502,
+ 0x001083, 0x001875, 0x010042, 0x10000A,
+ 0x00008D, 0x010924, 0x001375, 0x330542,
+ 0x330CCB, 0x332CCB, 0x3334CB, 0x333CCB,
+ 0x3344CB, 0x334CCB, 0x3354CB, 0x305C8B,
+ 0x006083, 0x0002F5, 0x010042, 0x08000A,
+ 0x000904, 0x19B286, 0x000007, 0x001E2D,
+ 0x0005FD, 0x018042, 0x08000A, 0x028924,
+ 0x280502, 0x00060D, 0x000810, 0x280C3A,
+ 0x00008D, 0x000810, 0x28143A, 0x0A808D,
+ 0x000820, 0x0002F5, 0x010040, 0x220007,
+ 0x001275, 0x030042, 0x21004A, 0x00008D,
+ 0x1A0944, 0x000007, 0x01AB8D, 0x000810,
+ 0x08043A, 0x2CAA06, 0x000007, 0x0001F5,
+ 0x030042, 0x0D004A, 0x10000A, 0x089144,
+ 0x000007, 0x000820, 0x010040, 0x0025F5,
+ 0x0A3144, 0x000007, 0x000820, 0x032860,
+ 0x030040, 0x00217D, 0x038042, 0x0B804A,
+ 0x10000A, 0x000820, 0x031060, 0x030040,
+ 0x00008D, 0x000124, 0x00012C, 0x000E64,
+ 0x001A64, 0x00636C, 0x08010A, 0x10012A,
+ 0x000820, 0x031060, 0x030040, 0x0020FD,
+ 0x018042, 0x08000A, 0x00227D, 0x018042,
+ 0x10000A, 0x000820, 0x031060, 0x030040,
+ 0x00197D, 0x018042, 0x08000A, 0x0022FD,
+ 0x038042, 0x10000A, 0x000820, 0x031060,
+ 0x030040, 0x090D04, 0x000007, 0x000820,
+ 0x030040, 0x038042, 0x0B804A, 0x10000A,
+ 0x000820, 0x031060, 0x030040, 0x038042,
+ 0x13804A, 0x19804A, 0x110D04, 0x198D04,
+ 0x000007, 0x08000A, 0x001020, 0x031860,
+ 0x030860, 0x030040, 0x00008D, 0x0B0944,
+ 0x000007, 0x000820, 0x010040, 0x0005F5,
+ 0x030042, 0x08000A, 0x000820, 0x010040,
+ 0x0000F5, 0x010042, 0x08000A, 0x000904,
+ 0x1D9886, 0x001E75, 0x030042, 0x01044A,
+ 0x000C0A, 0x1DAA06, 0x000007, 0x000402,
+ 0x000C02, 0x00177D, 0x001AF5, 0x018042,
+ 0x03144A, 0x031C4A, 0x03244A, 0x032C4A,
+ 0x03344A, 0x033C4A, 0x03444A, 0x004C0A,
+ 0x00043D, 0x0013F5, 0x001AFD, 0x030042,
+ 0x0B004A, 0x1B804A, 0x13804A, 0x20000A,
+ 0x089144, 0x19A144, 0x0389E4, 0x0399EC,
+ 0x005502, 0x005D0A, 0x030042, 0x0B004A,
+ 0x1B804A, 0x13804A, 0x20000A, 0x089144,
+ 0x19A144, 0x0389E4, 0x0399EC, 0x006502,
+ 0x006D0A, 0x030042, 0x0B004A, 0x19004A,
+ 0x2B804A, 0x13804A, 0x21804A, 0x30000A,
+ 0x089144, 0x19A144, 0x2AB144, 0x0389E4,
+ 0x0399EC, 0x007502, 0x007D0A, 0x03A9E4,
+ 0x000702, 0x00107D, 0x000415, 0x018042,
+ 0x08000A, 0x0109E4, 0x000F02, 0x002AF5,
+ 0x0019FD, 0x010042, 0x09804A, 0x10000A,
+ 0x000934, 0x001674, 0x0029F5, 0x010042,
+ 0x10000A, 0x00917C, 0x002075, 0x010042,
+ 0x08000A, 0x000904, 0x200A86, 0x0026F5,
+ 0x0027F5, 0x030042, 0x09004A, 0x10000A,
+ 0x000A3C, 0x00167C, 0x001A75, 0x000BFD,
+ 0x010042, 0x51804A, 0x48000A, 0x160007,
+ 0x001075, 0x010042, 0x282C0A, 0x281D12,
+ 0x282512, 0x001F32, 0x1E0007, 0x0E0007,
+ 0x001975, 0x010042, 0x002DF5, 0x0D004A,
+ 0x10000A, 0x009144, 0x20EA86, 0x010042,
+ 0x28340A, 0x000E5D, 0x00008D, 0x000375,
+ 0x000820, 0x010040, 0x05D2F4, 0x54D104,
+ 0x00735C, 0x218B86, 0x000007, 0x0C0007,
+ 0x080007, 0x0A0007, 0x02178D, 0x000810,
+ 0x08043A, 0x34B206, 0x000007, 0x219206,
+ 0x000007, 0x080007, 0x002275, 0x010042,
+ 0x20000A, 0x002104, 0x225886, 0x001E2D,
+ 0x0002F5, 0x010042, 0x08000A, 0x000904,
+ 0x21CA86, 0x000007, 0x002010, 0x30043A,
+ 0x00057D, 0x0180C3, 0x08000A, 0x028924,
+ 0x280502, 0x280C02, 0x0A810D, 0x000820,
+ 0x0002F5, 0x010040, 0x220007, 0x0004FD,
+ 0x018042, 0x70000A, 0x030000, 0x007020,
+ 0x07FA06, 0x018040, 0x022B8D, 0x000810,
+ 0x08043A, 0x2CAA06, 0x000007, 0x0002FD,
+ 0x018042, 0x08000A, 0x000904, 0x22C286,
+ 0x000007, 0x020206, 0x000007, 0x000875,
+ 0x0009FD, 0x00010D, 0x234206, 0x000295,
+ 0x000B75, 0x00097D, 0x00000D, 0x000515,
+ 0x010042, 0x18000A, 0x001904, 0x2A0086,
+ 0x0006F5, 0x001020, 0x010040, 0x0004F5,
+ 0x000820, 0x010040, 0x000775, 0x010042,
+ 0x09804A, 0x10000A, 0x001124, 0x000904,
+ 0x23F286, 0x000815, 0x080102, 0x101204,
+ 0x241206, 0x000575, 0x081204, 0x000007,
+ 0x100102, 0x000575, 0x000425, 0x021124,
+ 0x100102, 0x000820, 0x031060, 0x010040,
+ 0x001924, 0x2A0086, 0x00008D, 0x000464,
+ 0x009D04, 0x291086, 0x180102, 0x000575,
+ 0x010042, 0x28040A, 0x00018D, 0x000924,
+ 0x280D02, 0x00000D, 0x000924, 0x281502,
+ 0x10000D, 0x000820, 0x0002F5, 0x010040,
+ 0x200007, 0x001175, 0x0002FD, 0x018042,
+ 0x08000A, 0x000904, 0x24FA86, 0x000007,
+ 0x000100, 0x080B20, 0x130B60, 0x1B0B60,
+ 0x030A60, 0x010040, 0x050042, 0x3D004A,
+ 0x35004A, 0x2D004A, 0x20000A, 0x0006F5,
+ 0x010042, 0x28140A, 0x0004F5, 0x010042,
+ 0x08000A, 0x000315, 0x010D04, 0x260286,
+ 0x004015, 0x000095, 0x010D04, 0x25F086,
+ 0x100022, 0x10002A, 0x261A06, 0x000007,
+ 0x333104, 0x2AA904, 0x000007, 0x032124,
+ 0x280502, 0x284402, 0x001124, 0x400102,
+ 0x000424, 0x000424, 0x003224, 0x00292C,
+ 0x00636C, 0x277386, 0x000007, 0x02B164,
+ 0x000464, 0x000464, 0x00008D, 0x000A64,
+ 0x280D02, 0x10008D, 0x000820, 0x0002F5,
+ 0x010040, 0x220007, 0x00008D, 0x38B904,
+ 0x000007, 0x03296C, 0x30010A, 0x0002F5,
+ 0x010042, 0x08000A, 0x000904, 0x270286,
+ 0x000007, 0x00212C, 0x28050A, 0x00316C,
+ 0x00046C, 0x00046C, 0x28450A, 0x001124,
+ 0x006B64, 0x100102, 0x00008D, 0x01096C,
+ 0x280D0A, 0x10010D, 0x000820, 0x0002F5,
+ 0x010040, 0x220007, 0x004124, 0x000424,
+ 0x000424, 0x003224, 0x300102, 0x032944,
+ 0x27FA86, 0x000007, 0x300002, 0x0004F5,
+ 0x010042, 0x08000A, 0x000315, 0x010D04,
+ 0x284086, 0x003124, 0x000464, 0x300102,
+ 0x0002F5, 0x010042, 0x08000A, 0x000904,
+ 0x284A86, 0x000007, 0x284402, 0x003124,
+ 0x300502, 0x003924, 0x300583, 0x000883,
+ 0x0005F5, 0x010042, 0x28040A, 0x00008D,
+ 0x008124, 0x280D02, 0x00008D, 0x008124,
+ 0x281502, 0x10018D, 0x000820, 0x0002F5,
+ 0x010040, 0x220007, 0x001025, 0x000575,
+ 0x030042, 0x09004A, 0x10000A, 0x0A0904,
+ 0x121104, 0x000007, 0x001020, 0x050860,
+ 0x050040, 0x0006FD, 0x018042, 0x09004A,
+ 0x10000A, 0x0000A5, 0x0A0904, 0x121104,
+ 0x000007, 0x000820, 0x019060, 0x010040,
+ 0x0002F5, 0x010042, 0x08000A, 0x000904,
+ 0x29CA86, 0x000007, 0x244206, 0x000007,
+ 0x000606, 0x000007, 0x0002F5, 0x010042,
+ 0x08000A, 0x000904, 0x2A1A86, 0x000007,
+ 0x000100, 0x080B20, 0x138B60, 0x1B8B60,
+ 0x238B60, 0x2B8B60, 0x338B60, 0x3B8B60,
+ 0x438B60, 0x4B8B60, 0x538B60, 0x5B8B60,
+ 0x638B60, 0x6B8B60, 0x738B60, 0x7B8B60,
+ 0x038F60, 0x0B8F60, 0x138F60, 0x1B8F60,
+ 0x238F60, 0x2B8F60, 0x338F60, 0x3B8F60,
+ 0x438F60, 0x4B8F60, 0x538F60, 0x5B8F60,
+ 0x638F60, 0x6B8F60, 0x738F60, 0x7B8F60,
+ 0x038A60, 0x000606, 0x018040, 0x00008D,
+ 0x000A64, 0x280D02, 0x000A24, 0x00027D,
+ 0x018042, 0x10000A, 0x001224, 0x0003FD,
+ 0x018042, 0x08000A, 0x000904, 0x2C0A86,
+ 0x000007, 0x00018D, 0x000A24, 0x000464,
+ 0x000464, 0x080102, 0x000924, 0x000424,
+ 0x000424, 0x100102, 0x02000D, 0x009144,
+ 0x2C6186, 0x000007, 0x0001FD, 0x018042,
+ 0x08000A, 0x000A44, 0x2C4386, 0x018042,
+ 0x0A000D, 0x000820, 0x0002FD, 0x018040,
+ 0x200007, 0x00027D, 0x001020, 0x000606,
+ 0x018040, 0x0002F5, 0x010042, 0x08000A,
+ 0x000904, 0x2CB286, 0x000007, 0x00037D,
+ 0x018042, 0x08000A, 0x000904, 0x2CE286,
+ 0x000007, 0x000075, 0x002E7D, 0x010042,
+ 0x0B804A, 0x000020, 0x000904, 0x000686,
+ 0x010040, 0x31844A, 0x30048B, 0x000883,
+ 0x00008D, 0x000810, 0x28143A, 0x00008D,
+ 0x000810, 0x280C3A, 0x000675, 0x010042,
+ 0x08000A, 0x003815, 0x010924, 0x280502,
+ 0x0B000D, 0x000820, 0x0002F5, 0x010040,
+ 0x000606, 0x220007, 0x000464, 0x000464,
+ 0x000606, 0x000007, 0x000134, 0x007F8D,
+ 0x00093C, 0x281D12, 0x282512, 0x001F32,
+ 0x0E0007, 0x00010D, 0x00037D, 0x000820,
+ 0x018040, 0x05D2F4, 0x000007, 0x080007,
+ 0x00037D, 0x018042, 0x08000A, 0x000904,
+ 0x2E8A86, 0x000007, 0x000606, 0x000007,
+ 0x000007, 0x000012, 0x100007, 0x320007,
+ 0x600007, 0x460007, 0x100080, 0x48001A,
+ 0x004904, 0x2EF186, 0x000007, 0x001210,
+ 0x58003A, 0x000145, 0x5C5D04, 0x000007,
+ 0x000080, 0x48001A, 0x004904, 0x2F4186,
+ 0x000007, 0x001210, 0x50003A, 0x005904,
+ 0x2F9886, 0x000045, 0x0000C5, 0x7FFFF5,
+ 0x7FFF7D, 0x07D524, 0x004224, 0x500102,
+ 0x200502, 0x000082, 0x40001A, 0x004104,
+ 0x2FC986, 0x000007, 0x003865, 0x40001A,
+ 0x004020, 0x00104D, 0x04C184, 0x31AB86,
+ 0x000040, 0x040007, 0x000165, 0x000145,
+ 0x004020, 0x000040, 0x000765, 0x080080,
+ 0x40001A, 0x004104, 0x305986, 0x000007,
+ 0x001210, 0x40003A, 0x004104, 0x30B286,
+ 0x00004D, 0x0000CD, 0x004810, 0x20043A,
+ 0x000882, 0x40001A, 0x004104, 0x30C186,
+ 0x000007, 0x004820, 0x005904, 0x319886,
+ 0x000040, 0x0007E5, 0x200480, 0x2816A0,
+ 0x3216E0, 0x3A16E0, 0x4216E0, 0x021260,
+ 0x000040, 0x000032, 0x400075, 0x00007D,
+ 0x07D574, 0x200512, 0x000082, 0x40001A,
+ 0x004104, 0x317186, 0x000007, 0x038A06,
+ 0x640007, 0x0000E5, 0x000020, 0x000040,
+ 0x000A65, 0x000020, 0x020040, 0x020040,
+ 0x000040, 0x000165, 0x000042, 0x70000A,
+ 0x007104, 0x323286, 0x000007, 0x060007,
+ 0x019A06, 0x640007, 0x050000, 0x007020,
+ 0x000040, 0x038A06, 0x640007, 0x000007,
+ 0x00306D, 0x028860, 0x029060, 0x08000A,
+ 0x028860, 0x008040, 0x100012, 0x00100D,
+ 0x009184, 0x32D186, 0x000E0D, 0x009184,
+ 0x33E186, 0x000007, 0x300007, 0x001020,
+ 0x003B6D, 0x008040, 0x000080, 0x08001A,
+ 0x000904, 0x32F186, 0x000007, 0x001220,
+ 0x000DED, 0x008040, 0x008042, 0x10000A,
+ 0x40000D, 0x109544, 0x000007, 0x001020,
+ 0x000DED, 0x008040, 0x008042, 0x20040A,
+ 0x000082, 0x08001A, 0x000904, 0x338186,
+ 0x000007, 0x003B6D, 0x008042, 0x08000A,
+ 0x000E15, 0x010984, 0x342B86, 0x600007,
+ 0x08001A, 0x000C15, 0x010984, 0x341386,
+ 0x000020, 0x1A0007, 0x0002ED, 0x008040,
+ 0x620007, 0x00306D, 0x028042, 0x0A804A,
+ 0x000820, 0x0A804A, 0x000606, 0x10804A,
+ 0x000007, 0x282512, 0x001F32, 0x05D2F4,
+ 0x54D104, 0x00735C, 0x000786, 0x000007,
+ 0x0C0007, 0x0A0007, 0x1C0007, 0x003465,
+ 0x020040, 0x004820, 0x025060, 0x40000A,
+ 0x024060, 0x000040, 0x454944, 0x000007,
+ 0x004020, 0x003AE5, 0x000040, 0x0028E5,
+ 0x000042, 0x48000A, 0x004904, 0x39F886,
+ 0x002C65, 0x000042, 0x40000A, 0x0000D5,
+ 0x454104, 0x000007, 0x000655, 0x054504,
+ 0x368286, 0x0001D5, 0x054504, 0x368086,
+ 0x002B65, 0x000042, 0x003AE5, 0x50004A,
+ 0x40000A, 0x45C3D4, 0x000007, 0x454504,
+ 0x000007, 0x0000CD, 0x444944, 0x000007,
+ 0x454504, 0x000007, 0x00014D, 0x554944,
+ 0x000007, 0x045144, 0x367986, 0x002C65,
+ 0x000042, 0x48000A, 0x4CD104, 0x000007,
+ 0x04C144, 0x368386, 0x000007, 0x160007,
+ 0x002CE5, 0x040042, 0x40000A, 0x004020,
+ 0x000040, 0x002965, 0x000042, 0x40000A,
+ 0x004104, 0x36F086, 0x000007, 0x002402,
+ 0x383206, 0x005C02, 0x0025E5, 0x000042,
+ 0x40000A, 0x004274, 0x002AE5, 0x000042,
+ 0x40000A, 0x004274, 0x500112, 0x0029E5,
+ 0x000042, 0x40000A, 0x004234, 0x454104,
+ 0x000007, 0x004020, 0x000040, 0x003EE5,
+ 0x000020, 0x000040, 0x002DE5, 0x400152,
+ 0x50000A, 0x045144, 0x37DA86, 0x0000C5,
+ 0x003EE5, 0x004020, 0x000040, 0x002BE5,
+ 0x000042, 0x40000A, 0x404254, 0x000007,
+ 0x002AE5, 0x004020, 0x000040, 0x500132,
+ 0x040134, 0x005674, 0x0029E5, 0x020042,
+ 0x42000A, 0x000042, 0x50000A, 0x05417C,
+ 0x0028E5, 0x000042, 0x48000A, 0x0000C5,
+ 0x4CC144, 0x38A086, 0x0026E5, 0x0027E5,
+ 0x020042, 0x40004A, 0x50000A, 0x00423C,
+ 0x00567C, 0x0028E5, 0x004820, 0x000040,
+ 0x281D12, 0x282512, 0x001F72, 0x002965,
+ 0x000042, 0x40000A, 0x004104, 0x393A86,
+ 0x0E0007, 0x160007, 0x1E0007, 0x003EE5,
+ 0x000042, 0x40000A, 0x004104, 0x397886,
+ 0x002D65, 0x000042, 0x28340A, 0x003465,
+ 0x020042, 0x42004A, 0x004020, 0x4A004A,
+ 0x50004A, 0x05D2F4, 0x54D104, 0x00735C,
+ 0x39E186, 0x000007, 0x000606, 0x080007,
+ 0x0C0007, 0x080007, 0x0A0007, 0x0001E5,
+ 0x020045, 0x004020, 0x000060, 0x000365,
+ 0x000040, 0x002E65, 0x001A20, 0x0A1A60,
+ 0x000040, 0x003465, 0x020042, 0x42004A,
+ 0x004020, 0x4A004A, 0x000606, 0x50004A,
+ 0x0017FD, 0x018042, 0x08000A, 0x000904,
+ 0x225A86, 0x000007, 0x00107D, 0x018042,
+ 0x0011FD, 0x33804A, 0x19804A, 0x20000A,
+ 0x000095, 0x2A1144, 0x01A144, 0x3B9086,
+ 0x00040D, 0x00B184, 0x3B9186, 0x0018FD,
+ 0x018042, 0x0010FD, 0x09804A, 0x38000A,
+ 0x000095, 0x010924, 0x003A64, 0x3B8186,
+ 0x000007, 0x003904, 0x3B9286, 0x000007,
+ 0x3B9A06, 0x00000D, 0x00008D, 0x000820,
+ 0x00387D, 0x018040, 0x700002, 0x00117D,
+ 0x018042, 0x00197D, 0x29804A, 0x30000A,
+ 0x380002, 0x003124, 0x000424, 0x000424,
+ 0x002A24, 0x280502, 0x00068D, 0x000810,
+ 0x28143A, 0x00750D, 0x00B124, 0x002264,
+ 0x3D0386, 0x284402, 0x000810, 0x280C3A,
+ 0x0B800D, 0x000820, 0x0002FD, 0x018040,
+ 0x200007, 0x00758D, 0x00B124, 0x100102,
+ 0x012144, 0x3E4986, 0x001810, 0x10003A,
+ 0x00387D, 0x018042, 0x08000A, 0x000904,
+ 0x3E4886, 0x030000, 0x3E4A06, 0x0000BD,
+ 0x00008D, 0x023164, 0x000A64, 0x280D02,
+ 0x0B808D, 0x000820, 0x0002FD, 0x018040,
+ 0x200007, 0x00387D, 0x018042, 0x08000A,
+ 0x000904, 0x3E3286, 0x030000, 0x0002FD,
+ 0x018042, 0x08000A, 0x000904, 0x3D8286,
+ 0x000007, 0x002810, 0x28043A, 0x00750D,
+ 0x030924, 0x002264, 0x280D02, 0x02316C,
+ 0x28450A, 0x0B810D, 0x000820, 0x0002FD,
+ 0x018040, 0x200007, 0x00008D, 0x000A24,
+ 0x3E4A06, 0x100102, 0x001810, 0x10003A,
+ 0x0000BD, 0x003810, 0x30043A, 0x00187D,
+ 0x018042, 0x0018FD, 0x09804A, 0x20000A,
+ 0x0000AD, 0x028924, 0x07212C, 0x001010,
+ 0x300583, 0x300D8B, 0x3014BB, 0x301C83,
+ 0x002083, 0x00137D, 0x038042, 0x33844A,
+ 0x33ACCB, 0x33B4CB, 0x33BCCB, 0x33C4CB,
+ 0x33CCCB, 0x33D4CB, 0x305C8B, 0x006083,
+ 0x001E0D, 0x0005FD, 0x018042, 0x20000A,
+ 0x020924, 0x00068D, 0x00A96C, 0x00009D,
+ 0x0002FD, 0x018042, 0x08000A, 0x000904,
+ 0x3F6A86, 0x000007, 0x280502, 0x280D0A,
+ 0x284402, 0x001810, 0x28143A, 0x0C008D,
+ 0x000820, 0x0002FD, 0x018040, 0x220007,
+ 0x003904, 0x225886, 0x001E0D, 0x00057D,
+ 0x018042, 0x20000A, 0x020924, 0x0000A5,
+ 0x0002FD, 0x018042, 0x08000A, 0x000904,
+ 0x402A86, 0x000007, 0x280502, 0x280C02,
+ 0x002010, 0x28143A, 0x0C010D, 0x000820,
+ 0x0002FD, 0x018040, 0x225A06, 0x220007,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000
};
#endif
Index: via8233.c
===================================================================
RCS file: /home/cvs/src/sys/dev/sound/pci/via8233.c,v
retrieving revision 1.3
retrieving revision 1.4
diff -L sys/dev/sound/pci/via8233.c -L sys/dev/sound/pci/via8233.c -u -r1.3 -r1.4
--- sys/dev/sound/pci/via8233.c
+++ sys/dev/sound/pci/via8233.c
@@ -1,39 +1,39 @@
/*-
-* Copyright (c) 2002 Orion Hodson <orion at freebsd.org>
-* Portions of this code derived from via82c686.c:
-* Copyright (c) 2000 David Jones <dej at ox.org>
-* All rights reserved.
-*
-* Redistribution and use in source and binary forms, with or without
-* modification, are permitted provided that the following conditions
-* are met:
-* 1. Redistributions of source code must retain the above copyright
-* notice, this list of conditions and the following disclaimer.
-* 2. Redistributions in binary form must reproduce the above copyright
-* notice, this list of conditions and the following disclaimer in the
-* documentation and/or other materials provided with the distribution.
-*
-* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
-* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
-* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
-* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
-* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
-* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
-* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
-* SUCH DAMAGE.
-*/
+ * Copyright (c) 2002 Orion Hodson <orion at freebsd.org>
+ * Portions of this code derived from via82c686.c:
+ * Copyright (c) 2000 David Jones <dej at ox.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
/*
-* Credits due to:
-*
-* Grzybowski Rafal, Russell Davies, Mark Handley, Daniel O'Connor for
-* comments, machine time, testing patches, and patience. VIA for
-* providing specs. ALSA for helpful comments and some register poke
-* ordering.
-*/
+ * Credits due to:
+ *
+ * Grzybowski Rafal, Russell Davies, Mark Handley, Daniel O'Connor for
+ * comments, machine time, testing patches, and patience. VIA for
+ * providing specs. ALSA for helpful comments and some register poke
+ * ordering.
+ */
#include <dev/sound/pcm/sound.h>
#include <dev/sound/pcm/ac97.h>
@@ -44,7 +44,7 @@
#include <dev/sound/pci/via8233.h>
-SND_DECLARE_FILE("$MidnightBSD$");
+SND_DECLARE_FILE("$FreeBSD: src/sys/dev/sound/pci/via8233.c,v 1.37 2007/06/14 11:13:38 ariff Exp $");
#define VIA8233_PCI_ID 0x30591106
@@ -62,13 +62,18 @@
#define NWRCHANS 1 /* No of write channels */
#define NCHANS (NWRCHANS + NDXSCHANS + NMSGDCHANS)
#define NSEGS NCHANS * SEGS_PER_CHAN /* Segments in SGD table */
+#define VIA_SEGS_MIN 2
+#define VIA_SEGS_MAX 64
+#define VIA_SEGS_DEFAULT 2
+#define VIA_BLK_MIN 32
+#define VIA_BLK_ALIGN (~(VIA_BLK_MIN - 1))
#define VIA_DEFAULT_BUFSZ 0x1000
/* we rely on this struct being packed to 64 bits */
struct via_dma_op {
-volatile u_int32_t ptr;
-volatile u_int32_t flags;
+ volatile uint32_t ptr;
+ volatile uint32_t flags;
#define VIA_DMAOP_EOL 0x80000000
#define VIA_DMAOP_FLAG 0x40000000
#define VIA_DMAOP_STOP 0x20000000
@@ -78,163 +83,224 @@
struct via_info;
struct via_chinfo {
-struct via_info *parent;
-struct pcm_channel *channel;
-struct snd_dbuf *buffer;
-struct via_dma_op *sgd_table;
-bus_addr_t sgd_addr;
-int dir, blksz;
-int rbase;
+ struct via_info *parent;
+ struct pcm_channel *channel;
+ struct snd_dbuf *buffer;
+ struct via_dma_op *sgd_table;
+ bus_addr_t sgd_addr;
+ int dir, rbase, active;
+ unsigned int blksz, blkcnt;
+ unsigned int ptr, prevptr;
};
struct via_info {
-bus_space_tag_t st;
-bus_space_handle_t sh;
-bus_dma_tag_t parent_dmat;
-bus_dma_tag_t sgd_dmat;
-bus_dmamap_t sgd_dmamap;
-bus_addr_t sgd_addr;
-
-struct resource *reg, *irq;
-int regid, irqid;
-void *ih;
-struct ac97_info *codec;
-
-unsigned int bufsz;
-int dxs_src, dma_eol_wake;
-
-struct via_chinfo pch[NDXSCHANS + NMSGDCHANS];
-struct via_chinfo rch[NWRCHANS];
-struct via_dma_op *sgd_table;
-u_int16_t codec_caps;
-u_int16_t n_dxs_registered;
-struct mtx *lock;
+ device_t dev;
+
+ bus_space_tag_t st;
+ bus_space_handle_t sh;
+ bus_dma_tag_t parent_dmat;
+ bus_dma_tag_t sgd_dmat;
+ bus_dmamap_t sgd_dmamap;
+ bus_addr_t sgd_addr;
+
+ struct resource *reg, *irq;
+ int regid, irqid;
+ void *ih;
+ struct ac97_info *codec;
+
+ unsigned int bufsz, blkcnt;
+ int dxs_src, dma_eol_wake;
+
+ struct via_chinfo pch[NDXSCHANS + NMSGDCHANS];
+ struct via_chinfo rch[NWRCHANS];
+ struct via_dma_op *sgd_table;
+ uint16_t codec_caps;
+ uint16_t n_dxs_registered;
+ int play_num, rec_num;
+ struct mtx *lock;
+ struct callout poll_timer;
+ int poll_ticks, polling;
};
-static u_int32_t via_fmt[] = {
-AFMT_U8,
-AFMT_STEREO | AFMT_U8,
-AFMT_S16_LE,
-AFMT_STEREO | AFMT_S16_LE,
-0
+static uint32_t via_fmt[] = {
+ AFMT_U8,
+ AFMT_STEREO | AFMT_U8,
+ AFMT_S16_LE,
+ AFMT_STEREO | AFMT_S16_LE,
+ 0
};
static struct pcmchan_caps via_vracaps = { 4000, 48000, via_fmt, 0 };
static struct pcmchan_caps via_caps = { 48000, 48000, via_fmt, 0 };
+static __inline int
+via_chan_active(struct via_info *via)
+{
+ int i, ret = 0;
+
+ if (via == NULL)
+ return (0);
+
+ for (i = 0; i < NDXSCHANS + NMSGDCHANS; i++)
+ ret += via->pch[i].active;
+
+ for (i = 0; i < NWRCHANS; i++)
+ ret += via->rch[i].active;
+
+ return (ret);
+}
+
#ifdef SND_DYNSYSCTL
static int
sysctl_via8233_spdif_enable(SYSCTL_HANDLER_ARGS)
{
-struct via_info *via;
-device_t dev;
-uint32_t r;
-int err, new_en;
-
-dev = oidp->oid_arg1;
-via = pcm_getdevinfo(dev);
-snd_mtxlock(via->lock);
-r = pci_read_config(dev, VIA_PCI_SPDIF, 1);
-snd_mtxunlock(via->lock);
-new_en = (r & VIA_SPDIF_EN) ? 1 : 0;
-err = sysctl_handle_int(oidp, &new_en, sizeof(new_en), req);
-
-if (err || req->newptr == NULL)
-return err;
-if (new_en < 0 || new_en > 1)
-return EINVAL;
-
-if (new_en)
-r |= VIA_SPDIF_EN;
-else
-r &= ~VIA_SPDIF_EN;
-snd_mtxlock(via->lock);
-pci_write_config(dev, VIA_PCI_SPDIF, r, 1);
-snd_mtxunlock(via->lock);
+ struct via_info *via;
+ device_t dev;
+ uint32_t r;
+ int err, new_en;
+
+ dev = oidp->oid_arg1;
+ via = pcm_getdevinfo(dev);
+ snd_mtxlock(via->lock);
+ r = pci_read_config(dev, VIA_PCI_SPDIF, 1);
+ snd_mtxunlock(via->lock);
+ new_en = (r & VIA_SPDIF_EN) ? 1 : 0;
+ err = sysctl_handle_int(oidp, &new_en, 0, req);
+
+ if (err || req->newptr == NULL)
+ return (err);
+ if (new_en < 0 || new_en > 1)
+ return (EINVAL);
+
+ if (new_en)
+ r |= VIA_SPDIF_EN;
+ else
+ r &= ~VIA_SPDIF_EN;
+ snd_mtxlock(via->lock);
+ pci_write_config(dev, VIA_PCI_SPDIF, r, 1);
+ snd_mtxunlock(via->lock);
-return 0;
+ return (0);
}
-#if 0
static int
sysctl_via8233_dxs_src(SYSCTL_HANDLER_ARGS)
{
-struct via_info *via;
-device_t dev;
-int err, val;
-
-dev = oidp->oid_arg1;
-via = pcm_getdevinfo(dev);
-snd_mtxlock(via->lock);
-val = via->dxs_src;
-snd_mtxunlock(via->lock);
-err = sysctl_handle_int(oidp, &val, sizeof(val), req);
-
-if (err || req->newptr == NULL)
-return err;
-if (val < 0 || val > 1)
-return EINVAL;
-
-snd_mtxlock(via->lock);
-via->dxs_src = val;
-snd_mtxunlock(via->lock);
+ struct via_info *via;
+ device_t dev;
+ int err, val;
+
+ dev = oidp->oid_arg1;
+ via = pcm_getdevinfo(dev);
+ snd_mtxlock(via->lock);
+ val = via->dxs_src;
+ snd_mtxunlock(via->lock);
+ err = sysctl_handle_int(oidp, &val, 0, req);
+
+ if (err || req->newptr == NULL)
+ return (err);
+ if (val < 0 || val > 1)
+ return (EINVAL);
+
+ snd_mtxlock(via->lock);
+ via->dxs_src = val;
+ snd_mtxunlock(via->lock);
-return 0;
+ return (0);
+}
+
+static int
+sysctl_via_polling(SYSCTL_HANDLER_ARGS)
+{
+ struct via_info *via;
+ device_t dev;
+ int err, val;
+
+ dev = oidp->oid_arg1;
+ via = pcm_getdevinfo(dev);
+ if (via == NULL)
+ return (EINVAL);
+ snd_mtxlock(via->lock);
+ val = via->polling;
+ snd_mtxunlock(via->lock);
+ err = sysctl_handle_int(oidp, &val, 0, req);
+
+ if (err || req->newptr == NULL)
+ return (err);
+ if (val < 0 || val > 1)
+ return (EINVAL);
+
+ snd_mtxlock(via->lock);
+ if (val != via->polling) {
+ if (via_chan_active(via) != 0)
+ err = EBUSY;
+ else if (val == 0)
+ via->polling = 0;
+ else
+ via->polling = 1;
+ }
+ snd_mtxunlock(via->lock);
+
+ return (err);
}
-#endif
#endif /* SND_DYNSYSCTL */
static void
via_init_sysctls(device_t dev)
{
#ifdef SND_DYNSYSCTL
-SYSCTL_ADD_PROC(snd_sysctl_tree(dev),
-SYSCTL_CHILDREN(snd_sysctl_tree_top(dev)),
-OID_AUTO, "spdif_enabled",
-CTLTYPE_INT | CTLFLAG_RW, dev, sizeof(dev),
-sysctl_via8233_spdif_enable, "I",
-"Enable S/PDIF output on primary playback channel");
-#if 0
-SYSCTL_ADD_PROC(snd_sysctl_tree(dev),
-SYSCTL_CHILDREN(snd_sysctl_tree_top(dev)),
-OID_AUTO, "via_dxs_src",
-CTLTYPE_INT | CTLFLAG_RW, dev, sizeof(dev),
-sysctl_via8233_dxs_src, "I",
-"Enable VIA DXS Sample Rate Converter");
-#endif
+ /* XXX: an user should be able to set this with a control tool,
+ if not done before 7.0-RELEASE, this needs to be converted to
+ a device specific sysctl "dev.pcm.X.yyy" via device_get_sysctl_*()
+ as discussed on multimedia@ in msg-id <861wujij2q.fsf at xps.des.no> */
+ SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev),
+ SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO,
+ "spdif_enabled", CTLTYPE_INT | CTLFLAG_RW, dev, sizeof(dev),
+ sysctl_via8233_spdif_enable, "I",
+ "Enable S/PDIF output on primary playback channel");
+ SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev),
+ SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO,
+ "dxs_src", CTLTYPE_INT | CTLFLAG_RW, dev, sizeof(dev),
+ sysctl_via8233_dxs_src, "I",
+ "Enable VIA DXS Sample Rate Converter");
+ SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev),
+ SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO,
+ "polling", CTLTYPE_INT | CTLFLAG_RW, dev, sizeof(dev),
+ sysctl_via_polling, "I",
+ "Enable polling mode");
#endif
}
-static __inline u_int32_t
+static __inline uint32_t
via_rd(struct via_info *via, int regno, int size)
{
-switch (size) {
-case 1:
-return bus_space_read_1(via->st, via->sh, regno);
-case 2:
-return bus_space_read_2(via->st, via->sh, regno);
-case 4:
-return bus_space_read_4(via->st, via->sh, regno);
-default:
-return 0xFFFFFFFF;
-}
+ switch (size) {
+ case 1:
+ return (bus_space_read_1(via->st, via->sh, regno));
+ case 2:
+ return (bus_space_read_2(via->st, via->sh, regno));
+ case 4:
+ return (bus_space_read_4(via->st, via->sh, regno));
+ default:
+ return (0xFFFFFFFF);
+ }
}
static __inline void
-via_wr(struct via_info *via, int regno, u_int32_t data, int size)
+via_wr(struct via_info *via, int regno, uint32_t data, int size)
{
-switch (size) {
-case 1:
-bus_space_write_1(via->st, via->sh, regno, data);
-break;
-case 2:
-bus_space_write_2(via->st, via->sh, regno, data);
-break;
-case 4:
-bus_space_write_4(via->st, via->sh, regno, data);
-break;
-}
+ switch (size) {
+ case 1:
+ bus_space_write_1(via->st, via->sh, regno, data);
+ break;
+ case 2:
+ bus_space_write_2(via->st, via->sh, regno, data);
+ break;
+ case 4:
+ bus_space_write_4(via->st, via->sh, regno, data);
+ break;
+ }
}
/* -------------------------------------------------------------------- */
@@ -243,71 +309,72 @@
static int
via_waitready_codec(struct via_info *via)
{
-int i;
+ int i;
-/* poll until codec not busy */
-for (i = 0; i < 1000; i++) {
-if ((via_rd(via, VIA_AC97_CONTROL, 4) & VIA_AC97_BUSY) == 0)
-return 0;
-DELAY(1);
-}
-printf("via: codec busyn");
-return 1;
+ /* poll until codec not busy */
+ for (i = 0; i < 1000; i++) {
+ if ((via_rd(via, VIA_AC97_CONTROL, 4) & VIA_AC97_BUSY) == 0)
+ return (0);
+ DELAY(1);
+ }
+ device_printf(via->dev, "%s: codec busy\n", __func__);
+ return (1);
}
static int
via_waitvalid_codec(struct via_info *via)
{
-int i;
+ int i;
-/* poll until codec valid */
-for (i = 0; i < 1000; i++) {
-if (via_rd(via, VIA_AC97_CONTROL, 4) & VIA_AC97_CODEC00_VALID)
-return 0;
-DELAY(1);
-}
-printf("via: codec invalidn");
-return 1;
+ /* poll until codec valid */
+ for (i = 0; i < 1000; i++) {
+ if (via_rd(via, VIA_AC97_CONTROL, 4) & VIA_AC97_CODEC00_VALID)
+ return (0);
+ DELAY(1);
+ }
+ device_printf(via->dev, "%s: codec invalid\n", __func__);
+ return (1);
}
static int
-via_write_codec(kobj_t obj, void *addr, int reg, u_int32_t val)
+via_write_codec(kobj_t obj, void *addr, int reg, uint32_t val)
{
-struct via_info *via = addr;
+ struct via_info *via = addr;
-if (via_waitready_codec(via)) return -1;
+ if (via_waitready_codec(via))
+ return (-1);
-via_wr(via, VIA_AC97_CONTROL,
-VIA_AC97_CODEC00_VALID | VIA_AC97_INDEX(reg) |
-VIA_AC97_DATA(val), 4);
+ via_wr(via, VIA_AC97_CONTROL,
+ VIA_AC97_CODEC00_VALID | VIA_AC97_INDEX(reg) |
+ VIA_AC97_DATA(val), 4);
-return 0;
+ return (0);
}
static int
via_read_codec(kobj_t obj, void *addr, int reg)
{
-struct via_info *via = addr;
+ struct via_info *via = addr;
-if (via_waitready_codec(via))
-return -1;
+ if (via_waitready_codec(via))
+ return (-1);
-via_wr(via, VIA_AC97_CONTROL, VIA_AC97_CODEC00_VALID |
-VIA_AC97_READ | VIA_AC97_INDEX(reg), 4);
+ via_wr(via, VIA_AC97_CONTROL, VIA_AC97_CODEC00_VALID |
+ VIA_AC97_READ | VIA_AC97_INDEX(reg), 4);
-if (via_waitready_codec(via))
-return -1;
+ if (via_waitready_codec(via))
+ return (-1);
-if (via_waitvalid_codec(via))
-return -1;
+ if (via_waitvalid_codec(via))
+ return (-1);
-return via_rd(via, VIA_AC97_CONTROL, 2);
+ return (via_rd(via, VIA_AC97_CONTROL, 2));
}
static kobj_method_t via_ac97_methods[] = {
-KOBJMETHOD(ac97_read, via_read_codec),
-KOBJMETHOD(ac97_write, via_write_codec),
-{ 0, 0 }
+ KOBJMETHOD(ac97_read, via_read_codec),
+ KOBJMETHOD(ac97_write, via_write_codec),
+ { 0, 0 }
};
AC97_DECLARE(via_ac97);
@@ -316,135 +383,134 @@
static int
via_buildsgdt(struct via_chinfo *ch)
{
-u_int32_t phys_addr, flag;
-int i, seg_size;
+ uint32_t phys_addr, flag;
+ int i;
-seg_size = sndbuf_getsize(ch->buffer) / SEGS_PER_CHAN;
-phys_addr = sndbuf_getbufaddr(ch->buffer);
+ phys_addr = sndbuf_getbufaddr(ch->buffer);
-for (i = 0; i < SEGS_PER_CHAN; i++) {
-flag = (i == SEGS_PER_CHAN - 1) ? VIA_DMAOP_EOL : VIA_DMAOP_FLAG;
-ch->sgd_table[i].ptr = phys_addr + (i * seg_size);
-ch->sgd_table[i].flags = flag | seg_size;
-}
+ for (i = 0; i < ch->blkcnt; i++) {
+ flag = (i == ch->blkcnt - 1) ? VIA_DMAOP_EOL : VIA_DMAOP_FLAG;
+ ch->sgd_table[i].ptr = phys_addr + (i * ch->blksz);
+ ch->sgd_table[i].flags = flag | ch->blksz;
+ }
-return 0;
+ return (0);
}
/* -------------------------------------------------------------------- */
/* Format setting functions */
static int
-via8233wr_setformat(kobj_t obj, void *data, u_int32_t format)
+via8233wr_setformat(kobj_t obj, void *data, uint32_t format)
{
-struct via_chinfo *ch = data;
-struct via_info *via = ch->parent;
+ struct via_chinfo *ch = data;
+ struct via_info *via = ch->parent;
-u_int32_t f = WR_FORMAT_STOP_INDEX;
+ uint32_t f = WR_FORMAT_STOP_INDEX;
-if (format & AFMT_STEREO)
-f |= WR_FORMAT_STEREO;
-if (format & AFMT_S16_LE)
-f |= WR_FORMAT_16BIT;
-snd_mtxlock(via->lock);
-via_wr(via, VIA_WR0_FORMAT, f, 4);
-snd_mtxunlock(via->lock);
+ if (format & AFMT_STEREO)
+ f |= WR_FORMAT_STEREO;
+ if (format & AFMT_S16_LE)
+ f |= WR_FORMAT_16BIT;
+ snd_mtxlock(via->lock);
+ via_wr(via, VIA_WR0_FORMAT, f, 4);
+ snd_mtxunlock(via->lock);
-return 0;
+ return (0);
}
static int
-via8233dxs_setformat(kobj_t obj, void *data, u_int32_t format)
+via8233dxs_setformat(kobj_t obj, void *data, uint32_t format)
{
-struct via_chinfo *ch = data;
-struct via_info *via = ch->parent;
-u_int32_t r, v;
-
-r = ch->rbase + VIA8233_RP_DXS_RATEFMT;
-snd_mtxlock(via->lock);
-v = via_rd(via, r, 4);
+ struct via_chinfo *ch = data;
+ struct via_info *via = ch->parent;
+ uint32_t r, v;
+
+ r = ch->rbase + VIA8233_RP_DXS_RATEFMT;
+ snd_mtxlock(via->lock);
+ v = via_rd(via, r, 4);
+
+ v &= ~(VIA8233_DXS_RATEFMT_STEREO | VIA8233_DXS_RATEFMT_16BIT);
+ if (format & AFMT_STEREO)
+ v |= VIA8233_DXS_RATEFMT_STEREO;
+ if (format & AFMT_16BIT)
+ v |= VIA8233_DXS_RATEFMT_16BIT;
+ via_wr(via, r, v, 4);
+ snd_mtxunlock(via->lock);
-v &= ~(VIA8233_DXS_RATEFMT_STEREO | VIA8233_DXS_RATEFMT_16BIT);
-if (format & AFMT_STEREO)
-v |= VIA8233_DXS_RATEFMT_STEREO;
-if (format & AFMT_16BIT)
-v |= VIA8233_DXS_RATEFMT_16BIT;
-via_wr(via, r, v, 4);
-snd_mtxunlock(via->lock);
-
-return 0;
+ return (0);
}
static int
-via8233msgd_setformat(kobj_t obj, void *data, u_int32_t format)
+via8233msgd_setformat(kobj_t obj, void *data, uint32_t format)
{
-struct via_chinfo *ch = data;
-struct via_info *via = ch->parent;
+ struct via_chinfo *ch = data;
+ struct via_info *via = ch->parent;
-u_int32_t s = 0xff000000;
-u_int8_t v = (format & AFMT_S16_LE) ? MC_SGD_16BIT : MC_SGD_8BIT;
+ uint32_t s = 0xff000000;
+ uint8_t v = (format & AFMT_S16_LE) ? MC_SGD_16BIT : MC_SGD_8BIT;
-if (format & AFMT_STEREO) {
-v |= MC_SGD_CHANNELS(2);
-s |= SLOT3(1) | SLOT4(2);
-} else {
-v |= MC_SGD_CHANNELS(1);
-s |= SLOT3(1) | SLOT4(1);
-}
+ if (format & AFMT_STEREO) {
+ v |= MC_SGD_CHANNELS(2);
+ s |= SLOT3(1) | SLOT4(2);
+ } else {
+ v |= MC_SGD_CHANNELS(1);
+ s |= SLOT3(1) | SLOT4(1);
+ }
+
+ snd_mtxlock(via->lock);
+ via_wr(via, VIA_MC_SLOT_SELECT, s, 4);
+ via_wr(via, VIA_MC_SGD_FORMAT, v, 1);
+ snd_mtxunlock(via->lock);
-snd_mtxlock(via->lock);
-via_wr(via, VIA_MC_SLOT_SELECT, s, 4);
-via_wr(via, VIA_MC_SGD_FORMAT, v, 1);
-snd_mtxunlock(via->lock);
-
-return 0;
+ return (0);
}
/* -------------------------------------------------------------------- */
/* Speed setting functions */
static int
-via8233wr_setspeed(kobj_t obj, void *data, u_int32_t speed)
+via8233wr_setspeed(kobj_t obj, void *data, uint32_t speed)
{
-struct via_chinfo *ch = data;
-struct via_info *via = ch->parent;
+ struct via_chinfo *ch = data;
+ struct via_info *via = ch->parent;
-if (via->codec_caps & AC97_EXTCAP_VRA)
-return ac97_setrate(via->codec, AC97_REGEXT_LADCRATE, speed);
+ if (via->codec_caps & AC97_EXTCAP_VRA)
+ return (ac97_setrate(via->codec, AC97_REGEXT_LADCRATE, speed));
-return 48000;
+ return (48000);
}
static int
-via8233dxs_setspeed(kobj_t obj, void *data, u_int32_t speed)
+via8233dxs_setspeed(kobj_t obj, void *data, uint32_t speed)
{
-struct via_chinfo *ch = data;
-struct via_info *via = ch->parent;
-u_int32_t r, v;
+ struct via_chinfo *ch = data;
+ struct via_info *via = ch->parent;
+ uint32_t r, v;
-r = ch->rbase + VIA8233_RP_DXS_RATEFMT;
-snd_mtxlock(via->lock);
-v = via_rd(via, r, 4) & ~VIA8233_DXS_RATEFMT_48K;
+ r = ch->rbase + VIA8233_RP_DXS_RATEFMT;
+ snd_mtxlock(via->lock);
+ v = via_rd(via, r, 4) & ~VIA8233_DXS_RATEFMT_48K;
-/* Careful to avoid overflow (divide by 48 per vt8233c docs) */
+ /* Careful to avoid overflow (divide by 48 per vt8233c docs) */
-v |= VIA8233_DXS_RATEFMT_48K * (speed / 48) / (48000 / 48);
-via_wr(via, r, v, 4);
-snd_mtxunlock(via->lock);
+ v |= VIA8233_DXS_RATEFMT_48K * (speed / 48) / (48000 / 48);
+ via_wr(via, r, v, 4);
+ snd_mtxunlock(via->lock);
-return speed;
+ return (speed);
}
static int
-via8233msgd_setspeed(kobj_t obj, void *data, u_int32_t speed)
+via8233msgd_setspeed(kobj_t obj, void *data, uint32_t speed)
{
-struct via_chinfo *ch = data;
-struct via_info *via = ch->parent;
+ struct via_chinfo *ch = data;
+ struct via_info *via = ch->parent;
-if (via->codec_caps & AC97_EXTCAP_VRA)
-return ac97_setrate(via->codec, AC97_REGEXT_FDACRATE, speed);
+ if (via->codec_caps & AC97_EXTCAP_VRA)
+ return (ac97_setrate(via->codec, AC97_REGEXT_FDACRATE, speed));
-return 48000;
+ return (48000);
}
/* -------------------------------------------------------------------- */
@@ -453,83 +519,128 @@
static struct pcmchan_caps *
via8233wr_getcaps(kobj_t obj, void *data)
{
-struct via_chinfo *ch = data;
-struct via_info *via = ch->parent;
+ struct via_chinfo *ch = data;
+ struct via_info *via = ch->parent;
-/* Controlled by ac97 registers */
-if (via->codec_caps & AC97_EXTCAP_VRA)
-return &via_vracaps;
-return &via_caps;
+ /* Controlled by ac97 registers */
+ if (via->codec_caps & AC97_EXTCAP_VRA)
+ return (&via_vracaps);
+ return (&via_caps);
}
static struct pcmchan_caps *
via8233dxs_getcaps(kobj_t obj, void *data)
{
-struct via_chinfo *ch = data;
-struct via_info *via = ch->parent;
+ struct via_chinfo *ch = data;
+ struct via_info *via = ch->parent;
-/*
-* Controlled by onboard registers
-*
-* Apparently, few boards can do DXS sample rate
-* conversion.
-*/
-if (via->dxs_src)
-return &via_vracaps;
-return &via_caps;
+ /*
+ * Controlled by onboard registers
+ *
+ * Apparently, few boards can do DXS sample rate
+ * conversion.
+ */
+ if (via->dxs_src)
+ return (&via_vracaps);
+ return (&via_caps);
}
static struct pcmchan_caps *
via8233msgd_getcaps(kobj_t obj, void *data)
{
-struct via_chinfo *ch = data;
-struct via_info *via = ch->parent;
+ struct via_chinfo *ch = data;
+ struct via_info *via = ch->parent;
-/* Controlled by ac97 registers */
-if (via->codec_caps & AC97_EXTCAP_VRA)
-return &via_vracaps;
-return &via_caps;
+ /* Controlled by ac97 registers */
+ if (via->codec_caps & AC97_EXTCAP_VRA)
+ return (&via_vracaps);
+ return (&via_caps);
}
/* -------------------------------------------------------------------- */
/* Common functions */
static int
-via8233chan_setblocksize(kobj_t obj, void *data, u_int32_t blocksize)
+via8233chan_setfragments(kobj_t obj, void *data,
+ uint32_t blksz, uint32_t blkcnt)
+{
+ struct via_chinfo *ch = data;
+ struct via_info *via = ch->parent;
+
+ blksz &= VIA_BLK_ALIGN;
+
+ if (blksz > (sndbuf_getmaxsize(ch->buffer) / VIA_SEGS_MIN))
+ blksz = sndbuf_getmaxsize(ch->buffer) / VIA_SEGS_MIN;
+ if (blksz < VIA_BLK_MIN)
+ blksz = VIA_BLK_MIN;
+ if (blkcnt > VIA_SEGS_MAX)
+ blkcnt = VIA_SEGS_MAX;
+ if (blkcnt < VIA_SEGS_MIN)
+ blkcnt = VIA_SEGS_MIN;
+
+ while ((blksz * blkcnt) > sndbuf_getmaxsize(ch->buffer)) {
+ if ((blkcnt >> 1) >= VIA_SEGS_MIN)
+ blkcnt >>= 1;
+ else if ((blksz >> 1) >= VIA_BLK_MIN)
+ blksz >>= 1;
+ else
+ break;
+ }
+
+ if ((sndbuf_getblksz(ch->buffer) != blksz ||
+ sndbuf_getblkcnt(ch->buffer) != blkcnt) &&
+ sndbuf_resize(ch->buffer, blkcnt, blksz) != 0)
+ device_printf(via->dev, "%s: failed blksz=%u blkcnt=%u\n",
+ __func__, blksz, blkcnt);
+
+ ch->blksz = sndbuf_getblksz(ch->buffer);
+ ch->blkcnt = sndbuf_getblkcnt(ch->buffer);
+
+ return (1);
+}
+
+static int
+via8233chan_setblocksize(kobj_t obj, void *data, uint32_t blksz)
{
-struct via_chinfo *ch = data;
+ struct via_chinfo *ch = data;
+ struct via_info *via = ch->parent;
+
+ via8233chan_setfragments(obj, data, blksz, via->blkcnt);
-sndbuf_resize(ch->buffer, SEGS_PER_CHAN, blocksize);
-ch->blksz = sndbuf_getblksz(ch->buffer);
-return ch->blksz;
+ return (ch->blksz);
}
static int
via8233chan_getptr(kobj_t obj, void *data)
{
-struct via_chinfo *ch = data;
-struct via_info *via = ch->parent;
-u_int32_t v, index, count;
-int ptr;
-
-snd_mtxlock(via->lock);
-v = via_rd(via, ch->rbase + VIA_RP_CURRENT_COUNT, 4);
-snd_mtxunlock(via->lock);
-index = v >> 24; /* Last completed buffer */
-count = v & 0x00ffffff; /* Bytes remaining */
-ptr = (index + 1) * ch->blksz - count;
-ptr %= SEGS_PER_CHAN * ch->blksz; /* Wrap to available space */
+ struct via_chinfo *ch = data;
+ struct via_info *via = ch->parent;
+ uint32_t v, index, count;
+ int ptr;
+
+ snd_mtxlock(via->lock);
+ if (via->polling != 0) {
+ ptr = ch->ptr;
+ snd_mtxunlock(via->lock);
+ } else {
+ v = via_rd(via, ch->rbase + VIA_RP_CURRENT_COUNT, 4);
+ snd_mtxunlock(via->lock);
+ index = v >> 24; /* Last completed buffer */
+ count = v & 0x00ffffff; /* Bytes remaining */
+ ptr = (index + 1) * ch->blksz - count;
+ ptr %= ch->blkcnt * ch->blksz; /* Wrap to available space */
+ }
-return ptr;
+ return (ptr);
}
static void
via8233chan_reset(struct via_info *via, struct via_chinfo *ch)
{
-via_wr(via, ch->rbase + VIA_RP_CONTROL, SGD_CONTROL_STOP, 1);
-via_wr(via, ch->rbase + VIA_RP_CONTROL, 0x00, 1);
-via_wr(via, ch->rbase + VIA_RP_STATUS,
-SGD_STATUS_EOL | SGD_STATUS_FLAG, 1);
+ via_wr(via, ch->rbase + VIA_RP_CONTROL, SGD_CONTROL_STOP, 1);
+ via_wr(via, ch->rbase + VIA_RP_CONTROL, 0x00, 1);
+ via_wr(via, ch->rbase + VIA_RP_STATUS,
+ SGD_STATUS_EOL | SGD_STATUS_FLAG, 1);
}
/* -------------------------------------------------------------------- */
@@ -538,171 +649,358 @@
static void
via8233chan_sgdinit(struct via_info *via, struct via_chinfo *ch, int chnum)
{
-ch->sgd_table = &via->sgd_table[chnum * SEGS_PER_CHAN];
-ch->sgd_addr = via->sgd_addr + chnum * SEGS_PER_CHAN * sizeof(struct via_dma_op);
+ ch->sgd_table = &via->sgd_table[chnum * VIA_SEGS_MAX];
+ ch->sgd_addr = via->sgd_addr + chnum * VIA_SEGS_MAX *
+ sizeof(struct via_dma_op);
}
static void*
via8233wr_init(kobj_t obj, void *devinfo, struct snd_dbuf *b,
-struct pcm_channel *c, int dir)
+ struct pcm_channel *c, int dir)
{
-struct via_info *via = devinfo;
-struct via_chinfo *ch = &via->rch[c->num];
+ struct via_info *via = devinfo;
+ struct via_chinfo *ch;
+ int num;
+
+ snd_mtxlock(via->lock);
+ num = via->rec_num++;
+ ch = &via->rch[num];
+ ch->parent = via;
+ ch->channel = c;
+ ch->buffer = b;
+ ch->dir = dir;
+ ch->blkcnt = via->blkcnt;
+ ch->rbase = VIA_WR_BASE(num);
+ via_wr(via, ch->rbase + VIA_WR_RP_SGD_FORMAT, WR_FIFO_ENABLE, 1);
+ snd_mtxunlock(via->lock);
+
+ if (sndbuf_alloc(ch->buffer, via->parent_dmat, 0, via->bufsz) != 0)
+ return (NULL);
+
+ snd_mtxlock(via->lock);
+ via8233chan_sgdinit(via, ch, num);
+ via8233chan_reset(via, ch);
+ snd_mtxunlock(via->lock);
-ch->parent = via;
-ch->channel = c;
-ch->buffer = b;
-ch->dir = dir;
-
-ch->rbase = VIA_WR_BASE(c->num);
-snd_mtxlock(via->lock);
-via_wr(via, ch->rbase + VIA_WR_RP_SGD_FORMAT, WR_FIFO_ENABLE, 1);
-snd_mtxunlock(via->lock);
-
-if (sndbuf_alloc(ch->buffer, via->parent_dmat, via->bufsz) != 0)
-return NULL;
-
-snd_mtxlock(via->lock);
-via8233chan_sgdinit(via, ch, c->num);
-via8233chan_reset(via, ch);
-snd_mtxunlock(via->lock);
-
-return ch;
+ return (ch);
}
static void*
via8233dxs_init(kobj_t obj, void *devinfo, struct snd_dbuf *b,
-struct pcm_channel *c, int dir)
+ struct pcm_channel *c, int dir)
{
-struct via_info *via = devinfo;
-struct via_chinfo *ch = &via->pch[c->num];
-
-ch->parent = via;
-ch->channel = c;
-ch->buffer = b;
-ch->dir = dir;
+ struct via_info *via = devinfo;
+ struct via_chinfo *ch;
+ int num;
+
+ snd_mtxlock(via->lock);
+ num = via->play_num++;
+ ch = &via->pch[num];
+ ch->parent = via;
+ ch->channel = c;
+ ch->buffer = b;
+ ch->dir = dir;
+ ch->blkcnt = via->blkcnt;
+
+ /*
+ * All cards apparently support DXS3, but not other DXS
+ * channels. We therefore want to align first DXS channel to
+ * DXS3.
+ */
+ ch->rbase = VIA_DXS_BASE(NDXSCHANS - 1 - via->n_dxs_registered);
+ via->n_dxs_registered++;
+ snd_mtxunlock(via->lock);
+
+ if (sndbuf_alloc(ch->buffer, via->parent_dmat, 0, via->bufsz) != 0)
+ return (NULL);
+
+ snd_mtxlock(via->lock);
+ via8233chan_sgdinit(via, ch, NWRCHANS + num);
+ via8233chan_reset(via, ch);
+ snd_mtxunlock(via->lock);
-/*
-* All cards apparently support DXS3, but not other DXS
-* channels. We therefore want to align first DXS channel to
-* DXS3.
-*/
-snd_mtxlock(via->lock);
-ch->rbase = VIA_DXS_BASE(NDXSCHANS - 1 - via->n_dxs_registered);
-via->n_dxs_registered++;
-snd_mtxunlock(via->lock);
-
-if (sndbuf_alloc(ch->buffer, via->parent_dmat, via->bufsz) != 0)
-return NULL;
-
-snd_mtxlock(via->lock);
-via8233chan_sgdinit(via, ch, NWRCHANS + c->num);
-via8233chan_reset(via, ch);
-snd_mtxunlock(via->lock);
-
-return ch;
+ return (ch);
}
static void*
via8233msgd_init(kobj_t obj, void *devinfo, struct snd_dbuf *b,
-struct pcm_channel *c, int dir)
+ struct pcm_channel *c, int dir)
{
-struct via_info *via = devinfo;
-struct via_chinfo *ch = &via->pch[c->num];
-
-ch->parent = via;
-ch->channel = c;
-ch->buffer = b;
-ch->dir = dir;
-ch->rbase = VIA_MC_SGD_STATUS;
-
-if (sndbuf_alloc(ch->buffer, via->parent_dmat, via->bufsz) != 0)
-return NULL;
-
-snd_mtxlock(via->lock);
-via8233chan_sgdinit(via, ch, NWRCHANS + c->num);
-via8233chan_reset(via, ch);
-snd_mtxunlock(via->lock);
+ struct via_info *via = devinfo;
+ struct via_chinfo *ch;
+ int num;
+
+ snd_mtxlock(via->lock);
+ num = via->play_num++;
+ ch = &via->pch[num];
+ ch->parent = via;
+ ch->channel = c;
+ ch->buffer = b;
+ ch->dir = dir;
+ ch->rbase = VIA_MC_SGD_STATUS;
+ ch->blkcnt = via->blkcnt;
+ snd_mtxunlock(via->lock);
+
+ if (sndbuf_alloc(ch->buffer, via->parent_dmat, 0, via->bufsz) != 0)
+ return (NULL);
+
+ snd_mtxlock(via->lock);
+ via8233chan_sgdinit(via, ch, NWRCHANS + num);
+ via8233chan_reset(via, ch);
+ snd_mtxunlock(via->lock);
-return ch;
+ return (ch);
}
static void
via8233chan_mute(struct via_info *via, struct via_chinfo *ch, int muted)
{
-if (BASE_IS_VIA_DXS_REG(ch->rbase)) {
-int r;
-muted = (muted) ? VIA8233_DXS_MUTE : 0;
-via_wr(via, ch->rbase + VIA8233_RP_DXS_LVOL, muted, 1);
-via_wr(via, ch->rbase + VIA8233_RP_DXS_RVOL, muted, 1);
-r = via_rd(via, ch->rbase + VIA8233_RP_DXS_LVOL, 1) & VIA8233_DXS_MUTE;
-if (r != muted) {
-printf("via: failed to set dxs volume "
-"(dxs base 0x%02x).n", ch->rbase);
-}
+ if (BASE_IS_VIA_DXS_REG(ch->rbase)) {
+ int r;
+ muted = (muted) ? VIA8233_DXS_MUTE : 0;
+ via_wr(via, ch->rbase + VIA8233_RP_DXS_LVOL, muted, 1);
+ via_wr(via, ch->rbase + VIA8233_RP_DXS_RVOL, muted, 1);
+ r = via_rd(via, ch->rbase + VIA8233_RP_DXS_LVOL, 1) &
+ VIA8233_DXS_MUTE;
+ if (r != muted)
+ device_printf(via->dev,
+ "%s: failed to set dxs volume "
+ "(dxs base 0x%02x).\n", __func__, ch->rbase);
+ }
+}
+
+static __inline int
+via_poll_channel(struct via_chinfo *ch)
+{
+ struct via_info *via;
+ uint32_t sz, delta;
+ uint32_t v, index, count;
+ int ptr;
+
+ if (ch == NULL || ch->channel == NULL || ch->active == 0)
+ return (0);
+
+ via = ch->parent;
+ sz = ch->blksz * ch->blkcnt;
+ v = via_rd(via, ch->rbase + VIA_RP_CURRENT_COUNT, 4);
+ index = v >> 24;
+ count = v & 0x00ffffff;
+ ptr = ((index + 1) * ch->blksz) - count;
+ ptr %= sz;
+ ptr &= ~(ch->blksz - 1);
+ ch->ptr = ptr;
+ delta = (sz + ptr - ch->prevptr) % sz;
+
+ if (delta < ch->blksz)
+ return (0);
+
+ ch->prevptr = ptr;
+
+ return (1);
}
+
+static void
+via_poll_callback(void *arg)
+{
+ struct via_info *via = arg;
+ uint32_t ptrigger = 0, rtrigger = 0;
+ int i;
+
+ if (via == NULL)
+ return;
+
+ snd_mtxlock(via->lock);
+ if (via->polling == 0 || via_chan_active(via) == 0) {
+ snd_mtxunlock(via->lock);
+ return;
+ }
+
+ for (i = 0; i < NDXSCHANS + NMSGDCHANS; i++)
+ ptrigger |= (via_poll_channel(&via->pch[i]) != 0) ?
+ (1 << i) : 0;
+
+ for (i = 0; i < NWRCHANS; i++)
+ rtrigger |= (via_poll_channel(&via->rch[i]) != 0) ?
+ (1 << i) : 0;
+
+ /* XXX */
+ callout_reset(&via->poll_timer, 1/*via->poll_ticks*/,
+ via_poll_callback, via);
+
+ snd_mtxunlock(via->lock);
+
+ for (i = 0; i < NDXSCHANS + NMSGDCHANS; i++) {
+ if (ptrigger & (1 << i))
+ chn_intr(via->pch[i].channel);
+ }
+ for (i = 0; i < NWRCHANS; i++) {
+ if (rtrigger & (1 << i))
+ chn_intr(via->rch[i].channel);
+ }
}
static int
-via8233chan_trigger(kobj_t obj, void* data, int go)
+via_poll_ticks(struct via_info *via)
{
-struct via_chinfo *ch = data;
-struct via_info *via = ch->parent;
+ struct via_chinfo *ch;
+ int i;
+ int ret = hz;
+ int pollticks;
+
+ for (i = 0; i < NDXSCHANS + NMSGDCHANS; i++) {
+ ch = &via->pch[i];
+ if (ch->channel == NULL || ch->active == 0)
+ continue;
+ pollticks = ((uint64_t)hz * ch->blksz) /
+ ((uint64_t)sndbuf_getbps(ch->buffer) *
+ sndbuf_getspd(ch->buffer));
+ pollticks >>= 2;
+ if (pollticks > hz)
+ pollticks = hz;
+ if (pollticks < 1)
+ pollticks = 1;
+ if (pollticks < ret)
+ ret = pollticks;
+ }
+
+ for (i = 0; i < NWRCHANS; i++) {
+ ch = &via->rch[i];
+ if (ch->channel == NULL || ch->active == 0)
+ continue;
+ pollticks = ((uint64_t)hz * ch->blksz) /
+ ((uint64_t)sndbuf_getbps(ch->buffer) *
+ sndbuf_getspd(ch->buffer));
+ pollticks >>= 2;
+ if (pollticks > hz)
+ pollticks = hz;
+ if (pollticks < 1)
+ pollticks = 1;
+ if (pollticks < ret)
+ ret = pollticks;
+ }
-snd_mtxlock(via->lock);
-switch(go) {
-case PCMTRIG_START:
-via_buildsgdt(ch);
-via8233chan_mute(via, ch, 0);
-via_wr(via, ch->rbase + VIA_RP_TABLE_PTR, ch->sgd_addr, 4);
-via_wr(via, ch->rbase + VIA_RP_CONTROL,
-SGD_CONTROL_START | SGD_CONTROL_AUTOSTART |
-SGD_CONTROL_I_EOL | SGD_CONTROL_I_FLAG, 1);
-break;
-case PCMTRIG_STOP:
-case PCMTRIG_ABORT:
-via_wr(via, ch->rbase + VIA_RP_CONTROL, SGD_CONTROL_STOP, 1);
-via8233chan_mute(via, ch, 1);
-via8233chan_reset(via, ch);
-break;
+ return (ret);
}
-snd_mtxunlock(via->lock);
-return 0;
+
+static int
+via8233chan_trigger(kobj_t obj, void* data, int go)
+{
+ struct via_chinfo *ch = data;
+ struct via_info *via = ch->parent;
+ int pollticks;
+
+ if (!PCMTRIG_COMMON(go))
+ return (0);
+
+ snd_mtxlock(via->lock);
+ switch(go) {
+ case PCMTRIG_START:
+ via_buildsgdt(ch);
+ via8233chan_mute(via, ch, 0);
+ via_wr(via, ch->rbase + VIA_RP_TABLE_PTR, ch->sgd_addr, 4);
+ if (via->polling != 0) {
+ ch->ptr = 0;
+ ch->prevptr = 0;
+ pollticks = ((uint64_t)hz * ch->blksz) /
+ ((uint64_t)sndbuf_getbps(ch->buffer) *
+ sndbuf_getspd(ch->buffer));
+ pollticks >>= 2;
+ if (pollticks > hz)
+ pollticks = hz;
+ if (pollticks < 1)
+ pollticks = 1;
+ if (via_chan_active(via) == 0 ||
+ pollticks < via->poll_ticks) {
+ if (bootverbose) {
+ if (via_chan_active(via) == 0)
+ printf("%s: pollticks=%d\n",
+ __func__, pollticks);
+ else
+ printf("%s: "
+ "pollticks %d -> %d\n",
+ __func__, via->poll_ticks,
+ pollticks);
+ }
+ via->poll_ticks = pollticks;
+ callout_reset(&via->poll_timer, 1,
+ via_poll_callback, via);
+ }
+ }
+ via_wr(via, ch->rbase + VIA_RP_CONTROL,
+ SGD_CONTROL_START | SGD_CONTROL_AUTOSTART |
+ ((via->polling == 0) ?
+ (SGD_CONTROL_I_EOL | SGD_CONTROL_I_FLAG) : 0), 1);
+ ch->active = 1;
+ break;
+ case PCMTRIG_STOP:
+ case PCMTRIG_ABORT:
+ via_wr(via, ch->rbase + VIA_RP_CONTROL, SGD_CONTROL_STOP, 1);
+ via8233chan_mute(via, ch, 1);
+ via8233chan_reset(via, ch);
+ ch->active = 0;
+ if (via->polling != 0) {
+ if (via_chan_active(via) == 0) {
+ callout_stop(&via->poll_timer);
+ via->poll_ticks = 1;
+ } else {
+ pollticks = via_poll_ticks(via);
+ if (pollticks > via->poll_ticks) {
+ if (bootverbose)
+ printf("%s: pollticks "
+ "%d -> %d\n",
+ __func__, via->poll_ticks,
+ pollticks);
+ via->poll_ticks = pollticks;
+ callout_reset(&via->poll_timer,
+ 1, via_poll_callback,
+ via);
+ }
+ }
+ }
+ break;
+ default:
+ break;
+ }
+ snd_mtxunlock(via->lock);
+ return (0);
}
static kobj_method_t via8233wr_methods[] = {
-KOBJMETHOD(channel_init, via8233wr_init),
-KOBJMETHOD(channel_setformat, via8233wr_setformat),
-KOBJMETHOD(channel_setspeed, via8233wr_setspeed),
-KOBJMETHOD(channel_getcaps, via8233wr_getcaps),
-KOBJMETHOD(channel_setblocksize, via8233chan_setblocksize),
-KOBJMETHOD(channel_trigger, via8233chan_trigger),
-KOBJMETHOD(channel_getptr, via8233chan_getptr),
-{ 0, 0 }
+ KOBJMETHOD(channel_init, via8233wr_init),
+ KOBJMETHOD(channel_setformat, via8233wr_setformat),
+ KOBJMETHOD(channel_setspeed, via8233wr_setspeed),
+ KOBJMETHOD(channel_getcaps, via8233wr_getcaps),
+ KOBJMETHOD(channel_setblocksize, via8233chan_setblocksize),
+ KOBJMETHOD(channel_setfragments, via8233chan_setfragments),
+ KOBJMETHOD(channel_trigger, via8233chan_trigger),
+ KOBJMETHOD(channel_getptr, via8233chan_getptr),
+ { 0, 0 }
};
CHANNEL_DECLARE(via8233wr);
static kobj_method_t via8233dxs_methods[] = {
-KOBJMETHOD(channel_init, via8233dxs_init),
-KOBJMETHOD(channel_setformat, via8233dxs_setformat),
-KOBJMETHOD(channel_setspeed, via8233dxs_setspeed),
-KOBJMETHOD(channel_getcaps, via8233dxs_getcaps),
-KOBJMETHOD(channel_setblocksize, via8233chan_setblocksize),
-KOBJMETHOD(channel_trigger, via8233chan_trigger),
-KOBJMETHOD(channel_getptr, via8233chan_getptr),
-{ 0, 0 }
+ KOBJMETHOD(channel_init, via8233dxs_init),
+ KOBJMETHOD(channel_setformat, via8233dxs_setformat),
+ KOBJMETHOD(channel_setspeed, via8233dxs_setspeed),
+ KOBJMETHOD(channel_getcaps, via8233dxs_getcaps),
+ KOBJMETHOD(channel_setblocksize, via8233chan_setblocksize),
+ KOBJMETHOD(channel_setfragments, via8233chan_setfragments),
+ KOBJMETHOD(channel_trigger, via8233chan_trigger),
+ KOBJMETHOD(channel_getptr, via8233chan_getptr),
+ { 0, 0 }
};
CHANNEL_DECLARE(via8233dxs);
static kobj_method_t via8233msgd_methods[] = {
-KOBJMETHOD(channel_init, via8233msgd_init),
-KOBJMETHOD(channel_setformat, via8233msgd_setformat),
-KOBJMETHOD(channel_setspeed, via8233msgd_setspeed),
-KOBJMETHOD(channel_getcaps, via8233msgd_getcaps),
-KOBJMETHOD(channel_setblocksize, via8233chan_setblocksize),
-KOBJMETHOD(channel_trigger, via8233chan_trigger),
-KOBJMETHOD(channel_getptr, via8233chan_getptr),
-{ 0, 0 }
+ KOBJMETHOD(channel_init, via8233msgd_init),
+ KOBJMETHOD(channel_setformat, via8233msgd_setformat),
+ KOBJMETHOD(channel_setspeed, via8233msgd_setspeed),
+ KOBJMETHOD(channel_getcaps, via8233msgd_getcaps),
+ KOBJMETHOD(channel_setblocksize, via8233chan_setblocksize),
+ KOBJMETHOD(channel_setfragments, via8233chan_setfragments),
+ KOBJMETHOD(channel_trigger, via8233chan_trigger),
+ KOBJMETHOD(channel_getptr, via8233chan_getptr),
+ { 0, 0 }
};
CHANNEL_DECLARE(via8233msgd);
@@ -711,383 +1009,436 @@
static void
via_intr(void *p)
{
-struct via_info *via = p;
-int i, reg, stat;
-
-/* Poll playback channels */
-snd_mtxlock(via->lock);
-for (i = 0; i < NDXSCHANS + NMSGDCHANS; i++) {
-if (via->pch[i].channel == NULL)
-continue;
-reg = via->pch[i].rbase + VIA_RP_STATUS;
-stat = via_rd(via, reg, 1);
-if (stat & SGD_STATUS_INTR) {
-if (via->dma_eol_wake && ((stat & SGD_STATUS_EOL) ||
-!(stat & SGD_STATUS_ACTIVE))) {
-via_wr(via,
-via->pch[i].rbase + VIA_RP_CONTROL,
-SGD_CONTROL_START |
-SGD_CONTROL_AUTOSTART |
-SGD_CONTROL_I_EOL |
-SGD_CONTROL_I_FLAG, 1);
-}
-via_wr(via, reg, stat, 1);
-snd_mtxunlock(via->lock);
-chn_intr(via->pch[i].channel);
-snd_mtxlock(via->lock);
-}
-}
-
-/* Poll record channels */
-for (i = 0; i < NWRCHANS; i++) {
-if (via->rch[i].channel == NULL)
-continue;
-reg = via->rch[i].rbase + VIA_RP_STATUS;
-stat = via_rd(via, reg, 1);
-if (stat & SGD_STATUS_INTR) {
-if (via->dma_eol_wake && ((stat & SGD_STATUS_EOL) ||
-!(stat & SGD_STATUS_ACTIVE))) {
-via_wr(via,
-via->rch[i].rbase + VIA_RP_CONTROL,
-SGD_CONTROL_START |
-SGD_CONTROL_AUTOSTART |
-SGD_CONTROL_I_EOL |
-SGD_CONTROL_I_FLAG, 1);
-}
-via_wr(via, reg, stat, 1);
-snd_mtxunlock(via->lock);
-chn_intr(via->rch[i].channel);
-snd_mtxlock(via->lock);
-}
-}
-snd_mtxunlock(via->lock);
+ struct via_info *via = p;
+ uint32_t ptrigger = 0, rtrigger = 0;
+ int i, reg, stat;
+
+ snd_mtxlock(via->lock);
+ if (via->polling != 0) {
+ snd_mtxunlock(via->lock);
+ return;
+ }
+ /* Poll playback channels */
+ for (i = 0; i < NDXSCHANS + NMSGDCHANS; i++) {
+ if (via->pch[i].channel == NULL || via->pch[i].active == 0)
+ continue;
+ reg = via->pch[i].rbase + VIA_RP_STATUS;
+ stat = via_rd(via, reg, 1);
+ if (stat & SGD_STATUS_INTR) {
+ if (via->dma_eol_wake && ((stat & SGD_STATUS_EOL) ||
+ !(stat & SGD_STATUS_ACTIVE)))
+ via_wr(via, via->pch[i].rbase + VIA_RP_CONTROL,
+ SGD_CONTROL_START | SGD_CONTROL_AUTOSTART |
+ SGD_CONTROL_I_EOL | SGD_CONTROL_I_FLAG, 1);
+ via_wr(via, reg, stat, 1);
+ ptrigger |= 1 << i;
+ }
+ }
+ /* Poll record channels */
+ for (i = 0; i < NWRCHANS; i++) {
+ if (via->rch[i].channel == NULL || via->rch[i].active == 0)
+ continue;
+ reg = via->rch[i].rbase + VIA_RP_STATUS;
+ stat = via_rd(via, reg, 1);
+ if (stat & SGD_STATUS_INTR) {
+ if (via->dma_eol_wake && ((stat & SGD_STATUS_EOL) ||
+ !(stat & SGD_STATUS_ACTIVE)))
+ via_wr(via, via->rch[i].rbase + VIA_RP_CONTROL,
+ SGD_CONTROL_START | SGD_CONTROL_AUTOSTART |
+ SGD_CONTROL_I_EOL | SGD_CONTROL_I_FLAG, 1);
+ via_wr(via, reg, stat, 1);
+ rtrigger |= 1 << i;
+ }
+ }
+ snd_mtxunlock(via->lock);
+
+ for (i = 0; i < NDXSCHANS + NMSGDCHANS; i++) {
+ if (ptrigger & (1 << i))
+ chn_intr(via->pch[i].channel);
+ }
+ for (i = 0; i < NWRCHANS; i++) {
+ if (rtrigger & (1 << i))
+ chn_intr(via->rch[i].channel);
+ }
}
/*
-* Probe and attach the card
-*/
+ * Probe and attach the card
+ */
static int
via_probe(device_t dev)
{
-switch(pci_get_devid(dev)) {
-case VIA8233_PCI_ID:
-switch(pci_get_revid(dev)) {
-case VIA8233_REV_ID_8233PRE:
-device_set_desc(dev, "VIA VT8233 (pre)");
-return BUS_PROBE_DEFAULT;
-case VIA8233_REV_ID_8233C:
-device_set_desc(dev, "VIA VT8233C");
-return BUS_PROBE_DEFAULT;
-case VIA8233_REV_ID_8233:
-device_set_desc(dev, "VIA VT8233");
-return BUS_PROBE_DEFAULT;
-case VIA8233_REV_ID_8233A:
-device_set_desc(dev, "VIA VT8233A");
-return BUS_PROBE_DEFAULT;
-case VIA8233_REV_ID_8235:
-device_set_desc(dev, "VIA VT8235");
-return BUS_PROBE_DEFAULT;
-case VIA8233_REV_ID_8237:
-device_set_desc(dev, "VIA VT8237");
-return BUS_PROBE_DEFAULT;
-case VIA8233_REV_ID_8251:
-device_set_desc(dev, "VIA VT8251");
-return BUS_PROBE_DEFAULT;
-default:
-device_set_desc(dev, "VIA VT8233X"); /* Unknown */
-return BUS_PROBE_DEFAULT;
-}
-}
-return ENXIO;
+ switch(pci_get_devid(dev)) {
+ case VIA8233_PCI_ID:
+ switch(pci_get_revid(dev)) {
+ case VIA8233_REV_ID_8233PRE:
+ device_set_desc(dev, "VIA VT8233 (pre)");
+ return (BUS_PROBE_DEFAULT);
+ case VIA8233_REV_ID_8233C:
+ device_set_desc(dev, "VIA VT8233C");
+ return (BUS_PROBE_DEFAULT);
+ case VIA8233_REV_ID_8233:
+ device_set_desc(dev, "VIA VT8233");
+ return (BUS_PROBE_DEFAULT);
+ case VIA8233_REV_ID_8233A:
+ device_set_desc(dev, "VIA VT8233A");
+ return (BUS_PROBE_DEFAULT);
+ case VIA8233_REV_ID_8235:
+ device_set_desc(dev, "VIA VT8235");
+ return (BUS_PROBE_DEFAULT);
+ case VIA8233_REV_ID_8237:
+ device_set_desc(dev, "VIA VT8237");
+ return (BUS_PROBE_DEFAULT);
+ case VIA8233_REV_ID_8251:
+ device_set_desc(dev, "VIA VT8251");
+ return (BUS_PROBE_DEFAULT);
+ default:
+ device_set_desc(dev, "VIA VT8233X"); /* Unknown */
+ return (BUS_PROBE_DEFAULT);
+ }
+ }
+ return (ENXIO);
}
static void
dma_cb(void *p, bus_dma_segment_t *bds, int a, int b)
{
-struct via_info *via = (struct via_info *)p;
-via->sgd_addr = bds->ds_addr;
+ struct via_info *via = (struct via_info *)p;
+ via->sgd_addr = bds->ds_addr;
}
static int
via_chip_init(device_t dev)
{
-u_int32_t data, cnt;
+ uint32_t data, cnt;
-/* Wake up and reset AC97 if necessary */
-data = pci_read_config(dev, VIA_PCI_ACLINK_STAT, 1);
+ /* Wake up and reset AC97 if necessary */
+ data = pci_read_config(dev, VIA_PCI_ACLINK_STAT, 1);
-if ((data & VIA_PCI_ACLINK_C00_READY) == 0) {
-/* Cold reset per ac97r2.3 spec (page 95) */
-/* Assert low */
-pci_write_config(dev, VIA_PCI_ACLINK_CTRL,
-VIA_PCI_ACLINK_EN, 1);
-/* Wait T_rst_low */
-DELAY(100);
-/* Assert high */
-pci_write_config(dev, VIA_PCI_ACLINK_CTRL,
-VIA_PCI_ACLINK_EN | VIA_PCI_ACLINK_NRST, 1);
-/* Wait T_rst2clk */
-DELAY(5);
-/* Assert low */
-pci_write_config(dev, VIA_PCI_ACLINK_CTRL,
-VIA_PCI_ACLINK_EN, 1);
-} else {
-/* Warm reset */
-/* Force no sync */
-pci_write_config(dev, VIA_PCI_ACLINK_CTRL,
-VIA_PCI_ACLINK_EN, 1);
-DELAY(100);
-/* Sync */
-pci_write_config(dev, VIA_PCI_ACLINK_CTRL,
-VIA_PCI_ACLINK_EN | VIA_PCI_ACLINK_SYNC, 1);
-/* Wait T_sync_high */
-DELAY(5);
-/* Force no sync */
-pci_write_config(dev, VIA_PCI_ACLINK_CTRL,
-VIA_PCI_ACLINK_EN, 1);
-/* Wait T_sync2clk */
-DELAY(5);
-}
-
-/* Power everything up */
-pci_write_config(dev, VIA_PCI_ACLINK_CTRL, VIA_PCI_ACLINK_DESIRED, 1);
-
-/* Wait for codec to become ready (largest reported delay 310ms) */
-for (cnt = 0; cnt < 2000; cnt++) {
-data = pci_read_config(dev, VIA_PCI_ACLINK_STAT, 1);
-if (data & VIA_PCI_ACLINK_C00_READY) {
-return 0;
-}
-DELAY(5000);
-}
-device_printf(dev, "primary codec not ready (cnt = 0x%02x)n", cnt);
-return ENXIO;
+ if ((data & VIA_PCI_ACLINK_C00_READY) == 0) {
+ /* Cold reset per ac97r2.3 spec (page 95) */
+ /* Assert low */
+ pci_write_config(dev, VIA_PCI_ACLINK_CTRL,
+ VIA_PCI_ACLINK_EN, 1);
+ /* Wait T_rst_low */
+ DELAY(100);
+ /* Assert high */
+ pci_write_config(dev, VIA_PCI_ACLINK_CTRL,
+ VIA_PCI_ACLINK_EN | VIA_PCI_ACLINK_NRST, 1);
+ /* Wait T_rst2clk */
+ DELAY(5);
+ /* Assert low */
+ pci_write_config(dev, VIA_PCI_ACLINK_CTRL,
+ VIA_PCI_ACLINK_EN, 1);
+ } else {
+ /* Warm reset */
+ /* Force no sync */
+ pci_write_config(dev, VIA_PCI_ACLINK_CTRL,
+ VIA_PCI_ACLINK_EN, 1);
+ DELAY(100);
+ /* Sync */
+ pci_write_config(dev, VIA_PCI_ACLINK_CTRL,
+ VIA_PCI_ACLINK_EN | VIA_PCI_ACLINK_SYNC, 1);
+ /* Wait T_sync_high */
+ DELAY(5);
+ /* Force no sync */
+ pci_write_config(dev, VIA_PCI_ACLINK_CTRL,
+ VIA_PCI_ACLINK_EN, 1);
+ /* Wait T_sync2clk */
+ DELAY(5);
+ }
+
+ /* Power everything up */
+ pci_write_config(dev, VIA_PCI_ACLINK_CTRL, VIA_PCI_ACLINK_DESIRED, 1);
+
+ /* Wait for codec to become ready (largest reported delay 310ms) */
+ for (cnt = 0; cnt < 2000; cnt++) {
+ data = pci_read_config(dev, VIA_PCI_ACLINK_STAT, 1);
+ if (data & VIA_PCI_ACLINK_C00_READY)
+ return (0);
+ DELAY(5000);
+ }
+ device_printf(dev, "primary codec not ready (cnt = 0x%02x)\n", cnt);
+ return (ENXIO);
}
static int
via_attach(device_t dev)
{
-struct via_info *via = 0;
-char status[SND_STATUSLEN];
-int i, via_dxs_disabled, via_dxs_src, via_dxs_chnum, via_sgd_chnum;
-uint32_t revid;
-
-if ((via = malloc(sizeof *via, M_DEVBUF, M_NOWAIT | M_ZERO)) == NULL) {
-device_printf(dev, "cannot allocate softcn");
-return ENXIO;
-}
-via->lock = snd_mtxcreate(device_get_nameunit(dev), "sound softc");
-
-pci_set_powerstate(dev, PCI_POWERSTATE_D0);
-pci_enable_busmaster(dev);
-
-via->regid = PCIR_BAR(0);
-via->reg = bus_alloc_resource_any(dev, SYS_RES_IOPORT, &via->regid,
-RF_ACTIVE);
-if (!via->reg) {
-device_printf(dev, "cannot allocate bus resource.");
-goto bad;
-}
-via->st = rman_get_bustag(via->reg);
-via->sh = rman_get_bushandle(via->reg);
-
-via->bufsz = pcm_getbuffersize(dev, 4096, VIA_DEFAULT_BUFSZ, 65536);
-
-via->irqid = 0;
-via->irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &via->irqid,
-RF_ACTIVE | RF_SHAREABLE);
-if (!via->irq ||
-snd_setup_intr(dev, via->irq, INTR_MPSAFE, via_intr, via, &via->ih)) {
-device_printf(dev, "unable to map interruptn");
-goto bad;
-}
-
-/* DMA tag for buffers */
-if (bus_dma_tag_create(/*parent*/NULL, /*alignment*/2, /*boundary*/0,
-/*lowaddr*/BUS_SPACE_MAXADDR_32BIT,
-/*highaddr*/BUS_SPACE_MAXADDR,
-/*filter*/NULL, /*filterarg*/NULL,
-/*maxsize*/via->bufsz, /*nsegments*/1, /*maxsegz*/0x3ffff,
-/*flags*/0, /*lockfunc*/NULL,
-/*lockarg*/NULL, &via->parent_dmat) != 0) {
-device_printf(dev, "unable to create dma tagn");
-goto bad;
-}
-
-/*
-* DMA tag for SGD table. The 686 uses scatter/gather DMA and
-* requires a list in memory of work to do. We need only 16 bytes
-* for this list, and it is wasteful to allocate 16K.
-*/
-if (bus_dma_tag_create(/*parent*/NULL, /*alignment*/2, /*boundary*/0,
-/*lowaddr*/BUS_SPACE_MAXADDR_32BIT,
-/*highaddr*/BUS_SPACE_MAXADDR,
-/*filter*/NULL, /*filterarg*/NULL,
-/*maxsize*/NSEGS * sizeof(struct via_dma_op),
-/*nsegments*/1, /*maxsegz*/0x3ffff,
-/*flags*/0, /*lockfunc*/NULL,
-/*lockarg*/NULL, &via->sgd_dmat) != 0) {
-device_printf(dev, "unable to create dma tagn");
-goto bad;
-}
-
-if (bus_dmamem_alloc(via->sgd_dmat, (void **)&via->sgd_table,
-BUS_DMA_NOWAIT, &via->sgd_dmamap) == -1)
-goto bad;
-if (bus_dmamap_load(via->sgd_dmat, via->sgd_dmamap, via->sgd_table,
-NSEGS * sizeof(struct via_dma_op), dma_cb, via, 0))
-goto bad;
-
-if (via_chip_init(dev))
-goto bad;
-
-via->codec = AC97_CREATE(dev, via, via_ac97);
-if (!via->codec)
-goto bad;
-
-mixer_init(dev, ac97_getmixerclass(), via->codec);
-
-via->codec_caps = ac97_getextcaps(via->codec);
-
-/* Try to set VRA without generating an error, VRM not reqrd yet */
-if (via->codec_caps &
-(AC97_EXTCAP_VRA | AC97_EXTCAP_VRM | AC97_EXTCAP_DRA)) {
-u_int16_t ext = ac97_getextmode(via->codec);
-ext |= (via->codec_caps &
-(AC97_EXTCAP_VRA | AC97_EXTCAP_VRM));
-ext &= ~AC97_EXTCAP_DRA;
-ac97_setextmode(via->codec, ext);
-}
-
-snprintf(status, SND_STATUSLEN, "at io 0x%lx irq %ld %s",
-rman_get_start(via->reg), rman_get_start(via->irq),PCM_KLDSTRING(snd_via8233));
+ struct via_info *via = 0;
+ char status[SND_STATUSLEN];
+ int i, via_dxs_disabled, via_dxs_src, via_dxs_chnum, via_sgd_chnum;
+ int nsegs;
+ uint32_t revid;
+
+ via = malloc(sizeof *via, M_DEVBUF, M_WAITOK | M_ZERO);
+ via->lock = snd_mtxcreate(device_get_nameunit(dev),
+ "snd_via8233 softc");
+ via->dev = dev;
+
+ callout_init(&via->poll_timer, CALLOUT_MPSAFE);
+ via->poll_ticks = 1;
+
+ if (resource_int_value(device_get_name(dev),
+ device_get_unit(dev), "polling", &i) == 0 && i != 0)
+ via->polling = 1;
+ else
+ via->polling = 0;
+
+ pci_set_powerstate(dev, PCI_POWERSTATE_D0);
+ pci_enable_busmaster(dev);
+
+ via->regid = PCIR_BAR(0);
+ via->reg = bus_alloc_resource_any(dev, SYS_RES_IOPORT, &via->regid,
+ RF_ACTIVE);
+ if (!via->reg) {
+ device_printf(dev, "cannot allocate bus resource.");
+ goto bad;
+ }
+ via->st = rman_get_bustag(via->reg);
+ via->sh = rman_get_bushandle(via->reg);
+
+ via->irqid = 0;
+ via->irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &via->irqid,
+ RF_ACTIVE | RF_SHAREABLE);
+ if (!via->irq ||
+ snd_setup_intr(dev, via->irq, INTR_MPSAFE,
+ via_intr, via, &via->ih)) {
+ device_printf(dev, "unable to map interrupt\n");
+ goto bad;
+ }
+
+ via->bufsz = pcm_getbuffersize(dev, 4096, VIA_DEFAULT_BUFSZ, 65536);
+ if (resource_int_value(device_get_name(dev),
+ device_get_unit(dev), "blocksize", &i) == 0 && i > 0) {
+ i &= VIA_BLK_ALIGN;
+ if (i < VIA_BLK_MIN)
+ i = VIA_BLK_MIN;
+ via->blkcnt = via->bufsz / i;
+ i = 0;
+ while (via->blkcnt >> i)
+ i++;
+ via->blkcnt = 1 << (i - 1);
+ if (via->blkcnt < VIA_SEGS_MIN)
+ via->blkcnt = VIA_SEGS_MIN;
+ else if (via->blkcnt > VIA_SEGS_MAX)
+ via->blkcnt = VIA_SEGS_MAX;
+
+ } else
+ via->blkcnt = VIA_SEGS_DEFAULT;
+
+ revid = pci_get_revid(dev);
+
+ /*
+ * VIA8251 lost its interrupt after DMA EOL, and need
+ * a gentle spank on its face within interrupt handler.
+ */
+ if (revid == VIA8233_REV_ID_8251)
+ via->dma_eol_wake = 1;
+ else
+ via->dma_eol_wake = 0;
+
+ /*
+ * Decide whether DXS had to be disabled or not
+ */
+ if (revid == VIA8233_REV_ID_8233A) {
+ /*
+ * DXS channel is disabled. Reports from multiple users
+ * that it plays at half-speed. Do not see this behaviour
+ * on available 8233C or when emulating 8233A register set
+ * on 8233C (either with or without ac97 VRA).
+ */
+ via_dxs_disabled = 1;
+ } else if (resource_int_value(device_get_name(dev),
+ device_get_unit(dev), "via_dxs_disabled",
+ &via_dxs_disabled) == 0)
+ via_dxs_disabled = (via_dxs_disabled > 0) ? 1 : 0;
+ else
+ via_dxs_disabled = 0;
+
+ if (via_dxs_disabled) {
+ via_dxs_chnum = 0;
+ via_sgd_chnum = 1;
+ } else {
+ if (resource_int_value(device_get_name(dev),
+ device_get_unit(dev), "via_dxs_channels",
+ &via_dxs_chnum) != 0)
+ via_dxs_chnum = NDXSCHANS;
+ if (resource_int_value(device_get_name(dev),
+ device_get_unit(dev), "via_sgd_channels",
+ &via_sgd_chnum) != 0)
+ via_sgd_chnum = NMSGDCHANS;
+ }
+ if (via_dxs_chnum > NDXSCHANS)
+ via_dxs_chnum = NDXSCHANS;
+ else if (via_dxs_chnum < 0)
+ via_dxs_chnum = 0;
+ if (via_sgd_chnum > NMSGDCHANS)
+ via_sgd_chnum = NMSGDCHANS;
+ else if (via_sgd_chnum < 0)
+ via_sgd_chnum = 0;
+ if (via_dxs_chnum + via_sgd_chnum < 1) {
+ /* Minimalist ? */
+ via_dxs_chnum = 1;
+ via_sgd_chnum = 0;
+ }
+ if (via_dxs_chnum > 0 && resource_int_value(device_get_name(dev),
+ device_get_unit(dev), "via_dxs_src", &via_dxs_src) == 0)
+ via->dxs_src = (via_dxs_src > 0) ? 1 : 0;
+ else
+ via->dxs_src = 0;
+
+ nsegs = (via_dxs_chnum + via_sgd_chnum + NWRCHANS) * VIA_SEGS_MAX;
+
+ /* DMA tag for buffers */
+ if (bus_dma_tag_create(/*parent*/bus_get_dma_tag(dev), /*alignment*/2,
+ /*boundary*/0,
+ /*lowaddr*/BUS_SPACE_MAXADDR_32BIT,
+ /*highaddr*/BUS_SPACE_MAXADDR,
+ /*filter*/NULL, /*filterarg*/NULL,
+ /*maxsize*/via->bufsz, /*nsegments*/1, /*maxsegz*/0x3ffff,
+ /*flags*/0, /*lockfunc*/NULL,
+ /*lockarg*/NULL, &via->parent_dmat) != 0) {
+ device_printf(dev, "unable to create dma tag\n");
+ goto bad;
+ }
+
+ /*
+ * DMA tag for SGD table. The 686 uses scatter/gather DMA and
+ * requires a list in memory of work to do. We need only 16 bytes
+ * for this list, and it is wasteful to allocate 16K.
+ */
+ if (bus_dma_tag_create(/*parent*/bus_get_dma_tag(dev), /*alignment*/2,
+ /*boundary*/0,
+ /*lowaddr*/BUS_SPACE_MAXADDR_32BIT,
+ /*highaddr*/BUS_SPACE_MAXADDR,
+ /*filter*/NULL, /*filterarg*/NULL,
+ /*maxsize*/nsegs * sizeof(struct via_dma_op),
+ /*nsegments*/1, /*maxsegz*/0x3ffff,
+ /*flags*/0, /*lockfunc*/NULL,
+ /*lockarg*/NULL, &via->sgd_dmat) != 0) {
+ device_printf(dev, "unable to create dma tag\n");
+ goto bad;
+ }
+
+ if (bus_dmamem_alloc(via->sgd_dmat, (void **)&via->sgd_table,
+ BUS_DMA_NOWAIT, &via->sgd_dmamap) == -1)
+ goto bad;
+ if (bus_dmamap_load(via->sgd_dmat, via->sgd_dmamap, via->sgd_table,
+ nsegs * sizeof(struct via_dma_op), dma_cb, via, 0))
+ goto bad;
+
+ if (via_chip_init(dev))
+ goto bad;
+
+ via->codec = AC97_CREATE(dev, via, via_ac97);
+ if (!via->codec)
+ goto bad;
+
+ mixer_init(dev, ac97_getmixerclass(), via->codec);
+
+ via->codec_caps = ac97_getextcaps(via->codec);
+
+ /* Try to set VRA without generating an error, VRM not reqrd yet */
+ if (via->codec_caps &
+ (AC97_EXTCAP_VRA | AC97_EXTCAP_VRM | AC97_EXTCAP_DRA)) {
+ uint16_t ext = ac97_getextmode(via->codec);
+ ext |= (via->codec_caps &
+ (AC97_EXTCAP_VRA | AC97_EXTCAP_VRM));
+ ext &= ~AC97_EXTCAP_DRA;
+ ac97_setextmode(via->codec, ext);
+ }
+
+ snprintf(status, SND_STATUSLEN, "at io 0x%lx irq %ld %s",
+ rman_get_start(via->reg), rman_get_start(via->irq),
+ PCM_KLDSTRING(snd_via8233));
+
+ /* Register */
+ if (pcm_register(dev, via, via_dxs_chnum + via_sgd_chnum, NWRCHANS))
+ goto bad;
+ for (i = 0; i < via_dxs_chnum; i++)
+ pcm_addchan(dev, PCMDIR_PLAY, &via8233dxs_class, via);
+ for (i = 0; i < via_sgd_chnum; i++)
+ pcm_addchan(dev, PCMDIR_PLAY, &via8233msgd_class, via);
+ for (i = 0; i < NWRCHANS; i++)
+ pcm_addchan(dev, PCMDIR_REC, &via8233wr_class, via);
+ if (via_dxs_chnum > 0)
+ via_init_sysctls(dev);
+ device_printf(dev, "<VIA DXS %sabled: DXS%s %d / SGD %d / REC %d>\n",
+ (via_dxs_chnum > 0) ? "En" : "Dis", (via->dxs_src) ? "(SRC)" : "",
+ via_dxs_chnum, via_sgd_chnum, NWRCHANS);
-revid = pci_get_revid(dev);
+ pcm_setstatus(dev, status);
-/*
-* VIA8251 lost its interrupt after DMA EOL, and need
-* a gentle spank on its face within interrupt handler.
-*/
-if (revid == VIA8233_REV_ID_8251)
-via->dma_eol_wake = 1;
-else
-via->dma_eol_wake = 0;
-
-/*
-* Decide whether DXS had to be disabled or not
-*/
-if (revid == VIA8233_REV_ID_8233A) {
-/*
-* DXS channel is disabled. Reports from multiple users
-* that it plays at half-speed. Do not see this behaviour
-* on available 8233C or when emulating 8233A register set
-* on 8233C (either with or without ac97 VRA).
-*/
-via_dxs_disabled = 1;
-} else if (resource_int_value(device_get_name(dev),
-device_get_unit(dev), "via_dxs_disabled",
-&via_dxs_disabled) == 0)
-via_dxs_disabled = (via_dxs_disabled > 0) ? 1 : 0;
-else
-via_dxs_disabled = 0;
-
-if (via_dxs_disabled) {
-via_dxs_chnum = 0;
-via_sgd_chnum = 1;
-} else {
-if (resource_int_value(device_get_name(dev),
-device_get_unit(dev), "via_dxs_channels",
-&via_dxs_chnum) != 0)
-via_dxs_chnum = NDXSCHANS;
-if (resource_int_value(device_get_name(dev),
-device_get_unit(dev), "via_sgd_channels",
-&via_sgd_chnum) != 0)
-via_sgd_chnum = NMSGDCHANS;
-}
-if (via_dxs_chnum > NDXSCHANS)
-via_dxs_chnum = NDXSCHANS;
-else if (via_dxs_chnum < 0)
-via_dxs_chnum = 0;
-if (via_sgd_chnum > NMSGDCHANS)
-via_sgd_chnum = NMSGDCHANS;
-else if (via_sgd_chnum < 0)
-via_sgd_chnum = 0;
-if (via_dxs_chnum + via_sgd_chnum < 1) {
-/* Minimalist ? */
-via_dxs_chnum = 1;
-via_sgd_chnum = 0;
-}
-if (via_dxs_chnum > 0 && resource_int_value(device_get_name(dev),
-device_get_unit(dev), "via_dxs_src",
-&via_dxs_src) == 0)
-via->dxs_src = (via_dxs_src > 0) ? 1 : 0;
-else
-via->dxs_src = 0;
-/* Register */
-if (pcm_register(dev, via, via_dxs_chnum + via_sgd_chnum, NWRCHANS))
-goto bad;
-for (i = 0; i < via_dxs_chnum; i++)
-pcm_addchan(dev, PCMDIR_PLAY, &via8233dxs_class, via);
-for (i = 0; i < via_sgd_chnum; i++)
-pcm_addchan(dev, PCMDIR_PLAY, &via8233msgd_class, via);
-for (i = 0; i < NWRCHANS; i++)
-pcm_addchan(dev, PCMDIR_REC, &via8233wr_class, via);
-if (via_dxs_chnum > 0)
-via_init_sysctls(dev);
-device_printf(dev, "<VIA DXS %sabled: DXS%s %d / SGD %d / REC %d>n",
-(via_dxs_chnum > 0) ? "En" : "Dis",
-(via->dxs_src) ? "(SRC)" : "",
-via_dxs_chnum, via_sgd_chnum, NWRCHANS);
-
-pcm_setstatus(dev, status);
-
-return 0;
+ return (0);
bad:
-if (via->codec) ac97_destroy(via->codec);
-if (via->reg) bus_release_resource(dev, SYS_RES_IOPORT, via->regid, via->reg);
-if (via->ih) bus_teardown_intr(dev, via->irq, via->ih);
-if (via->irq) bus_release_resource(dev, SYS_RES_IRQ, via->irqid, via->irq);
-if (via->parent_dmat) bus_dma_tag_destroy(via->parent_dmat);
-if (via->sgd_dmamap) bus_dmamap_unload(via->sgd_dmat, via->sgd_dmamap);
-if (via->sgd_dmat) bus_dma_tag_destroy(via->sgd_dmat);
-if (via->lock) snd_mtxfree(via->lock);
-if (via) free(via, M_DEVBUF);
-return ENXIO;
+ if (via->codec)
+ ac97_destroy(via->codec);
+ if (via->reg)
+ bus_release_resource(dev, SYS_RES_IOPORT, via->regid, via->reg);
+ if (via->ih)
+ bus_teardown_intr(dev, via->irq, via->ih);
+ if (via->irq)
+ bus_release_resource(dev, SYS_RES_IRQ, via->irqid, via->irq);
+ if (via->parent_dmat)
+ bus_dma_tag_destroy(via->parent_dmat);
+ if (via->sgd_dmamap)
+ bus_dmamap_unload(via->sgd_dmat, via->sgd_dmamap);
+ if (via->sgd_table)
+ bus_dmamem_free(via->sgd_dmat, via->sgd_table, via->sgd_dmamap);
+ if (via->sgd_dmat)
+ bus_dma_tag_destroy(via->sgd_dmat);
+ if (via->lock)
+ snd_mtxfree(via->lock);
+ if (via)
+ free(via, M_DEVBUF);
+ return (ENXIO);
}
static int
via_detach(device_t dev)
{
-int r;
-struct via_info *via = 0;
-
-r = pcm_unregister(dev);
-if (r) return r;
+ int r;
+ struct via_info *via;
-via = pcm_getdevinfo(dev);
-bus_release_resource(dev, SYS_RES_IOPORT, via->regid, via->reg);
-bus_teardown_intr(dev, via->irq, via->ih);
-bus_release_resource(dev, SYS_RES_IRQ, via->irqid, via->irq);
-bus_dma_tag_destroy(via->parent_dmat);
-bus_dmamap_unload(via->sgd_dmat, via->sgd_dmamap);
-bus_dma_tag_destroy(via->sgd_dmat);
-snd_mtxfree(via->lock);
-free(via, M_DEVBUF);
-return 0;
+ r = pcm_unregister(dev);
+ if (r)
+ return (r);
+
+ via = pcm_getdevinfo(dev);
+
+ if (via != NULL && (via->play_num != 0 || via->rec_num != 0)) {
+ snd_mtxlock(via->lock);
+ via->polling = 0;
+ callout_stop(&via->poll_timer);
+ snd_mtxunlock(via->lock);
+ callout_drain(&via->poll_timer);
+ }
+
+ bus_release_resource(dev, SYS_RES_IOPORT, via->regid, via->reg);
+ bus_teardown_intr(dev, via->irq, via->ih);
+ bus_release_resource(dev, SYS_RES_IRQ, via->irqid, via->irq);
+ bus_dma_tag_destroy(via->parent_dmat);
+ bus_dmamap_unload(via->sgd_dmat, via->sgd_dmamap);
+ bus_dmamem_free(via->sgd_dmat, via->sgd_table, via->sgd_dmamap);
+ bus_dma_tag_destroy(via->sgd_dmat);
+ snd_mtxfree(via->lock);
+ free(via, M_DEVBUF);
+ return (0);
}
static device_method_t via_methods[] = {
-DEVMETHOD(device_probe, via_probe),
-DEVMETHOD(device_attach, via_attach),
-DEVMETHOD(device_detach, via_detach),
-{ 0, 0}
+ DEVMETHOD(device_probe, via_probe),
+ DEVMETHOD(device_attach, via_attach),
+ DEVMETHOD(device_detach, via_detach),
+ { 0, 0}
};
static driver_t via_driver = {
-"pcm",
-via_methods,
-PCM_SOFTC_SIZE,
+ "pcm",
+ via_methods,
+ PCM_SOFTC_SIZE,
};
DRIVER_MODULE(snd_via8233, pci, via_driver, pcm_devclass, 0, 0);
Index: csavar.h
===================================================================
RCS file: /home/cvs/src/sys/dev/sound/pci/csavar.h,v
retrieving revision 1.2
retrieving revision 1.3
diff -L sys/dev/sound/pci/csavar.h -L sys/dev/sound/pci/csavar.h -u -r1.2 -r1.3
--- sys/dev/sound/pci/csavar.h
+++ sys/dev/sound/pci/csavar.h
@@ -1,58 +1,57 @@
/*-
-* Copyright (c) 1999 Seigo Tanimura
-* All rights reserved.
-*
-* Redistribution and use in source and binary forms, with or without
-* modification, are permitted provided that the following conditions
-* are met:
-* 1. Redistributions of source code must retain the above copyright
-* notice, this list of conditions and the following disclaimer.
-* 2. Redistributions in binary form must reproduce the above copyright
-* notice, this list of conditions and the following disclaimer in the
-* documentation and/or other materials provided with the distribution.
-*
-* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
-* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
-* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
-* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
-* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
-* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
-* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
-* SUCH DAMAGE.
-*
-* $MidnightBSD$
-* $FreeBSD: src/sys/dev/sound/pci/csavar.h,v 1.5 2005/06/27 07:43:57 glebius Exp $
-*/
+ * Copyright (c) 1999 Seigo Tanimura
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD: src/sys/dev/sound/pci/csavar.h,v 1.5 2005/06/27 07:43:57 glebius Exp $
+ */
#ifndef _CSA_VAR_H
#define _CSA_VAR_H
struct csa_card {
-u_int16_t subvendor, subdevice;
-char *name;
-void *amp;
-void *amp_init;
-int (*active)(int);
-int inv_eapd;
+ u_int16_t subvendor, subdevice;
+ char *name;
+ void *amp;
+ void *amp_init;
+ int (*active)(int);
+ int inv_eapd;
};
/* Resources. */
struct csa_res {
-int io_rid; /* io rid */
-struct resource *io; /* io */
-int mem_rid; /* memory rid */
-struct resource *mem; /* memory */
-int irq_rid; /* irq rid */
-struct resource *irq; /* irq */
+ int io_rid; /* io rid */
+ struct resource *io; /* io */
+ int mem_rid; /* memory rid */
+ struct resource *mem; /* memory */
+ int irq_rid; /* irq rid */
+ struct resource *irq; /* irq */
};
typedef struct csa_res csa_res;
/* State of the bridge. */
struct csa_bridgeinfo {
-u_int32_t hisr; /* The value of HISR on this interrupt. */
-struct csa_card *card;
+ u_int32_t hisr; /* The value of HISR on this interrupt. */
+ struct csa_card *card;
};
void csa_clearserialfifos(csa_res *resp);
--- /dev/null
+++ sys/dev/sound/pci/emu10kx-midi.c
@@ -0,0 +1,246 @@
+/*-
+ * Copyright (c) 1999 Seigo Tanimura
+ * (c) 2003 Mathew Kanner
+ * Copyright (c) 2003-2006 Yuriy Tsibizov <yuriy.tsibizov at gfk.ru>
+ * All rights reserved
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD: src/sys/dev/sound/pci/emu10kx-midi.c,v 1.4 2007/09/12 07:43:42 ariff Exp $
+ */
+
+#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/bus.h>
+#include <machine/bus.h>
+#include <sys/rman.h>
+#include <sys/systm.h>
+#include <sys/sbuf.h>
+#include <sys/queue.h>
+#include <sys/lock.h>
+#include <sys/mutex.h>
+
+#include <dev/sound/chip.h>
+#include <dev/sound/pcm/sound.h>
+
+#include <dev/sound/midi/midi.h>
+#include <dev/sound/midi/mpu401.h>
+#include "mpufoi_if.h"
+
+#include <dev/sound/pci/emu10kx.h>
+#include "emu10k1-alsa%diked.h"
+
+struct emu_midi_softc {
+ struct mtx mtx;
+ device_t dev;
+ struct mpu401 *mpu;
+ mpu401_intr_t *mpu_intr;
+ struct emu_sc_info *card;
+ int port; /* I/O port or I/O ptr reg */
+ int is_emu10k1;
+ int fflags; /* File flags */
+ int ihandle; /* interrupt manager handle */
+};
+
+static uint32_t emu_midi_card_intr(void *p, uint32_t arg);
+static devclass_t emu_midi_devclass;
+
+static unsigned char
+emu_mread(void *arg __unused, struct emu_midi_softc *sc, int reg)
+{
+ unsigned int d;
+
+ d = 0;
+ if (sc->is_emu10k1)
+ d = emu_rd(sc->card, 0x18 + reg, 1);
+ else
+ d = emu_rdptr(sc->card, 0, sc->port + reg);
+
+ return (d);
+}
+
+static void
+emu_mwrite(void *arg __unused, struct emu_midi_softc *sc, int reg, unsigned char b)
+{
+
+ if (sc->is_emu10k1)
+ emu_wr(sc->card, 0x18 + reg, b, 1);
+ else
+ emu_wrptr(sc->card, 0, sc->port + reg, b);
+}
+
+static int
+emu_muninit(void *arg __unused, struct emu_midi_softc *sc)
+{
+
+ mtx_lock(&sc->mtx);
+ sc->mpu_intr = NULL;
+ mtx_unlock(&sc->mtx);
+
+ 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}
+};
+static DEFINE_CLASS(emu_mpu, emu_mpu_methods, 0);
+
+static uint32_t
+emu_midi_card_intr(void *p, uint32_t intr_status)
+{
+ struct emu_midi_softc *sc = (struct emu_midi_softc *)p;
+ if (sc->mpu_intr)
+ (sc->mpu_intr) (sc->mpu);
+ if (sc->mpu_intr == NULL) {
+ /* We should read MIDI event to unlock card after
+ * interrupt. XXX - check, why this happens. */
+ if (bootverbose)
+ device_printf(sc->dev, "midi interrupt %08x without interrupt handler, force mread!\n", intr_status);
+ (void)emu_mread((void *)(NULL), sc, 0);
+ }
+ return (intr_status); /* Acknowledge everything */
+}
+
+static void
+emu_midi_intr(void *p)
+{
+ (void)emu_midi_card_intr(p, 0);
+}
+
+static int
+emu_midi_probe(device_t dev)
+{
+ struct emu_midi_softc *scp;
+ uintptr_t func, r, is_emu10k1;
+
+ r = BUS_READ_IVAR(device_get_parent(dev), dev, 0, &func);
+ if (func != SCF_MIDI)
+ return (ENXIO);
+
+ scp = device_get_softc(dev);
+ bzero(scp, sizeof(*scp));
+ r = BUS_READ_IVAR(device_get_parent(dev), dev, EMU_VAR_ISEMU10K1, &is_emu10k1);
+ scp->is_emu10k1 = is_emu10k1 ? 1 : 0;
+
+ device_set_desc(dev, "EMU10Kx MIDI Interface");
+ return (0);
+}
+
+static int
+emu_midi_attach(device_t dev)
+{
+ struct emu_midi_softc * scp;
+ struct sndcard_func *func;
+ struct emu_midiinfo *midiinfo;
+ uint32_t inte_val, ipr_val;
+
+ scp = device_get_softc(dev);
+ func = device_get_ivars(dev);
+
+ scp->dev = dev;
+ midiinfo = (struct emu_midiinfo *)func->varinfo;
+ scp->port = midiinfo->port;
+ scp->card = midiinfo->card;
+
+ mtx_init(&scp->mtx, device_get_nameunit(dev), "midi softc", MTX_DEF);
+
+ if (scp->is_emu10k1) {
+ /* SB Live! - only one MIDI device here */
+ inte_val = 0;
+ /* inte_val |= INTE_MIDITXENABLE;*/
+ inte_val |= INTE_MIDIRXENABLE;
+ ipr_val = IPR_MIDITRANSBUFEMPTY;
+ ipr_val |= IPR_MIDIRECVBUFEMPTY;
+ } else {
+ if (scp->port == A_MUDATA1) {
+ /* EXTERNAL MIDI (AudigyDrive) */
+ inte_val = 0;
+ /* inte_val |= A_INTE_MIDITXENABLE1;*/
+ inte_val |= INTE_MIDIRXENABLE;
+ ipr_val = IPR_MIDITRANSBUFEMPTY;
+ ipr_val |= IPR_MIDIRECVBUFEMPTY;
+ } else {
+ /* MIDI hw config port 2 */
+ inte_val = 0;
+ /* inte_val |= A_INTE_MIDITXENABLE2;*/
+ inte_val |= INTE_A_MIDIRXENABLE2;
+ ipr_val = IPR_A_MIDITRANSBUFEMPTY2;
+ ipr_val |= IPR_A_MIDIRECVBUFEMPTY2;
+ }
+ }
+
+ scp->ihandle = emu_intr_register(scp->card, inte_val, ipr_val, &emu_midi_card_intr, scp);
+ /* Init the interface. */
+ scp->mpu = mpu401_init(&emu_mpu_class, scp, emu_midi_intr, &scp->mpu_intr);
+ if (scp->mpu == NULL) {
+ emu_intr_unregister(scp->card, scp->ihandle);
+ mtx_destroy(&scp->mtx);
+ return (ENOMEM);
+ }
+ /*
+ * XXX I don't know how to check for Live!Drive / AudigyDrive
+ * presence. Let's hope that IR enabling code will not harm if
+ * it is not present.
+ */
+ if (scp->is_emu10k1)
+ emu_enable_ir(scp->card);
+ else {
+ if (scp->port == A_MUDATA1)
+ emu_enable_ir(scp->card);
+ }
+
+ return (0);
+}
+
+
+static int
+emu_midi_detach(device_t dev)
+{
+ struct emu_midi_softc *scp;
+
+ scp = device_get_softc(dev);
+ mpu401_uninit(scp->mpu);
+ emu_intr_unregister(scp->card, scp->ihandle);
+ mtx_destroy(&scp->mtx);
+ return (0);
+}
+
+static device_method_t emu_midi_methods[] = {
+ DEVMETHOD(device_probe, emu_midi_probe),
+ DEVMETHOD(device_attach, emu_midi_attach),
+ DEVMETHOD(device_detach, emu_midi_detach),
+
+ {0, 0},
+};
+
+static driver_t emu_midi_driver = {
+ "midi",
+ emu_midi_methods,
+ sizeof(struct emu_midi_softc),
+};
+DRIVER_MODULE(snd_emu10kx_midi, emu10kx, emu_midi_driver, emu_midi_devclass, 0, 0);
+MODULE_DEPEND(snd_emu10kx_midi, snd_emu10kx, SND_EMU10KX_MINVER, SND_EMU10KX_PREFVER, SND_EMU10KX_MAXVER);
+MODULE_DEPEND(snd_emu10kx_midi, sound, SOUND_MINVER, SOUND_PREFVER, SOUND_MAXVER);
+MODULE_VERSION(snd_emu10kx_midi, SND_EMU10KX_PREFVER);
Index: csapcm.c
===================================================================
RCS file: /home/cvs/src/sys/dev/sound/pci/csapcm.c,v
retrieving revision 1.3
retrieving revision 1.4
diff -L sys/dev/sound/pci/csapcm.c -L sys/dev/sound/pci/csapcm.c -u -r1.3 -r1.4
--- sys/dev/sound/pci/csapcm.c
+++ sys/dev/sound/pci/csapcm.c
@@ -1,32 +1,32 @@
/*-
-* Copyright (c) 1999 Seigo Tanimura
-* All rights reserved.
-*
-* Portions of this source are based on cwcealdr.cpp and dhwiface.cpp in
-* cwcealdr1.zip, the sample sources by Crystal Semiconductor.
-* Copyright (c) 1996-1998 Crystal Semiconductor Corp.
-*
-* Redistribution and use in source and binary forms, with or without
-* modification, are permitted provided that the following conditions
-* are met:
-* 1. Redistributions of source code must retain the above copyright
-* notice, this list of conditions and the following disclaimer.
-* 2. Redistributions in binary form must reproduce the above copyright
-* notice, this list of conditions and the following disclaimer in the
-* documentation and/or other materials provided with the distribution.
-*
-* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
-* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
-* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
-* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
-* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
-* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
-* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
-* SUCH DAMAGE.
-*/
+ * Copyright (c) 1999 Seigo Tanimura
+ * All rights reserved.
+ *
+ * Portions of this source are based on cwcealdr.cpp and dhwiface.cpp in
+ * cwcealdr1.zip, the sample sources by Crystal Semiconductor.
+ * Copyright (c) 1996-1998 Crystal Semiconductor Corp.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
#include <sys/soundcard.h>
#include <dev/sound/pcm/sound.h>
@@ -38,7 +38,7 @@
#include <dev/pci/pcireg.h>
#include <dev/pci/pcivar.h>
-SND_DECLARE_FILE("$MidnightBSD$");
+SND_DECLARE_FILE("$FreeBSD: src/sys/dev/sound/pci/csapcm.c,v 1.41 2007/06/17 06:10:41 ariff Exp $");
/* Buffer size on dma transfer. Fixed for CS416x. */
#define CS461x_BUFFSIZE (4 * 1024)
@@ -49,30 +49,30 @@
struct csa_info;
struct csa_chinfo {
-struct csa_info *parent;
-struct pcm_channel *channel;
-struct snd_dbuf *buffer;
-int dir;
-u_int32_t fmt, spd;
-int dma;
+ struct csa_info *parent;
+ struct pcm_channel *channel;
+ struct snd_dbuf *buffer;
+ int dir;
+ u_int32_t fmt, spd;
+ int dma;
};
struct csa_info {
-csa_res res; /* resource */
-void *ih; /* Interrupt cookie */
-bus_dma_tag_t parent_dmat; /* DMA tag */
-struct csa_bridgeinfo *binfo; /* The state of the parent. */
-struct csa_card *card;
-
-int active;
-/* Contents of board's registers */
-u_long pfie;
-u_long pctl;
-u_long cctl;
-struct csa_chinfo pch, rch;
-u_int32_t ac97[CS461x_AC97_NUMBER_RESTORE_REGS];
-u_int32_t ac97_powerdown;
-u_int32_t ac97_general_purpose;
+ csa_res res; /* resource */
+ void *ih; /* Interrupt cookie */
+ bus_dma_tag_t parent_dmat; /* DMA tag */
+ struct csa_bridgeinfo *binfo; /* The state of the parent. */
+ struct csa_card *card;
+
+ int active;
+ /* Contents of board's registers */
+ u_long pfie;
+ u_long pctl;
+ u_long cctl;
+ struct csa_chinfo pch, rch;
+ u_int32_t ac97[CS461x_AC97_NUMBER_RESTORE_REGS];
+ u_int32_t ac97_powerdown;
+ u_int32_t ac97_general_purpose;
};
/* -------------------------------------------------------------------- */
@@ -94,22 +94,22 @@
static void csa_ac97_resume(struct csa_info *csa);
static u_int32_t csa_playfmt[] = {
-AFMT_U8,
-AFMT_STEREO | AFMT_U8,
-AFMT_S8,
-AFMT_STEREO | AFMT_S8,
-AFMT_S16_LE,
-AFMT_STEREO | AFMT_S16_LE,
-AFMT_S16_BE,
-AFMT_STEREO | AFMT_S16_BE,
-0
+ AFMT_U8,
+ AFMT_STEREO | AFMT_U8,
+ AFMT_S8,
+ AFMT_STEREO | AFMT_S8,
+ AFMT_S16_LE,
+ AFMT_STEREO | AFMT_S16_LE,
+ AFMT_S16_BE,
+ AFMT_STEREO | AFMT_S16_BE,
+ 0
};
static struct pcmchan_caps csa_playcaps = {8000, 48000, csa_playfmt, 0};
static u_int32_t csa_recfmt[] = {
-AFMT_S16_LE,
-AFMT_STEREO | AFMT_S16_LE,
-0
+ AFMT_S16_LE,
+ AFMT_STEREO | AFMT_S16_LE,
+ 0
};
static struct pcmchan_caps csa_reccaps = {11025, 48000, csa_recfmt, 0};
@@ -118,17 +118,17 @@
static int
csa_active(struct csa_info *csa, int run)
{
-int old;
+ int old;
-old = csa->active;
-csa->active += run;
+ old = csa->active;
+ csa->active += run;
-if ((csa->active > 1) || (csa->active < -1))
-csa->active = 0;
-if (csa->card->active)
-return (csa->card->active(!(csa->active && old)));
+ if ((csa->active > 1) || (csa->active < -1))
+ csa->active = 0;
+ if (csa->card->active)
+ return (csa->card->active(!(csa->active && old)));
-return 0;
+ return 0;
}
/* -------------------------------------------------------------------- */
@@ -137,388 +137,388 @@
static int
csa_rdcd(kobj_t obj, void *devinfo, int regno)
{
-u_int32_t data;
-struct csa_info *csa = (struct csa_info *)devinfo;
+ u_int32_t data;
+ struct csa_info *csa = (struct csa_info *)devinfo;
-csa_active(csa, 1);
-if (csa_readcodec(&csa->res, regno + BA0_AC97_RESET, &data))
-data = 0;
-csa_active(csa, -1);
+ csa_active(csa, 1);
+ if (csa_readcodec(&csa->res, regno + BA0_AC97_RESET, &data))
+ data = 0;
+ csa_active(csa, -1);
-return data;
+ return data;
}
static int
csa_wrcd(kobj_t obj, void *devinfo, int regno, u_int32_t data)
{
-struct csa_info *csa = (struct csa_info *)devinfo;
+ struct csa_info *csa = (struct csa_info *)devinfo;
-csa_active(csa, 1);
-csa_writecodec(&csa->res, regno + BA0_AC97_RESET, data);
-csa_active(csa, -1);
+ csa_active(csa, 1);
+ csa_writecodec(&csa->res, regno + BA0_AC97_RESET, data);
+ csa_active(csa, -1);
-return 0;
+ return 0;
}
static kobj_method_t csa_ac97_methods[] = {
-KOBJMETHOD(ac97_read, csa_rdcd),
-KOBJMETHOD(ac97_write, csa_wrcd),
-{ 0, 0 }
+ KOBJMETHOD(ac97_read, csa_rdcd),
+ KOBJMETHOD(ac97_write, csa_wrcd),
+ { 0, 0 }
};
AC97_DECLARE(csa_ac97);
static void
csa_setplaysamplerate(csa_res *resp, u_long ulInRate)
{
-u_long ulTemp1, ulTemp2;
-u_long ulPhiIncr;
-u_long ulCorrectionPerGOF, ulCorrectionPerSec;
-u_long ulOutRate;
-
-ulOutRate = 48000;
-
-/*
-* Compute the values used to drive the actual sample rate conversion.
-* The following formulas are being computed, using inline assembly
-* since we need to use 64 bit arithmetic to compute the values:
-*
-* ulPhiIncr = floor((Fs,in * 2^26) / Fs,out)
-* ulCorrectionPerGOF = floor((Fs,in * 2^26 - Fs,out * ulPhiIncr) /
-* GOF_PER_SEC)
-* ulCorrectionPerSec = Fs,in * 2^26 - Fs,out * phiIncr -
-* GOF_PER_SEC * ulCorrectionPerGOF
-*
-* i.e.
-*
-* ulPhiIncr:ulOther = dividend:remainder((Fs,in * 2^26) / Fs,out)
-* ulCorrectionPerGOF:ulCorrectionPerSec =
-* dividend:remainder(ulOther / GOF_PER_SEC)
-*/
-ulTemp1 = ulInRate << 16;
-ulPhiIncr = ulTemp1 / ulOutRate;
-ulTemp1 -= ulPhiIncr * ulOutRate;
-ulTemp1 <<= 10;
-ulPhiIncr <<= 10;
-ulTemp2 = ulTemp1 / ulOutRate;
-ulPhiIncr += ulTemp2;
-ulTemp1 -= ulTemp2 * ulOutRate;
-ulCorrectionPerGOF = ulTemp1 / GOF_PER_SEC;
-ulTemp1 -= ulCorrectionPerGOF * GOF_PER_SEC;
-ulCorrectionPerSec = ulTemp1;
-
-/*
-* Fill in the SampleRateConverter control block.
-*/
-csa_writemem(resp, BA1_PSRC, ((ulCorrectionPerSec << 16) & 0xFFFF0000) | (ulCorrectionPerGOF & 0xFFFF));
-csa_writemem(resp, BA1_PPI, ulPhiIncr);
+ u_long ulTemp1, ulTemp2;
+ u_long ulPhiIncr;
+ u_long ulCorrectionPerGOF, ulCorrectionPerSec;
+ u_long ulOutRate;
+
+ ulOutRate = 48000;
+
+ /*
+ * Compute the values used to drive the actual sample rate conversion.
+ * The following formulas are being computed, using inline assembly
+ * since we need to use 64 bit arithmetic to compute the values:
+ *
+ * ulPhiIncr = floor((Fs,in * 2^26) / Fs,out)
+ * ulCorrectionPerGOF = floor((Fs,in * 2^26 - Fs,out * ulPhiIncr) /
+ * GOF_PER_SEC)
+ * ulCorrectionPerSec = Fs,in * 2^26 - Fs,out * phiIncr -
+ * GOF_PER_SEC * ulCorrectionPerGOF
+ *
+ * i.e.
+ *
+ * ulPhiIncr:ulOther = dividend:remainder((Fs,in * 2^26) / Fs,out)
+ * ulCorrectionPerGOF:ulCorrectionPerSec =
+ * dividend:remainder(ulOther / GOF_PER_SEC)
+ */
+ ulTemp1 = ulInRate << 16;
+ ulPhiIncr = ulTemp1 / ulOutRate;
+ ulTemp1 -= ulPhiIncr * ulOutRate;
+ ulTemp1 <<= 10;
+ ulPhiIncr <<= 10;
+ ulTemp2 = ulTemp1 / ulOutRate;
+ ulPhiIncr += ulTemp2;
+ ulTemp1 -= ulTemp2 * ulOutRate;
+ ulCorrectionPerGOF = ulTemp1 / GOF_PER_SEC;
+ ulTemp1 -= ulCorrectionPerGOF * GOF_PER_SEC;
+ ulCorrectionPerSec = ulTemp1;
+
+ /*
+ * Fill in the SampleRateConverter control block.
+ */
+ csa_writemem(resp, BA1_PSRC, ((ulCorrectionPerSec << 16) & 0xFFFF0000) | (ulCorrectionPerGOF & 0xFFFF));
+ csa_writemem(resp, BA1_PPI, ulPhiIncr);
}
static void
csa_setcapturesamplerate(csa_res *resp, u_long ulOutRate)
{
-u_long ulPhiIncr, ulCoeffIncr, ulTemp1, ulTemp2;
-u_long ulCorrectionPerGOF, ulCorrectionPerSec, ulInitialDelay;
-u_long dwFrameGroupLength, dwCnt;
-u_long ulInRate;
-
-ulInRate = 48000;
-
-/*
-* We can only decimate by up to a factor of 1/9th the hardware rate.
-* Return an error if an attempt is made to stray outside that limit.
-*/
-if((ulOutRate * 9) < ulInRate)
-return;
-
-/*
-* We can not capture at at rate greater than the Input Rate (48000).
-* Return an error if an attempt is made to stray outside that limit.
-*/
-if(ulOutRate > ulInRate)
-return;
-
-/*
-* Compute the values used to drive the actual sample rate conversion.
-* The following formulas are being computed, using inline assembly
-* since we need to use 64 bit arithmetic to compute the values:
-*
-* ulCoeffIncr = -floor((Fs,out * 2^23) / Fs,in)
-* ulPhiIncr = floor((Fs,in * 2^26) / Fs,out)
-* ulCorrectionPerGOF = floor((Fs,in * 2^26 - Fs,out * ulPhiIncr) /
-* GOF_PER_SEC)
-* ulCorrectionPerSec = Fs,in * 2^26 - Fs,out * phiIncr -
-* GOF_PER_SEC * ulCorrectionPerGOF
-* ulInitialDelay = ceil((24 * Fs,in) / Fs,out)
-*
-* i.e.
-*
-* ulCoeffIncr = neg(dividend((Fs,out * 2^23) / Fs,in))
-* ulPhiIncr:ulOther = dividend:remainder((Fs,in * 2^26) / Fs,out)
-* ulCorrectionPerGOF:ulCorrectionPerSec =
-* dividend:remainder(ulOther / GOF_PER_SEC)
-* ulInitialDelay = dividend(((24 * Fs,in) + Fs,out - 1) / Fs,out)
-*/
-ulTemp1 = ulOutRate << 16;
-ulCoeffIncr = ulTemp1 / ulInRate;
-ulTemp1 -= ulCoeffIncr * ulInRate;
-ulTemp1 <<= 7;
-ulCoeffIncr <<= 7;
-ulCoeffIncr += ulTemp1 / ulInRate;
-ulCoeffIncr ^= 0xFFFFFFFF;
-ulCoeffIncr++;
-ulTemp1 = ulInRate << 16;
-ulPhiIncr = ulTemp1 / ulOutRate;
-ulTemp1 -= ulPhiIncr * ulOutRate;
-ulTemp1 <<= 10;
-ulPhiIncr <<= 10;
-ulTemp2 = ulTemp1 / ulOutRate;
-ulPhiIncr += ulTemp2;
-ulTemp1 -= ulTemp2 * ulOutRate;
-ulCorrectionPerGOF = ulTemp1 / GOF_PER_SEC;
-ulTemp1 -= ulCorrectionPerGOF * GOF_PER_SEC;
-ulCorrectionPerSec = ulTemp1;
-ulInitialDelay = ((ulInRate * 24) + ulOutRate - 1) / ulOutRate;
-
-/*
-* Fill in the VariDecimate control block.
-*/
-csa_writemem(resp, BA1_CSRC,
-((ulCorrectionPerSec << 16) & 0xFFFF0000) | (ulCorrectionPerGOF & 0xFFFF));
-csa_writemem(resp, BA1_CCI, ulCoeffIncr);
-csa_writemem(resp, BA1_CD,
-(((BA1_VARIDEC_BUF_1 + (ulInitialDelay << 2)) << 16) & 0xFFFF0000) | 0x80);
-csa_writemem(resp, BA1_CPI, ulPhiIncr);
-
-/*
-* Figure out the frame group length for the write back task. Basically,
-* this is just the factors of 24000 (2^6*3*5^3) that are not present in
-* the output sample rate.
-*/
-dwFrameGroupLength = 1;
-for(dwCnt = 2; dwCnt <= 64; dwCnt *= 2)
-{
-if(((ulOutRate / dwCnt) * dwCnt) !=
-ulOutRate)
-{
-dwFrameGroupLength *= 2;
-}
-}
-if(((ulOutRate / 3) * 3) !=
-ulOutRate)
-{
-dwFrameGroupLength *= 3;
-}
-for(dwCnt = 5; dwCnt <= 125; dwCnt *= 5)
-{
-if(((ulOutRate / dwCnt) * dwCnt) !=
-ulOutRate)
-{
-dwFrameGroupLength *= 5;
-}
-}
-
-/*
-* Fill in the WriteBack control block.
-*/
-csa_writemem(resp, BA1_CFG1, dwFrameGroupLength);
-csa_writemem(resp, BA1_CFG2, (0x00800000 | dwFrameGroupLength));
-csa_writemem(resp, BA1_CCST, 0x0000FFFF);
-csa_writemem(resp, BA1_CSPB, ((65536 * ulOutRate) / 24000));
-csa_writemem(resp, (BA1_CSPB + 4), 0x0000FFFF);
+ u_long ulPhiIncr, ulCoeffIncr, ulTemp1, ulTemp2;
+ u_long ulCorrectionPerGOF, ulCorrectionPerSec, ulInitialDelay;
+ u_long dwFrameGroupLength, dwCnt;
+ u_long ulInRate;
+
+ ulInRate = 48000;
+
+ /*
+ * We can only decimate by up to a factor of 1/9th the hardware rate.
+ * Return an error if an attempt is made to stray outside that limit.
+ */
+ if((ulOutRate * 9) < ulInRate)
+ return;
+
+ /*
+ * We can not capture at at rate greater than the Input Rate (48000).
+ * Return an error if an attempt is made to stray outside that limit.
+ */
+ if(ulOutRate > ulInRate)
+ return;
+
+ /*
+ * Compute the values used to drive the actual sample rate conversion.
+ * The following formulas are being computed, using inline assembly
+ * since we need to use 64 bit arithmetic to compute the values:
+ *
+ * ulCoeffIncr = -floor((Fs,out * 2^23) / Fs,in)
+ * ulPhiIncr = floor((Fs,in * 2^26) / Fs,out)
+ * ulCorrectionPerGOF = floor((Fs,in * 2^26 - Fs,out * ulPhiIncr) /
+ * GOF_PER_SEC)
+ * ulCorrectionPerSec = Fs,in * 2^26 - Fs,out * phiIncr -
+ * GOF_PER_SEC * ulCorrectionPerGOF
+ * ulInitialDelay = ceil((24 * Fs,in) / Fs,out)
+ *
+ * i.e.
+ *
+ * ulCoeffIncr = neg(dividend((Fs,out * 2^23) / Fs,in))
+ * ulPhiIncr:ulOther = dividend:remainder((Fs,in * 2^26) / Fs,out)
+ * ulCorrectionPerGOF:ulCorrectionPerSec =
+ * dividend:remainder(ulOther / GOF_PER_SEC)
+ * ulInitialDelay = dividend(((24 * Fs,in) + Fs,out - 1) / Fs,out)
+ */
+ ulTemp1 = ulOutRate << 16;
+ ulCoeffIncr = ulTemp1 / ulInRate;
+ ulTemp1 -= ulCoeffIncr * ulInRate;
+ ulTemp1 <<= 7;
+ ulCoeffIncr <<= 7;
+ ulCoeffIncr += ulTemp1 / ulInRate;
+ ulCoeffIncr ^= 0xFFFFFFFF;
+ ulCoeffIncr++;
+ ulTemp1 = ulInRate << 16;
+ ulPhiIncr = ulTemp1 / ulOutRate;
+ ulTemp1 -= ulPhiIncr * ulOutRate;
+ ulTemp1 <<= 10;
+ ulPhiIncr <<= 10;
+ ulTemp2 = ulTemp1 / ulOutRate;
+ ulPhiIncr += ulTemp2;
+ ulTemp1 -= ulTemp2 * ulOutRate;
+ ulCorrectionPerGOF = ulTemp1 / GOF_PER_SEC;
+ ulTemp1 -= ulCorrectionPerGOF * GOF_PER_SEC;
+ ulCorrectionPerSec = ulTemp1;
+ ulInitialDelay = ((ulInRate * 24) + ulOutRate - 1) / ulOutRate;
+
+ /*
+ * Fill in the VariDecimate control block.
+ */
+ csa_writemem(resp, BA1_CSRC,
+ ((ulCorrectionPerSec << 16) & 0xFFFF0000) | (ulCorrectionPerGOF & 0xFFFF));
+ csa_writemem(resp, BA1_CCI, ulCoeffIncr);
+ csa_writemem(resp, BA1_CD,
+ (((BA1_VARIDEC_BUF_1 + (ulInitialDelay << 2)) << 16) & 0xFFFF0000) | 0x80);
+ csa_writemem(resp, BA1_CPI, ulPhiIncr);
+
+ /*
+ * Figure out the frame group length for the write back task. Basically,
+ * this is just the factors of 24000 (2^6*3*5^3) that are not present in
+ * the output sample rate.
+ */
+ dwFrameGroupLength = 1;
+ for(dwCnt = 2; dwCnt <= 64; dwCnt *= 2)
+ {
+ if(((ulOutRate / dwCnt) * dwCnt) !=
+ ulOutRate)
+ {
+ dwFrameGroupLength *= 2;
+ }
+ }
+ if(((ulOutRate / 3) * 3) !=
+ ulOutRate)
+ {
+ dwFrameGroupLength *= 3;
+ }
+ for(dwCnt = 5; dwCnt <= 125; dwCnt *= 5)
+ {
+ if(((ulOutRate / dwCnt) * dwCnt) !=
+ ulOutRate)
+ {
+ dwFrameGroupLength *= 5;
+ }
+ }
+
+ /*
+ * Fill in the WriteBack control block.
+ */
+ csa_writemem(resp, BA1_CFG1, dwFrameGroupLength);
+ csa_writemem(resp, BA1_CFG2, (0x00800000 | dwFrameGroupLength));
+ csa_writemem(resp, BA1_CCST, 0x0000FFFF);
+ csa_writemem(resp, BA1_CSPB, ((65536 * ulOutRate) / 24000));
+ csa_writemem(resp, (BA1_CSPB + 4), 0x0000FFFF);
}
static void
csa_startplaydma(struct csa_info *csa)
{
-csa_res *resp;
-u_long ul;
+ csa_res *resp;
+ u_long ul;
-if (!csa->pch.dma) {
-resp = &csa->res;
-ul = csa_readmem(resp, BA1_PCTL);
-ul &= 0x0000ffff;
-csa_writemem(resp, BA1_PCTL, ul | csa->pctl);
-csa_writemem(resp, BA1_PVOL, 0x80008000);
-csa->pch.dma = 1;
-}
+ if (!csa->pch.dma) {
+ resp = &csa->res;
+ ul = csa_readmem(resp, BA1_PCTL);
+ ul &= 0x0000ffff;
+ csa_writemem(resp, BA1_PCTL, ul | csa->pctl);
+ csa_writemem(resp, BA1_PVOL, 0x80008000);
+ csa->pch.dma = 1;
+ }
}
static void
csa_startcapturedma(struct csa_info *csa)
{
-csa_res *resp;
-u_long ul;
+ csa_res *resp;
+ u_long ul;
-if (!csa->rch.dma) {
-resp = &csa->res;
-ul = csa_readmem(resp, BA1_CCTL);
-ul &= 0xffff0000;
-csa_writemem(resp, BA1_CCTL, ul | csa->cctl);
-csa_writemem(resp, BA1_CVOL, 0x80008000);
-csa->rch.dma = 1;
-}
+ if (!csa->rch.dma) {
+ resp = &csa->res;
+ ul = csa_readmem(resp, BA1_CCTL);
+ ul &= 0xffff0000;
+ csa_writemem(resp, BA1_CCTL, ul | csa->cctl);
+ csa_writemem(resp, BA1_CVOL, 0x80008000);
+ csa->rch.dma = 1;
+ }
}
static void
csa_stopplaydma(struct csa_info *csa)
{
-csa_res *resp;
-u_long ul;
+ csa_res *resp;
+ u_long ul;
-if (csa->pch.dma) {
-resp = &csa->res;
-ul = csa_readmem(resp, BA1_PCTL);
-csa->pctl = ul & 0xffff0000;
-csa_writemem(resp, BA1_PCTL, ul & 0x0000ffff);
-csa_writemem(resp, BA1_PVOL, 0xffffffff);
-csa->pch.dma = 0;
-
-/*
-* The bitwise pointer of the serial FIFO in the DSP
-* seems to make an error upon starting or stopping the
-* DSP. Clear the FIFO and correct the pointer if we
-* are not capturing.
-*/
-if (!csa->rch.dma) {
-csa_clearserialfifos(resp);
-csa_writeio(resp, BA0_SERBSP, 0);
-}
-}
+ if (csa->pch.dma) {
+ resp = &csa->res;
+ ul = csa_readmem(resp, BA1_PCTL);
+ csa->pctl = ul & 0xffff0000;
+ csa_writemem(resp, BA1_PCTL, ul & 0x0000ffff);
+ csa_writemem(resp, BA1_PVOL, 0xffffffff);
+ csa->pch.dma = 0;
+
+ /*
+ * The bitwise pointer of the serial FIFO in the DSP
+ * seems to make an error upon starting or stopping the
+ * DSP. Clear the FIFO and correct the pointer if we
+ * are not capturing.
+ */
+ if (!csa->rch.dma) {
+ csa_clearserialfifos(resp);
+ csa_writeio(resp, BA0_SERBSP, 0);
+ }
+ }
}
static void
csa_stopcapturedma(struct csa_info *csa)
{
-csa_res *resp;
-u_long ul;
+ csa_res *resp;
+ u_long ul;
-if (csa->rch.dma) {
-resp = &csa->res;
-ul = csa_readmem(resp, BA1_CCTL);
-csa->cctl = ul & 0x0000ffff;
-csa_writemem(resp, BA1_CCTL, ul & 0xffff0000);
-csa_writemem(resp, BA1_CVOL, 0xffffffff);
-csa->rch.dma = 0;
-
-/*
-* The bitwise pointer of the serial FIFO in the DSP
-* seems to make an error upon starting or stopping the
-* DSP. Clear the FIFO and correct the pointer if we
-* are not playing.
-*/
-if (!csa->pch.dma) {
-csa_clearserialfifos(resp);
-csa_writeio(resp, BA0_SERBSP, 0);
-}
-}
+ if (csa->rch.dma) {
+ resp = &csa->res;
+ ul = csa_readmem(resp, BA1_CCTL);
+ csa->cctl = ul & 0x0000ffff;
+ csa_writemem(resp, BA1_CCTL, ul & 0xffff0000);
+ csa_writemem(resp, BA1_CVOL, 0xffffffff);
+ csa->rch.dma = 0;
+
+ /*
+ * The bitwise pointer of the serial FIFO in the DSP
+ * seems to make an error upon starting or stopping the
+ * DSP. Clear the FIFO and correct the pointer if we
+ * are not playing.
+ */
+ if (!csa->pch.dma) {
+ csa_clearserialfifos(resp);
+ csa_writeio(resp, BA0_SERBSP, 0);
+ }
+ }
}
static int
csa_startdsp(csa_res *resp)
{
-int i;
-u_long ul;
-
-/*
-* Set the frame timer to reflect the number of cycles per frame.
-*/
-csa_writemem(resp, BA1_FRMT, 0xadf);
-
-/*
-* Turn on the run, run at frame, and DMA enable bits in the local copy of
-* the SP control register.
-*/
-csa_writemem(resp, BA1_SPCR, SPCR_RUN | SPCR_RUNFR | SPCR_DRQEN);
-
-/*
-* Wait until the run at frame bit resets itself in the SP control
-* register.
-*/
-ul = 0;
-for (i = 0 ; i < 25 ; i++) {
-/*
-* Wait a little bit, so we don't issue PCI reads too frequently.
-*/
-DELAY(50);
-/*
-* Fetch the current value of the SP status register.
-*/
-ul = csa_readmem(resp, BA1_SPCR);
+ int i;
+ u_long ul;
-/*
-* If the run at frame bit has reset, then stop waiting.
-*/
-if((ul & SPCR_RUNFR) == 0)
-break;
-}
-/*
-* If the run at frame bit never reset, then return an error.
-*/
-if((ul & SPCR_RUNFR) != 0)
-return (EAGAIN);
+ /*
+ * Set the frame timer to reflect the number of cycles per frame.
+ */
+ csa_writemem(resp, BA1_FRMT, 0xadf);
+
+ /*
+ * Turn on the run, run at frame, and DMA enable bits in the local copy of
+ * the SP control register.
+ */
+ csa_writemem(resp, BA1_SPCR, SPCR_RUN | SPCR_RUNFR | SPCR_DRQEN);
+
+ /*
+ * Wait until the run at frame bit resets itself in the SP control
+ * register.
+ */
+ ul = 0;
+ for (i = 0 ; i < 25 ; i++) {
+ /*
+ * Wait a little bit, so we don't issue PCI reads too frequently.
+ */
+ DELAY(50);
+ /*
+ * Fetch the current value of the SP status register.
+ */
+ ul = csa_readmem(resp, BA1_SPCR);
+
+ /*
+ * If the run at frame bit has reset, then stop waiting.
+ */
+ if((ul & SPCR_RUNFR) == 0)
+ break;
+ }
+ /*
+ * If the run at frame bit never reset, then return an error.
+ */
+ if((ul & SPCR_RUNFR) != 0)
+ return (EAGAIN);
-return (0);
+ return (0);
}
static int
csa_stopdsp(csa_res *resp)
{
-/*
-* Turn off the run, run at frame, and DMA enable bits in
-* the local copy of the SP control register.
-*/
-csa_writemem(resp, BA1_SPCR, 0);
+ /*
+ * Turn off the run, run at frame, and DMA enable bits in
+ * the local copy of the SP control register.
+ */
+ csa_writemem(resp, BA1_SPCR, 0);
-return (0);
+ return (0);
}
static int
csa_setupchan(struct csa_chinfo *ch)
{
-struct csa_info *csa = ch->parent;
-csa_res *resp = &csa->res;
-u_long pdtc, tmp;
-
-if (ch->dir == PCMDIR_PLAY) {
-/* direction */
-csa_writemem(resp, BA1_PBA, sndbuf_getbufaddr(ch->buffer));
-
-/* format */
-csa->pfie = csa_readmem(resp, BA1_PFIE) & ~0x0000f03f;
-if (!(ch->fmt & AFMT_SIGNED))
-csa->pfie |= 0x8000;
-if (ch->fmt & AFMT_BIGENDIAN)
-csa->pfie |= 0x4000;
-if (!(ch->fmt & AFMT_STEREO))
-csa->pfie |= 0x2000;
-if (ch->fmt & AFMT_8BIT)
-csa->pfie |= 0x1000;
-csa_writemem(resp, BA1_PFIE, csa->pfie);
-
-tmp = 4;
-if (ch->fmt & AFMT_16BIT)
-tmp <<= 1;
-if (ch->fmt & AFMT_STEREO)
-tmp <<= 1;
-tmp--;
-
-pdtc = csa_readmem(resp, BA1_PDTC) & ~0x000001ff;
-pdtc |= tmp;
-csa_writemem(resp, BA1_PDTC, pdtc);
-
-/* rate */
-csa_setplaysamplerate(resp, ch->spd);
-} else if (ch->dir == PCMDIR_REC) {
-/* direction */
-csa_writemem(resp, BA1_CBA, sndbuf_getbufaddr(ch->buffer));
-
-/* format */
-csa_writemem(resp, BA1_CIE, (csa_readmem(resp, BA1_CIE) & ~0x0000003f) | 0x00000001);
-
-/* rate */
-csa_setcapturesamplerate(resp, ch->spd);
-}
-return 0;
+ struct csa_info *csa = ch->parent;
+ csa_res *resp = &csa->res;
+ u_long pdtc, tmp;
+
+ if (ch->dir == PCMDIR_PLAY) {
+ /* direction */
+ csa_writemem(resp, BA1_PBA, sndbuf_getbufaddr(ch->buffer));
+
+ /* format */
+ csa->pfie = csa_readmem(resp, BA1_PFIE) & ~0x0000f03f;
+ if (!(ch->fmt & AFMT_SIGNED))
+ csa->pfie |= 0x8000;
+ if (ch->fmt & AFMT_BIGENDIAN)
+ csa->pfie |= 0x4000;
+ if (!(ch->fmt & AFMT_STEREO))
+ csa->pfie |= 0x2000;
+ if (ch->fmt & AFMT_8BIT)
+ csa->pfie |= 0x1000;
+ csa_writemem(resp, BA1_PFIE, csa->pfie);
+
+ tmp = 4;
+ if (ch->fmt & AFMT_16BIT)
+ tmp <<= 1;
+ if (ch->fmt & AFMT_STEREO)
+ tmp <<= 1;
+ tmp--;
+
+ pdtc = csa_readmem(resp, BA1_PDTC) & ~0x000001ff;
+ pdtc |= tmp;
+ csa_writemem(resp, BA1_PDTC, pdtc);
+
+ /* rate */
+ csa_setplaysamplerate(resp, ch->spd);
+ } else if (ch->dir == PCMDIR_REC) {
+ /* direction */
+ csa_writemem(resp, BA1_CBA, sndbuf_getbufaddr(ch->buffer));
+
+ /* format */
+ csa_writemem(resp, BA1_CIE, (csa_readmem(resp, BA1_CIE) & ~0x0000003f) | 0x00000001);
+
+ /* rate */
+ csa_setcapturesamplerate(resp, ch->spd);
+ }
+ return 0;
}
/* -------------------------------------------------------------------- */
@@ -527,107 +527,107 @@
static void *
csachan_init(kobj_t obj, void *devinfo, struct snd_dbuf *b, struct pcm_channel *c, int dir)
{
-struct csa_info *csa = devinfo;
-struct csa_chinfo *ch = (dir == PCMDIR_PLAY)? &csa->pch : &csa->rch;
+ struct csa_info *csa = devinfo;
+ struct csa_chinfo *ch = (dir == PCMDIR_PLAY)? &csa->pch : &csa->rch;
-ch->parent = csa;
-ch->channel = c;
-ch->buffer = b;
-ch->dir = dir;
-if (sndbuf_alloc(ch->buffer, csa->parent_dmat, CS461x_BUFFSIZE) != 0)
-return NULL;
-return ch;
+ ch->parent = csa;
+ ch->channel = c;
+ ch->buffer = b;
+ ch->dir = dir;
+ if (sndbuf_alloc(ch->buffer, csa->parent_dmat, 0, CS461x_BUFFSIZE) != 0)
+ return NULL;
+ return ch;
}
static int
csachan_setformat(kobj_t obj, void *data, u_int32_t format)
{
-struct csa_chinfo *ch = data;
+ struct csa_chinfo *ch = data;
-ch->fmt = format;
-return 0;
+ ch->fmt = format;
+ return 0;
}
static int
csachan_setspeed(kobj_t obj, void *data, u_int32_t speed)
{
-struct csa_chinfo *ch = data;
+ struct csa_chinfo *ch = data;
-ch->spd = speed;
-return ch->spd; /* XXX calc real speed */
+ ch->spd = speed;
+ return ch->spd; /* XXX calc real speed */
}
static int
csachan_setblocksize(kobj_t obj, void *data, u_int32_t blocksize)
{
-return CS461x_BUFFSIZE / 2;
+ return CS461x_BUFFSIZE / 2;
}
static int
csachan_trigger(kobj_t obj, void *data, int go)
{
-struct csa_chinfo *ch = data;
-struct csa_info *csa = ch->parent;
+ struct csa_chinfo *ch = data;
+ struct csa_info *csa = ch->parent;
-if (go == PCMTRIG_EMLDMAWR || go == PCMTRIG_EMLDMARD)
-return 0;
+ if (!PCMTRIG_COMMON(go))
+ return 0;
-if (go == PCMTRIG_START) {
-csa_active(csa, 1);
-csa_setupchan(ch);
-if (ch->dir == PCMDIR_PLAY)
-csa_startplaydma(csa);
-else
-csa_startcapturedma(csa);
-} else {
-if (ch->dir == PCMDIR_PLAY)
-csa_stopplaydma(csa);
-else
-csa_stopcapturedma(csa);
-csa_active(csa, -1);
-}
-return 0;
+ if (go == PCMTRIG_START) {
+ csa_active(csa, 1);
+ csa_setupchan(ch);
+ if (ch->dir == PCMDIR_PLAY)
+ csa_startplaydma(csa);
+ else
+ csa_startcapturedma(csa);
+ } else {
+ if (ch->dir == PCMDIR_PLAY)
+ csa_stopplaydma(csa);
+ else
+ csa_stopcapturedma(csa);
+ csa_active(csa, -1);
+ }
+ return 0;
}
static int
csachan_getptr(kobj_t obj, void *data)
{
-struct csa_chinfo *ch = data;
-struct csa_info *csa = ch->parent;
-csa_res *resp;
-int ptr;
-
-resp = &csa->res;
-
-if (ch->dir == PCMDIR_PLAY) {
-ptr = csa_readmem(resp, BA1_PBA) - sndbuf_getbufaddr(ch->buffer);
-if ((ch->fmt & AFMT_U8) != 0 || (ch->fmt & AFMT_S8) != 0)
-ptr >>= 1;
-} else {
-ptr = csa_readmem(resp, BA1_CBA) - sndbuf_getbufaddr(ch->buffer);
-if ((ch->fmt & AFMT_U8) != 0 || (ch->fmt & AFMT_S8) != 0)
-ptr >>= 1;
-}
+ struct csa_chinfo *ch = data;
+ struct csa_info *csa = ch->parent;
+ csa_res *resp;
+ int ptr;
+
+ resp = &csa->res;
+
+ if (ch->dir == PCMDIR_PLAY) {
+ ptr = csa_readmem(resp, BA1_PBA) - sndbuf_getbufaddr(ch->buffer);
+ if ((ch->fmt & AFMT_U8) != 0 || (ch->fmt & AFMT_S8) != 0)
+ ptr >>= 1;
+ } else {
+ ptr = csa_readmem(resp, BA1_CBA) - sndbuf_getbufaddr(ch->buffer);
+ if ((ch->fmt & AFMT_U8) != 0 || (ch->fmt & AFMT_S8) != 0)
+ ptr >>= 1;
+ }
-return (ptr);
+ return (ptr);
}
static struct pcmchan_caps *
csachan_getcaps(kobj_t obj, void *data)
{
-struct csa_chinfo *ch = data;
-return (ch->dir == PCMDIR_PLAY)? &csa_playcaps : &csa_reccaps;
+ struct csa_chinfo *ch = data;
+ return (ch->dir == PCMDIR_PLAY)? &csa_playcaps : &csa_reccaps;
}
static kobj_method_t csachan_methods[] = {
-KOBJMETHOD(channel_init, csachan_init),
-KOBJMETHOD(channel_setformat, csachan_setformat),
-KOBJMETHOD(channel_setspeed, csachan_setspeed),
-KOBJMETHOD(channel_setblocksize, csachan_setblocksize),
-KOBJMETHOD(channel_trigger, csachan_trigger),
-KOBJMETHOD(channel_getptr, csachan_getptr),
-KOBJMETHOD(channel_getcaps, csachan_getcaps),
-{ 0, 0 }
+ KOBJMETHOD(channel_init, csachan_init),
+ KOBJMETHOD(channel_setformat, csachan_setformat),
+ KOBJMETHOD(channel_setspeed, csachan_setspeed),
+ KOBJMETHOD(channel_setblocksize, csachan_setblocksize),
+ KOBJMETHOD(channel_trigger, csachan_trigger),
+ KOBJMETHOD(channel_getptr, csachan_getptr),
+ KOBJMETHOD(channel_getcaps, csachan_getcaps),
+ { 0, 0 }
};
CHANNEL_DECLARE(csachan);
@@ -636,400 +636,400 @@
static void
csa_intr(void *p)
{
-struct csa_info *csa = p;
+ struct csa_info *csa = p;
-if ((csa->binfo->hisr & HISR_VC0) != 0)
-chn_intr(csa->pch.channel);
-if ((csa->binfo->hisr & HISR_VC1) != 0)
-chn_intr(csa->rch.channel);
+ if ((csa->binfo->hisr & HISR_VC0) != 0)
+ chn_intr(csa->pch.channel);
+ if ((csa->binfo->hisr & HISR_VC1) != 0)
+ chn_intr(csa->rch.channel);
}
/* -------------------------------------------------------------------- */
/*
-* Probe and attach the card
-*/
+ * Probe and attach the card
+ */
static int
csa_init(struct csa_info *csa)
{
-csa_res *resp;
+ csa_res *resp;
-resp = &csa->res;
+ resp = &csa->res;
-csa->pfie = 0;
-csa_stopplaydma(csa);
-csa_stopcapturedma(csa);
-
-if (csa_startdsp(resp))
-return (1);
-
-/* Crank up the power on the DAC and ADC. */
-csa_setplaysamplerate(resp, 8000);
-csa_setcapturesamplerate(resp, 8000);
-/* Set defaults */
-csa_writeio(resp, BA0_EGPIODR, EGPIODR_GPOE0);
-csa_writeio(resp, BA0_EGPIOPTR, EGPIOPTR_GPPT0);
-/* Power up amplifier */
-csa_writeio(resp, BA0_EGPIODR, csa_readio(resp, BA0_EGPIODR) |
-EGPIODR_GPOE2);
-csa_writeio(resp, BA0_EGPIOPTR, csa_readio(resp, BA0_EGPIOPTR) |
-EGPIOPTR_GPPT2);
+ csa->pfie = 0;
+ csa_stopplaydma(csa);
+ csa_stopcapturedma(csa);
+
+ if (csa_startdsp(resp))
+ return (1);
+
+ /* Crank up the power on the DAC and ADC. */
+ csa_setplaysamplerate(resp, 8000);
+ csa_setcapturesamplerate(resp, 8000);
+ /* Set defaults */
+ csa_writeio(resp, BA0_EGPIODR, EGPIODR_GPOE0);
+ csa_writeio(resp, BA0_EGPIOPTR, EGPIOPTR_GPPT0);
+ /* Power up amplifier */
+ csa_writeio(resp, BA0_EGPIODR, csa_readio(resp, BA0_EGPIODR) |
+ EGPIODR_GPOE2);
+ csa_writeio(resp, BA0_EGPIOPTR, csa_readio(resp, BA0_EGPIOPTR) |
+ EGPIOPTR_GPPT2);
-return 0;
+ return 0;
}
/* Allocates resources. */
static int
csa_allocres(struct csa_info *csa, device_t dev)
{
-csa_res *resp;
+ csa_res *resp;
-resp = &csa->res;
-if (resp->io == NULL) {
-resp->io = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
-&resp->io_rid, RF_ACTIVE);
-if (resp->io == NULL)
-return (1);
-}
-if (resp->mem == NULL) {
-resp->mem = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
-&resp->mem_rid, RF_ACTIVE);
-if (resp->mem == NULL)
-return (1);
-}
-if (resp->irq == NULL) {
-resp->irq = bus_alloc_resource_any(dev, SYS_RES_IRQ,
-&resp->irq_rid, RF_ACTIVE | RF_SHAREABLE);
-if (resp->irq == NULL)
-return (1);
-}
-if (bus_dma_tag_create(/*parent*/NULL, /*alignment*/CS461x_BUFFSIZE, /*boundary*/CS461x_BUFFSIZE,
-/*lowaddr*/BUS_SPACE_MAXADDR_32BIT,
-/*highaddr*/BUS_SPACE_MAXADDR,
-/*filter*/NULL, /*filterarg*/NULL,
-/*maxsize*/CS461x_BUFFSIZE, /*nsegments*/1, /*maxsegz*/0x3ffff,
-/*flags*/0, /*lockfunc*/busdma_lock_mutex,
-/*lockarg*/&Giant, &csa->parent_dmat) != 0)
-return (1);
+ resp = &csa->res;
+ if (resp->io == NULL) {
+ resp->io = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
+ &resp->io_rid, RF_ACTIVE);
+ if (resp->io == NULL)
+ return (1);
+ }
+ if (resp->mem == NULL) {
+ resp->mem = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
+ &resp->mem_rid, RF_ACTIVE);
+ if (resp->mem == NULL)
+ return (1);
+ }
+ if (resp->irq == NULL) {
+ resp->irq = bus_alloc_resource_any(dev, SYS_RES_IRQ,
+ &resp->irq_rid, RF_ACTIVE | RF_SHAREABLE);
+ if (resp->irq == NULL)
+ return (1);
+ }
+ if (bus_dma_tag_create(/*parent*/bus_get_dma_tag(dev),
+ /*alignment*/CS461x_BUFFSIZE,
+ /*boundary*/CS461x_BUFFSIZE,
+ /*lowaddr*/BUS_SPACE_MAXADDR_32BIT,
+ /*highaddr*/BUS_SPACE_MAXADDR,
+ /*filter*/NULL, /*filterarg*/NULL,
+ /*maxsize*/CS461x_BUFFSIZE, /*nsegments*/1, /*maxsegz*/0x3ffff,
+ /*flags*/0, /*lockfunc*/busdma_lock_mutex,
+ /*lockarg*/&Giant, &csa->parent_dmat) != 0)
+ return (1);
-return (0);
+ return (0);
}
/* Releases resources. */
static void
csa_releaseres(struct csa_info *csa, device_t dev)
{
-csa_res *resp;
+ csa_res *resp;
-KASSERT(csa != NULL, ("called with bogus resource structure"));
+ KASSERT(csa != NULL, ("called with bogus resource structure"));
-resp = &csa->res;
-if (resp->irq != NULL) {
-if (csa->ih)
-bus_teardown_intr(dev, resp->irq, csa->ih);
-bus_release_resource(dev, SYS_RES_IRQ, resp->irq_rid, resp->irq);
-resp->irq = NULL;
-}
-if (resp->io != NULL) {
-bus_release_resource(dev, SYS_RES_MEMORY, resp->io_rid, resp->io);
-resp->io = NULL;
-}
-if (resp->mem != NULL) {
-bus_release_resource(dev, SYS_RES_MEMORY, resp->mem_rid, resp->mem);
-resp->mem = NULL;
-}
-if (csa->parent_dmat != NULL) {
-bus_dma_tag_destroy(csa->parent_dmat);
-csa->parent_dmat = NULL;
-}
+ resp = &csa->res;
+ if (resp->irq != NULL) {
+ if (csa->ih)
+ bus_teardown_intr(dev, resp->irq, csa->ih);
+ bus_release_resource(dev, SYS_RES_IRQ, resp->irq_rid, resp->irq);
+ resp->irq = NULL;
+ }
+ if (resp->io != NULL) {
+ bus_release_resource(dev, SYS_RES_MEMORY, resp->io_rid, resp->io);
+ resp->io = NULL;
+ }
+ if (resp->mem != NULL) {
+ bus_release_resource(dev, SYS_RES_MEMORY, resp->mem_rid, resp->mem);
+ resp->mem = NULL;
+ }
+ if (csa->parent_dmat != NULL) {
+ bus_dma_tag_destroy(csa->parent_dmat);
+ csa->parent_dmat = NULL;
+ }
-free(csa, M_DEVBUF);
+ free(csa, M_DEVBUF);
}
static int
pcmcsa_probe(device_t dev)
{
-char *s;
-struct sndcard_func *func;
+ char *s;
+ struct sndcard_func *func;
-/* The parent device has already been probed. */
+ /* The parent device has already been probed. */
-func = device_get_ivars(dev);
-if (func == NULL || func->func != SCF_PCM)
-return (ENXIO);
+ func = device_get_ivars(dev);
+ if (func == NULL || func->func != SCF_PCM)
+ return (ENXIO);
-s = "CS461x PCM Audio";
+ s = "CS461x PCM Audio";
-device_set_desc(dev, s);
-return (0);
+ device_set_desc(dev, s);
+ return (0);
}
static int
pcmcsa_attach(device_t dev)
{
-struct csa_info *csa;
-csa_res *resp;
-int unit;
-char status[SND_STATUSLEN];
-struct ac97_info *codec;
-struct sndcard_func *func;
-
-csa = malloc(sizeof(*csa), M_DEVBUF, M_NOWAIT | M_ZERO);
-if (csa == NULL)
-return (ENOMEM);
-unit = device_get_unit(dev);
-func = device_get_ivars(dev);
-csa->binfo = func->varinfo;
-/*
-* Fake the status of DMA so that the initial value of
-* PCTL and CCTL can be stored into csa->pctl and csa->cctl,
-* respectively.
-*/
-csa->pch.dma = csa->rch.dma = 1;
-csa->active = 0;
-csa->card = csa->binfo->card;
-
-/* Allocate the resources. */
-resp = &csa->res;
-resp->io_rid = PCIR_BAR(0);
-resp->mem_rid = PCIR_BAR(1);
-resp->irq_rid = 0;
-if (csa_allocres(csa, dev)) {
-csa_releaseres(csa, dev);
-return (ENXIO);
-}
-
-csa_active(csa, 1);
-if (csa_init(csa)) {
-csa_releaseres(csa, dev);
-return (ENXIO);
-}
-codec = AC97_CREATE(dev, csa, csa_ac97);
-if (codec == NULL) {
-csa_releaseres(csa, dev);
-return (ENXIO);
-}
-if (csa->card->inv_eapd)
-ac97_setflags(codec, AC97_F_EAPD_INV);
-if (mixer_init(dev, ac97_getmixerclass(), codec) == -1) {
-ac97_destroy(codec);
-csa_releaseres(csa, dev);
-return (ENXIO);
-}
-
-snprintf(status, SND_STATUSLEN, "at irq %ld %s",
-rman_get_start(resp->irq),PCM_KLDSTRING(snd_csa));
-
-/* Enable interrupt. */
-if (snd_setup_intr(dev, resp->irq, 0, csa_intr, csa, &csa->ih)) {
-ac97_destroy(codec);
-csa_releaseres(csa, dev);
-return (ENXIO);
-}
-csa_writemem(resp, BA1_PFIE, csa_readmem(resp, BA1_PFIE) & ~0x0000f03f);
-csa_writemem(resp, BA1_CIE, (csa_readmem(resp, BA1_CIE) & ~0x0000003f) | 0x00000001);
-csa_active(csa, -1);
-
-if (pcm_register(dev, csa, 1, 1)) {
-ac97_destroy(codec);
-csa_releaseres(csa, dev);
-return (ENXIO);
-}
-pcm_addchan(dev, PCMDIR_REC, &csachan_class, csa);
-pcm_addchan(dev, PCMDIR_PLAY, &csachan_class, csa);
-pcm_setstatus(dev, status);
+ struct csa_info *csa;
+ csa_res *resp;
+ int unit;
+ char status[SND_STATUSLEN];
+ struct ac97_info *codec;
+ struct sndcard_func *func;
+
+ csa = malloc(sizeof(*csa), M_DEVBUF, M_WAITOK | M_ZERO);
+ unit = device_get_unit(dev);
+ func = device_get_ivars(dev);
+ csa->binfo = func->varinfo;
+ /*
+ * Fake the status of DMA so that the initial value of
+ * PCTL and CCTL can be stored into csa->pctl and csa->cctl,
+ * respectively.
+ */
+ csa->pch.dma = csa->rch.dma = 1;
+ csa->active = 0;
+ csa->card = csa->binfo->card;
+
+ /* Allocate the resources. */
+ resp = &csa->res;
+ resp->io_rid = PCIR_BAR(0);
+ resp->mem_rid = PCIR_BAR(1);
+ resp->irq_rid = 0;
+ if (csa_allocres(csa, dev)) {
+ csa_releaseres(csa, dev);
+ return (ENXIO);
+ }
+
+ csa_active(csa, 1);
+ if (csa_init(csa)) {
+ csa_releaseres(csa, dev);
+ return (ENXIO);
+ }
+ codec = AC97_CREATE(dev, csa, csa_ac97);
+ if (codec == NULL) {
+ csa_releaseres(csa, dev);
+ return (ENXIO);
+ }
+ if (csa->card->inv_eapd)
+ ac97_setflags(codec, AC97_F_EAPD_INV);
+ if (mixer_init(dev, ac97_getmixerclass(), codec) == -1) {
+ ac97_destroy(codec);
+ csa_releaseres(csa, dev);
+ return (ENXIO);
+ }
+
+ snprintf(status, SND_STATUSLEN, "at irq %ld %s",
+ rman_get_start(resp->irq),PCM_KLDSTRING(snd_csa));
+
+ /* Enable interrupt. */
+ if (snd_setup_intr(dev, resp->irq, 0, csa_intr, csa, &csa->ih)) {
+ ac97_destroy(codec);
+ csa_releaseres(csa, dev);
+ return (ENXIO);
+ }
+ csa_writemem(resp, BA1_PFIE, csa_readmem(resp, BA1_PFIE) & ~0x0000f03f);
+ csa_writemem(resp, BA1_CIE, (csa_readmem(resp, BA1_CIE) & ~0x0000003f) | 0x00000001);
+ csa_active(csa, -1);
+
+ if (pcm_register(dev, csa, 1, 1)) {
+ ac97_destroy(codec);
+ csa_releaseres(csa, dev);
+ return (ENXIO);
+ }
+ pcm_addchan(dev, PCMDIR_REC, &csachan_class, csa);
+ pcm_addchan(dev, PCMDIR_PLAY, &csachan_class, csa);
+ pcm_setstatus(dev, status);
-return (0);
+ return (0);
}
static int
pcmcsa_detach(device_t dev)
{
-int r;
-struct csa_info *csa;
+ int r;
+ struct csa_info *csa;
-r = pcm_unregister(dev);
-if (r)
-return r;
+ r = pcm_unregister(dev);
+ if (r)
+ return r;
-csa = pcm_getdevinfo(dev);
-csa_releaseres(csa, dev);
+ csa = pcm_getdevinfo(dev);
+ csa_releaseres(csa, dev);
-return 0;
+ return 0;
}
static void
csa_ac97_suspend(struct csa_info *csa)
{
-int count, i;
-uint32_t tmp;
-
-for (count = 0x2, i=0;
-(count <= CS461x_AC97_HIGHESTREGTORESTORE) &&
-(i < CS461x_AC97_NUMBER_RESTORE_REGS);
-count += 2, i++)
-csa_readcodec(&csa->res, BA0_AC97_RESET + count, &csa->ac97[i]);
-
-/* mute the outputs */
-csa_writecodec(&csa->res, BA0_AC97_MASTER_VOLUME, 0x8000);
-csa_writecodec(&csa->res, BA0_AC97_HEADPHONE_VOLUME, 0x8000);
-csa_writecodec(&csa->res, BA0_AC97_MASTER_VOLUME_MONO, 0x8000);
-csa_writecodec(&csa->res, BA0_AC97_PCM_OUT_VOLUME, 0x8000);
-/* save the registers that cause pops */
-csa_readcodec(&csa->res, BA0_AC97_POWERDOWN, &csa->ac97_powerdown);
-csa_readcodec(&csa->res, BA0_AC97_GENERAL_PURPOSE,
-&csa->ac97_general_purpose);
+ int count, i;
+ uint32_t tmp;
-/*
-* And power down everything on the AC97 codec. Well, for now,
-* only power down the DAC/ADC and MIXER VREFON components.
-* trouble with removing VREF.
-*/
-
-/* MIXVON */
-csa_readcodec(&csa->res, BA0_AC97_POWERDOWN, &tmp);
-csa_writecodec(&csa->res, BA0_AC97_POWERDOWN,
-tmp | CS_AC97_POWER_CONTROL_MIXVON);
-/* ADC */
-csa_readcodec(&csa->res, BA0_AC97_POWERDOWN, &tmp);
-csa_writecodec(&csa->res, BA0_AC97_POWERDOWN,
-tmp | CS_AC97_POWER_CONTROL_ADC);
-/* DAC */
-csa_readcodec(&csa->res, BA0_AC97_POWERDOWN, &tmp);
-csa_writecodec(&csa->res, BA0_AC97_POWERDOWN,
-tmp | CS_AC97_POWER_CONTROL_DAC);
+ for (count = 0x2, i=0;
+ (count <= CS461x_AC97_HIGHESTREGTORESTORE) &&
+ (i < CS461x_AC97_NUMBER_RESTORE_REGS);
+ count += 2, i++)
+ csa_readcodec(&csa->res, BA0_AC97_RESET + count, &csa->ac97[i]);
+
+ /* mute the outputs */
+ csa_writecodec(&csa->res, BA0_AC97_MASTER_VOLUME, 0x8000);
+ csa_writecodec(&csa->res, BA0_AC97_HEADPHONE_VOLUME, 0x8000);
+ csa_writecodec(&csa->res, BA0_AC97_MASTER_VOLUME_MONO, 0x8000);
+ csa_writecodec(&csa->res, BA0_AC97_PCM_OUT_VOLUME, 0x8000);
+ /* save the registers that cause pops */
+ csa_readcodec(&csa->res, BA0_AC97_POWERDOWN, &csa->ac97_powerdown);
+ csa_readcodec(&csa->res, BA0_AC97_GENERAL_PURPOSE,
+ &csa->ac97_general_purpose);
+
+ /*
+ * And power down everything on the AC97 codec. Well, for now,
+ * only power down the DAC/ADC and MIXER VREFON components.
+ * trouble with removing VREF.
+ */
+
+ /* MIXVON */
+ csa_readcodec(&csa->res, BA0_AC97_POWERDOWN, &tmp);
+ csa_writecodec(&csa->res, BA0_AC97_POWERDOWN,
+ tmp | CS_AC97_POWER_CONTROL_MIXVON);
+ /* ADC */
+ csa_readcodec(&csa->res, BA0_AC97_POWERDOWN, &tmp);
+ csa_writecodec(&csa->res, BA0_AC97_POWERDOWN,
+ tmp | CS_AC97_POWER_CONTROL_ADC);
+ /* DAC */
+ csa_readcodec(&csa->res, BA0_AC97_POWERDOWN, &tmp);
+ csa_writecodec(&csa->res, BA0_AC97_POWERDOWN,
+ tmp | CS_AC97_POWER_CONTROL_DAC);
}
static void
csa_ac97_resume(struct csa_info *csa)
{
-int count, i;
+ int count, i;
-/*
-* First, we restore the state of the general purpose register. This
-* contains the mic select (mic1 or mic2) and if we restore this after
-* we restore the mic volume/boost state and mic2 was selected at
-* suspend time, we will end up with a brief period of time where mic1
-* is selected with the volume/boost settings for mic2, causing
-* acoustic feedback. So we restore the general purpose register
-* first, thereby getting the correct mic selected before we restore
-* the mic volume/boost.
-*/
-csa_writecodec(&csa->res, BA0_AC97_GENERAL_PURPOSE,
-csa->ac97_general_purpose);
-/*
-* Now, while the outputs are still muted, restore the state of power
-* on the AC97 part.
-*/
-csa_writecodec(&csa->res, BA0_AC97_POWERDOWN, csa->ac97_powerdown);
-/*
-* Restore just the first set of registers, from register number
-* 0x02 to the register number that ulHighestRegToRestore specifies.
-*/
-for (count = 0x2, i=0;
-(count <= CS461x_AC97_HIGHESTREGTORESTORE) &&
-(i < CS461x_AC97_NUMBER_RESTORE_REGS);
-count += 2, i++)
-csa_writecodec(&csa->res, BA0_AC97_RESET + count, csa->ac97[i]);
+ /*
+ * First, we restore the state of the general purpose register. This
+ * contains the mic select (mic1 or mic2) and if we restore this after
+ * we restore the mic volume/boost state and mic2 was selected at
+ * suspend time, we will end up with a brief period of time where mic1
+ * is selected with the volume/boost settings for mic2, causing
+ * acoustic feedback. So we restore the general purpose register
+ * first, thereby getting the correct mic selected before we restore
+ * the mic volume/boost.
+ */
+ csa_writecodec(&csa->res, BA0_AC97_GENERAL_PURPOSE,
+ csa->ac97_general_purpose);
+ /*
+ * Now, while the outputs are still muted, restore the state of power
+ * on the AC97 part.
+ */
+ csa_writecodec(&csa->res, BA0_AC97_POWERDOWN, csa->ac97_powerdown);
+ /*
+ * Restore just the first set of registers, from register number
+ * 0x02 to the register number that ulHighestRegToRestore specifies.
+ */
+ for (count = 0x2, i=0;
+ (count <= CS461x_AC97_HIGHESTREGTORESTORE) &&
+ (i < CS461x_AC97_NUMBER_RESTORE_REGS);
+ count += 2, i++)
+ csa_writecodec(&csa->res, BA0_AC97_RESET + count, csa->ac97[i]);
}
static int
pcmcsa_suspend(device_t dev)
{
-struct csa_info *csa;
-csa_res *resp;
-
-csa = pcm_getdevinfo(dev);
-resp = &csa->res;
-
-csa_active(csa, 1);
+ struct csa_info *csa;
+ csa_res *resp;
-/* playback interrupt disable */
-csa_writemem(resp, BA1_PFIE,
-(csa_readmem(resp, BA1_PFIE) & ~0x0000f03f) | 0x00000010);
-/* capture interrupt disable */
-csa_writemem(resp, BA1_CIE,
-(csa_readmem(resp, BA1_CIE) & ~0x0000003f) | 0x00000011);
-csa_stopplaydma(csa);
-csa_stopcapturedma(csa);
+ csa = pcm_getdevinfo(dev);
+ resp = &csa->res;
-csa_ac97_suspend(csa);
+ csa_active(csa, 1);
-csa_resetdsp(resp);
-
-csa_stopdsp(resp);
-/*
-* Power down the DAC and ADC. For now leave the other areas on.
-*/
-csa_writecodec(&csa->res, BA0_AC97_POWERDOWN, 0x300);
-/*
-* Power down the PLL.
-*/
-csa_writemem(resp, BA0_CLKCR1, 0);
-/*
-* Turn off the Processor by turning off the software clock
-* enable flag in the clock control register.
-*/
-csa_writemem(resp, BA0_CLKCR1,
-csa_readmem(resp, BA0_CLKCR1) & ~CLKCR1_SWCE);
+ /* playback interrupt disable */
+ csa_writemem(resp, BA1_PFIE,
+ (csa_readmem(resp, BA1_PFIE) & ~0x0000f03f) | 0x00000010);
+ /* capture interrupt disable */
+ csa_writemem(resp, BA1_CIE,
+ (csa_readmem(resp, BA1_CIE) & ~0x0000003f) | 0x00000011);
+ csa_stopplaydma(csa);
+ csa_stopcapturedma(csa);
+
+ csa_ac97_suspend(csa);
+
+ csa_resetdsp(resp);
+
+ csa_stopdsp(resp);
+ /*
+ * Power down the DAC and ADC. For now leave the other areas on.
+ */
+ csa_writecodec(&csa->res, BA0_AC97_POWERDOWN, 0x300);
+ /*
+ * Power down the PLL.
+ */
+ csa_writemem(resp, BA0_CLKCR1, 0);
+ /*
+ * Turn off the Processor by turning off the software clock
+ * enable flag in the clock control register.
+ */
+ csa_writemem(resp, BA0_CLKCR1,
+ csa_readmem(resp, BA0_CLKCR1) & ~CLKCR1_SWCE);
-csa_active(csa, -1);
+ csa_active(csa, -1);
-return 0;
+ return 0;
}
static int
pcmcsa_resume(device_t dev)
{
-struct csa_info *csa;
-csa_res *resp;
+ struct csa_info *csa;
+ csa_res *resp;
-csa = pcm_getdevinfo(dev);
-resp = &csa->res;
+ csa = pcm_getdevinfo(dev);
+ resp = &csa->res;
-csa_active(csa, 1);
+ csa_active(csa, 1);
-/* cs_hardware_init */
-csa_stopplaydma(csa);
-csa_stopcapturedma(csa);
-csa_ac97_resume(csa);
-if (csa_startdsp(resp))
-return (ENXIO);
-/* Enable interrupts on the part. */
-if ((csa_readio(resp, BA0_HISR) & HISR_INTENA) == 0)
-csa_writeio(resp, BA0_HICR, HICR_IEV | HICR_CHGM);
-/* playback interrupt enable */
-csa_writemem(resp, BA1_PFIE, csa_readmem(resp, BA1_PFIE) & ~0x0000f03f);
-/* capture interrupt enable */
-csa_writemem(resp, BA1_CIE,
-(csa_readmem(resp, BA1_CIE) & ~0x0000003f) | 0x00000001);
-/* cs_restart_part */
-csa_setupchan(&csa->pch);
-csa_startplaydma(csa);
-csa_setupchan(&csa->rch);
-csa_startcapturedma(csa);
+ /* cs_hardware_init */
+ csa_stopplaydma(csa);
+ csa_stopcapturedma(csa);
+ csa_ac97_resume(csa);
+ if (csa_startdsp(resp))
+ return (ENXIO);
+ /* Enable interrupts on the part. */
+ if ((csa_readio(resp, BA0_HISR) & HISR_INTENA) == 0)
+ csa_writeio(resp, BA0_HICR, HICR_IEV | HICR_CHGM);
+ /* playback interrupt enable */
+ csa_writemem(resp, BA1_PFIE, csa_readmem(resp, BA1_PFIE) & ~0x0000f03f);
+ /* capture interrupt enable */
+ csa_writemem(resp, BA1_CIE,
+ (csa_readmem(resp, BA1_CIE) & ~0x0000003f) | 0x00000001);
+ /* cs_restart_part */
+ csa_setupchan(&csa->pch);
+ csa_startplaydma(csa);
+ csa_setupchan(&csa->rch);
+ csa_startcapturedma(csa);
-csa_active(csa, -1);
+ csa_active(csa, -1);
-return 0;
+ return 0;
}
static device_method_t pcmcsa_methods[] = {
-/* Device interface */
-DEVMETHOD(device_probe , pcmcsa_probe ),
-DEVMETHOD(device_attach, pcmcsa_attach),
-DEVMETHOD(device_detach, pcmcsa_detach),
-DEVMETHOD(device_suspend, pcmcsa_suspend),
-DEVMETHOD(device_resume, pcmcsa_resume),
+ /* Device interface */
+ DEVMETHOD(device_probe , pcmcsa_probe ),
+ DEVMETHOD(device_attach, pcmcsa_attach),
+ DEVMETHOD(device_detach, pcmcsa_detach),
+ DEVMETHOD(device_suspend, pcmcsa_suspend),
+ DEVMETHOD(device_resume, pcmcsa_resume),
-{ 0, 0 },
+ { 0, 0 },
};
static driver_t pcmcsa_driver = {
-"pcm",
-pcmcsa_methods,
-PCM_SOFTC_SIZE,
+ "pcm",
+ pcmcsa_methods,
+ PCM_SOFTC_SIZE,
};
DRIVER_MODULE(snd_csapcm, csa, pcmcsa_driver, pcm_devclass, 0, 0);
--- /dev/null
+++ sys/dev/sound/pci/spicds.c
@@ -0,0 +1,360 @@
+/*
+ * Copyright (c) 2006 Konstantin Dimitrov <kosio.dimitrov at gmail.com>
+ * Copyright (c) 2001 Katsurajima Naoto <raven at katsurajima.seya.yokohama.jp>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHERIN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THEPOSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD: src/sys/dev/sound/pci/spicds.c,v 1.6 2007/05/27 19:58:39 joel Exp $
+ */
+
+#include <dev/sound/pcm/sound.h>
+
+#include <dev/sound/pci/spicds.h>
+
+MALLOC_DEFINE(M_SPICDS, "spicds", "SPI codec");
+
+#define SPICDS_NAMELEN 16
+struct spicds_info {
+ device_t dev;
+ spicds_ctrl ctrl;
+ void *devinfo;
+ int num; /* number of this device */
+ unsigned int type; /* codec type */
+ unsigned int cif; /* Controll data Interface Format (0/1) */
+ unsigned int format; /* data format and master clock frequency */
+ unsigned int dvc; /* De-emphasis and Volume Control */
+ unsigned int left, right;
+ char name[SPICDS_NAMELEN];
+ struct mtx *lock;
+};
+
+static void
+spicds_wrbit(struct spicds_info *codec, int bit)
+{
+ unsigned int cs, cdti;
+ if (codec->cif)
+ cs = 1;
+ else
+ cs = 0;
+ if (bit)
+ cdti = 1;
+ else
+ cdti = 0;
+ codec->ctrl(codec->devinfo, cs, 0, cdti);
+ DELAY(1);
+ codec->ctrl(codec->devinfo, cs, 1, cdti);
+ DELAY(1);
+
+ return;
+}
+
+static void
+spicds_wrcd(struct spicds_info *codec, int reg, u_int16_t val)
+{
+ int mask;
+
+#if(0)
+ device_printf(codec->dev, "spicds_wrcd(codec, 0x%02x, 0x%02x)\n", reg, val);
+#endif
+ /* start */
+ if (codec->cif)
+ codec->ctrl(codec->devinfo, 1, 1, 0);
+ else
+ codec->ctrl(codec->devinfo, 0, 1, 0);
+ DELAY(1);
+ if (codec->type != SPICDS_TYPE_WM8770) {
+ if (codec->type == SPICDS_TYPE_AK4381) {
+ /* AK4381 chip address */
+ spicds_wrbit(codec, 0);
+ spicds_wrbit(codec, 1);
+ }
+ else if (codec->type == SPICDS_TYPE_AK4396)
+ {
+ /* AK4396 chip address */
+ spicds_wrbit(codec, 0);
+ spicds_wrbit(codec, 0);
+ }
+ else {
+ /* chip address */
+ spicds_wrbit(codec, 1);
+ spicds_wrbit(codec, 0);
+ }
+ /* write */
+ spicds_wrbit(codec, 1);
+ /* register address */
+ for (mask = 0x10; mask != 0; mask >>= 1)
+ spicds_wrbit(codec, reg & mask);
+ /* data */
+ for (mask = 0x80; mask != 0; mask >>= 1)
+ spicds_wrbit(codec, val & mask);
+ /* stop */
+ DELAY(1);
+ }
+ else {
+ /* register address */
+ for (mask = 0x40; mask != 0; mask >>= 1)
+ spicds_wrbit(codec, reg & mask);
+ /* data */
+ for (mask = 0x100; mask != 0; mask >>= 1)
+ spicds_wrbit(codec, val & mask);
+ /* stop */
+ DELAY(1);
+ }
+ if (codec->cif) {
+ codec->ctrl(codec->devinfo, 0, 1, 0);
+ DELAY(1);
+ codec->ctrl(codec->devinfo, 1, 1, 0);
+ }
+ else {
+ codec->ctrl(codec->devinfo, 1, 1, 0);
+ }
+
+ return;
+}
+
+struct spicds_info *
+spicds_create(device_t dev, void *devinfo, int num, spicds_ctrl ctrl)
+{
+ struct spicds_info *codec;
+
+#if(0)
+ device_printf(dev, "spicds_create(dev, devinfo, %d, ctrl)\n", num);
+#endif
+ codec = (struct spicds_info *)malloc(sizeof *codec, M_SPICDS, M_NOWAIT);
+ if (codec == NULL)
+ return NULL;
+
+ snprintf(codec->name, SPICDS_NAMELEN, "%s:spicds%d", device_get_nameunit(dev), num);
+ codec->lock = snd_mtxcreate(codec->name, codec->name);
+ codec->dev = dev;
+ codec->ctrl = ctrl;
+ codec->devinfo = devinfo;
+ codec->num = num;
+ codec->type = SPICDS_TYPE_AK4524;
+ codec->cif = 0;
+ codec->format = AK452X_FORMAT_I2S | AK452X_FORMAT_256FSN | AK452X_FORMAT_1X;
+ codec->dvc = AK452X_DVC_DEMOFF | AK452X_DVC_ZTM1024 | AK452X_DVC_ZCE;
+
+ return codec;
+}
+
+void
+spicds_destroy(struct spicds_info *codec)
+{
+ snd_mtxfree(codec->lock);
+ free(codec, M_SPICDS);
+}
+
+void
+spicds_settype(struct spicds_info *codec, unsigned int type)
+{
+ snd_mtxlock(codec->lock);
+ codec->type = type;
+ snd_mtxunlock(codec->lock);
+}
+
+void
+spicds_setcif(struct spicds_info *codec, unsigned int cif)
+{
+ snd_mtxlock(codec->lock);
+ codec->cif = cif;
+ snd_mtxunlock(codec->lock);
+}
+
+void
+spicds_setformat(struct spicds_info *codec, unsigned int format)
+{
+ snd_mtxlock(codec->lock);
+ codec->format = format;
+ snd_mtxunlock(codec->lock);
+}
+
+void
+spicds_setdvc(struct spicds_info *codec, unsigned int dvc)
+{
+ snd_mtxlock(codec->lock);
+ codec->dvc = dvc;
+ snd_mtxunlock(codec->lock);
+}
+
+void
+spicds_init(struct spicds_info *codec)
+{
+#if(0)
+ device_printf(codec->dev, "spicds_init(codec)\n");
+#endif
+ snd_mtxlock(codec->lock);
+ if (codec->type == SPICDS_TYPE_AK4524 ||\
+ codec->type == SPICDS_TYPE_AK4528) {
+ /* power off */
+ spicds_wrcd(codec, AK4524_POWER, 0);
+ /* set parameter */
+ spicds_wrcd(codec, AK4524_FORMAT, codec->format);
+ spicds_wrcd(codec, AK4524_DVC, codec->dvc);
+ /* power on */
+ spicds_wrcd(codec, AK4524_POWER, AK452X_POWER_PWDA | AK452X_POWER_PWAD | AK452X_POWER_PWVR);
+ /* free reset register */
+ spicds_wrcd(codec, AK4524_RESET, AK452X_RESET_RSDA | AK452X_RESET_RSAD);
+ }
+ if (codec->type == SPICDS_TYPE_WM8770) {
+ /* WM8770 init values are taken from ALSA */
+ /* These come first to reduce init pop noise */
+ spicds_wrcd(codec, 0x1b, 0x044); /* ADC Mux (AC'97 source) */
+ spicds_wrcd(codec, 0x1c, 0x00B); /* Out Mux1 (VOUT1 = DAC+AUX, VOUT2 = DAC) */
+ spicds_wrcd(codec, 0x1d, 0x009); /* Out Mux2 (VOUT2 = DAC, VOUT3 = DAC) */
+
+ spicds_wrcd(codec, 0x18, 0x000); /* All power-up */
+
+ spicds_wrcd(codec, 0x16, 0x122); /* I2S, normal polarity, 24bit */
+ spicds_wrcd(codec, 0x17, 0x022); /* 256fs, slave mode */
+
+ spicds_wrcd(codec, 0x19, 0x000); /* -12dB ADC/L */
+ spicds_wrcd(codec, 0x1a, 0x000); /* -12dB ADC/R */
+ }
+ if (codec->type == SPICDS_TYPE_AK4358)
+ spicds_wrcd(codec, 0x00, 0x07); /* I2S, 24bit, power-up */
+ if (codec->type == SPICDS_TYPE_AK4381)
+ spicds_wrcd(codec, 0x00, 0x0f); /* I2S, 24bit, power-up */
+ if (codec->type == SPICDS_TYPE_AK4396)
+ spicds_wrcd(codec, 0x00, 0x07); /* I2S, 24bit, power-up */
+ snd_mtxunlock(codec->lock);
+}
+
+void
+spicds_reinit(struct spicds_info *codec)
+{
+ snd_mtxlock(codec->lock);
+ if (codec->type != SPICDS_TYPE_WM8770) {
+ /* reset */
+ spicds_wrcd(codec, AK4524_RESET, 0);
+ /* set parameter */
+ spicds_wrcd(codec, AK4524_FORMAT, codec->format);
+ spicds_wrcd(codec, AK4524_DVC, codec->dvc);
+ /* free reset register */
+ spicds_wrcd(codec, AK4524_RESET, AK452X_RESET_RSDA | AK452X_RESET_RSAD);
+ }
+ else {
+ /* WM8770 reinit */
+ /* AK4358 reinit */
+ /* AK4381 reinit */
+ }
+ snd_mtxunlock(codec->lock);
+}
+
+void
+spicds_set(struct spicds_info *codec, int dir, unsigned int left, unsigned int right)
+{
+#if(0)
+ device_printf(codec->dev, "spicds_set(codec, %d, %d, %d)\n", dir, left, right);
+#endif
+ snd_mtxlock(codec->lock);
+ if (left >= 100)
+ if ((codec->type == SPICDS_TYPE_AK4381) || \
+ (codec->type == SPICDS_TYPE_AK4396))
+ left = 255;
+ else
+ left = 127;
+ else
+ switch (codec->type) {
+ case SPICDS_TYPE_WM8770:
+ left = left + 27;
+ break;
+ case SPICDS_TYPE_AK4381 || SPICDS_TYPE_AK4396:
+ left = left * 255 / 100;
+ break;
+ default:
+ left = left * 127 / 100;
+ }
+ if (right >= 100)
+ if ((codec->type == SPICDS_TYPE_AK4381) || \
+ (codec->type == SPICDS_TYPE_AK4396))
+ right = 255;
+ else
+ right = 127;
+ else
+ switch (codec->type) {
+ case SPICDS_TYPE_WM8770:
+ right = right + 27;
+ break;
+ case SPICDS_TYPE_AK4381 || SPICDS_TYPE_AK4396:
+ right = right * 255 / 100;
+ break;
+ default:
+ right = right * 127 / 100;
+ }
+ if (dir == PCMDIR_REC && codec->type == SPICDS_TYPE_AK4524) {
+#if(0)
+ device_printf(codec->dev, "spicds_set(): AK4524(REC) %d/%d\n", left, right);
+#endif
+ spicds_wrcd(codec, AK4524_LIPGA, left);
+ spicds_wrcd(codec, AK4524_RIPGA, right);
+ }
+ if (dir == PCMDIR_PLAY && codec->type == SPICDS_TYPE_AK4524) {
+#if(0)
+ device_printf(codec->dev, "spicds_set(): AK4524(PLAY) %d/%d\n", left, right);
+#endif
+ spicds_wrcd(codec, AK4524_LOATT, left);
+ spicds_wrcd(codec, AK4524_ROATT, right);
+ }
+ if (dir == PCMDIR_PLAY && codec->type == SPICDS_TYPE_AK4528) {
+#if(0)
+ device_printf(codec->dev, "spicds_set(): AK4528(PLAY) %d/%d\n", left, right);
+#endif
+ spicds_wrcd(codec, AK4528_LOATT, left);
+ spicds_wrcd(codec, AK4528_ROATT, right);
+ }
+ if (dir == PCMDIR_PLAY && codec->type == SPICDS_TYPE_WM8770) {
+#if(0)
+ device_printf(codec->dev, "spicds_set(): WM8770(PLAY) %d/%d\n", left, right);
+#endif
+ spicds_wrcd(codec, WM8770_AOATT_L1, left | WM8770_AOATT_UPDATE);
+ spicds_wrcd(codec, WM8770_AOATT_R1, right | WM8770_AOATT_UPDATE);
+ }
+ if (dir == PCMDIR_PLAY && codec->type == SPICDS_TYPE_AK4358) {
+#if(0)
+ device_printf(codec->dev, "spicds_set(): AK4358(PLAY) %d/%d\n", left, right);
+#endif
+ spicds_wrcd(codec, AK4358_LO1ATT, left | AK4358_OATT_ENABLE);
+ spicds_wrcd(codec, AK4358_RO1ATT, right | AK4358_OATT_ENABLE);
+ }
+ if (dir == PCMDIR_PLAY && codec->type == SPICDS_TYPE_AK4381) {
+#if(0)
+ device_printf(codec->dev, "spicds_set(): AK4381(PLAY) %d/%d\n", left, right);
+#endif
+ spicds_wrcd(codec, AK4381_LOATT, left);
+ spicds_wrcd(codec, AK4381_ROATT, right);
+ }
+
+ if (dir == PCMDIR_PLAY && codec->type == SPICDS_TYPE_AK4396) {
+#if(0)
+ device_printf(codec->dev, "spicds_set(): AK4396(PLAY) %d/%d\n", left, right);
+#endif
+ spicds_wrcd(codec, AK4396_LOATT, left);
+ spicds_wrcd(codec, AK4396_ROATT, right);
+ }
+
+ snd_mtxunlock(codec->lock);
+}
+
+MODULE_DEPEND(snd_spicds, sound, SOUND_MINVER, SOUND_PREFVER, SOUND_MAXVER);
+MODULE_VERSION(snd_spicds, 1);
Index: emu10k1.c
===================================================================
RCS file: /home/cvs/src/sys/dev/sound/pci/emu10k1.c,v
retrieving revision 1.2
retrieving revision 1.3
diff -L sys/dev/sound/pci/emu10k1.c -L sys/dev/sound/pci/emu10k1.c -u -r1.2 -r1.3
--- sys/dev/sound/pci/emu10k1.c
+++ sys/dev/sound/pci/emu10k1.c
@@ -1,41 +1,43 @@
/*-
-* Copyright (c) 2004 David O'Brien <obrien at FreeBSD.org>
-* Copyright (c) 2003 Orlando Bassotto <orlando.bassotto at ieo-research.it>
-* Copyright (c) 1999 Cameron Grant <cg at freebsd.org>
-* All rights reserved.
-*
-* Redistribution and use in source and binary forms, with or without
-* modification, are permitted provided that the following conditions
-* are met:
-* 1. Redistributions of source code must retain the above copyright
-* notice, this list of conditions and the following disclaimer.
-* 2. Redistributions in binary form must reproduce the above copyright
-* notice, this list of conditions and the following disclaimer in the
-* documentation and/or other materials provided with the distribution.
-*
-* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
-* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
-* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
-* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
-* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHERIN CONTRACT, STRICT
-* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
-* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
-* SUCH DAMAGE.
-*/
+ * Copyright (c) 2004 David O'Brien <obrien at FreeBSD.org>
+ * Copyright (c) 2003 Orlando Bassotto <orlando.bassotto at ieo-research.it>
+ * Copyright (c) 1999 Cameron Grant <cg at freebsd.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHERIN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
#include <dev/sound/pcm/sound.h>
#include <dev/sound/pcm/ac97.h>
-#include <gnu/dev/sound/pci/emu10k1.h>
#include "emu10k1-alsa%diked.h"
#include <dev/pci/pcireg.h>
#include <dev/pci/pcivar.h>
#include <sys/queue.h>
-SND_DECLARE_FILE("$MidnightBSD$");
+#include <dev/sound/midi/mpu401.h>
+#include "mpufoi_if.h"
+
+SND_DECLARE_FILE("$FreeBSD: src/sys/dev/sound/pci/emu10k1.c,v 1.69 2007/06/17 06:10:42 ariff Exp $");
/* -------------------------------------------------------------------- */
@@ -68,82 +70,85 @@
#define A_IOCFG_GPOUT_AD (A_IOCFG_GPOUT_A|A_IOCFG_GPOUT_D) /* A_IOCFG_GPOUT0 */
struct emu_memblk {
-SLIST_ENTRY(emu_memblk) link;
-void *buf;
-bus_addr_t buf_addr;
-u_int32_t pte_start, pte_size;
+ SLIST_ENTRY(emu_memblk) link;
+ void *buf;
+ bus_addr_t buf_addr;
+ u_int32_t pte_start, pte_size;
};
struct emu_mem {
-u_int8_t bmap[EMUMAXPAGES / 8];
-u_int32_t *ptb_pages;
-void *silent_page;
-bus_addr_t silent_page_addr;
-bus_addr_t ptb_pages_addr;
-SLIST_HEAD(, emu_memblk) blocks;
+ u_int8_t bmap[EMUMAXPAGES / 8];
+ u_int32_t *ptb_pages;
+ void *silent_page;
+ bus_addr_t silent_page_addr;
+ bus_addr_t ptb_pages_addr;
+ SLIST_HEAD(, emu_memblk) blocks;
};
struct emu_voice {
-int vnum;
-int b16:1, stereo:1, busy:1, running:1, ismaster:1;
-int speed;
-int start, end, vol;
-int fxrt1; /* FX routing */
-int fxrt2; /* FX routing (only for audigy) */
-u_int32_t buf;
-struct emu_voice *slave;
-struct pcm_channel *channel;
+ int vnum;
+ unsigned int b16:1, stereo:1, busy:1, running:1, ismaster:1;
+ int speed;
+ int start, end, vol;
+ int fxrt1; /* FX routing */
+ int fxrt2; /* FX routing (only for audigy) */
+ u_int32_t buf;
+ struct emu_voice *slave;
+ struct pcm_channel *channel;
};
struct sc_info;
/* channel registers */
struct sc_pchinfo {
-int spd, fmt, blksz, run;
-struct emu_voice *master, *slave;
-struct snd_dbuf *buffer;
-struct pcm_channel *channel;
-struct sc_info *parent;
+ int spd, fmt, blksz, run;
+ struct emu_voice *master, *slave;
+ struct snd_dbuf *buffer;
+ struct pcm_channel *channel;
+ struct sc_info *parent;
};
struct sc_rchinfo {
-int spd, fmt, run, blksz, num;
-u_int32_t idxreg, basereg, sizereg, setupreg, irqmask;
-struct snd_dbuf *buffer;
-struct pcm_channel *channel;
-struct sc_info *parent;
+ int spd, fmt, run, blksz, num;
+ u_int32_t idxreg, basereg, sizereg, setupreg, irqmask;
+ struct snd_dbuf *buffer;
+ struct pcm_channel *channel;
+ struct sc_info *parent;
};
/* device private data */
struct sc_info {
-device_t dev;
-u_int32_t type, rev;
-u_int32_t tos_link:1, APS:1, audigy:1, audigy2:1;
-u_int32_t addrmask; /* wider if audigy */
-
-bus_space_tag_t st;
-bus_space_handle_t sh;
-bus_dma_tag_t parent_dmat;
-
-struct resource *reg, *irq;
-void *ih;
-struct mtx *lock;
-
-unsigned int bufsz;
-int timer, timerinterval;
-int pnum, rnum;
-int nchans;
-struct emu_mem mem;
-struct emu_voice voice[64];
-struct sc_pchinfo pch[EMU_MAX_CHANS];
-struct sc_rchinfo rch[3];
+ device_t dev;
+ u_int32_t type, rev;
+ u_int32_t tos_link:1, APS:1, audigy:1, audigy2:1;
+ u_int32_t addrmask; /* wider if audigy */
+
+ bus_space_tag_t st;
+ bus_space_handle_t sh;
+ bus_dma_tag_t parent_dmat;
+
+ struct resource *reg, *irq;
+ void *ih;
+ struct mtx *lock;
+
+ unsigned int bufsz;
+ int timer, timerinterval;
+ int pnum, rnum;
+ int nchans;
+ struct emu_mem mem;
+ 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;
};
/* -------------------------------------------------------------------- */
/*
-* prototypes
-*/
+ * prototypes
+ */
/* stuff */
static int emu_init(struct sc_info *);
@@ -163,33 +168,33 @@
/* -------------------------------------------------------------------- */
static u_int32_t emu_rfmt_ac97[] = {
-AFMT_S16_LE,
-AFMT_STEREO | AFMT_S16_LE,
-0
+ AFMT_S16_LE,
+ AFMT_STEREO | AFMT_S16_LE,
+ 0
};
static u_int32_t emu_rfmt_mic[] = {
-AFMT_U8,
-0
+ AFMT_U8,
+ 0
};
static u_int32_t emu_rfmt_efx[] = {
-AFMT_STEREO | AFMT_S16_LE,
-0
+ AFMT_STEREO | AFMT_S16_LE,
+ 0
};
static struct pcmchan_caps emu_reccaps[3] = {
-{8000, 48000, emu_rfmt_ac97, 0},
-{8000, 8000, emu_rfmt_mic, 0},
-{48000, 48000, emu_rfmt_efx, 0},
+ {8000, 48000, emu_rfmt_ac97, 0},
+ {8000, 8000, emu_rfmt_mic, 0},
+ {48000, 48000, emu_rfmt_efx, 0},
};
static u_int32_t emu_pfmt[] = {
-AFMT_U8,
-AFMT_STEREO | AFMT_U8,
-AFMT_S16_LE,
-AFMT_STEREO | AFMT_S16_LE,
-0
+ AFMT_U8,
+ AFMT_STEREO | AFMT_U8,
+ AFMT_S16_LE,
+ AFMT_STEREO | AFMT_S16_LE,
+ 0
};
static struct pcmchan_caps emu_playcaps = {4000, 48000, emu_pfmt, 0};
@@ -197,7 +202,7 @@
static int adcspeed[8] = {48000, 44100, 32000, 24000, 22050, 16000, 11025, 8000};
/* audigy supports 12kHz. */
static int audigy_adcspeed[9] = {
-48000, 44100, 32000, 24000, 22050, 16000, 12000, 11025, 8000
+ 48000, 44100, 32000, 24000, 22050, 16000, 12000, 11025, 8000
};
/* -------------------------------------------------------------------- */
@@ -205,75 +210,75 @@
static u_int32_t
emu_rd(struct sc_info *sc, int regno, int size)
{
-switch (size) {
-case 1:
-return bus_space_read_1(sc->st, sc->sh, regno);
-case 2:
-return bus_space_read_2(sc->st, sc->sh, regno);
-case 4:
-return bus_space_read_4(sc->st, sc->sh, regno);
-default:
-return 0xffffffff;
-}
+ switch (size) {
+ case 1:
+ return bus_space_read_1(sc->st, sc->sh, regno);
+ case 2:
+ return bus_space_read_2(sc->st, sc->sh, regno);
+ case 4:
+ return bus_space_read_4(sc->st, sc->sh, regno);
+ default:
+ return 0xffffffff;
+ }
}
static void
emu_wr(struct sc_info *sc, int regno, u_int32_t data, int size)
{
-switch (size) {
-case 1:
-bus_space_write_1(sc->st, sc->sh, regno, data);
-break;
-case 2:
-bus_space_write_2(sc->st, sc->sh, regno, data);
-break;
-case 4:
-bus_space_write_4(sc->st, sc->sh, regno, data);
-break;
-}
+ switch (size) {
+ case 1:
+ bus_space_write_1(sc->st, sc->sh, regno, data);
+ break;
+ case 2:
+ bus_space_write_2(sc->st, sc->sh, regno, data);
+ break;
+ case 4:
+ bus_space_write_4(sc->st, sc->sh, regno, data);
+ break;
+ }
}
static u_int32_t
emu_rdptr(struct sc_info *sc, int chn, int reg)
{
-u_int32_t ptr, val, mask, size, offset;
+ u_int32_t ptr, val, mask, size, offset;
-ptr = ((reg << 16) & sc->addrmask) | (chn & PTR_CHANNELNUM_MASK);
-emu_wr(sc, PTR, ptr, 4);
-val = emu_rd(sc, DATA, 4);
-if (reg & 0xff000000) {
-size = (reg >> 24) & 0x3f;
-offset = (reg >> 16) & 0x1f;
-mask = ((1 << size) - 1) << offset;
-val &= mask;
-val >>= offset;
-}
-return val;
+ ptr = ((reg << 16) & sc->addrmask) | (chn & PTR_CHANNELNUM_MASK);
+ emu_wr(sc, PTR, ptr, 4);
+ val = emu_rd(sc, DATA, 4);
+ if (reg & 0xff000000) {
+ size = (reg >> 24) & 0x3f;
+ offset = (reg >> 16) & 0x1f;
+ mask = ((1 << size) - 1) << offset;
+ val &= mask;
+ val >>= offset;
+ }
+ return val;
}
static void
emu_wrptr(struct sc_info *sc, int chn, int reg, u_int32_t data)
{
-u_int32_t ptr, mask, size, offset;
+ u_int32_t ptr, mask, size, offset;
-ptr = ((reg << 16) & sc->addrmask) | (chn & PTR_CHANNELNUM_MASK);
-emu_wr(sc, PTR, ptr, 4);
-if (reg & 0xff000000) {
-size = (reg >> 24) & 0x3f;
-offset = (reg >> 16) & 0x1f;
-mask = ((1 << size) - 1) << offset;
-data <<= offset;
-data &= mask;
-data |= emu_rd(sc, DATA, 4) & ~mask;
-}
-emu_wr(sc, DATA, data, 4);
+ ptr = ((reg << 16) & sc->addrmask) | (chn & PTR_CHANNELNUM_MASK);
+ emu_wr(sc, PTR, ptr, 4);
+ if (reg & 0xff000000) {
+ size = (reg >> 24) & 0x3f;
+ offset = (reg >> 16) & 0x1f;
+ mask = ((1 << size) - 1) << offset;
+ data <<= offset;
+ data &= mask;
+ data |= emu_rd(sc, DATA, 4) & ~mask;
+ }
+ emu_wr(sc, DATA, data, 4);
}
static void
emu_wrefx(struct sc_info *sc, unsigned int pc, unsigned int data)
{
-pc += sc->audigy ? AUDIGY_CODEBASE : MICROCODEBASE;
-emu_wrptr(sc, 0, pc, data);
+ pc += sc->audigy ? A_MICROCODEBASE : MICROCODEBASE;
+ emu_wrptr(sc, 0, pc, data);
}
/* -------------------------------------------------------------------- */
@@ -283,26 +288,26 @@
static int
emu_rdcd(kobj_t obj, void *devinfo, int regno)
{
-struct sc_info *sc = (struct sc_info *)devinfo;
+ struct sc_info *sc = (struct sc_info *)devinfo;
-emu_wr(sc, AC97ADDRESS, regno, 1);
-return emu_rd(sc, AC97DATA, 2);
+ emu_wr(sc, AC97ADDRESS, regno, 1);
+ return emu_rd(sc, AC97DATA, 2);
}
static int
emu_wrcd(kobj_t obj, void *devinfo, int regno, u_int32_t data)
{
-struct sc_info *sc = (struct sc_info *)devinfo;
+ struct sc_info *sc = (struct sc_info *)devinfo;
-emu_wr(sc, AC97ADDRESS, regno, 1);
-emu_wr(sc, AC97DATA, data, 2);
-return 0;
+ emu_wr(sc, AC97ADDRESS, regno, 1);
+ emu_wr(sc, AC97DATA, data, 2);
+ return 0;
}
static kobj_method_t emu_ac97_methods[] = {
-KOBJMETHOD(ac97_read, emu_rdcd),
-KOBJMETHOD(ac97_write, emu_wrcd),
-{ 0, 0 }
+ KOBJMETHOD(ac97_read, emu_rdcd),
+ KOBJMETHOD(ac97_write, emu_wrcd),
+ { 0, 0 }
};
AC97_DECLARE(emu_ac97);
@@ -311,834 +316,899 @@
static int
emu_settimer(struct sc_info *sc)
{
-struct sc_pchinfo *pch;
-struct sc_rchinfo *rch;
-int i, tmp, rate;
-
-rate = 0;
-for (i = 0; i < sc->nchans; i++) {
-pch = &sc->pch[i];
-if (pch->buffer) {
-tmp = (pch->spd * sndbuf_getbps(pch->buffer))
-/ pch->blksz;
-if (tmp > rate)
-rate = tmp;
-}
-}
-
-for (i = 0; i < 3; i++) {
-rch = &sc->rch[i];
-if (rch->buffer) {
-tmp = (rch->spd * sndbuf_getbps(rch->buffer))
-/ rch->blksz;
-if (tmp > rate)
-rate = tmp;
-}
-}
-RANGE(rate, 48, 9600);
-sc->timerinterval = 48000 / rate;
-emu_wr(sc, TIMER, sc->timerinterval & 0x03ff, 2);
+ struct sc_pchinfo *pch;
+ struct sc_rchinfo *rch;
+ int i, tmp, rate;
+
+ rate = 0;
+ for (i = 0; i < sc->nchans; i++) {
+ pch = &sc->pch[i];
+ if (pch->buffer) {
+ tmp = (pch->spd * sndbuf_getbps(pch->buffer))
+ / pch->blksz;
+ if (tmp > rate)
+ rate = tmp;
+ }
+ }
+
+ for (i = 0; i < 3; i++) {
+ rch = &sc->rch[i];
+ if (rch->buffer) {
+ tmp = (rch->spd * sndbuf_getbps(rch->buffer))
+ / rch->blksz;
+ if (tmp > rate)
+ rate = tmp;
+ }
+ }
+ RANGE(rate, 48, 9600);
+ sc->timerinterval = 48000 / rate;
+ emu_wr(sc, TIMER, sc->timerinterval & 0x03ff, 2);
-return sc->timerinterval;
+ return sc->timerinterval;
}
static int
emu_enatimer(struct sc_info *sc, int go)
{
-u_int32_t x;
-if (go) {
-if (sc->timer++ == 0) {
-x = emu_rd(sc, INTE, 4);
-x |= INTE_INTERVALTIMERENB;
-emu_wr(sc, INTE, x, 4);
-}
-} else {
-sc->timer = 0;
-x = emu_rd(sc, INTE, 4);
-x &= ~INTE_INTERVALTIMERENB;
-emu_wr(sc, INTE, x, 4);
-}
-return 0;
+ u_int32_t x;
+ if (go) {
+ if (sc->timer++ == 0) {
+ x = emu_rd(sc, INTE, 4);
+ x |= INTE_INTERVALTIMERENB;
+ emu_wr(sc, INTE, x, 4);
+ }
+ } else {
+ sc->timer = 0;
+ x = emu_rd(sc, INTE, 4);
+ x &= ~INTE_INTERVALTIMERENB;
+ emu_wr(sc, INTE, x, 4);
+ }
+ return 0;
}
static void
emu_enastop(struct sc_info *sc, char channel, int enable)
{
-int reg = (channel & 0x20) ? SOLEH : SOLEL;
-channel &= 0x1f;
-reg |= 1 << 24;
-reg |= channel << 16;
-emu_wrptr(sc, 0, reg, enable);
+ int reg = (channel & 0x20) ? SOLEH : SOLEL;
+ channel &= 0x1f;
+ reg |= 1 << 24;
+ reg |= channel << 16;
+ emu_wrptr(sc, 0, reg, enable);
}
static int
emu_recval(int speed) {
-int val;
+ int val;
-val = 0;
-while (val < 7 && speed < adcspeed[val])
-val++;
-return val;
+ val = 0;
+ while (val < 7 && speed < adcspeed[val])
+ val++;
+ return val;
}
static int
audigy_recval(int speed) {
-int val;
+ int val;
-val = 0;
-while (val < 8 && speed < audigy_adcspeed[val])
-val++;
-return val;
+ val = 0;
+ while (val < 8 && speed < audigy_adcspeed[val])
+ val++;
+ return val;
}
static u_int32_t
emu_rate_to_pitch(u_int32_t rate)
{
-static u_int32_t logMagTable[128] = {
-0x00000, 0x02dfc, 0x05b9e, 0x088e6, 0x0b5d6, 0x0e26f, 0x10eb3, 0x13aa2,
-0x1663f, 0x1918a, 0x1bc84, 0x1e72e, 0x2118b, 0x23b9a, 0x2655d, 0x28ed5,
-0x2b803, 0x2e0e8, 0x30985, 0x331db, 0x359eb, 0x381b6, 0x3a93d, 0x3d081,
-0x3f782, 0x41e42, 0x444c1, 0x46b01, 0x49101, 0x4b6c4, 0x4dc49, 0x50191,
-0x5269e, 0x54b6f, 0x57006, 0x59463, 0x5b888, 0x5dc74, 0x60029, 0x623a7,
-0x646ee, 0x66a00, 0x68cdd, 0x6af86, 0x6d1fa, 0x6f43c, 0x7164b, 0x73829,
-0x759d4, 0x77b4f, 0x79c9a, 0x7bdb5, 0x7dea1, 0x7ff5e, 0x81fed, 0x8404e,
-0x86082, 0x88089, 0x8a064, 0x8c014, 0x8df98, 0x8fef1, 0x91e20, 0x93d26,
-0x95c01, 0x97ab4, 0x9993e, 0x9b79f, 0x9d5d9, 0x9f3ec, 0xa11d8, 0xa2f9d,
-0xa4d3c, 0xa6ab5, 0xa8808, 0xaa537, 0xac241, 0xadf26, 0xafbe7, 0xb1885,
-0xb3500, 0xb5157, 0xb6d8c, 0xb899f, 0xba58f, 0xbc15e, 0xbdd0c, 0xbf899,
-0xc1404, 0xc2f50, 0xc4a7b, 0xc6587, 0xc8073, 0xc9b3f, 0xcb5ed, 0xcd07c,
-0xceaec, 0xd053f, 0xd1f73, 0xd398a, 0xd5384, 0xd6d60, 0xd8720, 0xda0c3,
-0xdba4a, 0xdd3b4, 0xded03, 0xe0636, 0xe1f4e, 0xe384a, 0xe512c, 0xe69f3,
-0xe829f, 0xe9b31, 0xeb3a9, 0xecc08, 0xee44c, 0xefc78, 0xf148a, 0xf2c83,
-0xf4463, 0xf5c2a, 0xf73da, 0xf8b71, 0xfa2f0, 0xfba57, 0xfd1a7, 0xfe8df
-};
-static char logSlopeTable[128] = {
-0x5c, 0x5c, 0x5b, 0x5a, 0x5a, 0x59, 0x58, 0x58,
-0x57, 0x56, 0x56, 0x55, 0x55, 0x54, 0x53, 0x53,
-0x52, 0x52, 0x51, 0x51, 0x50, 0x50, 0x4f, 0x4f,
-0x4e, 0x4d, 0x4d, 0x4d, 0x4c, 0x4c, 0x4b, 0x4b,
-0x4a, 0x4a, 0x49, 0x49, 0x48, 0x48, 0x47, 0x47,
-0x47, 0x46, 0x46, 0x45, 0x45, 0x45, 0x44, 0x44,
-0x43, 0x43, 0x43, 0x42, 0x42, 0x42, 0x41, 0x41,
-0x41, 0x40, 0x40, 0x40, 0x3f, 0x3f, 0x3f, 0x3e,
-0x3e, 0x3e, 0x3d, 0x3d, 0x3d, 0x3c, 0x3c, 0x3c,
-0x3b, 0x3b, 0x3b, 0x3b, 0x3a, 0x3a, 0x3a, 0x39,
-0x39, 0x39, 0x39, 0x38, 0x38, 0x38, 0x38, 0x37,
-0x37, 0x37, 0x37, 0x36, 0x36, 0x36, 0x36, 0x35,
-0x35, 0x35, 0x35, 0x34, 0x34, 0x34, 0x34, 0x34,
-0x33, 0x33, 0x33, 0x33, 0x32, 0x32, 0x32, 0x32,
-0x32, 0x31, 0x31, 0x31, 0x31, 0x31, 0x30, 0x30,
-0x30, 0x30, 0x30, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f
-};
-int i;
+ static u_int32_t logMagTable[128] = {
+ 0x00000, 0x02dfc, 0x05b9e, 0x088e6, 0x0b5d6, 0x0e26f, 0x10eb3, 0x13aa2,
+ 0x1663f, 0x1918a, 0x1bc84, 0x1e72e, 0x2118b, 0x23b9a, 0x2655d, 0x28ed5,
+ 0x2b803, 0x2e0e8, 0x30985, 0x331db, 0x359eb, 0x381b6, 0x3a93d, 0x3d081,
+ 0x3f782, 0x41e42, 0x444c1, 0x46b01, 0x49101, 0x4b6c4, 0x4dc49, 0x50191,
+ 0x5269e, 0x54b6f, 0x57006, 0x59463, 0x5b888, 0x5dc74, 0x60029, 0x623a7,
+ 0x646ee, 0x66a00, 0x68cdd, 0x6af86, 0x6d1fa, 0x6f43c, 0x7164b, 0x73829,
+ 0x759d4, 0x77b4f, 0x79c9a, 0x7bdb5, 0x7dea1, 0x7ff5e, 0x81fed, 0x8404e,
+ 0x86082, 0x88089, 0x8a064, 0x8c014, 0x8df98, 0x8fef1, 0x91e20, 0x93d26,
+ 0x95c01, 0x97ab4, 0x9993e, 0x9b79f, 0x9d5d9, 0x9f3ec, 0xa11d8, 0xa2f9d,
+ 0xa4d3c, 0xa6ab5, 0xa8808, 0xaa537, 0xac241, 0xadf26, 0xafbe7, 0xb1885,
+ 0xb3500, 0xb5157, 0xb6d8c, 0xb899f, 0xba58f, 0xbc15e, 0xbdd0c, 0xbf899,
+ 0xc1404, 0xc2f50, 0xc4a7b, 0xc6587, 0xc8073, 0xc9b3f, 0xcb5ed, 0xcd07c,
+ 0xceaec, 0xd053f, 0xd1f73, 0xd398a, 0xd5384, 0xd6d60, 0xd8720, 0xda0c3,
+ 0xdba4a, 0xdd3b4, 0xded03, 0xe0636, 0xe1f4e, 0xe384a, 0xe512c, 0xe69f3,
+ 0xe829f, 0xe9b31, 0xeb3a9, 0xecc08, 0xee44c, 0xefc78, 0xf148a, 0xf2c83,
+ 0xf4463, 0xf5c2a, 0xf73da, 0xf8b71, 0xfa2f0, 0xfba57, 0xfd1a7, 0xfe8df
+ };
+ static char logSlopeTable[128] = {
+ 0x5c, 0x5c, 0x5b, 0x5a, 0x5a, 0x59, 0x58, 0x58,
+ 0x57, 0x56, 0x56, 0x55, 0x55, 0x54, 0x53, 0x53,
+ 0x52, 0x52, 0x51, 0x51, 0x50, 0x50, 0x4f, 0x4f,
+ 0x4e, 0x4d, 0x4d, 0x4d, 0x4c, 0x4c, 0x4b, 0x4b,
+ 0x4a, 0x4a, 0x49, 0x49, 0x48, 0x48, 0x47, 0x47,
+ 0x47, 0x46, 0x46, 0x45, 0x45, 0x45, 0x44, 0x44,
+ 0x43, 0x43, 0x43, 0x42, 0x42, 0x42, 0x41, 0x41,
+ 0x41, 0x40, 0x40, 0x40, 0x3f, 0x3f, 0x3f, 0x3e,
+ 0x3e, 0x3e, 0x3d, 0x3d, 0x3d, 0x3c, 0x3c, 0x3c,
+ 0x3b, 0x3b, 0x3b, 0x3b, 0x3a, 0x3a, 0x3a, 0x39,
+ 0x39, 0x39, 0x39, 0x38, 0x38, 0x38, 0x38, 0x37,
+ 0x37, 0x37, 0x37, 0x36, 0x36, 0x36, 0x36, 0x35,
+ 0x35, 0x35, 0x35, 0x34, 0x34, 0x34, 0x34, 0x34,
+ 0x33, 0x33, 0x33, 0x33, 0x32, 0x32, 0x32, 0x32,
+ 0x32, 0x31, 0x31, 0x31, 0x31, 0x31, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f
+ };
+ int i;
+
+ if (rate == 0)
+ return 0; /* Bail out if no leading "1" */
+ rate *= 11185; /* Scale 48000 to 0x20002380 */
+ for (i = 31; i > 0; i--) {
+ if (rate & 0x80000000) { /* Detect leading "1" */
+ return (((u_int32_t) (i - 15) << 20) +
+ logMagTable[0x7f & (rate >> 24)] +
+ (0x7f & (rate >> 17)) *
+ logSlopeTable[0x7f & (rate >> 24)]);
+ }
+ rate <<= 1;
+ }
-if (rate == 0)
-return 0; /* Bail out if no leading "1" */
-rate *= 11185; /* Scale 48000 to 0x20002380 */
-for (i = 31; i > 0; i--) {
-if (rate & 0x80000000) { /* Detect leading "1" */
-return (((u_int32_t) (i - 15) << 20) +
-logMagTable[0x7f & (rate >> 24)] +
-(0x7f & (rate >> 17)) *
-logSlopeTable[0x7f & (rate >> 24)]);
-}
-rate <<= 1;
-}
-
-return 0; /* Should never reach this point */
+ return 0; /* Should never reach this point */
}
static u_int32_t
emu_rate_to_linearpitch(u_int32_t rate)
{
-rate = (rate << 8) / 375;
-return (rate >> 1) + (rate & 1);
+ rate = (rate << 8) / 375;
+ return (rate >> 1) + (rate & 1);
}
static struct emu_voice *
emu_valloc(struct sc_info *sc)
{
-struct emu_voice *v;
-int i;
+ struct emu_voice *v;
+ int i;
-v = NULL;
-for (i = 0; i < 64 && sc->voice[i].busy; i++);
-if (i < 64) {
-v = &sc->voice[i];
-v->busy = 1;
-}
-return v;
+ v = NULL;
+ for (i = 0; i < 64 && sc->voice[i].busy; i++);
+ if (i < 64) {
+ v = &sc->voice[i];
+ v->busy = 1;
+ }
+ return v;
}
static int
emu_vinit(struct sc_info *sc, struct emu_voice *m, struct emu_voice *s,
-u_int32_t sz, struct snd_dbuf *b)
+ u_int32_t sz, struct snd_dbuf *b)
{
-void *buf;
-bus_addr_t tmp_addr;
+ void *buf;
+ bus_addr_t tmp_addr;
-buf = emu_memalloc(sc, sz, &tmp_addr);
-if (buf == NULL)
-return -1;
-if (b != NULL)
-sndbuf_setup(b, buf, sz);
-m->start = emu_memstart(sc, buf) * EMUPAGESIZE;
-m->end = m->start + sz;
-m->channel = NULL;
-m->speed = 0;
-m->b16 = 0;
-m->stereo = 0;
-m->running = 0;
-m->ismaster = 1;
-m->vol = 0xff;
-m->buf = tmp_addr;
-m->slave = s;
-if (sc->audigy) {
-m->fxrt1 = FXBUS_MIDI_CHORUS | FXBUS_PCM_RIGHT << 8 |
-FXBUS_PCM_LEFT << 16 | FXBUS_MIDI_REVERB << 24;
-m->fxrt2 = 0x3f3f3f3f; /* No effects on second route */
-} else {
-m->fxrt1 = FXBUS_MIDI_CHORUS | FXBUS_PCM_RIGHT << 4 |
-FXBUS_PCM_LEFT << 8 | FXBUS_MIDI_REVERB << 12;
-m->fxrt2 = 0;
-}
-
-if (s != NULL) {
-s->start = m->start;
-s->end = m->end;
-s->channel = NULL;
-s->speed = 0;
-s->b16 = 0;
-s->stereo = 0;
-s->running = 0;
-s->ismaster = 0;
-s->vol = m->vol;
-s->buf = m->buf;
-s->fxrt1 = m->fxrt1;
-s->fxrt2 = m->fxrt2;
-s->slave = NULL;
-}
-return 0;
+ buf = emu_memalloc(sc, sz, &tmp_addr);
+ if (buf == NULL)
+ return -1;
+ if (b != NULL)
+ sndbuf_setup(b, buf, sz);
+ m->start = emu_memstart(sc, buf) * EMUPAGESIZE;
+ m->end = m->start + sz;
+ m->channel = NULL;
+ m->speed = 0;
+ m->b16 = 0;
+ m->stereo = 0;
+ m->running = 0;
+ m->ismaster = 1;
+ m->vol = 0xff;
+ m->buf = tmp_addr;
+ m->slave = s;
+ if (sc->audigy) {
+ m->fxrt1 = FXBUS_MIDI_CHORUS | FXBUS_PCM_RIGHT << 8 |
+ FXBUS_PCM_LEFT << 16 | FXBUS_MIDI_REVERB << 24;
+ m->fxrt2 = 0x3f3f3f3f; /* No effects on second route */
+ } else {
+ m->fxrt1 = FXBUS_MIDI_CHORUS | FXBUS_PCM_RIGHT << 4 |
+ FXBUS_PCM_LEFT << 8 | FXBUS_MIDI_REVERB << 12;
+ m->fxrt2 = 0;
+ }
+
+ if (s != NULL) {
+ s->start = m->start;
+ s->end = m->end;
+ s->channel = NULL;
+ s->speed = 0;
+ s->b16 = 0;
+ s->stereo = 0;
+ s->running = 0;
+ s->ismaster = 0;
+ s->vol = m->vol;
+ s->buf = m->buf;
+ s->fxrt1 = m->fxrt1;
+ s->fxrt2 = m->fxrt2;
+ s->slave = NULL;
+ }
+ return 0;
}
static void
emu_vsetup(struct sc_pchinfo *ch)
{
-struct emu_voice *v = ch->master;
+ struct emu_voice *v = ch->master;
-if (ch->fmt) {
-v->b16 = (ch->fmt & AFMT_16BIT) ? 1 : 0;
-v->stereo = (ch->fmt & AFMT_STEREO) ? 1 : 0;
-if (v->slave != NULL) {
-v->slave->b16 = v->b16;
-v->slave->stereo = v->stereo;
-}
-}
-if (ch->spd) {
-v->speed = ch->spd;
-if (v->slave != NULL)
-v->slave->speed = v->speed;
-}
+ if (ch->fmt) {
+ v->b16 = (ch->fmt & AFMT_16BIT) ? 1 : 0;
+ v->stereo = (ch->fmt & AFMT_STEREO) ? 1 : 0;
+ if (v->slave != NULL) {
+ v->slave->b16 = v->b16;
+ v->slave->stereo = v->stereo;
+ }
+ }
+ if (ch->spd) {
+ v->speed = ch->spd;
+ if (v->slave != NULL)
+ v->slave->speed = v->speed;
+ }
}
static void
emu_vwrite(struct sc_info *sc, struct emu_voice *v)
{
-int s;
-int l, r, x, y;
-u_int32_t sa, ea, start, val, silent_page;
-
-s = (v->stereo ? 1 : 0) + (v->b16 ? 1 : 0);
-
-sa = v->start >> s;
-ea = v->end >> s;
-
-l = r = x = y = v->vol;
-if (v->stereo) {
-l = v->ismaster ? l : 0;
-r = v->ismaster ? 0 : r;
-}
-
-emu_wrptr(sc, v->vnum, CPF, v->stereo ? CPF_STEREO_MASK : 0);
-val = v->stereo ? 28 : 30;
-val *= v->b16 ? 1 : 2;
-start = sa + val;
-
-if (sc->audigy) {
-emu_wrptr(sc, v->vnum, A_FXRT1, v->fxrt1);
-emu_wrptr(sc, v->vnum, A_FXRT2, v->fxrt2);
-emu_wrptr(sc, v->vnum, A_SENDAMOUNTS, 0);
-}
-else
-emu_wrptr(sc, v->vnum, FXRT, v->fxrt1 << 16);
-
-emu_wrptr(sc, v->vnum, PTRX, (x << 8) | r);
-emu_wrptr(sc, v->vnum, DSL, ea | (y << 24));
-emu_wrptr(sc, v->vnum, PSST, sa | (l << 24));
-emu_wrptr(sc, v->vnum, CCCA, start | (v->b16 ? 0 : CCCA_8BITSELECT));
-
-emu_wrptr(sc, v->vnum, Z1, 0);
-emu_wrptr(sc, v->vnum, Z2, 0);
-
-silent_page = ((u_int32_t)(sc->mem.silent_page_addr) << 1)
-| MAP_PTI_MASK;
-emu_wrptr(sc, v->vnum, MAPA, silent_page);
-emu_wrptr(sc, v->vnum, MAPB, silent_page);
-
-emu_wrptr(sc, v->vnum, CVCF, CVCF_CURRENTFILTER_MASK);
-emu_wrptr(sc, v->vnum, VTFT, VTFT_FILTERTARGET_MASK);
-emu_wrptr(sc, v->vnum, ATKHLDM, 0);
-emu_wrptr(sc, v->vnum, DCYSUSM, DCYSUSM_DECAYTIME_MASK);
-emu_wrptr(sc, v->vnum, LFOVAL1, 0x8000);
-emu_wrptr(sc, v->vnum, LFOVAL2, 0x8000);
-emu_wrptr(sc, v->vnum, FMMOD, 0);
-emu_wrptr(sc, v->vnum, TREMFRQ, 0);
-emu_wrptr(sc, v->vnum, FM2FRQ2, 0);
-emu_wrptr(sc, v->vnum, ENVVAL, 0x8000);
-
-emu_wrptr(sc, v->vnum, ATKHLDV,
-ATKHLDV_HOLDTIME_MASK | ATKHLDV_ATTACKTIME_MASK);
-emu_wrptr(sc, v->vnum, ENVVOL, 0x8000);
+ int s;
+ int l, r, x, y;
+ u_int32_t sa, ea, start, val, silent_page;
+
+ s = (v->stereo ? 1 : 0) + (v->b16 ? 1 : 0);
+
+ sa = v->start >> s;
+ ea = v->end >> s;
+
+ l = r = x = y = v->vol;
+ if (v->stereo) {
+ l = v->ismaster ? l : 0;
+ r = v->ismaster ? 0 : r;
+ }
+
+ emu_wrptr(sc, v->vnum, CPF, v->stereo ? CPF_STEREO_MASK : 0);
+ val = v->stereo ? 28 : 30;
+ val *= v->b16 ? 1 : 2;
+ start = sa + val;
+
+ if (sc->audigy) {
+ emu_wrptr(sc, v->vnum, A_FXRT1, v->fxrt1);
+ emu_wrptr(sc, v->vnum, A_FXRT2, v->fxrt2);
+ emu_wrptr(sc, v->vnum, A_SENDAMOUNTS, 0);
+ }
+ else
+ emu_wrptr(sc, v->vnum, FXRT, v->fxrt1 << 16);
+
+ emu_wrptr(sc, v->vnum, PTRX, (x << 8) | r);
+ emu_wrptr(sc, v->vnum, DSL, ea | (y << 24));
+ emu_wrptr(sc, v->vnum, PSST, sa | (l << 24));
+ emu_wrptr(sc, v->vnum, CCCA, start | (v->b16 ? 0 : CCCA_8BITSELECT));
+
+ emu_wrptr(sc, v->vnum, Z1, 0);
+ emu_wrptr(sc, v->vnum, Z2, 0);
+
+ silent_page = ((u_int32_t)(sc->mem.silent_page_addr) << 1)
+ | MAP_PTI_MASK;
+ emu_wrptr(sc, v->vnum, MAPA, silent_page);
+ emu_wrptr(sc, v->vnum, MAPB, silent_page);
+
+ emu_wrptr(sc, v->vnum, CVCF, CVCF_CURRENTFILTER_MASK);
+ emu_wrptr(sc, v->vnum, VTFT, VTFT_FILTERTARGET_MASK);
+ emu_wrptr(sc, v->vnum, ATKHLDM, 0);
+ emu_wrptr(sc, v->vnum, DCYSUSM, DCYSUSM_DECAYTIME_MASK);
+ emu_wrptr(sc, v->vnum, LFOVAL1, 0x8000);
+ emu_wrptr(sc, v->vnum, LFOVAL2, 0x8000);
+ emu_wrptr(sc, v->vnum, FMMOD, 0);
+ emu_wrptr(sc, v->vnum, TREMFRQ, 0);
+ emu_wrptr(sc, v->vnum, FM2FRQ2, 0);
+ emu_wrptr(sc, v->vnum, ENVVAL, 0x8000);
+
+ emu_wrptr(sc, v->vnum, ATKHLDV,
+ ATKHLDV_HOLDTIME_MASK | ATKHLDV_ATTACKTIME_MASK);
+ emu_wrptr(sc, v->vnum, ENVVOL, 0x8000);
-emu_wrptr(sc, v->vnum, PEFE_FILTERAMOUNT, 0x7f);
-emu_wrptr(sc, v->vnum, PEFE_PITCHAMOUNT, 0);
+ emu_wrptr(sc, v->vnum, PEFE_FILTERAMOUNT, 0x7f);
+ emu_wrptr(sc, v->vnum, PEFE_PITCHAMOUNT, 0);
-if (v->slave != NULL)
-emu_vwrite(sc, v->slave);
+ if (v->slave != NULL)
+ emu_vwrite(sc, v->slave);
}
static void
emu_vtrigger(struct sc_info *sc, struct emu_voice *v, int go)
{
-u_int32_t pitch_target, initial_pitch;
-u_int32_t cra, cs, ccis;
-u_int32_t sample, i;
-
-if (go) {
-cra = 64;
-cs = v->stereo ? 4 : 2;
-ccis = v->stereo ? 28 : 30;
-ccis *= v->b16 ? 1 : 2;
-sample = v->b16 ? 0x00000000 : 0x80808080;
-
-for (i = 0; i < cs; i++)
-emu_wrptr(sc, v->vnum, CD0 + i, sample);
-emu_wrptr(sc, v->vnum, CCR_CACHEINVALIDSIZE, 0);
-emu_wrptr(sc, v->vnum, CCR_READADDRESS, cra);
-emu_wrptr(sc, v->vnum, CCR_CACHEINVALIDSIZE, ccis);
-
-emu_wrptr(sc, v->vnum, IFATN, 0xff00);
-emu_wrptr(sc, v->vnum, VTFT, 0xffffffff);
-emu_wrptr(sc, v->vnum, CVCF, 0xffffffff);
-emu_wrptr(sc, v->vnum, DCYSUSV, 0x00007f7f);
-emu_enastop(sc, v->vnum, 0);
-
-pitch_target = emu_rate_to_linearpitch(v->speed);
-initial_pitch = emu_rate_to_pitch(v->speed) >> 8;
-emu_wrptr(sc, v->vnum, PTRX_PITCHTARGET, pitch_target);
-emu_wrptr(sc, v->vnum, CPF_CURRENTPITCH, pitch_target);
-emu_wrptr(sc, v->vnum, IP, initial_pitch);
-} else {
-emu_wrptr(sc, v->vnum, PTRX_PITCHTARGET, 0);
-emu_wrptr(sc, v->vnum, CPF_CURRENTPITCH, 0);
-emu_wrptr(sc, v->vnum, IFATN, 0xffff);
-emu_wrptr(sc, v->vnum, VTFT, 0x0000ffff);
-emu_wrptr(sc, v->vnum, CVCF, 0x0000ffff);
-emu_wrptr(sc, v->vnum, IP, 0);
-emu_enastop(sc, v->vnum, 1);
-}
-if (v->slave != NULL)
-emu_vtrigger(sc, v->slave, go);
+ u_int32_t pitch_target, initial_pitch;
+ u_int32_t cra, cs, ccis;
+ u_int32_t sample, i;
+
+ if (go) {
+ cra = 64;
+ cs = v->stereo ? 4 : 2;
+ ccis = v->stereo ? 28 : 30;
+ ccis *= v->b16 ? 1 : 2;
+ sample = v->b16 ? 0x00000000 : 0x80808080;
+
+ for (i = 0; i < cs; i++)
+ emu_wrptr(sc, v->vnum, CD0 + i, sample);
+ emu_wrptr(sc, v->vnum, CCR_CACHEINVALIDSIZE, 0);
+ emu_wrptr(sc, v->vnum, CCR_READADDRESS, cra);
+ emu_wrptr(sc, v->vnum, CCR_CACHEINVALIDSIZE, ccis);
+
+ emu_wrptr(sc, v->vnum, IFATN, 0xff00);
+ emu_wrptr(sc, v->vnum, VTFT, 0xffffffff);
+ emu_wrptr(sc, v->vnum, CVCF, 0xffffffff);
+ emu_wrptr(sc, v->vnum, DCYSUSV, 0x00007f7f);
+ emu_enastop(sc, v->vnum, 0);
+
+ pitch_target = emu_rate_to_linearpitch(v->speed);
+ initial_pitch = emu_rate_to_pitch(v->speed) >> 8;
+ emu_wrptr(sc, v->vnum, PTRX_PITCHTARGET, pitch_target);
+ emu_wrptr(sc, v->vnum, CPF_CURRENTPITCH, pitch_target);
+ emu_wrptr(sc, v->vnum, IP, initial_pitch);
+ } else {
+ emu_wrptr(sc, v->vnum, PTRX_PITCHTARGET, 0);
+ emu_wrptr(sc, v->vnum, CPF_CURRENTPITCH, 0);
+ emu_wrptr(sc, v->vnum, IFATN, 0xffff);
+ emu_wrptr(sc, v->vnum, VTFT, 0x0000ffff);
+ emu_wrptr(sc, v->vnum, CVCF, 0x0000ffff);
+ emu_wrptr(sc, v->vnum, IP, 0);
+ emu_enastop(sc, v->vnum, 1);
+ }
+ if (v->slave != NULL)
+ emu_vtrigger(sc, v->slave, go);
}
static int
emu_vpos(struct sc_info *sc, struct emu_voice *v)
{
-int s, ptr;
+ int s, ptr;
-s = (v->b16 ? 1 : 0) + (v->stereo ? 1 : 0);
-ptr = (emu_rdptr(sc, v->vnum, CCCA_CURRADDR) - (v->start >> s)) << s;
-return ptr & ~0x0000001f;
+ s = (v->b16 ? 1 : 0) + (v->stereo ? 1 : 0);
+ ptr = (emu_rdptr(sc, v->vnum, CCCA_CURRADDR) - (v->start >> s)) << s;
+ return ptr & ~0x0000001f;
}
#ifdef EMUDEBUG
static void
emu_vdump(struct sc_info *sc, struct emu_voice *v)
{
-char *regname[] = {
-"cpf", "ptrx", "cvcf", "vtft", "z2", "z1", "psst", "dsl",
-"ccca", "ccr", "clp", "fxrt", "mapa", "mapb", NULL, NULL,
-"envvol", "atkhldv", "dcysusv", "lfoval1",
-"envval", "atkhldm", "dcysusm", "lfoval2",
-"ip", "ifatn", "pefe", "fmmod", "tremfrq", "fmfrq2",
-"tempenv"
-};
-char *regname2[] = {
-"mudata1", "mustat1", "mudata2", "mustat2",
-"fxwc1", "fxwc2", "spdrate", NULL, NULL,
-NULL, NULL, NULL, "fxrt2", "sndamnt", "fxrt1",
-NULL, NULL
-};
-int i, x;
-
-printf("voice number %dn", v->vnum);
-for (i = 0, x = 0; i <= 0x1e; i++) {
-if (regname[i] == NULL)
-continue;
-printf("%st[%08x]", regname[i], emu_rdptr(sc, v->vnum, i));
-printf("%s", (x == 2) ? "n" : "t");
-x++;
-if (x > 2)
-x = 0;
-}
-
-/* Print out audigy extra registers */
-if (sc->audigy) {
-for (i = 0; i <= 0xe; i++) {
-if (regname2[i] == NULL)
-continue;
-printf("%st[%08x]", regname2[i],
-emu_rdptr(sc, v->vnum, i + 0x70));
-printf("%s", (x == 2)? "n" : "t");
-x++;
-if (x > 2)
-x = 0;
-}
-}
-printf("nn");
+ char *regname[] = {
+ "cpf", "ptrx", "cvcf", "vtft", "z2", "z1", "psst", "dsl",
+ "ccca", "ccr", "clp", "fxrt", "mapa", "mapb", NULL, NULL,
+ "envvol", "atkhldv", "dcysusv", "lfoval1",
+ "envval", "atkhldm", "dcysusm", "lfoval2",
+ "ip", "ifatn", "pefe", "fmmod", "tremfrq", "fmfrq2",
+ "tempenv"
+ };
+ char *regname2[] = {
+ "mudata1", "mustat1", "mudata2", "mustat2",
+ "fxwc1", "fxwc2", "spdrate", NULL, NULL,
+ NULL, NULL, NULL, "fxrt2", "sndamnt", "fxrt1",
+ NULL, NULL
+ };
+ int i, x;
+
+ printf("voice number %d\n", v->vnum);
+ for (i = 0, x = 0; i <= 0x1e; i++) {
+ if (regname[i] == NULL)
+ continue;
+ printf("%s\t[%08x]", regname[i], emu_rdptr(sc, v->vnum, i));
+ printf("%s", (x == 2) ? "\n" : "\t");
+ x++;
+ if (x > 2)
+ x = 0;
+ }
+
+ /* Print out audigy extra registers */
+ if (sc->audigy) {
+ for (i = 0; i <= 0xe; i++) {
+ if (regname2[i] == NULL)
+ continue;
+ printf("%s\t[%08x]", regname2[i],
+ emu_rdptr(sc, v->vnum, i + 0x70));
+ printf("%s", (x == 2)? "\n" : "\t");
+ x++;
+ if (x > 2)
+ x = 0;
+ }
+ }
+ printf("\n\n");
}
#endif
/* channel interface */
static void *
emupchan_init(kobj_t obj, void *devinfo, struct snd_dbuf *b,
-struct pcm_channel *c, int dir)
+ struct pcm_channel *c, int dir)
{
-struct sc_info *sc = devinfo;
-struct sc_pchinfo *ch;
-void *r;
-
-KASSERT(dir == PCMDIR_PLAY, ("emupchan_init: bad direction"));
-ch = &sc->pch[sc->pnum++];
-ch->buffer = b;
-ch->parent = sc;
-ch->channel = c;
-ch->blksz = sc->bufsz / 2;
-ch->fmt = AFMT_U8;
-ch->spd = 8000;
-snd_mtxlock(sc->lock);
-ch->master = emu_valloc(sc);
-ch->slave = emu_valloc(sc);
-snd_mtxunlock(sc->lock);
-r = (emu_vinit(sc, ch->master, ch->slave, sc->bufsz, ch->buffer))
-? NULL : ch;
+ struct sc_info *sc = devinfo;
+ struct sc_pchinfo *ch;
+ void *r;
+
+ KASSERT(dir == PCMDIR_PLAY, ("emupchan_init: bad direction"));
+ ch = &sc->pch[sc->pnum++];
+ ch->buffer = b;
+ ch->parent = sc;
+ ch->channel = c;
+ ch->blksz = sc->bufsz / 2;
+ ch->fmt = AFMT_U8;
+ ch->spd = 8000;
+ snd_mtxlock(sc->lock);
+ ch->master = emu_valloc(sc);
+ ch->slave = emu_valloc(sc);
+ snd_mtxunlock(sc->lock);
+ r = (emu_vinit(sc, ch->master, ch->slave, sc->bufsz, ch->buffer))
+ ? NULL : ch;
-return r;
+ return r;
}
static int
emupchan_free(kobj_t obj, void *data)
{
-struct sc_pchinfo *ch = data;
-struct sc_info *sc = ch->parent;
-int r;
-
-snd_mtxlock(sc->lock);
-r = emu_memfree(sc, sndbuf_getbuf(ch->buffer));
-snd_mtxunlock(sc->lock);
+ struct sc_pchinfo *ch = data;
+ struct sc_info *sc = ch->parent;
+ int r;
+
+ snd_mtxlock(sc->lock);
+ r = emu_memfree(sc, sndbuf_getbuf(ch->buffer));
+ snd_mtxunlock(sc->lock);
-return r;
+ return r;
}
static int
emupchan_setformat(kobj_t obj, void *data, u_int32_t format)
{
-struct sc_pchinfo *ch = data;
+ struct sc_pchinfo *ch = data;
-ch->fmt = format;
-return 0;
+ ch->fmt = format;
+ return 0;
}
static int
emupchan_setspeed(kobj_t obj, void *data, u_int32_t speed)
{
-struct sc_pchinfo *ch = data;
+ struct sc_pchinfo *ch = data;
-ch->spd = speed;
-return ch->spd;
+ ch->spd = speed;
+ return ch->spd;
}
static int
emupchan_setblocksize(kobj_t obj, void *data, u_int32_t blocksize)
{
-struct sc_pchinfo *ch = data;
-struct sc_info *sc = ch->parent;
-int irqrate, blksz;
-
-ch->blksz = blocksize;
-snd_mtxlock(sc->lock);
-emu_settimer(sc);
-irqrate = 48000 / sc->timerinterval;
-snd_mtxunlock(sc->lock);
-blksz = (ch->spd * sndbuf_getbps(ch->buffer)) / irqrate;
-return blocksize;
+ struct sc_pchinfo *ch = data;
+ struct sc_info *sc = ch->parent;
+ int irqrate, blksz;
+
+ ch->blksz = blocksize;
+ snd_mtxlock(sc->lock);
+ emu_settimer(sc);
+ irqrate = 48000 / sc->timerinterval;
+ snd_mtxunlock(sc->lock);
+ blksz = (ch->spd * sndbuf_getbps(ch->buffer)) / irqrate;
+ return blocksize;
}
static int
emupchan_trigger(kobj_t obj, void *data, int go)
{
-struct sc_pchinfo *ch = data;
-struct sc_info *sc = ch->parent;
+ struct sc_pchinfo *ch = data;
+ struct sc_info *sc = ch->parent;
-if (go == PCMTRIG_EMLDMAWR || go == PCMTRIG_EMLDMARD)
-return 0;
+ if (!PCMTRIG_COMMON(go))
+ return 0;
-snd_mtxlock(sc->lock);
-if (go == PCMTRIG_START) {
-emu_vsetup(ch);
-emu_vwrite(sc, ch->master);
-emu_settimer(sc);
-emu_enatimer(sc, 1);
+ snd_mtxlock(sc->lock);
+ if (go == PCMTRIG_START) {
+ emu_vsetup(ch);
+ emu_vwrite(sc, ch->master);
+ emu_settimer(sc);
+ emu_enatimer(sc, 1);
#ifdef EMUDEBUG
-printf("start [%d bit, %s, %d hz]n",
-ch->master->b16 ? 16 : 8,
-ch->master->stereo ? "stereo" : "mono",
-ch->master->speed);
-emu_vdump(sc, ch->master);
-emu_vdump(sc, ch->slave);
+ printf("start [%d bit, %s, %d hz]\n",
+ ch->master->b16 ? 16 : 8,
+ ch->master->stereo ? "stereo" : "mono",
+ ch->master->speed);
+ emu_vdump(sc, ch->master);
+ emu_vdump(sc, ch->slave);
#endif
-}
-ch->run = (go == PCMTRIG_START) ? 1 : 0;
-emu_vtrigger(sc, ch->master, ch->run);
-snd_mtxunlock(sc->lock);
-return 0;
+ }
+ ch->run = (go == PCMTRIG_START) ? 1 : 0;
+ emu_vtrigger(sc, ch->master, ch->run);
+ snd_mtxunlock(sc->lock);
+ return 0;
}
static int
emupchan_getptr(kobj_t obj, void *data)
{
-struct sc_pchinfo *ch = data;
-struct sc_info *sc = ch->parent;
-int r;
-
-snd_mtxlock(sc->lock);
-r = emu_vpos(sc, ch->master);
-snd_mtxunlock(sc->lock);
+ struct sc_pchinfo *ch = data;
+ struct sc_info *sc = ch->parent;
+ int r;
+
+ snd_mtxlock(sc->lock);
+ r = emu_vpos(sc, ch->master);
+ snd_mtxunlock(sc->lock);
-return r;
+ return r;
}
static struct pcmchan_caps *
emupchan_getcaps(kobj_t obj, void *data)
{
-return &emu_playcaps;
+ return &emu_playcaps;
}
static kobj_method_t emupchan_methods[] = {
-KOBJMETHOD(channel_init, emupchan_init),
-KOBJMETHOD(channel_free, emupchan_free),
-KOBJMETHOD(channel_setformat, emupchan_setformat),
-KOBJMETHOD(channel_setspeed, emupchan_setspeed),
-KOBJMETHOD(channel_setblocksize, emupchan_setblocksize),
-KOBJMETHOD(channel_trigger, emupchan_trigger),
-KOBJMETHOD(channel_getptr, emupchan_getptr),
-KOBJMETHOD(channel_getcaps, emupchan_getcaps),
-{ 0, 0 }
+ KOBJMETHOD(channel_init, emupchan_init),
+ KOBJMETHOD(channel_free, emupchan_free),
+ KOBJMETHOD(channel_setformat, emupchan_setformat),
+ KOBJMETHOD(channel_setspeed, emupchan_setspeed),
+ KOBJMETHOD(channel_setblocksize, emupchan_setblocksize),
+ KOBJMETHOD(channel_trigger, emupchan_trigger),
+ KOBJMETHOD(channel_getptr, emupchan_getptr),
+ KOBJMETHOD(channel_getcaps, emupchan_getcaps),
+ { 0, 0 }
};
CHANNEL_DECLARE(emupchan);
/* channel interface */
static void *
emurchan_init(kobj_t obj, void *devinfo, struct snd_dbuf *b,
-struct pcm_channel *c, int dir)
+ struct pcm_channel *c, int dir)
{
-struct sc_info *sc = devinfo;
-struct sc_rchinfo *ch;
+ struct sc_info *sc = devinfo;
+ struct sc_rchinfo *ch;
-KASSERT(dir == PCMDIR_REC, ("emurchan_init: bad direction"));
-ch = &sc->rch[sc->rnum];
-ch->buffer = b;
-ch->parent = sc;
-ch->channel = c;
-ch->blksz = sc->bufsz / 2;
-ch->fmt = AFMT_U8;
-ch->spd = 8000;
-ch->num = sc->rnum;
-switch(sc->rnum) {
-case 0:
-ch->idxreg = sc->audigy ? A_ADCIDX : ADCIDX;
-ch->basereg = ADCBA;
-ch->sizereg = ADCBS;
-ch->setupreg = ADCCR;
-ch->irqmask = INTE_ADCBUFENABLE;
-break;
-
-case 1:
-ch->idxreg = FXIDX;
-ch->basereg = FXBA;
-ch->sizereg = FXBS;
-ch->setupreg = FXWC;
-ch->irqmask = INTE_EFXBUFENABLE;
-break;
-
-case 2:
-ch->idxreg = MICIDX;
-ch->basereg = MICBA;
-ch->sizereg = MICBS;
-ch->setupreg = 0;
-ch->irqmask = INTE_MICBUFENABLE;
-break;
-}
-sc->rnum++;
-if (sndbuf_alloc(ch->buffer, sc->parent_dmat, sc->bufsz) != 0)
-return NULL;
-else {
-snd_mtxlock(sc->lock);
-emu_wrptr(sc, 0, ch->basereg, sndbuf_getbufaddr(ch->buffer));
-emu_wrptr(sc, 0, ch->sizereg, 0); /* off */
-snd_mtxunlock(sc->lock);
-return ch;
-}
+ KASSERT(dir == PCMDIR_REC, ("emurchan_init: bad direction"));
+ ch = &sc->rch[sc->rnum];
+ ch->buffer = b;
+ ch->parent = sc;
+ ch->channel = c;
+ ch->blksz = sc->bufsz / 2;
+ ch->fmt = AFMT_U8;
+ ch->spd = 8000;
+ ch->num = sc->rnum;
+ switch(sc->rnum) {
+ case 0:
+ ch->idxreg = sc->audigy ? A_ADCIDX : ADCIDX;
+ ch->basereg = ADCBA;
+ ch->sizereg = ADCBS;
+ ch->setupreg = ADCCR;
+ ch->irqmask = INTE_ADCBUFENABLE;
+ break;
+
+ case 1:
+ ch->idxreg = FXIDX;
+ ch->basereg = FXBA;
+ ch->sizereg = FXBS;
+ ch->setupreg = FXWC;
+ ch->irqmask = INTE_EFXBUFENABLE;
+ break;
+
+ case 2:
+ ch->idxreg = MICIDX;
+ ch->basereg = MICBA;
+ ch->sizereg = MICBS;
+ ch->setupreg = 0;
+ ch->irqmask = INTE_MICBUFENABLE;
+ break;
+ }
+ sc->rnum++;
+ if (sndbuf_alloc(ch->buffer, sc->parent_dmat, 0, sc->bufsz) != 0)
+ return NULL;
+ else {
+ snd_mtxlock(sc->lock);
+ emu_wrptr(sc, 0, ch->basereg, sndbuf_getbufaddr(ch->buffer));
+ emu_wrptr(sc, 0, ch->sizereg, 0); /* off */
+ snd_mtxunlock(sc->lock);
+ return ch;
+ }
}
static int
emurchan_setformat(kobj_t obj, void *data, u_int32_t format)
{
-struct sc_rchinfo *ch = data;
+ struct sc_rchinfo *ch = data;
-ch->fmt = format;
-return 0;
+ ch->fmt = format;
+ return 0;
}
static int
emurchan_setspeed(kobj_t obj, void *data, u_int32_t speed)
{
-struct sc_rchinfo *ch = data;
+ struct sc_rchinfo *ch = data;
-if (ch->num == 0) {
-if (ch->parent->audigy)
-speed = audigy_adcspeed[audigy_recval(speed)];
-else
-speed = adcspeed[emu_recval(speed)];
-}
-if (ch->num == 1)
-speed = 48000;
-if (ch->num == 2)
-speed = 8000;
-ch->spd = speed;
-return ch->spd;
+ if (ch->num == 0) {
+ if (ch->parent->audigy)
+ speed = audigy_adcspeed[audigy_recval(speed)];
+ else
+ speed = adcspeed[emu_recval(speed)];
+ }
+ if (ch->num == 1)
+ speed = 48000;
+ if (ch->num == 2)
+ speed = 8000;
+ ch->spd = speed;
+ return ch->spd;
}
static int
emurchan_setblocksize(kobj_t obj, void *data, u_int32_t blocksize)
{
-struct sc_rchinfo *ch = data;
-struct sc_info *sc = ch->parent;
-int irqrate, blksz;
-
-ch->blksz = blocksize;
-snd_mtxlock(sc->lock);
-emu_settimer(sc);
-irqrate = 48000 / sc->timerinterval;
-snd_mtxunlock(sc->lock);
-blksz = (ch->spd * sndbuf_getbps(ch->buffer)) / irqrate;
-return blocksize;
+ struct sc_rchinfo *ch = data;
+ struct sc_info *sc = ch->parent;
+ int irqrate, blksz;
+
+ ch->blksz = blocksize;
+ snd_mtxlock(sc->lock);
+ emu_settimer(sc);
+ irqrate = 48000 / sc->timerinterval;
+ snd_mtxunlock(sc->lock);
+ blksz = (ch->spd * sndbuf_getbps(ch->buffer)) / irqrate;
+ return blocksize;
}
/* semantic note: must start at beginning of buffer */
static int
emurchan_trigger(kobj_t obj, void *data, int go)
{
-struct sc_rchinfo *ch = data;
-struct sc_info *sc = ch->parent;
-u_int32_t val, sz;
-
-switch(sc->bufsz) {
-case 4096:
-sz = ADCBS_BUFSIZE_4096;
-break;
-
-case 8192:
-sz = ADCBS_BUFSIZE_8192;
-break;
-
-case 16384:
-sz = ADCBS_BUFSIZE_16384;
-break;
-
-case 32768:
-sz = ADCBS_BUFSIZE_32768;
-break;
-
-case 65536:
-sz = ADCBS_BUFSIZE_65536;
-break;
-
-default:
-sz = ADCBS_BUFSIZE_4096;
-}
-
-snd_mtxlock(sc->lock);
-switch(go) {
-case PCMTRIG_START:
-ch->run = 1;
-emu_wrptr(sc, 0, ch->sizereg, sz);
-if (ch->num == 0) {
-if (sc->audigy) {
-val = A_ADCCR_LCHANENABLE;
-if (ch->fmt & AFMT_STEREO)
-val |= A_ADCCR_RCHANENABLE;
-val |= audigy_recval(ch->spd);
-} else {
-val = ADCCR_LCHANENABLE;
-if (ch->fmt & AFMT_STEREO)
-val |= ADCCR_RCHANENABLE;
-val |= emu_recval(ch->spd);
-}
-
-emu_wrptr(sc, 0, ch->setupreg, 0);
-emu_wrptr(sc, 0, ch->setupreg, val);
-}
-val = emu_rd(sc, INTE, 4);
-val |= ch->irqmask;
-emu_wr(sc, INTE, val, 4);
-break;
-
-case PCMTRIG_STOP:
-case PCMTRIG_ABORT:
-ch->run = 0;
-emu_wrptr(sc, 0, ch->sizereg, 0);
-if (ch->setupreg)
-emu_wrptr(sc, 0, ch->setupreg, 0);
-val = emu_rd(sc, INTE, 4);
-val &= ~ch->irqmask;
-emu_wr(sc, INTE, val, 4);
-break;
-
-case PCMTRIG_EMLDMAWR:
-case PCMTRIG_EMLDMARD:
-default:
-break;
-}
-snd_mtxunlock(sc->lock);
+ struct sc_rchinfo *ch = data;
+ struct sc_info *sc = ch->parent;
+ u_int32_t val, sz;
+
+ if (!PCMTRIG_COMMON(go))
+ return 0;
+
+ switch(sc->bufsz) {
+ case 4096:
+ sz = ADCBS_BUFSIZE_4096;
+ break;
+
+ case 8192:
+ sz = ADCBS_BUFSIZE_8192;
+ break;
+
+ case 16384:
+ sz = ADCBS_BUFSIZE_16384;
+ break;
+
+ case 32768:
+ sz = ADCBS_BUFSIZE_32768;
+ break;
+
+ case 65536:
+ sz = ADCBS_BUFSIZE_65536;
+ break;
+
+ default:
+ sz = ADCBS_BUFSIZE_4096;
+ }
+
+ snd_mtxlock(sc->lock);
+ switch(go) {
+ case PCMTRIG_START:
+ ch->run = 1;
+ emu_wrptr(sc, 0, ch->sizereg, sz);
+ if (ch->num == 0) {
+ if (sc->audigy) {
+ val = A_ADCCR_LCHANENABLE;
+ if (ch->fmt & AFMT_STEREO)
+ val |= A_ADCCR_RCHANENABLE;
+ val |= audigy_recval(ch->spd);
+ } else {
+ val = ADCCR_LCHANENABLE;
+ if (ch->fmt & AFMT_STEREO)
+ val |= ADCCR_RCHANENABLE;
+ val |= emu_recval(ch->spd);
+ }
+
+ emu_wrptr(sc, 0, ch->setupreg, 0);
+ emu_wrptr(sc, 0, ch->setupreg, val);
+ }
+ val = emu_rd(sc, INTE, 4);
+ val |= ch->irqmask;
+ emu_wr(sc, INTE, val, 4);
+ break;
+
+ case PCMTRIG_STOP:
+ case PCMTRIG_ABORT:
+ ch->run = 0;
+ emu_wrptr(sc, 0, ch->sizereg, 0);
+ if (ch->setupreg)
+ emu_wrptr(sc, 0, ch->setupreg, 0);
+ val = emu_rd(sc, INTE, 4);
+ val &= ~ch->irqmask;
+ emu_wr(sc, INTE, val, 4);
+ break;
+
+ case PCMTRIG_EMLDMAWR:
+ case PCMTRIG_EMLDMARD:
+ default:
+ break;
+ }
+ snd_mtxunlock(sc->lock);
-return 0;
+ return 0;
}
static int
emurchan_getptr(kobj_t obj, void *data)
{
-struct sc_rchinfo *ch = data;
-struct sc_info *sc = ch->parent;
-int r;
-
-snd_mtxlock(sc->lock);
-r = emu_rdptr(sc, 0, ch->idxreg) & 0x0000ffff;
-snd_mtxunlock(sc->lock);
+ struct sc_rchinfo *ch = data;
+ struct sc_info *sc = ch->parent;
+ int r;
+
+ snd_mtxlock(sc->lock);
+ r = emu_rdptr(sc, 0, ch->idxreg) & 0x0000ffff;
+ snd_mtxunlock(sc->lock);
-return r;
+ return r;
}
static struct pcmchan_caps *
emurchan_getcaps(kobj_t obj, void *data)
{
-struct sc_rchinfo *ch = data;
+ struct sc_rchinfo *ch = data;
-return &emu_reccaps[ch->num];
+ return &emu_reccaps[ch->num];
}
static kobj_method_t emurchan_methods[] = {
-KOBJMETHOD(channel_init, emurchan_init),
-KOBJMETHOD(channel_setformat, emurchan_setformat),
-KOBJMETHOD(channel_setspeed, emurchan_setspeed),
-KOBJMETHOD(channel_setblocksize, emurchan_setblocksize),
-KOBJMETHOD(channel_trigger, emurchan_trigger),
-KOBJMETHOD(channel_getptr, emurchan_getptr),
-KOBJMETHOD(channel_getcaps, emurchan_getcaps),
-{ 0, 0 }
+ KOBJMETHOD(channel_init, emurchan_init),
+ KOBJMETHOD(channel_setformat, emurchan_setformat),
+ KOBJMETHOD(channel_setspeed, emurchan_setspeed),
+ KOBJMETHOD(channel_setblocksize, emurchan_setblocksize),
+ KOBJMETHOD(channel_trigger, emurchan_trigger),
+ KOBJMETHOD(channel_getptr, emurchan_getptr),
+ KOBJMETHOD(channel_getcaps, emurchan_getcaps),
+ { 0, 0 }
};
CHANNEL_DECLARE(emurchan);
-/* -------------------------------------------------------------------- */
-/* The interrupt handler */
+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_intr(void *data)
+emu_mwrite(void *arg, struct sc_info *sc, int reg, unsigned char b)
{
-struct sc_info *sc = data;
-u_int32_t stat, ack, i, x;
-snd_mtxlock(sc->lock);
-while (1) {
-stat = emu_rd(sc, IPR, 4);
-if (stat == 0)
-break;
-ack = 0;
-
-/* process irq */
-if (stat & IPR_INTERVALTIMER)
-ack |= IPR_INTERVALTIMER;
-
-if (stat & (IPR_ADCBUFFULL | IPR_ADCBUFHALFFULL))
-ack |= stat & (IPR_ADCBUFFULL | IPR_ADCBUFHALFFULL);
-
-if (stat & (IPR_EFXBUFFULL | IPR_EFXBUFHALFFULL))
-ack |= stat & (IPR_EFXBUFFULL | IPR_EFXBUFHALFFULL);
-
-if (stat & (IPR_MICBUFFULL | IPR_MICBUFHALFFULL))
-ack |= stat & (IPR_MICBUFFULL | IPR_MICBUFHALFFULL);
-
-if (stat & IPR_PCIERROR) {
-ack |= IPR_PCIERROR;
-device_printf(sc->dev, "pci errorn");
-/* we still get an nmi with ecc ram even if we ack this */
+ emu_wr(sc, 0x18 + reg, b, 1);
}
-if (stat & IPR_SAMPLERATETRACKER) {
-ack |= IPR_SAMPLERATETRACKER;
-#ifdef EMUDEBUG
-device_printf(sc->dev,
-"sample rate tracker lock status changen");
-#endif
+
+static int
+emu_muninit(void *arg, struct sc_info *sc)
+{
+
+ snd_mtxlock(sc->lock);
+ sc->mpu_intr = 0;
+ snd_mtxunlock(sc->lock);
+
+ return 0;
}
-if (stat & ~ack)
-device_printf(sc->dev, "dodgy irq: %x (harmless)n",
-stat & ~ack);
+static kobj_method_t emu_mpu_methods[] = {
+ KOBJMETHOD(mpufoi_read, emu_mread),
+ KOBJMETHOD(mpufoi_write, emu_mwrite),
+ KOBJMETHOD(mpufoi_uninit, emu_muninit),
+ { 0, 0 }
+};
-emu_wr(sc, IPR, stat, 4);
+static DEFINE_CLASS(emu_mpu, emu_mpu_methods, 0);
-if (ack) {
-snd_mtxunlock(sc->lock);
+static void
+emu_intr2(void *p)
+{
+ struct sc_info *sc = (struct sc_info *)p;
-if (ack & IPR_INTERVALTIMER) {
-x = 0;
-for (i = 0; i < sc->nchans; i++) {
-if (sc->pch[i].run) {
-x = 1;
-chn_intr(sc->pch[i].channel);
-}
-}
-if (x == 0)
-emu_enatimer(sc, 0);
+ if (sc->mpu_intr)
+ (sc->mpu_intr)(sc->mpu);
}
+static void
+emu_midiattach(struct sc_info *sc)
+{
+ int i;
-if (ack & (IPR_ADCBUFFULL | IPR_ADCBUFHALFFULL)) {
-if (sc->rch[0].channel)
-chn_intr(sc->rch[0].channel);
-}
-if (ack & (IPR_EFXBUFFULL | IPR_EFXBUFHALFFULL)) {
-if (sc->rch[1].channel)
-chn_intr(sc->rch[1].channel);
-}
-if (ack & (IPR_MICBUFFULL | IPR_MICBUFHALFFULL)) {
-if (sc->rch[2].channel)
-chn_intr(sc->rch[2].channel);
-}
+ i = emu_rd(sc, INTE, 4);
+ i |= INTE_MIDIRXENABLE;
+ emu_wr(sc, INTE, i, 4);
-snd_mtxlock(sc->lock);
-}
+ sc->mpu = mpu401_init(&emu_mpu_class, sc, emu_intr2, &sc->mpu_intr);
}
-snd_mtxunlock(sc->lock);
+/* -------------------------------------------------------------------- */
+/* The interrupt handler */
+
+static void
+emu_intr(void *data)
+{
+ struct sc_info *sc = data;
+ u_int32_t stat, ack, i, x;
+
+ snd_mtxlock(sc->lock);
+ while (1) {
+ stat = emu_rd(sc, IPR, 4);
+ if (stat == 0)
+ break;
+ ack = 0;
+
+ /* process irq */
+ if (stat & IPR_INTERVALTIMER)
+ ack |= IPR_INTERVALTIMER;
+
+ if (stat & (IPR_ADCBUFFULL | IPR_ADCBUFHALFFULL))
+ ack |= stat & (IPR_ADCBUFFULL | IPR_ADCBUFHALFFULL);
+
+ if (stat & (IPR_EFXBUFFULL | IPR_EFXBUFHALFFULL))
+ ack |= stat & (IPR_EFXBUFFULL | IPR_EFXBUFHALFFULL);
+
+ if (stat & (IPR_MICBUFFULL | IPR_MICBUFHALFFULL))
+ ack |= stat & (IPR_MICBUFFULL | IPR_MICBUFHALFFULL);
+
+ if (stat & IPR_PCIERROR) {
+ ack |= IPR_PCIERROR;
+ device_printf(sc->dev, "pci error\n");
+ /* we still get an nmi with ecc ram even if we ack this */
+ }
+ if (stat & IPR_SAMPLERATETRACKER) {
+ ack |= IPR_SAMPLERATETRACKER;
+#ifdef EMUDEBUG
+ device_printf(sc->dev,
+ "sample rate tracker lock status change\n");
+#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);
+
+ emu_wr(sc, IPR, stat, 4);
+
+ if (ack) {
+ snd_mtxunlock(sc->lock);
+
+ if (ack & IPR_INTERVALTIMER) {
+ x = 0;
+ for (i = 0; i < sc->nchans; i++) {
+ if (sc->pch[i].run) {
+ x = 1;
+ chn_intr(sc->pch[i].channel);
+ }
+ }
+ if (x == 0)
+ emu_enatimer(sc, 0);
+ }
+
+
+ if (ack & (IPR_ADCBUFFULL | IPR_ADCBUFHALFFULL)) {
+ if (sc->rch[0].channel)
+ chn_intr(sc->rch[0].channel);
+ }
+ if (ack & (IPR_EFXBUFFULL | IPR_EFXBUFHALFFULL)) {
+ if (sc->rch[1].channel)
+ chn_intr(sc->rch[1].channel);
+ }
+ if (ack & (IPR_MICBUFFULL | IPR_MICBUFHALFFULL)) {
+ if (sc->rch[2].channel)
+ chn_intr(sc->rch[2].channel);
+ }
+
+ snd_mtxlock(sc->lock);
+ }
+ }
+ snd_mtxunlock(sc->lock);
}
/* -------------------------------------------------------------------- */
@@ -1146,947 +1216,949 @@
static void
emu_setmap(void *arg, bus_dma_segment_t *segs, int nseg, int error)
{
-bus_addr_t *phys = arg;
+ bus_addr_t *phys = arg;
-*phys = error ? 0 : (bus_addr_t)segs->ds_addr;
+ *phys = error ? 0 : (bus_addr_t)segs->ds_addr;
-if (bootverbose) {
-printf("emu: setmap (%lx, %lx), nseg=%d, error=%dn",
-(unsigned long)segs->ds_addr, (unsigned long)segs->ds_len,
-nseg, error);
-}
+ if (bootverbose) {
+ printf("emu: setmap (%lx, %lx), nseg=%d, error=%d\n",
+ (unsigned long)segs->ds_addr, (unsigned long)segs->ds_len,
+ nseg, error);
+ }
}
static void *
emu_malloc(struct sc_info *sc, u_int32_t sz, bus_addr_t *addr)
{
-void *buf;
-bus_dmamap_t map;
+ void *buf;
+ bus_dmamap_t map;
-*addr = 0;
-if (bus_dmamem_alloc(sc->parent_dmat, &buf, BUS_DMA_NOWAIT, &map))
-return NULL;
-if (bus_dmamap_load(sc->parent_dmat, map, buf, sz, emu_setmap, addr, 0)
-|| !*addr)
-return NULL;
-return buf;
+ *addr = 0;
+ if (bus_dmamem_alloc(sc->parent_dmat, &buf, BUS_DMA_NOWAIT, &map))
+ return NULL;
+ if (bus_dmamap_load(sc->parent_dmat, map, buf, sz, emu_setmap, addr, 0)
+ || !*addr)
+ return NULL;
+ return buf;
}
static void
emu_free(struct sc_info *sc, void *buf)
{
-bus_dmamem_free(sc->parent_dmat, buf, NULL);
+ bus_dmamem_free(sc->parent_dmat, buf, NULL);
}
static void *
emu_memalloc(struct sc_info *sc, u_int32_t sz, bus_addr_t *addr)
{
-u_int32_t blksz, start, idx, ofs, tmp, found;
-struct emu_mem *mem = &sc->mem;
-struct emu_memblk *blk;
-void *buf;
-
-blksz = sz / EMUPAGESIZE;
-if (sz > (blksz * EMUPAGESIZE))
-blksz++;
-/* find a free block in the bitmap */
-found = 0;
-start = 1;
-while (!found && start + blksz < EMUMAXPAGES) {
-found = 1;
-for (idx = start; idx < start + blksz; idx++)
-if (mem->bmap[idx >> 3] & (1 << (idx & 7)))
-found = 0;
-if (!found)
-start++;
-}
-if (!found)
-return NULL;
-blk = malloc(sizeof(*blk), M_DEVBUF, M_NOWAIT);
-if (blk == NULL)
-return NULL;
-buf = emu_malloc(sc, sz, &blk->buf_addr);
-*addr = blk->buf_addr;
-if (buf == NULL) {
-free(blk, M_DEVBUF);
-return NULL;
-}
-blk->buf = buf;
-blk->pte_start = start;
-blk->pte_size = blksz;
+ u_int32_t blksz, start, idx, ofs, tmp, found;
+ struct emu_mem *mem = &sc->mem;
+ struct emu_memblk *blk;
+ void *buf;
+
+ blksz = sz / EMUPAGESIZE;
+ if (sz > (blksz * EMUPAGESIZE))
+ blksz++;
+ /* find a free block in the bitmap */
+ found = 0;
+ start = 1;
+ while (!found && start + blksz < EMUMAXPAGES) {
+ found = 1;
+ for (idx = start; idx < start + blksz; idx++)
+ if (mem->bmap[idx >> 3] & (1 << (idx & 7)))
+ found = 0;
+ if (!found)
+ start++;
+ }
+ if (!found)
+ return NULL;
+ blk = malloc(sizeof(*blk), M_DEVBUF, M_NOWAIT);
+ if (blk == NULL)
+ return NULL;
+ buf = emu_malloc(sc, sz, &blk->buf_addr);
+ *addr = blk->buf_addr;
+ if (buf == NULL) {
+ free(blk, M_DEVBUF);
+ return NULL;
+ }
+ blk->buf = buf;
+ blk->pte_start = start;
+ blk->pte_size = blksz;
#ifdef EMUDEBUG
-printf("buf %p, pte_start %d, pte_size %dn", blk->buf,
-blk->pte_start, blk->pte_size);
+ printf("buf %p, pte_start %d, pte_size %d\n", blk->buf,
+ blk->pte_start, blk->pte_size);
#endif
-ofs = 0;
-for (idx = start; idx < start + blksz; idx++) {
-mem->bmap[idx >> 3] |= 1 << (idx & 7);
-tmp = (u_int32_t)(u_long)((u_int8_t *)blk->buf_addr + ofs);
+ ofs = 0;
+ for (idx = start; idx < start + blksz; idx++) {
+ mem->bmap[idx >> 3] |= 1 << (idx & 7);
+ tmp = (u_int32_t)(u_long)((u_int8_t *)blk->buf_addr + ofs);
#ifdef EMUDEBUG
-printf("pte[%d] -> %x phys, %x virtn", idx, tmp,
-((u_int32_t)buf) + ofs);
+ printf("pte[%d] -> %x phys, %x virt\n", idx, tmp,
+ ((u_int32_t)buf) + ofs);
#endif
-mem->ptb_pages[idx] = (tmp << 1) | idx;
-ofs += EMUPAGESIZE;
-}
-SLIST_INSERT_HEAD(&mem->blocks, blk, link);
-return buf;
+ mem->ptb_pages[idx] = (tmp << 1) | idx;
+ ofs += EMUPAGESIZE;
+ }
+ SLIST_INSERT_HEAD(&mem->blocks, blk, link);
+ return buf;
}
static int
emu_memfree(struct sc_info *sc, void *buf)
{
-u_int32_t idx, tmp;
-struct emu_mem *mem = &sc->mem;
-struct emu_memblk *blk, *i;
-
-blk = NULL;
-SLIST_FOREACH(i, &mem->blocks, link) {
-if (i->buf == buf)
-blk = i;
-}
-if (blk == NULL)
-return EINVAL;
-SLIST_REMOVE(&mem->blocks, blk, emu_memblk, link);
-emu_free(sc, buf);
-tmp = (u_int32_t)(sc->mem.silent_page_addr) << 1;
-for (idx = blk->pte_start; idx < blk->pte_start + blk->pte_size; idx++) {
-mem->bmap[idx >> 3] &= ~(1 << (idx & 7));
-mem->ptb_pages[idx] = tmp | idx;
-}
-free(blk, M_DEVBUF);
-return 0;
+ u_int32_t idx, tmp;
+ struct emu_mem *mem = &sc->mem;
+ struct emu_memblk *blk, *i;
+
+ blk = NULL;
+ SLIST_FOREACH(i, &mem->blocks, link) {
+ if (i->buf == buf)
+ blk = i;
+ }
+ if (blk == NULL)
+ return EINVAL;
+ SLIST_REMOVE(&mem->blocks, blk, emu_memblk, link);
+ emu_free(sc, buf);
+ tmp = (u_int32_t)(sc->mem.silent_page_addr) << 1;
+ for (idx = blk->pte_start; idx < blk->pte_start + blk->pte_size; idx++) {
+ mem->bmap[idx >> 3] &= ~(1 << (idx & 7));
+ mem->ptb_pages[idx] = tmp | idx;
+ }
+ free(blk, M_DEVBUF);
+ return 0;
}
static int
emu_memstart(struct sc_info *sc, void *buf)
{
-struct emu_mem *mem = &sc->mem;
-struct emu_memblk *blk, *i;
+ struct emu_mem *mem = &sc->mem;
+ struct emu_memblk *blk, *i;
-blk = NULL;
-SLIST_FOREACH(i, &mem->blocks, link) {
-if (i->buf == buf)
-blk = i;
-}
-if (blk == NULL)
-return -EINVAL;
-return blk->pte_start;
+ blk = NULL;
+ SLIST_FOREACH(i, &mem->blocks, link) {
+ if (i->buf == buf)
+ blk = i;
+ }
+ if (blk == NULL)
+ return -EINVAL;
+ return blk->pte_start;
}
static void
emu_addefxop(struct sc_info *sc, int op, int z, int w, int x, int y,
-u_int32_t *pc)
+ u_int32_t *pc)
{
-emu_wrefx(sc, (*pc) * 2, (x << 10) | y);
-emu_wrefx(sc, (*pc) * 2 + 1, (op << 20) | (z << 10) | w);
-(*pc)++;
+ emu_wrefx(sc, (*pc) * 2, (x << 10) | y);
+ emu_wrefx(sc, (*pc) * 2 + 1, (op << 20) | (z << 10) | w);
+ (*pc)++;
}
static void
audigy_addefxop(struct sc_info *sc, int op, int z, int w, int x, int y,
-u_int32_t *pc)
+ u_int32_t *pc)
{
-emu_wrefx(sc, (*pc) * 2, (x << 12) | y);
-emu_wrefx(sc, (*pc) * 2 + 1, (op << 24) | (z << 12) | w);
-(*pc)++;
+ emu_wrefx(sc, (*pc) * 2, (x << 12) | y);
+ emu_wrefx(sc, (*pc) * 2 + 1, (op << 24) | (z << 12) | w);
+ (*pc)++;
}
static void
audigy_initefx(struct sc_info *sc)
{
-int i;
-u_int32_t pc = 0;
+ int i;
+ u_int32_t pc = 0;
-/* skip 0, 0, -1, 0 - NOPs */
-for (i = 0; i < 512; i++)
-audigy_addefxop(sc, 0x0f, 0x0c0, 0x0c0, 0x0cf, 0x0c0, &pc);
-
-for (i = 0; i < 512; i++)
-emu_wrptr(sc, 0, A_FXGPREGBASE + i, 0x0);
-
-pc = 16;
-
-/* stop fx processor */
-emu_wrptr(sc, 0, A_DBG, A_DBG_SINGLE_STEP);
-
-/* Audigy 2 (EMU10K2) DSP Registers:
-FX Bus
-0x000-0x00f : 16 registers (???)
-Input
-0x040/0x041 : AC97 Codec (l/r)
-0x042/0x043 : ADC, S/PDIF (l/r)
-0x044/0x045 : Optical S/PDIF in (l/r)
-0x046/0x047 : ???
-0x048/0x049 : Line/Mic 2 (l/r)
-0x04a/0x04b : RCA S/PDIF (l/r)
-0x04c/0x04d : Aux 2 (l/r)
-Output
-0x060/0x061 : Digital Front (l/r)
-0x062/0x063 : Digital Center/LFE
-0x064/0x065 : AudigyDrive Heaphone (l/r)
-0x066/0x067 : Digital Rear (l/r)
-0x068/0x069 : Analog Front (l/r)
-0x06a/0x06b : Analog Center/LFE
-0x06c/0x06d : ???
-0x06e/0x06f : Analog Rear (l/r)
-0x070/0x071 : AC97 Output (l/r)
-0x072/0x073 : ???
-0x074/0x075 : ???
-0x076/0x077 : ADC Recording Buffer (l/r)
-Constants
-0x0c0 - 0x0c4 = 0 - 4
-0x0c5 = 0x8, 0x0c6 = 0x10, 0x0c7 = 0x20
-0x0c8 = 0x100, 0x0c9 = 0x10000, 0x0ca = 0x80000
-0x0cb = 0x10000000, 0x0cc = 0x20000000, 0x0cd = 0x40000000
-0x0ce = 0x80000000, 0x0cf = 0x7fffffff, 0x0d0 = 0xffffffff
-0x0d1 = 0xfffffffe, 0x0d2 = 0xc0000000, 0x0d3 = 0x41fbbcdc
-0x0d4 = 0x5a7ef9db, 0x0d5 = 0x00100000, 0x0dc = 0x00000001 (???)
-Temporary Values
-0x0d6 : Accumulator (???)
-0x0d7 : Condition Register
-0x0d8 : Noise source
-0x0d9 : Noise source
-Tank Memory Data Registers
-0x200 - 0x2ff
-Tank Memory Address Registers
-0x300 - 0x3ff
-General Purpose Registers
-0x400 - 0x5ff
-*/
-
-/* AC97Output[l/r] = FXBus PCM[l/r] */
-audigy_addefxop(sc, iACC3, A_EXTOUT(A_EXTOUT_AC97_L), A_C_00000000,
-A_C_00000000, A_FXBUS(FXBUS_PCM_LEFT), &pc);
-audigy_addefxop(sc, iACC3, A_EXTOUT(A_EXTOUT_AC97_R), A_C_00000000,
-A_C_00000000, A_FXBUS(FXBUS_PCM_RIGHT), &pc);
-
-/* GPR[0/1] = RCA S/PDIF[l/r] -- Master volume */
-audigy_addefxop(sc, iACC3, A_GPR(0), A_C_00000000,
-A_C_00000000, A_EXTIN(EXTIN_COAX_SPDIF_L), &pc);
-audigy_addefxop(sc, iACC3, A_GPR(1), A_C_00000000,
-A_C_00000000, A_EXTIN(EXTIN_COAX_SPDIF_R), &pc);
-
-/* GPR[2] = GPR[0] (Left) / 2 + GPR[1] (Right) / 2 -- Central volume */
-audigy_addefxop(sc, iINTERP, A_GPR(2), A_GPR(1),
-A_C_40000000, A_GPR(0), &pc);
-
-/* Headphones[l/r] = GPR[0/1] */
-audigy_addefxop(sc, iACC3, A_EXTOUT(A_EXTOUT_HEADPHONE_L),
-A_C_00000000, A_C_00000000, A_GPR(0), &pc);
-audigy_addefxop(sc, iACC3, A_EXTOUT(A_EXTOUT_HEADPHONE_R),
-A_C_00000000, A_C_00000000, A_GPR(1), &pc);
-
-/* Analog Front[l/r] = GPR[0/1] */
-audigy_addefxop(sc, iACC3, A_EXTOUT(A_EXTOUT_AFRONT_L), A_C_00000000,
-A_C_00000000, A_GPR(0), &pc);
-audigy_addefxop(sc, iACC3, A_EXTOUT(A_EXTOUT_AFRONT_R), A_C_00000000,
-A_C_00000000, A_GPR(1), &pc);
-
-/* Digital Front[l/r] = GPR[0/1] */
-audigy_addefxop(sc, iACC3, A_EXTOUT(A_EXTOUT_FRONT_L), A_C_00000000,
-A_C_00000000, A_GPR(0), &pc);
-audigy_addefxop(sc, iACC3, A_EXTOUT(A_EXTOUT_FRONT_R), A_C_00000000,
-A_C_00000000, A_GPR(1), &pc);
-
-/* Center and Subwoofer configuration */
-/* Analog Center = GPR[0] + GPR[2] */
-audigy_addefxop(sc, iACC3, A_EXTOUT(A_EXTOUT_ACENTER), A_C_00000000,
-A_GPR(0), A_GPR(2), &pc);
-/* Analog Sub = GPR[1] + GPR[2] */
-audigy_addefxop(sc, iACC3, A_EXTOUT(A_EXTOUT_ALFE), A_C_00000000,
-A_GPR(1), A_GPR(2), &pc);
-
-/* Digital Center = GPR[0] + GPR[2] */
-audigy_addefxop(sc, iACC3, A_EXTOUT(A_EXTOUT_CENTER), A_C_00000000,
-A_GPR(0), A_GPR(2), &pc);
-/* Digital Sub = GPR[1] + GPR[2] */
-audigy_addefxop(sc, iACC3, A_EXTOUT(A_EXTOUT_LFE), A_C_00000000,
-A_GPR(1), A_GPR(2), &pc);
+ /* skip 0, 0, -1, 0 - NOPs */
+ for (i = 0; i < 512; i++)
+ audigy_addefxop(sc, 0x0f, 0x0c0, 0x0c0, 0x0cf, 0x0c0, &pc);
+
+ for (i = 0; i < 512; i++)
+ emu_wrptr(sc, 0, A_FXGPREGBASE + i, 0x0);
+
+ pc = 16;
+
+ /* stop fx processor */
+ emu_wrptr(sc, 0, A_DBG, A_DBG_SINGLE_STEP);
+
+ /* Audigy 2 (EMU10K2) DSP Registers:
+ FX Bus
+ 0x000-0x00f : 16 registers (?)
+ Input
+ 0x040/0x041 : AC97 Codec (l/r)
+ 0x042/0x043 : ADC, S/PDIF (l/r)
+ 0x044/0x045 : Optical S/PDIF in (l/r)
+ 0x046/0x047 : ?
+ 0x048/0x049 : Line/Mic 2 (l/r)
+ 0x04a/0x04b : RCA S/PDIF (l/r)
+ 0x04c/0x04d : Aux 2 (l/r)
+ Output
+ 0x060/0x061 : Digital Front (l/r)
+ 0x062/0x063 : Digital Center/LFE
+ 0x064/0x065 : AudigyDrive Heaphone (l/r)
+ 0x066/0x067 : Digital Rear (l/r)
+ 0x068/0x069 : Analog Front (l/r)
+ 0x06a/0x06b : Analog Center/LFE
+ 0x06c/0x06d : ?
+ 0x06e/0x06f : Analog Rear (l/r)
+ 0x070/0x071 : AC97 Output (l/r)
+ 0x072/0x073 : ?
+ 0x074/0x075 : ?
+ 0x076/0x077 : ADC Recording Buffer (l/r)
+ Constants
+ 0x0c0 - 0x0c4 = 0 - 4
+ 0x0c5 = 0x8, 0x0c6 = 0x10, 0x0c7 = 0x20
+ 0x0c8 = 0x100, 0x0c9 = 0x10000, 0x0ca = 0x80000
+ 0x0cb = 0x10000000, 0x0cc = 0x20000000, 0x0cd = 0x40000000
+ 0x0ce = 0x80000000, 0x0cf = 0x7fffffff, 0x0d0 = 0xffffffff
+ 0x0d1 = 0xfffffffe, 0x0d2 = 0xc0000000, 0x0d3 = 0x41fbbcdc
+ 0x0d4 = 0x5a7ef9db, 0x0d5 = 0x00100000, 0x0dc = 0x00000001 (?)
+ Temporary Values
+ 0x0d6 : Accumulator (?)
+ 0x0d7 : Condition Register
+ 0x0d8 : Noise source
+ 0x0d9 : Noise source
+ Tank Memory Data Registers
+ 0x200 - 0x2ff
+ Tank Memory Address Registers
+ 0x300 - 0x3ff
+ General Purpose Registers
+ 0x400 - 0x5ff
+ */
+
+ /* AC97Output[l/r] = FXBus PCM[l/r] */
+ audigy_addefxop(sc, iACC3, A_EXTOUT(A_EXTOUT_AC97_L), A_C_00000000,
+ A_C_00000000, A_FXBUS(FXBUS_PCM_LEFT), &pc);
+ audigy_addefxop(sc, iACC3, A_EXTOUT(A_EXTOUT_AC97_R), A_C_00000000,
+ A_C_00000000, A_FXBUS(FXBUS_PCM_RIGHT), &pc);
+
+ /* GPR[0/1] = RCA S/PDIF[l/r] -- Master volume */
+ audigy_addefxop(sc, iACC3, A_GPR(0), A_C_00000000,
+ A_C_00000000, A_EXTIN(EXTIN_COAX_SPDIF_L), &pc);
+ audigy_addefxop(sc, iACC3, A_GPR(1), A_C_00000000,
+ A_C_00000000, A_EXTIN(EXTIN_COAX_SPDIF_R), &pc);
+
+ /* GPR[2] = GPR[0] (Left) / 2 + GPR[1] (Right) / 2 -- Central volume */
+ audigy_addefxop(sc, iINTERP, A_GPR(2), A_GPR(1),
+ A_C_40000000, A_GPR(0), &pc);
+
+ /* Headphones[l/r] = GPR[0/1] */
+ audigy_addefxop(sc, iACC3, A_EXTOUT(A_EXTOUT_HEADPHONE_L),
+ A_C_00000000, A_C_00000000, A_GPR(0), &pc);
+ audigy_addefxop(sc, iACC3, A_EXTOUT(A_EXTOUT_HEADPHONE_R),
+ A_C_00000000, A_C_00000000, A_GPR(1), &pc);
+
+ /* Analog Front[l/r] = GPR[0/1] */
+ audigy_addefxop(sc, iACC3, A_EXTOUT(A_EXTOUT_AFRONT_L), A_C_00000000,
+ A_C_00000000, A_GPR(0), &pc);
+ audigy_addefxop(sc, iACC3, A_EXTOUT(A_EXTOUT_AFRONT_R), A_C_00000000,
+ A_C_00000000, A_GPR(1), &pc);
+
+ /* Digital Front[l/r] = GPR[0/1] */
+ audigy_addefxop(sc, iACC3, A_EXTOUT(A_EXTOUT_FRONT_L), A_C_00000000,
+ A_C_00000000, A_GPR(0), &pc);
+ audigy_addefxop(sc, iACC3, A_EXTOUT(A_EXTOUT_FRONT_R), A_C_00000000,
+ A_C_00000000, A_GPR(1), &pc);
+
+ /* Center and Subwoofer configuration */
+ /* Analog Center = GPR[0] + GPR[2] */
+ audigy_addefxop(sc, iACC3, A_EXTOUT(A_EXTOUT_ACENTER), A_C_00000000,
+ A_GPR(0), A_GPR(2), &pc);
+ /* Analog Sub = GPR[1] + GPR[2] */
+ audigy_addefxop(sc, iACC3, A_EXTOUT(A_EXTOUT_ALFE), A_C_00000000,
+ A_GPR(1), A_GPR(2), &pc);
+
+ /* Digital Center = GPR[0] + GPR[2] */
+ audigy_addefxop(sc, iACC3, A_EXTOUT(A_EXTOUT_CENTER), A_C_00000000,
+ A_GPR(0), A_GPR(2), &pc);
+ /* Digital Sub = GPR[1] + GPR[2] */
+ audigy_addefxop(sc, iACC3, A_EXTOUT(A_EXTOUT_LFE), A_C_00000000,
+ A_GPR(1), A_GPR(2), &pc);
#if 0
-/* Analog Rear[l/r] = (GPR[0/1] * RearVolume[l/r]) >> 31 */
-/* RearVolume = GPR[0x10/0x11] (Will this ever be implemented?) */
-audigy_addefxop(sc, iMAC0, A_EXTOUT(A_EXTOUT_AREAR_L), A_C_00000000,
-A_GPR(16), A_GPR(0), &pc);
-audigy_addefxop(sc, iMAC0, A_EXTOUT(A_EXTOUT_AREAR_R), A_C_00000000,
-A_GPR(17), A_GPR(1), &pc);
-
-/* Digital Rear[l/r] = (GPR[0/1] * RearVolume[l/r]) >> 31 */
-/* RearVolume = GPR[0x10/0x11] (Will this ever be implemented?) */
-audigy_addefxop(sc, iMAC0, A_EXTOUT(A_EXTOUT_REAR_L), A_C_00000000,
-A_GPR(16), A_GPR(0), &pc);
-audigy_addefxop(sc, iMAC0, A_EXTOUT(A_EXTOUT_REAR_R), A_C_00000000,
-A_GPR(17), A_GPR(1), &pc);
+ /* Analog Rear[l/r] = (GPR[0/1] * RearVolume[l/r]) >> 31 */
+ /* RearVolume = GPR[0x10/0x11] (Will this ever be implemented?) */
+ audigy_addefxop(sc, iMAC0, A_EXTOUT(A_EXTOUT_AREAR_L), A_C_00000000,
+ A_GPR(16), A_GPR(0), &pc);
+ audigy_addefxop(sc, iMAC0, A_EXTOUT(A_EXTOUT_AREAR_R), A_C_00000000,
+ A_GPR(17), A_GPR(1), &pc);
+
+ /* Digital Rear[l/r] = (GPR[0/1] * RearVolume[l/r]) >> 31 */
+ /* RearVolume = GPR[0x10/0x11] (Will this ever be implemented?) */
+ audigy_addefxop(sc, iMAC0, A_EXTOUT(A_EXTOUT_REAR_L), A_C_00000000,
+ A_GPR(16), A_GPR(0), &pc);
+ audigy_addefxop(sc, iMAC0, A_EXTOUT(A_EXTOUT_REAR_R), A_C_00000000,
+ A_GPR(17), A_GPR(1), &pc);
#else
-/* XXX This is just a copy to the channel, since we do not have
-* a patch manager, it is useful for have another output enabled.
-*/
-
-/* Analog Rear[l/r] = GPR[0/1] */
-audigy_addefxop(sc, iACC3, A_EXTOUT(A_EXTOUT_AREAR_L), A_C_00000000,
-A_C_00000000, A_GPR(0), &pc);
-audigy_addefxop(sc, iACC3, A_EXTOUT(A_EXTOUT_AREAR_R), A_C_00000000,
-A_C_00000000, A_GPR(1), &pc);
-
-/* Digital Rear[l/r] = GPR[0/1] */
-audigy_addefxop(sc, iACC3, A_EXTOUT(A_EXTOUT_REAR_L), A_C_00000000,
-A_C_00000000, A_GPR(0), &pc);
-audigy_addefxop(sc, iACC3, A_EXTOUT(A_EXTOUT_REAR_R), A_C_00000000,
-A_C_00000000, A_GPR(1), &pc);
+ /* XXX This is just a copy to the channel, since we do not have
+ * a patch manager, it is useful for have another output enabled.
+ */
+
+ /* Analog Rear[l/r] = GPR[0/1] */
+ audigy_addefxop(sc, iACC3, A_EXTOUT(A_EXTOUT_AREAR_L), A_C_00000000,
+ A_C_00000000, A_GPR(0), &pc);
+ audigy_addefxop(sc, iACC3, A_EXTOUT(A_EXTOUT_AREAR_R), A_C_00000000,
+ A_C_00000000, A_GPR(1), &pc);
+
+ /* Digital Rear[l/r] = GPR[0/1] */
+ audigy_addefxop(sc, iACC3, A_EXTOUT(A_EXTOUT_REAR_L), A_C_00000000,
+ A_C_00000000, A_GPR(0), &pc);
+ audigy_addefxop(sc, iACC3, A_EXTOUT(A_EXTOUT_REAR_R), A_C_00000000,
+ A_C_00000000, A_GPR(1), &pc);
#endif
-/* ADC Recording buffer[l/r] = AC97Input[l/r] */
-audigy_addefxop(sc, iACC3, A_EXTOUT(A_EXTOUT_ADC_CAP_L), A_C_00000000,
-A_C_00000000, A_EXTIN(A_EXTIN_AC97_L), &pc);
-audigy_addefxop(sc, iACC3, A_EXTOUT(A_EXTOUT_ADC_CAP_R), A_C_00000000,
-A_C_00000000, A_EXTIN(A_EXTIN_AC97_R), &pc);
+ /* ADC Recording buffer[l/r] = AC97Input[l/r] */
+ audigy_addefxop(sc, iACC3, A_EXTOUT(A_EXTOUT_ADC_CAP_L), A_C_00000000,
+ A_C_00000000, A_EXTIN(A_EXTIN_AC97_L), &pc);
+ audigy_addefxop(sc, iACC3, A_EXTOUT(A_EXTOUT_ADC_CAP_R), A_C_00000000,
+ A_C_00000000, A_EXTIN(A_EXTIN_AC97_R), &pc);
-/* resume normal operations */
-emu_wrptr(sc, 0, A_DBG, 0);
+ /* resume normal operations */
+ emu_wrptr(sc, 0, A_DBG, 0);
}
static void
emu_initefx(struct sc_info *sc)
{
-int i;
-u_int32_t pc = 16;
+ int i;
+ u_int32_t pc = 16;
-/* acc3 0,0,0,0 - NOPs */
-for (i = 0; i < 512; i++) {
-emu_wrefx(sc, i * 2, 0x10040);
-emu_wrefx(sc, i * 2 + 1, 0x610040);
-}
-
-for (i = 0; i < 256; i++)
-emu_wrptr(sc, 0, FXGPREGBASE + i, 0);
-
-/* FX-8010 DSP Registers:
-FX Bus
-0x000-0x00f : 16 registers
-Input
-0x010/0x011 : AC97 Codec (l/r)
-0x012/0x013 : ADC, S/PDIF (l/r)
-0x014/0x015 : Mic(left), Zoom (l/r)
-0x016/0x017 : TOS link in (l/r)
-0x018/0x019 : Line/Mic 1 (l/r)
-0x01a/0x01b : COAX S/PDIF (l/r)
-0x01c/0x01d : Line/Mic 2 (l/r)
-Output
-0x020/0x021 : AC97 Output (l/r)
-0x022/0x023 : TOS link out (l/r)
-0x024/0x025 : Center/LFE
-0x026/0x027 : LiveDrive Headphone (l/r)
-0x028/0x029 : Rear Channel (l/r)
-0x02a/0x02b : ADC Recording Buffer (l/r)
-0x02c : Mic Recording Buffer
-0x031/0x032 : Analog Center/LFE
-Constants
-0x040 - 0x044 = 0 - 4
-0x045 = 0x8, 0x046 = 0x10, 0x047 = 0x20
-0x048 = 0x100, 0x049 = 0x10000, 0x04a = 0x80000
-0x04b = 0x10000000, 0x04c = 0x20000000, 0x04d = 0x40000000
-0x04e = 0x80000000, 0x04f = 0x7fffffff, 0x050 = 0xffffffff
-0x051 = 0xfffffffe, 0x052 = 0xc0000000, 0x053 = 0x41fbbcdc
-0x054 = 0x5a7ef9db, 0x055 = 0x00100000
-Temporary Values
-0x056 : Accumulator
-0x057 : Condition Register
-0x058 : Noise source
-0x059 : Noise source
-0x05a : IRQ Register
-0x05b : TRAM Delay Base Address Count
-General Purpose Registers
-0x100 - 0x1ff
-Tank Memory Data Registers
-0x200 - 0x2ff
-Tank Memory Address Registers
-0x300 - 0x3ff
-*/
-
-/* Routing - this will be configurable in later version */
-
-/* GPR[0/1] = FX * 4 + SPDIF-in */
-emu_addefxop(sc, iMACINT0, GPR(0), EXTIN(EXTIN_SPDIF_CD_L),
-FXBUS(FXBUS_PCM_LEFT), C_00000004, &pc);
-emu_addefxop(sc, iMACINT0, GPR(1), EXTIN(EXTIN_SPDIF_CD_R),
-FXBUS(FXBUS_PCM_RIGHT), C_00000004, &pc);
-
-/* GPR[0/1] += APS-input */
-emu_addefxop(sc, iACC3, GPR(0), GPR(0), C_00000000,
-sc->APS ? EXTIN(EXTIN_TOSLINK_L) : C_00000000, &pc);
-emu_addefxop(sc, iACC3, GPR(1), GPR(1), C_00000000,
-sc->APS ? EXTIN(EXTIN_TOSLINK_R) : C_00000000, &pc);
-
-/* FrontOut (AC97) = GPR[0/1] */
-emu_addefxop(sc, iACC3, EXTOUT(EXTOUT_AC97_L), C_00000000,
-C_00000000, GPR(0), &pc);
-emu_addefxop(sc, iACC3, EXTOUT(EXTOUT_AC97_R), C_00000000,
-C_00000001, GPR(1), &pc);
+ /* acc3 0,0,0,0 - NOPs */
+ for (i = 0; i < 512; i++) {
+ emu_wrefx(sc, i * 2, 0x10040);
+ emu_wrefx(sc, i * 2 + 1, 0x610040);
+ }
+
+ for (i = 0; i < 256; i++)
+ emu_wrptr(sc, 0, FXGPREGBASE + i, 0);
+
+ /* FX-8010 DSP Registers:
+ FX Bus
+ 0x000-0x00f : 16 registers
+ Input
+ 0x010/0x011 : AC97 Codec (l/r)
+ 0x012/0x013 : ADC, S/PDIF (l/r)
+ 0x014/0x015 : Mic(left), Zoom (l/r)
+ 0x016/0x017 : TOS link in (l/r)
+ 0x018/0x019 : Line/Mic 1 (l/r)
+ 0x01a/0x01b : COAX S/PDIF (l/r)
+ 0x01c/0x01d : Line/Mic 2 (l/r)
+ Output
+ 0x020/0x021 : AC97 Output (l/r)
+ 0x022/0x023 : TOS link out (l/r)
+ 0x024/0x025 : Center/LFE
+ 0x026/0x027 : LiveDrive Headphone (l/r)
+ 0x028/0x029 : Rear Channel (l/r)
+ 0x02a/0x02b : ADC Recording Buffer (l/r)
+ 0x02c : Mic Recording Buffer
+ 0x031/0x032 : Analog Center/LFE
+ Constants
+ 0x040 - 0x044 = 0 - 4
+ 0x045 = 0x8, 0x046 = 0x10, 0x047 = 0x20
+ 0x048 = 0x100, 0x049 = 0x10000, 0x04a = 0x80000
+ 0x04b = 0x10000000, 0x04c = 0x20000000, 0x04d = 0x40000000
+ 0x04e = 0x80000000, 0x04f = 0x7fffffff, 0x050 = 0xffffffff
+ 0x051 = 0xfffffffe, 0x052 = 0xc0000000, 0x053 = 0x41fbbcdc
+ 0x054 = 0x5a7ef9db, 0x055 = 0x00100000
+ Temporary Values
+ 0x056 : Accumulator
+ 0x057 : Condition Register
+ 0x058 : Noise source
+ 0x059 : Noise source
+ 0x05a : IRQ Register
+ 0x05b : TRAM Delay Base Address Count
+ General Purpose Registers
+ 0x100 - 0x1ff
+ Tank Memory Data Registers
+ 0x200 - 0x2ff
+ Tank Memory Address Registers
+ 0x300 - 0x3ff
+ */
+
+ /* Routing - this will be configurable in later version */
+
+ /* GPR[0/1] = FX * 4 + SPDIF-in */
+ emu_addefxop(sc, iMACINT0, GPR(0), EXTIN(EXTIN_SPDIF_CD_L),
+ FXBUS(FXBUS_PCM_LEFT), C_00000004, &pc);
+ emu_addefxop(sc, iMACINT0, GPR(1), EXTIN(EXTIN_SPDIF_CD_R),
+ FXBUS(FXBUS_PCM_RIGHT), C_00000004, &pc);
+
+ /* GPR[0/1] += APS-input */
+ emu_addefxop(sc, iACC3, GPR(0), GPR(0), C_00000000,
+ sc->APS ? EXTIN(EXTIN_TOSLINK_L) : C_00000000, &pc);
+ emu_addefxop(sc, iACC3, GPR(1), GPR(1), C_00000000,
+ sc->APS ? EXTIN(EXTIN_TOSLINK_R) : C_00000000, &pc);
+
+ /* FrontOut (AC97) = GPR[0/1] */
+ emu_addefxop(sc, iACC3, EXTOUT(EXTOUT_AC97_L), C_00000000,
+ C_00000000, GPR(0), &pc);
+ emu_addefxop(sc, iACC3, EXTOUT(EXTOUT_AC97_R), C_00000000,
+ C_00000001, GPR(1), &pc);
-/* GPR[2] = GPR[0] (Left) / 2 + GPR[1] (Right) / 2 -- Central volume */
-emu_addefxop(sc, iINTERP, GPR(2), GPR(1), C_40000000, GPR(0), &pc);
+ /* GPR[2] = GPR[0] (Left) / 2 + GPR[1] (Right) / 2 -- Central volume */
+ emu_addefxop(sc, iINTERP, GPR(2), GPR(1), C_40000000, GPR(0), &pc);
#if 0
-/* RearOut = (GPR[0/1] * RearVolume) >> 31 */
-/* RearVolume = GPR[0x10/0x11] */
-emu_addefxop(sc, iMAC0, EXTOUT(EXTOUT_REAR_L), C_00000000,
-GPR(16), GPR(0), &pc);
-emu_addefxop(sc, iMAC0, EXTOUT(EXTOUT_REAR_R), C_00000000,
-GPR(17), GPR(1), &pc);
+ /* RearOut = (GPR[0/1] * RearVolume) >> 31 */
+ /* RearVolume = GPR[0x10/0x11] */
+ emu_addefxop(sc, iMAC0, EXTOUT(EXTOUT_REAR_L), C_00000000,
+ GPR(16), GPR(0), &pc);
+ emu_addefxop(sc, iMAC0, EXTOUT(EXTOUT_REAR_R), C_00000000,
+ GPR(17), GPR(1), &pc);
#else
-/* XXX This is just a copy to the channel, since we do not have
-* a patch manager, it is useful for have another output enabled.
-*/
-
-/* Rear[l/r] = GPR[0/1] */
-emu_addefxop(sc, iACC3, EXTOUT(EXTOUT_REAR_L), C_00000000,
-C_00000000, GPR(0), &pc);
-emu_addefxop(sc, iACC3, EXTOUT(EXTOUT_REAR_R), C_00000000,
-C_00000000, GPR(1), &pc);
+ /* XXX This is just a copy to the channel, since we do not have
+ * a patch manager, it is useful for have another output enabled.
+ */
+
+ /* Rear[l/r] = GPR[0/1] */
+ emu_addefxop(sc, iACC3, EXTOUT(EXTOUT_REAR_L), C_00000000,
+ C_00000000, GPR(0), &pc);
+ emu_addefxop(sc, iACC3, EXTOUT(EXTOUT_REAR_R), C_00000000,
+ C_00000000, GPR(1), &pc);
#endif
-/* TOS out[l/r] = GPR[0/1] */
-emu_addefxop(sc, iACC3, EXTOUT(EXTOUT_TOSLINK_L), C_00000000,
-C_00000000, GPR(0), &pc);
-emu_addefxop(sc, iACC3, EXTOUT(EXTOUT_TOSLINK_R), C_00000000,
-C_00000000, GPR(1), &pc);
-
-/* Center and Subwoofer configuration */
-/* Analog Center = GPR[0] + GPR[2] */
-emu_addefxop(sc, iACC3, EXTOUT(EXTOUT_ACENTER), C_00000000,
-GPR(0), GPR(2), &pc);
-/* Analog Sub = GPR[1] + GPR[2] */
-emu_addefxop(sc, iACC3, EXTOUT(EXTOUT_ALFE), C_00000000,
-GPR(1), GPR(2), &pc);
-/* Digital Center = GPR[0] + GPR[2] */
-emu_addefxop(sc, iACC3, EXTOUT(EXTOUT_CENTER), C_00000000,
-GPR(0), GPR(2), &pc);
-/* Digital Sub = GPR[1] + GPR[2] */
-emu_addefxop(sc, iACC3, EXTOUT(EXTOUT_LFE), C_00000000,
-GPR(1), GPR(2), &pc);
-
-/* Headphones[l/r] = GPR[0/1] */
-emu_addefxop(sc, iACC3, EXTOUT(EXTOUT_HEADPHONE_L), C_00000000,
-C_00000000, GPR(0), &pc);
-emu_addefxop(sc, iACC3, EXTOUT(EXTOUT_HEADPHONE_R), C_00000000,
-C_00000000, GPR(1), &pc);
-
-/* ADC Recording buffer[l/r] = AC97Input[l/r] */
-emu_addefxop(sc, iACC3, EXTOUT(EXTOUT_ADC_CAP_L), C_00000000,
-C_00000000, EXTIN(EXTIN_AC97_L), &pc);
-emu_addefxop(sc, iACC3, EXTOUT(EXTOUT_ADC_CAP_R), C_00000000,
-C_00000000, EXTIN(EXTIN_AC97_R), &pc);
+ /* TOS out[l/r] = GPR[0/1] */
+ emu_addefxop(sc, iACC3, EXTOUT(EXTOUT_TOSLINK_L), C_00000000,
+ C_00000000, GPR(0), &pc);
+ emu_addefxop(sc, iACC3, EXTOUT(EXTOUT_TOSLINK_R), C_00000000,
+ C_00000000, GPR(1), &pc);
+
+ /* Center and Subwoofer configuration */
+ /* Analog Center = GPR[0] + GPR[2] */
+ emu_addefxop(sc, iACC3, EXTOUT(EXTOUT_ACENTER), C_00000000,
+ GPR(0), GPR(2), &pc);
+ /* Analog Sub = GPR[1] + GPR[2] */
+ emu_addefxop(sc, iACC3, EXTOUT(EXTOUT_ALFE), C_00000000,
+ GPR(1), GPR(2), &pc);
+ /* Digital Center = GPR[0] + GPR[2] */
+ emu_addefxop(sc, iACC3, EXTOUT(EXTOUT_AC97_CENTER), C_00000000,
+ GPR(0), GPR(2), &pc);
+ /* Digital Sub = GPR[1] + GPR[2] */
+ emu_addefxop(sc, iACC3, EXTOUT(EXTOUT_AC97_LFE), C_00000000,
+ GPR(1), GPR(2), &pc);
+
+ /* Headphones[l/r] = GPR[0/1] */
+ emu_addefxop(sc, iACC3, EXTOUT(EXTOUT_HEADPHONE_L), C_00000000,
+ C_00000000, GPR(0), &pc);
+ emu_addefxop(sc, iACC3, EXTOUT(EXTOUT_HEADPHONE_R), C_00000000,
+ C_00000000, GPR(1), &pc);
+
+ /* ADC Recording buffer[l/r] = AC97Input[l/r] */
+ emu_addefxop(sc, iACC3, EXTOUT(EXTOUT_ADC_CAP_L), C_00000000,
+ C_00000000, EXTIN(EXTIN_AC97_L), &pc);
+ emu_addefxop(sc, iACC3, EXTOUT(EXTOUT_ADC_CAP_R), C_00000000,
+ C_00000000, EXTIN(EXTIN_AC97_R), &pc);
-/* resume normal operations */
-emu_wrptr(sc, 0, DBG, 0);
+ /* resume normal operations */
+ emu_wrptr(sc, 0, DBG, 0);
}
/* Probe and attach the card */
static int
emu_init(struct sc_info *sc)
{
-u_int32_t spcs, ch, tmp, i;
+ u_int32_t spcs, ch, tmp, i;
-if (sc->audigy) {
-/* enable additional AC97 slots */
-emu_wrptr(sc, 0, AC97SLOT, AC97SLOT_CNTR | AC97SLOT_LFE);
-}
-
-/* disable audio and lock cache */
-emu_wr(sc, HCFG,
-HCFG_LOCKSOUNDCACHE | HCFG_LOCKTANKCACHE_MASK | HCFG_MUTEBUTTONENABLE,
-4);
-
-/* reset recording buffers */
-emu_wrptr(sc, 0, MICBS, ADCBS_BUFSIZE_NONE);
-emu_wrptr(sc, 0, MICBA, 0);
-emu_wrptr(sc, 0, FXBS, ADCBS_BUFSIZE_NONE);
-emu_wrptr(sc, 0, FXBA, 0);
-emu_wrptr(sc, 0, ADCBS, ADCBS_BUFSIZE_NONE);
-emu_wrptr(sc, 0, ADCBA, 0);
-
-/* disable channel interrupt */
-emu_wr(sc, INTE,
-INTE_INTERVALTIMERENB | INTE_SAMPLERATETRACKER | INTE_PCIERRORENABLE,
-4);
-emu_wrptr(sc, 0, CLIEL, 0);
-emu_wrptr(sc, 0, CLIEH, 0);
-emu_wrptr(sc, 0, SOLEL, 0);
-emu_wrptr(sc, 0, SOLEH, 0);
-
-/* wonder what these do... */
-if (sc->audigy) {
-emu_wrptr(sc, 0, SPBYPASS, 0xf00);
-emu_wrptr(sc, 0, AC97SLOT, 0x3);
-}
-
-/* init envelope engine */
-for (ch = 0; ch < NUM_G; ch++) {
-emu_wrptr(sc, ch, DCYSUSV, ENV_OFF);
-emu_wrptr(sc, ch, IP, 0);
-emu_wrptr(sc, ch, VTFT, 0xffff);
-emu_wrptr(sc, ch, CVCF, 0xffff);
-emu_wrptr(sc, ch, PTRX, 0);
-emu_wrptr(sc, ch, CPF, 0);
-emu_wrptr(sc, ch, CCR, 0);
-
-emu_wrptr(sc, ch, PSST, 0);
-emu_wrptr(sc, ch, DSL, 0x10);
-emu_wrptr(sc, ch, CCCA, 0);
-emu_wrptr(sc, ch, Z1, 0);
-emu_wrptr(sc, ch, Z2, 0);
-emu_wrptr(sc, ch, FXRT, 0xd01c0000);
-
-emu_wrptr(sc, ch, ATKHLDM, 0);
-emu_wrptr(sc, ch, DCYSUSM, 0);
-emu_wrptr(sc, ch, IFATN, 0xffff);
-emu_wrptr(sc, ch, PEFE, 0);
-emu_wrptr(sc, ch, FMMOD, 0);
-emu_wrptr(sc, ch, TREMFRQ, 24); /* 1 Hz */
-emu_wrptr(sc, ch, FM2FRQ2, 24); /* 1 Hz */
-emu_wrptr(sc, ch, TEMPENV, 0);
-
-/*** these are last so OFF prevents writing ***/
-emu_wrptr(sc, ch, LFOVAL2, 0);
-emu_wrptr(sc, ch, LFOVAL1, 0);
-emu_wrptr(sc, ch, ATKHLDV, 0);
-emu_wrptr(sc, ch, ENVVOL, 0);
-emu_wrptr(sc, ch, ENVVAL, 0);
-
-if (sc->audigy) {
-/* audigy cards need this to initialize correctly */
-emu_wrptr(sc, ch, 0x4c, 0);
-emu_wrptr(sc, ch, 0x4d, 0);
-emu_wrptr(sc, ch, 0x4e, 0);
-emu_wrptr(sc, ch, 0x4f, 0);
-/* set default routing */
-emu_wrptr(sc, ch, A_FXRT1, 0x03020100);
-emu_wrptr(sc, ch, A_FXRT2, 0x3f3f3f3f);
-emu_wrptr(sc, ch, A_SENDAMOUNTS, 0);
-}
-
-sc->voice[ch].vnum = ch;
-sc->voice[ch].slave = NULL;
-sc->voice[ch].busy = 0;
-sc->voice[ch].ismaster = 0;
-sc->voice[ch].running = 0;
-sc->voice[ch].b16 = 0;
-sc->voice[ch].stereo = 0;
-sc->voice[ch].speed = 0;
-sc->voice[ch].start = 0;
-sc->voice[ch].end = 0;
-sc->voice[ch].channel = NULL;
-}
-sc->pnum = sc->rnum = 0;
+ if (sc->audigy) {
+ /* enable additional AC97 slots */
+ emu_wrptr(sc, 0, AC97SLOT, AC97SLOT_CNTR | AC97SLOT_LFE);
+ }
+
+ /* disable audio and lock cache */
+ emu_wr(sc, HCFG,
+ HCFG_LOCKSOUNDCACHE | HCFG_LOCKTANKCACHE_MASK | HCFG_MUTEBUTTONENABLE,
+ 4);
+
+ /* reset recording buffers */
+ emu_wrptr(sc, 0, MICBS, ADCBS_BUFSIZE_NONE);
+ emu_wrptr(sc, 0, MICBA, 0);
+ emu_wrptr(sc, 0, FXBS, ADCBS_BUFSIZE_NONE);
+ emu_wrptr(sc, 0, FXBA, 0);
+ emu_wrptr(sc, 0, ADCBS, ADCBS_BUFSIZE_NONE);
+ emu_wrptr(sc, 0, ADCBA, 0);
+
+ /* disable channel interrupt */
+ emu_wr(sc, INTE,
+ INTE_INTERVALTIMERENB | INTE_SAMPLERATETRACKER | INTE_PCIERRORENABLE,
+ 4);
+ emu_wrptr(sc, 0, CLIEL, 0);
+ emu_wrptr(sc, 0, CLIEH, 0);
+ emu_wrptr(sc, 0, SOLEL, 0);
+ emu_wrptr(sc, 0, SOLEH, 0);
+
+ /* wonder what these do... */
+ if (sc->audigy) {
+ emu_wrptr(sc, 0, SPBYPASS, 0xf00);
+ emu_wrptr(sc, 0, AC97SLOT, 0x3);
+ }
+
+ /* init envelope engine */
+ for (ch = 0; ch < NUM_G; ch++) {
+ emu_wrptr(sc, ch, DCYSUSV, ENV_OFF);
+ emu_wrptr(sc, ch, IP, 0);
+ emu_wrptr(sc, ch, VTFT, 0xffff);
+ emu_wrptr(sc, ch, CVCF, 0xffff);
+ emu_wrptr(sc, ch, PTRX, 0);
+ emu_wrptr(sc, ch, CPF, 0);
+ emu_wrptr(sc, ch, CCR, 0);
+
+ emu_wrptr(sc, ch, PSST, 0);
+ emu_wrptr(sc, ch, DSL, 0x10);
+ emu_wrptr(sc, ch, CCCA, 0);
+ emu_wrptr(sc, ch, Z1, 0);
+ emu_wrptr(sc, ch, Z2, 0);
+ emu_wrptr(sc, ch, FXRT, 0xd01c0000);
+
+ emu_wrptr(sc, ch, ATKHLDM, 0);
+ emu_wrptr(sc, ch, DCYSUSM, 0);
+ emu_wrptr(sc, ch, IFATN, 0xffff);
+ emu_wrptr(sc, ch, PEFE, 0);
+ emu_wrptr(sc, ch, FMMOD, 0);
+ emu_wrptr(sc, ch, TREMFRQ, 24); /* 1 Hz */
+ emu_wrptr(sc, ch, FM2FRQ2, 24); /* 1 Hz */
+ emu_wrptr(sc, ch, TEMPENV, 0);
+
+ /*** these are last so OFF prevents writing ***/
+ emu_wrptr(sc, ch, LFOVAL2, 0);
+ emu_wrptr(sc, ch, LFOVAL1, 0);
+ emu_wrptr(sc, ch, ATKHLDV, 0);
+ emu_wrptr(sc, ch, ENVVOL, 0);
+ emu_wrptr(sc, ch, ENVVAL, 0);
+
+ if (sc->audigy) {
+ /* audigy cards need this to initialize correctly */
+ emu_wrptr(sc, ch, 0x4c, 0);
+ emu_wrptr(sc, ch, 0x4d, 0);
+ emu_wrptr(sc, ch, 0x4e, 0);
+ emu_wrptr(sc, ch, 0x4f, 0);
+ /* set default routing */
+ emu_wrptr(sc, ch, A_FXRT1, 0x03020100);
+ emu_wrptr(sc, ch, A_FXRT2, 0x3f3f3f3f);
+ emu_wrptr(sc, ch, A_SENDAMOUNTS, 0);
+ }
+
+ sc->voice[ch].vnum = ch;
+ sc->voice[ch].slave = NULL;
+ sc->voice[ch].busy = 0;
+ sc->voice[ch].ismaster = 0;
+ sc->voice[ch].running = 0;
+ sc->voice[ch].b16 = 0;
+ sc->voice[ch].stereo = 0;
+ sc->voice[ch].speed = 0;
+ sc->voice[ch].start = 0;
+ sc->voice[ch].end = 0;
+ sc->voice[ch].channel = NULL;
+ }
+ sc->pnum = sc->rnum = 0;
+
+ /*
+ * Init to 0x02109204 :
+ * Clock accuracy = 0 (1000ppm)
+ * Sample Rate = 2 (48kHz)
+ * Audio Channel = 1 (Left of 2)
+ * Source Number = 0 (Unspecified)
+ * Generation Status = 1 (Original for Cat Code 12)
+ * Cat Code = 12 (Digital Signal Mixer)
+ * Mode = 0 (Mode 0)
+ * Emphasis = 0 (None)
+ * CP = 1 (Copyright unasserted)
+ * AN = 0 (Audio data)
+ * P = 0 (Consumer)
+ */
+ spcs = SPCS_CLKACCY_1000PPM | SPCS_SAMPLERATE_48 |
+ SPCS_CHANNELNUM_LEFT | SPCS_SOURCENUM_UNSPEC |
+ SPCS_GENERATIONSTATUS | 0x00001200 | 0x00000000 |
+ SPCS_EMPHASIS_NONE | SPCS_COPYRIGHT;
+ emu_wrptr(sc, 0, SPCS0, spcs);
+ emu_wrptr(sc, 0, SPCS1, spcs);
+ emu_wrptr(sc, 0, SPCS2, spcs);
+
+ if (!sc->audigy)
+ emu_initefx(sc);
+ else if (sc->audigy2) { /* Audigy 2 */
+ /* from ALSA initialization code: */
+
+ /* Hack for Alice3 to work independent of haP16V driver */
+ u_int32_t tmp;
+
+ /* Setup SRCMulti_I2S SamplingRate */
+ tmp = emu_rdptr(sc, 0, A_SPDIF_SAMPLERATE) & 0xfffff1ff;
+ emu_wrptr(sc, 0, A_SPDIF_SAMPLERATE, tmp | 0x400);
+
+ /* Setup SRCSel (Enable SPDIF, I2S SRCMulti) */
+ emu_wr(sc, 0x20, 0x00600000, 4);
+ emu_wr(sc, 0x24, 0x00000014, 4);
+
+ /* Setup SRCMulti Input Audio Enable */
+ emu_wr(sc, 0x20, 0x006e0000, 4);
+ emu_wr(sc, 0x24, 0xff00ff00, 4);
+ }
+
+ SLIST_INIT(&sc->mem.blocks);
+ sc->mem.ptb_pages = emu_malloc(sc, EMUMAXPAGES * sizeof(u_int32_t),
+ &sc->mem.ptb_pages_addr);
+ if (sc->mem.ptb_pages == NULL)
+ return -1;
+
+ sc->mem.silent_page = emu_malloc(sc, EMUPAGESIZE,
+ &sc->mem.silent_page_addr);
+ if (sc->mem.silent_page == NULL) {
+ emu_free(sc, sc->mem.ptb_pages);
+ return -1;
+ }
+ /* Clear page with silence & setup all pointers to this page */
+ bzero(sc->mem.silent_page, EMUPAGESIZE);
+ tmp = (u_int32_t)(sc->mem.silent_page_addr) << 1;
+ for (i = 0; i < EMUMAXPAGES; i++)
+ sc->mem.ptb_pages[i] = tmp | i;
+
+ emu_wrptr(sc, 0, PTB, (sc->mem.ptb_pages_addr));
+ emu_wrptr(sc, 0, TCB, 0); /* taken from original driver */
+ emu_wrptr(sc, 0, TCBS, 0); /* taken from original driver */
+
+ for (ch = 0; ch < NUM_G; ch++) {
+ emu_wrptr(sc, ch, MAPA, tmp | MAP_PTI_MASK);
+ emu_wrptr(sc, ch, MAPB, tmp | MAP_PTI_MASK);
+ }
+
+ /* emu_memalloc(sc, EMUPAGESIZE); */
+ /*
+ * Hokay, now enable the AUD bit
+ *
+ * Audigy
+ * Enable Audio = 0 (enabled after fx processor initialization)
+ * Mute Disable Audio = 0
+ * Joystick = 1
+ *
+ * Audigy 2
+ * Enable Audio = 1
+ * Mute Disable Audio = 0
+ * Joystick = 1
+ * GP S/PDIF AC3 Enable = 1
+ * CD S/PDIF AC3 Enable = 1
+ *
+ * EMU10K1
+ * Enable Audio = 1
+ * Mute Disable Audio = 0
+ * Lock Tank Memory = 1
+ * Lock Sound Memory = 0
+ * Auto Mute = 1
+ */
+
+ if (sc->audigy) {
+ tmp = HCFG_AUTOMUTE | HCFG_JOYENABLE;
+ if (sc->audigy2) /* Audigy 2 */
+ tmp = HCFG_AUDIOENABLE | HCFG_AC3ENABLE_CDSPDIF |
+ HCFG_AC3ENABLE_GPSPDIF;
+ emu_wr(sc, HCFG, tmp, 4);
+
+ audigy_initefx(sc);
+
+ /* from ALSA initialization code: */
+
+ /* enable audio and disable both audio/digital outputs */
+ emu_wr(sc, HCFG, emu_rd(sc, HCFG, 4) | HCFG_AUDIOENABLE, 4);
+ emu_wr(sc, A_IOCFG, emu_rd(sc, A_IOCFG, 4) & ~A_IOCFG_GPOUT_AD,
+ 4);
+ if (sc->audigy2) { /* Audigy 2 */
+ /* Unmute Analog.
+ * Set GPO6 to 1 for Apollo. This has to be done after
+ * init Alice3 I2SOut beyond 48kHz.
+ * So, sequence is important.
+ */
+ emu_wr(sc, A_IOCFG,
+ emu_rd(sc, A_IOCFG, 4) | A_IOCFG_GPOUT_A, 4);
+ }
+ } else {
+ /* EMU10K1 initialization code */
+ tmp = HCFG_AUDIOENABLE | HCFG_LOCKTANKCACHE_MASK
+ | HCFG_AUTOMUTE;
+ if (sc->rev >= 6)
+ tmp |= HCFG_JOYENABLE;
+
+ emu_wr(sc, HCFG, tmp, 4);
+
+ /* TOSLink detection */
+ sc->tos_link = 0;
+ tmp = emu_rd(sc, HCFG, 4);
+ if (tmp & (HCFG_GPINPUT0 | HCFG_GPINPUT1)) {
+ emu_wr(sc, HCFG, tmp | HCFG_GPOUT1, 4);
+ DELAY(50);
+ if (tmp != (emu_rd(sc, HCFG, 4) & ~HCFG_GPOUT1)) {
+ sc->tos_link = 1;
+ emu_wr(sc, HCFG, tmp, 4);
+ }
+ }
+ }
-/*
-* Init to 0x02109204 :
-* Clock accuracy = 0 (1000ppm)
-* Sample Rate = 2 (48kHz)
-* Audio Channel = 1 (Left of 2)
-* Source Number = 0 (Unspecified)
-* Generation Status = 1 (Original for Cat Code 12)
-* Cat Code = 12 (Digital Signal Mixer)
-* Mode = 0 (Mode 0)
-* Emphasis = 0 (None)
-* CP = 1 (Copyright unasserted)
-* AN = 0 (Audio data)
-* P = 0 (Consumer)
-*/
-spcs = SPCS_CLKACCY_1000PPM | SPCS_SAMPLERATE_48 |
-SPCS_CHANNELNUM_LEFT | SPCS_SOURCENUM_UNSPEC |
-SPCS_GENERATIONSTATUS | 0x00001200 | 0x00000000 |
-SPCS_EMPHASIS_NONE | SPCS_COPYRIGHT;
-emu_wrptr(sc, 0, SPCS0, spcs);
-emu_wrptr(sc, 0, SPCS1, spcs);
-emu_wrptr(sc, 0, SPCS2, spcs);
-
-if (!sc->audigy)
-emu_initefx(sc);
-else if (sc->audigy2) { /* Audigy 2 */
-/* from ALSA initialization code: */
-
-/* Hack for Alice3 to work independent of haP16V driver */
-u_int32_t tmp;
-
-/* Setup SRCMulti_I2S SamplingRate */
-tmp = emu_rdptr(sc, 0, A_SPDIF_SAMPLERATE) & 0xfffff1ff;
-emu_wrptr(sc, 0, A_SPDIF_SAMPLERATE, tmp | 0x400);
-
-/* Setup SRCSel (Enable SPDIF, I2S SRCMulti) */
-emu_wr(sc, 0x20, 0x00600000, 4);
-emu_wr(sc, 0x24, 0x00000014, 4);
-
-/* Setup SRCMulti Input Audio Enable */
-emu_wr(sc, 0x20, 0x006e0000, 4);
-emu_wr(sc, 0x24, 0xff00ff00, 4);
-}
-
-SLIST_INIT(&sc->mem.blocks);
-sc->mem.ptb_pages = emu_malloc(sc, EMUMAXPAGES * sizeof(u_int32_t),
-&sc->mem.ptb_pages_addr);
-if (sc->mem.ptb_pages == NULL)
-return -1;
-
-sc->mem.silent_page = emu_malloc(sc, EMUPAGESIZE,
-&sc->mem.silent_page_addr);
-if (sc->mem.silent_page == NULL) {
-emu_free(sc, sc->mem.ptb_pages);
-return -1;
-}
-/* Clear page with silence & setup all pointers to this page */
-bzero(sc->mem.silent_page, EMUPAGESIZE);
-tmp = (u_int32_t)(sc->mem.silent_page_addr) << 1;
-for (i = 0; i < EMUMAXPAGES; i++)
-sc->mem.ptb_pages[i] = tmp | i;
-
-emu_wrptr(sc, 0, PTB, (sc->mem.ptb_pages_addr));
-emu_wrptr(sc, 0, TCB, 0); /* taken from original driver */
-emu_wrptr(sc, 0, TCBS, 0); /* taken from original driver */
-
-for (ch = 0; ch < NUM_G; ch++) {
-emu_wrptr(sc, ch, MAPA, tmp | MAP_PTI_MASK);
-emu_wrptr(sc, ch, MAPB, tmp | MAP_PTI_MASK);
-}
-
-/* emu_memalloc(sc, EMUPAGESIZE); */
-/*
-* Hokay, now enable the AUD bit
-*
-* Audigy
-* Enable Audio = 0 (enabled after fx processor initialization)
-* Mute Disable Audio = 0
-* Joystick = 1
-*
-* Audigy 2
-* Enable Audio = 1
-* Mute Disable Audio = 0
-* Joystick = 1
-* GP S/PDIF AC3 Enable = 1
-* CD S/PDIF AC3 Enable = 1
-*
-* EMU10K1
-* Enable Audio = 1
-* Mute Disable Audio = 0
-* Lock Tank Memory = 1
-* Lock Sound Memory = 0
-* Auto Mute = 1
-*/
-
-if (sc->audigy) {
-tmp = HCFG_AUTOMUTE | HCFG_JOYENABLE;
-if (sc->audigy2) /* Audigy 2 */
-tmp = HCFG_AUDIOENABLE | HCFG_AC3ENABLE_CDSPDIF |
-HCFG_AC3ENABLE_GPSPDIF;
-emu_wr(sc, HCFG, tmp, 4);
-
-audigy_initefx(sc);
-
-/* from ALSA initialization code: */
-
-/* enable audio and disable both audio/digital outputs */
-emu_wr(sc, HCFG, emu_rd(sc, HCFG, 4) | HCFG_AUDIOENABLE, 4);
-emu_wr(sc, A_IOCFG, emu_rd(sc, A_IOCFG, 4) & ~A_IOCFG_GPOUT_AD,
-4);
-if (sc->audigy2) { /* Audigy 2 */
-/* Unmute Analog.
-* Set GPO6 to 1 for Apollo. This has to be done after
-* init Alice3 I2SOut beyond 48kHz.
-* So, sequence is important.
-*/
-emu_wr(sc, A_IOCFG,
-emu_rd(sc, A_IOCFG, 4) | A_IOCFG_GPOUT_A, 4);
-}
-} else {
-/* EMU10K1 initialization code */
-tmp = HCFG_AUDIOENABLE | HCFG_LOCKTANKCACHE_MASK
-| HCFG_AUTOMUTE;
-if (sc->rev >= 6)
-tmp |= HCFG_JOYENABLE;
-
-emu_wr(sc, HCFG, tmp, 4);
-
-/* TOSLink detection */
-sc->tos_link = 0;
-tmp = emu_rd(sc, HCFG, 4);
-if (tmp & (HCFG_GPINPUT0 | HCFG_GPINPUT1)) {
-emu_wr(sc, HCFG, tmp | HCFG_GPOUT1, 4);
-DELAY(50);
-if (tmp != (emu_rd(sc, HCFG, 4) & ~HCFG_GPOUT1)) {
-sc->tos_link = 1;
-emu_wr(sc, HCFG, tmp, 4);
-}
-}
-}
-
-return 0;
+ return 0;
}
static int
emu_uninit(struct sc_info *sc)
{
-u_int32_t ch;
+ u_int32_t ch;
-emu_wr(sc, INTE, 0, 4);
-for (ch = 0; ch < NUM_G; ch++)
-emu_wrptr(sc, ch, DCYSUSV, ENV_OFF);
-for (ch = 0; ch < NUM_G; ch++) {
-emu_wrptr(sc, ch, VTFT, 0);
-emu_wrptr(sc, ch, CVCF, 0);
-emu_wrptr(sc, ch, PTRX, 0);
-emu_wrptr(sc, ch, CPF, 0);
-}
-
-if (sc->audigy) { /* stop fx processor */
-emu_wrptr(sc, 0, A_DBG, A_DBG_SINGLE_STEP);
-}
-
-/* disable audio and lock cache */
-emu_wr(sc, HCFG,
-HCFG_LOCKSOUNDCACHE | HCFG_LOCKTANKCACHE_MASK | HCFG_MUTEBUTTONENABLE,
-4);
-
-emu_wrptr(sc, 0, PTB, 0);
-/* reset recording buffers */
-emu_wrptr(sc, 0, MICBS, ADCBS_BUFSIZE_NONE);
-emu_wrptr(sc, 0, MICBA, 0);
-emu_wrptr(sc, 0, FXBS, ADCBS_BUFSIZE_NONE);
-emu_wrptr(sc, 0, FXBA, 0);
-emu_wrptr(sc, 0, FXWC, 0);
-emu_wrptr(sc, 0, ADCBS, ADCBS_BUFSIZE_NONE);
-emu_wrptr(sc, 0, ADCBA, 0);
-emu_wrptr(sc, 0, TCB, 0);
-emu_wrptr(sc, 0, TCBS, 0);
-
-/* disable channel interrupt */
-emu_wrptr(sc, 0, CLIEL, 0);
-emu_wrptr(sc, 0, CLIEH, 0);
-emu_wrptr(sc, 0, SOLEL, 0);
-emu_wrptr(sc, 0, SOLEH, 0);
-
-/* init envelope engine */
-if (!SLIST_EMPTY(&sc->mem.blocks))
-device_printf(sc->dev, "warning: memblock list not emptyn");
-emu_free(sc, sc->mem.ptb_pages);
-emu_free(sc, sc->mem.silent_page);
-
-return 0;
+ emu_wr(sc, INTE, 0, 4);
+ for (ch = 0; ch < NUM_G; ch++)
+ emu_wrptr(sc, ch, DCYSUSV, ENV_OFF);
+ for (ch = 0; ch < NUM_G; ch++) {
+ emu_wrptr(sc, ch, VTFT, 0);
+ emu_wrptr(sc, ch, CVCF, 0);
+ emu_wrptr(sc, ch, PTRX, 0);
+ emu_wrptr(sc, ch, CPF, 0);
+ }
+
+ if (sc->audigy) { /* stop fx processor */
+ emu_wrptr(sc, 0, A_DBG, A_DBG_SINGLE_STEP);
+ }
+
+ /* disable audio and lock cache */
+ emu_wr(sc, HCFG,
+ HCFG_LOCKSOUNDCACHE | HCFG_LOCKTANKCACHE_MASK | HCFG_MUTEBUTTONENABLE,
+ 4);
+
+ emu_wrptr(sc, 0, PTB, 0);
+ /* reset recording buffers */
+ emu_wrptr(sc, 0, MICBS, ADCBS_BUFSIZE_NONE);
+ emu_wrptr(sc, 0, MICBA, 0);
+ emu_wrptr(sc, 0, FXBS, ADCBS_BUFSIZE_NONE);
+ emu_wrptr(sc, 0, FXBA, 0);
+ emu_wrptr(sc, 0, FXWC, 0);
+ emu_wrptr(sc, 0, ADCBS, ADCBS_BUFSIZE_NONE);
+ emu_wrptr(sc, 0, ADCBA, 0);
+ emu_wrptr(sc, 0, TCB, 0);
+ emu_wrptr(sc, 0, TCBS, 0);
+
+ /* disable channel interrupt */
+ emu_wrptr(sc, 0, CLIEL, 0);
+ emu_wrptr(sc, 0, CLIEH, 0);
+ emu_wrptr(sc, 0, SOLEL, 0);
+ emu_wrptr(sc, 0, SOLEH, 0);
+
+ /* init envelope engine */
+ if (!SLIST_EMPTY(&sc->mem.blocks))
+ device_printf(sc->dev, "warning: memblock list not empty\n");
+ emu_free(sc, sc->mem.ptb_pages);
+ emu_free(sc, sc->mem.silent_page);
+
+ if(sc->mpu)
+ mpu401_uninit(sc->mpu);
+ return 0;
}
static int
emu_pci_probe(device_t dev)
{
-char *s = NULL;
-
-switch (pci_get_devid(dev)) {
-case EMU10K1_PCI_ID:
-s = "Creative EMU10K1";
-break;
-
-case EMU10K2_PCI_ID:
-if (pci_get_revid(dev) == 0x04)
-s = "Creative Audigy 2 (EMU10K2)";
-else
-s = "Creative Audigy (EMU10K2)";
-break;
-
-case EMU10K3_PCI_ID:
-s = "Creative Audigy 2 (EMU10K3)";
-break;
+ char *s = NULL;
-default:
-return ENXIO;
-}
+ switch (pci_get_devid(dev)) {
+ case EMU10K1_PCI_ID:
+ s = "Creative EMU10K1";
+ break;
+
+ case EMU10K2_PCI_ID:
+ if (pci_get_revid(dev) == 0x04)
+ s = "Creative Audigy 2 (EMU10K2)";
+ else
+ s = "Creative Audigy (EMU10K2)";
+ break;
+
+ case EMU10K3_PCI_ID:
+ s = "Creative Audigy 2 (EMU10K3)";
+ break;
+
+ default:
+ return ENXIO;
+ }
-device_set_desc(dev, s);
-return BUS_PROBE_DEFAULT;
+ device_set_desc(dev, s);
+ return BUS_PROBE_LOW_PRIORITY;
}
static int
emu_pci_attach(device_t dev)
{
-struct ac97_info *codec = NULL;
-struct sc_info *sc;
-u_int32_t data;
-int i, gotmic;
-char status[SND_STATUSLEN];
-
-if ((sc = malloc(sizeof(*sc), M_DEVBUF, M_WAITOK | M_ZERO)) == NULL) {
-device_printf(dev, "cannot allocate softcn");
-return ENXIO;
-}
-
-sc->lock = snd_mtxcreate(device_get_nameunit(dev), "sound softc");
-sc->dev = dev;
-sc->type = pci_get_devid(dev);
-sc->rev = pci_get_revid(dev);
-sc->audigy = sc->type == EMU10K2_PCI_ID || sc->type == EMU10K3_PCI_ID;
-sc->audigy2 = (sc->audigy && sc->rev == 0x04);
-sc->nchans = sc->audigy ? 8 : 4;
-sc->addrmask = sc->audigy ? A_PTR_ADDRESS_MASK : PTR_ADDRESS_MASK;
-
-data = pci_read_config(dev, PCIR_COMMAND, 2);
-data |= (PCIM_CMD_PORTEN | PCIM_CMD_BUSMASTEREN);
-pci_write_config(dev, PCIR_COMMAND, data, 2);
-data = pci_read_config(dev, PCIR_COMMAND, 2);
-
-i = PCIR_BAR(0);
-sc->reg = bus_alloc_resource_any(dev, SYS_RES_IOPORT, &i, RF_ACTIVE);
-if (sc->reg == NULL) {
-device_printf(dev, "unable to map register spacen");
-goto bad;
-}
-sc->st = rman_get_bustag(sc->reg);
-sc->sh = rman_get_bushandle(sc->reg);
-
-sc->bufsz = pcm_getbuffersize(dev, 4096, EMU_DEFAULT_BUFSZ, 65536);
-
-if (bus_dma_tag_create(/*parent*/NULL, /*alignment*/2, /*boundary*/0,
-/*lowaddr*/1 << 31, /* can only access 0-2gb */
-/*highaddr*/BUS_SPACE_MAXADDR,
-/*filter*/NULL, /*filterarg*/NULL,
-/*maxsize*/sc->bufsz, /*nsegments*/1, /*maxsegz*/0x3ffff,
-/*flags*/0, /*lockfunc*/busdma_lock_mutex,
-/*lockarg*/&Giant, &sc->parent_dmat) != 0) {
-device_printf(dev, "unable to create dma tagn");
-goto bad;
-}
-
-if (emu_init(sc) == -1) {
-device_printf(dev, "unable to initialize the cardn");
-goto bad;
-}
-
-codec = AC97_CREATE(dev, sc, emu_ac97);
-if (codec == NULL) goto bad;
-gotmic = (ac97_getcaps(codec) & AC97_CAP_MICCHANNEL) ? 1 : 0;
-if (mixer_init(dev, ac97_getmixerclass(), codec) == -1) goto bad;
-
-i = 0;
-sc->irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &i,
-RF_ACTIVE | RF_SHAREABLE);
-if (!sc->irq ||
-snd_setup_intr(dev, sc->irq, INTR_MPSAFE, emu_intr, sc, &sc->ih)) {
-device_printf(dev, "unable to map interruptn");
-goto bad;
-}
-
-snprintf(status, SND_STATUSLEN, "at io 0x%lx irq %ld %s",
-rman_get_start(sc->reg), rman_get_start(sc->irq),
-PCM_KLDSTRING(snd_emu10k1));
-
-if (pcm_register(dev, sc, sc->nchans, gotmic ? 3 : 2)) goto bad;
-for (i = 0; i < sc->nchans; i++)
-pcm_addchan(dev, PCMDIR_PLAY, &emupchan_class, sc);
-for (i = 0; i < (gotmic ? 3 : 2); i++)
-pcm_addchan(dev, PCMDIR_REC, &emurchan_class, sc);
+ struct ac97_info *codec = NULL;
+ struct sc_info *sc;
+ u_int32_t data;
+ int i, gotmic;
+ char status[SND_STATUSLEN];
+
+ sc = malloc(sizeof(*sc), M_DEVBUF, M_WAITOK | M_ZERO);
+ sc->lock = snd_mtxcreate(device_get_nameunit(dev), "snd_emu10k1 softc");
+ sc->dev = dev;
+ sc->type = pci_get_devid(dev);
+ sc->rev = pci_get_revid(dev);
+ sc->audigy = sc->type == EMU10K2_PCI_ID || sc->type == EMU10K3_PCI_ID;
+ sc->audigy2 = (sc->audigy && sc->rev == 0x04);
+ sc->nchans = sc->audigy ? 8 : 4;
+ sc->addrmask = sc->audigy ? A_PTR_ADDRESS_MASK : PTR_ADDRESS_MASK;
+
+ data = pci_read_config(dev, PCIR_COMMAND, 2);
+ data |= (PCIM_CMD_PORTEN | PCIM_CMD_BUSMASTEREN);
+ pci_write_config(dev, PCIR_COMMAND, data, 2);
+ data = pci_read_config(dev, PCIR_COMMAND, 2);
+
+ i = PCIR_BAR(0);
+ sc->reg = bus_alloc_resource_any(dev, SYS_RES_IOPORT, &i, RF_ACTIVE);
+ if (sc->reg == NULL) {
+ device_printf(dev, "unable to map register space\n");
+ goto bad;
+ }
+ sc->st = rman_get_bustag(sc->reg);
+ sc->sh = rman_get_bushandle(sc->reg);
+
+ sc->bufsz = pcm_getbuffersize(dev, 4096, EMU_DEFAULT_BUFSZ, 65536);
+
+ if (bus_dma_tag_create(/*parent*/bus_get_dma_tag(dev), /*alignment*/2,
+ /*boundary*/0,
+ /*lowaddr*/1 << 31, /* can only access 0-2gb */
+ /*highaddr*/BUS_SPACE_MAXADDR,
+ /*filter*/NULL, /*filterarg*/NULL,
+ /*maxsize*/sc->bufsz, /*nsegments*/1, /*maxsegz*/0x3ffff,
+ /*flags*/0, /*lockfunc*/busdma_lock_mutex,
+ /*lockarg*/&Giant, &sc->parent_dmat) != 0) {
+ device_printf(dev, "unable to create dma tag\n");
+ goto bad;
+ }
+
+ if (emu_init(sc) == -1) {
+ device_printf(dev, "unable to initialize the card\n");
+ goto bad;
+ }
+
+ codec = AC97_CREATE(dev, sc, emu_ac97);
+ if (codec == NULL) goto bad;
+ 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);
+ if (!sc->irq ||
+ snd_setup_intr(dev, sc->irq, INTR_MPSAFE, emu_intr, sc, &sc->ih)) {
+ device_printf(dev, "unable to map interrupt\n");
+ goto bad;
+ }
+
+ snprintf(status, SND_STATUSLEN, "at io 0x%lx irq %ld %s",
+ rman_get_start(sc->reg), rman_get_start(sc->irq),
+ PCM_KLDSTRING(snd_emu10k1));
+
+ if (pcm_register(dev, sc, sc->nchans, gotmic ? 3 : 2)) goto bad;
+ for (i = 0; i < sc->nchans; i++)
+ pcm_addchan(dev, PCMDIR_PLAY, &emupchan_class, sc);
+ for (i = 0; i < (gotmic ? 3 : 2); i++)
+ pcm_addchan(dev, PCMDIR_REC, &emurchan_class, sc);
-pcm_setstatus(dev, status);
+ pcm_setstatus(dev, status);
-return 0;
+ return 0;
bad:
-if (codec) ac97_destroy(codec);
-if (sc->reg) bus_release_resource(dev, SYS_RES_IOPORT, PCIR_BAR(0), sc->reg);
-if (sc->ih) bus_teardown_intr(dev, sc->irq, sc->ih);
-if (sc->irq) bus_release_resource(dev, SYS_RES_IRQ, 0, sc->irq);
-if (sc->parent_dmat) bus_dma_tag_destroy(sc->parent_dmat);
-if (sc->lock) snd_mtxfree(sc->lock);
-free(sc, M_DEVBUF);
-return ENXIO;
+ if (codec) ac97_destroy(codec);
+ if (sc->reg) bus_release_resource(dev, SYS_RES_IOPORT, PCIR_BAR(0), sc->reg);
+ if (sc->ih) bus_teardown_intr(dev, sc->irq, sc->ih);
+ if (sc->irq) bus_release_resource(dev, SYS_RES_IRQ, 0, sc->irq);
+ if (sc->parent_dmat) bus_dma_tag_destroy(sc->parent_dmat);
+ if (sc->lock) snd_mtxfree(sc->lock);
+ free(sc, M_DEVBUF);
+ return ENXIO;
}
static int
emu_pci_detach(device_t dev)
{
-int r;
-struct sc_info *sc;
+ int r;
+ struct sc_info *sc;
-r = pcm_unregister(dev);
-if (r)
-return r;
-
-sc = pcm_getdevinfo(dev);
-/* shutdown chip */
-emu_uninit(sc);
-
-bus_release_resource(dev, SYS_RES_IOPORT, PCIR_BAR(0), sc->reg);
-bus_teardown_intr(dev, sc->irq, sc->ih);
-bus_release_resource(dev, SYS_RES_IRQ, 0, sc->irq);
-bus_dma_tag_destroy(sc->parent_dmat);
-snd_mtxfree(sc->lock);
-free(sc, M_DEVBUF);
+ r = pcm_unregister(dev);
+ if (r)
+ return r;
+
+ sc = pcm_getdevinfo(dev);
+ /* shutdown chip */
+ emu_uninit(sc);
+
+ bus_release_resource(dev, SYS_RES_IOPORT, PCIR_BAR(0), sc->reg);
+ bus_teardown_intr(dev, sc->irq, sc->ih);
+ bus_release_resource(dev, SYS_RES_IRQ, 0, sc->irq);
+ bus_dma_tag_destroy(sc->parent_dmat);
+ snd_mtxfree(sc->lock);
+ free(sc, M_DEVBUF);
-return 0;
+ return 0;
}
/* add suspend, resume */
static device_method_t emu_methods[] = {
-/* Device interface */
-DEVMETHOD(device_probe, emu_pci_probe),
-DEVMETHOD(device_attach, emu_pci_attach),
-DEVMETHOD(device_detach, emu_pci_detach),
+ /* Device interface */
+ DEVMETHOD(device_probe, emu_pci_probe),
+ DEVMETHOD(device_attach, emu_pci_attach),
+ DEVMETHOD(device_detach, emu_pci_detach),
-{ 0, 0 }
+ { 0, 0 }
};
static driver_t emu_driver = {
-"pcm",
-emu_methods,
-PCM_SOFTC_SIZE,
+ "pcm",
+ emu_methods,
+ PCM_SOFTC_SIZE,
};
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
emujoy_pci_probe(device_t dev)
{
-char *s = NULL;
+ char *s = NULL;
-switch (pci_get_devid(dev)) {
-case 0x70021102:
-s = "Creative EMU10K1 Joystick";
-device_quiet(dev);
-break;
-case 0x70031102:
-s = "Creative EMU10K2 Joystick";
-device_quiet(dev);
-break;
-}
+ switch (pci_get_devid(dev)) {
+ case 0x70021102:
+ s = "Creative EMU10K1 Joystick";
+ device_quiet(dev);
+ break;
+ case 0x70031102:
+ s = "Creative EMU10K2 Joystick";
+ device_quiet(dev);
+ break;
+ }
-if (s) device_set_desc(dev, s);
-return s ? -1000 : ENXIO;
+ if (s) device_set_desc(dev, s);
+ return s ? -1000 : ENXIO;
}
static int
emujoy_pci_attach(device_t dev)
{
-return 0;
+ return 0;
}
static int
emujoy_pci_detach(device_t dev)
{
-return 0;
+ return 0;
}
static device_method_t emujoy_methods[] = {
-DEVMETHOD(device_probe, emujoy_pci_probe),
-DEVMETHOD(device_attach, emujoy_pci_attach),
-DEVMETHOD(device_detach, emujoy_pci_detach),
+ DEVMETHOD(device_probe, emujoy_pci_probe),
+ DEVMETHOD(device_attach, emujoy_pci_attach),
+ DEVMETHOD(device_detach, emujoy_pci_detach),
-{ 0, 0 }
+ { 0, 0 }
};
static driver_t emujoy_driver = {
-"emujoy",
-emujoy_methods,
-8,
+ "emujoy",
+ emujoy_methods,
+ 8,
};
static devclass_t emujoy_devclass;
--- /dev/null
+++ sys/dev/sound/pci/spicds.h
@@ -0,0 +1,121 @@
+/*
+ * Copyright (c) 2006 Konstantin Dimitrov <kosio.dimitrov at gmail.com>
+ * Copyright (c) 2001 Katsurajima Naoto <raven at katsurajima.seya.yokohama.jp>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHERIN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THEPOSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD: src/sys/dev/sound/pci/spicds.h,v 1.4 2007/05/27 19:58:39 joel Exp $
+ */
+
+/* supported CODECs */
+#define SPICDS_TYPE_AK4524 0
+#define SPICDS_TYPE_AK4528 1
+#define SPICDS_TYPE_WM8770 2
+#define SPICDS_TYPE_AK4358 3
+#define SPICDS_TYPE_AK4381 4
+#define SPICDS_TYPE_AK4396 5
+
+/* AK4524/AK4528 control registers */
+#define AK4524_POWER 0x00
+#define AK4528_POWER 0x00
+#define AK452X_POWER_PWDA 0x01
+#define AK452X_POWER_PWAD 0x02
+#define AK452X_POWER_PWVR 0x04
+#define AK4524_RESET 0x01
+#define AK4528_RESET 0x01
+#define AK452X_RESET_RSDA 0x01
+#define AK452X_RESET_RSAD 0x02
+#define AK4524_FORMAT 0x02
+#define AK4528_FORMAT 0x02
+#define AK452X_FORMAT_1X 0x00
+#define AK452X_FORMAT_2X 0x01
+#define AK452X_FORMAT_4X1 0x02
+#define AK452X_FORMAT_4X2 0x03
+#define AK452X_FORMAT_256FSN 0x00
+#define AK452X_FORMAT_512FSN 0x04
+#define AK452X_FORMAT_1024FSN 0x08
+#define AK452X_FORMAT_384FSN 0x10
+#define AK452X_FORMAT_768FSN 0x14
+#define AK452X_FORMAT_OM24IL16 0x00
+#define AK452X_FORMAT_OM24IL20 0x20
+#define AK452X_FORMAT_OM24IM24 0x40
+#define AK452X_FORMAT_I2S 0x60
+#define AK452X_FORMAT_OM24IL24 0x80
+#define AK4524_DVC 0x03
+#define AK452X_DVC_DEM441 0x00
+#define AK452X_DVC_DEMOFF 0x01
+#define AK452X_DVC_DEM48 0x02
+#define AK452X_DVC_DEM32 0x03
+#define AK452X_DVC_ZTM256 0x00
+#define AK452X_DVC_ZTM512 0x04
+#define AK452X_DVC_ZTM1024 0x08
+#define AK452X_DVC_ZTM2048 0x0c
+#define AK452X_DVC_ZCE 0x10
+#define AK452X_DVC_HPFL 0x04
+#define AK452X_DVC_HPFR 0x08
+#define AK452X_DVC_SMUTE 0x80
+#define AK4524_LIPGA 0x04
+#define AK4524_RIPGA 0x05
+#define AK4524_LOATT 0x06
+#define AK4524_ROATT 0x07
+#define AK4528_LOATT 0x04
+#define AK4528_ROATT 0x05
+
+/* WM8770 control registers */
+#define WM8770_AOATT_L1 0x00
+#define WM8770_AOATT_R1 0x01
+#define WM8770_AOATT_L2 0x02
+#define WM8770_AOATT_R2 0x03
+#define WM8770_AOATT_L3 0x04
+#define WM8770_AOATT_R3 0x05
+#define WM8770_AOATT_L4 0x06
+#define WM8770_AOATT_R4 0x07
+#define WM8770_AOATT_MAST 0x08
+#define WM8770_AOATT_UPDATE 0x100
+
+/* AK4358 control registers */
+#define AK4358_LO1ATT 0x04
+#define AK4358_RO1ATT 0x05
+#define AK4358_OATT_ENABLE 0x80
+
+/* AK4381 control registers */
+#define AK4381_LOATT 0x03
+#define AK4381_ROATT 0x04
+
+/* AK4396 control registers */
+#define AK4396_LOATT 0x03
+#define AK4396_ROATT 0x04
+
+struct spicds_info;
+
+typedef void (*spicds_ctrl)(void *, unsigned int, unsigned int, unsigned int);
+
+struct spicds_info *spicds_create(device_t dev, void *devinfo, int num, spicds_ctrl);
+void spicds_destroy(struct spicds_info *codec);
+void spicds_settype(struct spicds_info *codec, unsigned int type);
+void spicds_setcif(struct spicds_info *codec, unsigned int cif);
+void spicds_setformat(struct spicds_info *codec, unsigned int format);
+void spicds_setdvc(struct spicds_info *codec, unsigned int dvc);
+void spicds_init(struct spicds_info *codec);
+void spicds_reinit(struct spicds_info *codec);
+void spicds_set(struct spicds_info *codec, int dir, unsigned int left, unsigned int right);
--- /dev/null
+++ sys/dev/sound/pci/emu10kx.c
@@ -0,0 +1,3560 @@
+/*-
+ * Copyright (c) 1999 Cameron Grant <cg at freebsd.org>
+ * Copyright (c) 2003-2007 Yuriy Tsibizov <yuriy.tsibizov at gfk.ru>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHERIN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD: src/sys/dev/sound/pci/emu10kx.c,v 1.12 2007/09/12 07:43:42 ariff Exp $
+ */
+
+#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/bus.h>
+#include <machine/bus.h>
+#include <sys/rman.h>
+#include <sys/systm.h>
+#include <sys/sbuf.h>
+#include <sys/queue.h>
+#include <sys/lock.h>
+#include <sys/mutex.h>
+#include <sys/sysctl.h>
+#include <sys/kdb.h>
+
+#include <dev/pci/pcireg.h>
+#include <dev/pci/pcivar.h>
+
+#include <machine/clock.h> /* for DELAY */
+
+#include <dev/sound/chip.h>
+#include <dev/sound/pcm/sound.h>
+#include <dev/sound/pcm/ac97.h>
+
+#include <dev/sound/pci/emu10kx.h>
+
+/* hw flags */
+#define HAS_51 0x0001
+#define HAS_71 0x0002
+#define HAS_AC97 0x0004
+
+#define IS_EMU10K1 0x0008
+#define IS_EMU10K2 0x0010
+#define IS_CA0102 0x0020
+#define IS_CA0108 0x0040
+#define IS_UNKNOWN 0x0080
+
+#define BROKEN_DIGITAL 0x0100
+#define DIGITAL_ONLY 0x0200
+
+#define IS_CARDBUS 0x0400
+
+#define MODE_ANALOG 1
+#define MODE_DIGITAL 2
+#define SPDIF_MODE_PCM 1
+#define SPDIF_MODE_AC3 2
+
+#define MACS 0x0
+#define MACS1 0x1
+#define MACW 0x2
+#define MACW1 0x3
+#define MACINTS 0x4
+#define MACINTW 0x5
+#define ACC3 0x6
+#define MACMV 0x7
+#define ANDXOR 0x8
+#define TSTNEG 0x9
+#define LIMIT 0xA
+#define LIMIT1 0xB
+#define LOG 0xC
+#define EXP 0xD
+#define INTERP 0xE
+#define SKIP 0xF
+
+#define GPR(i) (sc->gpr_base+(i))
+#define INP(i) (sc->input_base+(i))
+#define OUTP(i) (sc->output_base+(i))
+#define FX(i) (i)
+#define FX2(i) (sc->efxc_base+(i))
+#define DSP_CONST(i) (sc->dsp_zero+(i))
+
+#define COND_NORMALIZED DSP_CONST(0x1)
+#define COND_BORROW DSP_CONST(0x2)
+#define COND_MINUS DSP_CONST(0x3)
+#define COND_LESS_ZERO DSP_CONST(0x4)
+#define COND_EQ_ZERO DSP_CONST(0x5)
+#define COND_SATURATION DSP_CONST(0x6)
+#define COND_NEQ_ZERO DSP_CONST(0x8)
+
+#define DSP_ACCUM DSP_CONST(0x16)
+#define DSP_CCR DSP_CONST(0x17)
+
+/* Live! Inputs */
+#define IN_AC97_L 0x00
+#define IN_AC97_R 0x01
+#define IN_AC97 IN_AC97_L
+#define IN_SPDIF_CD_L 0x02
+#define IN_SPDIF_CD_R 0x03
+#define IN_SPDIF_CD IN_SPDIF_CD_L
+#define IN_ZOOM_L 0x04
+#define IN_ZOOM_R 0x05
+#define IN_ZOOM IN_ZOOM_L
+#define IN_TOSLINK_L 0x06
+#define IN_TOSLINK_R 0x07
+#define IN_TOSLINK IN_TOSLINK_L
+#define IN_LINE1_L 0x08
+#define IN_LINE1_R 0x09
+#define IN_LINE1 IN_LINE1_L
+#define IN_COAX_SPDIF_L 0x0a
+#define IN_COAX_SPDIF_R 0x0b
+#define IN_COAX_SPDIF IN_COAX_SPDIF_L
+#define IN_LINE2_L 0x0c
+#define IN_LINE2_R 0x0d
+#define IN_LINE2 IN_LINE2_L
+#define IN_0E 0x0e
+#define IN_0F 0x0f
+
+/* Outputs */
+#define OUT_AC97_L 0x00
+#define OUT_AC97_R 0x01
+#define OUT_AC97 OUT_AC97_L
+#define OUT_A_FRONT OUT_AC97
+#define OUT_TOSLINK_L 0x02
+#define OUT_TOSLINK_R 0x03
+#define OUT_TOSLINK OUT_TOSLINK_L
+#define OUT_D_CENTER 0x04
+#define OUT_D_SUB 0x05
+#define OUT_HEADPHONE_L 0x06
+#define OUT_HEADPHONE_R 0x07
+#define OUT_HEADPHONE OUT_HEADPHONE_L
+#define OUT_REAR_L 0x08
+#define OUT_REAR_R 0x09
+#define OUT_REAR OUT_REAR_L
+#define OUT_ADC_REC_L 0x0a
+#define OUT_ADC_REC_R 0x0b
+#define OUT_ADC_REC OUT_ADC_REC_L
+#define OUT_MIC_CAP 0x0c
+
+/* Live! 5.1 Digital, non-standart 5.1 (center & sub) outputs */
+#define OUT_A_CENTER 0x11
+#define OUT_A_SUB 0x12
+
+/* Audigy Inputs */
+#define A_IN_AC97_L 0x00
+#define A_IN_AC97_R 0x01
+#define A_IN_AC97 A_IN_AC97_L
+#define A_IN_SPDIF_CD_L 0x02
+#define A_IN_SPDIF_CD_R 0x03
+#define A_IN_SPDIF_CD A_IN_SPDIF_CD_L
+#define A_IN_O_SPDIF_L 0x04
+#define A_IN_O_SPDIF_R 0x05
+#define A_IN_O_SPDIF A_IN_O_SPDIF_L
+#define A_IN_LINE2_L 0x08
+#define A_IN_LINE2_R 0x09
+#define A_IN_LINE2 A_IN_LINE2_L
+#define A_IN_R_SPDIF_L 0x0a
+#define A_IN_R_SPDIF_R 0x0b
+#define A_IN_R_SPDIF A_IN_R_SPDIF_L
+#define A_IN_AUX2_L 0x0c
+#define A_IN_AUX2_R 0x0d
+#define A_IN_AUX2 A_IN_AUX2_L
+
+/* Audigiy Outputs */
+#define A_OUT_D_FRONT_L 0x00
+#define A_OUT_D_FRONT_R 0x01
+#define A_OUT_D_FRONT A_OUT_D_FRONT_L
+#define A_OUT_D_CENTER 0x02
+#define A_OUT_D_SUB 0x03
+#define A_OUT_D_SIDE_L 0x04
+#define A_OUT_D_SIDE_R 0x05
+#define A_OUT_D_SIDE A_OUT_D_SIDE_L
+#define A_OUT_D_REAR_L 0x06
+#define A_OUT_D_REAR_R 0x07
+#define A_OUT_D_REAR A_OUT_D_REAR_L
+
+/* on Audigy Platinum only */
+#define A_OUT_HPHONE_L 0x04
+#define A_OUT_HPHONE_R 0x05
+#define A_OUT_HPHONE A_OUT_HPHONE_L
+
+#define A_OUT_A_FRONT_L 0x08
+#define A_OUT_A_FRONT_R 0x09
+#define A_OUT_A_FRONT A_OUT_A_FRONT_L
+#define A_OUT_A_CENTER 0x0a
+#define A_OUT_A_SUB 0x0b
+#define A_OUT_A_SIDE_L 0x0c
+#define A_OUT_A_SIDE_R 0x0d
+#define A_OUT_A_SIDE A_OUT_A_SIDE_L
+#define A_OUT_A_REAR_L 0x0e
+#define A_OUT_A_REAR_R 0x0f
+#define A_OUT_A_REAR A_OUT_A_REAR_L
+#define A_OUT_AC97_L 0x10
+#define A_OUT_AC97_R 0x11
+#define A_OUT_AC97 A_OUT_AC97_L
+#define A_OUT_ADC_REC_L 0x16
+#define A_OUT_ADC_REC_R 0x17
+#define A_OUT_ADC_REC A_OUT_ADC_REC_L
+
+#include "emu10k1-alsa%diked.h"
+#include "p16v-alsa%diked.h"
+#include "p17v-alsa%diked.h"
+
+#define C_FRONT_L 0
+#define C_FRONT_R 1
+#define C_REC_L 2
+#define C_REC_R 3
+#define C_REAR_L 4
+#define C_REAR_R 5
+#define C_CENTER 6
+#define C_SUB 7
+#define C_SIDE_L 8
+#define C_SIDE_R 9
+#define NUM_CACHES 10
+
+#define CDSPDIFMUTE 0
+#define ANALOGMUTE 1
+#define NUM_MUTE 2
+
+#define EMU_MAX_GPR 512
+#define EMU_MAX_IRQ_CONSUMERS 32
+
+struct emu_voice {
+ int vnum;
+ unsigned int b16:1, stereo:1, busy:1, running:1, ismaster:1;
+ int speed;
+ int start;
+ int end;
+ int vol;
+ uint32_t buf;
+ void *vbuf;
+ struct emu_voice *slave;
+ uint32_t sa;
+ uint32_t ea;
+ uint32_t routing[8];
+ uint32_t amounts[8];
+};
+
+struct emu_memblk {
+ SLIST_ENTRY(emu_memblk) link;
+ void *buf;
+ char owner[16];
+ bus_addr_t buf_addr;
+ uint32_t pte_start, pte_size;
+};
+
+struct emu_mem {
+ uint8_t bmap[EMU_MAXPAGES / 8];
+ uint32_t *ptb_pages;
+ void *silent_page;
+ bus_addr_t silent_page_addr;
+ bus_addr_t ptb_pages_addr;
+ bus_dma_tag_t dmat;
+ struct emu_sc_info *card;
+ SLIST_HEAD(, emu_memblk) blocks;
+};
+
+/* rm */
+struct emu_rm {
+ struct emu_sc_info *card;
+ struct mtx gpr_lock;
+ signed int allocmap[EMU_MAX_GPR];
+ int num_gprs;
+ int last_free_gpr;
+ int num_used;
+};
+
+struct emu_intr_handler {
+ void* softc;
+ uint32_t intr_mask;
+ uint32_t inte_mask;
+ uint32_t(*irq_func) (void *softc, uint32_t irq);
+};
+
+struct emu_sc_info {
+ struct mtx lock;
+ struct mtx rw; /* Hardware exclusive access lock */
+
+ /* Hardware and subdevices */
+ device_t dev;
+ device_t pcm[RT_COUNT];
+ device_t midi[2];
+ uint32_t type;
+ uint32_t rev;
+
+ bus_space_tag_t st;
+ bus_space_handle_t sh;
+
+ struct cdev *cdev; /* /dev/emu10k character device */
+ struct mtx emu10kx_lock;
+ int emu10kx_isopen;
+ struct sbuf emu10kx_sbuf;
+ int emu10kx_bufptr;
+
+
+ /* Resources */
+ struct resource *reg;
+ struct resource *irq;
+ void *ih;
+
+ /* IRQ handlers */
+ struct emu_intr_handler ihandler[EMU_MAX_IRQ_CONSUMERS];
+
+ /* Card HW configuration */
+ unsigned int mode; /* analog / digital */
+ unsigned int mchannel_fx;
+ unsigned int dsp_zero;
+ unsigned int code_base;
+ unsigned int code_size;
+ unsigned int gpr_base;
+ unsigned int num_gprs;
+ unsigned int input_base;
+ unsigned int output_base;
+ unsigned int efxc_base;
+ unsigned int opcode_shift;
+ unsigned int high_operand_shift;
+ unsigned int address_mask;
+ uint32_t is_emu10k1:1, is_emu10k2, is_ca0102, is_ca0108:1,
+ has_ac97:1, has_51:1, has_71:1,
+ enable_ir:1,
+ broken_digital:1, is_cardbus:1;
+
+ signed int mch_disabled, mch_rec, dbg_level;
+ signed int num_inputs;
+ unsigned int num_outputs;
+ unsigned int num_fxbuses;
+ unsigned int routing_code_start;
+ unsigned int routing_code_end;
+
+ /* HW resources */
+ struct emu_voice voice[NUM_G]; /* Hardware voices */
+ uint32_t irq_mask[EMU_MAX_IRQ_CONSUMERS]; /* IRQ manager data */
+ int timer[EMU_MAX_IRQ_CONSUMERS]; /* timer */
+ int timerinterval;
+ struct emu_rm *rm;
+ struct emu_mem mem; /* memory */
+
+ /* Mixer */
+ int mixer_gpr[NUM_MIXERS];
+ int mixer_volcache[NUM_MIXERS];
+ int cache_gpr[NUM_CACHES];
+ int dummy_gpr;
+ int mute_gpr[NUM_MUTE];
+ struct sysctl_ctx_list *ctx;
+ struct sysctl_oid *root;
+};
+
+static void emu_setmap(void *arg, bus_dma_segment_t * segs, int nseg, int error);
+static void* emu_malloc(struct emu_mem *mem, uint32_t sz, bus_addr_t * addr);
+static void emu_free(struct emu_mem *mem, void *dmabuf);
+static void* emu_memalloc(struct emu_mem *mem, uint32_t sz, bus_addr_t * addr, const char * owner);
+static int emu_memfree(struct emu_mem *mem, void *membuf);
+static int emu_memstart(struct emu_mem *mem, void *membuf);
+
+/* /dev */
+static int emu10kx_dev_init(struct emu_sc_info *sc);
+static int emu10kx_dev_uninit(struct emu_sc_info *sc);
+static int emu10kx_prepare(struct emu_sc_info *sc, struct sbuf *s);
+
+static void emumix_set_mode(struct emu_sc_info *sc, int mode);
+static void emumix_set_spdif_mode(struct emu_sc_info *sc, int mode);
+static void emumix_set_fxvol(struct emu_sc_info *sc, unsigned gpr, int32_t vol);
+static void emumix_set_gpr(struct emu_sc_info *sc, unsigned gpr, int32_t val);
+static int sysctl_emu_mixer_control(SYSCTL_HANDLER_ARGS);
+
+static int emu_rm_init(struct emu_sc_info *sc);
+static int emu_rm_uninit(struct emu_sc_info *sc);
+static int emu_rm_gpr_alloc(struct emu_rm *rm, int count);
+
+static unsigned int emu_getcard(device_t dev);
+static uint32_t emu_rd_nolock(struct emu_sc_info *sc, unsigned int regno, unsigned int size);
+static void emu_wr_nolock(struct emu_sc_info *sc, unsigned int regno, uint32_t data, unsigned int size);
+static void emu_wr_cbptr(struct emu_sc_info *sc, uint32_t data);
+
+static void emu_vstop(struct emu_sc_info *sc, char channel, int enable);
+
+static void emu_intr(void *p);
+static void emu_wrefx(struct emu_sc_info *sc, unsigned int pc, unsigned int data);
+static void emu_addefxop(struct emu_sc_info *sc, unsigned int op, unsigned int z, unsigned int w, unsigned int x, unsigned int y, uint32_t * pc);
+static void emu_initefx(struct emu_sc_info *sc);
+
+static int emu_cardbus_init(struct emu_sc_info *sc);
+static int emu_init(struct emu_sc_info *sc);
+static int emu_uninit(struct emu_sc_info *sc);
+
+static int emu_read_ivar(device_t bus __unused, device_t dev, int ivar_index, uintptr_t * result);
+static int emu_write_ivar(device_t bus __unused, device_t dev __unused,
+ int ivar_index, uintptr_t value __unused);
+
+static int emu_pci_probe(device_t dev);
+static int emu_pci_attach(device_t dev);
+static int emu_pci_detach(device_t dev);
+static int emu_modevent(module_t mod __unused, int cmd, void *data __unused);
+
+#ifdef SND_EMU10KX_DEBUG
+
+#define EMU_MTX_DEBUG() do { \
+ if (mtx_owned(&sc->rw)) { \
+ printf("RW owned in %s line %d for %s\n", __func__, \
+ __LINE__ , device_get_nameunit(sc->dev)); \
+ printf("rw lock owned: %d\n", mtx_owned(&sc->rw)); \
+ printf("rw lock: value %x thread %x\n", \
+ ((&sc->rw)->mtx_lock & ~MTX_FLAGMASK), \
+ (uintptr_t)curthread); \
+ printf("rw lock: recursed %d\n", mtx_recursed(&sc->rw));\
+ db_show_mtx(&sc->rw); \
+ } \
+ } while (0)
+#else
+#define EMU_MTX_DEBUG() do { \
+ } while (0)
+#endif
+
+#define EMU_RWLOCK() do { \
+ EMU_MTX_DEBUG(); \
+ mtx_lock(&(sc->rw)); \
+ } while (0)
+
+#define EMU_RWUNLOCK() do { \
+ mtx_unlock(&(sc->rw)); \
+ EMU_MTX_DEBUG(); \
+ } while (0)
+
+/* Supported cards */
+struct emu_hwinfo {
+ uint16_t vendor;
+ uint16_t device;
+ uint16_t subvendor;
+ uint16_t subdevice;
+ char SBcode[8];
+ char desc[32];
+ int flags;
+};
+
+static struct emu_hwinfo emu_cards[] = {
+ {0xffff, 0xffff, 0xffff, 0xffff, "BADCRD", "Not a compatible card", 0},
+ /* 0x0020..0x002f 4.0 EMU10K1 cards */
+ {0x1102, 0x0002, 0x1102, 0x0020, "CT4850", "SBLive! Value", HAS_AC97 | IS_EMU10K1},
+ {0x1102, 0x0002, 0x1102, 0x0021, "CT4620", "SBLive!", HAS_AC97 | IS_EMU10K1},
+ {0x1102, 0x0002, 0x1102, 0x002f, "CT????", "SBLive! mainboard implementation", HAS_AC97 | IS_EMU10K1},
+
+ /* (range unknown) 5.1 EMU10K1 cards */
+ {0x1102, 0x0002, 0x1102, 0x100a, "CT????", "SBLive! 5.1", HAS_AC97 | HAS_51 | IS_EMU10K1},
+
+ /* 0x80??..0x805? 4.0 EMU10K1 cards */
+ {0x1102, 0x0002, 0x1102, 0x8022, "CT4780", "SBLive! Value", HAS_AC97 | IS_EMU10K1},
+ {0x1102, 0x0002, 0x1102, 0x8023, "CT4790", "SB PCI512", HAS_AC97 | IS_EMU10K1},
+ {0x1102, 0x0002, 0x1102, 0x8024, "CT4760", "SBLive!", HAS_AC97 | IS_EMU10K1},
+ {0x1102, 0x0002, 0x1102, 0x8025, "CT????", "SBLive! Mainboard Implementation", HAS_AC97 | IS_EMU10K1},
+ {0x1102, 0x0002, 0x1102, 0x8026, "CT4830", "SBLive! Value", HAS_AC97 | IS_EMU10K1},
+ {0x1102, 0x0002, 0x1102, 0x8027, "CT4832", "SBLive! Value", HAS_AC97 | IS_EMU10K1},
+ {0x1102, 0x0002, 0x1102, 0x8028, "CT4760", "SBLive! OEM version", HAS_AC97 | IS_EMU10K1},
+ {0x1102, 0x0002, 0x1102, 0x8031, "CT4831", "SBLive! Value", HAS_AC97 | IS_EMU10K1},
+ {0x1102, 0x0002, 0x1102, 0x8040, "CT4760", "SBLive!", HAS_AC97 | IS_EMU10K1},
+ {0x1102, 0x0002, 0x1102, 0x8051, "CT4850", "SBLive! Value", HAS_AC97 | IS_EMU10K1},
+
+ /* 0x8061..0x???? 5.1 EMU10K1 cards */
+ {0x1102, 0x0002, 0x1102, 0x8061, "SB????", "SBLive! Player 5.1", HAS_AC97 | HAS_51 | IS_EMU10K1},
+ {0x1102, 0x0002, 0x1102, 0x8062, "CT4830", "SBLive! 1024", HAS_AC97 | HAS_51 | IS_EMU10K1},
+ {0x1102, 0x0002, 0x1102, 0x8064, "SB????", "SBLive! 5.1", HAS_AC97 | HAS_51 | IS_EMU10K1},
+ {0x1102, 0x0002, 0x1102, 0x8065, "SB0220", "SBLive! 5.1 Digital", HAS_AC97 | HAS_51 | IS_EMU10K1},
+ {0x1102, 0x0002, 0x1102, 0x8066, "CT4780", "SBLive! 5.1 Digital", HAS_AC97 | HAS_51 | IS_EMU10K1},
+ {0x1102, 0x0002, 0x1102, 0x8067, "SB????", "SBLive!", HAS_AC97 | HAS_51 | IS_EMU10K1},
+
+ /* Generic SB Live! */
+ {0x1102, 0x0002, 0x1102, 0x0000, "SB????", "SBLive! (Unknown model)", HAS_AC97 | IS_EMU10K1},
+
+ /* 0x0041..0x0043 EMU10K2 (some kind of Audigy) cards */
+
+ /* 0x0051..0x0051 5.1 CA0100-IAF cards */
+ {0x1102, 0x0004, 0x1102, 0x0051, "SB0090", "Audigy", HAS_AC97 | HAS_51 | IS_EMU10K2},
+ /* ES is CA0100-IDF chip that don't work in digital mode */
+ {0x1102, 0x0004, 0x1102, 0x0052, "SB0160", "Audigy ES", HAS_AC97 | HAS_71 | IS_EMU10K2 | BROKEN_DIGITAL},
+ /* 0x0053..0x005C 5.1 CA0101-NAF cards */
+ {0x1102, 0x0004, 0x1102, 0x0053, "SB0090", "Audigy Player/OEM", HAS_AC97 | HAS_51 | IS_EMU10K2},
+ {0x1102, 0x0004, 0x1102, 0x0058, "SB0090", "Audigy Player/OEM", HAS_AC97 | HAS_51 | IS_EMU10K2},
+
+ /* 0x1002..0x1009 5.1 CA0102-IAT cards */
+ {0x1102, 0x0004, 0x1102, 0x1002, "SB????", "Audigy 2 Platinum", HAS_51 | IS_CA0102},
+ {0x1102, 0x0004, 0x1102, 0x1005, "SB????", "Audigy 2 Platinum EX", HAS_51 | IS_CA0102},
+ {0x1102, 0x0004, 0x1102, 0x1007, "SB0240", "Audigy 2", HAS_AC97 | HAS_51 | IS_CA0102},
+
+ /* 0x2001..0x2003 7.1 CA0102-ICT cards */
+ {0x1102, 0x0004, 0x1102, 0x2001, "SB0350", "Audigy 2 ZS", HAS_AC97 | HAS_71 | IS_CA0102},
+ {0x1102, 0x0004, 0x1102, 0x2002, "SB0350", "Audigy 2 ZS", HAS_AC97 | HAS_71 | IS_CA0102},
+ /* XXX No reports about 0x2003 & 0x2004 cards */
+ {0x1102, 0x0004, 0x1102, 0x2003, "SB0350", "Audigy 2 ZS", HAS_AC97 | HAS_71 | IS_CA0102},
+ {0x1102, 0x0004, 0x1102, 0x2004, "SB0350", "Audigy 2 ZS", HAS_AC97 | HAS_71 | IS_CA0102},
+ {0x1102, 0x0004, 0x1102, 0x2005, "SB0350", "Audigy 2 ZS", HAS_AC97 | HAS_71 | IS_CA0102},
+
+ /* (range unknown) 7.1 CA0102-xxx Audigy 4 cards */
+ {0x1102, 0x0004, 0x1102, 0x2007, "SB0380", "Audigy 4 Pro", HAS_AC97 | HAS_71 | IS_CA0102},
+
+ /* Generic Audigy or Audigy 2 */
+ {0x1102, 0x0004, 0x1102, 0x0000, "SB????", "Audigy (Unknown model)", HAS_AC97 | HAS_51 | IS_EMU10K2},
+
+ /* We don't support CA0103-DAT (Audigy LS) cards */
+ /* There is NO CA0104-xxx cards */
+ /* There is NO CA0105-xxx cards */
+ /* We don't support CA0106-DAT (SB Live! 24 bit) cards */
+ /* There is NO CA0107-xxx cards */
+
+ /* 0x1000..0x1001 7.1 CA0108-IAT cards */
+ {0x1102, 0x0008, 0x1102, 0x1000, "SB????", "Audigy 2 LS", HAS_AC97 | HAS_51 | IS_CA0108 | DIGITAL_ONLY},
+ {0x1102, 0x0008, 0x1102, 0x1001, "SB0400", "Audigy 2 Value", HAS_AC97 | HAS_71 | IS_CA0108 | DIGITAL_ONLY},
+ {0x1102, 0x0008, 0x1102, 0x1021, "SB0610", "Audigy 4", HAS_AC97 | HAS_71 | IS_CA0108 | DIGITAL_ONLY},
+
+ {0x1102, 0x0008, 0x1102, 0x2001, "SB0530", "Audigy 2 ZS CardBus", HAS_AC97 | HAS_71 | IS_CA0108 | IS_CARDBUS},
+
+ {0x1102, 0x0008, 0x0000, 0x0000, "SB????", "Audigy 2 Value (Unknown model)", HAS_AC97 | HAS_51 | IS_CA0108},
+};
+/* Unsupported cards */
+
+static struct emu_hwinfo emu_bad_cards[] = {
+ /* APS cards should be possible to support */
+ {0x1102, 0x0002, 0x1102, 0x4001, "EMUAPS", "E-mu APS", 0},
+ {0x1102, 0x0002, 0x1102, 0x4002, "EMUAPS", "E-mu APS", 0},
+ {0x1102, 0x0004, 0x1102, 0x4001, "EMU???", "E-mu 1212m [4001]", 0},
+ /* Similar-named ("Live!" or "Audigy") cards on different chipsets */
+ {0x1102, 0x8064, 0x0000, 0x0000, "SB0100", "SBLive! 5.1 OEM", 0},
+ {0x1102, 0x0006, 0x0000, 0x0000, "SB0200", "DELL OEM SBLive! Value", 0},
+ {0x1102, 0x0007, 0x0000, 0x0000, "SB0310", "Audigy LS", 0},
+};
+
+/*
+ * Get best known information about device.
+ */
+static unsigned int
+emu_getcard(device_t dev)
+{
+ uint16_t device;
+ uint16_t subdevice;
+ int n_cards;
+ unsigned int thiscard;
+ int i;
+
+ device = pci_read_config(dev, PCIR_DEVICE, /* bytes */ 2);
+ subdevice = pci_read_config(dev, PCIR_SUBDEV_0, /* bytes */ 2);
+
+ n_cards = sizeof(emu_cards) / sizeof(struct emu_hwinfo);
+ thiscard = 0;
+ for (i = 1; i < n_cards; i++) {
+ if (device == emu_cards[i].device) {
+ if (subdevice == emu_cards[i].subdevice) {
+ thiscard = i;
+ break;
+ }
+ if (0x0000 == emu_cards[i].subdevice) {
+ thiscard = i;
+ /*
+ * don't break, we can get more specific card
+ * later in the list.
+ */
+ }
+ }
+ }
+
+ n_cards = sizeof(emu_bad_cards) / sizeof(struct emu_hwinfo);
+ for (i = 0; i < n_cards; i++) {
+ if (device == emu_bad_cards[i].device) {
+ if (subdevice == emu_bad_cards[i].subdevice) {
+ thiscard = 0;
+ break;
+ }
+ if (0x0000 == emu_bad_cards[i].subdevice) {
+ thiscard = 0;
+ break; /* we avoid all this cards */
+ }
+ }
+ }
+ return (thiscard);
+}
+
+
+/*
+ * Base hardware interface are 32 (Audigy) or 64 (Audigy2) registers.
+ * Some of them are used directly, some of them provide pointer / data pairs.
+ */
+static uint32_t
+emu_rd_nolock(struct emu_sc_info *sc, unsigned int regno, unsigned int size)
+{
+
+ KASSERT(sc != NULL, ("emu_rd: NULL sc"));
+ switch (size) {
+ case 1:
+ return (bus_space_read_1(sc->st, sc->sh, regno));
+ case 2:
+ return (bus_space_read_2(sc->st, sc->sh, regno));
+ case 4:
+ return (bus_space_read_4(sc->st, sc->sh, regno));
+ }
+ return (0xffffffff);
+}
+
+static void
+emu_wr_nolock(struct emu_sc_info *sc, unsigned int regno, uint32_t data, unsigned int size)
+{
+
+ KASSERT(sc != NULL, ("emu_rd: NULL sc"));
+ switch (size) {
+ case 1:
+ bus_space_write_1(sc->st, sc->sh, regno, data);
+ break;
+ case 2:
+ bus_space_write_2(sc->st, sc->sh, regno, data);
+ break;
+ case 4:
+ bus_space_write_4(sc->st, sc->sh, regno, data);
+ break;
+ }
+}
+/*
+ * PTR / DATA interface. Access to EMU10Kx is made
+ * via (channel, register) pair. Some registers are channel-specific,
+ * some not.
+ */
+uint32_t
+emu_rdptr(struct emu_sc_info *sc, unsigned int chn, unsigned int reg)
+{
+ uint32_t ptr, val, mask, size, offset;
+
+ ptr = ((reg << 16) & sc->address_mask) | (chn & PTR_CHANNELNUM_MASK);
+
+ EMU_RWLOCK();
+ emu_wr_nolock(sc, PTR, ptr, 4);
+ val = emu_rd_nolock(sc, DATA, 4);
+ EMU_RWUNLOCK();
+
+ /*
+ * XXX Some register numbers has data size and offset encoded in
+ * it to get only part of 32bit register. This use is not described
+ * in register name, be careful!
+ */
+ if (reg & 0xff000000) {
+ size = (reg >> 24) & 0x3f;
+ offset = (reg >> 16) & 0x1f;
+ mask = ((1 << size) - 1) << offset;
+ val &= mask;
+ val >>= offset;
+ }
+ return (val);
+}
+
+void
+emu_wrptr(struct emu_sc_info *sc, unsigned int chn, unsigned int reg, uint32_t data)
+{
+ uint32_t ptr, mask, size, offset;
+
+ ptr = ((reg << 16) & sc->address_mask) | (chn & PTR_CHANNELNUM_MASK);
+
+ EMU_RWLOCK();
+ emu_wr_nolock(sc, PTR, ptr, 4);
+ /*
+ * XXX Another kind of magic encoding in register number. This can
+ * give you side effect - it will read previous data from register
+ * and change only required bits.
+ */
+ if (reg & 0xff000000) {
+ size = (reg >> 24) & 0x3f;
+ offset = (reg >> 16) & 0x1f;
+ mask = ((1 << size) - 1) << offset;
+ data <<= offset;
+ data &= mask;
+ data |= emu_rd_nolock(sc, DATA, 4) & ~mask;
+ }
+ emu_wr_nolock(sc, DATA, data, 4);
+ EMU_RWUNLOCK();
+}
+/*
+ * PTR2 / DATA2 interface. Access to P16v is made
+ * via (channel, register) pair. Some registers are channel-specific,
+ * some not. This interface is supported by CA0102 and CA0108 chips only.
+ */
+uint32_t
+emu_rd_p16vptr(struct emu_sc_info *sc, uint16_t chn, uint16_t reg)
+{
+ uint32_t val;
+
+ /* XXX separate lock? */
+ EMU_RWLOCK();
+ emu_wr_nolock(sc, PTR2, (reg << 16) | chn, 4);
+ val = emu_rd_nolock(sc, DATA2, 4);
+
+ EMU_RWUNLOCK();
+
+ return (val);
+}
+
+void
+emu_wr_p16vptr(struct emu_sc_info *sc, uint16_t chn, uint16_t reg, uint32_t data)
+{
+
+ EMU_RWLOCK();
+ emu_wr_nolock(sc, PTR2, (reg << 16) | chn, 4);
+ emu_wr_nolock(sc, DATA2, data, 4);
+ EMU_RWUNLOCK();
+}
+/*
+ * XXX CardBus interface. Not tested on any real hardware.
+ */
+static void
+emu_wr_cbptr(struct emu_sc_info *sc, uint32_t data)
+{
+ uint32_t val;
+
+ /*
+ * 0x38 is IPE3 (CD S/PDIF interrupt pending register) on CA0102. Seems
+ * to be some reg/value accessible kind of config register on CardBus
+ * CA0108, with value(?) in top 16 bit, address(?) in low 16
+ */
+
+ val = emu_rd_nolock(sc, 0x38, 4);
+ emu_wr_nolock(sc, 0x38, data, 4);
+ val = emu_rd_nolock(sc, 0x38, 4);
+
+}
+
+/*
+ * Direct hardware register access
+ * Assume that it is never used to access PTR-based registers and can run unlocked.
+ */
+void
+emu_wr(struct emu_sc_info *sc, unsigned int regno, uint32_t data, unsigned int size)
+{
+ KASSERT(regno != PTR, ("emu_wr: attempt to write to PTR"));
+ KASSERT(regno != PTR2, ("emu_wr: attempt to write to PTR2"));
+
+ emu_wr_nolock(sc, regno, data, size);
+}
+
+uint32_t
+emu_rd(struct emu_sc_info *sc, unsigned int regno, unsigned int size)
+{
+ uint32_t rd;
+
+ KASSERT(regno != DATA, ("emu_rd: attempt to read DATA"));
+ KASSERT(regno != DATA2, ("emu_rd: attempt to read DATA2"));
+
+ rd = emu_rd_nolock(sc, regno, size);
+ return (rd);
+}
+
+/*
+ * Enabling IR MIDI messages is another kind of black magic. It just
+ * has to be made this way. It really do it.
+ */
+void
+emu_enable_ir(struct emu_sc_info *sc)
+{
+ uint32_t iocfg;
+
+ if (sc->is_emu10k2 || sc->is_ca0102) {
+ iocfg = emu_rd_nolock(sc, A_IOCFG, 2);
+ emu_wr_nolock(sc, A_IOCFG, iocfg | A_IOCFG_GPOUT2, 2);
+ DELAY(500);
+ emu_wr_nolock(sc, A_IOCFG, iocfg | A_IOCFG_GPOUT1 | A_IOCFG_GPOUT2, 2);
+ DELAY(500);
+ emu_wr_nolock(sc, A_IOCFG, iocfg | A_IOCFG_GPOUT1, 2);
+ DELAY(100);
+ emu_wr_nolock(sc, A_IOCFG, iocfg, 2);
+ device_printf(sc->dev, "Audigy IR MIDI events enabled.\n");
+ sc->enable_ir = 1;
+ }
+ if (sc->is_emu10k1) {
+ iocfg = emu_rd_nolock(sc, HCFG, 4);
+ emu_wr_nolock(sc, HCFG, iocfg | HCFG_GPOUT2, 4);
+ DELAY(500);
+ emu_wr_nolock(sc, HCFG, iocfg | HCFG_GPOUT1 | HCFG_GPOUT2, 4);
+ DELAY(100);
+ emu_wr_nolock(sc, HCFG, iocfg, 4);
+ device_printf(sc->dev, "SB Live! IR MIDI events enabled.\n");
+ sc->enable_ir = 1;
+ }
+}
+
+
+/*
+ * emu_timer_ - HW timer managment
+ */
+int
+emu_timer_create(struct emu_sc_info *sc)
+{
+ int i, timer;
+
+ timer = -1;
+
+ mtx_lock(&sc->lock);
+ for (i = 0; i < EMU_MAX_IRQ_CONSUMERS; i++)
+ if (sc->timer[i] == 0) {
+ sc->timer[i] = -1; /* disable it */
+ timer = i;
+ mtx_unlock(&sc->lock);
+ return (timer);
+ }
+ mtx_unlock(&sc->lock);
+
+ return (-1);
+}
+
+int
+emu_timer_set(struct emu_sc_info *sc, int timer, int delay)
+{
+ int i;
+
+ if (timer < 0)
+ return (-1);
+
+ RANGE(delay, 16, 1024);
+ RANGE(timer, 0, EMU_MAX_IRQ_CONSUMERS-1);
+
+ mtx_lock(&sc->lock);
+ sc->timer[timer] = delay;
+ for (i = 0; i < EMU_MAX_IRQ_CONSUMERS; i++)
+ if (sc->timerinterval > sc->timer[i])
+ sc->timerinterval = sc->timer[i];
+
+ /* XXX */
+ emu_wr(sc, TIMER, sc->timerinterval & 0x03ff, 2);
+ mtx_unlock(&sc->lock);
+
+ return (timer);
+}
+
+int
+emu_timer_enable(struct emu_sc_info *sc, int timer, int go)
+{
+ uint32_t x;
+ int ena_int;
+ int i;
+
+ if (timer < 0)
+ return (-1);
+
+ RANGE(timer, 0, EMU_MAX_IRQ_CONSUMERS-1);
+
+ mtx_lock(&sc->lock);
+
+ if ((go == 1) && (sc->timer[timer] < 0))
+ sc->timer[timer] = -sc->timer[timer];
+ if ((go == 0) && (sc->timer[timer] > 0))
+ sc->timer[timer] = -sc->timer[timer];
+
+ ena_int = 0;
+ for (i = 0; i < EMU_MAX_IRQ_CONSUMERS; i++) {
+ if (sc->timerinterval > sc->timer[i])
+ sc->timerinterval = sc->timer[i];
+ if (sc->timer[i] > 0)
+ ena_int = 1;
+ }
+
+ emu_wr(sc, TIMER, sc->timerinterval & 0x03ff, 2);
+
+ if (ena_int == 1) {
+ x = emu_rd(sc, INTE, 4);
+ x |= INTE_INTERVALTIMERENB;
+ emu_wr(sc, INTE, x, 4);
+ } else {
+ x = emu_rd(sc, INTE, 4);
+ x &= ~INTE_INTERVALTIMERENB;
+ emu_wr(sc, INTE, x, 4);
+ }
+ mtx_unlock(&sc->lock);
+ return (0);
+}
+
+int
+emu_timer_clear(struct emu_sc_info *sc, int timer)
+{
+ if (timer < 0)
+ return (-1);
+
+ RANGE(timer, 0, EMU_MAX_IRQ_CONSUMERS-1);
+
+ emu_timer_enable(sc, timer, 0);
+
+ mtx_lock(&sc->lock);
+ if (sc->timer[timer] != 0)
+ sc->timer[timer] = 0;
+ mtx_unlock(&sc->lock);
+
+ return (timer);
+}
+
+/*
+ * emu_intr_ - HW interrupt handler managment
+ */
+int
+emu_intr_register(struct emu_sc_info *sc, uint32_t inte_mask, uint32_t intr_mask, uint32_t(*func) (void *softc, uint32_t irq), void *isc)
+{
+ int i;
+ uint32_t x;
+
+ mtx_lock(&sc->lock);
+ for (i = 0; i < EMU_MAX_IRQ_CONSUMERS; i++)
+ if (sc->ihandler[i].inte_mask == 0) {
+ sc->ihandler[i].inte_mask = inte_mask;
+ sc->ihandler[i].intr_mask = intr_mask;
+ sc->ihandler[i].softc = isc;
+ sc->ihandler[i].irq_func = func;
+ x = emu_rd(sc, INTE, 4);
+ x |= inte_mask;
+ emu_wr(sc, INTE, x, 4);
+ mtx_unlock(&sc->lock);
+ if (sc->dbg_level > 1)
+ device_printf(sc->dev, "ihandle %d registered\n", i);
+
+ return (i);
+ }
+ mtx_unlock(&sc->lock);
+ if (sc->dbg_level > 1)
+ device_printf(sc->dev, "ihandle not registered\n");
+
+ return (-1);
+}
+
+int
+emu_intr_unregister(struct emu_sc_info *sc, int hnumber)
+{
+ uint32_t x;
+ int i;
+
+ mtx_lock(&sc->lock);
+
+ if (sc->ihandler[hnumber].inte_mask == 0) {
+ mtx_unlock(&sc->lock);
+ return (-1);
+ }
+
+ x = emu_rd(sc, INTE, 4);
+ x &= ~sc->ihandler[hnumber].inte_mask;
+
+ sc->ihandler[hnumber].inte_mask = 0;
+ sc->ihandler[hnumber].intr_mask = 0;
+ sc->ihandler[hnumber].softc = NULL;
+ sc->ihandler[hnumber].irq_func = NULL;
+
+ /* other interupt handlers may use this INTE value */
+ for (i = 0; i < EMU_MAX_IRQ_CONSUMERS; i++)
+ if (sc->ihandler[i].inte_mask != 0)
+ x |= sc->ihandler[i].inte_mask;
+
+ emu_wr(sc, INTE, x, 4);
+
+ mtx_unlock(&sc->lock);
+ return (hnumber);
+}
+
+static void
+emu_intr(void *p)
+{
+ struct emu_sc_info *sc = (struct emu_sc_info *)p;
+ uint32_t stat, ack;
+ int i;
+
+ for (;;) {
+ stat = emu_rd(sc, IPR, 4);
+ ack = 0;
+ if (stat == 0)
+ break;
+ emu_wr(sc, IPR, stat, 4);
+ for (i = 0; i < EMU_MAX_IRQ_CONSUMERS; i++) {
+ if ((((sc->ihandler[i].intr_mask) & stat) != 0) &&
+ (((void *)sc->ihandler[i].irq_func) != NULL)) {
+ ack |= sc->ihandler[i].irq_func(sc->ihandler[i].softc,
+ (sc->ihandler[i].intr_mask) & stat);
+ }
+ }
+ if (sc->dbg_level > 1)
+ if (stat & (~ack))
+ device_printf(sc->dev, "Unhandled interrupt: %08x\n", stat & (~ack));
+
+ }
+
+ if ((sc->is_ca0102) || (sc->is_ca0108))
+ for (;;) {
+ stat = emu_rd(sc, IPR2, 4);
+ ack = 0;
+ if (stat == 0)
+ break;
+ emu_wr(sc, IPR2, stat, 4);
+ if (sc->dbg_level > 1)
+ device_printf(sc->dev, "IPR2: %08x\n", stat);
+
+ break; /* to avoid infinite loop. shoud be removed
+ * after completion of P16V interface. */
+ }
+
+ if (sc->is_ca0102)
+ for (;;) {
+ stat = emu_rd(sc, IPR3, 4);
+ ack = 0;
+ if (stat == 0)
+ break;
+ emu_wr(sc, IPR3, stat, 4);
+ if (sc->dbg_level > 1)
+ device_printf(sc->dev, "IPR3: %08x\n", stat);
+
+ break; /* to avoid infinite loop. should be removed
+ * after completion of S/PDIF interface */
+ }
+}
+
+
+/*
+ * Get data from private emu10kx structure for PCM buffer allocation.
+ * Used by PCM code only.
+ */
+bus_dma_tag_t
+emu_gettag(struct emu_sc_info *sc)
+{
+ return (sc->mem.dmat);
+}
+
+static void
+emu_setmap(void *arg, bus_dma_segment_t * segs, int nseg, int error)
+{
+ bus_addr_t *phys = (bus_addr_t *) arg;
+
+ *phys = error ? 0 : (bus_addr_t) segs->ds_addr;
+
+ if (bootverbose) {
+ printf("emu10kx: setmap (%lx, %lx), nseg=%d, error=%d\n",
+ (unsigned long)segs->ds_addr, (unsigned long)segs->ds_len,
+ nseg, error);
+ }
+}
+
+static void *
+emu_malloc(struct emu_mem *mem, uint32_t sz, bus_addr_t * addr)
+{
+ void *dmabuf;
+ bus_dmamap_t map;
+ int error;
+
+ *addr = 0;
+ if ((error = bus_dmamem_alloc(mem->dmat, &dmabuf, BUS_DMA_NOWAIT, &map))) {
+ if (mem->card->dbg_level > 2)
+ device_printf(mem->card->dev, "emu_malloc: failed to alloc DMA map: %d\n", error);
+ return (NULL);
+ }
+ if ((error = bus_dmamap_load(mem->dmat, map, dmabuf, sz, emu_setmap, addr, 0)) || !*addr) {
+ if (mem->card->dbg_level > 2)
+ device_printf(mem->card->dev, "emu_malloc: failed to load DMA memory: %d\n", error);
+ return (NULL);
+ }
+ return (dmabuf);
+}
+
+static void
+emu_free(struct emu_mem *mem, void *dmabuf)
+{
+ bus_dmamem_free(mem->dmat, dmabuf, NULL);
+}
+
+static void *
+emu_memalloc(struct emu_mem *mem, uint32_t sz, bus_addr_t * addr, const char *owner)
+{
+ uint32_t blksz, start, idx, ofs, tmp, found;
+ struct emu_memblk *blk;
+ void *membuf;
+
+ blksz = sz / EMUPAGESIZE;
+ if (sz > (blksz * EMUPAGESIZE))
+ blksz++;
+ if (blksz > EMU_MAX_BUFSZ / EMUPAGESIZE) {
+ if (mem->card->dbg_level > 2)
+ device_printf(mem->card->dev, "emu_memalloc: memory request tool large\n");
+ return (NULL);
+ }
+ /* find a free block in the bitmap */
+ found = 0;
+ start = 1;
+ while (!found && start + blksz < EMU_MAXPAGES) {
+ found = 1;
+ for (idx = start; idx < start + blksz; idx++)
+ if (mem->bmap[idx >> 3] & (1 << (idx & 7)))
+ found = 0;
+ if (!found)
+ start++;
+ }
+ if (!found) {
+ if (mem->card->dbg_level > 2)
+ device_printf(mem->card->dev, "emu_memalloc: no free space in bitmap\n");
+ return (NULL);
+ }
+ blk = malloc(sizeof(*blk), M_DEVBUF, M_NOWAIT);
+ if (blk == NULL) {
+ if (mem->card->dbg_level > 2)
+ device_printf(mem->card->dev, "emu_memalloc: buffer allocation failed\n");
+ return (NULL);
+ }
+ bzero(blk, sizeof(*blk));
+ membuf = emu_malloc(mem, sz, &blk->buf_addr);
+ *addr = blk->buf_addr;
+ if (membuf == NULL) {
+ if (mem->card->dbg_level > 2)
+ device_printf(mem->card->dev, "emu_memalloc: can't setup HW memory\n");
+ free(blk, M_DEVBUF);
+ return (NULL);
+ }
+ blk->buf = membuf;
+ blk->pte_start = start;
+ blk->pte_size = blksz;
+ strncpy(blk->owner, owner, 15);
+ blk->owner[15] = '\0';
+ ofs = 0;
+ for (idx = start; idx < start + blksz; idx++) {
+ mem->bmap[idx >> 3] |= 1 << (idx & 7);
+ tmp = (uint32_t) (u_long) ((uint8_t *) blk->buf_addr + ofs);
+ mem->ptb_pages[idx] = (tmp << 1) | idx;
+ ofs += EMUPAGESIZE;
+ }
+ SLIST_INSERT_HEAD(&mem->blocks, blk, link);
+ return (membuf);
+}
+
+static int
+emu_memfree(struct emu_mem *mem, void *membuf)
+{
+ uint32_t idx, tmp;
+ struct emu_memblk *blk, *i;
+
+ blk = NULL;
+ SLIST_FOREACH(i, &mem->blocks, link) {
+ if (i->buf == membuf)
+ blk = i;
+ }
+ if (blk == NULL)
+ return (EINVAL);
+ SLIST_REMOVE(&mem->blocks, blk, emu_memblk, link);
+ emu_free(mem, membuf);
+ tmp = (uint32_t) (mem->silent_page_addr) << 1;
+ for (idx = blk->pte_start; idx < blk->pte_start + blk->pte_size; idx++) {
+ mem->bmap[idx >> 3] &= ~(1 << (idx & 7));
+ mem->ptb_pages[idx] = tmp | idx;
+ }
+ free(blk, M_DEVBUF);
+ return (0);
+}
+
+static int
+emu_memstart(struct emu_mem *mem, void *membuf)
+{
+ struct emu_memblk *blk, *i;
+
+ blk = NULL;
+ SLIST_FOREACH(i, &mem->blocks, link) {
+ if (i->buf == membuf)
+ blk = i;
+ }
+ if (blk == NULL)
+ return (-1);
+ return (blk->pte_start);
+}
+
+
+static uint32_t
+emu_rate_to_pitch(uint32_t rate)
+{
+ static uint32_t logMagTable[128] = {
+ 0x00000, 0x02dfc, 0x05b9e, 0x088e6, 0x0b5d6, 0x0e26f, 0x10eb3, 0x13aa2,
+ 0x1663f, 0x1918a, 0x1bc84, 0x1e72e, 0x2118b, 0x23b9a, 0x2655d, 0x28ed5,
+ 0x2b803, 0x2e0e8, 0x30985, 0x331db, 0x359eb, 0x381b6, 0x3a93d, 0x3d081,
+ 0x3f782, 0x41e42, 0x444c1, 0x46b01, 0x49101, 0x4b6c4, 0x4dc49, 0x50191,
+ 0x5269e, 0x54b6f, 0x57006, 0x59463, 0x5b888, 0x5dc74, 0x60029, 0x623a7,
+ 0x646ee, 0x66a00, 0x68cdd, 0x6af86, 0x6d1fa, 0x6f43c, 0x7164b, 0x73829,
+ 0x759d4, 0x77b4f, 0x79c9a, 0x7bdb5, 0x7dea1, 0x7ff5e, 0x81fed, 0x8404e,
+ 0x86082, 0x88089, 0x8a064, 0x8c014, 0x8df98, 0x8fef1, 0x91e20, 0x93d26,
+ 0x95c01, 0x97ab4, 0x9993e, 0x9b79f, 0x9d5d9, 0x9f3ec, 0xa11d8, 0xa2f9d,
+ 0xa4d3c, 0xa6ab5, 0xa8808, 0xaa537, 0xac241, 0xadf26, 0xafbe7, 0xb1885,
+ 0xb3500, 0xb5157, 0xb6d8c, 0xb899f, 0xba58f, 0xbc15e, 0xbdd0c, 0xbf899,
+ 0xc1404, 0xc2f50, 0xc4a7b, 0xc6587, 0xc8073, 0xc9b3f, 0xcb5ed, 0xcd07c,
+ 0xceaec, 0xd053f, 0xd1f73, 0xd398a, 0xd5384, 0xd6d60, 0xd8720, 0xda0c3,
+ 0xdba4a, 0xdd3b4, 0xded03, 0xe0636, 0xe1f4e, 0xe384a, 0xe512c, 0xe69f3,
+ 0xe829f, 0xe9b31, 0xeb3a9, 0xecc08, 0xee44c, 0xefc78, 0xf148a, 0xf2c83,
+ 0xf4463, 0xf5c2a, 0xf73da, 0xf8b71, 0xfa2f0, 0xfba57, 0xfd1a7, 0xfe8df
+ };
+ static char logSlopeTable[128] = {
+ 0x5c, 0x5c, 0x5b, 0x5a, 0x5a, 0x59, 0x58, 0x58,
+ 0x57, 0x56, 0x56, 0x55, 0x55, 0x54, 0x53, 0x53,
+ 0x52, 0x52, 0x51, 0x51, 0x50, 0x50, 0x4f, 0x4f,
+ 0x4e, 0x4d, 0x4d, 0x4d, 0x4c, 0x4c, 0x4b, 0x4b,
+ 0x4a, 0x4a, 0x49, 0x49, 0x48, 0x48, 0x47, 0x47,
+ 0x47, 0x46, 0x46, 0x45, 0x45, 0x45, 0x44, 0x44,
+ 0x43, 0x43, 0x43, 0x42, 0x42, 0x42, 0x41, 0x41,
+ 0x41, 0x40, 0x40, 0x40, 0x3f, 0x3f, 0x3f, 0x3e,
+ 0x3e, 0x3e, 0x3d, 0x3d, 0x3d, 0x3c, 0x3c, 0x3c,
+ 0x3b, 0x3b, 0x3b, 0x3b, 0x3a, 0x3a, 0x3a, 0x39,
+ 0x39, 0x39, 0x39, 0x38, 0x38, 0x38, 0x38, 0x37,
+ 0x37, 0x37, 0x37, 0x36, 0x36, 0x36, 0x36, 0x35,
+ 0x35, 0x35, 0x35, 0x34, 0x34, 0x34, 0x34, 0x34,
+ 0x33, 0x33, 0x33, 0x33, 0x32, 0x32, 0x32, 0x32,
+ 0x32, 0x31, 0x31, 0x31, 0x31, 0x31, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f
+ };
+ int i;
+
+ if (rate == 0)
+ return (0);
+ rate *= 11185; /* Scale 48000 to 0x20002380 */
+ for (i = 31; i > 0; i--) {
+ if (rate & 0x80000000) { /* Detect leading "1" */
+ return (((uint32_t) (i - 15) << 20) +
+ logMagTable[0x7f & (rate >> 24)] +
+ (0x7f & (rate >> 17)) *
+ logSlopeTable[0x7f & (rate >> 24)]);
+ }
+ rate <<= 1;
+ }
+ /* NOTREACHED */
+ return (0);
+}
+
+static uint32_t
+emu_rate_to_linearpitch(uint32_t rate)
+{
+ rate = (rate << 8) / 375;
+ return ((rate >> 1) + (rate & 1));
+}
+
+struct emu_voice *
+emu_valloc(struct emu_sc_info *sc)
+{
+ struct emu_voice *v;
+ int i;
+
+ v = NULL;
+ mtx_lock(&sc->lock);
+ for (i = 0; i < NUM_G && sc->voice[i].busy; i++);
+ if (i < NUM_G) {
+ v = &sc->voice[i];
+ v->busy = 1;
+ }
+ mtx_unlock(&sc->lock);
+ return (v);
+}
+
+void
+emu_vfree(struct emu_sc_info *sc, struct emu_voice *v)
+{
+ int i, r;
+
+ mtx_lock(&sc->lock);
+ for (i = 0; i < NUM_G; i++) {
+ if (v == &sc->voice[i] && sc->voice[i].busy) {
+ v->busy = 0;
+ /*
+ * XXX What we should do with mono channels?
+ * See -pcm.c emupchan_init for other side of
+ * this problem
+ */
+ if (v->slave != NULL)
+ r = emu_memfree(&sc->mem, v->vbuf);
+ }
+ }
+ mtx_unlock(&sc->lock);
+}
+
+int
+emu_vinit(struct emu_sc_info *sc, struct emu_voice *m, struct emu_voice *s,
+ uint32_t sz, struct snd_dbuf *b)
+{
+ void *vbuf;
+ bus_addr_t tmp_addr;
+
+ vbuf = emu_memalloc(&sc->mem, sz, &tmp_addr, "vinit");
+ if (vbuf == NULL) {
+ if(sc->dbg_level > 2)
+ device_printf(sc->dev, "emu_memalloc returns NULL in enu_vinit\n");
+ return (ENOMEM);
+ }
+ if (b != NULL)
+ sndbuf_setup(b, vbuf, sz);
+ m->start = emu_memstart(&sc->mem, vbuf) * EMUPAGESIZE;
+ if (m->start < 0) {
+ if(sc->dbg_level > 2)
+ device_printf(sc->dev, "emu_memstart returns (-1) in enu_vinit\n");
+ emu_memfree(&sc->mem, vbuf);
+ return (ENOMEM);
+ }
+ m->end = m->start + sz;
+ m->speed = 0;
+ m->b16 = 0;
+ m->stereo = 0;
+ m->running = 0;
+ m->ismaster = 1;
+ m->vol = 0xff;
+ m->buf = tmp_addr;
+ m->vbuf = vbuf;
+ m->slave = s;
+ if (s != NULL) {
+ s->start = m->start;
+ s->end = m->end;
+ s->speed = 0;
+ s->b16 = 0;
+ s->stereo = 0;
+ s->running = 0;
+ s->ismaster = 0;
+ s->vol = m->vol;
+ s->buf = m->buf;
+ s->vbuf = NULL;
+ s->slave = NULL;
+ }
+ return (0);
+}
+
+void
+emu_vsetup(struct emu_voice *v, int fmt, int spd)
+{
+ if (fmt) {
+ v->b16 = (fmt & AFMT_16BIT) ? 1 : 0;
+ v->stereo = (fmt & AFMT_STEREO) ? 1 : 0;
+ if (v->slave != NULL) {
+ v->slave->b16 = v->b16;
+ v->slave->stereo = v->stereo;
+ }
+ }
+ if (spd) {
+ v->speed = spd;
+ if (v->slave != NULL)
+ v->slave->speed = v->speed;
+ }
+}
+
+void
+emu_vroute(struct emu_sc_info *sc, struct emu_route *rt, struct emu_voice *v)
+{
+ int i;
+
+ for (i = 0; i < 8; i++) {
+ v->routing[i] = rt->routing_left[i];
+ v->amounts[i] = rt->amounts_left[i];
+ }
+ if ((v->stereo) && (v->ismaster == 0))
+ for (i = 0; i < 8; i++) {
+ v->routing[i] = rt->routing_right[i];
+ v->amounts[i] = rt->amounts_right[i];
+ }
+
+ if ((v->stereo) && (v->slave != NULL))
+ emu_vroute(sc, rt, v->slave);
+}
+
+void
+emu_vwrite(struct emu_sc_info *sc, struct emu_voice *v)
+{
+ int s;
+ uint32_t start, val, silent_page;
+
+ s = (v->stereo ? 1 : 0) + (v->b16 ? 1 : 0);
+
+ v->sa = v->start >> s;
+ v->ea = v->end >> s;
+
+
+ if (v->stereo) {
+ emu_wrptr(sc, v->vnum, CPF, CPF_STEREO_MASK);
+ } else {
+ emu_wrptr(sc, v->vnum, CPF, 0);
+ }
+ val = v->stereo ? 28 : 30;
+ val *= v->b16 ? 1 : 2;
+ start = v->sa + val;
+
+ if (sc->is_emu10k1) {
+ emu_wrptr(sc, v->vnum, FXRT, ((v->routing[3] << 12) |
+ (v->routing[2] << 8) |
+ (v->routing[1] << 4) |
+ (v->routing[0] << 0)) << 16);
+ } else {
+ emu_wrptr(sc, v->vnum, A_FXRT1, (v->routing[3] << 24) |
+ (v->routing[2] << 16) |
+ (v->routing[1] << 8) |
+ (v->routing[0] << 0));
+ emu_wrptr(sc, v->vnum, A_FXRT2, (v->routing[7] << 24) |
+ (v->routing[6] << 16) |
+ (v->routing[5] << 8) |
+ (v->routing[4] << 0));
+ emu_wrptr(sc, v->vnum, A_SENDAMOUNTS, (v->amounts[7] << 24) |
+ (v->amounts[6] << 26) |
+ (v->amounts[5] << 8) |
+ (v->amounts[4] << 0));
+ }
+ emu_wrptr(sc, v->vnum, PTRX, (v->amounts[0] << 8) | (v->amounts[1] << 0));
+ emu_wrptr(sc, v->vnum, DSL, v->ea | (v->amounts[3] << 24));
+ emu_wrptr(sc, v->vnum, PSST, v->sa | (v->amounts[2] << 24));
+
+ emu_wrptr(sc, v->vnum, CCCA, start | (v->b16 ? 0 : CCCA_8BITSELECT));
+ emu_wrptr(sc, v->vnum, Z1, 0);
+ emu_wrptr(sc, v->vnum, Z2, 0);
+
+ silent_page = ((uint32_t) (sc->mem.silent_page_addr) << 1) | MAP_PTI_MASK;
+ emu_wrptr(sc, v->vnum, MAPA, silent_page);
+ emu_wrptr(sc, v->vnum, MAPB, silent_page);
+
+ emu_wrptr(sc, v->vnum, CVCF, CVCF_CURRENTFILTER_MASK);
+ emu_wrptr(sc, v->vnum, VTFT, VTFT_FILTERTARGET_MASK);
+ emu_wrptr(sc, v->vnum, ATKHLDM, 0);
+ emu_wrptr(sc, v->vnum, DCYSUSM, DCYSUSM_DECAYTIME_MASK);
+ emu_wrptr(sc, v->vnum, LFOVAL1, 0x8000);
+ emu_wrptr(sc, v->vnum, LFOVAL2, 0x8000);
+ emu_wrptr(sc, v->vnum, FMMOD, 0);
+ emu_wrptr(sc, v->vnum, TREMFRQ, 0);
+ emu_wrptr(sc, v->vnum, FM2FRQ2, 0);
+ emu_wrptr(sc, v->vnum, ENVVAL, 0x8000);
+
+ emu_wrptr(sc, v->vnum, ATKHLDV, ATKHLDV_HOLDTIME_MASK | ATKHLDV_ATTACKTIME_MASK);
+ emu_wrptr(sc, v->vnum, ENVVOL, 0x8000);
+
+ emu_wrptr(sc, v->vnum, PEFE_FILTERAMOUNT, 0x7f);
+ emu_wrptr(sc, v->vnum, PEFE_PITCHAMOUNT, 0);
+ if ((v->stereo) && (v->slave != NULL))
+ emu_vwrite(sc, v->slave);
+}
+
+static void
+emu_vstop(struct emu_sc_info *sc, char channel, int enable)
+{
+ int reg;
+
+ reg = (channel & 0x20) ? SOLEH : SOLEL;
+ channel &= 0x1f;
+ reg |= 1 << 24;
+ reg |= channel << 16;
+ emu_wrptr(sc, 0, reg, enable);
+}
+
+void
+emu_vtrigger(struct emu_sc_info *sc, struct emu_voice *v, int go)
+{
+ uint32_t pitch_target, initial_pitch;
+ uint32_t cra, cs, ccis;
+ uint32_t sample, i;
+
+ if (go) {
+ cra = 64;
+ cs = v->stereo ? 4 : 2;
+ ccis = v->stereo ? 28 : 30;
+ ccis *= v->b16 ? 1 : 2;
+ sample = v->b16 ? 0x00000000 : 0x80808080;
+ for (i = 0; i < cs; i++)
+ emu_wrptr(sc, v->vnum, CD0 + i, sample);
+ emu_wrptr(sc, v->vnum, CCR_CACHEINVALIDSIZE, 0);
+ emu_wrptr(sc, v->vnum, CCR_READADDRESS, cra);
+ emu_wrptr(sc, v->vnum, CCR_CACHEINVALIDSIZE, ccis);
+
+ emu_wrptr(sc, v->vnum, IFATN, 0xff00);
+ emu_wrptr(sc, v->vnum, VTFT, 0xffffffff);
+ emu_wrptr(sc, v->vnum, CVCF, 0xffffffff);
+ emu_wrptr(sc, v->vnum, DCYSUSV, 0x00007f7f);
+ emu_vstop(sc, v->vnum, 0);
+
+ pitch_target = emu_rate_to_linearpitch(v->speed);
+ initial_pitch = emu_rate_to_pitch(v->speed) >> 8;
+ emu_wrptr(sc, v->vnum, PTRX_PITCHTARGET, pitch_target);
+ emu_wrptr(sc, v->vnum, CPF_CURRENTPITCH, pitch_target);
+ emu_wrptr(sc, v->vnum, IP, initial_pitch);
+ } else {
+ emu_wrptr(sc, v->vnum, PTRX_PITCHTARGET, 0);
+ emu_wrptr(sc, v->vnum, CPF_CURRENTPITCH, 0);
+ emu_wrptr(sc, v->vnum, IFATN, 0xffff);
+ emu_wrptr(sc, v->vnum, VTFT, 0x0000ffff);
+ emu_wrptr(sc, v->vnum, CVCF, 0x0000ffff);
+ emu_wrptr(sc, v->vnum, IP, 0);
+ emu_vstop(sc, v->vnum, 1);
+ }
+ if ((v->stereo) && (v->slave != NULL))
+ emu_vtrigger(sc, v->slave, go);
+}
+
+int
+emu_vpos(struct emu_sc_info *sc, struct emu_voice *v)
+{
+ int s, ptr;
+
+ s = (v->b16 ? 1 : 0) + (v->stereo ? 1 : 0);
+ ptr = (emu_rdptr(sc, v->vnum, CCCA_CURRADDR) - (v->start >> s)) << s;
+ return (ptr & ~0x0000001f);
+}
+
+
+/* fx */
+static void
+emu_wrefx(struct emu_sc_info *sc, unsigned int pc, unsigned int data)
+{
+ emu_wrptr(sc, 0, sc->code_base + pc, data);
+}
+
+
+static void
+emu_addefxop(struct emu_sc_info *sc, unsigned int op, unsigned int z, unsigned int w, unsigned int x, unsigned int y, uint32_t * pc)
+{
+ if ((*pc) + 1 > sc->code_size) {
+ device_printf(sc->dev, "DSP CODE OVERRUN: attept to write past code_size (pc=%d)\n", (*pc));
+ return;
+ }
+ emu_wrefx(sc, (*pc) * 2, (x << sc->high_operand_shift) | y);
+ emu_wrefx(sc, (*pc) * 2 + 1, (op << sc->opcode_shift) | (z << sc->high_operand_shift) | w);
+ (*pc)++;
+}
+
+static int
+sysctl_emu_mixer_control(SYSCTL_HANDLER_ARGS)
+{
+ struct emu_sc_info *sc;
+ int mixer_id;
+ int new_vol;
+ int err;
+
+ sc = arg1;
+ mixer_id = arg2;
+
+ new_vol = emumix_get_volume(sc, mixer_id);
+ err = sysctl_handle_int(oidp, &new_vol, 0, req);
+
+ if (err || req->newptr == NULL)
+ return (err);
+ if (new_vol < 0 || new_vol > 100)
+ return (EINVAL);
+ emumix_set_volume(sc, mixer_id, new_vol);
+
+ return (0);
+}
+
+static int
+emu_addefxmixer(struct emu_sc_info *sc, const char *mix_name, const int mix_id, uint32_t defvolume)
+{
+ int volgpr;
+ char sysctl_name[32];
+
+ volgpr = emu_rm_gpr_alloc(sc->rm, 1);
+ emumix_set_fxvol(sc, volgpr, defvolume);
+ /*
+ * Mixer controls with NULL mix_name are handled
+ * by AC97 emulation code or PCM mixer.
+ */
+ if (mix_name != NULL) {
+ /*
+ * Temporary sysctls should start with underscore,
+ * see freebsd-current mailing list, emu10kx driver
+ * discussion around 2006-05-24.
+ */
+ snprintf(sysctl_name, 32, "_%s", mix_name);
+ SYSCTL_ADD_PROC(sc->ctx,
+ SYSCTL_CHILDREN(sc->root),
+ OID_AUTO, sysctl_name,
+ CTLTYPE_INT | CTLFLAG_RW, sc, mix_id,
+ sysctl_emu_mixer_control, "I", "");
+ }
+
+ return (volgpr);
+}
+
+static int
+sysctl_emu_digitalswitch_control(SYSCTL_HANDLER_ARGS)
+{
+ struct emu_sc_info *sc;
+ int new_val;
+ int err;
+
+ sc = arg1;
+
+ new_val = (sc->mode == MODE_DIGITAL) ? 1 : 0;
+ err = sysctl_handle_int(oidp, &new_val, 0, req);
+
+ if (err || req->newptr == NULL)
+ return (err);
+ if (new_val < 0 || new_val > 1)
+ return (EINVAL);
+
+ switch (new_val) {
+ case 0:
+ emumix_set_mode(sc, MODE_ANALOG);
+ break;
+ case 1:
+ emumix_set_mode(sc, MODE_DIGITAL);
+ break;
+ }
+ return (0);
+}
+
+static void
+emu_digitalswitch(struct emu_sc_info *sc)
+{
+ /* XXX temporary? */
+ SYSCTL_ADD_PROC(sc->ctx,
+ SYSCTL_CHILDREN(sc->root),
+ OID_AUTO, "_digital",
+ CTLTYPE_INT | CTLFLAG_RW, sc, 0,
+ sysctl_emu_digitalswitch_control, "I", "Enable digital output");
+
+ return;
+}
+
+/*
+ * Allocate cache GPRs that will hold mixed output channels
+ * and clear it on every DSP run.
+ */
+#define EFX_CACHE(CACHE_IDX) do { \
+ sc->cache_gpr[CACHE_IDX] = emu_rm_gpr_alloc(sc->rm, 1); \
+ emu_addefxop(sc, ACC3, \
+ GPR(sc->cache_gpr[CACHE_IDX]), \
+ DSP_CONST(0), \
+ DSP_CONST(0), \
+ DSP_CONST(0), \
+ &pc); \
+} while (0)
+
+/* Allocate GPR for volume control and route sound: OUT = OUT + IN * VOL */
+#define EFX_ROUTE(TITLE, INP_NR, IN_GPR_IDX, OUT_CACHE_IDX, DEF) do { \
+ sc->mixer_gpr[IN_GPR_IDX] = emu_addefxmixer(sc, TITLE, IN_GPR_IDX, DEF); \
+ sc->mixer_volcache[IN_GPR_IDX] = DEF; \
+ emu_addefxop(sc, MACS, \
+ GPR(sc->cache_gpr[OUT_CACHE_IDX]), \
+ GPR(sc->cache_gpr[OUT_CACHE_IDX]), \
+ INP_NR, \
+ GPR(sc->mixer_gpr[IN_GPR_IDX]), \
+ &pc); \
+} while (0)
+
+/* allocate GPR, OUT = IN * VOL */
+#define EFX_OUTPUT(TITLE, OUT_CACHE_IDX, OUT_GPR_IDX, OUTP_NR, DEF) do { \
+ sc->mixer_gpr[OUT_GPR_IDX] = emu_addefxmixer(sc, TITLE, OUT_GPR_IDX, DEF); \
+ sc->mixer_volcache[OUT_GPR_IDX] = DEF; \
+ emu_addefxop(sc, MACS, \
+ OUTP(OUTP_NR), \
+ DSP_CONST(0), \
+ GPR(sc->cache_gpr[OUT_CACHE_IDX]), \
+ GPR(sc->mixer_gpr[OUT_GPR_IDX]), \
+ &pc); \
+} while (0)
+
+/* like EFX_OUTPUT, but don't allocate mixer gpr */
+#define EFX_OUTPUTD(OUT_CACHE_IDX, OUT_GPR_IDX, OUTP_NR) do { \
+ emu_addefxop(sc, MACS, \
+ OUTP(OUTP_NR), \
+ DSP_CONST(0), \
+ GPR(sc->cache_gpr[OUT_CACHE_IDX]), \
+ GPR(sc->mixer_gpr[OUT_GPR_IDX]), \
+ &pc); \
+} while (0)
+
+/* skip next OPCOUNT instructions if FLAG != 0 */
+#define EFX_SKIP(OPCOUNT, FLAG_GPR) do { \
+ emu_addefxop(sc, MACS, \
+ DSP_CONST(0), \
+ GPR(sc->mute_gpr[FLAG_GPR]), \
+ DSP_CONST(0), \
+ DSP_CONST(0), \
+ &pc); \
+ emu_addefxop(sc, SKIP, \
+ DSP_CCR, \
+ DSP_CCR, \
+ COND_NEQ_ZERO, \
+ OPCOUNT, \
+ &pc); \
+} while (0)
+
+#define EFX_COPY(TO, FROM) do { \
+ emu_addefxop(sc, ACC3, \
+ TO, \
+ DSP_CONST(0), \
+ DSP_CONST(0), \
+ FROM, \
+ &pc); \
+} while (0)
+
+
+static void
+emu_initefx(struct emu_sc_info *sc)
+{
+ unsigned int i;
+ uint32_t pc;
+
+ /* stop DSP */
+ if (sc->is_emu10k1) {
+ emu_wrptr(sc, 0, DBG, EMU10K1_DBG_SINGLE_STEP);
+ } else {
+ emu_wrptr(sc, 0, A_DBG, A_DBG_SINGLE_STEP);
+ }
+
+ /* code size is in instructions */
+ pc = 0;
+ for (i = 0; i < sc->code_size; i++) {
+ if (sc->is_emu10k1) {
+ emu_addefxop(sc, ACC3, DSP_CONST(0x0), DSP_CONST(0x0), DSP_CONST(0x0), DSP_CONST(0x0), &pc);
+ } else {
+ emu_addefxop(sc, SKIP, DSP_CONST(0x0), DSP_CONST(0x0), DSP_CONST(0xf), DSP_CONST(0x0), &pc);
+ }
+ }
+
+ /* allocate GPRs for mute switches (EFX_SKIP). Mute by default */
+ for (i = 0; i < NUM_MUTE; i++) {
+ sc->mute_gpr[i] = emu_rm_gpr_alloc(sc->rm, 1);
+ emumix_set_gpr(sc, sc->mute_gpr[i], 1);
+ }
+ emu_digitalswitch(sc);
+
+ pc = 0;
+
+ /*
+ * DSP code below is not good, because:
+ * 1. It can be written smaller, if it can use DSP accumulator register
+ * instead of cache_gpr[].
+ * 2. It can be more careful when volume is 100%, because in DSP
+ * x*0x7fffffff may not be equal to x !
+ */
+
+ /* clean outputs */
+ for (i = 0; i < 16 ; i++) {
+ emu_addefxop(sc, ACC3, OUTP(i), DSP_CONST(0), DSP_CONST(0), DSP_CONST(0), &pc);
+ }
+
+
+ if (sc->is_emu10k1) {
+ EFX_CACHE(C_FRONT_L);
+ EFX_CACHE(C_FRONT_R);
+ EFX_CACHE(C_REC_L);
+ EFX_CACHE(C_REC_R);
+
+ /* fx0 to front/record, 100%/muted by default */
+ EFX_ROUTE("pcm_front_l", FX(0), M_FX0_FRONT_L, C_FRONT_L, 100);
+ EFX_ROUTE("pcm_front_r", FX(1), M_FX1_FRONT_R, C_FRONT_R, 100);
+ EFX_ROUTE(NULL, FX(0), M_FX0_REC_L, C_REC_L, 0);
+ EFX_ROUTE(NULL, FX(1), M_FX1_REC_R, C_REC_R, 0);
+
+ /* in0, from AC97 codec output */
+ EFX_ROUTE("ac97_front_l", INP(IN_AC97_L), M_IN0_FRONT_L, C_FRONT_L, 0);
+ EFX_ROUTE("ac97_front_r", INP(IN_AC97_R), M_IN0_FRONT_R, C_FRONT_R, 0);
+ EFX_ROUTE("ac97_rec_l", INP(IN_AC97_L), M_IN0_REC_L, C_REC_L, 0);
+ EFX_ROUTE("ac97_rec_r", INP(IN_AC97_R), M_IN0_REC_R, C_REC_R, 0);
+
+ /* in1, from CD S/PDIF */
+ /* XXX EFX_SKIP 4 assumes that each EFX_ROUTE is one DSP op */
+ EFX_SKIP(4, CDSPDIFMUTE);
+ EFX_ROUTE(NULL, INP(IN_SPDIF_CD_L), M_IN1_FRONT_L, C_FRONT_L, 0);
+ EFX_ROUTE(NULL, INP(IN_SPDIF_CD_R), M_IN1_FRONT_R, C_FRONT_R, 0);
+ EFX_ROUTE(NULL, INP(IN_SPDIF_CD_L), M_IN1_REC_L, C_REC_L, 0);
+ EFX_ROUTE(NULL, INP(IN_SPDIF_CD_R), M_IN1_REC_R, C_REC_R, 0);
+
+ if (sc->dbg_level > 0) {
+ /* in2, ZoomVide (???) */
+ EFX_ROUTE("zoom_front_l", INP(IN_ZOOM_L), M_IN2_FRONT_L, C_FRONT_L, 0);
+ EFX_ROUTE("zoom_front_r", INP(IN_ZOOM_R), M_IN2_FRONT_R, C_FRONT_R, 0);
+ EFX_ROUTE("zoom_rec_l", INP(IN_ZOOM_L), M_IN2_REC_L, C_REC_L, 0);
+ EFX_ROUTE("zoom_rec_r", INP(IN_ZOOM_R), M_IN2_REC_R, C_REC_R, 0);
+ }
+
+ /* in3, TOSLink */
+ EFX_ROUTE(NULL, INP(IN_TOSLINK_L), M_IN3_FRONT_L, C_FRONT_L, 0);
+ EFX_ROUTE(NULL, INP(IN_TOSLINK_R), M_IN3_FRONT_R, C_FRONT_R, 0);
+ EFX_ROUTE(NULL, INP(IN_TOSLINK_L), M_IN3_REC_L, C_REC_L, 0);
+ EFX_ROUTE(NULL, INP(IN_TOSLINK_R), M_IN3_REC_R, C_REC_R, 0);
+ /* in4, LineIn */
+ EFX_ROUTE(NULL, INP(IN_LINE1_L), M_IN4_FRONT_L, C_FRONT_L, 0);
+ EFX_ROUTE(NULL, INP(IN_LINE1_R), M_IN4_FRONT_R, C_FRONT_R, 0);
+ EFX_ROUTE(NULL, INP(IN_LINE1_L), M_IN4_REC_L, C_REC_L, 0);
+ EFX_ROUTE(NULL, INP(IN_LINE1_R), M_IN4_REC_R, C_REC_R, 0);
+
+ /* in5, on-card S/PDIF */
+ EFX_ROUTE(NULL, INP(IN_COAX_SPDIF_L), M_IN5_FRONT_L, C_FRONT_L, 0);
+ EFX_ROUTE(NULL, INP(IN_COAX_SPDIF_R), M_IN5_FRONT_R, C_FRONT_R, 0);
+ EFX_ROUTE(NULL, INP(IN_COAX_SPDIF_L), M_IN5_REC_L, C_REC_L, 0);
+ EFX_ROUTE(NULL, INP(IN_COAX_SPDIF_R), M_IN5_REC_R, C_REC_R, 0);
+
+ /* in6, Line2 on Live!Drive */
+ EFX_ROUTE(NULL, INP(IN_LINE2_L), M_IN6_FRONT_L, C_FRONT_L, 0);
+ EFX_ROUTE(NULL, INP(IN_LINE2_R), M_IN6_FRONT_R, C_FRONT_R, 0);
+ EFX_ROUTE(NULL, INP(IN_LINE2_L), M_IN6_REC_L, C_REC_L, 0);
+ EFX_ROUTE(NULL, INP(IN_LINE2_R), M_IN6_REC_R, C_REC_R, 0);
+
+ if (sc->dbg_level > 0) {
+ /* in7, unknown */
+ EFX_ROUTE("in7_front_l", INP(0xE), M_IN7_FRONT_L, C_FRONT_L, 0);
+ EFX_ROUTE("in7_front_r", INP(0xF), M_IN7_FRONT_R, C_FRONT_R, 0);
+ EFX_ROUTE("in7_rec_l", INP(0xE), M_IN7_REC_L, C_REC_L, 0);
+ EFX_ROUTE("in7_rec_r", INP(0xF), M_IN7_REC_R, C_REC_R, 0);
+ }
+
+ /* analog and digital */
+ EFX_OUTPUT("master_front_l", C_FRONT_L, M_MASTER_FRONT_L, OUT_AC97_L, 100);
+ EFX_OUTPUT("master_front_r", C_FRONT_R, M_MASTER_FRONT_R, OUT_AC97_R, 100);
+ /* S/PDIF */
+ EFX_OUTPUTD(C_FRONT_L, M_MASTER_FRONT_L, OUT_TOSLINK_L);
+ EFX_OUTPUTD(C_FRONT_R, M_MASTER_FRONT_R, OUT_TOSLINK_R);
+ /* Headphones */
+ EFX_OUTPUTD(C_FRONT_L, M_MASTER_FRONT_L, OUT_HEADPHONE_L);
+ EFX_OUTPUTD(C_FRONT_R, M_MASTER_FRONT_R, OUT_HEADPHONE_R);
+
+ /* rec output to "ADC" */
+ EFX_OUTPUT("master_rec_l", C_REC_L, M_MASTER_REC_L, OUT_ADC_REC_L, 100);
+ EFX_OUTPUT("master_rec_r", C_REC_R, M_MASTER_REC_R, OUT_ADC_REC_R, 100);
+
+ if (!(sc->mch_disabled)) {
+ /*
+ * Additional channel volume is controlled by mixer in
+ * emu_dspmixer_set() in -pcm.c
+ */
+
+ /* fx2/3 (pcm1) to rear */
+ EFX_CACHE(C_REAR_L);
+ EFX_CACHE(C_REAR_R);
+ EFX_ROUTE(NULL, FX(2), M_FX2_REAR_L, C_REAR_L, 100);
+ EFX_ROUTE(NULL, FX(3), M_FX3_REAR_R, C_REAR_R, 100);
+
+ EFX_OUTPUT(NULL, C_REAR_L, M_MASTER_REAR_L, OUT_REAR_L, 100);
+ EFX_OUTPUT(NULL, C_REAR_R, M_MASTER_REAR_R, OUT_REAR_R, 100);
+ if (sc->has_51) {
+ /* fx4 (pcm2) to center */
+ EFX_CACHE(C_CENTER);
+ EFX_ROUTE(NULL, FX(4), M_FX4_CENTER, C_CENTER, 100);
+ EFX_OUTPUT(NULL, C_CENTER, M_MASTER_CENTER, OUT_D_CENTER, 100);
+
+ /* XXX in digital mode (default) this should be muted because
+ this output is shared with digital out */
+ EFX_SKIP(1, ANALOGMUTE);
+ EFX_OUTPUTD(C_CENTER, M_MASTER_CENTER, OUT_A_CENTER);
+
+ /* fx5 (pcm3) to sub */
+ EFX_CACHE(C_SUB);
+ EFX_ROUTE(NULL, FX(5), M_FX5_SUBWOOFER, C_SUB, 100);
+ EFX_OUTPUT(NULL, C_SUB, M_MASTER_SUBWOOFER, OUT_D_SUB, 100);
+
+ /* XXX in digital mode (default) this should be muted because
+ this output is shared with digital out */
+ EFX_SKIP(1, ANALOGMUTE);
+ EFX_OUTPUTD(C_SUB, M_MASTER_SUBWOOFER, OUT_A_SUB);
+
+ }
+ } else {
+ /* SND_EMU10KX_MULTICHANNEL_DISABLED */
+ EFX_OUTPUT(NULL, C_FRONT_L, M_MASTER_REAR_L, OUT_REAR_L, 57); /* 75%*75% */
+ EFX_OUTPUT(NULL, C_FRONT_R, M_MASTER_REAR_R, OUT_REAR_R, 57); /* 75%*75% */
+
+#if 0
+ /* XXX 5.1 does not work */
+
+ if (sc->has_51) {
+ /* (fx0+fx1)/2 to center */
+ EFX_CACHE(C_CENTER);
+ emu_addefxop(sc, MACS,
+ GPR(sc->cache_gpr[C_CENTER]),
+ GPR(sc->cache_gpr[C_CENTER]),
+ DSP_CONST(0xd), /* = 1/2 */
+ GPR(sc->cache_gpr[C_FRONT_L]),
+ &pc);
+ emu_addefxop(sc, MACS,
+ GPR(sc->cache_gpr[C_CENTER]),
+ GPR(sc->cache_gpr[C_CENTER]),
+ DSP_CONST(0xd), /* = 1/2 */
+ GPR(sc->cache_gpr[C_FRONT_R]),
+ &pc);
+ EFX_OUTPUT(NULL, C_CENTER, M_MASTER_CENTER, OUT_D_CENTER, 100);
+
+ /* XXX in digital mode (default) this should be muted because
+ this output is shared with digital out */
+ EFX_SKIP(1, ANALOGMUTE);
+ EFX_OUTPUTD(C_CENTER, M_MASTER_CENTER, OUT_A_CENTER);
+
+ /* (fx0+fx1)/2 to sub */
+ EFX_CACHE(C_SUB);
+ emu_addefxop(sc, MACS,
+ GPR(sc->cache_gpr[C_CENTER]),
+ GPR(sc->cache_gpr[C_CENTER]),
+ DSP_CONST(0xd), /* = 1/2 */
+ GPR(sc->cache_gpr[C_FRONT_L]),
+ &pc);
+ emu_addefxop(sc, MACS,
+ GPR(sc->cache_gpr[C_CENTER]),
+ GPR(sc->cache_gpr[C_CENTER]),
+ DSP_CONST(0xd), /* = 1/2 */
+ GPR(sc->cache_gpr[C_FRONT_R]),
+ &pc);
+ /* XXX add lowpass filter here */
+
+ EFX_OUTPUT(NULL, C_SUB, M_MASTER_SUBWOOFER, OUT_D_SUB, 100);
+
+ /* XXX in digital mode (default) this should be muted because
+ this output is shared with digital out */
+ EFX_SKIP(1, ANALOGMUTE);
+ EFX_OUTPUTD(C_SUB, M_MASTER_SUBWOOFER, OUT_A_SUB);
+ }
+#endif
+ } /* !mch_disabled */
+ if (sc->mch_rec) {
+ /*
+ * MCH RECORDING , hight 16 slots. On 5.1 cards first 4 slots
+ * are used as outputs and already filled with data
+ */
+ /*
+ * XXX On Live! cards stream does not begin at zero offset.
+ * It can be HW, driver or sound buffering problem.
+ * Use sync substream (offset 0x3E) to let userland find
+ * correct data.
+ */
+
+ /*
+ * Substream map (in byte offsets, each substream is 2 bytes):
+ * 0x00..0x1E - outputs
+ * 0x20..0x3E - FX, inputs ans sync stream
+ */
+
+ /* First 2 channels (offset 0x20,0x22) are empty */
+ for(i = (sc->has_51 ? 2 : 0); i < 2; i++)
+ EFX_COPY(FX2(i), DSP_CONST(0));
+
+ /* PCM Playback monitoring, offset 0x24..0x2A */
+ for(i = 0; i < 4; i++)
+ EFX_COPY(FX2(i+2), FX(i));
+
+ /* Copy of some inputs, offset 0x2C..0x3C */
+ for(i = 0; i < 9; i++)
+ EFX_COPY(FX2(i+8), INP(i));
+
+ /* sync data (0xc0de, offset 0x3E) */
+ sc->dummy_gpr = emu_rm_gpr_alloc(sc->rm, 1);
+ emumix_set_gpr(sc, sc->dummy_gpr, 0xc0de0000);
+
+ EFX_COPY(FX2(15), GPR(sc->dummy_gpr));
+ } /* mch_rec */
+ } else /* emu10k2 and later */ {
+ EFX_CACHE(C_FRONT_L);
+ EFX_CACHE(C_FRONT_R);
+ EFX_CACHE(C_REC_L);
+ EFX_CACHE(C_REC_R);
+
+ /* fx0 to front/record, 100%/muted by default */
+ /*
+ * FRONT_[L|R] is controlled by AC97 emulation in
+ * emu_ac97_[read|write]_emulation in -pcm.c
+ */
+ EFX_ROUTE(NULL, FX(0), M_FX0_FRONT_L, C_FRONT_L, 100);
+ EFX_ROUTE(NULL, FX(1), M_FX1_FRONT_R, C_FRONT_R, 100);
+ EFX_ROUTE(NULL, FX(0), M_FX0_REC_L, C_REC_L, 0);
+ EFX_ROUTE(NULL, FX(1), M_FX1_REC_R, C_REC_R, 0);
+
+ /* in0, from AC97 codec output */
+ EFX_ROUTE(NULL, INP(A_IN_AC97_L), M_IN0_FRONT_L, C_FRONT_L, 100);
+ EFX_ROUTE(NULL, INP(A_IN_AC97_R), M_IN0_FRONT_R, C_FRONT_R, 100);
+ EFX_ROUTE(NULL, INP(A_IN_AC97_L), M_IN0_REC_L, C_REC_L, 0);
+ EFX_ROUTE(NULL, INP(A_IN_AC97_R), M_IN0_REC_R, C_REC_R, 0);
+
+ /* in1, from CD S/PDIF */
+ EFX_ROUTE(NULL, INP(A_IN_SPDIF_CD_L), M_IN1_FRONT_L, C_FRONT_L, 0);
+ EFX_ROUTE(NULL, INP(A_IN_SPDIF_CD_R), M_IN1_FRONT_R, C_FRONT_R, 0);
+ EFX_ROUTE(NULL, INP(A_IN_SPDIF_CD_L), M_IN1_REC_L, C_REC_L, 0);
+ EFX_ROUTE(NULL, INP(A_IN_SPDIF_CD_R), M_IN1_REC_R, C_REC_R, 0);
+
+ /* in2, optical & coax S/PDIF on AudigyDrive*/
+ /* XXX Should be muted when GPRSCS valid stream == 0 */
+ EFX_ROUTE(NULL, INP(A_IN_O_SPDIF_L), M_IN2_FRONT_L, C_FRONT_L, 0);
+ EFX_ROUTE(NULL, INP(A_IN_O_SPDIF_R), M_IN2_FRONT_R, C_FRONT_R, 0);
+ EFX_ROUTE(NULL, INP(A_IN_O_SPDIF_L), M_IN2_REC_L, C_REC_L, 0);
+ EFX_ROUTE(NULL, INP(A_IN_O_SPDIF_R), M_IN2_REC_R, C_REC_R, 0);
+
+ if (sc->dbg_level > 0) {
+ /* in3, unknown */
+ EFX_ROUTE("in3_front_l", INP(0x6), M_IN3_FRONT_L, C_FRONT_L, 0);
+ EFX_ROUTE("in3_front_r", INP(0x7), M_IN3_FRONT_R, C_FRONT_R, 0);
+ EFX_ROUTE("in3_rec_l", INP(0x6), M_IN3_REC_L, C_REC_L, 0);
+ EFX_ROUTE("in3_rec_r", INP(0x7), M_IN3_REC_R, C_REC_R, 0);
+ }
+
+ /* in4, LineIn 2 on AudigyDrive */
+ EFX_ROUTE(NULL, INP(A_IN_LINE2_L), M_IN4_FRONT_L, C_FRONT_L, 0);
+ EFX_ROUTE(NULL, INP(A_IN_LINE2_R), M_IN4_FRONT_R, C_FRONT_R, 0);
+ EFX_ROUTE(NULL, INP(A_IN_LINE2_L), M_IN4_REC_L, C_REC_L, 0);
+ EFX_ROUTE(NULL, INP(A_IN_LINE2_R), M_IN4_REC_R, C_REC_R, 0);
+
+ /* in5, on-card S/PDIF */
+ EFX_ROUTE(NULL, INP(A_IN_R_SPDIF_L), M_IN5_FRONT_L, C_FRONT_L, 0);
+ EFX_ROUTE(NULL, INP(A_IN_R_SPDIF_R), M_IN5_FRONT_R, C_FRONT_R, 0);
+ EFX_ROUTE(NULL, INP(A_IN_R_SPDIF_L), M_IN5_REC_L, C_REC_L, 0);
+ EFX_ROUTE(NULL, INP(A_IN_R_SPDIF_R), M_IN5_REC_R, C_REC_R, 0);
+
+ /* in6, AUX2 on AudigyDrive */
+ EFX_ROUTE(NULL, INP(A_IN_AUX2_L), M_IN6_FRONT_L, C_FRONT_L, 0);
+ EFX_ROUTE(NULL, INP(A_IN_AUX2_R), M_IN6_FRONT_R, C_FRONT_R, 0);
+ EFX_ROUTE(NULL, INP(A_IN_AUX2_L), M_IN6_REC_L, C_REC_L, 0);
+ EFX_ROUTE(NULL, INP(A_IN_AUX2_R), M_IN6_REC_R, C_REC_R, 0);
+
+ if (sc->dbg_level > 0) {
+ /* in7, unknown */
+ EFX_ROUTE("in7_front_l", INP(0xE), M_IN7_FRONT_L, C_FRONT_L, 0);
+ EFX_ROUTE("in7_front_r", INP(0xF), M_IN7_FRONT_R, C_FRONT_R, 0);
+ EFX_ROUTE("in7_rec_l", INP(0xE), M_IN7_REC_L, C_REC_L, 0);
+ EFX_ROUTE("in7_rec_r", INP(0xF), M_IN7_REC_R, C_REC_R, 0);
+ }
+
+ /* front output to headphones and alog and digital *front */
+ /* volume controlled by AC97 emulation */
+ EFX_OUTPUT(NULL, C_FRONT_L, M_MASTER_FRONT_L, A_OUT_A_FRONT_L, 100);
+ EFX_OUTPUT(NULL, C_FRONT_R, M_MASTER_FRONT_R, A_OUT_A_FRONT_R, 100);
+ EFX_OUTPUTD(C_FRONT_L, M_MASTER_FRONT_L, A_OUT_D_FRONT_L);
+ EFX_OUTPUTD(C_FRONT_R, M_MASTER_FRONT_R, A_OUT_D_FRONT_R);
+ EFX_OUTPUTD(C_FRONT_L, M_MASTER_FRONT_L, A_OUT_HPHONE_L);
+ EFX_OUTPUTD(C_FRONT_R, M_MASTER_FRONT_R, A_OUT_HPHONE_R);
+
+ /* rec output to "ADC" */
+ /* volume controlled by AC97 emulation */
+ EFX_OUTPUT(NULL, C_REC_L, M_MASTER_REC_L, A_OUT_ADC_REC_L, 100);
+ EFX_OUTPUT(NULL, C_REC_R, M_MASTER_REC_R, A_OUT_ADC_REC_R, 100);
+
+ if (!(sc->mch_disabled)) {
+ /*
+ * Additional channel volume is controlled by mixer in
+ * emu_dspmixer_set() in -pcm.c
+ */
+
+ /* fx2/3 (pcm1) to rear */
+ EFX_CACHE(C_REAR_L);
+ EFX_CACHE(C_REAR_R);
+ EFX_ROUTE(NULL, FX(2), M_FX2_REAR_L, C_REAR_L, 100);
+ EFX_ROUTE(NULL, FX(3), M_FX3_REAR_R, C_REAR_R, 100);
+
+ EFX_OUTPUT(NULL, C_REAR_L, M_MASTER_REAR_L, A_OUT_A_REAR_L, 100);
+ EFX_OUTPUT(NULL, C_REAR_R, M_MASTER_REAR_R, A_OUT_A_REAR_R, 100);
+ EFX_OUTPUTD(C_REAR_L, M_MASTER_REAR_L, A_OUT_D_REAR_L);
+ EFX_OUTPUTD(C_REAR_R, M_MASTER_REAR_R, A_OUT_D_REAR_R);
+
+ /* fx4 (pcm2) to center */
+ EFX_CACHE(C_CENTER);
+ EFX_ROUTE(NULL, FX(4), M_FX4_CENTER, C_CENTER, 100);
+ EFX_OUTPUT(NULL, C_CENTER, M_MASTER_CENTER, A_OUT_D_CENTER, 100);
+#if 0
+ /*
+ * XXX in digital mode (default) this should be muted
+ * because this output is shared with digital out
+ */
+ EFX_OUTPUTD(C_CENTER, M_MASTER_CENTER, A_OUT_A_CENTER);
+#endif
+ /* fx5 (pcm3) to sub */
+ EFX_CACHE(C_SUB);
+ EFX_ROUTE(NULL, FX(5), M_FX5_SUBWOOFER, C_SUB, 100);
+ EFX_OUTPUT(NULL, C_SUB, M_MASTER_SUBWOOFER, A_OUT_D_SUB, 100);
+#if 0
+ /*
+ * XXX in digital mode (default) this should be muted
+ * because this output is shared with digital out
+ */
+ EFX_OUTPUTD(C_SUB, M_MASTER_SUBWOOFER, A_OUT_A_SUB);
+#endif
+ if (sc->has_71) {
+ /* XXX this will broke headphones on AudigyDrive */
+ /* fx6/7 (pcm4) to side */
+ EFX_CACHE(C_SIDE_L);
+ EFX_CACHE(C_SIDE_R);
+ EFX_ROUTE(NULL, FX(6), M_FX6_SIDE_L, C_SIDE_L, 100);
+ EFX_ROUTE(NULL, FX(7), M_FX7_SIDE_R, C_SIDE_R, 100);
+ EFX_OUTPUT(NULL, C_SIDE_L, M_MASTER_SIDE_L, A_OUT_A_SIDE_L, 100);
+ EFX_OUTPUT(NULL, C_SIDE_R, M_MASTER_SIDE_R, A_OUT_A_SIDE_R, 100);
+ EFX_OUTPUTD(C_SIDE_L, M_MASTER_SIDE_L, A_OUT_D_SIDE_L);
+ EFX_OUTPUTD(C_SIDE_R, M_MASTER_SIDE_R, A_OUT_D_SIDE_R);
+ }
+ } else { /* mch_disabled */
+ EFX_OUTPUTD(C_FRONT_L, M_MASTER_FRONT_L, A_OUT_A_REAR_L);
+ EFX_OUTPUTD(C_FRONT_R, M_MASTER_FRONT_R, A_OUT_A_REAR_R);
+
+ EFX_OUTPUTD(C_FRONT_L, M_MASTER_FRONT_L, A_OUT_D_REAR_L);
+ EFX_OUTPUTD(C_FRONT_R, M_MASTER_FRONT_R, A_OUT_D_REAR_R);
+
+ if (sc->has_51) {
+ /* (fx0+fx1)/2 to center */
+ EFX_CACHE(C_CENTER);
+ emu_addefxop(sc, MACS,
+ GPR(sc->cache_gpr[C_CENTER]),
+ GPR(sc->cache_gpr[C_CENTER]),
+ DSP_CONST(0xd), /* = 1/2 */
+ GPR(sc->cache_gpr[C_FRONT_L]),
+ &pc);
+ emu_addefxop(sc, MACS,
+ GPR(sc->cache_gpr[C_CENTER]),
+ GPR(sc->cache_gpr[C_CENTER]),
+ DSP_CONST(0xd), /* = 1/2 */
+ GPR(sc->cache_gpr[C_FRONT_R]),
+ &pc);
+ EFX_OUTPUT(NULL, C_CENTER, M_MASTER_CENTER, A_OUT_D_CENTER, 100);
+
+ /* XXX in digital mode (default) this should be muted because
+ this output is shared with digital out */
+ EFX_SKIP(1, ANALOGMUTE);
+ EFX_OUTPUTD(C_CENTER, M_MASTER_CENTER, A_OUT_A_CENTER);
+
+ /* (fx0+fx1)/2 to sub */
+ EFX_CACHE(C_SUB);
+ emu_addefxop(sc, MACS,
+ GPR(sc->cache_gpr[C_SUB]),
+ GPR(sc->cache_gpr[C_SUB]),
+ DSP_CONST(0xd), /* = 1/2 */
+ GPR(sc->cache_gpr[C_FRONT_L]),
+ &pc);
+ emu_addefxop(sc, MACS,
+ GPR(sc->cache_gpr[C_SUB]),
+ GPR(sc->cache_gpr[C_SUB]),
+ DSP_CONST(0xd), /* = 1/2 */
+ GPR(sc->cache_gpr[C_FRONT_R]),
+ &pc);
+ /* XXX add lowpass filter here */
+
+ EFX_OUTPUT(NULL, C_SUB, M_MASTER_SUBWOOFER, A_OUT_D_SUB, 100);
+
+ /* XXX in digital mode (default) this should be muted because
+ this output is shared with digital out */
+ EFX_SKIP(1, ANALOGMUTE);
+ EFX_OUTPUTD(C_SUB, M_MASTER_SUBWOOFER, A_OUT_A_SUB);
+ }
+ } /* mch_disabled */
+ if (sc->mch_rec) {
+ /* MCH RECORDING, high 32 slots */
+
+ /*
+ * Stream map (in byte offsets):
+ * 0x00..0x3E - outputs
+ * 0x40..0x7E - FX, inputs
+ * each substream is 2 bytes.
+ */
+ /*
+ * XXX Audigy 2 Value cards (and, possibly,
+ * Audigy 4) write some unknown data in place of
+ * some outputs (offsets 0x20..0x3F) and one
+ * input (offset 0x7E).
+ */
+
+ /* PCM Playback monitoring, offsets 0x40..0x5E */
+ for(i = 0; i < 16; i++)
+ EFX_COPY(FX2(i), FX(i));
+
+ /* Copy of all inputs, offsets 0x60..0x7E */
+ for(i = 0; i < 16; i++)
+ EFX_COPY(FX2(i+16), INP(i));
+#if 0
+ /* XXX Audigy seems to work correct and does not need this */
+ /* sync data (0xc0de), offset 0x7E */
+ sc->dummy_gpr = emu_rm_gpr_alloc(sc->rm, 1);
+ emumix_set_gpr(sc, sc->dummy_gpr, 0xc0de0000);
+ EFX_COPY(FX2(31), GPR(sc->dummy_gpr));
+#endif
+ } /* mch_rec */
+ }
+
+ sc->routing_code_end = pc;
+
+ /* start DSP */
+ if (sc->is_emu10k1) {
+ emu_wrptr(sc, 0, DBG, 0);
+ } else {
+ emu_wrptr(sc, 0, A_DBG, 0);
+ }
+}
+
+/* /dev/em10kx */
+static d_open_t emu10kx_open;
+static d_close_t emu10kx_close;
+static d_read_t emu10kx_read;
+
+static struct cdevsw emu10kx_cdevsw = {
+ .d_open = emu10kx_open,
+ .d_close = emu10kx_close,
+ .d_read = emu10kx_read,
+ .d_name = "emu10kx",
+ .d_version = D_VERSION,
+};
+
+
+static int
+emu10kx_open(struct cdev *i_dev, int flags __unused, int mode __unused, struct thread *td __unused)
+{
+ int error;
+ struct emu_sc_info *sc;
+
+ sc = i_dev->si_drv1;
+ mtx_lock(&sc->emu10kx_lock);
+ if (sc->emu10kx_isopen) {
+ mtx_unlock(&sc->emu10kx_lock);
+ return (EBUSY);
+ }
+ sc->emu10kx_isopen = 1;
+ mtx_unlock(&sc->emu10kx_lock);
+ if (sbuf_new(&sc->emu10kx_sbuf, NULL, 4096, 0) == NULL) {
+ error = ENXIO;
+ goto out;
+ }
+ sc->emu10kx_bufptr = 0;
+ error = (emu10kx_prepare(sc, &sc->emu10kx_sbuf) > 0) ? 0 : ENOMEM;
+out:
+ if (error) {
+ mtx_lock(&sc->emu10kx_lock);
+ sc->emu10kx_isopen = 0;
+ mtx_unlock(&sc->emu10kx_lock);
+ }
+ return (error);
+}
+
+static int
+emu10kx_close(struct cdev *i_dev, int flags __unused, int mode __unused, struct thread *td __unused)
+{
+ struct emu_sc_info *sc;
+
+ sc = i_dev->si_drv1;
+
+ mtx_lock(&sc->emu10kx_lock);
+ if (!(sc->emu10kx_isopen)) {
+ mtx_unlock(&sc->emu10kx_lock);
+ return (EBADF);
+ }
+ sbuf_delete(&sc->emu10kx_sbuf);
+ sc->emu10kx_isopen = 0;
+ mtx_unlock(&sc->emu10kx_lock);
+
+ return (0);
+}
+
+static int
+emu10kx_read(struct cdev *i_dev, struct uio *buf, int flag __unused)
+{
+ int l, err;
+ struct emu_sc_info *sc;
+
+ sc = i_dev->si_drv1;
+ mtx_lock(&sc->emu10kx_lock);
+ if (!(sc->emu10kx_isopen)) {
+ mtx_unlock(&sc->emu10kx_lock);
+ return (EBADF);
+ }
+ mtx_unlock(&sc->emu10kx_lock);
+
+ l = min(buf->uio_resid, sbuf_len(&sc->emu10kx_sbuf) - sc->emu10kx_bufptr);
+ err = (l > 0) ? uiomove(sbuf_data(&sc->emu10kx_sbuf) + sc->emu10kx_bufptr, l, buf) : 0;
+ sc->emu10kx_bufptr += l;
+
+ return (err);
+}
+
+static int
+emu10kx_prepare(struct emu_sc_info *sc, struct sbuf *s)
+{
+ int i;
+
+ sbuf_printf(s, "FreeBSD EMU10Kx Audio Driver\n");
+ sbuf_printf(s, "\nHardware resource usage:\n");
+ sbuf_printf(s, "DSP General Purpose Registers: %d used, %d total\n", sc->rm->num_used, sc->rm->num_gprs);
+ sbuf_printf(s, "DSP Instruction Registers: %d used, %d total\n", sc->routing_code_end, sc->code_size);
+ sbuf_printf(s, "Card supports");
+ if (sc->has_ac97) {
+ sbuf_printf(s, " AC97 codec");
+ } else {
+ sbuf_printf(s, " NO AC97 codec");
+ }
+ if (sc->has_51) {
+ if (sc->has_71)
+ sbuf_printf(s, " and 7.1 output");
+ else
+ sbuf_printf(s, " and 5.1 output");
+ }
+ if (sc->is_emu10k1)
+ sbuf_printf(s, ", SBLive! DSP code");
+ if (sc->is_emu10k2)
+ sbuf_printf(s, ", Audigy DSP code");
+ if (sc->is_ca0102)
+ sbuf_printf(s, ", Audigy DSP code with Audigy2 hacks");
+ if (sc->is_ca0108)
+ sbuf_printf(s, ", Audigy DSP code with Audigy2Value hacks");
+ sbuf_printf(s, "\n");
+ if (sc->broken_digital)
+ sbuf_printf(s, "Digital mode unsupported\n");
+ sbuf_printf(s, "\nInstalled devices:\n");
+ for (i = 0; i < RT_COUNT; i++)
+ if (sc->pcm[i] != NULL)
+ if (device_is_attached(sc->pcm[i])) {
+ sbuf_printf(s, "%s on %s\n", device_get_desc(sc->pcm[i]), device_get_nameunit(sc->pcm[i]));
+ }
+ if (sc->midi[0] != NULL)
+ if (device_is_attached(sc->midi[0])) {
+ sbuf_printf(s, "EMU10Kx MIDI Interface\n");
+ sbuf_printf(s, "\tOn-card connector on %s\n", device_get_nameunit(sc->midi[0]));
+ }
+ if (sc->midi[1] != NULL)
+ if (device_is_attached(sc->midi[1])) {
+ sbuf_printf(s, "\tOn-Drive connector on %s\n", device_get_nameunit(sc->midi[1]));
+ }
+ if (sc->midi[0] != NULL)
+ if (device_is_attached(sc->midi[0])) {
+ sbuf_printf(s, "\tIR reciever MIDI events %s\n", sc->enable_ir ? "enabled" : "disabled");
+ }
+ sbuf_printf(s, "Card is in %s mode\n", (sc->mode == MODE_ANALOG) ? "analog" : "digital");
+
+ sbuf_finish(s);
+ return (sbuf_len(s));
+}
+
+/* INIT & UNINIT */
+static int
+emu10kx_dev_init(struct emu_sc_info *sc)
+{
+ int unit;
+
+ mtx_init(&sc->emu10kx_lock, device_get_nameunit(sc->dev), "kxdevlock", 0);
+ unit = device_get_unit(sc->dev);
+
+ sc->cdev = make_dev(&emu10kx_cdevsw, unit2minor(unit), UID_ROOT, GID_WHEEL, 0640, "emu10kx%d", unit);
+ if (sc->cdev != NULL) {
+ sc->cdev->si_drv1 = sc;
+ return (0);
+ }
+ return (ENXIO);
+}
+
+static int
+emu10kx_dev_uninit(struct emu_sc_info *sc)
+{
+ mtx_lock(&sc->emu10kx_lock);
+ if (sc->emu10kx_isopen) {
+ mtx_unlock(&sc->emu10kx_lock);
+ return (EBUSY);
+ }
+ if (sc->cdev)
+ destroy_dev(sc->cdev);
+ sc->cdev = 0;
+
+ mtx_destroy(&sc->emu10kx_lock);
+ return (0);
+}
+
+/* resource manager */
+int
+emu_rm_init(struct emu_sc_info *sc)
+{
+ int i;
+ int maxcount;
+ struct emu_rm *rm;
+
+ rm = malloc(sizeof(struct emu_rm), M_DEVBUF, M_NOWAIT | M_ZERO);
+ if (rm == NULL) {
+ return (ENOMEM);
+ }
+ sc->rm = rm;
+ rm->card = sc;
+ maxcount = sc->num_gprs;
+ rm->num_used = 0;
+ mtx_init(&(rm->gpr_lock), device_get_nameunit(sc->dev), "gpr alloc", MTX_DEF);
+ rm->num_gprs = (maxcount < EMU_MAX_GPR ? maxcount : EMU_MAX_GPR);
+ for (i = 0; i < rm->num_gprs; i++)
+ rm->allocmap[i] = 0;
+ /* pre-allocate gpr[0] */
+ rm->allocmap[0] = 1;
+ rm->last_free_gpr = 1;
+
+ return (0);
+}
+
+int
+emu_rm_uninit(struct emu_sc_info *sc)
+{
+ int i;
+
+ if (sc->dbg_level > 1) {
+ mtx_lock(&(sc->rm->gpr_lock));
+ for (i = 1; i < sc->rm->last_free_gpr; i++)
+ if (sc->rm->allocmap[i] > 0)
+ device_printf(sc->dev, "rm: gpr %d not free before uninit\n", i);
+ mtx_unlock(&(sc->rm->gpr_lock));
+ }
+
+ mtx_destroy(&(sc->rm->gpr_lock));
+ free(sc->rm, M_DEVBUF);
+ return (0);
+}
+
+static int
+emu_rm_gpr_alloc(struct emu_rm *rm, int count)
+{
+ int i, j;
+ int allocated_gpr;
+
+ allocated_gpr = rm->num_gprs;
+ /* try fast way first */
+ mtx_lock(&(rm->gpr_lock));
+ if (rm->last_free_gpr + count <= rm->num_gprs) {
+ allocated_gpr = rm->last_free_gpr;
+ rm->last_free_gpr += count;
+ rm->allocmap[allocated_gpr] = count;
+ for (i = 1; i < count; i++)
+ rm->allocmap[allocated_gpr + i] = -(count - i);
+ } else {
+ /* longer */
+ i = 0;
+ allocated_gpr = rm->num_gprs;
+ while (i < rm->last_free_gpr - count) {
+ if (rm->allocmap[i] > 0) {
+ i += rm->allocmap[i];
+ } else {
+ allocated_gpr = i;
+ for (j = 1; j < count; j++) {
+ if (rm->allocmap[i + j] != 0)
+ allocated_gpr = rm->num_gprs;
+ }
+ if (allocated_gpr == i)
+ break;
+ }
+ }
+ if (allocated_gpr + count < rm->last_free_gpr) {
+ rm->allocmap[allocated_gpr] = count;
+ for (i = 1; i < count; i++)
+ rm->allocmap[allocated_gpr + i] = -(count - i);
+
+ }
+ }
+ if (allocated_gpr == rm->num_gprs)
+ allocated_gpr = (-1);
+ if (allocated_gpr >= 0)
+ rm->num_used += count;
+ mtx_unlock(&(rm->gpr_lock));
+ return (allocated_gpr);
+}
+
+/* mixer */
+void
+emumix_set_mode(struct emu_sc_info *sc, int mode)
+{
+ uint32_t a_iocfg;
+ uint32_t hcfg;
+ uint32_t tmp;
+
+ switch (mode) {
+ case MODE_DIGITAL:
+ /* FALLTHROUGH */
+ case MODE_ANALOG:
+ break;
+ default:
+ return;
+ }
+
+ hcfg = HCFG_AUDIOENABLE | HCFG_AUTOMUTE;
+ a_iocfg = 0;
+
+ if (sc->rev >= 6)
+ hcfg |= HCFG_JOYENABLE;
+
+ if (sc->is_emu10k1)
+ hcfg |= HCFG_LOCKTANKCACHE_MASK;
+ else
+ hcfg |= HCFG_CODECFORMAT_I2S | HCFG_JOYENABLE;
+
+
+ if (mode == MODE_DIGITAL) {
+ if (sc->broken_digital) {
+ device_printf(sc->dev, "Digital mode is reported as broken on this card.\n");
+ }
+ a_iocfg |= A_IOCFG_ENABLE_DIGITAL;
+ hcfg |= HCFG_GPOUT0;
+ }
+
+ if (mode == MODE_ANALOG)
+ emumix_set_spdif_mode(sc, SPDIF_MODE_PCM);
+
+ if (sc->is_emu10k2)
+ a_iocfg |= 0x80; /* XXX */
+
+ if ((sc->is_ca0102) || (sc->is_ca0108))
+ /*
+ * Setting A_IOCFG_DISABLE_ANALOG will do opposite things
+ * on diffrerent cards.
+ * "don't disable analog outs" on Audigy 2 (ca0102/ca0108)
+ * "disable analog outs" on Audigy (emu10k2)
+ */
+ a_iocfg |= A_IOCFG_DISABLE_ANALOG;
+
+ if (sc->is_ca0108)
+ a_iocfg |= 0x20; /* XXX */
+
+ /* Mute analog center & subwoofer before mode change */
+ if (mode == MODE_DIGITAL)
+ emumix_set_gpr(sc, sc->mute_gpr[ANALOGMUTE], 1);
+
+ emu_wr(sc, HCFG, hcfg, 4);
+
+ if ((sc->is_emu10k2) || (sc->is_ca0102) || (sc->is_ca0108)) {
+ tmp = emu_rd(sc, A_IOCFG, 2);
+ tmp = a_iocfg;
+ emu_wr(sc, A_IOCFG, tmp, 2);
+ }
+
+ /* Unmute if we have changed mode to analog. */
+
+ if (mode == MODE_ANALOG)
+ emumix_set_gpr(sc, sc->mute_gpr[ANALOGMUTE], 0);
+
+ sc->mode = mode;
+}
+
+void
+emumix_set_spdif_mode(struct emu_sc_info *sc, int mode)
+{
+ uint32_t spcs;
+
+ switch (mode) {
+ case SPDIF_MODE_PCM:
+ break;
+ case SPDIF_MODE_AC3:
+ device_printf(sc->dev, "AC3 mode does not work and disabled\n");
+ return;
+ default:
+ return;
+ }
+
+ spcs = SPCS_CLKACCY_1000PPM | SPCS_SAMPLERATE_48 |
+ SPCS_CHANNELNUM_LEFT | SPCS_SOURCENUM_UNSPEC |
+ SPCS_GENERATIONSTATUS | 0x00001200 | 0x00000000 |
+ SPCS_EMPHASIS_NONE | SPCS_COPYRIGHT;
+
+ mode = SPDIF_MODE_PCM;
+
+ emu_wrptr(sc, 0, SPCS0, spcs);
+ emu_wrptr(sc, 0, SPCS1, spcs);
+ emu_wrptr(sc, 0, SPCS2, spcs);
+}
+
+#define L2L_POINTS 10
+
+static int l2l_df[L2L_POINTS] = {
+ 0x572C5CA, /* 100..90 */
+ 0x3211625, /* 90..80 */
+ 0x1CC1A76, /* 80..70 */
+ 0x108428F, /* 70..60 */
+ 0x097C70A, /* 60..50 */
+ 0x0572C5C, /* 50..40 */
+ 0x0321162, /* 40..30 */
+ 0x01CC1A7, /* 30..20 */
+ 0x0108428, /* 20..10 */
+ 0x016493D /* 10..0 */
+};
+
+static int l2l_f[L2L_POINTS] = {
+ 0x4984461A, /* 90 */
+ 0x2A3968A7, /* 80 */
+ 0x18406003, /* 70 */
+ 0x0DEDC66D, /* 60 */
+ 0x07FFFFFF, /* 50 */
+ 0x04984461, /* 40 */
+ 0x02A3968A, /* 30 */
+ 0x01840600, /* 20 */
+ 0x00DEDC66, /* 10 */
+ 0x00000000 /* 0 */
+};
+
+
+static int
+log2lin(int log_t)
+{
+ int lin_t;
+ int idx, lin;
+
+ if (log_t <= 0) {
+ lin_t = 0x00000000;
+ return (lin_t);
+ }
+
+ if (log_t >= 100) {
+ lin_t = 0x7fffffff;
+ return (lin_t);
+ }
+
+ idx = (L2L_POINTS - 1) - log_t / (L2L_POINTS);
+ lin = log_t % (L2L_POINTS);
+ lin_t = l2l_df[idx] * lin + l2l_f[idx];
+ return (lin_t);
+}
+
+
+void
+emumix_set_fxvol(struct emu_sc_info *sc, unsigned gpr, int32_t vol)
+{
+
+ vol = log2lin(vol);
+ emumix_set_gpr(sc, gpr, vol);
+}
+
+void
+emumix_set_gpr(struct emu_sc_info *sc, unsigned gpr, int32_t val)
+{
+ if (sc->dbg_level > 1)
+ if (gpr == 0) {
+ device_printf(sc->dev, "Zero gpr write access\n");
+#ifdef KDB
+ kdb_backtrace();
+#endif
+ return;
+ }
+
+ emu_wrptr(sc, 0, GPR(gpr), val);
+}
+
+void
+emumix_set_volume(struct emu_sc_info *sc, int mixer_idx, int volume)
+{
+
+ RANGE(volume, 0, 100);
+ if (mixer_idx < NUM_MIXERS) {
+ sc->mixer_volcache[mixer_idx] = volume;
+ emumix_set_fxvol(sc, sc->mixer_gpr[mixer_idx], volume);
+ }
+}
+
+int
+emumix_get_volume(struct emu_sc_info *sc, int mixer_idx)
+{
+ if ((mixer_idx < NUM_MIXERS) && (mixer_idx >= 0))
+ return (sc->mixer_volcache[mixer_idx]);
+ return (-1);
+}
+
+/* Init CardBus part */
+static int
+emu_cardbus_init(struct emu_sc_info *sc)
+{
+
+ /*
+ * XXX May not need this if we have IPR3 handler.
+ * Is it a real init calls, or IPR3 interrupt acknowledgments?
+ * Looks much like "(data << 16) | register".
+ */
+ emu_wr_cbptr(sc, (0x00d0 << 16) | 0x0000);
+ emu_wr_cbptr(sc, (0x00d0 << 16) | 0x0001);
+ emu_wr_cbptr(sc, (0x00d0 << 16) | 0x005f);
+ emu_wr_cbptr(sc, (0x00d0 << 16) | 0x007f);
+
+ emu_wr_cbptr(sc, (0x0090 << 16) | 0x007f);
+
+ return (0);
+}
+
+/* Probe and attach the card */
+static int
+emu_init(struct emu_sc_info *sc)
+{
+ uint32_t ch, tmp;
+ uint32_t spdif_sr;
+ uint32_t ac97slot;
+ int def_mode;
+ int i;
+
+ /* disable audio and lock cache */
+ emu_wr(sc, HCFG, HCFG_LOCKSOUNDCACHE | HCFG_LOCKTANKCACHE_MASK | HCFG_MUTEBUTTONENABLE, 4);
+
+ /* reset recording buffers */
+ emu_wrptr(sc, 0, MICBS, ADCBS_BUFSIZE_NONE);
+ emu_wrptr(sc, 0, MICBA, 0);
+ emu_wrptr(sc, 0, FXBS, ADCBS_BUFSIZE_NONE);
+ emu_wrptr(sc, 0, FXBA, 0);
+ emu_wrptr(sc, 0, ADCBS, ADCBS_BUFSIZE_NONE);
+ emu_wrptr(sc, 0, ADCBA, 0);
+
+ /* disable channel interrupt */
+ emu_wr(sc, INTE, INTE_INTERVALTIMERENB | INTE_SAMPLERATETRACKER | INTE_PCIERRORENABLE, 4);
+ emu_wrptr(sc, 0, CLIEL, 0);
+ emu_wrptr(sc, 0, CLIEH, 0);
+ emu_wrptr(sc, 0, SOLEL, 0);
+ emu_wrptr(sc, 0, SOLEH, 0);
+
+ /* disable P16V and S/PDIF interrupts */
+ if ((sc->is_ca0102) || (sc->is_ca0108))
+ emu_wr(sc, INTE2, 0, 4);
+
+ if (sc->is_ca0102)
+ emu_wr(sc, INTE3, 0, 4);
+
+ /* init phys inputs and outputs */
+ ac97slot = 0;
+ if (sc->has_51)
+ ac97slot = AC97SLOT_CNTR | AC97SLOT_LFE;
+ if (sc->has_71)
+ ac97slot = AC97SLOT_CNTR | AC97SLOT_LFE | AC97SLOT_REAR_LEFT | AC97SLOT_REAR_RIGHT;
+ if (sc->is_emu10k2)
+ ac97slot |= 0x40;
+ emu_wrptr(sc, 0, AC97SLOT, ac97slot);
+
+ if (sc->is_emu10k2) /* XXX for later cards? */
+ emu_wrptr(sc, 0, SPBYPASS, 0xf00); /* What will happen if
+ * we write 1 here? */
+
+ if (bus_dma_tag_create( /* parent */ bus_get_dma_tag(sc->dev),
+ /* alignment */ 2, /* boundary */ 0,
+ /* lowaddr */ 1 << 31, /* can only access 0-2gb */
+ /* highaddr */ BUS_SPACE_MAXADDR,
+ /* filter */ NULL, /* filterarg */ NULL,
+ /* maxsize */ EMU_MAX_BUFSZ, /* nsegments */ 1, /* maxsegz */ 0x3ffff,
+ /* flags */ 0, /* lockfunc */ busdma_lock_mutex,
+ /* lockarg */ &Giant, &(sc->mem.dmat)) != 0) {
+ device_printf(sc->dev, "unable to create dma tag\n");
+ bus_dma_tag_destroy(sc->mem.dmat);
+ return (ENOMEM);
+ }
+
+ sc->mem.card = sc;
+ SLIST_INIT(&sc->mem.blocks);
+ sc->mem.ptb_pages = emu_malloc(&sc->mem, EMU_MAXPAGES * sizeof(uint32_t), &sc->mem.ptb_pages_addr);
+ if (sc->mem.ptb_pages == NULL)
+ return (ENOMEM);
+
+ sc->mem.silent_page = emu_malloc(&sc->mem, EMUPAGESIZE, &sc->mem.silent_page_addr);
+ if (sc->mem.silent_page == NULL) {
+ emu_free(&sc->mem, sc->mem.ptb_pages);
+ return (ENOMEM);
+ }
+ /* Clear page with silence & setup all pointers to this page */
+ bzero(sc->mem.silent_page, EMUPAGESIZE);
+ tmp = (uint32_t) (sc->mem.silent_page_addr) << 1;
+ for (i = 0; i < EMU_MAXPAGES; i++)
+ sc->mem.ptb_pages[i] = tmp | i;
+
+ for (ch = 0; ch < NUM_G; ch++) {
+ emu_wrptr(sc, ch, MAPA, tmp | MAP_PTI_MASK);
+ emu_wrptr(sc, ch, MAPB, tmp | MAP_PTI_MASK);
+ }
+ emu_wrptr(sc, 0, PTB, (sc->mem.ptb_pages_addr));
+ emu_wrptr(sc, 0, TCB, 0); /* taken from original driver */
+ emu_wrptr(sc, 0, TCBS, 0); /* taken from original driver */
+
+ /* init envelope engine */
+ for (ch = 0; ch < NUM_G; ch++) {
+ emu_wrptr(sc, ch, DCYSUSV, 0);
+ emu_wrptr(sc, ch, IP, 0);
+ emu_wrptr(sc, ch, VTFT, 0xffff);
+ emu_wrptr(sc, ch, CVCF, 0xffff);
+ emu_wrptr(sc, ch, PTRX, 0);
+ emu_wrptr(sc, ch, CPF, 0);
+ emu_wrptr(sc, ch, CCR, 0);
+
+ emu_wrptr(sc, ch, PSST, 0);
+ emu_wrptr(sc, ch, DSL, 0x10);
+ emu_wrptr(sc, ch, CCCA, 0);
+ emu_wrptr(sc, ch, Z1, 0);
+ emu_wrptr(sc, ch, Z2, 0);
+ emu_wrptr(sc, ch, FXRT, 0xd01c0000);
+
+ emu_wrptr(sc, ch, ATKHLDM, 0);
+ emu_wrptr(sc, ch, DCYSUSM, 0);
+ emu_wrptr(sc, ch, IFATN, 0xffff);
+ emu_wrptr(sc, ch, PEFE, 0);
+ emu_wrptr(sc, ch, FMMOD, 0);
+ emu_wrptr(sc, ch, TREMFRQ, 24); /* 1 Hz */
+ emu_wrptr(sc, ch, FM2FRQ2, 24); /* 1 Hz */
+ emu_wrptr(sc, ch, TEMPENV, 0);
+
+ /*** these are last so OFF prevents writing ***/
+ emu_wrptr(sc, ch, LFOVAL2, 0);
+ emu_wrptr(sc, ch, LFOVAL1, 0);
+ emu_wrptr(sc, ch, ATKHLDV, 0);
+ emu_wrptr(sc, ch, ENVVOL, 0);
+ emu_wrptr(sc, ch, ENVVAL, 0);
+
+ if ((sc->is_emu10k2) || (sc->is_ca0102) || (sc->is_ca0108)) {
+ emu_wrptr(sc, ch, 0x4c, 0x0);
+ emu_wrptr(sc, ch, 0x4d, 0x0);
+ emu_wrptr(sc, ch, 0x4e, 0x0);
+ emu_wrptr(sc, ch, 0x4f, 0x0);
+ emu_wrptr(sc, ch, A_FXRT1, 0x3f3f3f3f);
+ emu_wrptr(sc, ch, A_FXRT2, 0x3f3f3f3f);
+ emu_wrptr(sc, ch, A_SENDAMOUNTS, 0x0);
+ }
+ }
+
+ emumix_set_spdif_mode(sc, SPDIF_MODE_PCM);
+
+ if ((sc->is_emu10k2) || (sc->is_ca0102) || (sc->is_ca0108))
+ emu_wrptr(sc, 0, A_SPDIF_SAMPLERATE, A_SPDIF_48000);
+
+ /*
+ * CAxxxx cards needs additional setup:
+ * 1. Set I2S capture sample rate to 96000
+ * 2. Disable P16v / P17v proceesing
+ * 3. Allow EMU10K DSP inputs
+ */
+ if ((sc->is_ca0102) || (sc->is_ca0108)) {
+
+ spdif_sr = emu_rdptr(sc, 0, A_SPDIF_SAMPLERATE);
+ spdif_sr &= 0xfffff1ff;
+ spdif_sr |= A_I2S_CAPTURE_96000;
+ emu_wrptr(sc, 0, A_SPDIF_SAMPLERATE, spdif_sr);
+
+ /* Disable P16v processing */
+ emu_wr_p16vptr(sc, 0, SRCSel, 0x14);
+
+ /* Setup P16v/P17v sound routing */
+ if (sc->is_ca0102)
+ emu_wr_p16vptr(sc, 0, SRCMULTI_ENABLE, 0xFF00FF00);
+ else {
+ emu_wr_p16vptr(sc, 0, P17V_MIXER_I2S_ENABLE, 0xFF000000);
+ emu_wr_p16vptr(sc, 0, P17V_MIXER_SPDIF_ENABLE, 0xFF000000);
+
+ tmp = emu_rd(sc, A_IOCFG, 2);
+ emu_wr(sc, A_IOCFG, tmp & ~0x8, 2);
+ }
+ }
+ emu_initefx(sc);
+
+ def_mode = MODE_ANALOG;
+ if ((sc->is_emu10k2) || (sc->is_ca0102) || (sc->is_ca0108))
+ def_mode = MODE_DIGITAL;
+ if (((sc->is_emu10k2) || (sc->is_ca0102) || (sc->is_ca0108)) && (sc->broken_digital)) {
+ device_printf(sc->dev, "Audigy card initialized in analog mode.\n");
+ def_mode = MODE_ANALOG;
+ }
+ emumix_set_mode(sc, def_mode);
+
+ if (bootverbose) {
+ tmp = emu_rd(sc, HCFG, 4);
+ device_printf(sc->dev, "Card Configuration ( 0x%08x )\n", tmp);
+ device_printf(sc->dev, "Card Configuration ( & 0xff000000 ) : %s%s%s%s%s%s%s%s\n",
+ (tmp & 0x80000000 ? "[Legacy MPIC] " : ""),
+ (tmp & 0x40000000 ? "[0x40] " : ""),
+ (tmp & 0x20000000 ? "[0x20] " : ""),
+ (tmp & 0x10000000 ? "[0x10] " : ""),
+ (tmp & 0x08000000 ? "[0x08] " : ""),
+ (tmp & 0x04000000 ? "[0x04] " : ""),
+ (tmp & 0x02000000 ? "[0x02] " : ""),
+ (tmp & 0x01000000 ? "[0x01]" : " "));
+ device_printf(sc->dev, "Card Configuration ( & 0x00ff0000 ) : %s%s%s%s%s%s%s%s\n",
+ (tmp & 0x00800000 ? "[0x80] " : ""),
+ (tmp & 0x00400000 ? "[0x40] " : ""),
+ (tmp & 0x00200000 ? "[Legacy INT] " : ""),
+ (tmp & 0x00100000 ? "[0x10] " : ""),
+ (tmp & 0x00080000 ? "[0x08] " : ""),
+ (tmp & 0x00040000 ? "[Codec4] " : ""),
+ (tmp & 0x00020000 ? "[Codec2] " : ""),
+ (tmp & 0x00010000 ? "[I2S Codec]" : " "));
+ device_printf(sc->dev, "Card Configuration ( & 0x0000ff00 ) : %s%s%s%s%s%s%s%s\n",
+ (tmp & 0x00008000 ? "[0x80] " : ""),
+ (tmp & 0x00004000 ? "[GPINPUT0] " : ""),
+ (tmp & 0x00002000 ? "[GPINPUT1] " : ""),
+ (tmp & 0x00001000 ? "[GPOUT0] " : ""),
+ (tmp & 0x00000800 ? "[GPOUT1] " : ""),
+ (tmp & 0x00000400 ? "[GPOUT2] " : ""),
+ (tmp & 0x00000200 ? "[Joystick] " : ""),
+ (tmp & 0x00000100 ? "[0x01]" : " "));
+ device_printf(sc->dev, "Card Configuration ( & 0x000000ff ) : %s%s%s%s%s%s%s%s\n",
+ (tmp & 0x00000080 ? "[0x80] " : ""),
+ (tmp & 0x00000040 ? "[0x40] " : ""),
+ (tmp & 0x00000020 ? "[0x20] " : ""),
+ (tmp & 0x00000010 ? "[AUTOMUTE] " : ""),
+ (tmp & 0x00000008 ? "[LOCKSOUNDCACHE] " : ""),
+ (tmp & 0x00000004 ? "[LOCKTANKCACHE] " : ""),
+ (tmp & 0x00000002 ? "[MUTEBUTTONENABLE] " : ""),
+ (tmp & 0x00000001 ? "[AUDIOENABLE]" : " "));
+
+ if ((sc->is_emu10k2) || (sc->is_ca0102) || (sc->is_ca0108)) {
+ tmp = emu_rd(sc, A_IOCFG, 2);
+ device_printf(sc->dev, "Audigy Card Configuration ( 0x%04x )\n", tmp);
+ device_printf(sc->dev, "Audigy Card Configuration ( & 0xff00 )");
+ printf(" : %s%s%s%s%s%s%s%s\n",
+ (tmp & 0x8000 ? "[Rear Speakers] " : ""),
+ (tmp & 0x4000 ? "[Front Speakers] " : ""),
+ (tmp & 0x2000 ? "[0x20] " : ""),
+ (tmp & 0x1000 ? "[0x10] " : ""),
+ (tmp & 0x0800 ? "[0x08] " : ""),
+ (tmp & 0x0400 ? "[0x04] " : ""),
+ (tmp & 0x0200 ? "[0x02] " : ""),
+ (tmp & 0x0100 ? "[AudigyDrive Phones]" : " "));
+ device_printf(sc->dev, "Audigy Card Configuration ( & 0x00ff )");
+ printf(" : %s%s%s%s%s%s%s%s\n",
+ (tmp & 0x0080 ? "[0x80] " : ""),
+ (tmp & 0x0040 ? "[Mute AnalogOut] " : ""),
+ (tmp & 0x0020 ? "[0x20] " : ""),
+ (tmp & 0x0010 ? "[0x10] " : ""),
+ (tmp & 0x0008 ? "[0x08] " : ""),
+ (tmp & 0x0004 ? "[GPOUT0] " : ""),
+ (tmp & 0x0002 ? "[GPOUT1] " : ""),
+ (tmp & 0x0001 ? "[GPOUT2]" : " "));
+ } /* is_emu10k2 or ca* */
+ } /* bootverbose */
+ return (0);
+}
+
+static int
+emu_uninit(struct emu_sc_info *sc)
+{
+ uint32_t ch;
+ struct emu_memblk *blk;
+
+ emu_wr(sc, INTE, 0, 4);
+ for (ch = 0; ch < NUM_G; ch++)
+ emu_wrptr(sc, ch, DCYSUSV, 0);
+ for (ch = 0; ch < NUM_G; ch++) {
+ emu_wrptr(sc, ch, VTFT, 0);
+ emu_wrptr(sc, ch, CVCF, 0);
+ emu_wrptr(sc, ch, PTRX, 0);
+ emu_wrptr(sc, ch, CPF, 0);
+ }
+
+ /* disable audio and lock cache */
+ emu_wr(sc, HCFG, HCFG_LOCKSOUNDCACHE | HCFG_LOCKTANKCACHE_MASK | HCFG_MUTEBUTTONENABLE, 4);
+
+ emu_wrptr(sc, 0, PTB, 0);
+ /* reset recording buffers */
+ emu_wrptr(sc, 0, MICBS, ADCBS_BUFSIZE_NONE);
+ emu_wrptr(sc, 0, MICBA, 0);
+ emu_wrptr(sc, 0, FXBS, ADCBS_BUFSIZE_NONE);
+ emu_wrptr(sc, 0, FXBA, 0);
+ emu_wrptr(sc, 0, FXWC, 0);
+ emu_wrptr(sc, 0, ADCBS, ADCBS_BUFSIZE_NONE);
+ emu_wrptr(sc, 0, ADCBA, 0);
+ emu_wrptr(sc, 0, TCB, 0);
+ emu_wrptr(sc, 0, TCBS, 0);
+
+ /* disable channel interrupt */
+ emu_wrptr(sc, 0, CLIEL, 0);
+ emu_wrptr(sc, 0, CLIEH, 0);
+ emu_wrptr(sc, 0, SOLEL, 0);
+ emu_wrptr(sc, 0, SOLEH, 0);
+
+ if (!SLIST_EMPTY(&sc->mem.blocks))
+ device_printf(sc->dev, "warning: memblock list not empty\n");
+
+ SLIST_FOREACH(blk, &sc->mem.blocks, link)
+ if (blk != NULL)
+ device_printf(sc->dev, "lost %d for %s\n", blk->pte_size, blk->owner);
+
+ emu_free(&sc->mem, sc->mem.ptb_pages);
+ emu_free(&sc->mem, sc->mem.silent_page);
+
+ return (0);
+}
+
+static int
+emu_read_ivar(device_t bus, device_t dev, int ivar_index, uintptr_t * result)
+{
+ struct sndcard_func *func = device_get_ivars(dev);
+ struct emu_sc_info *sc = device_get_softc(bus);
+
+ if (func==NULL)
+ return (ENOMEM);
+ if (sc == NULL)
+ return (ENOMEM);
+
+ switch (ivar_index) {
+ case EMU_VAR_FUNC:
+ *result = func->func;
+ break;
+ case EMU_VAR_ROUTE:
+ if (func->varinfo == NULL)
+ return (ENOMEM);
+ *result = ((struct emu_pcminfo *)func->varinfo)->route;
+ break;
+ case EMU_VAR_ISEMU10K1:
+ *result = sc->is_emu10k1;
+ break;
+ case EMU_VAR_MCH_DISABLED:
+ *result = sc->mch_disabled;
+ break;
+ case EMU_VAR_MCH_REC:
+ *result = sc->mch_rec;
+ break;
+ default:
+ return (ENOENT);
+ }
+
+ return (0);
+}
+
+static int
+emu_write_ivar(device_t bus __unused, device_t dev __unused,
+ int ivar_index, uintptr_t value __unused)
+{
+
+ switch (ivar_index) {
+ case 0:
+ return (EINVAL);
+
+ default:
+ return (ENOENT);
+ }
+}
+
+static int
+emu_pci_probe(device_t dev)
+{
+ struct sbuf *s;
+ unsigned int thiscard = 0;
+ uint16_t vendor;
+
+ vendor = pci_read_config(dev, PCIR_DEVVENDOR, /* bytes */ 2);
+ if (vendor != 0x1102)
+ return (ENXIO); /* Not Creative */
+
+ thiscard = emu_getcard(dev);
+ if (thiscard == 0)
+ return (ENXIO);
+
+ s = sbuf_new(NULL, NULL, 4096, 0);
+ if (s == NULL)
+ return (ENOMEM);
+ sbuf_printf(s, "Creative %s [%s]", emu_cards[thiscard].desc, emu_cards[thiscard].SBcode);
+ sbuf_finish(s);
+
+ device_set_desc_copy(dev, sbuf_data(s));
+
+ sbuf_delete(s);
+
+ return (BUS_PROBE_DEFAULT);
+}
+
+
+static int
+emu_pci_attach(device_t dev)
+{
+ struct sndcard_func *func;
+ struct emu_sc_info *sc;
+ struct emu_pcminfo *pcminfo;
+#if 0
+ struct emu_midiinfo *midiinfo;
+#endif
+ uint32_t data;
+ int i;
+ int device_flags;
+ char status[255];
+ int error = ENXIO;
+ int unit;
+
+ sc = device_get_softc(dev);
+ unit = device_get_unit(dev);
+
+ if (resource_disabled("emu10kx", unit)) {
+ device_printf(dev, "disabled by kernel hints\n");
+ return (ENXIO); /* XXX to avoid unit reuse */
+ }
+
+ /* Get configuration */
+
+ sc->ctx = device_get_sysctl_ctx(dev);
+ if (sc->ctx == NULL)
+ goto bad;
+ sc->root = device_get_sysctl_tree(dev);
+ if (sc->root == NULL)
+ goto bad;
+
+ if (resource_int_value("emu10kx", unit, "multichannel_disabled", &(sc->mch_disabled)))
+ RANGE(sc->mch_disabled, 0, 1);
+ SYSCTL_ADD_INT(device_get_sysctl_ctx(dev),
+ SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
+ OID_AUTO, "multichannel_disabled", CTLFLAG_RD, &(sc->mch_disabled), 0, "Multichannel playback setting");
+
+ if (resource_int_value("emu10kx", unit, "multichannel_recording", &(sc->mch_rec)))
+ RANGE(sc->mch_rec, 0, 1);
+ SYSCTL_ADD_INT(device_get_sysctl_ctx(dev),
+ SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
+ OID_AUTO, "multichannel_recording", CTLFLAG_RD, &(sc->mch_rec), 0, "Multichannel recording setting");
+
+ if (resource_int_value("emu10kx", unit, "debug", &(sc->dbg_level)))
+ RANGE(sc->mch_rec, 0, 2);
+ SYSCTL_ADD_INT(device_get_sysctl_ctx(dev),
+ SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
+ OID_AUTO, "debug", CTLFLAG_RW, &(sc->dbg_level), 0, "Debug level");
+
+ /* Fill in the softc. */
+ mtx_init(&sc->lock, device_get_nameunit(dev), "bridge conf", MTX_DEF);
+ mtx_init(&sc->rw, device_get_nameunit(dev), "exclusive io", MTX_DEF);
+ sc->dev = dev;
+ sc->type = pci_get_devid(dev);
+ sc->rev = pci_get_revid(dev);
+ sc->enable_ir = 0;
+ sc->has_ac97 = 0;
+ sc->has_51 = 0;
+ sc->has_71 = 0;
+ sc->broken_digital = 0;
+ sc->is_emu10k1 = 0;
+ sc->is_emu10k2 = 0;
+ sc->is_ca0102 = 0;
+ sc->is_ca0108 = 0;
+ sc->is_cardbus = 0;
+
+ device_flags = emu_cards[emu_getcard(dev)].flags;
+ if (device_flags & HAS_51)
+ sc->has_51 = 1;
+ if (device_flags & HAS_71) {
+ sc->has_51 = 1;
+ sc->has_71 = 1;
+ }
+ if (device_flags & IS_EMU10K1)
+ sc->is_emu10k1 = 1;
+ if (device_flags & IS_EMU10K2)
+ sc->is_emu10k2 = 1;
+ if (device_flags & IS_CA0102)
+ sc->is_ca0102 = 1;
+ if (device_flags & IS_CA0108)
+ sc->is_ca0108 = 1;
+ if ((sc->is_emu10k2) && (sc->rev == 4)) {
+ sc->is_emu10k2 = 0;
+ sc->is_ca0102 = 1; /* for unknown Audigy 2 cards */
+ }
+ if ((sc->is_ca0102 == 1) || (sc->is_ca0108 == 1))
+ if (device_flags & IS_CARDBUS)
+ sc->is_cardbus = 1;
+
+ if ((sc->is_emu10k1 + sc->is_emu10k2 + sc->is_ca0102 + sc->is_ca0108) != 1) {
+ device_printf(sc->dev, "Unable to detect HW chipset\n");
+ goto bad;
+ }
+ if (device_flags & BROKEN_DIGITAL)
+ sc->broken_digital = 1;
+ if (device_flags & HAS_AC97)
+ sc->has_ac97 = 1;
+
+ sc->opcode_shift = 0;
+ if ((sc->is_emu10k2) || (sc->is_ca0102) || (sc->is_ca0108)) {
+ sc->opcode_shift = 24;
+ sc->high_operand_shift = 12;
+
+ /* DSP map */
+ /* sc->fx_base = 0x0 */
+ sc->input_base = 0x40;
+ /* sc->p16vinput_base = 0x50; */
+ sc->output_base = 0x60;
+ sc->efxc_base = 0x80;
+ /* sc->output32h_base = 0xa0; */
+ /* sc->output32l_base = 0xb0; */
+ sc->dsp_zero = 0xc0;
+ /* 0xe0...0x100 are unknown */
+ /* sc->tram_base = 0x200 */
+ /* sc->tram_addr_base = 0x300 */
+ sc->gpr_base = A_FXGPREGBASE;
+ sc->num_gprs = 0x200;
+ sc->code_base = A_MICROCODEBASE;
+ sc->code_size = 0x800 / 2; /* 0x600-0xdff, 2048 words,
+ * 1024 instructions */
+
+ sc->mchannel_fx = 8;
+ sc->num_fxbuses = 16;
+ sc->num_inputs = 8;
+ sc->num_outputs = 16;
+ sc->address_mask = A_PTR_ADDRESS_MASK;
+ }
+ if (sc->is_emu10k1) {
+ sc->has_51 = 0; /* We don't support 5.1 sound on SB Live! 5.1 */
+ sc->opcode_shift = 20;
+ sc->high_operand_shift = 10;
+ sc->code_base = MICROCODEBASE;
+ sc->code_size = 0x400 / 2; /* 0x400-0x7ff, 1024 words,
+ * 512 instructions */
+ sc->gpr_base = FXGPREGBASE;
+ sc->num_gprs = 0x100;
+ sc->input_base = 0x10;
+ sc->output_base = 0x20;
+ /*
+ * XXX 5.1 Analog outputs are inside efxc address space!
+ * They use ouput+0x11/+0x12 (=efxc+1/+2).
+ * Don't use this efx registers for recording on SB Live! 5.1!
+ */
+ sc->efxc_base = 0x30;
+ sc->dsp_zero = 0x40;
+ sc->mchannel_fx = 0;
+ sc->num_fxbuses = 8;
+ sc->num_inputs = 8;
+ sc->num_outputs = 16;
+ sc->address_mask = PTR_ADDRESS_MASK;
+ }
+ if (sc->opcode_shift == 0)
+ goto bad;
+
+ data = pci_read_config(dev, PCIR_COMMAND, 2);
+ data |= (PCIM_CMD_PORTEN | PCIM_CMD_BUSMASTEREN);
+ pci_write_config(dev, PCIR_COMMAND, data, 2);
+ data = pci_read_config(dev, PCIR_COMMAND, 2);
+
+ pci_enable_busmaster(dev);
+
+ i = PCIR_BAR(0);
+ sc->reg = bus_alloc_resource_any(dev, SYS_RES_IOPORT, &i, RF_ACTIVE);
+ if (sc->reg == NULL) {
+ device_printf(dev, "unable to map register space\n");
+ goto bad;
+ }
+ sc->st = rman_get_bustag(sc->reg);
+ sc->sh = rman_get_bushandle(sc->reg);
+
+ for (i = 0; i < EMU_MAX_IRQ_CONSUMERS; i++)
+ sc->timer[i] = 0; /* disable it */
+
+ i = 0;
+ sc->irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &i, RF_ACTIVE | RF_SHAREABLE);
+ if ((sc->irq == NULL) || bus_setup_intr(dev, sc->irq, INTR_MPSAFE | INTR_TYPE_AV, NULL, emu_intr, sc, &sc->ih)) {
+ device_printf(dev, "unable to map interrupt\n");
+ goto bad;
+ }
+ if (emu_rm_init(sc) != 0) {
+ device_printf(dev, "unable to create resource manager\n");
+ goto bad;
+ }
+ if (sc->is_cardbus)
+ if (emu_cardbus_init(sc) != 0) {
+ device_printf(dev, "unable to initialize CardBus interface\n");
+ goto bad;
+ }
+ if (emu_init(sc) != 0) {
+ device_printf(dev, "unable to initialize the card\n");
+ goto bad;
+ }
+ if (emu10kx_dev_init(sc) != 0) {
+ device_printf(dev, "unable to create control device\n");
+ goto bad;
+ }
+ snprintf(status, 255, "rev %d at io 0x%lx irq %ld", sc->rev, rman_get_start(sc->reg), rman_get_start(sc->irq));
+
+ /* Voices */
+ for (i = 0; i < NUM_G; i++) {
+ sc->voice[i].vnum = i;
+ sc->voice[i].slave = NULL;
+ sc->voice[i].busy = 0;
+ sc->voice[i].ismaster = 0;
+ sc->voice[i].running = 0;
+ sc->voice[i].b16 = 0;
+ sc->voice[i].stereo = 0;
+ sc->voice[i].speed = 0;
+ sc->voice[i].start = 0;
+ sc->voice[i].end = 0;
+ }
+
+ /* PCM Audio */
+ for (i = 0; i < RT_COUNT; i++)
+ sc->pcm[i] = NULL;
+
+ /* FRONT */
+ func = malloc(sizeof(struct sndcard_func), M_DEVBUF, M_NOWAIT | M_ZERO);
+ if (func == NULL) {
+ error = ENOMEM;
+ goto bad;
+ }
+ pcminfo = malloc(sizeof(struct emu_pcminfo), M_DEVBUF, M_NOWAIT | M_ZERO);
+ if (pcminfo == NULL) {
+ error = ENOMEM;
+ goto bad;
+ }
+ pcminfo->card = sc;
+ pcminfo->route = RT_FRONT;
+
+ func->func = SCF_PCM;
+ func->varinfo = pcminfo;
+ sc->pcm[RT_FRONT] = device_add_child(dev, "pcm", -1);
+ device_set_ivars(sc->pcm[RT_FRONT], func);
+
+ if (!(sc->mch_disabled)) {
+ /* REAR */
+ func = malloc(sizeof(struct sndcard_func), M_DEVBUF, M_NOWAIT | M_ZERO);
+ if (func == NULL) {
+ error = ENOMEM;
+ goto bad;
+ }
+ pcminfo = malloc(sizeof(struct emu_pcminfo), M_DEVBUF, M_NOWAIT | M_ZERO);
+ if (pcminfo == NULL) {
+ error = ENOMEM;
+ goto bad;
+ }
+ pcminfo->card = sc;
+ pcminfo->route = RT_REAR;
+
+ func->func = SCF_PCM;
+ func->varinfo = pcminfo;
+ sc->pcm[RT_REAR] = device_add_child(dev, "pcm", -1);
+ device_set_ivars(sc->pcm[RT_REAR], func);
+ if (sc->has_51) {
+ /* CENTER */
+ func = malloc(sizeof(struct sndcard_func), M_DEVBUF, M_NOWAIT | M_ZERO);
+ if (func == NULL) {
+ error = ENOMEM;
+ goto bad;
+ }
+ pcminfo = malloc(sizeof(struct emu_pcminfo), M_DEVBUF, M_NOWAIT | M_ZERO);
+ if (pcminfo == NULL) {
+ error = ENOMEM;
+ goto bad;
+ }
+ pcminfo->card = sc;
+ pcminfo->route = RT_CENTER;
+
+ func->func = SCF_PCM;
+ func->varinfo = pcminfo;
+ sc->pcm[RT_CENTER] = device_add_child(dev, "pcm", -1);
+ device_set_ivars(sc->pcm[RT_CENTER], func);
+ /* SUB */
+ func = malloc(sizeof(struct sndcard_func), M_DEVBUF, M_NOWAIT | M_ZERO);
+ if (func == NULL) {
+ error = ENOMEM;
+ goto bad;
+ }
+ pcminfo = malloc(sizeof(struct emu_pcminfo), M_DEVBUF, M_NOWAIT | M_ZERO);
+ if (pcminfo == NULL) {
+ error = ENOMEM;
+ goto bad;
+ }
+ pcminfo->card = sc;
+ pcminfo->route = RT_SUB;
+
+ func->func = SCF_PCM;
+ func->varinfo = pcminfo;
+ sc->pcm[RT_SUB] = device_add_child(dev, "pcm", -1);
+ device_set_ivars(sc->pcm[RT_SUB], func);
+ }
+ if (sc->has_71) {
+ /* SIDE */
+ func = malloc(sizeof(struct sndcard_func), M_DEVBUF, M_NOWAIT | M_ZERO);
+ if (func == NULL) {
+ error = ENOMEM;
+ goto bad;
+ }
+ pcminfo = malloc(sizeof(struct emu_pcminfo), M_DEVBUF, M_NOWAIT | M_ZERO);
+ if (pcminfo == NULL) {
+ error = ENOMEM;
+ goto bad;
+ }
+ pcminfo->card = sc;
+ pcminfo->route = RT_SIDE;
+
+ func->func = SCF_PCM;
+ func->varinfo = pcminfo;
+ sc->pcm[RT_SIDE] = device_add_child(dev, "pcm", -1);
+ device_set_ivars(sc->pcm[RT_SIDE], func);
+ }
+ } /* mch_disabled */
+
+ if (sc->mch_rec) {
+ func = malloc(sizeof(struct sndcard_func), M_DEVBUF, M_NOWAIT | M_ZERO);
+ if (func == NULL) {
+ error = ENOMEM;
+ goto bad;
+ }
+ pcminfo = malloc(sizeof(struct emu_pcminfo), M_DEVBUF, M_NOWAIT | M_ZERO);
+ if (pcminfo == NULL) {
+ error = ENOMEM;
+ goto bad;
+ }
+ pcminfo->card = sc;
+ pcminfo->route = RT_MCHRECORD;
+
+ func->func = SCF_PCM;
+ func->varinfo = pcminfo;
+ sc->pcm[RT_MCHRECORD] = device_add_child(dev, "pcm", -1);
+ device_set_ivars(sc->pcm[RT_MCHRECORD], func);
+ } /*mch_rec */
+
+ for (i = 0; i < 2; i++)
+ sc->midi[i] = NULL;
+
+ /* MIDI has some memory mangament and (possible) locking problems */
+#if 0
+ /* Midi Interface 1: Live!, Audigy, Audigy 2 */
+ if ((sc->is_emu10k1) || (sc->is_emu10k2) || (sc->is_ca0102)) {
+ func = malloc(sizeof(struct sndcard_func), M_DEVBUF, M_NOWAIT | M_ZERO);
+ if (func == NULL) {
+ error = ENOMEM;
+ goto bad;
+ }
+ midiinfo = malloc(sizeof(struct emu_midiinfo), M_DEVBUF, M_NOWAIT | M_ZERO);
+ if (midiinfo == NULL) {
+ error = ENOMEM;
+ goto bad;
+ }
+ midiinfo->card = sc;
+ if (sc->is_emu10k2 || (sc->is_ca0102)) {
+ midiinfo->port = A_MUDATA1;
+ midiinfo->portnr = 1;
+ }
+ if (sc->is_emu10k1) {
+ midiinfo->port = MUDATA;
+ midiinfo->portnr = 1;
+ }
+ func->func = SCF_MIDI;
+ func->varinfo = midiinfo;
+ sc->midi[0] = device_add_child(dev, "midi", -1);
+ device_set_ivars(sc->midi[0], func);
+ }
+ /* Midi Interface 2: Audigy, Audigy 2 (on AudigyDrive) */
+ if (sc->is_emu10k2 || (sc->is_ca0102)) {
+ func = malloc(sizeof(struct sndcard_func), M_DEVBUF, M_NOWAIT | M_ZERO);
+ if (func == NULL) {
+ error = ENOMEM;
+ goto bad;
+ }
+ midiinfo = malloc(sizeof(struct emu_midiinfo), M_DEVBUF, M_NOWAIT | M_ZERO);
+ if (midiinfo == NULL) {
+ error = ENOMEM;
+ goto bad;
+ }
+ midiinfo->card = sc;
+
+ midiinfo->port = A_MUDATA2;
+ midiinfo->portnr = 2;
+
+ func->func = SCF_MIDI;
+ func->varinfo = midiinfo;
+ sc->midi[1] = device_add_child(dev, "midi", -1);
+ device_set_ivars(sc->midi[1], func);
+ }
+#endif
+ return (bus_generic_attach(dev));
+
+bad:
+ /* XXX can we just call emu_pci_detach here? */
+ if (sc->cdev)
+ emu10kx_dev_uninit(sc);
+ if (sc->rm != NULL)
+ emu_rm_uninit(sc);
+ if (sc->reg)
+ bus_release_resource(dev, SYS_RES_IOPORT, PCIR_BAR(0), sc->reg);
+ if (sc->ih)
+ bus_teardown_intr(dev, sc->irq, sc->ih);
+ if (sc->irq)
+ bus_release_resource(dev, SYS_RES_IRQ, 0, sc->irq);
+ mtx_destroy(&sc->rw);
+ mtx_destroy(&sc->lock);
+ return (error);
+}
+
+static int
+emu_pci_detach(device_t dev)
+{
+ struct emu_sc_info *sc;
+ struct sndcard_func *func;
+ int devcount, i;
+ device_t *childlist;
+ int r = 0;
+
+ sc = device_get_softc(dev);
+
+ for (i = 0; i < RT_COUNT; i++) {
+ if (sc->pcm[i] != NULL) {
+ func = device_get_ivars(sc->pcm[i]);
+ if (func != NULL && func->func == SCF_PCM) {
+ device_set_ivars(sc->pcm[i], NULL);
+ free(func->varinfo, M_DEVBUF);
+ free(func, M_DEVBUF);
+ }
+ r = device_delete_child(dev, sc->pcm[i]);
+ if (r) return (r);
+ }
+ }
+
+ if (sc->midi[0] != NULL) {
+ func = device_get_ivars(sc->midi[0]);
+ if (func != NULL && func->func == SCF_MIDI) {
+ device_set_ivars(sc->midi[0], NULL);
+ free(func->varinfo, M_DEVBUF);
+ free(func, M_DEVBUF);
+ }
+ r = device_delete_child(dev, sc->midi[0]);
+ if (r) return (r);
+ }
+
+ if (sc->midi[1] != NULL) {
+ func = device_get_ivars(sc->midi[1]);
+ if (func != NULL && func->func == SCF_MIDI) {
+ device_set_ivars(sc->midi[1], NULL);
+ free(func->varinfo, M_DEVBUF);
+ free(func, M_DEVBUF);
+ }
+ r = device_delete_child(dev, sc->midi[1]);
+ if (r) return (r);
+ }
+
+ if (device_get_children(dev, &childlist, &devcount) == 0)
+ for (i = 0; i < devcount - 1; i++) {
+ device_printf(dev, "removing stale child %d (unit %d)\n", i, device_get_unit(childlist[i]));
+ func = device_get_ivars(childlist[i]);
+ if (func != NULL && (func->func == SCF_MIDI || func->func == SCF_PCM)) {
+ device_set_ivars(childlist[i], NULL);
+ free(func->varinfo, M_DEVBUF);
+ free(func, M_DEVBUF);
+ }
+ device_delete_child(dev, childlist[i]);
+ }
+ if (childlist != NULL)
+ free(childlist, M_TEMP);
+
+ r = emu10kx_dev_uninit(sc);
+ if (r)
+ return (r);
+
+ /* shutdown chip */
+ emu_uninit(sc);
+ emu_rm_uninit(sc);
+
+ if (sc->mem.dmat)
+ bus_dma_tag_destroy(sc->mem.dmat);
+
+ if (sc->reg)
+ bus_release_resource(dev, SYS_RES_IOPORT, PCIR_BAR(0), sc->reg);
+ bus_teardown_intr(dev, sc->irq, sc->ih);
+ bus_release_resource(dev, SYS_RES_IRQ, 0, sc->irq);
+ mtx_destroy(&sc->rw);
+ mtx_destroy(&sc->lock);
+
+ return (bus_generic_detach(dev));
+}
+/* add suspend, resume */
+static device_method_t emu_methods[] = {
+ /* Device interface */
+ DEVMETHOD(device_probe, emu_pci_probe),
+ DEVMETHOD(device_attach, emu_pci_attach),
+ DEVMETHOD(device_detach, emu_pci_detach),
+ /* Bus methods */
+ DEVMETHOD(bus_read_ivar, emu_read_ivar),
+ DEVMETHOD(bus_write_ivar, emu_write_ivar),
+
+ {0, 0}
+};
+
+
+static driver_t emu_driver = {
+ "emu10kx",
+ emu_methods,
+ sizeof(struct emu_sc_info),
+ NULL,
+ 0,
+ NULL
+};
+
+static int
+emu_modevent(module_t mod __unused, int cmd, void *data __unused)
+{
+ int err = 0;
+
+ switch (cmd) {
+ case MOD_LOAD:
+ break; /* Success */
+
+ case MOD_UNLOAD:
+ case MOD_SHUTDOWN:
+
+ /* XXX Should we check state of pcm & midi subdevices here? */
+
+ break; /* Success */
+
+ default:
+ err = EINVAL;
+ break;
+ }
+
+ return (err);
+
+}
+
+static devclass_t emu_devclass;
+
+DRIVER_MODULE(snd_emu10kx, pci, emu_driver, emu_devclass, emu_modevent, NULL);
+DRIVER_MODULE(snd_emu10kx, cardbus, emu_driver, emu_devclass, emu_modevent, NULL);
+MODULE_VERSION(snd_emu10kx, SND_EMU10KX_PREFVER);
Index: au88x0.c
===================================================================
RCS file: /home/cvs/src/sys/dev/sound/pci/au88x0.c,v
retrieving revision 1.2
retrieving revision 1.3
diff -L sys/dev/sound/pci/au88x0.c -L sys/dev/sound/pci/au88x0.c -u -r1.2 -r1.3
--- sys/dev/sound/pci/au88x0.c
+++ sys/dev/sound/pci/au88x0.c
@@ -1,33 +1,32 @@
/*-
-* Copyright (c) 2003 Dag-Erling Coïdan Smørgrav
-* All rights reserved.
-*
-* Redistribution and use in source and binary forms, with or without
-* modification, are permitted provided that the following conditions
-* are met:
-* 1. Redistributions of source code must retain the above copyright
-* notice, this list of conditions and the following disclaimer
-* in this position and unchanged.
-* 2. Redistributions in binary form must reproduce the above copyright
-* notice, this list of conditions and the following disclaimer in the
-* documentation and/or other materials provided with the distribution.
-* 3. The name of the author may not be used to endorse or promote products
-* derived from this software without specific prior written permission.
-*
-* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
-* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
-* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
-* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
-* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
-* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
-* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-*
-* $MidnightBSD$
-* $FreeBSD: src/sys/dev/sound/pci/au88x0.c,v 1.10 2005/03/01 08:58:05 imp Exp $
-*/
+ * Copyright (c) 2003 Dag-Erling Coïdan Smørgrav
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer
+ * in this position and unchanged.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD: src/sys/dev/sound/pci/au88x0.c,v 1.13 2007/06/17 06:10:41 ariff Exp $
+ */
#include <dev/sound/pcm/sound.h>
#include <dev/sound/pcm/ac97.h>
@@ -39,684 +38,691 @@
#include <dev/pci/pcivar.h>
-/*************************************************************************** * *
-* SUPPORTED CHIPSETS *
-* *
-***************************************************************************/
+/***************************************************************************\
+ * *
+ * SUPPORTED CHIPSETS *
+ * *
+\***************************************************************************/
static struct au88x0_chipset au88x0_chipsets[] = {
-{
-.auc_name = "Aureal Vortex (8820)",
-.auc_pci_id = 0x000112eb,
-
-.auc_control = 0x1280c,
-
-.auc_irq_source = 0x12800,
-.auc_irq_mask = 0x12804,
-.auc_irq_control = 0x12808,
-.auc_irq_status = 0x1199c,
-
-.auc_dma_control = 0x1060c,
-
-.auc_fifo_size = 0x20,
-.auc_wt_fifos = 32,
-.auc_wt_fifo_base = 0x0e800,
-.auc_wt_fifo_ctl = 0x0f800,
-.auc_wt_dma_ctl = 0x10500,
-.auc_adb_fifos = 16,
-.auc_adb_fifo_base = 0x0e000,
-.auc_adb_fifo_ctl = 0x0f840,
-.auc_adb_dma_ctl = 0x10580,
-
-.auc_adb_route_base = 0x10800,
-.auc_adb_route_bits = 7,
-.auc_adb_codec_in = 0x48,
-.auc_adb_codec_out = 0x58,
-},
-{
-.auc_name = "Aureal Vortex 2 (8830)",
-.auc_pci_id = 0x000212eb,
-
-.auc_control = 0x2a00c,
-
-.auc_irq_source = 0x2a000,
-.auc_irq_mask = 0x2a004,
-.auc_irq_control = 0x2a008,
-.auc_irq_status = 0x2919c,
-
-.auc_dma_control = 0x27ae8,
-
-.auc_fifo_size = 0x40,
-.auc_wt_fifos = 64,
-.auc_wt_fifo_base = 0x10000,
-.auc_wt_fifo_ctl = 0x16000,
-.auc_wt_dma_ctl = 0x27900,
-.auc_adb_fifos = 32,
-.auc_adb_fifo_base = 0x14000,
-.auc_adb_fifo_ctl = 0x16100,
-.auc_adb_dma_ctl = 0x27a00,
-
-.auc_adb_route_base = 0x28000,
-.auc_adb_route_bits = 8,
-.auc_adb_codec_in = 0x70,
-.auc_adb_codec_out = 0x88,
-},
-{
-.auc_name = "Aureal Vortex Advantage (8810)",
-.auc_pci_id = 0x000312eb,
-
-.auc_control = 0x2a00c,
-
-.auc_irq_source = 0x2a000,
-.auc_irq_mask = 0x2a004,
-.auc_irq_control = 0x2a008,
-.auc_irq_status = 0x2919c,
-
-.auc_dma_control = 0x27ae8,
-
-.auc_fifo_size = 0x20,
-.auc_wt_fifos = 32,
-.auc_wt_fifo_base = 0x10000,
-.auc_wt_fifo_ctl = 0x16000,
-.auc_wt_dma_ctl = 0x27fd8,
-.auc_adb_fifos = 16,
-.auc_adb_fifo_base = 0x14000,
-.auc_adb_fifo_ctl = 0x16100,
-.auc_adb_dma_ctl = 0x27180,
-
-.auc_adb_route_base = 0x28000,
-.auc_adb_route_bits = 8,
-.auc_adb_codec_in = 0x70,
-.auc_adb_codec_out = 0x88,
-},
-{
-.auc_pci_id = 0,
-}
+ {
+ .auc_name = "Aureal Vortex (8820)",
+ .auc_pci_id = 0x000112eb,
+
+ .auc_control = 0x1280c,
+
+ .auc_irq_source = 0x12800,
+ .auc_irq_mask = 0x12804,
+ .auc_irq_control = 0x12808,
+ .auc_irq_status = 0x1199c,
+
+ .auc_dma_control = 0x1060c,
+
+ .auc_fifo_size = 0x20,
+ .auc_wt_fifos = 32,
+ .auc_wt_fifo_base = 0x0e800,
+ .auc_wt_fifo_ctl = 0x0f800,
+ .auc_wt_dma_ctl = 0x10500,
+ .auc_adb_fifos = 16,
+ .auc_adb_fifo_base = 0x0e000,
+ .auc_adb_fifo_ctl = 0x0f840,
+ .auc_adb_dma_ctl = 0x10580,
+
+ .auc_adb_route_base = 0x10800,
+ .auc_adb_route_bits = 7,
+ .auc_adb_codec_in = 0x48,
+ .auc_adb_codec_out = 0x58,
+ },
+ {
+ .auc_name = "Aureal Vortex 2 (8830)",
+ .auc_pci_id = 0x000212eb,
+
+ .auc_control = 0x2a00c,
+
+ .auc_irq_source = 0x2a000,
+ .auc_irq_mask = 0x2a004,
+ .auc_irq_control = 0x2a008,
+ .auc_irq_status = 0x2919c,
+
+ .auc_dma_control = 0x27ae8,
+
+ .auc_fifo_size = 0x40,
+ .auc_wt_fifos = 64,
+ .auc_wt_fifo_base = 0x10000,
+ .auc_wt_fifo_ctl = 0x16000,
+ .auc_wt_dma_ctl = 0x27900,
+ .auc_adb_fifos = 32,
+ .auc_adb_fifo_base = 0x14000,
+ .auc_adb_fifo_ctl = 0x16100,
+ .auc_adb_dma_ctl = 0x27a00,
+
+ .auc_adb_route_base = 0x28000,
+ .auc_adb_route_bits = 8,
+ .auc_adb_codec_in = 0x70,
+ .auc_adb_codec_out = 0x88,
+ },
+ {
+ .auc_name = "Aureal Vortex Advantage (8810)",
+ .auc_pci_id = 0x000312eb,
+
+ .auc_control = 0x2a00c,
+
+ .auc_irq_source = 0x2a000,
+ .auc_irq_mask = 0x2a004,
+ .auc_irq_control = 0x2a008,
+ .auc_irq_status = 0x2919c,
+
+ .auc_dma_control = 0x27ae8,
+
+ .auc_fifo_size = 0x20,
+ .auc_wt_fifos = 32,
+ .auc_wt_fifo_base = 0x10000,
+ .auc_wt_fifo_ctl = 0x16000,
+ .auc_wt_dma_ctl = 0x27fd8,
+ .auc_adb_fifos = 16,
+ .auc_adb_fifo_base = 0x14000,
+ .auc_adb_fifo_ctl = 0x16100,
+ .auc_adb_dma_ctl = 0x27180,
+
+ .auc_adb_route_base = 0x28000,
+ .auc_adb_route_bits = 8,
+ .auc_adb_codec_in = 0x70,
+ .auc_adb_codec_out = 0x88,
+ },
+ {
+ .auc_pci_id = 0,
+ }
};
-/*************************************************************************** * *
-* FORMATS AND CAPABILITIES *
-* *
-***************************************************************************/
+/***************************************************************************\
+ * *
+ * FORMATS AND CAPABILITIES *
+ * *
+\***************************************************************************/
static u_int32_t au88x0_formats[] = {
-AFMT_U8,
-AFMT_STEREO | AFMT_U8,
-AFMT_S16_LE,
-AFMT_STEREO | AFMT_S16_LE,
-0
+ AFMT_U8,
+ AFMT_STEREO | AFMT_U8,
+ AFMT_S16_LE,
+ AFMT_STEREO | AFMT_S16_LE,
+ 0
};
static struct pcmchan_caps au88x0_capabilities = {
-4000, /* minimum sample rate */
-48000, /* maximum sample rate */
-au88x0_formats, /* supported formats */
-0 /* no particular capabilities */
+ 4000, /* minimum sample rate */
+ 48000, /* maximum sample rate */
+ au88x0_formats, /* supported formats */
+ 0 /* no particular capabilities */
};
-/*************************************************************************** * *
-* CODEC INTERFACE *
-* *
-***************************************************************************/
+/***************************************************************************\
+ * *
+ * CODEC INTERFACE *
+ * *
+\***************************************************************************/
/*
-* Read from the au88x0 register space
-*/
+ * Read from the au88x0 register space
+ */
#if 1
/* all our writes are 32-bit */
-#define au88x0_read(aui, reg, n) bus_space_read_4((aui)->aui_spct, (aui)->aui_spch, (reg))
-#define au88x0_write(aui, reg, data, n) bus_space_write_4((aui)->aui_spct, (aui)->aui_spch, (reg), (data))
+#define au88x0_read(aui, reg, n) \
+ bus_space_read_4((aui)->aui_spct, (aui)->aui_spch, (reg))
+#define au88x0_write(aui, reg, data, n) \
+ bus_space_write_4((aui)->aui_spct, (aui)->aui_spch, (reg), (data))
#else
static uint32_t
au88x0_read(struct au88x0_info *aui, int reg, int size)
{
-uint32_t data;
+ uint32_t data;
-switch (size) {
-case 1:
-data = bus_space_read_1(aui->aui_spct, aui->aui_spch, reg);
-break;
-case 2:
-data = bus_space_read_2(aui->aui_spct, aui->aui_spch, reg);
-break;
-case 4:
-data = bus_space_read_4(aui->aui_spct, aui->aui_spch, reg);
-break;
-default:
-panic("unsupported read size %d", size);
-}
-return (data);
+ switch (size) {
+ case 1:
+ data = bus_space_read_1(aui->aui_spct, aui->aui_spch, reg);
+ break;
+ case 2:
+ data = bus_space_read_2(aui->aui_spct, aui->aui_spch, reg);
+ break;
+ case 4:
+ data = bus_space_read_4(aui->aui_spct, aui->aui_spch, reg);
+ break;
+ default:
+ panic("unsupported read size %d", size);
+ }
+ return (data);
}
/*
-* Write to the au88x0 register space
-*/
+ * Write to the au88x0 register space
+ */
static void
au88x0_write(struct au88x0_info *aui, int reg, uint32_t data, int size)
{
-switch (size) {
-case 1:
-bus_space_write_1(aui->aui_spct, aui->aui_spch, reg, data);
-break;
-case 2:
-bus_space_write_2(aui->aui_spct, aui->aui_spch, reg, data);
-break;
-case 4:
-bus_space_write_4(aui->aui_spct, aui->aui_spch, reg, data);
-break;
-default:
-panic("unsupported write size %d", size);
-}
+ switch (size) {
+ case 1:
+ bus_space_write_1(aui->aui_spct, aui->aui_spch, reg, data);
+ break;
+ case 2:
+ bus_space_write_2(aui->aui_spct, aui->aui_spch, reg, data);
+ break;
+ case 4:
+ bus_space_write_4(aui->aui_spct, aui->aui_spch, reg, data);
+ break;
+ default:
+ panic("unsupported write size %d", size);
+ }
}
#endif
/*
-* Reset and initialize the codec
-*/
+ * Reset and initialize the codec
+ */
static void
au88x0_codec_init(struct au88x0_info *aui)
{
-uint32_t data;
-int i;
+ uint32_t data;
+ int i;
-/* wave that chicken */
-au88x0_write(aui, AU88X0_CODEC_CONTROL, 0x8068, 4);
-DELAY(AU88X0_SETTLE_DELAY);
-au88x0_write(aui, AU88X0_CODEC_CONTROL, 0x00e8, 4);
-DELAY(1000);
-for (i = 0; i < 32; ++i) {
-au88x0_write(aui, AU88X0_CODEC_CHANNEL + i * 4, 0, 4);
-DELAY(AU88X0_SETTLE_DELAY);
-}
-au88x0_write(aui, AU88X0_CODEC_CONTROL, 0x00e8, 4);
-DELAY(AU88X0_SETTLE_DELAY);
-
-/* enable both codec channels */
-data = au88x0_read(aui, AU88X0_CODEC_ENABLE, 4);
-data |= (1 << (8 + 0)) | (1 << (8 + 1));
-au88x0_write(aui, AU88X0_CODEC_ENABLE, data, 4);
-DELAY(AU88X0_SETTLE_DELAY);
+ /* wave that chicken */
+ au88x0_write(aui, AU88X0_CODEC_CONTROL, 0x8068, 4);
+ DELAY(AU88X0_SETTLE_DELAY);
+ au88x0_write(aui, AU88X0_CODEC_CONTROL, 0x00e8, 4);
+ DELAY(1000);
+ for (i = 0; i < 32; ++i) {
+ au88x0_write(aui, AU88X0_CODEC_CHANNEL + i * 4, 0, 4);
+ DELAY(AU88X0_SETTLE_DELAY);
+ }
+ au88x0_write(aui, AU88X0_CODEC_CONTROL, 0x00e8, 4);
+ DELAY(AU88X0_SETTLE_DELAY);
+
+ /* enable both codec channels */
+ data = au88x0_read(aui, AU88X0_CODEC_ENABLE, 4);
+ data |= (1 << (8 + 0)) | (1 << (8 + 1));
+ au88x0_write(aui, AU88X0_CODEC_ENABLE, data, 4);
+ DELAY(AU88X0_SETTLE_DELAY);
}
/*
-* Wait for the codec to get ready to accept a register write
-* Should be called at spltty
-*/
+ * Wait for the codec to get ready to accept a register write
+ * Should be called at spltty
+ */
static int
au88x0_codec_wait(struct au88x0_info *aui)
{
-uint32_t data;
-int i;
+ uint32_t data;
+ int i;
-for (i = 0; i < AU88X0_RETRY_COUNT; ++i) {
-data = au88x0_read(aui, AU88X0_CODEC_CONTROL, 4);
-if (data & AU88X0_CDCTL_WROK)
-return (0);
-DELAY(AU88X0_SETTLE_DELAY);
-}
-device_printf(aui->aui_dev, "timeout while waiting for codecn");
-return (-1);
+ for (i = 0; i < AU88X0_RETRY_COUNT; ++i) {
+ data = au88x0_read(aui, AU88X0_CODEC_CONTROL, 4);
+ if (data & AU88X0_CDCTL_WROK)
+ return (0);
+ DELAY(AU88X0_SETTLE_DELAY);
+ }
+ device_printf(aui->aui_dev, "timeout while waiting for codec\n");
+ return (-1);
}
/*
-* Read from the ac97 codec
-*/
+ * Read from the ac97 codec
+ */
static int
au88x0_codec_read(kobj_t obj, void *arg, int reg)
{
-struct au88x0_info *aui = arg;
-uint32_t data;
-int sl;
-
-sl = spltty();
-au88x0_codec_wait(aui);
-au88x0_write(aui, AU88X0_CODEC_IO, AU88X0_CDIO_READ(reg), 4);
-DELAY(1000);
-data = au88x0_read(aui, AU88X0_CODEC_IO, 4);
-splx(sl);
-data &= AU88X0_CDIO_DATA_MASK;
-data >>= AU88X0_CDIO_DATA_SHIFT;
-return (data);
+ struct au88x0_info *aui = arg;
+ uint32_t data;
+ int sl;
+
+ sl = spltty();
+ au88x0_codec_wait(aui);
+ au88x0_write(aui, AU88X0_CODEC_IO, AU88X0_CDIO_READ(reg), 4);
+ DELAY(1000);
+ data = au88x0_read(aui, AU88X0_CODEC_IO, 4);
+ splx(sl);
+ data &= AU88X0_CDIO_DATA_MASK;
+ data >>= AU88X0_CDIO_DATA_SHIFT;
+ return (data);
}
/*
-* Write to the ac97 codec
-*/
+ * Write to the ac97 codec
+ */
static int
au88x0_codec_write(kobj_t obj, void *arg, int reg, uint32_t data)
{
-struct au88x0_info *aui = arg;
-int sl;
+ struct au88x0_info *aui = arg;
+ int sl;
-sl = spltty();
-au88x0_codec_wait(aui);
-au88x0_write(aui, AU88X0_CODEC_IO, AU88X0_CDIO_WRITE(reg, data), 4);
-splx(sl);
-return 0;
+ sl = spltty();
+ au88x0_codec_wait(aui);
+ au88x0_write(aui, AU88X0_CODEC_IO, AU88X0_CDIO_WRITE(reg, data), 4);
+ splx(sl);
+ return 0;
}
/*
-* Codec interface glue
-*/
+ * Codec interface glue
+ */
static kobj_method_t au88x0_ac97_methods[] = {
-KOBJMETHOD(ac97_read, au88x0_codec_read),
-KOBJMETHOD(ac97_write, au88x0_codec_write),
-{ 0, 0 }
+ KOBJMETHOD(ac97_read, au88x0_codec_read),
+ KOBJMETHOD(ac97_write, au88x0_codec_write),
+ { 0, 0 }
};
AC97_DECLARE(au88x0_ac97);
-#define au88x0_channel(aui, dir) &(aui)->aui_chan[((dir) == PCMDIR_PLAY) ? 0 : 1]
+#define au88x0_channel(aui, dir) \
+ &(aui)->aui_chan[((dir) == PCMDIR_PLAY) ? 0 : 1]
-/*************************************************************************** * *
-* CHANNEL INTERFACE *
-* *
-***************************************************************************/
+/***************************************************************************\
+ * *
+ * CHANNEL INTERFACE *
+ * *
+\***************************************************************************/
/*
-* Initialize a PCM channel
-*/
+ * Initialize a PCM channel
+ */
static void *
au88x0_chan_init(kobj_t obj, void *arg,
-struct snd_dbuf *buf, struct pcm_channel *chan, int dir)
+ struct snd_dbuf *buf, struct pcm_channel *chan, int dir)
{
-struct au88x0_info *aui = arg;
-struct au88x0_chan_info *auci = au88x0_channel(aui, dir);
+ struct au88x0_info *aui = arg;
+ struct au88x0_chan_info *auci = au88x0_channel(aui, dir);
-if (sndbuf_alloc(buf, aui->aui_dmat, aui->aui_bufsize) != 0)
-return (NULL);
-auci->auci_aui = aui;
-auci->auci_pcmchan = chan;
-auci->auci_buf = buf;
-auci->auci_dir = dir;
-return (auci);
+ if (sndbuf_alloc(buf, aui->aui_dmat, 0, aui->aui_bufsize) != 0)
+ return (NULL);
+ auci->auci_aui = aui;
+ auci->auci_pcmchan = chan;
+ auci->auci_buf = buf;
+ auci->auci_dir = dir;
+ return (auci);
}
/*
-* Set the data format for a PCM channel
-*/
+ * Set the data format for a PCM channel
+ */
static int
au88x0_chan_setformat(kobj_t obj, void *arg, u_int32_t format)
{
-/* XXX */
-return (ENXIO);
+ /* XXX */
+ return (ENXIO);
}
/*
-* Set the sample rate for a PCM channel
-*/
+ * Set the sample rate for a PCM channel
+ */
static int
au88x0_chan_setspeed(kobj_t obj, void *arg, u_int32_t speed)
{
-/* XXX */
-return (speed);
+ /* XXX */
+ return (speed);
}
/*
-* Set the block size for a PCM channel
-*/
+ * Set the block size for a PCM channel
+ */
static int
au88x0_chan_setblocksize(kobj_t obj, void *arg, u_int32_t blocksize)
{
-/* XXX */
-return (blocksize);
+ /* XXX */
+ return (blocksize);
}
/*
-* Initiate a data transfer
-*/
+ * Initiate a data transfer
+ */
static int
au88x0_chan_trigger(kobj_t obj, void *arg, int trigger)
{
-struct au88x0_chan_info *auci = arg;
+ struct au88x0_chan_info *auci = arg;
-(void)auci;
-switch (trigger) {
-case PCMTRIG_START:
-break;
-case PCMTRIG_STOP:
-case PCMTRIG_ABORT:
-break;
-}
-return (0);
+ (void)auci;
+ switch (trigger) {
+ case PCMTRIG_START:
+ break;
+ case PCMTRIG_STOP:
+ case PCMTRIG_ABORT:
+ break;
+ }
+ return (0);
}
/*
-*
-*/
+ *
+ */
static int
au88x0_chan_getptr(kobj_t obj, void *arg)
{
-/* XXX */
-return (0);
+ /* XXX */
+ return (0);
}
/*
-* Return the capabilities of a PCM channel
-*/
+ * Return the capabilities of a PCM channel
+ */
static struct pcmchan_caps *
au88x0_chan_getcaps(kobj_t obj, void *arg)
{
-return (&au88x0_capabilities);
+ return (&au88x0_capabilities);
}
/*
-* Channel interface glue
-*/
+ * Channel interface glue
+ */
static kobj_method_t au88x0_chan_methods[] = {
-KOBJMETHOD(channel_init, au88x0_chan_init),
-KOBJMETHOD(channel_setformat, au88x0_chan_setformat),
-KOBJMETHOD(channel_setspeed, au88x0_chan_setspeed),
-KOBJMETHOD(channel_setblocksize, au88x0_chan_setblocksize),
-KOBJMETHOD(channel_trigger, au88x0_chan_trigger),
-KOBJMETHOD(channel_getptr, au88x0_chan_getptr),
-KOBJMETHOD(channel_getcaps, au88x0_chan_getcaps),
-{ 0, 0 }
+ KOBJMETHOD(channel_init, au88x0_chan_init),
+ KOBJMETHOD(channel_setformat, au88x0_chan_setformat),
+ KOBJMETHOD(channel_setspeed, au88x0_chan_setspeed),
+ KOBJMETHOD(channel_setblocksize, au88x0_chan_setblocksize),
+ KOBJMETHOD(channel_trigger, au88x0_chan_trigger),
+ KOBJMETHOD(channel_getptr, au88x0_chan_getptr),
+ KOBJMETHOD(channel_getcaps, au88x0_chan_getcaps),
+ { 0, 0 }
};
CHANNEL_DECLARE(au88x0_chan);
-/*************************************************************************** * *
-* INTERRUPT HANDLER *
-* *
-***************************************************************************/
+/***************************************************************************\
+ * *
+ * INTERRUPT HANDLER *
+ * *
+\***************************************************************************/
static void
au88x0_intr(void *arg)
{
-struct au88x0_info *aui = arg;
-struct au88x0_chipset *auc = aui->aui_chipset;
-int pending, source;
-
-pending = au88x0_read(aui, auc->auc_irq_control, 4);
-if ((pending & AU88X0_IRQ_PENDING_BIT) == 0)
-return;
-source = au88x0_read(aui, auc->auc_irq_source, 4);
-if (source & AU88X0_IRQ_FATAL_ERR)
-device_printf(aui->aui_dev,
-"fatal error interrupt receivedn");
-if (source & AU88X0_IRQ_PARITY_ERR)
-device_printf(aui->aui_dev,
-"parity error interrupt receivedn");
-/* XXX handle the others... */
-
-/* acknowledge the interrupts we just handled */
-au88x0_write(aui, auc->auc_irq_source, source, 4);
-au88x0_read(aui, auc->auc_irq_source, 4);
+ struct au88x0_info *aui = arg;
+ struct au88x0_chipset *auc = aui->aui_chipset;
+ int pending, source;
+
+ pending = au88x0_read(aui, auc->auc_irq_control, 4);
+ if ((pending & AU88X0_IRQ_PENDING_BIT) == 0)
+ return;
+ source = au88x0_read(aui, auc->auc_irq_source, 4);
+ if (source & AU88X0_IRQ_FATAL_ERR)
+ device_printf(aui->aui_dev,
+ "fatal error interrupt received\n");
+ if (source & AU88X0_IRQ_PARITY_ERR)
+ device_printf(aui->aui_dev,
+ "parity error interrupt received\n");
+ /* XXX handle the others... */
+
+ /* acknowledge the interrupts we just handled */
+ au88x0_write(aui, auc->auc_irq_source, source, 4);
+ au88x0_read(aui, auc->auc_irq_source, 4);
}
-/*************************************************************************** * *
-* INITIALIZATION *
-* *
-***************************************************************************/
+/***************************************************************************\
+ * *
+ * INITIALIZATION *
+ * *
+\***************************************************************************/
/*
-* Reset and initialize the ADB and WT FIFOs
-*
-* - need to find out what the magic values 0x42000 and 0x2000 mean.
-*/
+ * Reset and initialize the ADB and WT FIFOs
+ *
+ * - need to find out what the magic values 0x42000 and 0x2000 mean.
+ */
static void
au88x0_fifo_init(struct au88x0_info *aui)
{
-struct au88x0_chipset *auc = aui->aui_chipset;
-int i;
+ struct au88x0_chipset *auc = aui->aui_chipset;
+ int i;
-/* reset, then clear the ADB FIFOs */
-for (i = 0; i < auc->auc_adb_fifos; ++i)
-au88x0_write(aui, auc->auc_adb_fifo_ctl + i * 4, 0x42000, 4);
-for (i = 0; i < auc->auc_adb_fifos * auc->auc_fifo_size; ++i)
-au88x0_write(aui, auc->auc_adb_fifo_base + i * 4, 0, 4);
+ /* reset, then clear the ADB FIFOs */
+ for (i = 0; i < auc->auc_adb_fifos; ++i)
+ au88x0_write(aui, auc->auc_adb_fifo_ctl + i * 4, 0x42000, 4);
+ for (i = 0; i < auc->auc_adb_fifos * auc->auc_fifo_size; ++i)
+ au88x0_write(aui, auc->auc_adb_fifo_base + i * 4, 0, 4);
-/* reset, then clear the WT FIFOs */
-for (i = 0; i < auc->auc_wt_fifos; ++i)
-au88x0_write(aui, auc->auc_wt_fifo_ctl + i * 4, 0x42000, 4);
-for (i = 0; i < auc->auc_wt_fifos * auc->auc_fifo_size; ++i)
-au88x0_write(aui, auc->auc_wt_fifo_base + i * 4, 0, 4);
+ /* reset, then clear the WT FIFOs */
+ for (i = 0; i < auc->auc_wt_fifos; ++i)
+ au88x0_write(aui, auc->auc_wt_fifo_ctl + i * 4, 0x42000, 4);
+ for (i = 0; i < auc->auc_wt_fifos * auc->auc_fifo_size; ++i)
+ au88x0_write(aui, auc->auc_wt_fifo_base + i * 4, 0, 4);
}
/*
-* Hardware initialization
-*/
+ * Hardware initialization
+ */
static void
au88x0_init(struct au88x0_info *aui)
{
-struct au88x0_chipset *auc = aui->aui_chipset;
+ struct au88x0_chipset *auc = aui->aui_chipset;
-/* reset the chip */
-au88x0_write(aui, auc->auc_control, 0xffffffff, 4);
-DELAY(10000);
+ /* reset the chip */
+ au88x0_write(aui, auc->auc_control, 0xffffffff, 4);
+ DELAY(10000);
-/* clear all interrupts */
-au88x0_write(aui, auc->auc_irq_source, 0xffffffff, 4);
-au88x0_read(aui, auc->auc_irq_source, 4);
-au88x0_read(aui, auc->auc_irq_status, 4);
+ /* clear all interrupts */
+ au88x0_write(aui, auc->auc_irq_source, 0xffffffff, 4);
+ au88x0_read(aui, auc->auc_irq_source, 4);
+ au88x0_read(aui, auc->auc_irq_status, 4);
-/* initialize the codec */
-au88x0_codec_init(aui);
+ /* initialize the codec */
+ au88x0_codec_init(aui);
-/* initialize the fifos */
-au88x0_fifo_init(aui);
+ /* initialize the fifos */
+ au88x0_fifo_init(aui);
-/* initialize the DMA engine */
-/* XXX chicken-waving! */
-au88x0_write(aui, auc->auc_dma_control, 0x1380000, 4);
+ /* initialize the DMA engine */
+ /* XXX chicken-waving! */
+ au88x0_write(aui, auc->auc_dma_control, 0x1380000, 4);
}
/*
-* Construct and set status string
-*/
+ * Construct and set status string
+ */
static void
au88x0_set_status(device_t dev)
{
-char status[SND_STATUSLEN];
-struct au88x0_info *aui;
+ char status[SND_STATUSLEN];
+ struct au88x0_info *aui;
-aui = pcm_getdevinfo(dev);
-snprintf(status, sizeof status, "at %s 0x%lx irq %ld %s",
-(aui->aui_regtype == SYS_RES_IOPORT)? "io" : "memory",
-rman_get_start(aui->aui_reg), rman_get_start(aui->aui_irq),PCM_KLDSTRING(snd_au88x0));
-pcm_setstatus(dev, status);
+ aui = pcm_getdevinfo(dev);
+ snprintf(status, sizeof status, "at %s 0x%lx irq %ld %s",
+ (aui->aui_regtype == SYS_RES_IOPORT)? "io" : "memory",
+ rman_get_start(aui->aui_reg), rman_get_start(aui->aui_irq),PCM_KLDSTRING(snd_au88x0));
+ pcm_setstatus(dev, status);
}
-/*************************************************************************** * *
-* PCI INTERFACE *
-* *
-***************************************************************************/
+/***************************************************************************\
+ * *
+ * PCI INTERFACE *
+ * *
+\***************************************************************************/
/*
-* Probe
-*/
+ * Probe
+ */
static int
au88x0_pci_probe(device_t dev)
{
-struct au88x0_chipset *auc;
-uint32_t pci_id;
+ struct au88x0_chipset *auc;
+ uint32_t pci_id;
-pci_id = pci_get_devid(dev);
-for (auc = au88x0_chipsets; auc->auc_pci_id; ++auc) {
-if (auc->auc_pci_id == pci_id) {
-device_set_desc(dev, auc->auc_name);
-return BUS_PROBE_DEFAULT;
-}
-}
-return (ENXIO);
+ pci_id = pci_get_devid(dev);
+ for (auc = au88x0_chipsets; auc->auc_pci_id; ++auc) {
+ if (auc->auc_pci_id == pci_id) {
+ device_set_desc(dev, auc->auc_name);
+ return BUS_PROBE_DEFAULT;
+ }
+ }
+ return (ENXIO);
}
/*
-* Attach
-*/
+ * Attach
+ */
static int
au88x0_pci_attach(device_t dev)
{
-struct au88x0_chipset *auc;
-struct au88x0_info *aui = NULL;
-uint32_t config;
-int error;
-
-if ((aui = malloc(sizeof *aui, M_DEVBUF, M_NOWAIT|M_ZERO)) == NULL) {
-device_printf(dev, "failed to allocate softcn");
-return (ENXIO);
-}
-aui->aui_dev = dev;
-
-/* Model-specific parameters */
-aui->aui_model = pci_get_devid(dev);
-for (auc = au88x0_chipsets; auc->auc_pci_id; ++auc)
-if (auc->auc_pci_id == aui->aui_model)
-aui->aui_chipset = auc;
-if (aui->aui_chipset == NULL)
-panic("%s() called for non-au88x0 device", __func__);
-
-/* enable pio, mmio, bus-mastering dma */
-config = pci_read_config(dev, PCIR_COMMAND, 2);
-config |= (PCIM_CMD_PORTEN|PCIM_CMD_MEMEN|PCIM_CMD_BUSMASTEREN);
-pci_write_config(dev, PCIR_COMMAND, config, 2);
-
-/* register mapping */
-config = pci_read_config(dev, PCIR_COMMAND, 2);
-if (config & PCIM_CMD_MEMEN) {
-/* try memory-mapped I/O */
-aui->aui_regid = PCIR_BAR(0);
-aui->aui_regtype = SYS_RES_MEMORY;
-aui->aui_reg = bus_alloc_resource_any(dev, aui->aui_regtype,
-&aui->aui_regid, RF_ACTIVE);
-}
-if (aui->aui_reg == NULL && (config & PCIM_CMD_PORTEN)) {
-/* fall back on port I/O */
-aui->aui_regid = PCIR_BAR(0);
-aui->aui_regtype = SYS_RES_IOPORT;
-aui->aui_reg = bus_alloc_resource_any(dev, aui->aui_regtype,
-&aui->aui_regid, RF_ACTIVE);
-}
-if (aui->aui_reg == NULL) {
-/* both mmio and pio failed... */
-device_printf(dev, "failed to map registersn");
-goto failed;
-}
-aui->aui_spct = rman_get_bustag(aui->aui_reg);
-aui->aui_spch = rman_get_bushandle(aui->aui_reg);
-
-/* IRQ mapping */
-aui->aui_irqid = 0;
-aui->aui_irqtype = SYS_RES_IRQ;
-aui->aui_irq = bus_alloc_resource_any(dev, aui->aui_irqtype,
-&aui->aui_irqid, RF_ACTIVE | RF_SHAREABLE);
-if (aui->aui_irq == 0) {
-device_printf(dev, "failed to map IRQn");
-goto failed;
-}
-
-/* install interrupt handler */
-error = snd_setup_intr(dev, aui->aui_irq, 0, au88x0_intr,
-aui, &aui->aui_irqh);
-if (error != 0) {
-device_printf(dev, "failed to install interrupt handlern");
-goto failed;
-}
-
-/* DMA mapping */
-aui->aui_bufsize = pcm_getbuffersize(dev, AU88X0_BUFSIZE_MIN,
-AU88X0_BUFSIZE_DFLT, AU88X0_BUFSIZE_MAX);
-error = bus_dma_tag_create(NULL,
-2, 0, /* 16-bit alignment, no boundary */
-BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, /* restrict to 4GB */
-NULL, NULL, /* no filter */
-aui->aui_bufsize, 1, aui->aui_bufsize,
-0, busdma_lock_mutex, &Giant, &aui->aui_dmat);
-if (error != 0) {
-device_printf(dev, "failed to create DMA tagn");
-goto failed;
-}
-
-/* initialize the hardware */
-au88x0_init(aui);
-
-/* initialize the ac97 codec and mixer */
-if ((aui->aui_ac97i = AC97_CREATE(dev, aui, au88x0_ac97)) == NULL) {
-device_printf(dev, "failed to initialize ac97 codecn");
-goto failed;
-}
-if (mixer_init(dev, ac97_getmixerclass(), aui->aui_ac97i) != 0) {
-device_printf(dev, "failed to initialize ac97 mixern");
-goto failed;
-}
-
-/* register with the pcm driver */
-if (pcm_register(dev, aui, 0, 0))
-goto failed;
-pcm_addchan(dev, PCMDIR_PLAY, &au88x0_chan_class, aui);
+ struct au88x0_chipset *auc;
+ struct au88x0_info *aui = NULL;
+ uint32_t config;
+ int error;
+
+ aui = malloc(sizeof(*aui), M_DEVBUF, M_WAITOK | M_ZERO);
+ aui->aui_dev = dev;
+
+ /* Model-specific parameters */
+ aui->aui_model = pci_get_devid(dev);
+ for (auc = au88x0_chipsets; auc->auc_pci_id; ++auc)
+ if (auc->auc_pci_id == aui->aui_model)
+ aui->aui_chipset = auc;
+ if (aui->aui_chipset == NULL)
+ panic("%s() called for non-au88x0 device", __func__);
+
+ /* enable pio, mmio, bus-mastering dma */
+ config = pci_read_config(dev, PCIR_COMMAND, 2);
+ config |= (PCIM_CMD_PORTEN|PCIM_CMD_MEMEN|PCIM_CMD_BUSMASTEREN);
+ pci_write_config(dev, PCIR_COMMAND, config, 2);
+
+ /* register mapping */
+ config = pci_read_config(dev, PCIR_COMMAND, 2);
+ if (config & PCIM_CMD_MEMEN) {
+ /* try memory-mapped I/O */
+ aui->aui_regid = PCIR_BAR(0);
+ aui->aui_regtype = SYS_RES_MEMORY;
+ aui->aui_reg = bus_alloc_resource_any(dev, aui->aui_regtype,
+ &aui->aui_regid, RF_ACTIVE);
+ }
+ if (aui->aui_reg == NULL && (config & PCIM_CMD_PORTEN)) {
+ /* fall back on port I/O */
+ aui->aui_regid = PCIR_BAR(0);
+ aui->aui_regtype = SYS_RES_IOPORT;
+ aui->aui_reg = bus_alloc_resource_any(dev, aui->aui_regtype,
+ &aui->aui_regid, RF_ACTIVE);
+ }
+ if (aui->aui_reg == NULL) {
+ /* both mmio and pio failed... */
+ device_printf(dev, "failed to map registers\n");
+ goto failed;
+ }
+ aui->aui_spct = rman_get_bustag(aui->aui_reg);
+ aui->aui_spch = rman_get_bushandle(aui->aui_reg);
+
+ /* IRQ mapping */
+ aui->aui_irqid = 0;
+ aui->aui_irqtype = SYS_RES_IRQ;
+ aui->aui_irq = bus_alloc_resource_any(dev, aui->aui_irqtype,
+ &aui->aui_irqid, RF_ACTIVE | RF_SHAREABLE);
+ if (aui->aui_irq == 0) {
+ device_printf(dev, "failed to map IRQ\n");
+ goto failed;
+ }
+
+ /* install interrupt handler */
+ error = snd_setup_intr(dev, aui->aui_irq, 0, au88x0_intr,
+ aui, &aui->aui_irqh);
+ if (error != 0) {
+ device_printf(dev, "failed to install interrupt handler\n");
+ goto failed;
+ }
+
+ /* DMA mapping */
+ aui->aui_bufsize = pcm_getbuffersize(dev, AU88X0_BUFSIZE_MIN,
+ AU88X0_BUFSIZE_DFLT, AU88X0_BUFSIZE_MAX);
+ error = bus_dma_tag_create(bus_get_dma_tag(dev),
+ 2, 0, /* 16-bit alignment, no boundary */
+ BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, /* restrict to 4GB */
+ NULL, NULL, /* no filter */
+ aui->aui_bufsize, 1, aui->aui_bufsize,
+ 0, busdma_lock_mutex, &Giant, &aui->aui_dmat);
+ if (error != 0) {
+ device_printf(dev, "failed to create DMA tag\n");
+ goto failed;
+ }
+
+ /* initialize the hardware */
+ au88x0_init(aui);
+
+ /* initialize the ac97 codec and mixer */
+ if ((aui->aui_ac97i = AC97_CREATE(dev, aui, au88x0_ac97)) == NULL) {
+ device_printf(dev, "failed to initialize ac97 codec\n");
+ goto failed;
+ }
+ if (mixer_init(dev, ac97_getmixerclass(), aui->aui_ac97i) != 0) {
+ device_printf(dev, "failed to initialize ac97 mixer\n");
+ goto failed;
+ }
+
+ /* register with the pcm driver */
+ if (pcm_register(dev, aui, 0, 0))
+ goto failed;
+ pcm_addchan(dev, PCMDIR_PLAY, &au88x0_chan_class, aui);
#if 0
-pcm_addchan(dev, PCMDIR_REC, &au88x0_chan_class, aui);
+ pcm_addchan(dev, PCMDIR_REC, &au88x0_chan_class, aui);
#endif
-au88x0_set_status(dev);
+ au88x0_set_status(dev);
-return (0);
+ return (0);
failed:
-if (aui->aui_ac97i != NULL)
-ac97_destroy(aui->aui_ac97i);
-if (aui->aui_dmat)
-bus_dma_tag_destroy(aui->aui_dmat);
-if (aui->aui_irqh != NULL)
-bus_teardown_intr(dev, aui->aui_irq, aui->aui_irqh);
-if (aui->aui_irq)
-bus_release_resource(dev, aui->aui_irqtype,
-aui->aui_irqid, aui->aui_irq);
-if (aui->aui_reg)
-bus_release_resource(dev, aui->aui_regtype,
-aui->aui_regid, aui->aui_reg);
-free(aui, M_DEVBUF);
-return (ENXIO);
+ if (aui->aui_ac97i != NULL)
+ ac97_destroy(aui->aui_ac97i);
+ if (aui->aui_dmat)
+ bus_dma_tag_destroy(aui->aui_dmat);
+ if (aui->aui_irqh != NULL)
+ bus_teardown_intr(dev, aui->aui_irq, aui->aui_irqh);
+ if (aui->aui_irq)
+ bus_release_resource(dev, aui->aui_irqtype,
+ aui->aui_irqid, aui->aui_irq);
+ if (aui->aui_reg)
+ bus_release_resource(dev, aui->aui_regtype,
+ aui->aui_regid, aui->aui_reg);
+ free(aui, M_DEVBUF);
+ return (ENXIO);
}
/*
-* Detach
-*/
+ * Detach
+ */
static int
au88x0_pci_detach(device_t dev)
{
-struct au88x0_info *aui;
-int error;
+ struct au88x0_info *aui;
+ int error;
-aui = pcm_getdevinfo(dev);
-if ((error = pcm_unregister(dev)) != 0)
-return (error);
+ aui = pcm_getdevinfo(dev);
+ if ((error = pcm_unregister(dev)) != 0)
+ return (error);
-/* release resources in reverse order */
-bus_dma_tag_destroy(aui->aui_dmat);
-bus_teardown_intr(dev, aui->aui_irq, aui->aui_irqh);
-bus_release_resource(dev, aui->aui_irqtype,
-aui->aui_irqid, aui->aui_irq);
-bus_release_resource(dev, aui->aui_regtype,
-aui->aui_regid, aui->aui_reg);
-free(aui, M_DEVBUF);
+ /* release resources in reverse order */
+ bus_dma_tag_destroy(aui->aui_dmat);
+ bus_teardown_intr(dev, aui->aui_irq, aui->aui_irqh);
+ bus_release_resource(dev, aui->aui_irqtype,
+ aui->aui_irqid, aui->aui_irq);
+ bus_release_resource(dev, aui->aui_regtype,
+ aui->aui_regid, aui->aui_reg);
+ free(aui, M_DEVBUF);
-return (0);
+ return (0);
}
/*
-* Driver glue
-*/
+ * Driver glue
+ */
static device_method_t au88x0_methods[] = {
-DEVMETHOD(device_probe, au88x0_pci_probe),
-DEVMETHOD(device_attach, au88x0_pci_attach),
-DEVMETHOD(device_detach, au88x0_pci_detach),
-{ 0, 0 }
+ DEVMETHOD(device_probe, au88x0_pci_probe),
+ DEVMETHOD(device_attach, au88x0_pci_attach),
+ DEVMETHOD(device_detach, au88x0_pci_detach),
+ { 0, 0 }
};
static driver_t au88x0_driver = {
-"pcm",
-au88x0_methods,
-PCM_SOFTC_SIZE,
+ "pcm",
+ au88x0_methods,
+ PCM_SOFTC_SIZE,
};
DRIVER_MODULE(snd_au88x0, pci, au88x0_driver, pcm_devclass, 0, 0);
Index: neomagic-coeff.h
===================================================================
RCS file: /home/cvs/src/sys/dev/sound/pci/neomagic-coeff.h,v
retrieving revision 1.2
retrieving revision 1.3
diff -L sys/dev/sound/pci/neomagic-coeff.h -L sys/dev/sound/pci/neomagic-coeff.h -u -r1.2 -r1.3
--- sys/dev/sound/pci/neomagic-coeff.h
+++ sys/dev/sound/pci/neomagic-coeff.h
@@ -1,4639 +1,4638 @@
/*-
-* Copyright (c) 1999 Cameron Grant <cg at freebsd.org>
-* All rights reserved.
-*
-* Derived from the public domain Linux driver
-*
-* Redistribution and use in source and binary forms, with or without
-* modification, are permitted provided that the following conditions
-* are met:
-* 1. Redistributions of source code must retain the above copyright
-* notice, this list of conditions and the following disclaimer.
-* 2. Redistributions in binary form must reproduce the above copyright
-* notice, this list of conditions and the following disclaimer in the
-* documentation and/or other materials provided with the distribution.
-*
-* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
-* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
-* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
-* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
-* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHERIN CONTRACT, STRICT
-* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
-* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THEPOSSIBILITY OF
-* SUCH DAMAGE.
-*
-* $MidnightBSD$
-* $FreeBSD: src/sys/dev/sound/pci/neomagic-coeff.h,v 1.4 2005/01/06 01:43:19 imp Exp $
-*/
+ * Copyright (c) 1999 Cameron Grant <cg at freebsd.org>
+ * All rights reserved.
+ *
+ * Derived from the public domain Linux driver
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHERIN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THEPOSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD: src/sys/dev/sound/pci/neomagic-coeff.h,v 1.4 2005/01/06 01:43:19 imp Exp $
+ */
#define NM_TOTAL_COEFF_COUNT 0x3158
static u_char coefficients[NM_TOTAL_COEFF_COUNT * 4] = {
-0xFF, 0xFF, 0x2F, 0x00, 0x4B, 0xFF, 0xA5, 0x01, 0xEF, 0xFC, 0x21,
-0x05, 0x87, 0xF7, 0x62, 0x11, 0xE9, 0x45, 0x5E, 0xF9, 0xB5, 0x01,
-0xDE, 0xFF, 0xA4, 0xFF, 0x60, 0x00, 0xCA, 0xFF, 0x0D, 0x00, 0xFD,
-0xFF, 0x36, 0x00, 0x36, 0xFF, 0xE6, 0x01, 0x3D, 0xFC, 0xD6, 0x06,
-0x4C, 0xF3, 0xED, 0x20, 0x3D, 0x3D, 0x4A, 0xF3, 0x4E, 0x05, 0xB1,
-0xFD, 0xE1, 0x00, 0xC3, 0xFF, 0x05, 0x00, 0x02, 0x00, 0xFD, 0xFF,
-0x2A, 0x00, 0x5C, 0xFF, 0xAA, 0x01, 0x71, 0xFC, 0x07, 0x07, 0x7E,
-0xF1, 0x44, 0x30, 0x44, 0x30, 0x7E, 0xF1, 0x07, 0x07, 0x71, 0xFC,
-0xAA, 0x01, 0x5C, 0xFF, 0x2A, 0x00, 0xFD, 0xFF, 0x02, 0x00, 0x05,
-0x00, 0xC3, 0xFF, 0xE1, 0x00, 0xB1, 0xFD, 0x4E, 0x05, 0x4A, 0xF3,
-0x3D, 0x3D, 0xED, 0x20, 0x4C, 0xF3, 0xD6, 0x06, 0x3D, 0xFC, 0xE6,
-0x01, 0x36, 0xFF, 0x36, 0x00, 0xFD, 0xFF, 0x0D, 0x00, 0xCA, 0xFF,
-0x60, 0x00, 0xA4, 0xFF, 0xDE, 0xFF, 0xB5, 0x01, 0x5E, 0xF9, 0xE9,
-0x45, 0x62, 0x11, 0x87, 0xF7, 0x21, 0x05, 0xEF, 0xFC, 0xA5, 0x01,
-0x4B, 0xFF, 0x2F, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x1E, 0x00, 0x84,
-0xFF, 0x11, 0x01, 0x34, 0xFE, 0x8F, 0x02, 0xC7, 0xFC, 0xAE, 0x03,
-0xF7, 0x48, 0xAE, 0x03, 0xC7, 0xFC, 0x8F, 0x02, 0x34, 0xFE, 0x11,
-0x01, 0x84, 0xFF, 0x1E, 0x00, 0xFE, 0xFF, 0x34, 0x00, 0x3D, 0xFF,
-0xCA, 0x01, 0x95, 0xFC, 0xEA, 0x05, 0xBB, 0xF5, 0x25, 0x17, 0x3C,
-0x43, 0x8D, 0xF6, 0x43, 0x03, 0xF5, 0xFE, 0x26, 0x00, 0x20, 0x00,
-0xE2, 0xFF, 0x08, 0x00, 0xFD, 0xFF, 0x30, 0x00, 0x4D, 0xFF, 0xC5,
-0x01, 0x4C, 0xFC, 0x26, 0x07, 0xA3, 0xF1, 0xAB, 0x2C, 0xBB, 0x33,
-0x8F, 0xF1, 0xCA, 0x06, 0xA6, 0xFC, 0x85, 0x01, 0x6F, 0xFF, 0x24,
-0x00, 0xFD, 0xFF, 0x03, 0x00, 0xFE, 0xFF, 0xD5, 0xFF, 0xBC, 0x00,
-0xF0, 0xFD, 0xEC, 0x04, 0xD9, 0xF3, 0xB1, 0x3E, 0xCD, 0x1E, 0xC1,
-0xF3, 0xAF, 0x06, 0x49, 0xFC, 0xE4, 0x01, 0x36, 0xFF, 0x36, 0x00,
-0xFE, 0xFF, 0x16, 0x00, 0xA6, 0xFF, 0xBB, 0x00, 0xE9, 0xFE, 0x38,
-0x01, 0x4B, 0xFF, 0x28, 0xFE, 0x3A, 0x48, 0x04, 0x0A, 0x2E, 0xFA,
-0xDF, 0x03, 0x8A, 0xFD, 0x60, 0x01, 0x65, 0xFF, 0x27, 0x00, 0x00,
-0x00, 0xFF, 0xFF, 0x2E, 0x00, 0x50, 0xFF, 0x98, 0x01, 0x0D, 0xFD,
-0xE0, 0x04, 0x14, 0xF8, 0xC3, 0x0F, 0x89, 0x46, 0x4C, 0xFA, 0x38,
-0x01, 0x25, 0x00, 0x7D, 0xFF, 0x73, 0x00, 0xC2, 0xFF, 0x0F, 0x00,
-0xFD, 0xFF, 0x35, 0x00, 0x3A, 0xFF, 0xE3, 0x01, 0x31, 0xFC, 0x0F,
-0x07, 0x84, 0xF2, 0x29, 0x25, 0x1A, 0x3A, 0x67, 0xF2, 0xF6, 0x05,
-0x41, 0xFD, 0x24, 0x01, 0xA1, 0xFF, 0x12, 0x00, 0x00, 0x00, 0xFF,
-0xFF, 0x15, 0x00, 0x97, 0xFF, 0x37, 0x01, 0x22, 0xFD, 0x23, 0x06,
-0x2F, 0xF2, 0x11, 0x39, 0x7B, 0x26, 0x50, 0xF2, 0x1B, 0x07, 0x32,
-0xFC, 0xE1, 0x01, 0x3C, 0xFF, 0x35, 0x00, 0xFD, 0xFF, 0x0E, 0x00,
-0xC8, 0xFF, 0x64, 0x00, 0x9B, 0xFF, 0xEE, 0xFF, 0x98, 0x01, 0x93,
-0xF9, 0x10, 0x46, 0x03, 0x11, 0xA7, 0xF7, 0x12, 0x05, 0xF6, 0xFC,
-0xA2, 0x01, 0x4C, 0xFF, 0x2F, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x26,
-0x00, 0x6A, 0xFF, 0x53, 0x01, 0xA6, 0xFD, 0xA6, 0x03, 0xA1, 0xFA,
-0xDE, 0x08, 0x76, 0x48, 0x0C, 0xFF, 0xDE, 0xFE, 0x73, 0x01, 0xC9,
-0xFE, 0xCA, 0x00, 0xA0, 0xFF, 0x17, 0x00, 0xFE, 0xFF, 0x36, 0x00,
-0x36, 0xFF, 0xE1, 0x01, 0x52, 0xFC, 0x93, 0x06, 0x10, 0xF4, 0x78,
-0x1D, 0x90, 0x3F, 0x3E, 0xF4, 0xAA, 0x04, 0x19, 0xFE, 0xA4, 0x00,
-0xE2, 0xFF, 0xFA, 0xFF, 0x03, 0x00, 0xFD, 0xFF, 0x26, 0x00, 0x68,
-0xFF, 0x93, 0x01, 0x92, 0xFC, 0xE2, 0x06, 0x83, 0xF1, 0x8C, 0x32,
-0xED, 0x2D, 0x90, 0xF1, 0x1E, 0x07, 0x57, 0xFC, 0xBD, 0x01, 0x51,
-0xFF, 0x2E, 0x00, 0xFD, 0xFF, 0x07, 0x00, 0xE8, 0xFF, 0x12, 0x00,
-0x42, 0x00, 0xC4, 0xFE, 0x94, 0x03, 0x02, 0xF6, 0x89, 0x42, 0x76,
-0x18, 0x5C, 0xF5, 0x12, 0x06, 0x84, 0xFC, 0xD1, 0x01, 0x3B, 0xFF,
-0x34, 0x00, 0xFE, 0xFF, 0x1D, 0x00, 0x8A, 0xFF, 0x03, 0x01, 0x53,
-0xFE, 0x53, 0x02, 0x39, 0xFD, 0xA9, 0x02, 0xF2, 0x48, 0xB9, 0x04,
-0x54, 0xFC, 0xCA, 0x02, 0x16, 0xFE, 0x20, 0x01, 0x7F, 0xFF, 0x20,
-0x00, 0x00, 0x00, 0xFF, 0xFF, 0x33, 0x00, 0x40, 0xFF, 0xC3, 0x01,
-0xA7, 0xFC, 0xC0, 0x05, 0x1E, 0xF6, 0xD8, 0x15, 0xE7, 0x43, 0x20,
-0xF7, 0xEF, 0x02, 0x27, 0xFF, 0x0A, 0x00, 0x2E, 0x00, 0xDD, 0xFF,
-0x09, 0x00, 0xFD, 0xFF, 0x31, 0x00, 0x48, 0xFF, 0xCD, 0x01, 0x43,
-0xFC, 0x2A, 0x07, 0xBC, 0xF1, 0x64, 0x2B, 0xE3, 0x34, 0xA3, 0xF1,
-0xAE, 0x06, 0xBD, 0xFC, 0x77, 0x01, 0x77, 0xFF, 0x21, 0x00, 0xFE,
-0xFF, 0x02, 0x00, 0x03, 0x00, 0xCA, 0xFF, 0xD4, 0x00, 0xC8, 0xFD,
-0x2A, 0x05, 0x7D, 0xF3, 0xCA, 0x3D, 0x22, 0x20, 0x76, 0xF3, 0xC8,
-0x06, 0x41, 0xFC, 0xE6, 0x01, 0x36, 0xFF, 0x36, 0x00, 0xFD, 0xFF,
-0x14, 0x00, 0xAC, 0xFF, 0xAC, 0x00, 0x08, 0xFF, 0xFD, 0x00, 0xB5,
-0xFF, 0x4B, 0xFD, 0xF4, 0x47, 0x30, 0x0B, 0xBC, 0xF9, 0x17, 0x04,
-0x6E, 0xFD, 0x6D, 0x01, 0x60, 0xFF, 0x29, 0x00, 0x00, 0x00, 0xFF,
-0xFF, 0x2C, 0x00, 0x54, 0xFF, 0x8D, 0x01, 0x26, 0xFD, 0xAD, 0x04,
-0x82, 0xF8, 0x87, 0x0E, 0xF9, 0x46, 0x0C, 0xFB, 0xD4, 0x00, 0x5D,
-0x00, 0x5E, 0xFF, 0x82, 0x00, 0xBD, 0xFF, 0x10, 0x00, 0xFD, 0xFF,
-0x36, 0x00, 0x38, 0xFF, 0xE5, 0x01, 0x33, 0xFC, 0x01, 0x07, 0xBE,
-0xF2, 0xD6, 0x23, 0x1F, 0x3B, 0xA5, 0xF2, 0xC5, 0x05, 0x62, 0xFD,
-0x10, 0x01, 0xAB, 0xFF, 0x0E, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x19,
-0x00, 0x8E, 0xFF, 0x49, 0x01, 0x04, 0xFD, 0x4D, 0x06, 0x00, 0xF2,
-0xFE, 0x37, 0xCB, 0x27, 0x21, 0xF2, 0x23, 0x07, 0x34, 0xFC, 0xDD,
-0x01, 0x3F, 0xFF, 0x34, 0x00, 0xFD, 0xFF, 0x0C, 0x00, 0xCE, 0xFF,
-0x56, 0x00, 0xB9, 0xFF, 0xB8, 0xFF, 0xF7, 0x01, 0xE2, 0xF8, 0x8D,
-0x45, 0x46, 0x12, 0x3C, 0xF7, 0x43, 0x05, 0xDF, 0xFC, 0xAC, 0x01,
-0x48, 0xFF, 0x30, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x24, 0x00, 0x70,
-0xFF, 0x46, 0x01, 0xC3, 0xFD, 0x6D, 0x03, 0x14, 0xFB, 0xBE, 0x07,
-0xA6, 0x48, 0xF8, 0xFF, 0x70, 0xFE, 0xAE, 0x01, 0xAA, 0xFE, 0xD9,
-0x00, 0x9A, 0xFF, 0x19, 0x00, 0xFE, 0xFF, 0x36, 0x00, 0x37, 0xFF,
-0xDE, 0x01, 0x5D, 0xFC, 0x74, 0x06, 0x63, 0xF4, 0x23, 0x1C, 0x66,
-0x40, 0xAA, 0xF4, 0x65, 0x04, 0x44, 0xFE, 0x8B, 0x00, 0xEE, 0xFF,
-0xF5, 0xFF, 0x04, 0x00, 0xFD, 0xFF, 0x29, 0x00, 0x61, 0xFF, 0x9F,
-0x01, 0x80, 0xFC, 0xF7, 0x06, 0x7D, 0xF1, 0x5A, 0x31, 0x2C, 0x2F,
-0x83, 0xF1, 0x13, 0x07, 0x64, 0xFC, 0xB3, 0x01, 0x57, 0xFF, 0x2C,
-0x00, 0xFD, 0xFF, 0x06, 0x00, 0xED, 0xFF, 0x05, 0x00, 0x5D, 0x00,
-0x95, 0xFE, 0xE2, 0x03, 0x7F, 0xF5, 0xCC, 0x41, 0xC7, 0x19, 0xFF,
-0xF4, 0x37, 0x06, 0x75, 0xFC, 0xD6, 0x01, 0x39, 0xFF, 0x35, 0x00,
-0xFE, 0xFF, 0x1B, 0x00, 0x90, 0xFF, 0xF4, 0x00, 0x72, 0xFE, 0x18,
-0x02, 0xAA, 0xFD, 0xAB, 0x01, 0xDF, 0x48, 0xCA, 0x05, 0xE1, 0xFB,
-0x05, 0x03, 0xF7, 0xFD, 0x2E, 0x01, 0x79, 0xFF, 0x21, 0x00, 0x00,
-0x00, 0xFF, 0xFF, 0x32, 0x00, 0x43, 0xFF, 0xBB, 0x01, 0xBA, 0xFC,
-0x95, 0x05, 0x83, 0xF6, 0x8C, 0x14, 0x87, 0x44, 0xBB, 0xF7, 0x98,
-0x02, 0x5A, 0xFF, 0xEE, 0xFF, 0x3C, 0x00, 0xD8, 0xFF, 0x0A, 0x00,
-0xFD, 0xFF, 0x32, 0x00, 0x44, 0xFF, 0xD3, 0x01, 0x3C, 0xFC, 0x2A,
-0x07, 0xDC, 0xF1, 0x1A, 0x2A, 0x06, 0x36, 0xBE, 0xF1, 0x8E, 0x06,
-0xD5, 0xFC, 0x67, 0x01, 0x7F, 0xFF, 0x1E, 0x00, 0xFE, 0xFF, 0x01,
-0x00, 0x07, 0x00, 0xBE, 0xFF, 0xEA, 0x00, 0xA2, 0xFD, 0x65, 0x05,
-0x28, 0xF3, 0xDB, 0x3C, 0x78, 0x21, 0x30, 0xF3, 0xDF, 0x06, 0x3A,
-0xFC, 0xE6, 0x01, 0x37, 0xFF, 0x36, 0x00, 0xFD, 0xFF, 0x13, 0x00,
-0xB2, 0xFF, 0x9D, 0x00, 0x27, 0xFF, 0xC3, 0x00, 0x1F, 0x00, 0x76,
-0xFC, 0xA3, 0x47, 0x60, 0x0C, 0x4A, 0xF9, 0x4E, 0x04, 0x53, 0xFD,
-0x79, 0x01, 0x5C, 0xFF, 0x2A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2B,
-0x00, 0x58, 0xFF, 0x82, 0x01, 0x3F, 0xFD, 0x78, 0x04, 0xF2, 0xF8,
-0x50, 0x0D, 0x5E, 0x47, 0xD5, 0xFB, 0x6F, 0x00, 0x96, 0x00, 0x40,
-0xFF, 0x91, 0x00, 0xB7, 0xFF, 0x12, 0x00, 0xFD, 0xFF, 0x36, 0x00,
-0x37, 0xFF, 0xE6, 0x01, 0x36, 0xFC, 0xEF, 0x06, 0xFC, 0xF2, 0x81,
-0x22, 0x1C, 0x3C, 0xEC, 0xF2, 0x90, 0x05, 0x85, 0xFD, 0xFB, 0x00,
-0xB6, 0xFF, 0x0A, 0x00, 0x01, 0x00, 0xFE, 0xFF, 0x1C, 0x00, 0x85,
-0xFF, 0x5B, 0x01, 0xE9, 0xFC, 0x73, 0x06, 0xD8, 0xF1, 0xE5, 0x36,
-0x19, 0x29, 0xF8, 0xF1, 0x29, 0x07, 0x37, 0xFC, 0xD8, 0x01, 0x42,
-0xFF, 0x33, 0x00, 0xFD, 0xFF, 0x0B, 0x00, 0xD3, 0xFF, 0x47, 0x00,
-0xD7, 0xFF, 0x82, 0xFF, 0x53, 0x02, 0x39, 0xF8, 0xFD, 0x44, 0x8D,
-0x13, 0xD3, 0xF6, 0x72, 0x05, 0xCA, 0xFC, 0xB5, 0x01, 0x45, 0xFF,
-0x31, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x23, 0x00, 0x75, 0xFF, 0x39,
-0x01, 0xE0, 0xFD, 0x33, 0x03, 0x87, 0xFB, 0xA2, 0x06, 0xCB, 0x48,
-0xEA, 0x00, 0x01, 0xFE, 0xE9, 0x01, 0x8A, 0xFE, 0xE8, 0x00, 0x95,
-0xFF, 0x1A, 0x00, 0xFE, 0xFF, 0x35, 0x00, 0x38, 0xFF, 0xDA, 0x01,
-0x6A, 0xFC, 0x53, 0x06, 0xBA, 0xF4, 0xCE, 0x1A, 0x32, 0x41, 0x1F,
-0xF5, 0x1D, 0x04, 0x71, 0xFE, 0x71, 0x00, 0xFB, 0xFF, 0xF0, 0xFF,
-0x05, 0x00, 0xFD, 0xFF, 0x2B, 0x00, 0x5B, 0xFF, 0xAB, 0x01, 0x6F,
-0xFC, 0x08, 0x07, 0x7E, 0xF1, 0x21, 0x30, 0x67, 0x30, 0x7D, 0xF1,
-0x05, 0x07, 0x73, 0xFC, 0xA8, 0x01, 0x5C, 0xFF, 0x2A, 0x00, 0xFD,
-0xFF, 0x05, 0x00, 0xF2, 0xFF, 0xF8, 0xFF, 0x77, 0x00, 0x67, 0xFE,
-0x2D, 0x04, 0x04, 0xF5, 0x07, 0x41, 0x1B, 0x1B, 0xA6, 0xF4, 0x5A,
-0x06, 0x67, 0xFC, 0xDB, 0x01, 0x38, 0xFF, 0x36, 0x00, 0xFE, 0xFF,
-0x1A, 0x00, 0x96, 0xFF, 0xE5, 0x00, 0x91, 0xFE, 0xDC, 0x01, 0x1A,
-0xFE, 0xB3, 0x00, 0xC3, 0x48, 0xE1, 0x06, 0x6E, 0xFB, 0x40, 0x03,
-0xDA, 0xFD, 0x3C, 0x01, 0x74, 0xFF, 0x23, 0x00, 0x00, 0x00, 0xFF,
-0xFF, 0x31, 0x00, 0x46, 0xFF, 0xB3, 0x01, 0xCF, 0xFC, 0x67, 0x05,
-0xEA, 0xF6, 0x44, 0x13, 0x1E, 0x45, 0x5E, 0xF8, 0x3F, 0x02, 0x8E,
-0xFF, 0xD0, 0xFF, 0x4A, 0x00, 0xD2, 0xFF, 0x0B, 0x00, 0xFD, 0xFF,
-0x33, 0x00, 0x41, 0xFF, 0xD9, 0x01, 0x36, 0xFC, 0x28, 0x07, 0x01,
-0xF2, 0xCE, 0x28, 0x23, 0x37, 0xE0, 0xF1, 0x6B, 0x06, 0xEF, 0xFC,
-0x57, 0x01, 0x87, 0xFF, 0x1B, 0x00, 0xFE, 0xFF, 0x01, 0x00, 0x0B,
-0x00, 0xB4, 0xFF, 0x00, 0x01, 0x7E, 0xFD, 0x9C, 0x05, 0xDC, 0xF2,
-0xE4, 0x3B, 0xCD, 0x22, 0xEE, 0xF2, 0xF3, 0x06, 0x35, 0xFC, 0xE6,
-0x01, 0x37, 0xFF, 0x36, 0x00, 0xFD, 0xFF, 0x11, 0x00, 0xB8, 0xFF,
-0x8E, 0x00, 0x46, 0xFF, 0x8A, 0x00, 0x86, 0x00, 0xA7, 0xFB, 0x48,
-0x47, 0x95, 0x0D, 0xD9, 0xF8, 0x84, 0x04, 0x39, 0xFD, 0x85, 0x01,
-0x57, 0xFF, 0x2B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2A, 0x00, 0x5D,
-0xFF, 0x76, 0x01, 0x59, 0xFD, 0x42, 0x04, 0x63, 0xF9, 0x1C, 0x0C,
-0xB6, 0x47, 0xA4, 0xFC, 0x07, 0x00, 0xD0, 0x00, 0x20, 0xFF, 0xA0,
-0x00, 0xB1, 0xFF, 0x13, 0x00, 0xFD, 0xFF, 0x36, 0x00, 0x36, 0xFF,
-0xE6, 0x01, 0x3B, 0xFC, 0xDA, 0x06, 0x3F, 0xF3, 0x2C, 0x21, 0x11,
-0x3D, 0x3A, 0xF3, 0x58, 0x05, 0xAA, 0xFD, 0xE5, 0x00, 0xC1, 0xFF,
-0x06, 0x00, 0x01, 0x00, 0xFE, 0xFF, 0x1F, 0x00, 0x7D, 0xFF, 0x6B,
-0x01, 0xCF, 0xFC, 0x96, 0x06, 0xB7, 0xF1, 0xC6, 0x35, 0x64, 0x2A,
-0xD4, 0xF1, 0x2B, 0x07, 0x3D, 0xFC, 0xD2, 0x01, 0x45, 0xFF, 0x32,
-0x00, 0xFD, 0xFF, 0x0A, 0x00, 0xD9, 0xFF, 0x39, 0x00, 0xF4, 0xFF,
-0x4E, 0xFF, 0xAC, 0x02, 0x98, 0xF7, 0x65, 0x44, 0xD6, 0x14, 0x6C,
-0xF6, 0x9F, 0x05, 0xB6, 0xFC, 0xBD, 0x01, 0x42, 0xFF, 0x32, 0x00,
-0xFF, 0xFF, 0x00, 0x00, 0x21, 0x00, 0x7A, 0xFF, 0x2B, 0x01, 0xFE,
-0xFD, 0xF8, 0x02, 0xFB, 0xFB, 0x8D, 0x05, 0xE5, 0x48, 0xE3, 0x01,
-0x91, 0xFD, 0x25, 0x02, 0x6B, 0xFE, 0xF7, 0x00, 0x8F, 0xFF, 0x1C,
-0x00, 0xFE, 0xFF, 0x35, 0x00, 0x3A, 0xFF, 0xD5, 0x01, 0x78, 0xFC,
-0x2F, 0x06, 0x13, 0xF5, 0x7C, 0x19, 0xF7, 0x41, 0x9B, 0xF5, 0xD1,
-0x03, 0x9F, 0xFE, 0x57, 0x00, 0x08, 0x00, 0xEC, 0xFF, 0x06, 0x00,
-0xFD, 0xFF, 0x2D, 0x00, 0x55, 0xFF, 0xB5, 0x01, 0x61, 0xFC, 0x16,
-0x07, 0x85, 0xF1, 0xE6, 0x2E, 0x9E, 0x31, 0x7D, 0xF1, 0xF3, 0x06,
-0x84, 0xFC, 0x9D, 0x01, 0x63, 0xFF, 0x28, 0x00, 0xFD, 0xFF, 0x04,
-0x00, 0xF6, 0xFF, 0xEB, 0xFF, 0x91, 0x00, 0x3B, 0xFE, 0x75, 0x04,
-0x92, 0xF4, 0x36, 0x40, 0x6E, 0x1C, 0x50, 0xF4, 0x7B, 0x06, 0x5B,
-0xFC, 0xDF, 0x01, 0x37, 0xFF, 0x36, 0x00, 0xFE, 0xFF, 0x18, 0x00,
-0x9C, 0xFF, 0xD6, 0x00, 0xB1, 0xFE, 0xA1, 0x01, 0x89, 0xFE, 0xC3,
-0xFF, 0x9C, 0x48, 0xFD, 0x07, 0xFA, 0xFA, 0x7A, 0x03, 0xBC, 0xFD,
-0x49, 0x01, 0x6E, 0xFF, 0x24, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x30,
-0x00, 0x49, 0xFF, 0xAA, 0x01, 0xE4, 0xFC, 0x38, 0x05, 0x54, 0xF7,
-0xFE, 0x11, 0xAA, 0x45, 0x09, 0xF9, 0xE2, 0x01, 0xC4, 0xFF, 0xB3,
-0xFF, 0x59, 0x00, 0xCD, 0xFF, 0x0D, 0x00, 0xFD, 0xFF, 0x34, 0x00,
-0x3E, 0xFF, 0xDE, 0x01, 0x33, 0xFC, 0x22, 0x07, 0x2B, 0xF2, 0x80,
-0x27, 0x3B, 0x38, 0x0A, 0xF2, 0x44, 0x06, 0x0B, 0xFD, 0x45, 0x01,
-0x90, 0xFF, 0x18, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x0F, 0x00, 0xA9,
-0xFF, 0x15, 0x01, 0x5B, 0xFD, 0xD0, 0x05, 0x97, 0xF2, 0xE6, 0x3A,
-0x21, 0x24, 0xB1, 0xF2, 0x04, 0x07, 0x33, 0xFC, 0xE5, 0x01, 0x39,
-0xFF, 0x36, 0x00, 0xFD, 0xFF, 0x10, 0x00, 0xBE, 0xFF, 0x7F, 0x00,
-0x65, 0xFF, 0x51, 0x00, 0xEB, 0x00, 0xE1, 0xFA, 0xE1, 0x46, 0xCD,
-0x0E, 0x6A, 0xF8, 0xB8, 0x04, 0x20, 0xFD, 0x90, 0x01, 0x53, 0xFF,
-0x2D, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x28, 0x00, 0x62, 0xFF, 0x6A,
-0x01, 0x74, 0xFD, 0x0A, 0x04, 0xD5, 0xF9, 0xED, 0x0A, 0x03, 0x48,
-0x7C, 0xFD, 0x9E, 0xFF, 0x0A, 0x01, 0x01, 0xFF, 0xAF, 0x00, 0xAB,
-0xFF, 0x14, 0x00, 0xFD, 0xFF, 0x36, 0x00, 0x36, 0xFF, 0xE5, 0x01,
-0x42, 0xFC, 0xC3, 0x06, 0x87, 0xF3, 0xD7, 0x1F, 0xFE, 0x3D, 0x91,
-0xF3, 0x1D, 0x05, 0xD1, 0xFD, 0xCE, 0x00, 0xCC, 0xFF, 0x02, 0x00,
-0x02, 0x00, 0xFE, 0xFF, 0x22, 0x00, 0x75, 0xFF, 0x7A, 0x01, 0xB8,
-0xFC, 0xB4, 0x06, 0x9E, 0xF1, 0xA2, 0x34, 0xAD, 0x2B, 0xB6, 0xF1,
-0x29, 0x07, 0x45, 0xFC, 0xCB, 0x01, 0x49, 0xFF, 0x31, 0x00, 0xFD,
-0xFF, 0x09, 0x00, 0xDE, 0xFF, 0x2B, 0x00, 0x11, 0x00, 0x1B, 0xFF,
-0x02, 0x03, 0xFE, 0xF6, 0xC3, 0x43, 0x22, 0x16, 0x07, 0xF6, 0xCA,
-0x05, 0xA3, 0xFC, 0xC5, 0x01, 0x3F, 0xFF, 0x33, 0x00, 0xFF, 0xFF,
-0x00, 0x00, 0x20, 0x00, 0x80, 0xFF, 0x1C, 0x01, 0x1C, 0xFE, 0xBD,
-0x02, 0x6E, 0xFC, 0x7D, 0x04, 0xF3, 0x48, 0xE2, 0x02, 0x1F, 0xFD,
-0x60, 0x02, 0x4C, 0xFE, 0x06, 0x01, 0x89, 0xFF, 0x1D, 0x00, 0xFE,
-0xFF, 0x34, 0x00, 0x3C, 0xFF, 0xCF, 0x01, 0x88, 0xFC, 0x09, 0x06,
-0x71, 0xF5, 0x2B, 0x18, 0xB2, 0x42, 0x20, 0xF6, 0x83, 0x03, 0xCF,
-0xFE, 0x3C, 0x00, 0x15, 0x00, 0xE6, 0xFF, 0x07, 0x00, 0xFD, 0xFF,
-0x2E, 0x00, 0x50, 0xFF, 0xBF, 0x01, 0x54, 0xFC, 0x20, 0x07, 0x94,
-0xF1, 0xA6, 0x2D, 0xD0, 0x32, 0x85, 0xF1, 0xDD, 0x06, 0x96, 0xFC,
-0x90, 0x01, 0x69, 0xFF, 0x26, 0x00, 0xFD, 0xFF, 0x03, 0x00, 0xFB,
-0xFF, 0xDF, 0xFF, 0xA9, 0x00, 0x10, 0xFE, 0xB9, 0x04, 0x27, 0xF4,
-0x5E, 0x3F, 0xC3, 0x1D, 0xFE, 0xF3, 0x99, 0x06, 0x50, 0xFC, 0xE2,
-0x01, 0x36, 0xFF, 0x36, 0x00, 0xFE, 0xFF, 0x17, 0x00, 0xA2, 0xFF,
-0xC7, 0x00, 0xD0, 0xFE, 0x65, 0x01, 0xF6, 0xFE, 0xD9, 0xFE, 0x6A,
-0x48, 0x1F, 0x09, 0x87, 0xFA, 0xB3, 0x03, 0xA0, 0xFD, 0x56, 0x01,
-0x69, 0xFF, 0x26, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x2F, 0x00, 0x4D,
-0xFF, 0xA0, 0x01, 0xFB, 0xFC, 0x07, 0x05, 0xBF, 0xF7, 0xBB, 0x10,
-0x2B, 0x46, 0xBB, 0xF9, 0x83, 0x01, 0xFA, 0xFF, 0x95, 0xFF, 0x68,
-0x00, 0xC7, 0xFF, 0x0E, 0x00, 0xFD, 0xFF, 0x35, 0x00, 0x3C, 0xFF,
-0xE1, 0x01, 0x31, 0xFC, 0x19, 0x07, 0x5B, 0xF2, 0x30, 0x26, 0x4B,
-0x39, 0x3B, 0xF2, 0x1A, 0x06, 0x29, 0xFD, 0x33, 0x01, 0x99, 0xFF,
-0x15, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x13, 0x00, 0x9F, 0xFF, 0x28,
-0x01, 0x3A, 0xFD, 0x00, 0x06, 0x5A, 0xF2, 0xDF, 0x39, 0x73, 0x25,
-0x79, 0xF2, 0x12, 0x07, 0x31, 0xFC, 0xE3, 0x01, 0x3B, 0xFF, 0x35,
-0x00, 0xFD, 0xFF, 0x0F, 0x00, 0xC4, 0xFF, 0x70, 0x00, 0x84, 0xFF,
-0x19, 0x00, 0x4D, 0x01, 0x22, 0xFA, 0x70, 0x46, 0x0A, 0x10, 0xFC,
-0xF7, 0xEB, 0x04, 0x08, 0xFD, 0x9A, 0x01, 0x4F, 0xFF, 0x2E, 0x00,
-0xFF, 0xFF, 0x00, 0x00, 0x27, 0x00, 0x66, 0xFF, 0x5E, 0x01, 0x90,
-0xFD, 0xD2, 0x03, 0x47, 0xFA, 0xC3, 0x09, 0x48, 0x48, 0x5A, 0xFE,
-0x33, 0xFF, 0x45, 0x01, 0xE2, 0xFE, 0xBE, 0x00, 0xA5, 0xFF, 0x16,
-0x00, 0xFE, 0xFF, 0x36, 0x00, 0x36, 0xFF, 0xE3, 0x01, 0x4B, 0xFC,
-0xA9, 0x06, 0xD2, 0xF3, 0x81, 0x1E, 0xE4, 0x3E, 0xEF, 0xF3, 0xDE,
-0x04, 0xF9, 0xFD, 0xB7, 0x00, 0xD8, 0xFF, 0xFD, 0xFF, 0x03, 0x00,
-0xFD, 0xFF, 0x24, 0x00, 0x6D, 0xFF, 0x88, 0x01, 0xA2, 0xFC, 0xD0,
-0x06, 0x8C, 0xF1, 0x78, 0x33, 0xF2, 0x2C, 0x9E, 0xF1, 0x24, 0x07,
-0x4E, 0xFC, 0xC3, 0x01, 0x4E, 0xFF, 0x2F, 0x00, 0xFD, 0xFF, 0x08,
-0x00, 0xE4, 0xFF, 0x1D, 0x00, 0x2D, 0x00, 0xEA, 0xFE, 0x56, 0x03,
-0x6D, 0xF6, 0x17, 0x43, 0x70, 0x17, 0xA6, 0xF5, 0xF3, 0x05, 0x91,
-0xFC, 0xCC, 0x01, 0x3D, 0xFF, 0x34, 0x00, 0xFE, 0xFF, 0x1E, 0x00,
-0x86, 0xFF, 0x0E, 0x01, 0x3B, 0xFE, 0x82, 0x02, 0xE0, 0xFC, 0x73,
-0x03, 0xF6, 0x48, 0xE9, 0x03, 0xAD, 0xFC, 0x9C, 0x02, 0x2D, 0xFE,
-0x14, 0x01, 0x83, 0xFF, 0x1F, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x33,
-0x00, 0x3E, 0xFF, 0xC9, 0x01, 0x99, 0xFC, 0xE1, 0x05, 0xD1, 0xF5,
-0xDC, 0x16, 0x65, 0x43, 0xAD, 0xF6, 0x31, 0x03, 0x00, 0xFF, 0x20,
-0x00, 0x23, 0x00, 0xE1, 0xFF, 0x08, 0x00, 0xFD, 0xFF, 0x30, 0x00,
-0x4C, 0xFF, 0xC7, 0x01, 0x4A, 0xFC, 0x27, 0x07, 0xA8, 0xF1, 0x62,
-0x2C, 0xFD, 0x33, 0x93, 0xF1, 0xC4, 0x06, 0xAB, 0xFC, 0x82, 0x01,
-0x71, 0xFF, 0x23, 0x00, 0xFE, 0xFF, 0x02, 0x00, 0xFF, 0xFF, 0xD3,
-0xFF, 0xC1, 0x00, 0xE7, 0xFD, 0xFA, 0x04, 0xC4, 0xF3, 0x7E, 0x3E,
-0x19, 0x1F, 0xB0, 0xF3, 0xB5, 0x06, 0x47, 0xFC, 0xE4, 0x01, 0x36,
-0xFF, 0x36, 0x00, 0xFD, 0xFF, 0x15, 0x00, 0xA8, 0xFF, 0xB8, 0x00,
-0xF0, 0xFE, 0x2B, 0x01, 0x63, 0xFF, 0xF6, 0xFD, 0x2C, 0x48, 0x47,
-0x0A, 0x14, 0xFA, 0xEB, 0x03, 0x84, 0xFD, 0x63, 0x01, 0x64, 0xFF,
-0x27, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x2D, 0x00, 0x51, 0xFF, 0x96,
-0x01, 0x13, 0xFD, 0xD5, 0x04, 0x2C, 0xF8, 0x7D, 0x0F, 0xA3, 0x46,
-0x76, 0xFA, 0x22, 0x01, 0x32, 0x00, 0x76, 0xFF, 0x76, 0x00, 0xC1,
-0xFF, 0x0F, 0x00, 0xFD, 0xFF, 0x36, 0x00, 0x3A, 0xFF, 0xE4, 0x01,
-0x32, 0xFC, 0x0C, 0x07, 0x91, 0xF2, 0xDD, 0x24, 0x54, 0x3A, 0x74,
-0xF2, 0xEB, 0x05, 0x49, 0xFD, 0x20, 0x01, 0xA3, 0xFF, 0x11, 0x00,
-0x00, 0x00, 0xFF, 0xFF, 0x16, 0x00, 0x95, 0xFF, 0x3B, 0x01, 0x1B,
-0xFD, 0x2D, 0x06, 0x24, 0xF2, 0xD3, 0x38, 0xC6, 0x26, 0x45, 0xF2,
-0x1D, 0x07, 0x32, 0xFC, 0xE0, 0x01, 0x3D, 0xFF, 0x35, 0x00, 0xFD,
-0xFF, 0x0D, 0x00, 0xC9, 0xFF, 0x61, 0x00, 0xA2, 0xFF, 0xE2, 0xFF,
-0xAE, 0x01, 0x6B, 0xF9, 0xF2, 0x45, 0x4A, 0x11, 0x8F, 0xF7, 0x1D,
-0x05, 0xF1, 0xFC, 0xA4, 0x01, 0x4B, 0xFF, 0x2F, 0x00, 0xFF, 0xFF,
-0x00, 0x00, 0x25, 0x00, 0x6C, 0xFF, 0x51, 0x01, 0xAC, 0xFD, 0x9A,
-0x03, 0xBA, 0xFA, 0x9E, 0x08, 0x81, 0x48, 0x40, 0xFF, 0xC6, 0xFE,
-0x80, 0x01, 0xC2, 0xFE, 0xCE, 0x00, 0x9F, 0xFF, 0x17, 0x00, 0xFE,
-0xFF, 0x36, 0x00, 0x37, 0xFF, 0xE1, 0x01, 0x55, 0xFC, 0x8C, 0x06,
-0x22, 0xF4, 0x2C, 0x1D, 0xC0, 0x3F, 0x55, 0xF4, 0x9B, 0x04, 0x23,
-0xFE, 0x9F, 0x00, 0xE4, 0xFF, 0xF9, 0xFF, 0x04, 0x00, 0xFD, 0xFF,
-0x27, 0x00, 0x66, 0xFF, 0x96, 0x01, 0x8E, 0xFC, 0xE7, 0x06, 0x81,
-0xF1, 0x48, 0x32, 0x34, 0x2E, 0x8D, 0xF1, 0x1C, 0x07, 0x5A, 0xFC,
-0xBB, 0x01, 0x53, 0xFF, 0x2E, 0x00, 0xFD, 0xFF, 0x07, 0x00, 0xE9,
-0xFF, 0x0F, 0x00, 0x48, 0x00, 0xB9, 0xFE, 0xA6, 0x03, 0xE4, 0xF5,
-0x60, 0x42, 0xC1, 0x18, 0x47, 0xF5, 0x1A, 0x06, 0x81, 0xFC, 0xD2,
-0x01, 0x3B, 0xFF, 0x35, 0x00, 0xFE, 0xFF, 0x1C, 0x00, 0x8B, 0xFF,
-0xFF, 0x00, 0x5A, 0xFE, 0x46, 0x02, 0x52, 0xFD, 0x70, 0x02, 0xED,
-0x48, 0xF5, 0x04, 0x3B, 0xFC, 0xD7, 0x02, 0x0F, 0xFE, 0x23, 0x01,
-0x7E, 0xFF, 0x20, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x33, 0x00, 0x40,
-0xFF, 0xC1, 0x01, 0xAB, 0xFC, 0xB7, 0x05, 0x34, 0xF6, 0x8E, 0x15,
-0x0B, 0x44, 0x42, 0xF7, 0xDC, 0x02, 0x32, 0xFF, 0x04, 0x00, 0x31,
-0x00, 0xDC, 0xFF, 0x09, 0x00, 0xFD, 0xFF, 0x31, 0x00, 0x47, 0xFF,
-0xCE, 0x01, 0x41, 0xFC, 0x2A, 0x07, 0xC2, 0xF1, 0x1B, 0x2B, 0x25,
-0x35, 0xA8, 0xF1, 0xA7, 0x06, 0xC2, 0xFC, 0x74, 0x01, 0x78, 0xFF,
-0x20, 0x00, 0xFE, 0xFF, 0x02, 0x00, 0x04, 0x00, 0xC7, 0xFF, 0xD9,
-0x00, 0xBF, 0xFD, 0x38, 0x05, 0x69, 0xF3, 0x96, 0x3D, 0x6F, 0x20,
-0x66, 0xF3, 0xCE, 0x06, 0x3F, 0xFC, 0xE6, 0x01, 0x36, 0xFF, 0x36,
-0x00, 0xFD, 0xFF, 0x14, 0x00, 0xAE, 0xFF, 0xA9, 0x00, 0x0F, 0xFF,
-0xF0, 0x00, 0xCD, 0xFF, 0x1B, 0xFD, 0xE4, 0x47, 0x73, 0x0B, 0xA2,
-0xF9, 0x23, 0x04, 0x68, 0xFD, 0x70, 0x01, 0x5F, 0xFF, 0x29, 0x00,
-0x00, 0x00, 0xFF, 0xFF, 0x2C, 0x00, 0x55, 0xFF, 0x8B, 0x01, 0x2B,
-0xFD, 0xA1, 0x04, 0x9B, 0xF8, 0x42, 0x0E, 0x0F, 0x47, 0x38, 0xFB,
-0xBE, 0x00, 0x6A, 0x00, 0x58, 0xFF, 0x85, 0x00, 0xBB, 0xFF, 0x10,
-0x00, 0xFD, 0xFF, 0x36, 0x00, 0x38, 0xFF, 0xE6, 0x01, 0x34, 0xFC,
-0xFD, 0x06, 0xCB, 0xF2, 0x8A, 0x23, 0x58, 0x3B, 0xB4, 0xF2, 0xBA,
-0x05, 0x6A, 0xFD, 0x0B, 0x01, 0xAE, 0xFF, 0x0D, 0x00, 0x00, 0x00,
-0xFF, 0xFF, 0x19, 0x00, 0x8C, 0xFF, 0x4D, 0x01, 0xFE, 0xFC, 0x56,
-0x06, 0xF7, 0xF1, 0xBF, 0x37, 0x15, 0x28, 0x18, 0xF2, 0x25, 0x07,
-0x34, 0xFC, 0xDC, 0x01, 0x3F, 0xFF, 0x34, 0x00, 0xFD, 0xFF, 0x0C,
-0x00, 0xCF, 0xFF, 0x52, 0x00, 0xC0, 0xFF, 0xAC, 0xFF, 0x0C, 0x02,
-0xBC, 0xF8, 0x6D, 0x45, 0x8E, 0x12, 0x24, 0xF7, 0x4D, 0x05, 0xDB,
-0xFC, 0xAE, 0x01, 0x48, 0xFF, 0x30, 0x00, 0xFF, 0xFF, 0x00, 0x00,
-0x24, 0x00, 0x71, 0xFF, 0x43, 0x01, 0xC9, 0xFD, 0x60, 0x03, 0x2E,
-0xFB, 0x7E, 0x07, 0xAF, 0x48, 0x2D, 0x00, 0x58, 0xFE, 0xBB, 0x01,
-0xA3, 0xFE, 0xDD, 0x00, 0x99, 0xFF, 0x19, 0x00, 0xFE, 0xFF, 0x36,
-0x00, 0x37, 0xFF, 0xDD, 0x01, 0x60, 0xFC, 0x6D, 0x06, 0x76, 0xF4,
-0xD8, 0x1B, 0x95, 0x40, 0xC3, 0xF4, 0x56, 0x04, 0x4E, 0xFE, 0x85,
-0x00, 0xF1, 0xFF, 0xF4, 0xFF, 0x04, 0x00, 0xFD, 0xFF, 0x29, 0x00,
-0x60, 0xFF, 0xA2, 0x01, 0x7C, 0xFC, 0xFB, 0x06, 0x7C, 0xF1, 0x15,
-0x31, 0x73, 0x2F, 0x81, 0xF1, 0x10, 0x07, 0x67, 0xFC, 0xB1, 0x01,
-0x58, 0xFF, 0x2C, 0x00, 0xFD, 0xFF, 0x06, 0x00, 0xEE, 0xFF, 0x02,
-0x00, 0x63, 0x00, 0x8A, 0xFE, 0xF3, 0x03, 0x63, 0xF5, 0xA1, 0x41,
-0x12, 0x1A, 0xEB, 0xF4, 0x3F, 0x06, 0x72, 0xFC, 0xD7, 0x01, 0x39,
-0xFF, 0x35, 0x00, 0xFE, 0xFF, 0x1B, 0x00, 0x91, 0xFF, 0xF1, 0x00,
-0x79, 0xFE, 0x0A, 0x02, 0xC3, 0xFD, 0x73, 0x01, 0xDB, 0x48, 0x07,
-0x06, 0xC7, 0xFB, 0x12, 0x03, 0xF1, 0xFD, 0x31, 0x01, 0x78, 0xFF,
-0x22, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x32, 0x00, 0x43, 0xFF, 0xBA,
-0x01, 0xBF, 0xFC, 0x8B, 0x05, 0x99, 0xF6, 0x43, 0x14, 0xA9, 0x44,
-0xDE, 0xF7, 0x85, 0x02, 0x65, 0xFF, 0xE7, 0xFF, 0x3F, 0x00, 0xD6,
-0xFF, 0x0A, 0x00, 0xFD, 0xFF, 0x32, 0x00, 0x44, 0xFF, 0xD5, 0x01,
-0x3A, 0xFC, 0x2A, 0x07, 0xE3, 0xF1, 0xD1, 0x29, 0x46, 0x36, 0xC5,
-0xF1, 0x87, 0x06, 0xDA, 0xFC, 0x64, 0x01, 0x80, 0xFF, 0x1E, 0x00,
-0xFE, 0xFF, 0x01, 0x00, 0x08, 0x00, 0xBC, 0xFF, 0xEF, 0x00, 0x9A,
-0xFD, 0x72, 0x05, 0x16, 0xF3, 0xA5, 0x3C, 0xC4, 0x21, 0x21, 0xF3,
-0xE4, 0x06, 0x39, 0xFC, 0xE6, 0x01, 0x37, 0xFF, 0x36, 0x00, 0xFD,
-0xFF, 0x12, 0x00, 0xB3, 0xFF, 0x99, 0x00, 0x2E, 0xFF, 0xB6, 0x00,
-0x36, 0x00, 0x47, 0xFC, 0x90, 0x47, 0xA4, 0x0C, 0x31, 0xF9, 0x5A,
-0x04, 0x4E, 0xFD, 0x7C, 0x01, 0x5B, 0xFF, 0x2A, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x2B, 0x00, 0x59, 0xFF, 0x80, 0x01, 0x45, 0xFD, 0x6C,
-0x04, 0x0B, 0xF9, 0x0B, 0x0D, 0x73, 0x47, 0x02, 0xFC, 0x58, 0x00,
-0xA3, 0x00, 0x39, 0xFF, 0x94, 0x00, 0xB5, 0xFF, 0x12, 0x00, 0xFD,
-0xFF, 0x36, 0x00, 0x37, 0xFF, 0xE6, 0x01, 0x37, 0xFC, 0xEB, 0x06,
-0x0B, 0xF3, 0x35, 0x22, 0x52, 0x3C, 0xFD, 0xF2, 0x84, 0x05, 0x8D,
-0xFD, 0xF6, 0x00, 0xB8, 0xFF, 0x09, 0x00, 0x01, 0x00, 0xFE, 0xFF,
-0x1D, 0x00, 0x83, 0xFF, 0x5E, 0x01, 0xE3, 0xFC, 0x7B, 0x06, 0xD0,
-0xF1, 0xA5, 0x36, 0x62, 0x29, 0xEF, 0xF1, 0x29, 0x07, 0x39, 0xFC,
-0xD7, 0x01, 0x42, 0xFF, 0x33, 0x00, 0xFD, 0xFF, 0x0B, 0x00, 0xD5,
-0xFF, 0x44, 0x00, 0xDD, 0xFF, 0x77, 0xFF, 0x67, 0x02, 0x14, 0xF8,
-0xDC, 0x44, 0xD5, 0x13, 0xBC, 0xF6, 0x7C, 0x05, 0xC5, 0xFC, 0xB7,
-0x01, 0x44, 0xFF, 0x31, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x22, 0x00,
-0x76, 0xFF, 0x35, 0x01, 0xE7, 0xFD, 0x26, 0x03, 0xA1, 0xFB, 0x64,
-0x06, 0xD2, 0x48, 0x21, 0x01, 0xE8, 0xFD, 0xF7, 0x01, 0x83, 0xFE,
-0xEC, 0x00, 0x93, 0xFF, 0x1A, 0x00, 0xFE, 0xFF, 0x35, 0x00, 0x39,
-0xFF, 0xD9, 0x01, 0x6D, 0xFC, 0x4B, 0x06, 0xCD, 0xF4, 0x83, 0x1A,
-0x5F, 0x41, 0x3A, 0xF5, 0x0C, 0x04, 0x7B, 0xFE, 0x6C, 0x00, 0xFE,
-0xFF, 0xEF, 0xFF, 0x05, 0x00, 0xFD, 0xFF, 0x2B, 0x00, 0x5A, 0xFF,
-0xAD, 0x01, 0x6C, 0xFC, 0x0C, 0x07, 0x7F, 0xF1, 0xDC, 0x2F, 0xAD,
-0x30, 0x7D, 0xF1, 0x01, 0x07, 0x76, 0xFC, 0xA6, 0x01, 0x5E, 0xFF,
-0x2A, 0x00, 0xFD, 0xFF, 0x05, 0x00, 0xF3, 0xFF, 0xF5, 0xFF, 0x7D,
-0x00, 0x5D, 0xFE, 0x3E, 0x04, 0xEA, 0xF4, 0xD9, 0x40, 0x66, 0x1B,
-0x93, 0xF4, 0x62, 0x06, 0x64, 0xFC, 0xDC, 0x01, 0x38, 0xFF, 0x36,
-0x00, 0xFE, 0xFF, 0x19, 0x00, 0x97, 0xFF, 0xE2, 0x00, 0x98, 0xFE,
-0xCF, 0x01, 0x33, 0xFE, 0x7D, 0x00, 0xBB, 0x48, 0x1F, 0x07, 0x54,
-0xFB, 0x4C, 0x03, 0xD3, 0xFD, 0x3F, 0x01, 0x73, 0xFF, 0x23, 0x00,
-0x00, 0x00, 0xFF, 0xFF, 0x31, 0x00, 0x46, 0xFF, 0xB1, 0x01, 0xD3,
-0xFC, 0x5D, 0x05, 0x01, 0xF7, 0xFB, 0x12, 0x3F, 0x45, 0x83, 0xF8,
-0x2A, 0x02, 0x9A, 0xFF, 0xCA, 0xFF, 0x4E, 0x00, 0xD1, 0xFF, 0x0C,
-0x00, 0xFD, 0xFF, 0x34, 0x00, 0x40, 0xFF, 0xDA, 0x01, 0x35, 0xFC,
-0x27, 0x07, 0x09, 0xF2, 0x85, 0x28, 0x63, 0x37, 0xE9, 0xF1, 0x63,
-0x06, 0xF5, 0xFC, 0x53, 0x01, 0x89, 0xFF, 0x1A, 0x00, 0xFE, 0xFF,
-0x00, 0x00, 0x0C, 0x00, 0xB1, 0xFF, 0x04, 0x01, 0x76, 0xFD, 0xA8,
-0x05, 0xCC, 0xF2, 0xAB, 0x3B, 0x18, 0x23, 0xE0, 0xF2, 0xF7, 0x06,
-0x35, 0xFC, 0xE6, 0x01, 0x38, 0xFF, 0x36, 0x00, 0xFD, 0xFF, 0x11,
-0x00, 0xB9, 0xFF, 0x8A, 0x00, 0x4D, 0xFF, 0x7D, 0x00, 0x9C, 0x00,
-0x7B, 0xFB, 0x31, 0x47, 0xD9, 0x0D, 0xC0, 0xF8, 0x8F, 0x04, 0x34,
-0xFD, 0x87, 0x01, 0x56, 0xFF, 0x2C, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x29, 0x00, 0x5E, 0xFF, 0x74, 0x01, 0x5F, 0xFD, 0x35, 0x04, 0x7C,
-0xF9, 0xD8, 0x0B, 0xC9, 0x47, 0xD4, 0xFC, 0xF0, 0xFF, 0xDD, 0x00,
-0x19, 0xFF, 0xA4, 0x00, 0xAF, 0xFF, 0x13, 0x00, 0xFD, 0xFF, 0x36,
-0x00, 0x36, 0xFF, 0xE6, 0x01, 0x3D, 0xFC, 0xD5, 0x06, 0x4F, 0xF3,
-0xE0, 0x20, 0x45, 0x3D, 0x4D, 0xF3, 0x4B, 0x05, 0xB3, 0xFD, 0xE0,
-0x00, 0xC3, 0xFF, 0x05, 0x00, 0x02, 0x00, 0xFE, 0xFF, 0x20, 0x00,
-0x7B, 0xFF, 0x6E, 0x01, 0xCA, 0xFC, 0x9D, 0x06, 0xB1, 0xF1, 0x86,
-0x35, 0xAE, 0x2A, 0xCD, 0xF1, 0x2B, 0x07, 0x3F, 0xFC, 0xD1, 0x01,
-0x46, 0xFF, 0x32, 0x00, 0xFD, 0xFF, 0x0A, 0x00, 0xDA, 0xFF, 0x36,
-0x00, 0xFA, 0xFF, 0x43, 0xFF, 0xBF, 0x02, 0x75, 0xF7, 0x42, 0x44,
-0x20, 0x15, 0x55, 0xF6, 0xA9, 0x05, 0xB2, 0xFC, 0xBF, 0x01, 0x41,
-0xFF, 0x32, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x21, 0x00, 0x7C, 0xFF,
-0x27, 0x01, 0x05, 0xFE, 0xEB, 0x02, 0x14, 0xFC, 0x50, 0x05, 0xEA,
-0x48, 0x1B, 0x02, 0x78, 0xFD, 0x32, 0x02, 0x64, 0xFE, 0xFA, 0x00,
-0x8D, 0xFF, 0x1C, 0x00, 0xFE, 0xFF, 0x35, 0x00, 0x3A, 0xFF, 0xD4,
-0x01, 0x7C, 0xFC, 0x27, 0x06, 0x28, 0xF5, 0x31, 0x19, 0x21, 0x42,
-0xB8, 0xF5, 0xC0, 0x03, 0xAA, 0xFE, 0x51, 0x00, 0x0B, 0x00, 0xEA,
-0xFF, 0x06, 0x00, 0xFD, 0xFF, 0x2D, 0x00, 0x54, 0xFF, 0xB7, 0x01,
-0x5E, 0xFC, 0x19, 0x07, 0x88, 0xF1, 0x9F, 0x2E, 0xE3, 0x31, 0x7E,
-0xF1, 0xEE, 0x06, 0x88, 0xFC, 0x9A, 0x01, 0x64, 0xFF, 0x28, 0x00,
-0xFD, 0xFF, 0x04, 0x00, 0xF7, 0xFF, 0xE8, 0xFF, 0x96, 0x00, 0x31,
-0xFE, 0x84, 0x04, 0x79, 0xF4, 0x07, 0x40, 0xBA, 0x1C, 0x3E, 0xF4,
-0x82, 0x06, 0x58, 0xFC, 0xE0, 0x01, 0x37, 0xFF, 0x36, 0x00, 0xFE,
-0xFF, 0x18, 0x00, 0x9D, 0xFF, 0xD3, 0x00, 0xB8, 0xFE, 0x93, 0x01,
-0xA1, 0xFE, 0x8E, 0xFF, 0x92, 0x48, 0x3D, 0x08, 0xE1, 0xFA, 0x86,
-0x03, 0xB6, 0xFD, 0x4C, 0x01, 0x6D, 0xFF, 0x25, 0x00, 0x00, 0x00,
-0xFF, 0xFF, 0x30, 0x00, 0x4A, 0xFF, 0xA8, 0x01, 0xE9, 0xFC, 0x2D,
-0x05, 0x6B, 0xF7, 0xB6, 0x11, 0xC8, 0x45, 0x30, 0xF9, 0xCD, 0x01,
-0xD0, 0xFF, 0xAC, 0xFF, 0x5C, 0x00, 0xCB, 0xFF, 0x0D, 0x00, 0xFD,
-0xFF, 0x34, 0x00, 0x3E, 0xFF, 0xDF, 0x01, 0x33, 0xFC, 0x20, 0x07,
-0x35, 0xF2, 0x36, 0x27, 0x78, 0x38, 0x14, 0xF2, 0x3B, 0x06, 0x11,
-0xFD, 0x41, 0x01, 0x92, 0xFF, 0x17, 0x00, 0xFF, 0xFF, 0x00, 0x00,
-0x10, 0x00, 0xA7, 0xFF, 0x19, 0x01, 0x53, 0xFD, 0xDB, 0x05, 0x88,
-0xF2, 0xAD, 0x3A, 0x6D, 0x24, 0xA4, 0xF2, 0x08, 0x07, 0x32, 0xFC,
-0xE5, 0x01, 0x39, 0xFF, 0x36, 0x00, 0xFD, 0xFF, 0x10, 0x00, 0xBF,
-0xFF, 0x7B, 0x00, 0x6C, 0xFF, 0x44, 0x00, 0x01, 0x01, 0xB6, 0xFA,
-0xC8, 0x46, 0x13, 0x0F, 0x51, 0xF8, 0xC4, 0x04, 0x1B, 0xFD, 0x92,
-0x01, 0x52, 0xFF, 0x2D, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x28, 0x00,
-0x63, 0xFF, 0x67, 0x01, 0x7A, 0xFD, 0xFE, 0x03, 0xEE, 0xF9, 0xAA,
-0x0A, 0x16, 0x48, 0xAC, 0xFD, 0x86, 0xFF, 0x17, 0x01, 0xFA, 0xFE,
-0xB3, 0x00, 0xAA, 0xFF, 0x15, 0x00, 0xFD, 0xFF, 0x36, 0x00, 0x36,
-0xFF, 0xE5, 0x01, 0x44, 0xFC, 0xBD, 0x06, 0x97, 0xF3, 0x8A, 0x1F,
-0x31, 0x3E, 0xA5, 0xF3, 0x0F, 0x05, 0xDA, 0xFD, 0xC9, 0x00, 0xCF,
-0xFF, 0x01, 0x00, 0x02, 0x00, 0xFE, 0xFF, 0x22, 0x00, 0x73, 0xFF,
-0x7D, 0x01, 0xB3, 0xFC, 0xBB, 0x06, 0x9A, 0xF1, 0x60, 0x34, 0xF5,
-0x2B, 0xB0, 0xF1, 0x28, 0x07, 0x47, 0xFC, 0xCA, 0x01, 0x4A, 0xFF,
-0x30, 0x00, 0xFD, 0xFF, 0x09, 0x00, 0xDF, 0xFF, 0x28, 0x00, 0x17,
-0x00, 0x10, 0xFF, 0x15, 0x03, 0xDD, 0xF6, 0x9E, 0x43, 0x6C, 0x16,
-0xF1, 0xF5, 0xD3, 0x05, 0x9F, 0xFC, 0xC6, 0x01, 0x3F, 0xFF, 0x33,
-0x00, 0xFF, 0xFF, 0x00, 0x00, 0x1F, 0x00, 0x81, 0xFF, 0x19, 0x01,
-0x23, 0xFE, 0xB0, 0x02, 0x87, 0xFC, 0x41, 0x04, 0xF4, 0x48, 0x1C,
-0x03, 0x06, 0xFD, 0x6E, 0x02, 0x45, 0xFE, 0x09, 0x01, 0x88, 0xFF,
-0x1D, 0x00, 0xFE, 0xFF, 0x34, 0x00, 0x3C, 0xFF, 0xCE, 0x01, 0x8C,
-0xFC, 0x00, 0x06, 0x86, 0xF5, 0xE0, 0x17, 0xDB, 0x42, 0x3F, 0xF6,
-0x71, 0x03, 0xD9, 0xFE, 0x36, 0x00, 0x18, 0x00, 0xE5, 0xFF, 0x07,
-0x00, 0xFD, 0xFF, 0x2F, 0x00, 0x4F, 0xFF, 0xC1, 0x01, 0x52, 0xFC,
-0x22, 0x07, 0x98, 0xF1, 0x5E, 0x2D, 0x13, 0x33, 0x87, 0xF1, 0xD8,
-0x06, 0x9B, 0xFC, 0x8D, 0x01, 0x6B, 0xFF, 0x25, 0x00, 0xFD, 0xFF,
-0x03, 0x00, 0xFC, 0xFF, 0xDC, 0xFF, 0xAF, 0x00, 0x07, 0xFE, 0xC8,
-0x04, 0x10, 0xF4, 0x2D, 0x3F, 0x0F, 0x1E, 0xED, 0xF3, 0xA0, 0x06,
-0x4E, 0xFC, 0xE3, 0x01, 0x36, 0xFF, 0x36, 0x00, 0xFE, 0xFF, 0x16,
-0x00, 0xA3, 0xFF, 0xC3, 0x00, 0xD7, 0xFE, 0x58, 0x01, 0x0F, 0xFF,
-0xA6, 0xFE, 0x5D, 0x48, 0x61, 0x09, 0x6E, 0xFA, 0xC0, 0x03, 0x99,
-0xFD, 0x59, 0x01, 0x68, 0xFF, 0x26, 0x00, 0x00, 0x00, 0xFF, 0xFF,
-0x2E, 0x00, 0x4E, 0xFF, 0x9E, 0x01, 0x00, 0xFD, 0xFC, 0x04, 0xD7,
-0xF7, 0x75, 0x10, 0x48, 0x46, 0xE4, 0xF9, 0x6E, 0x01, 0x06, 0x00,
-0x8E, 0xFF, 0x6B, 0x00, 0xC6, 0xFF, 0x0E, 0x00, 0xFD, 0xFF, 0x35,
-0x00, 0x3B, 0xFF, 0xE2, 0x01, 0x31, 0xFC, 0x16, 0x07, 0x67, 0xF2,
-0xE5, 0x25, 0x87, 0x39, 0x47, 0xF2, 0x10, 0x06, 0x30, 0xFD, 0x2F,
-0x01, 0x9C, 0xFF, 0x14, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x13, 0x00,
-0x9D, 0xFF, 0x2D, 0x01, 0x33, 0xFD, 0x0B, 0x06, 0x4D, 0xF2, 0xA5,
-0x39, 0xBF, 0x25, 0x6D, 0xF2, 0x15, 0x07, 0x31, 0xFC, 0xE2, 0x01,
-0x3B, 0xFF, 0x35, 0x00, 0xFD, 0xFF, 0x0E, 0x00, 0xC5, 0xFF, 0x6D,
-0x00, 0x8B, 0xFF, 0x0D, 0x00, 0x63, 0x01, 0xF9, 0xF9, 0x55, 0x46,
-0x51, 0x10, 0xE3, 0xF7, 0xF7, 0x04, 0x03, 0xFD, 0x9D, 0x01, 0x4E,
-0xFF, 0x2E, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x26, 0x00, 0x68, 0xFF,
-0x5B, 0x01, 0x96, 0xFD, 0xC6, 0x03, 0x61, 0xFA, 0x81, 0x09, 0x57,
-0x48, 0x8D, 0xFE, 0x1B, 0xFF, 0x52, 0x01, 0xDB, 0xFE, 0xC2, 0x00,
-0xA4, 0xFF, 0x16, 0x00, 0xFE, 0xFF, 0x36, 0x00, 0x36, 0xFF, 0xE3,
-0x01, 0x4D, 0xFC, 0xA3, 0x06, 0xE4, 0xF3, 0x36, 0x1E, 0x16, 0x3F,
-0x05, 0xF4, 0xCF, 0x04, 0x02, 0xFE, 0xB2, 0x00, 0xDB, 0xFF, 0xFC,
-0xFF, 0x03, 0x00, 0xFD, 0xFF, 0x25, 0x00, 0x6C, 0xFF, 0x8B, 0x01,
-0x9D, 0xFC, 0xD5, 0x06, 0x89, 0xF1, 0x35, 0x33, 0x3A, 0x2D, 0x9A,
-0xF1, 0x23, 0x07, 0x51, 0xFC, 0xC2, 0x01, 0x4F, 0xFF, 0x2F, 0x00,
-0xFD, 0xFF, 0x07, 0x00, 0xE5, 0xFF, 0x1A, 0x00, 0x33, 0x00, 0xDF,
-0xFE, 0x68, 0x03, 0x4E, 0xF6, 0xEE, 0x42, 0xBB, 0x17, 0x90, 0xF5,
-0xFC, 0x05, 0x8E, 0xFC, 0xCD, 0x01, 0x3C, 0xFF, 0x34, 0x00, 0xFE,
-0xFF, 0x1E, 0x00, 0x87, 0xFF, 0x0B, 0x01, 0x42, 0xFE, 0x74, 0x02,
-0xF9, 0xFC, 0x39, 0x03, 0xF5, 0x48, 0x24, 0x04, 0x94, 0xFC, 0xA9,
-0x02, 0x27, 0xFE, 0x18, 0x01, 0x82, 0xFF, 0x1F, 0x00, 0x00, 0x00,
-0xFF, 0xFF, 0x33, 0x00, 0x3E, 0xFF, 0xC7, 0x01, 0x9D, 0xFC, 0xD8,
-0x05, 0xE7, 0xF5, 0x91, 0x16, 0x89, 0x43, 0xCD, 0xF6, 0x1E, 0x03,
-0x0B, 0xFF, 0x1A, 0x00, 0x26, 0x00, 0xE0, 0xFF, 0x08, 0x00, 0xFD,
-0xFF, 0x30, 0x00, 0x4B, 0xFF, 0xC9, 0x01, 0x48, 0xFC, 0x28, 0x07,
-0xAD, 0xF1, 0x19, 0x2C, 0x3F, 0x34, 0x97, 0xF1, 0xBE, 0x06, 0xB0,
-0xFC, 0x7F, 0x01, 0x72, 0xFF, 0x23, 0x00, 0xFE, 0xFF, 0x02, 0x00,
-0x00, 0x00, 0xD0, 0xFF, 0xC7, 0x00, 0xDE, 0xFD, 0x08, 0x05, 0xB0,
-0xF3, 0x4A, 0x3E, 0x64, 0x1F, 0xA0, 0xF3, 0xBB, 0x06, 0x45, 0xFC,
-0xE5, 0x01, 0x36, 0xFF, 0x36, 0x00, 0xFD, 0xFF, 0x15, 0x00, 0xA9,
-0xFF, 0xB4, 0x00, 0xF7, 0xFE, 0x1D, 0x01, 0x7A, 0xFF, 0xC5, 0xFD,
-0x1D, 0x48, 0x89, 0x0A, 0xFB, 0xF9, 0xF8, 0x03, 0x7D, 0xFD, 0x66,
-0x01, 0x63, 0xFF, 0x28, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x2D, 0x00,
-0x52, 0xFF, 0x93, 0x01, 0x18, 0xFD, 0xC9, 0x04, 0x45, 0xF8, 0x36,
-0x0F, 0xBB, 0x46, 0xA1, 0xFA, 0x0C, 0x01, 0x3E, 0x00, 0x70, 0xFF,
-0x7A, 0x00, 0xC0, 0xFF, 0x0F, 0x00, 0xFD, 0xFF, 0x36, 0x00, 0x39,
-0xFF, 0xE4, 0x01, 0x32, 0xFC, 0x09, 0x07, 0x9D, 0xF2, 0x92, 0x24,
-0x8F, 0x3A, 0x82, 0xF2, 0xE1, 0x05, 0x50, 0xFD, 0x1B, 0x01, 0xA6,
-0xFF, 0x10, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x17, 0x00, 0x93, 0xFF,
-0x3F, 0x01, 0x15, 0xFD, 0x36, 0x06, 0x19, 0xF2, 0x97, 0x38, 0x11,
-0x27, 0x3B, 0xF2, 0x1F, 0x07, 0x32, 0xFC, 0xDF, 0x01, 0x3D, 0xFF,
-0x34, 0x00, 0xFD, 0xFF, 0x0D, 0x00, 0xCB, 0xFF, 0x5E, 0x00, 0xA9,
-0xFF, 0xD6, 0xFF, 0xC3, 0x01, 0x43, 0xF9, 0xD7, 0x45, 0x92, 0x11,
-0x77, 0xF7, 0x28, 0x05, 0xEC, 0xFC, 0xA7, 0x01, 0x4A, 0xFF, 0x2F,
-0x00, 0xFF, 0xFF, 0x00, 0x00, 0x25, 0x00, 0x6D, 0xFF, 0x4E, 0x01,
-0xB3, 0xFD, 0x8D, 0x03, 0xD4, 0xFA, 0x5D, 0x08, 0x8D, 0x48, 0x74,
-0xFF, 0xAE, 0xFE, 0x8D, 0x01, 0xBB, 0xFE, 0xD1, 0x00, 0x9E, 0xFF,
-0x18, 0x00, 0xFE, 0xFF, 0x36, 0x00, 0x37, 0xFF, 0xE0, 0x01, 0x57,
-0xFC, 0x85, 0x06, 0x34, 0xF4, 0xE0, 0x1C, 0xF0, 0x3F, 0x6D, 0xF4,
-0x8C, 0x04, 0x2C, 0xFE, 0x99, 0x00, 0xE7, 0xFF, 0xF8, 0xFF, 0x04,
-0x00, 0xFD, 0xFF, 0x27, 0x00, 0x65, 0xFF, 0x98, 0x01, 0x8A, 0xFC,
-0xEC, 0x06, 0x7F, 0xF1, 0x04, 0x32, 0x7B, 0x2E, 0x8A, 0xF1, 0x1A,
-0x07, 0x5D, 0xFC, 0xB8, 0x01, 0x54, 0xFF, 0x2D, 0x00, 0xFD, 0xFF,
-0x06, 0x00, 0xEA, 0xFF, 0x0C, 0x00, 0x4E, 0x00, 0xAF, 0xFE, 0xB8,
-0x03, 0xC7, 0xF5, 0x38, 0x42, 0x0C, 0x19, 0x32, 0xF5, 0x23, 0x06,
-0x7D, 0xFC, 0xD3, 0x01, 0x3A, 0xFF, 0x35, 0x00, 0xFE, 0xFF, 0x1C,
-0x00, 0x8D, 0xFF, 0xFC, 0x00, 0x61, 0xFE, 0x39, 0x02, 0x6B, 0xFD,
-0x37, 0x02, 0xEB, 0x48, 0x31, 0x05, 0x21, 0xFC, 0xE4, 0x02, 0x08,
-0xFE, 0x26, 0x01, 0x7C, 0xFF, 0x21, 0x00, 0x00, 0x00, 0xFF, 0xFF,
-0x32, 0x00, 0x41, 0xFF, 0xC0, 0x01, 0xAF, 0xFC, 0xAD, 0x05, 0x4A,
-0xF6, 0x44, 0x15, 0x2F, 0x44, 0x64, 0xF7, 0xC9, 0x02, 0x3D, 0xFF,
-0xFE, 0xFF, 0x34, 0x00, 0xDB, 0xFF, 0x09, 0x00, 0xFD, 0xFF, 0x32,
-0x00, 0x47, 0xFF, 0xD0, 0x01, 0x40, 0xFC, 0x2A, 0x07, 0xCA, 0xF1,
-0xD1, 0x2A, 0x65, 0x35, 0xAE, 0xF1, 0xA0, 0x06, 0xC7, 0xFC, 0x70,
-0x01, 0x7A, 0xFF, 0x20, 0x00, 0xFE, 0xFF, 0x02, 0x00, 0x05, 0x00,
-0xC5, 0xFF, 0xDE, 0x00, 0xB7, 0xFD, 0x45, 0x05, 0x56, 0xF3, 0x61,
-0x3D, 0xBA, 0x20, 0x56, 0xF3, 0xD3, 0x06, 0x3E, 0xFC, 0xE6, 0x01,
-0x36, 0xFF, 0x36, 0x00, 0xFD, 0xFF, 0x13, 0x00, 0xAF, 0xFF, 0xA5,
-0x00, 0x16, 0xFF, 0xE3, 0x00, 0xE4, 0xFF, 0xEB, 0xFC, 0xD2, 0x47,
-0xB6, 0x0B, 0x89, 0xF9, 0x2F, 0x04, 0x62, 0xFD, 0x72, 0x01, 0x5E,
-0xFF, 0x29, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x2C, 0x00, 0x56, 0xFF,
-0x88, 0x01, 0x31, 0xFD, 0x95, 0x04, 0xB4, 0xF8, 0xFC, 0x0D, 0x26,
-0x47, 0x64, 0xFB, 0xA7, 0x00, 0x77, 0x00, 0x51, 0xFF, 0x89, 0x00,
-0xBA, 0xFF, 0x11, 0x00, 0xFD, 0xFF, 0x36, 0x00, 0x38, 0xFF, 0xE6,
-0x01, 0x34, 0xFC, 0xF9, 0x06, 0xD9, 0xF2, 0x3F, 0x23, 0x90, 0x3B,
-0xC4, 0xF2, 0xAE, 0x05, 0x72, 0xFD, 0x07, 0x01, 0xB0, 0xFF, 0x0C,
-0x00, 0x00, 0x00, 0xFF, 0xFF, 0x1A, 0x00, 0x8A, 0xFF, 0x51, 0x01,
-0xF8, 0xFC, 0x5E, 0x06, 0xED, 0xF1, 0x82, 0x37, 0x60, 0x28, 0x0E,
-0xF2, 0x26, 0x07, 0x35, 0xFC, 0xDB, 0x01, 0x40, 0xFF, 0x34, 0x00,
-0xFD, 0xFF, 0x0C, 0x00, 0xD0, 0xFF, 0x4F, 0x00, 0xC7, 0xFF, 0xA0,
-0xFF, 0x20, 0x02, 0x96, 0xF8, 0x4E, 0x45, 0xD7, 0x12, 0x0D, 0xF7,
-0x58, 0x05, 0xD6, 0xFC, 0xB0, 0x01, 0x47, 0xFF, 0x30, 0x00, 0xFF,
-0xFF, 0x00, 0x00, 0x23, 0x00, 0x72, 0xFF, 0x40, 0x01, 0xD0, 0xFD,
-0x53, 0x03, 0x47, 0xFB, 0x3F, 0x07, 0xB8, 0x48, 0x62, 0x00, 0x3F,
-0xFE, 0xC8, 0x01, 0x9C, 0xFE, 0xE0, 0x00, 0x98, 0xFF, 0x19, 0x00,
-0xFE, 0xFF, 0x36, 0x00, 0x38, 0xFF, 0xDC, 0x01, 0x63, 0xFC, 0x66,
-0x06, 0x89, 0xF4, 0x8C, 0x1B, 0xC3, 0x40, 0xDD, 0xF4, 0x46, 0x04,
-0x58, 0xFE, 0x80, 0x00, 0xF4, 0xFF, 0xF3, 0xFF, 0x05, 0x00, 0xFD,
-0xFF, 0x29, 0x00, 0x5F, 0xFF, 0xA5, 0x01, 0x78, 0xFC, 0xFF, 0x06,
-0x7D, 0xF1, 0xCF, 0x30, 0xB8, 0x2F, 0x80, 0xF1, 0x0D, 0x07, 0x6A,
-0xFC, 0xAE, 0x01, 0x59, 0xFF, 0x2B, 0x00, 0xFD, 0xFF, 0x05, 0x00,
-0xEF, 0xFF, 0xFF, 0xFF, 0x69, 0x00, 0x80, 0xFE, 0x04, 0x04, 0x48,
-0xF5, 0x74, 0x41, 0x5D, 0x1A, 0xD7, 0xF4, 0x47, 0x06, 0x6F, 0xFC,
-0xD8, 0x01, 0x39, 0xFF, 0x35, 0x00, 0xFE, 0xFF, 0x1B, 0x00, 0x93,
-0xFF, 0xED, 0x00, 0x80, 0xFE, 0xFD, 0x01, 0xDC, 0xFD, 0x3C, 0x01,
-0xD5, 0x48, 0x45, 0x06, 0xAE, 0xFB, 0x1F, 0x03, 0xEA, 0xFD, 0x34,
-0x01, 0x77, 0xFF, 0x22, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x31, 0x00,
-0x44, 0xFF, 0xB8, 0x01, 0xC3, 0xFC, 0x81, 0x05, 0xB0, 0xF6, 0xFA,
-0x13, 0xCC, 0x44, 0x02, 0xF8, 0x71, 0x02, 0x71, 0xFF, 0xE1, 0xFF,
-0x42, 0x00, 0xD5, 0xFF, 0x0B, 0x00, 0xFD, 0xFF, 0x33, 0x00, 0x43,
-0xFF, 0xD6, 0x01, 0x39, 0xFC, 0x2A, 0x07, 0xEB, 0xF1, 0x87, 0x29,
-0x85, 0x36, 0xCC, 0xF1, 0x7F, 0x06, 0xE0, 0xFC, 0x60, 0x01, 0x82,
-0xFF, 0x1D, 0x00, 0xFE, 0xFF, 0x01, 0x00, 0x09, 0x00, 0xBA, 0xFF,
-0xF4, 0x00, 0x91, 0xFD, 0x7E, 0x05, 0x05, 0xF3, 0x6E, 0x3C, 0x10,
-0x22, 0x12, 0xF3, 0xE9, 0x06, 0x38, 0xFC, 0xE6, 0x01, 0x37, 0xFF,
-0x36, 0x00, 0xFD, 0xFF, 0x12, 0x00, 0xB5, 0xFF, 0x96, 0x00, 0x35,
-0xFF, 0xA9, 0x00, 0x4D, 0x00, 0x19, 0xFC, 0x7C, 0x47, 0xE8, 0x0C,
-0x18, 0xF9, 0x66, 0x04, 0x48, 0xFD, 0x7E, 0x01, 0x5A, 0xFF, 0x2B,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x2A, 0x00, 0x5A, 0xFF, 0x7D, 0x01,
-0x4B, 0xFD, 0x60, 0x04, 0x24, 0xF9, 0xC6, 0x0C, 0x86, 0x47, 0x30,
-0xFC, 0x41, 0x00, 0xB0, 0x00, 0x32, 0xFF, 0x98, 0x00, 0xB4, 0xFF,
-0x12, 0x00, 0xFD, 0xFF, 0x36, 0x00, 0x37, 0xFF, 0xE6, 0x01, 0x38,
-0xFC, 0xE6, 0x06, 0x19, 0xF3, 0xEA, 0x21, 0x8A, 0x3C, 0x0E, 0xF3,
-0x78, 0x05, 0x96, 0xFD, 0xF1, 0x00, 0xBB, 0xFF, 0x08, 0x00, 0x01,
-0x00, 0xFE, 0xFF, 0x1D, 0x00, 0x81, 0xFF, 0x62, 0x01, 0xDD, 0xFC,
-0x83, 0x06, 0xC9, 0xF1, 0x66, 0x36, 0xAC, 0x29, 0xE7, 0xF1, 0x2A,
-0x07, 0x3A, 0xFC, 0xD5, 0x01, 0x43, 0xFF, 0x33, 0x00, 0xFD, 0xFF,
-0x0B, 0x00, 0xD6, 0xFF, 0x41, 0x00, 0xE4, 0xFF, 0x6B, 0xFF, 0x7B,
-0x02, 0xF0, 0xF7, 0xBA, 0x44, 0x1E, 0x14, 0xA5, 0xF6, 0x86, 0x05,
-0xC1, 0xFC, 0xB9, 0x01, 0x44, 0xFF, 0x32, 0x00, 0xFF, 0xFF, 0x00,
-0x00, 0x22, 0x00, 0x77, 0xFF, 0x32, 0x01, 0xED, 0xFD, 0x19, 0x03,
-0xBB, 0xFB, 0x26, 0x06, 0xD7, 0x48, 0x58, 0x01, 0xCF, 0xFD, 0x04,
-0x02, 0x7D, 0xFE, 0xEF, 0x00, 0x92, 0xFF, 0x1B, 0x00, 0xFE, 0xFF,
-0x35, 0x00, 0x39, 0xFF, 0xD8, 0x01, 0x70, 0xFC, 0x43, 0x06, 0xE1,
-0xF4, 0x38, 0x1A, 0x8C, 0x41, 0x55, 0xF5, 0xFC, 0x03, 0x85, 0xFE,
-0x66, 0x00, 0x01, 0x00, 0xEE, 0xFF, 0x06, 0x00, 0xFD, 0xFF, 0x2B,
-0x00, 0x59, 0xFF, 0xB0, 0x01, 0x69, 0xFC, 0x0F, 0x07, 0x80, 0xF1,
-0x96, 0x2F, 0xF2, 0x30, 0x7C, 0xF1, 0xFD, 0x06, 0x7A, 0xFC, 0xA3,
-0x01, 0x5F, 0xFF, 0x29, 0x00, 0xFD, 0xFF, 0x05, 0x00, 0xF4, 0xFF,
-0xF2, 0xFF, 0x83, 0x00, 0x53, 0xFE, 0x4E, 0x04, 0xD0, 0xF4, 0xAB,
-0x40, 0xB2, 0x1B, 0x7F, 0xF4, 0x69, 0x06, 0x62, 0xFC, 0xDD, 0x01,
-0x38, 0xFF, 0x36, 0x00, 0xFE, 0xFF, 0x19, 0x00, 0x98, 0xFF, 0xDE,
-0x00, 0x9F, 0xFE, 0xC2, 0x01, 0x4B, 0xFE, 0x48, 0x00, 0xB3, 0x48,
-0x5E, 0x07, 0x3B, 0xFB, 0x59, 0x03, 0xCD, 0xFD, 0x42, 0x01, 0x71,
-0xFF, 0x24, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x30, 0x00, 0x47, 0xFF,
-0xAF, 0x01, 0xD8, 0xFC, 0x52, 0x05, 0x19, 0xF7, 0xB2, 0x12, 0x5C,
-0x45, 0xA9, 0xF8, 0x16, 0x02, 0xA6, 0xFF, 0xC3, 0xFF, 0x51, 0x00,
-0xD0, 0xFF, 0x0C, 0x00, 0xFD, 0xFF, 0x34, 0x00, 0x40, 0xFF, 0xDB,
-0x01, 0x35, 0xFC, 0x25, 0x07, 0x13, 0xF2, 0x3A, 0x28, 0xA0, 0x37,
-0xF2, 0xF1, 0x5A, 0x06, 0xFB, 0xFC, 0x4F, 0x01, 0x8B, 0xFF, 0x1A,
-0x00, 0xFF, 0xFF, 0x00, 0x00, 0x0D, 0x00, 0xAF, 0xFF, 0x09, 0x01,
-0x6E, 0xFD, 0xB4, 0x05, 0xBC, 0xF2, 0x73, 0x3B, 0x64, 0x23, 0xD2,
-0xF2, 0xFB, 0x06, 0x34, 0xFC, 0xE6, 0x01, 0x38, 0xFF, 0x36, 0x00,
-0xFD, 0xFF, 0x11, 0x00, 0xBB, 0xFF, 0x87, 0x00, 0x54, 0xFF, 0x70,
-0x00, 0xB3, 0x00, 0x4E, 0xFB, 0x1A, 0x47, 0x1F, 0x0E, 0xA8, 0xF8,
-0x9B, 0x04, 0x2E, 0xFD, 0x8A, 0x01, 0x55, 0xFF, 0x2C, 0x00, 0xFF,
-0xFF, 0x00, 0x00, 0x29, 0x00, 0x5F, 0xFF, 0x71, 0x01, 0x65, 0xFD,
-0x29, 0x04, 0x96, 0xF9, 0x95, 0x0B, 0xDC, 0x47, 0x03, 0xFD, 0xD9,
-0xFF, 0xEA, 0x00, 0x12, 0xFF, 0xA7, 0x00, 0xAE, 0xFF, 0x14, 0x00,
-0xFD, 0xFF, 0x36, 0x00, 0x36, 0xFF, 0xE6, 0x01, 0x3E, 0xFC, 0xD0,
-0x06, 0x5E, 0xF3, 0x94, 0x20, 0x7B, 0x3D, 0x60, 0xF3, 0x3E, 0x05,
-0xBB, 0xFD, 0xDB, 0x00, 0xC6, 0xFF, 0x04, 0x00, 0x02, 0x00, 0xFE,
-0xFF, 0x20, 0x00, 0x79, 0xFF, 0x72, 0x01, 0xC4, 0xFC, 0xA4, 0x06,
-0xAB, 0xF1, 0x46, 0x35, 0xF7, 0x2A, 0xC6, 0xF1, 0x2A, 0x07, 0x40,
-0xFC, 0xCF, 0x01, 0x47, 0xFF, 0x31, 0x00, 0xFD, 0xFF, 0x09, 0x00,
-0xDB, 0xFF, 0x33, 0x00, 0x01, 0x00, 0x38, 0xFF, 0xD3, 0x02, 0x53,
-0xF7, 0x1F, 0x44, 0x69, 0x15, 0x3F, 0xF6, 0xB2, 0x05, 0xAD, 0xFC,
-0xC1, 0x01, 0x41, 0xFF, 0x32, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x20,
-0x00, 0x7D, 0xFF, 0x24, 0x01, 0x0C, 0xFE, 0xDE, 0x02, 0x2E, 0xFC,
-0x13, 0x05, 0xEC, 0x48, 0x54, 0x02, 0x5E, 0xFD, 0x3F, 0x02, 0x5D,
-0xFE, 0xFE, 0x00, 0x8C, 0xFF, 0x1C, 0x00, 0xFE, 0xFF, 0x35, 0x00,
-0x3B, 0xFF, 0xD3, 0x01, 0x7F, 0xFC, 0x1F, 0x06, 0x3C, 0xF5, 0xE6,
-0x18, 0x4D, 0x42, 0xD5, 0xF5, 0xAF, 0x03, 0xB4, 0xFE, 0x4B, 0x00,
-0x0E, 0x00, 0xE9, 0xFF, 0x07, 0x00, 0xFD, 0xFF, 0x2D, 0x00, 0x53,
-0xFF, 0xBA, 0x01, 0x5B, 0xFC, 0x1B, 0x07, 0x8B, 0xF1, 0x58, 0x2E,
-0x26, 0x32, 0x80, 0xF1, 0xEA, 0x06, 0x8C, 0xFC, 0x97, 0x01, 0x66,
-0xFF, 0x27, 0x00, 0xFD, 0xFF, 0x04, 0x00, 0xF8, 0xFF, 0xE6, 0xFF,
-0x9C, 0x00, 0x27, 0xFE, 0x94, 0x04, 0x61, 0xF4, 0xD7, 0x3F, 0x06,
-0x1D, 0x2B, 0xF4, 0x89, 0x06, 0x56, 0xFC, 0xE0, 0x01, 0x37, 0xFF,
-0x36, 0x00, 0xFE, 0xFF, 0x17, 0x00, 0x9E, 0xFF, 0xCF, 0x00, 0xBF,
-0xFE, 0x86, 0x01, 0xBA, 0xFE, 0x5A, 0xFF, 0x86, 0x48, 0x7D, 0x08,
-0xC7, 0xFA, 0x93, 0x03, 0xB0, 0xFD, 0x4F, 0x01, 0x6C, 0xFF, 0x25,
-0x00, 0x00, 0x00, 0xFF, 0xFF, 0x2F, 0x00, 0x4B, 0xFF, 0xA6, 0x01,
-0xEE, 0xFC, 0x23, 0x05, 0x83, 0xF7, 0x6E, 0x11, 0xE5, 0x45, 0x57,
-0xF9, 0xB8, 0x01, 0xDC, 0xFF, 0xA5, 0xFF, 0x5F, 0x00, 0xCA, 0xFF,
-0x0D, 0x00, 0xFD, 0xFF, 0x35, 0x00, 0x3D, 0xFF, 0xDF, 0x01, 0x32,
-0xFC, 0x1E, 0x07, 0x40, 0xF2, 0xEB, 0x26, 0xB5, 0x38, 0x1F, 0xF2,
-0x32, 0x06, 0x18, 0xFD, 0x3D, 0x01, 0x94, 0xFF, 0x16, 0x00, 0xFF,
-0xFF, 0x00, 0x00, 0x11, 0x00, 0xA4, 0xFF, 0x1D, 0x01, 0x4C, 0xFD,
-0xE6, 0x05, 0x7B, 0xF2, 0x71, 0x3A, 0xB8, 0x24, 0x97, 0xF2, 0x0B,
-0x07, 0x32, 0xFC, 0xE4, 0x01, 0x39, 0xFF, 0x36, 0x00, 0xFD, 0xFF,
-0x0F, 0x00, 0xC0, 0xFF, 0x78, 0x00, 0x73, 0xFF, 0x38, 0x00, 0x17,
-0x01, 0x8B, 0xFA, 0xAF, 0x46, 0x59, 0x0F, 0x39, 0xF8, 0xCF, 0x04,
-0x15, 0xFD, 0x95, 0x01, 0x51, 0xFF, 0x2D, 0x00, 0xFF, 0xFF, 0x00,
-0x00, 0x28, 0x00, 0x64, 0xFF, 0x65, 0x01, 0x81, 0xFD, 0xF2, 0x03,
-0x08, 0xFA, 0x68, 0x0A, 0x25, 0x48, 0xDE, 0xFD, 0x6E, 0xFF, 0x24,
-0x01, 0xF3, 0xFE, 0xB6, 0x00, 0xA8, 0xFF, 0x15, 0x00, 0xFD, 0xFF,
-0x36, 0x00, 0x36, 0xFF, 0xE5, 0x01, 0x46, 0xFC, 0xB8, 0x06, 0xA8,
-0xF3, 0x3F, 0x1F, 0x64, 0x3E, 0xBA, 0xF3, 0x01, 0x05, 0xE2, 0xFD,
-0xC4, 0x00, 0xD2, 0xFF, 0x00, 0x00, 0x02, 0x00, 0xFE, 0xFF, 0x23,
-0x00, 0x71, 0xFF, 0x81, 0x01, 0xAE, 0xFC, 0xC1, 0x06, 0x95, 0xF1,
-0x1E, 0x34, 0x3E, 0x2C, 0xAB, 0xF1, 0x27, 0x07, 0x49, 0xFC, 0xC8,
-0x01, 0x4B, 0xFF, 0x30, 0x00, 0xFD, 0xFF, 0x08, 0x00, 0xE1, 0xFF,
-0x25, 0x00, 0x1D, 0x00, 0x05, 0xFF, 0x28, 0x03, 0xBD, 0xF6, 0x77,
-0x43, 0xB6, 0x16, 0xDC, 0xF5, 0xDD, 0x05, 0x9B, 0xFC, 0xC8, 0x01,
-0x3E, 0xFF, 0x33, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x1F, 0x00, 0x83,
-0xFF, 0x16, 0x01, 0x2A, 0xFE, 0xA3, 0x02, 0xA1, 0xFC, 0x06, 0x04,
-0xF5, 0x48, 0x56, 0x03, 0xED, 0xFC, 0x7B, 0x02, 0x3E, 0xFE, 0x0C,
-0x01, 0x86, 0xFF, 0x1E, 0x00, 0xFE, 0xFF, 0x34, 0x00, 0x3D, 0xFF,
-0xCC, 0x01, 0x8F, 0xFC, 0xF8, 0x05, 0x9B, 0xF5, 0x96, 0x17, 0x02,
-0x43, 0x5E, 0xF6, 0x5F, 0x03, 0xE4, 0xFE, 0x30, 0x00, 0x1B, 0x00,
-0xE4, 0xFF, 0x08, 0x00, 0xFD, 0xFF, 0x2F, 0x00, 0x4E, 0xFF, 0xC3,
-0x01, 0x4F, 0xFC, 0x24, 0x07, 0x9C, 0xF1, 0x17, 0x2D, 0x57, 0x33,
-0x8A, 0xF1, 0xD3, 0x06, 0x9F, 0xFC, 0x8A, 0x01, 0x6D, 0xFF, 0x25,
-0x00, 0xFD, 0xFF, 0x03, 0x00, 0xFD, 0xFF, 0xD9, 0xFF, 0xB4, 0x00,
-0xFD, 0xFD, 0xD7, 0x04, 0xFA, 0xF3, 0xFC, 0x3E, 0x5B, 0x1E, 0xDB,
-0xF3, 0xA6, 0x06, 0x4C, 0xFC, 0xE3, 0x01, 0x36, 0xFF, 0x36, 0x00,
-0xFE, 0xFF, 0x16, 0x00, 0xA4, 0xFF, 0xC0, 0x00, 0xDE, 0xFE, 0x4B,
-0x01, 0x27, 0xFF, 0x73, 0xFE, 0x4F, 0x48, 0xA2, 0x09, 0x54, 0xFA,
-0xCC, 0x03, 0x93, 0xFD, 0x5C, 0x01, 0x67, 0xFF, 0x27, 0x00, 0x00,
-0x00, 0xFF, 0xFF, 0x2E, 0x00, 0x4E, 0xFF, 0x9C, 0x01, 0x05, 0xFD,
-0xF1, 0x04, 0xF0, 0xF7, 0x2D, 0x10, 0x61, 0x46, 0x0D, 0xFA, 0x58,
-0x01, 0x13, 0x00, 0x87, 0xFF, 0x6E, 0x00, 0xC4, 0xFF, 0x0E, 0x00,
-0xFD, 0xFF, 0x35, 0x00, 0x3B, 0xFF, 0xE3, 0x01, 0x31, 0xFC, 0x14,
-0x07, 0x73, 0xF2, 0x99, 0x25, 0xC2, 0x39, 0x54, 0xF2, 0x05, 0x06,
-0x37, 0xFD, 0x2B, 0x01, 0x9E, 0xFF, 0x13, 0x00, 0xFF, 0xFF, 0xFF,
-0xFF, 0x14, 0x00, 0x9B, 0xFF, 0x31, 0x01, 0x2C, 0xFD, 0x15, 0x06,
-0x41, 0xF2, 0x6A, 0x39, 0x0A, 0x26, 0x61, 0xF2, 0x17, 0x07, 0x31,
-0xFC, 0xE2, 0x01, 0x3B, 0xFF, 0x35, 0x00, 0xFD, 0xFF, 0x0E, 0x00,
-0xC6, 0xFF, 0x69, 0x00, 0x91, 0xFF, 0x00, 0x00, 0x78, 0x01, 0xD0,
-0xF9, 0x39, 0x46, 0x98, 0x10, 0xCB, 0xF7, 0x02, 0x05, 0xFE, 0xFC,
-0x9F, 0x01, 0x4D, 0xFF, 0x2E, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x26,
-0x00, 0x69, 0xFF, 0x58, 0x01, 0x9D, 0xFD, 0xB9, 0x03, 0x7B, 0xFA,
-0x40, 0x09, 0x63, 0x48, 0xBF, 0xFE, 0x03, 0xFF, 0x5F, 0x01, 0xD4,
-0xFE, 0xC5, 0x00, 0xA2, 0xFF, 0x16, 0x00, 0xFE, 0xFF, 0x36, 0x00,
-0x36, 0xFF, 0xE2, 0x01, 0x4F, 0xFC, 0x9C, 0x06, 0xF5, 0xF3, 0xEA,
-0x1D, 0x47, 0x3F, 0x1B, 0xF4, 0xC1, 0x04, 0x0B, 0xFE, 0xAC, 0x00,
-0xDE, 0xFF, 0xFB, 0xFF, 0x03, 0x00, 0xFD, 0xFF, 0x25, 0x00, 0x6A,
-0xFF, 0x8E, 0x01, 0x99, 0xFC, 0xDB, 0x06, 0x86, 0xF1, 0xF2, 0x32,
-0x82, 0x2D, 0x96, 0xF1, 0x21, 0x07, 0x53, 0xFC, 0xC0, 0x01, 0x50,
-0xFF, 0x2E, 0x00, 0xFD, 0xFF, 0x07, 0x00, 0xE6, 0xFF, 0x17, 0x00,
-0x39, 0x00, 0xD4, 0xFE, 0x7A, 0x03, 0x2F, 0xF6, 0xC7, 0x42, 0x06,
-0x18, 0x7B, 0xF5, 0x05, 0x06, 0x8A, 0xFC, 0xCF, 0x01, 0x3C, 0xFF,
-0x34, 0x00, 0xFE, 0xFF, 0x1D, 0x00, 0x88, 0xFF, 0x07, 0x01, 0x49,
-0xFE, 0x67, 0x02, 0x13, 0xFD, 0xFF, 0x02, 0xF4, 0x48, 0x5F, 0x04,
-0x7A, 0xFC, 0xB6, 0x02, 0x20, 0xFE, 0x1B, 0x01, 0x81, 0xFF, 0x1F,
-0x00, 0x00, 0x00, 0xFF, 0xFF, 0x33, 0x00, 0x3F, 0xFF, 0xC6, 0x01,
-0xA1, 0xFC, 0xCF, 0x05, 0xFC, 0xF5, 0x47, 0x16, 0xB0, 0x43, 0xEE,
-0xF6, 0x0C, 0x03, 0x16, 0xFF, 0x14, 0x00, 0x29, 0x00, 0xDF, 0xFF,
-0x09, 0x00, 0xFD, 0xFF, 0x30, 0x00, 0x4A, 0xFF, 0xCA, 0x01, 0x46,
-0xFC, 0x29, 0x07, 0xB3, 0xF1, 0xD1, 0x2B, 0x81, 0x34, 0x9C, 0xF1,
-0xB8, 0x06, 0xB5, 0xFC, 0x7C, 0x01, 0x74, 0xFF, 0x22, 0x00, 0xFE,
-0xFF, 0x02, 0x00, 0x01, 0x00, 0xCE, 0xFF, 0xCC, 0x00, 0xD5, 0xFD,
-0x16, 0x05, 0x9B, 0xF3, 0x18, 0x3E, 0xB1, 0x1F, 0x8F, 0xF3, 0xC0,
-0x06, 0x43, 0xFC, 0xE5, 0x01, 0x36, 0xFF, 0x36, 0x00, 0xFD, 0xFF,
-0x15, 0x00, 0xAA, 0xFF, 0xB1, 0x00, 0xFE, 0xFE, 0x10, 0x01, 0x92,
-0xFF, 0x94, 0xFD, 0x0D, 0x48, 0xCB, 0x0A, 0xE2, 0xF9, 0x04, 0x04,
-0x77, 0xFD, 0x69, 0x01, 0x62, 0xFF, 0x28, 0x00, 0x00, 0x00, 0xFF,
-0xFF, 0x2D, 0x00, 0x52, 0xFF, 0x91, 0x01, 0x1E, 0xFD, 0xBE, 0x04,
-0x5E, 0xF8, 0xF0, 0x0E, 0xD3, 0x46, 0xCB, 0xFA, 0xF6, 0x00, 0x4B,
-0x00, 0x69, 0xFF, 0x7D, 0x00, 0xBE, 0xFF, 0x10, 0x00, 0xFD, 0xFF,
-0x36, 0x00, 0x39, 0xFF, 0xE5, 0x01, 0x32, 0xFC, 0x06, 0x07, 0xAA,
-0xF2, 0x46, 0x24, 0xC8, 0x3A, 0x90, 0xF2, 0xD6, 0x05, 0x57, 0xFD,
-0x17, 0x01, 0xA8, 0xFF, 0x0F, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x18,
-0x00, 0x91, 0xFF, 0x43, 0x01, 0x0E, 0xFD, 0x40, 0x06, 0x0F, 0xF2,
-0x5B, 0x38, 0x5C, 0x27, 0x30, 0xF2, 0x21, 0x07, 0x33, 0xFC, 0xDE,
-0x01, 0x3E, 0xFF, 0x34, 0x00, 0xFD, 0xFF, 0x0D, 0x00, 0xCC, 0xFF,
-0x5A, 0x00, 0xAF, 0xFF, 0xCA, 0xFF, 0xD8, 0x01, 0x1C, 0xF9, 0xB8,
-0x45, 0xDA, 0x11, 0x60, 0xF7, 0x33, 0x05, 0xE7, 0xFC, 0xA9, 0x01,
-0x4A, 0xFF, 0x30, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x25, 0x00, 0x6E,
-0xFF, 0x4B, 0x01, 0xB9, 0xFD, 0x80, 0x03, 0xEE, 0xFA, 0x1D, 0x08,
-0x98, 0x48, 0xA8, 0xFF, 0x95, 0xFE, 0x9A, 0x01, 0xB4, 0xFE, 0xD4,
-0x00, 0x9C, 0xFF, 0x18, 0x00, 0xFE, 0xFF, 0x36, 0x00, 0x37, 0xFF,
-0xDF, 0x01, 0x5A, 0xFC, 0x7E, 0x06, 0x47, 0xF4, 0x94, 0x1C, 0x1F,
-0x40, 0x85, 0xF4, 0x7D, 0x04, 0x36, 0xFE, 0x93, 0x00, 0xEA, 0xFF,
-0xF7, 0xFF, 0x04, 0x00, 0xFD, 0xFF, 0x28, 0x00, 0x63, 0xFF, 0x9B,
-0x01, 0x86, 0xFC, 0xF1, 0x06, 0x7E, 0xF1, 0xC0, 0x31, 0xC2, 0x2E,
-0x87, 0xF1, 0x17, 0x07, 0x5F, 0xFC, 0xB6, 0x01, 0x55, 0xFF, 0x2D,
-0x00, 0xFD, 0xFF, 0x06, 0x00, 0xEB, 0xFF, 0x09, 0x00, 0x54, 0x00,
-0xA4, 0xFE, 0xC9, 0x03, 0xAA, 0xF5, 0x0C, 0x42, 0x56, 0x19, 0x1E,
-0xF5, 0x2B, 0x06, 0x7A, 0xFC, 0xD4, 0x01, 0x3A, 0xFF, 0x35, 0x00,
-0xFE, 0xFF, 0x1C, 0x00, 0x8E, 0xFF, 0xF9, 0x00, 0x68, 0xFE, 0x2C,
-0x02, 0x84, 0xFD, 0xFF, 0x01, 0xE6, 0x48, 0x6E, 0x05, 0x07, 0xFC,
-0xF1, 0x02, 0x01, 0xFE, 0x29, 0x01, 0x7B, 0xFF, 0x21, 0x00, 0x00,
-0x00, 0xFF, 0xFF, 0x32, 0x00, 0x42, 0xFF, 0xBE, 0x01, 0xB4, 0xFC,
-0xA4, 0x05, 0x61, 0xF6, 0xFB, 0x14, 0x53, 0x44, 0x86, 0xF7, 0xB6,
-0x02, 0x49, 0xFF, 0xF7, 0xFF, 0x37, 0x00, 0xD9, 0xFF, 0x0A, 0x00,
-0xFD, 0xFF, 0x32, 0x00, 0x46, 0xFF, 0xD1, 0x01, 0x3E, 0xFC, 0x2B,
-0x07, 0xD0, 0xF1, 0x89, 0x2A, 0xA6, 0x35, 0xB4, 0xF1, 0x99, 0x06,
-0xCD, 0xFC, 0x6D, 0x01, 0x7C, 0xFF, 0x1F, 0x00, 0xFE, 0xFF, 0x01,
-0x00, 0x06, 0x00, 0xC2, 0xFF, 0xE3, 0x00, 0xAE, 0xFD, 0x52, 0x05,
-0x44, 0xF3, 0x2A, 0x3D, 0x06, 0x21, 0x47, 0xF3, 0xD8, 0x06, 0x3C,
-0xFC, 0xE6, 0x01, 0x36, 0xFF, 0x36, 0x00, 0xFD, 0xFF, 0x13, 0x00,
-0xB0, 0xFF, 0xA2, 0x00, 0x1D, 0xFF, 0xD6, 0x00, 0xFC, 0xFF, 0xBC,
-0xFC, 0xC0, 0x47, 0xFA, 0x0B, 0x70, 0xF9, 0x3C, 0x04, 0x5C, 0xFD,
-0x75, 0x01, 0x5D, 0xFF, 0x2A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2B,
-0x00, 0x57, 0xFF, 0x86, 0x01, 0x36, 0xFD, 0x89, 0x04, 0xCD, 0xF8,
-0xB7, 0x0D, 0x3D, 0x47, 0x91, 0xFB, 0x91, 0x00, 0x83, 0x00, 0x4A,
-0xFF, 0x8C, 0x00, 0xB9, 0xFF, 0x11, 0x00, 0xFD, 0xFF, 0x36, 0x00,
-0x38, 0xFF, 0xE6, 0x01, 0x35, 0xFC, 0xF5, 0x06, 0xE7, 0xF2, 0xF2,
-0x22, 0xC7, 0x3B, 0xD4, 0xF2, 0xA2, 0x05, 0x7A, 0xFD, 0x02, 0x01,
-0xB2, 0xFF, 0x0B, 0x00, 0x01, 0x00, 0xFE, 0xFF, 0x1B, 0x00, 0x88,
-0xFF, 0x55, 0x01, 0xF2, 0xFC, 0x67, 0x06, 0xE4, 0xF1, 0x44, 0x37,
-0xAA, 0x28, 0x05, 0xF2, 0x27, 0x07, 0x36, 0xFC, 0xDA, 0x01, 0x41,
-0xFF, 0x33, 0x00, 0xFD, 0xFF, 0x0B, 0x00, 0xD2, 0xFF, 0x4C, 0x00,
-0xCD, 0xFF, 0x94, 0xFF, 0x34, 0x02, 0x70, 0xF8, 0x2E, 0x45, 0x20,
-0x13, 0xF6, 0xF6, 0x62, 0x05, 0xD1, 0xFC, 0xB2, 0x01, 0x46, 0xFF,
-0x31, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x23, 0x00, 0x73, 0xFF, 0x3D,
-0x01, 0xD6, 0xFD, 0x46, 0x03, 0x61, 0xFB, 0x00, 0x07, 0xBF, 0x48,
-0x98, 0x00, 0x26, 0xFE, 0xD5, 0x01, 0x95, 0xFE, 0xE3, 0x00, 0x96,
-0xFF, 0x1A, 0x00, 0xFE, 0xFF, 0x36, 0x00, 0x38, 0xFF, 0xDB, 0x01,
-0x66, 0xFC, 0x5E, 0x06, 0x9C, 0xF4, 0x40, 0x1B, 0xEF, 0x40, 0xF7,
-0xF4, 0x35, 0x04, 0x62, 0xFE, 0x7A, 0x00, 0xF7, 0xFF, 0xF2, 0xFF,
-0x05, 0x00, 0xFD, 0xFF, 0x2A, 0x00, 0x5D, 0xFF, 0xA7, 0x01, 0x75,
-0xFC, 0x03, 0x07, 0x7D, 0xF1, 0x8A, 0x30, 0xFF, 0x2F, 0x7E, 0xF1,
-0x0A, 0x07, 0x6E, 0xFC, 0xAC, 0x01, 0x5A, 0xFF, 0x2B, 0x00, 0xFD,
-0xFF, 0x05, 0x00, 0xF0, 0xFF, 0xFC, 0xFF, 0x6E, 0x00, 0x76, 0xFE,
-0x15, 0x04, 0x2C, 0xF5, 0x49, 0x41, 0xA9, 0x1A, 0xC3, 0xF4, 0x4F,
-0x06, 0x6C, 0xFC, 0xD9, 0x01, 0x38, 0xFF, 0x35, 0x00, 0xFE, 0xFF,
-0x1A, 0x00, 0x94, 0xFF, 0xEA, 0x00, 0x87, 0xFE, 0xF0, 0x01, 0xF5,
-0xFD, 0x05, 0x01, 0xCE, 0x48, 0x83, 0x06, 0x94, 0xFB, 0x2C, 0x03,
-0xE4, 0xFD, 0x37, 0x01, 0x76, 0xFF, 0x22, 0x00, 0x00, 0x00, 0xFF,
-0xFF, 0x31, 0x00, 0x45, 0xFF, 0xB6, 0x01, 0xC8, 0xFC, 0x77, 0x05,
-0xC7, 0xF6, 0xB1, 0x13, 0xED, 0x44, 0x26, 0xF8, 0x5D, 0x02, 0x7D,
-0xFF, 0xDA, 0xFF, 0x46, 0x00, 0xD4, 0xFF, 0x0B, 0x00, 0xFD, 0xFF,
-0x33, 0x00, 0x42, 0xFF, 0xD7, 0x01, 0x38, 0xFC, 0x29, 0x07, 0xF3,
-0xF1, 0x3E, 0x29, 0xC6, 0x36, 0xD4, 0xF1, 0x77, 0x06, 0xE6, 0xFC,
-0x5C, 0x01, 0x84, 0xFF, 0x1C, 0x00, 0xFE, 0xFF, 0x01, 0x00, 0x0A,
-0x00, 0xB7, 0xFF, 0xF9, 0x00, 0x89, 0xFD, 0x8A, 0x05, 0xF4, 0xF2,
-0x37, 0x3C, 0x5B, 0x22, 0x03, 0xF3, 0xED, 0x06, 0x37, 0xFC, 0xE6,
-0x01, 0x37, 0xFF, 0x36, 0x00, 0xFD, 0xFF, 0x12, 0x00, 0xB6, 0xFF,
-0x93, 0x00, 0x3C, 0xFF, 0x9D, 0x00, 0x63, 0x00, 0xEB, 0xFB, 0x69,
-0x47, 0x2D, 0x0D, 0xFF, 0xF8, 0x72, 0x04, 0x42, 0xFD, 0x81, 0x01,
-0x59, 0xFF, 0x2B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2A, 0x00, 0x5B,
-0xFF, 0x7A, 0x01, 0x50, 0xFD, 0x54, 0x04, 0x3D, 0xF9, 0x82, 0x0C,
-0x9A, 0x47, 0x5E, 0xFC, 0x2A, 0x00, 0xBD, 0x00, 0x2B, 0xFF, 0x9B,
-0x00, 0xB3, 0xFF, 0x12, 0x00, 0xFD, 0xFF, 0x36, 0x00, 0x37, 0xFF,
-0xE6, 0x01, 0x3A, 0xFC, 0xE2, 0x06, 0x28, 0xF3, 0x9E, 0x21, 0xC0,
-0x3C, 0x1F, 0xF3, 0x6C, 0x05, 0x9E, 0xFD, 0xED, 0x00, 0xBD, 0xFF,
-0x07, 0x00, 0x01, 0x00, 0xFE, 0xFF, 0x1E, 0x00, 0x80, 0xFF, 0x66,
-0x01, 0xD8, 0xFC, 0x8B, 0x06, 0xC1, 0xF1, 0x27, 0x36, 0xF6, 0x29,
-0xDF, 0xF1, 0x2A, 0x07, 0x3B, 0xFC, 0xD4, 0x01, 0x44, 0xFF, 0x32,
-0x00, 0xFD, 0xFF, 0x0A, 0x00, 0xD7, 0xFF, 0x3E, 0x00, 0xEA, 0xFF,
-0x60, 0xFF, 0x8F, 0x02, 0xCD, 0xF7, 0x99, 0x44, 0x68, 0x14, 0x8E,
-0xF6, 0x90, 0x05, 0xBC, 0xFC, 0xBA, 0x01, 0x43, 0xFF, 0x32, 0x00,
-0xFF, 0xFF, 0x00, 0x00, 0x22, 0x00, 0x79, 0xFF, 0x2F, 0x01, 0xF4,
-0xFD, 0x0C, 0x03, 0xD4, 0xFB, 0xE9, 0x05, 0xDE, 0x48, 0x8F, 0x01,
-0xB6, 0xFD, 0x11, 0x02, 0x76, 0xFE, 0xF2, 0x00, 0x91, 0xFF, 0x1B,
-0x00, 0xFE, 0xFF, 0x35, 0x00, 0x39, 0xFF, 0xD7, 0x01, 0x73, 0xFC,
-0x3B, 0x06, 0xF5, 0xF4, 0xED, 0x19, 0xB7, 0x41, 0x71, 0xF5, 0xEB,
-0x03, 0x90, 0xFE, 0x60, 0x00, 0x04, 0x00, 0xED, 0xFF, 0x06, 0x00,
-0xFD, 0xFF, 0x2C, 0x00, 0x57, 0xFF, 0xB2, 0x01, 0x65, 0xFC, 0x12,
-0x07, 0x82, 0xF1, 0x50, 0x2F, 0x38, 0x31, 0x7C, 0xF1, 0xF9, 0x06,
-0x7E, 0xFC, 0xA1, 0x01, 0x61, 0xFF, 0x29, 0x00, 0xFD, 0xFF, 0x04,
-0x00, 0xF5, 0xFF, 0xEF, 0xFF, 0x88, 0x00, 0x49, 0xFE, 0x5D, 0x04,
-0xB7, 0xF4, 0x7D, 0x40, 0xFD, 0x1B, 0x6C, 0xF4, 0x70, 0x06, 0x5F,
-0xFC, 0xDE, 0x01, 0x37, 0xFF, 0x36, 0x00, 0xFE, 0xFF, 0x19, 0x00,
-0x9A, 0xFF, 0xDB, 0x00, 0xA6, 0xFE, 0xB4, 0x01, 0x64, 0xFE, 0x12,
-0x00, 0xAA, 0x48, 0x9E, 0x07, 0x21, 0xFB, 0x66, 0x03, 0xC6, 0xFD,
-0x45, 0x01, 0x70, 0xFF, 0x24, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x30,
-0x00, 0x48, 0xFF, 0xAD, 0x01, 0xDD, 0xFC, 0x48, 0x05, 0x30, 0xF7,
-0x6B, 0x12, 0x7D, 0x45, 0xCF, 0xF8, 0x01, 0x02, 0xB2, 0xFF, 0xBD,
-0xFF, 0x54, 0x00, 0xCE, 0xFF, 0x0C, 0x00, 0xFD, 0xFF, 0x34, 0x00,
-0x3F, 0xFF, 0xDC, 0x01, 0x34, 0xFC, 0x24, 0x07, 0x1C, 0xF2, 0xF0,
-0x27, 0xDF, 0x37, 0xFB, 0xF1, 0x51, 0x06, 0x01, 0xFD, 0x4B, 0x01,
-0x8D, 0xFF, 0x19, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x0E, 0x00, 0xAC,
-0xFF, 0x0E, 0x01, 0x66, 0xFD, 0xBF, 0x05, 0xAD, 0xF2, 0x3B, 0x3B,
-0xB0, 0x23, 0xC4, 0xF2, 0xFF, 0x06, 0x33, 0xFC, 0xE5, 0x01, 0x38,
-0xFF, 0x36, 0x00, 0xFD, 0xFF, 0x10, 0x00, 0xBC, 0xFF, 0x84, 0x00,
-0x5B, 0xFF, 0x64, 0x00, 0xC9, 0x00, 0x22, 0xFB, 0x02, 0x47, 0x64,
-0x0E, 0x8F, 0xF8, 0xA7, 0x04, 0x29, 0xFD, 0x8C, 0x01, 0x54, 0xFF,
-0x2C, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x29, 0x00, 0x60, 0xFF, 0x6E,
-0x01, 0x6B, 0xFD, 0x1D, 0x04, 0xAF, 0xF9, 0x51, 0x0B, 0xEC, 0x47,
-0x33, 0xFD, 0xC1, 0xFF, 0xF7, 0x00, 0x0C, 0xFF, 0xAA, 0x00, 0xAD,
-0xFF, 0x14, 0x00, 0xFD, 0xFF, 0x36, 0x00, 0x36, 0xFF, 0xE6, 0x01,
-0x40, 0xFC, 0xCB, 0x06, 0x6E, 0xF3, 0x49, 0x20, 0xB0, 0x3D, 0x73,
-0xF3, 0x31, 0x05, 0xC4, 0xFD, 0xD6, 0x00, 0xC8, 0xFF, 0x03, 0x00,
-0x02, 0x00, 0xFE, 0xFF, 0x21, 0x00, 0x77, 0xFF, 0x75, 0x01, 0xBF,
-0xFC, 0xAB, 0x06, 0xA6, 0xF1, 0x05, 0x35, 0x40, 0x2B, 0xBF, 0xF1,
-0x2A, 0x07, 0x42, 0xFC, 0xCE, 0x01, 0x48, 0xFF, 0x31, 0x00, 0xFD,
-0xFF, 0x09, 0x00, 0xDC, 0xFF, 0x2F, 0x00, 0x07, 0x00, 0x2C, 0xFF,
-0xE6, 0x02, 0x31, 0xF7, 0xFA, 0x43, 0xB3, 0x15, 0x29, 0xF6, 0xBC,
-0x05, 0xA9, 0xFC, 0xC2, 0x01, 0x40, 0xFF, 0x33, 0x00, 0xFF, 0xFF,
-0x00, 0x00, 0x20, 0x00, 0x7E, 0xFF, 0x21, 0x01, 0x12, 0xFE, 0xD1,
-0x02, 0x47, 0xFC, 0xD7, 0x04, 0xF0, 0x48, 0x8D, 0x02, 0x45, 0xFD,
-0x4D, 0x02, 0x56, 0xFE, 0x01, 0x01, 0x8B, 0xFF, 0x1D, 0x00, 0xFE,
-0xFF, 0x34, 0x00, 0x3B, 0xFF, 0xD1, 0x01, 0x83, 0xFC, 0x16, 0x06,
-0x51, 0xF5, 0x9B, 0x18, 0x75, 0x42, 0xF3, 0xF5, 0x9D, 0x03, 0xBF,
-0xFE, 0x45, 0x00, 0x11, 0x00, 0xE8, 0xFF, 0x07, 0x00, 0xFD, 0xFF,
-0x2E, 0x00, 0x52, 0xFF, 0xBC, 0x01, 0x58, 0xFC, 0x1D, 0x07, 0x8E,
-0xF1, 0x11, 0x2E, 0x6B, 0x32, 0x81, 0xF1, 0xE5, 0x06, 0x90, 0xFC,
-0x94, 0x01, 0x67, 0xFF, 0x26, 0x00, 0xFD, 0xFF, 0x04, 0x00, 0xF9,
-0xFF, 0xE3, 0xFF, 0xA1, 0x00, 0x1E, 0xFE, 0xA3, 0x04, 0x49, 0xF4,
-0xA8, 0x3F, 0x52, 0x1D, 0x19, 0xF4, 0x90, 0x06, 0x53, 0xFC, 0xE1,
-0x01, 0x36, 0xFF, 0x36, 0x00, 0xFE, 0xFF, 0x17, 0x00, 0xA0, 0xFF,
-0xCC, 0x00, 0xC6, 0xFE, 0x79, 0x01, 0xD2, 0xFE, 0x26, 0xFF, 0x7C,
-0x48, 0xBE, 0x08, 0xAE, 0xFA, 0xA0, 0x03, 0xA9, 0xFD, 0x52, 0x01,
-0x6B, 0xFF, 0x25, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x2F, 0x00, 0x4C,
-0xFF, 0xA3, 0x01, 0xF3, 0xFC, 0x18, 0x05, 0x9B, 0xF7, 0x27, 0x11,
-0x02, 0x46, 0x7F, 0xF9, 0xA3, 0x01, 0xE8, 0xFF, 0x9F, 0xFF, 0x63,
-0x00, 0xC9, 0xFF, 0x0D, 0x00, 0xFD, 0xFF, 0x35, 0x00, 0x3C, 0xFF,
-0xE0, 0x01, 0x32, 0xFC, 0x1C, 0x07, 0x4B, 0xF2, 0xA0, 0x26, 0xF2,
-0x38, 0x2A, 0xF2, 0x28, 0x06, 0x1F, 0xFD, 0x39, 0x01, 0x96, 0xFF,
-0x16, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x11, 0x00, 0xA2, 0xFF, 0x22,
-0x01, 0x45, 0xFD, 0xF1, 0x05, 0x6D, 0xF2, 0x38, 0x3A, 0x03, 0x25,
-0x8B, 0xF2, 0x0E, 0x07, 0x32, 0xFC, 0xE4, 0x01, 0x3A, 0xFF, 0x36,
-0x00, 0xFD, 0xFF, 0x0F, 0x00, 0xC2, 0xFF, 0x75, 0x00, 0x7A, 0xFF,
-0x2B, 0x00, 0x2D, 0x01, 0x61, 0xFA, 0x97, 0x46, 0xA0, 0x0F, 0x20,
-0xF8, 0xDA, 0x04, 0x10, 0xFD, 0x97, 0x01, 0x50, 0xFF, 0x2E, 0x00,
-0xFF, 0xFF, 0x00, 0x00, 0x27, 0x00, 0x65, 0xFF, 0x62, 0x01, 0x87,
-0xFD, 0xE5, 0x03, 0x21, 0xFA, 0x25, 0x0A, 0x33, 0x48, 0x0F, 0xFE,
-0x57, 0xFF, 0x31, 0x01, 0xEC, 0xFE, 0xB9, 0x00, 0xA7, 0xFF, 0x15,
-0x00, 0xFE, 0xFF, 0x36, 0x00, 0x36, 0xFF, 0xE4, 0x01, 0x48, 0xFC,
-0xB2, 0x06, 0xB9, 0xF3, 0xF3, 0x1E, 0x98, 0x3E, 0xCF, 0xF3, 0xF3,
-0x04, 0xEB, 0xFD, 0xBF, 0x00, 0xD4, 0xFF, 0xFF, 0xFF, 0x03, 0x00,
-0xFE, 0xFF, 0x23, 0x00, 0x70, 0xFF, 0x84, 0x01, 0xA9, 0xFC, 0xC7,
-0x06, 0x91, 0xF1, 0xDC, 0x33, 0x87, 0x2C, 0xA5, 0xF1, 0x26, 0x07,
-0x4B, 0xFC, 0xC6, 0x01, 0x4C, 0xFF, 0x30, 0x00, 0xFD, 0xFF, 0x08,
-0x00, 0xE2, 0xFF, 0x21, 0x00, 0x23, 0x00, 0xFA, 0xFE, 0x3A, 0x03,
-0x9D, 0xF6, 0x50, 0x43, 0x00, 0x17, 0xC6, 0xF5, 0xE6, 0x05, 0x97,
-0xFC, 0xC9, 0x01, 0x3E, 0xFF, 0x34, 0x00, 0xFE, 0xFF, 0x00, 0x00,
-0x1E, 0x00, 0x84, 0xFF, 0x13, 0x01, 0x31, 0xFE, 0x95, 0x02, 0xBA,
-0xFC, 0xCB, 0x03, 0xF7, 0x48, 0x91, 0x03, 0xD3, 0xFC, 0x88, 0x02,
-0x38, 0xFE, 0x10, 0x01, 0x85, 0xFF, 0x1E, 0x00, 0xFE, 0xFF, 0x34,
-0x00, 0x3D, 0xFF, 0xCB, 0x01, 0x93, 0xFC, 0xEF, 0x05, 0xB0, 0xF5,
-0x4B, 0x17, 0x2A, 0x43, 0x7D, 0xF6, 0x4D, 0x03, 0xEF, 0xFE, 0x2A,
-0x00, 0x1E, 0x00, 0xE3, 0xFF, 0x08, 0x00, 0xFD, 0xFF, 0x2F, 0x00,
-0x4D, 0xFF, 0xC4, 0x01, 0x4D, 0xFC, 0x25, 0x07, 0xA1, 0xF1, 0xCE,
-0x2C, 0x99, 0x33, 0x8E, 0xF1, 0xCD, 0x06, 0xA4, 0xFC, 0x87, 0x01,
-0x6E, 0xFF, 0x24, 0x00, 0xFD, 0xFF, 0x03, 0x00, 0xFE, 0xFF, 0xD7,
-0xFF, 0xBA, 0x00, 0xF4, 0xFD, 0xE5, 0x04, 0xE4, 0xF3, 0xCA, 0x3E,
-0xA7, 0x1E, 0xCA, 0xF3, 0xAC, 0x06, 0x4A, 0xFC, 0xE4, 0x01, 0x36,
-0xFF, 0x36, 0x00, 0xFE, 0xFF, 0x16, 0x00, 0xA6, 0xFF, 0xBD, 0x00,
-0xE5, 0xFE, 0x3E, 0x01, 0x3F, 0xFF, 0x41, 0xFE, 0x41, 0x48, 0xE4,
-0x09, 0x3B, 0xFA, 0xD9, 0x03, 0x8D, 0xFD, 0x5F, 0x01, 0x66, 0xFF,
-0x27, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x2E, 0x00, 0x4F, 0xFF, 0x99,
-0x01, 0x0B, 0xFD, 0xE6, 0x04, 0x08, 0xF8, 0xE7, 0x0F, 0x7C, 0x46,
-0x37, 0xFA, 0x42, 0x01, 0x1F, 0x00, 0x81, 0xFF, 0x71, 0x00, 0xC3,
-0xFF, 0x0F, 0x00, 0xFD, 0xFF, 0x35, 0x00, 0x3A, 0xFF, 0xE3, 0x01,
-0x31, 0xFC, 0x11, 0x07, 0x7F, 0xF2, 0x4E, 0x25, 0xFD, 0x39, 0x60,
-0xF2, 0xFB, 0x05, 0x3E, 0xFD, 0x26, 0x01, 0xA0, 0xFF, 0x12, 0x00,
-0x00, 0x00, 0xFF, 0xFF, 0x15, 0x00, 0x98, 0xFF, 0x35, 0x01, 0x25,
-0xFD, 0x1E, 0x06, 0x35, 0xF2, 0x2E, 0x39, 0x55, 0x26, 0x56, 0xF2,
-0x1A, 0x07, 0x31, 0xFC, 0xE1, 0x01, 0x3C, 0xFF, 0x35, 0x00, 0xFD,
-0xFF, 0x0E, 0x00, 0xC7, 0xFF, 0x66, 0x00, 0x98, 0xFF, 0xF4, 0xFF,
-0x8E, 0x01, 0xA7, 0xF9, 0x1D, 0x46, 0xDF, 0x10, 0xB3, 0xF7, 0x0D,
-0x05, 0xF8, 0xFC, 0xA1, 0x01, 0x4C, 0xFF, 0x2F, 0x00, 0xFF, 0xFF,
-0x00, 0x00, 0x26, 0x00, 0x6A, 0xFF, 0x55, 0x01, 0xA3, 0xFD, 0xAD,
-0x03, 0x94, 0xFA, 0xFF, 0x08, 0x70, 0x48, 0xF3, 0xFE, 0xEA, 0xFE,
-0x6C, 0x01, 0xCD, 0xFE, 0xC9, 0x00, 0xA1, 0xFF, 0x17, 0x00, 0xFE,
-0xFF, 0x36, 0x00, 0x36, 0xFF, 0xE2, 0x01, 0x51, 0xFC, 0x96, 0x06,
-0x07, 0xF4, 0x9E, 0x1D, 0x77, 0x3F, 0x32, 0xF4, 0xB2, 0x04, 0x15,
-0xFE, 0xA7, 0x00, 0xE0, 0xFF, 0xFA, 0xFF, 0x03, 0x00, 0xFD, 0xFF,
-0x26, 0x00, 0x69, 0xFF, 0x91, 0x01, 0x94, 0xFC, 0xE0, 0x06, 0x84,
-0xF1, 0xAF, 0x32, 0xCA, 0x2D, 0x92, 0xF1, 0x1F, 0x07, 0x56, 0xFC,
-0xBE, 0x01, 0x51, 0xFF, 0x2E, 0x00, 0xFD, 0xFF, 0x07, 0x00, 0xE7,
-0xFF, 0x14, 0x00, 0x3F, 0x00, 0xC9, 0xFE, 0x8C, 0x03, 0x11, 0xF6,
-0x9E, 0x42, 0x50, 0x18, 0x66, 0xF5, 0x0D, 0x06, 0x86, 0xFC, 0xD0,
-0x01, 0x3B, 0xFF, 0x34, 0x00, 0xFE, 0xFF, 0x1D, 0x00, 0x8A, 0xFF,
-0x04, 0x01, 0x50, 0xFE, 0x5A, 0x02, 0x2C, 0xFD, 0xC6, 0x02, 0xF2,
-0x48, 0x9B, 0x04, 0x61, 0xFC, 0xC3, 0x02, 0x19, 0xFE, 0x1E, 0x01,
-0x7F, 0xFF, 0x20, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x33, 0x00, 0x40,
-0xFF, 0xC4, 0x01, 0xA5, 0xFC, 0xC5, 0x05, 0x13, 0xF6, 0xFD, 0x15,
-0xD4, 0x43, 0x0F, 0xF7, 0xF9, 0x02, 0x21, 0xFF, 0x0D, 0x00, 0x2C,
-0x00, 0xDE, 0xFF, 0x09, 0x00, 0xFD, 0xFF, 0x31, 0x00, 0x49, 0xFF,
-0xCC, 0x01, 0x44, 0xFC, 0x29, 0x07, 0xB9, 0xF1, 0x89, 0x2B, 0xC3,
-0x34, 0xA0, 0xF1, 0xB1, 0x06, 0xBA, 0xFC, 0x79, 0x01, 0x76, 0xFF,
-0x21, 0x00, 0xFE, 0xFF, 0x02, 0x00, 0x02, 0x00, 0xCB, 0xFF, 0xD1,
-0x00, 0xCC, 0xFD, 0x24, 0x05, 0x87, 0xF3, 0xE4, 0x3D, 0xFD, 0x1F,
-0x7F, 0xF3, 0xC6, 0x06, 0x41, 0xFC, 0xE5, 0x01, 0x36, 0xFF, 0x36,
-0x00, 0xFD, 0xFF, 0x14, 0x00, 0xAC, 0xFF, 0xAE, 0x00, 0x05, 0xFF,
-0x03, 0x01, 0xAA, 0xFF, 0x63, 0xFD, 0xFD, 0x47, 0x0E, 0x0B, 0xC8,
-0xF9, 0x11, 0x04, 0x71, 0xFD, 0x6C, 0x01, 0x61, 0xFF, 0x28, 0x00,
-0x00, 0x00, 0xFF, 0xFF, 0x2D, 0x00, 0x53, 0xFF, 0x8F, 0x01, 0x23,
-0xFD, 0xB2, 0x04, 0x76, 0xF8, 0xAA, 0x0E, 0xED, 0x46, 0xF7, 0xFA,
-0xDF, 0x00, 0x57, 0x00, 0x62, 0xFF, 0x80, 0x00, 0xBD, 0xFF, 0x10,
-0x00, 0xFD, 0xFF, 0x36, 0x00, 0x39, 0xFF, 0xE5, 0x01, 0x33, 0xFC,
-0x03, 0x07, 0xB7, 0xF2, 0xFC, 0x23, 0x03, 0x3B, 0x9E, 0xF2, 0xCB,
-0x05, 0x5F, 0xFD, 0x12, 0x01, 0xAA, 0xFF, 0x0E, 0x00, 0x00, 0x00,
-0xFF, 0xFF, 0x18, 0x00, 0x8F, 0xFF, 0x47, 0x01, 0x08, 0xFD, 0x49,
-0x06, 0x05, 0xF2, 0x1D, 0x38, 0xA6, 0x27, 0x26, 0xF2, 0x23, 0x07,
-0x33, 0xFC, 0xDD, 0x01, 0x3E, 0xFF, 0x34, 0x00, 0xFD, 0xFF, 0x0C,
-0x00, 0xCD, 0xFF, 0x57, 0x00, 0xB6, 0xFF, 0xBE, 0xFF, 0xED, 0x01,
-0xF5, 0xF8, 0x9B, 0x45, 0x22, 0x12, 0x48, 0xF7, 0x3D, 0x05, 0xE2,
-0xFC, 0xAB, 0x01, 0x49, 0xFF, 0x30, 0x00, 0xFF, 0xFF, 0x00, 0x00,
-0x24, 0x00, 0x6F, 0xFF, 0x48, 0x01, 0xC0, 0xFD, 0x73, 0x03, 0x07,
-0xFB, 0xDD, 0x07, 0xA1, 0x48, 0xDD, 0xFF, 0x7D, 0xFE, 0xA7, 0x01,
-0xAD, 0xFE, 0xD8, 0x00, 0x9B, 0xFF, 0x18, 0x00, 0xFE, 0xFF, 0x36,
-0x00, 0x37, 0xFF, 0xDF, 0x01, 0x5C, 0xFC, 0x78, 0x06, 0x5A, 0xF4,
-0x49, 0x1C, 0x4E, 0x40, 0x9E, 0xF4, 0x6D, 0x04, 0x3F, 0xFE, 0x8E,
-0x00, 0xED, 0xFF, 0xF6, 0xFF, 0x04, 0x00, 0xFD, 0xFF, 0x28, 0x00,
-0x62, 0xFF, 0x9E, 0x01, 0x82, 0xFC, 0xF5, 0x06, 0x7D, 0xF1, 0x7B,
-0x31, 0x09, 0x2F, 0x84, 0xF1, 0x15, 0x07, 0x62, 0xFC, 0xB4, 0x01,
-0x56, 0xFF, 0x2C, 0x00, 0xFD, 0xFF, 0x06, 0x00, 0xEC, 0xFF, 0x06,
-0x00, 0x5A, 0x00, 0x9A, 0xFE, 0xDA, 0x03, 0x8D, 0xF5, 0xE1, 0x41,
-0xA1, 0x19, 0x09, 0xF5, 0x33, 0x06, 0x77, 0xFC, 0xD6, 0x01, 0x3A,
-0xFF, 0x35, 0x00, 0xFE, 0xFF, 0x1B, 0x00, 0x8F, 0xFF, 0xF5, 0x00,
-0x6F, 0xFE, 0x1E, 0x02, 0x9D, 0xFD, 0xC7, 0x01, 0xE1, 0x48, 0xAB,
-0x05, 0xEE, 0xFB, 0xFE, 0x02, 0xFB, 0xFD, 0x2C, 0x01, 0x7A, 0xFF,
-0x21, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x32, 0x00, 0x42, 0xFF, 0xBC,
-0x01, 0xB8, 0xFC, 0x9A, 0x05, 0x77, 0xF6, 0xB1, 0x14, 0x77, 0x44,
-0xA9, 0xF7, 0xA2, 0x02, 0x54, 0xFF, 0xF1, 0xFF, 0x3A, 0x00, 0xD8,
-0xFF, 0x0A, 0x00, 0xFD, 0xFF, 0x32, 0x00, 0x45, 0xFF, 0xD3, 0x01,
-0x3C, 0xFC, 0x2A, 0x07, 0xD8, 0xF1, 0x3F, 0x2A, 0xE6, 0x35, 0xBB,
-0xF1, 0x92, 0x06, 0xD2, 0xFC, 0x69, 0x01, 0x7E, 0xFF, 0x1F, 0x00,
-0xFE, 0xFF, 0x01, 0x00, 0x07, 0x00, 0xC0, 0xFF, 0xE8, 0x00, 0xA6,
-0xFD, 0x5F, 0x05, 0x31, 0xF3, 0xF6, 0x3C, 0x52, 0x21, 0x37, 0xF3,
-0xDD, 0x06, 0x3B, 0xFC, 0xE6, 0x01, 0x36, 0xFF, 0x36, 0x00, 0xFD,
-0xFF, 0x13, 0x00, 0xB1, 0xFF, 0x9F, 0x00, 0x24, 0xFF, 0xC9, 0x00,
-0x13, 0x00, 0x8D, 0xFC, 0xAE, 0x47, 0x3E, 0x0C, 0x56, 0xF9, 0x48,
-0x04, 0x56, 0xFD, 0x78, 0x01, 0x5C, 0xFF, 0x2A, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x2B, 0x00, 0x58, 0xFF, 0x83, 0x01, 0x3C, 0xFD, 0x7E,
-0x04, 0xE6, 0xF8, 0x72, 0x0D, 0x52, 0x47, 0xBE, 0xFB, 0x7A, 0x00,
-0x90, 0x00, 0x43, 0xFF, 0x8F, 0x00, 0xB7, 0xFF, 0x11, 0x00, 0xFD,
-0xFF, 0x36, 0x00, 0x37, 0xFF, 0xE6, 0x01, 0x36, 0xFC, 0xF1, 0x06,
-0xF5, 0xF2, 0xA7, 0x22, 0xFF, 0x3B, 0xE4, 0xF2, 0x96, 0x05, 0x81,
-0xFD, 0xFD, 0x00, 0xB5, 0xFF, 0x0B, 0x00, 0x01, 0x00, 0xFE, 0xFF,
-0x1C, 0x00, 0x86, 0xFF, 0x59, 0x01, 0xEC, 0xFC, 0x6F, 0x06, 0xDC,
-0xF1, 0x04, 0x37, 0xF3, 0x28, 0xFC, 0xF1, 0x28, 0x07, 0x37, 0xFC,
-0xD8, 0x01, 0x41, 0xFF, 0x33, 0x00, 0xFD, 0xFF, 0x0B, 0x00, 0xD3,
-0xFF, 0x49, 0x00, 0xD4, 0xFF, 0x88, 0xFF, 0x49, 0x02, 0x4B, 0xF8,
-0x0D, 0x45, 0x68, 0x13, 0xDF, 0xF6, 0x6C, 0x05, 0xCC, 0xFC, 0xB4,
-0x01, 0x45, 0xFF, 0x31, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x23, 0x00,
-0x74, 0xFF, 0x3A, 0x01, 0xDD, 0xFD, 0x39, 0x03, 0x7B, 0xFB, 0xC1,
-0x06, 0xC7, 0x48, 0xCF, 0x00, 0x0D, 0xFE, 0xE3, 0x01, 0x8E, 0xFE,
-0xE7, 0x00, 0x95, 0xFF, 0x1A, 0x00, 0xFE, 0xFF, 0x36, 0x00, 0x38,
-0xFF, 0xDA, 0x01, 0x69, 0xFC, 0x57, 0x06, 0xAF, 0xF4, 0xF5, 0x1A,
-0x1D, 0x41, 0x11, 0xF5, 0x25, 0x04, 0x6C, 0xFE, 0x74, 0x00, 0xF9,
-0xFF, 0xF1, 0xFF, 0x05, 0x00, 0xFD, 0xFF, 0x2A, 0x00, 0x5C, 0xFF,
-0xAA, 0x01, 0x71, 0xFC, 0x07, 0x07, 0x7E, 0xF1, 0x44, 0x30, 0x44,
-0x30, 0x7E, 0xF1, 0x07, 0x07, 0x71, 0xFC, 0xAA, 0x01, 0x5C, 0xFF,
-0x2A, 0x00, 0xFD, 0xFF, 0x05, 0x00, 0xF1, 0xFF, 0xF9, 0xFF, 0x74,
-0x00, 0x6C, 0xFE, 0x25, 0x04, 0x11, 0xF5, 0x1D, 0x41, 0xF5, 0x1A,
-0xAF, 0xF4, 0x57, 0x06, 0x69, 0xFC, 0xDA, 0x01, 0x38, 0xFF, 0x36,
-0x00, 0xFE, 0xFF, 0x1A, 0x00, 0x95, 0xFF, 0xE7, 0x00, 0x8E, 0xFE,
-0xE3, 0x01, 0x0D, 0xFE, 0xCF, 0x00, 0xC7, 0x48, 0xC1, 0x06, 0x7B,
-0xFB, 0x39, 0x03, 0xDD, 0xFD, 0x3A, 0x01, 0x74, 0xFF, 0x23, 0x00,
-0x00, 0x00, 0xFF, 0xFF, 0x31, 0x00, 0x45, 0xFF, 0xB4, 0x01, 0xCC,
-0xFC, 0x6C, 0x05, 0xDF, 0xF6, 0x68, 0x13, 0x0D, 0x45, 0x4B, 0xF8,
-0x49, 0x02, 0x88, 0xFF, 0xD4, 0xFF, 0x49, 0x00, 0xD3, 0xFF, 0x0B,
-0x00, 0xFD, 0xFF, 0x33, 0x00, 0x41, 0xFF, 0xD8, 0x01, 0x37, 0xFC,
-0x28, 0x07, 0xFC, 0xF1, 0xF3, 0x28, 0x04, 0x37, 0xDC, 0xF1, 0x6F,
-0x06, 0xEC, 0xFC, 0x59, 0x01, 0x86, 0xFF, 0x1C, 0x00, 0xFE, 0xFF,
-0x01, 0x00, 0x0B, 0x00, 0xB5, 0xFF, 0xFD, 0x00, 0x81, 0xFD, 0x96,
-0x05, 0xE4, 0xF2, 0xFF, 0x3B, 0xA7, 0x22, 0xF5, 0xF2, 0xF1, 0x06,
-0x36, 0xFC, 0xE6, 0x01, 0x37, 0xFF, 0x36, 0x00, 0xFD, 0xFF, 0x11,
-0x00, 0xB7, 0xFF, 0x8F, 0x00, 0x43, 0xFF, 0x90, 0x00, 0x7A, 0x00,
-0xBE, 0xFB, 0x52, 0x47, 0x72, 0x0D, 0xE6, 0xF8, 0x7E, 0x04, 0x3C,
-0xFD, 0x83, 0x01, 0x58, 0xFF, 0x2B, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x2A, 0x00, 0x5C, 0xFF, 0x78, 0x01, 0x56, 0xFD, 0x48, 0x04, 0x56,
-0xF9, 0x3E, 0x0C, 0xAE, 0x47, 0x8D, 0xFC, 0x13, 0x00, 0xC9, 0x00,
-0x24, 0xFF, 0x9F, 0x00, 0xB1, 0xFF, 0x13, 0x00, 0xFD, 0xFF, 0x36,
-0x00, 0x36, 0xFF, 0xE6, 0x01, 0x3B, 0xFC, 0xDD, 0x06, 0x37, 0xF3,
-0x52, 0x21, 0xF6, 0x3C, 0x31, 0xF3, 0x5F, 0x05, 0xA6, 0xFD, 0xE8,
-0x00, 0xC0, 0xFF, 0x07, 0x00, 0x01, 0x00, 0xFE, 0xFF, 0x1F, 0x00,
-0x7E, 0xFF, 0x69, 0x01, 0xD2, 0xFC, 0x92, 0x06, 0xBB, 0xF1, 0xE6,
-0x35, 0x3F, 0x2A, 0xD8, 0xF1, 0x2A, 0x07, 0x3C, 0xFC, 0xD3, 0x01,
-0x45, 0xFF, 0x32, 0x00, 0xFD, 0xFF, 0x0A, 0x00, 0xD8, 0xFF, 0x3A,
-0x00, 0xF1, 0xFF, 0x54, 0xFF, 0xA2, 0x02, 0xA9, 0xF7, 0x77, 0x44,
-0xB1, 0x14, 0x77, 0xF6, 0x9A, 0x05, 0xB8, 0xFC, 0xBC, 0x01, 0x42,
-0xFF, 0x32, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x21, 0x00, 0x7A, 0xFF,
-0x2C, 0x01, 0xFB, 0xFD, 0xFE, 0x02, 0xEE, 0xFB, 0xAB, 0x05, 0xE1,
-0x48, 0xC7, 0x01, 0x9D, 0xFD, 0x1E, 0x02, 0x6F, 0xFE, 0xF5, 0x00,
-0x8F, 0xFF, 0x1B, 0x00, 0xFE, 0xFF, 0x35, 0x00, 0x3A, 0xFF, 0xD6,
-0x01, 0x77, 0xFC, 0x33, 0x06, 0x09, 0xF5, 0xA1, 0x19, 0xE1, 0x41,
-0x8D, 0xF5, 0xDA, 0x03, 0x9A, 0xFE, 0x5A, 0x00, 0x06, 0x00, 0xEC,
-0xFF, 0x06, 0x00, 0xFD, 0xFF, 0x2C, 0x00, 0x56, 0xFF, 0xB4, 0x01,
-0x62, 0xFC, 0x15, 0x07, 0x84, 0xF1, 0x09, 0x2F, 0x7B, 0x31, 0x7D,
-0xF1, 0xF5, 0x06, 0x82, 0xFC, 0x9E, 0x01, 0x62, 0xFF, 0x28, 0x00,
-0xFD, 0xFF, 0x04, 0x00, 0xF6, 0xFF, 0xED, 0xFF, 0x8E, 0x00, 0x3F,
-0xFE, 0x6D, 0x04, 0x9E, 0xF4, 0x4E, 0x40, 0x49, 0x1C, 0x5A, 0xF4,
-0x78, 0x06, 0x5C, 0xFC, 0xDF, 0x01, 0x37, 0xFF, 0x36, 0x00, 0xFE,
-0xFF, 0x18, 0x00, 0x9B, 0xFF, 0xD8, 0x00, 0xAD, 0xFE, 0xA7, 0x01,
-0x7D, 0xFE, 0xDD, 0xFF, 0xA1, 0x48, 0xDD, 0x07, 0x07, 0xFB, 0x73,
-0x03, 0xC0, 0xFD, 0x48, 0x01, 0x6F, 0xFF, 0x24, 0x00, 0x00, 0x00,
-0xFF, 0xFF, 0x30, 0x00, 0x49, 0xFF, 0xAB, 0x01, 0xE2, 0xFC, 0x3D,
-0x05, 0x48, 0xF7, 0x22, 0x12, 0x9B, 0x45, 0xF5, 0xF8, 0xED, 0x01,
-0xBE, 0xFF, 0xB6, 0xFF, 0x57, 0x00, 0xCD, 0xFF, 0x0C, 0x00, 0xFD,
-0xFF, 0x34, 0x00, 0x3E, 0xFF, 0xDD, 0x01, 0x33, 0xFC, 0x23, 0x07,
-0x26, 0xF2, 0xA6, 0x27, 0x1D, 0x38, 0x05, 0xF2, 0x49, 0x06, 0x08,
-0xFD, 0x47, 0x01, 0x8F, 0xFF, 0x18, 0x00, 0xFF, 0xFF, 0x00, 0x00,
-0x0E, 0x00, 0xAA, 0xFF, 0x12, 0x01, 0x5F, 0xFD, 0xCB, 0x05, 0x9E,
-0xF2, 0x03, 0x3B, 0xFC, 0x23, 0xB7, 0xF2, 0x03, 0x07, 0x33, 0xFC,
-0xE5, 0x01, 0x39, 0xFF, 0x36, 0x00, 0xFD, 0xFF, 0x10, 0x00, 0xBD,
-0xFF, 0x80, 0x00, 0x62, 0xFF, 0x57, 0x00, 0xDF, 0x00, 0xF7, 0xFA,
-0xED, 0x46, 0xAA, 0x0E, 0x76, 0xF8, 0xB2, 0x04, 0x23, 0xFD, 0x8F,
-0x01, 0x53, 0xFF, 0x2D, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x28, 0x00,
-0x61, 0xFF, 0x6C, 0x01, 0x71, 0xFD, 0x11, 0x04, 0xC8, 0xF9, 0x0E,
-0x0B, 0xFD, 0x47, 0x63, 0xFD, 0xAA, 0xFF, 0x03, 0x01, 0x05, 0xFF,
-0xAE, 0x00, 0xAC, 0xFF, 0x14, 0x00, 0xFD, 0xFF, 0x36, 0x00, 0x36,
-0xFF, 0xE5, 0x01, 0x41, 0xFC, 0xC6, 0x06, 0x7F, 0xF3, 0xFD, 0x1F,
-0xE4, 0x3D, 0x87, 0xF3, 0x24, 0x05, 0xCC, 0xFD, 0xD1, 0x00, 0xCB,
-0xFF, 0x02, 0x00, 0x02, 0x00, 0xFE, 0xFF, 0x21, 0x00, 0x76, 0xFF,
-0x79, 0x01, 0xBA, 0xFC, 0xB1, 0x06, 0xA0, 0xF1, 0xC3, 0x34, 0x89,
-0x2B, 0xB9, 0xF1, 0x29, 0x07, 0x44, 0xFC, 0xCC, 0x01, 0x49, 0xFF,
-0x31, 0x00, 0xFD, 0xFF, 0x09, 0x00, 0xDE, 0xFF, 0x2C, 0x00, 0x0D,
-0x00, 0x21, 0xFF, 0xF9, 0x02, 0x0F, 0xF7, 0xD4, 0x43, 0xFD, 0x15,
-0x13, 0xF6, 0xC5, 0x05, 0xA5, 0xFC, 0xC4, 0x01, 0x40, 0xFF, 0x33,
-0x00, 0xFF, 0xFF, 0x00, 0x00, 0x20, 0x00, 0x7F, 0xFF, 0x1E, 0x01,
-0x19, 0xFE, 0xC3, 0x02, 0x61, 0xFC, 0x9B, 0x04, 0xF2, 0x48, 0xC6,
-0x02, 0x2C, 0xFD, 0x5A, 0x02, 0x50, 0xFE, 0x04, 0x01, 0x8A, 0xFF,
-0x1D, 0x00, 0xFE, 0xFF, 0x34, 0x00, 0x3B, 0xFF, 0xD0, 0x01, 0x86,
-0xFC, 0x0D, 0x06, 0x66, 0xF5, 0x50, 0x18, 0x9E, 0x42, 0x11, 0xF6,
-0x8C, 0x03, 0xC9, 0xFE, 0x3F, 0x00, 0x14, 0x00, 0xE7, 0xFF, 0x07,
-0x00, 0xFD, 0xFF, 0x2E, 0x00, 0x51, 0xFF, 0xBE, 0x01, 0x56, 0xFC,
-0x1F, 0x07, 0x92, 0xF1, 0xCA, 0x2D, 0xAF, 0x32, 0x84, 0xF1, 0xE0,
-0x06, 0x94, 0xFC, 0x91, 0x01, 0x69, 0xFF, 0x26, 0x00, 0xFD, 0xFF,
-0x03, 0x00, 0xFA, 0xFF, 0xE0, 0xFF, 0xA7, 0x00, 0x15, 0xFE, 0xB2,
-0x04, 0x32, 0xF4, 0x77, 0x3F, 0x9E, 0x1D, 0x07, 0xF4, 0x96, 0x06,
-0x51, 0xFC, 0xE2, 0x01, 0x36, 0xFF, 0x36, 0x00, 0xFE, 0xFF, 0x17,
-0x00, 0xA1, 0xFF, 0xC9, 0x00, 0xCD, 0xFE, 0x6C, 0x01, 0xEA, 0xFE,
-0xF3, 0xFE, 0x70, 0x48, 0xFF, 0x08, 0x94, 0xFA, 0xAD, 0x03, 0xA3,
-0xFD, 0x55, 0x01, 0x6A, 0xFF, 0x26, 0x00, 0x00, 0x00, 0xFF, 0xFF,
-0x2F, 0x00, 0x4C, 0xFF, 0xA1, 0x01, 0xF8, 0xFC, 0x0D, 0x05, 0xB3,
-0xF7, 0xDF, 0x10, 0x1D, 0x46, 0xA7, 0xF9, 0x8E, 0x01, 0xF4, 0xFF,
-0x98, 0xFF, 0x66, 0x00, 0xC7, 0xFF, 0x0E, 0x00, 0xFD, 0xFF, 0x35,
-0x00, 0x3C, 0xFF, 0xE1, 0x01, 0x31, 0xFC, 0x1A, 0x07, 0x56, 0xF2,
-0x55, 0x26, 0x2E, 0x39, 0x35, 0xF2, 0x1E, 0x06, 0x25, 0xFD, 0x35,
-0x01, 0x98, 0xFF, 0x15, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x12, 0x00,
-0xA0, 0xFF, 0x26, 0x01, 0x3E, 0xFD, 0xFB, 0x05, 0x60, 0xF2, 0xFD,
-0x39, 0x4E, 0x25, 0x7F, 0xF2, 0x11, 0x07, 0x31, 0xFC, 0xE3, 0x01,
-0x3A, 0xFF, 0x35, 0x00, 0xFD, 0xFF, 0x0F, 0x00, 0xC3, 0xFF, 0x71,
-0x00, 0x81, 0xFF, 0x1F, 0x00, 0x42, 0x01, 0x37, 0xFA, 0x7C, 0x46,
-0xE7, 0x0F, 0x08, 0xF8, 0xE6, 0x04, 0x0B, 0xFD, 0x99, 0x01, 0x4F,
-0xFF, 0x2E, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x27, 0x00, 0x66, 0xFF,
-0x5F, 0x01, 0x8D, 0xFD, 0xD9, 0x03, 0x3B, 0xFA, 0xE4, 0x09, 0x41,
-0x48, 0x41, 0xFE, 0x3F, 0xFF, 0x3E, 0x01, 0xE5, 0xFE, 0xBD, 0x00,
-0xA6, 0xFF, 0x16, 0x00, 0xFE, 0xFF, 0x36, 0x00, 0x36, 0xFF, 0xE4,
-0x01, 0x4A, 0xFC, 0xAC, 0x06, 0xCA, 0xF3, 0xA7, 0x1E, 0xCA, 0x3E,
-0xE4, 0xF3, 0xE5, 0x04, 0xF4, 0xFD, 0xBA, 0x00, 0xD7, 0xFF, 0xFE,
-0xFF, 0x03, 0x00, 0xFD, 0xFF, 0x24, 0x00, 0x6E, 0xFF, 0x87, 0x01,
-0xA4, 0xFC, 0xCD, 0x06, 0x8E, 0xF1, 0x99, 0x33, 0xCE, 0x2C, 0xA1,
-0xF1, 0x25, 0x07, 0x4D, 0xFC, 0xC4, 0x01, 0x4D, 0xFF, 0x2F, 0x00,
-0xFD, 0xFF, 0x08, 0x00, 0xE3, 0xFF, 0x1E, 0x00, 0x2A, 0x00, 0xEF,
-0xFE, 0x4D, 0x03, 0x7D, 0xF6, 0x2A, 0x43, 0x4B, 0x17, 0xB0, 0xF5,
-0xEF, 0x05, 0x93, 0xFC, 0xCB, 0x01, 0x3D, 0xFF, 0x34, 0x00, 0xFE,
-0xFF, 0x1E, 0x00, 0x85, 0xFF, 0x10, 0x01, 0x38, 0xFE, 0x88, 0x02,
-0xD3, 0xFC, 0x91, 0x03, 0xF7, 0x48, 0xCB, 0x03, 0xBA, 0xFC, 0x95,
-0x02, 0x31, 0xFE, 0x13, 0x01, 0x84, 0xFF, 0x1E, 0x00, 0x00, 0x00,
-0xFE, 0xFF, 0x34, 0x00, 0x3E, 0xFF, 0xC9, 0x01, 0x97, 0xFC, 0xE6,
-0x05, 0xC6, 0xF5, 0x00, 0x17, 0x50, 0x43, 0x9D, 0xF6, 0x3A, 0x03,
-0xFA, 0xFE, 0x23, 0x00, 0x21, 0x00, 0xE2, 0xFF, 0x08, 0x00, 0xFD,
-0xFF, 0x30, 0x00, 0x4C, 0xFF, 0xC6, 0x01, 0x4B, 0xFC, 0x26, 0x07,
-0xA5, 0xF1, 0x87, 0x2C, 0xDC, 0x33, 0x91, 0xF1, 0xC7, 0x06, 0xA9,
-0xFC, 0x84, 0x01, 0x70, 0xFF, 0x23, 0x00, 0xFE, 0xFF, 0x03, 0x00,
-0xFF, 0xFF, 0xD4, 0xFF, 0xBF, 0x00, 0xEB, 0xFD, 0xF3, 0x04, 0xCF,
-0xF3, 0x98, 0x3E, 0xF3, 0x1E, 0xB9, 0xF3, 0xB2, 0x06, 0x48, 0xFC,
-0xE4, 0x01, 0x36, 0xFF, 0x36, 0x00, 0xFE, 0xFF, 0x15, 0x00, 0xA7,
-0xFF, 0xB9, 0x00, 0xEC, 0xFE, 0x31, 0x01, 0x57, 0xFF, 0x0F, 0xFE,
-0x33, 0x48, 0x25, 0x0A, 0x21, 0xFA, 0xE5, 0x03, 0x87, 0xFD, 0x62,
-0x01, 0x65, 0xFF, 0x27, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x2E, 0x00,
-0x50, 0xFF, 0x97, 0x01, 0x10, 0xFD, 0xDA, 0x04, 0x20, 0xF8, 0xA0,
-0x0F, 0x97, 0x46, 0x61, 0xFA, 0x2D, 0x01, 0x2B, 0x00, 0x7A, 0xFF,
-0x75, 0x00, 0xC2, 0xFF, 0x0F, 0x00, 0xFD, 0xFF, 0x36, 0x00, 0x3A,
-0xFF, 0xE4, 0x01, 0x32, 0xFC, 0x0E, 0x07, 0x8B, 0xF2, 0x03, 0x25,
-0x38, 0x3A, 0x6D, 0xF2, 0xF1, 0x05, 0x45, 0xFD, 0x22, 0x01, 0xA2,
-0xFF, 0x11, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x16, 0x00, 0x96, 0xFF,
-0x39, 0x01, 0x1F, 0xFD, 0x28, 0x06, 0x2A, 0xF2, 0xF2, 0x38, 0xA0,
-0x26, 0x4B, 0xF2, 0x1C, 0x07, 0x32, 0xFC, 0xE0, 0x01, 0x3C, 0xFF,
-0x35, 0x00, 0xFD, 0xFF, 0x0D, 0x00, 0xC9, 0xFF, 0x63, 0x00, 0x9F,
-0xFF, 0xE8, 0xFF, 0xA3, 0x01, 0x7F, 0xF9, 0x02, 0x46, 0x27, 0x11,
-0x9B, 0xF7, 0x18, 0x05, 0xF3, 0xFC, 0xA3, 0x01, 0x4C, 0xFF, 0x2F,
-0x00, 0xFF, 0xFF, 0x00, 0x00, 0x25, 0x00, 0x6B, 0xFF, 0x52, 0x01,
-0xA9, 0xFD, 0xA0, 0x03, 0xAE, 0xFA, 0xBE, 0x08, 0x7C, 0x48, 0x26,
-0xFF, 0xD2, 0xFE, 0x79, 0x01, 0xC6, 0xFE, 0xCC, 0x00, 0xA0, 0xFF,
-0x17, 0x00, 0xFE, 0xFF, 0x36, 0x00, 0x36, 0xFF, 0xE1, 0x01, 0x53,
-0xFC, 0x90, 0x06, 0x19, 0xF4, 0x52, 0x1D, 0xA8, 0x3F, 0x49, 0xF4,
-0xA3, 0x04, 0x1E, 0xFE, 0xA1, 0x00, 0xE3, 0xFF, 0xF9, 0xFF, 0x04,
-0x00, 0xFD, 0xFF, 0x26, 0x00, 0x67, 0xFF, 0x94, 0x01, 0x90, 0xFC,
-0xE5, 0x06, 0x81, 0xF1, 0x6B, 0x32, 0x11, 0x2E, 0x8E, 0xF1, 0x1D,
-0x07, 0x58, 0xFC, 0xBC, 0x01, 0x52, 0xFF, 0x2E, 0x00, 0xFD, 0xFF,
-0x07, 0x00, 0xE8, 0xFF, 0x11, 0x00, 0x45, 0x00, 0xBF, 0xFE, 0x9D,
-0x03, 0xF3, 0xF5, 0x75, 0x42, 0x9B, 0x18, 0x51, 0xF5, 0x16, 0x06,
-0x83, 0xFC, 0xD1, 0x01, 0x3B, 0xFF, 0x34, 0x00, 0xFE, 0xFF, 0x1D,
-0x00, 0x8B, 0xFF, 0x01, 0x01, 0x56, 0xFE, 0x4D, 0x02, 0x45, 0xFD,
-0x8D, 0x02, 0xF0, 0x48, 0xD7, 0x04, 0x47, 0xFC, 0xD1, 0x02, 0x12,
-0xFE, 0x21, 0x01, 0x7E, 0xFF, 0x20, 0x00, 0x00, 0x00, 0xFF, 0xFF,
-0x33, 0x00, 0x40, 0xFF, 0xC2, 0x01, 0xA9, 0xFC, 0xBC, 0x05, 0x29,
-0xF6, 0xB3, 0x15, 0xFA, 0x43, 0x31, 0xF7, 0xE6, 0x02, 0x2C, 0xFF,
-0x07, 0x00, 0x2F, 0x00, 0xDC, 0xFF, 0x09, 0x00, 0xFD, 0xFF, 0x31,
-0x00, 0x48, 0xFF, 0xCE, 0x01, 0x42, 0xFC, 0x2A, 0x07, 0xBF, 0xF1,
-0x40, 0x2B, 0x05, 0x35, 0xA6, 0xF1, 0xAB, 0x06, 0xBF, 0xFC, 0x75,
-0x01, 0x77, 0xFF, 0x21, 0x00, 0xFE, 0xFF, 0x02, 0x00, 0x03, 0x00,
-0xC8, 0xFF, 0xD6, 0x00, 0xC4, 0xFD, 0x31, 0x05, 0x73, 0xF3, 0xB0,
-0x3D, 0x49, 0x20, 0x6E, 0xF3, 0xCB, 0x06, 0x40, 0xFC, 0xE6, 0x01,
-0x36, 0xFF, 0x36, 0x00, 0xFD, 0xFF, 0x14, 0x00, 0xAD, 0xFF, 0xAA,
-0x00, 0x0C, 0xFF, 0xF7, 0x00, 0xC1, 0xFF, 0x33, 0xFD, 0xEC, 0x47,
-0x51, 0x0B, 0xAF, 0xF9, 0x1D, 0x04, 0x6B, 0xFD, 0x6E, 0x01, 0x60,
-0xFF, 0x29, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x2C, 0x00, 0x54, 0xFF,
-0x8C, 0x01, 0x29, 0xFD, 0xA7, 0x04, 0x8F, 0xF8, 0x64, 0x0E, 0x02,
-0x47, 0x22, 0xFB, 0xC9, 0x00, 0x64, 0x00, 0x5B, 0xFF, 0x84, 0x00,
-0xBC, 0xFF, 0x10, 0x00, 0xFD, 0xFF, 0x36, 0x00, 0x38, 0xFF, 0xE5,
-0x01, 0x33, 0xFC, 0xFF, 0x06, 0xC4, 0xF2, 0xB0, 0x23, 0x3B, 0x3B,
-0xAD, 0xF2, 0xBF, 0x05, 0x66, 0xFD, 0x0E, 0x01, 0xAC, 0xFF, 0x0E,
-0x00, 0x00, 0x00, 0xFF, 0xFF, 0x19, 0x00, 0x8D, 0xFF, 0x4B, 0x01,
-0x01, 0xFD, 0x51, 0x06, 0xFB, 0xF1, 0xDF, 0x37, 0xF0, 0x27, 0x1C,
-0xF2, 0x24, 0x07, 0x34, 0xFC, 0xDC, 0x01, 0x3F, 0xFF, 0x34, 0x00,
-0xFD, 0xFF, 0x0C, 0x00, 0xCE, 0xFF, 0x54, 0x00, 0xBD, 0xFF, 0xB2,
-0xFF, 0x01, 0x02, 0xCF, 0xF8, 0x7D, 0x45, 0x6B, 0x12, 0x30, 0xF7,
-0x48, 0x05, 0xDD, 0xFC, 0xAD, 0x01, 0x48, 0xFF, 0x30, 0x00, 0xFF,
-0xFF, 0x00, 0x00, 0x24, 0x00, 0x70, 0xFF, 0x45, 0x01, 0xC6, 0xFD,
-0x66, 0x03, 0x21, 0xFB, 0x9E, 0x07, 0xAA, 0x48, 0x12, 0x00, 0x64,
-0xFE, 0xB4, 0x01, 0xA6, 0xFE, 0xDB, 0x00, 0x9A, 0xFF, 0x19, 0x00,
-0xFE, 0xFF, 0x36, 0x00, 0x37, 0xFF, 0xDE, 0x01, 0x5F, 0xFC, 0x70,
-0x06, 0x6C, 0xF4, 0xFD, 0x1B, 0x7D, 0x40, 0xB7, 0xF4, 0x5D, 0x04,
-0x49, 0xFE, 0x88, 0x00, 0xEF, 0xFF, 0xF5, 0xFF, 0x04, 0x00, 0xFD,
-0xFF, 0x29, 0x00, 0x61, 0xFF, 0xA1, 0x01, 0x7E, 0xFC, 0xF9, 0x06,
-0x7C, 0xF1, 0x38, 0x31, 0x50, 0x2F, 0x82, 0xF1, 0x12, 0x07, 0x65,
-0xFC, 0xB2, 0x01, 0x57, 0xFF, 0x2C, 0x00, 0xFD, 0xFF, 0x06, 0x00,
-0xED, 0xFF, 0x04, 0x00, 0x60, 0x00, 0x90, 0xFE, 0xEB, 0x03, 0x71,
-0xF5, 0xB7, 0x41, 0xED, 0x19, 0xF5, 0xF4, 0x3B, 0x06, 0x73, 0xFC,
-0xD7, 0x01, 0x39, 0xFF, 0x35, 0x00, 0xFE, 0xFF, 0x1B, 0x00, 0x91,
-0xFF, 0xF2, 0x00, 0x76, 0xFE, 0x11, 0x02, 0xB6, 0xFD, 0x8F, 0x01,
-0xDE, 0x48, 0xE9, 0x05, 0xD4, 0xFB, 0x0C, 0x03, 0xF4, 0xFD, 0x2F,
-0x01, 0x79, 0xFF, 0x22, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x32, 0x00,
-0x43, 0xFF, 0xBA, 0x01, 0xBC, 0xFC, 0x90, 0x05, 0x8E, 0xF6, 0x68,
-0x14, 0x99, 0x44, 0xCD, 0xF7, 0x8F, 0x02, 0x60, 0xFF, 0xEA, 0xFF,
-0x3E, 0x00, 0xD7, 0xFF, 0x0A, 0x00, 0xFD, 0xFF, 0x32, 0x00, 0x44,
-0xFF, 0xD4, 0x01, 0x3B, 0xFC, 0x2A, 0x07, 0xDF, 0xF1, 0xF6, 0x29,
-0x27, 0x36, 0xC1, 0xF1, 0x8B, 0x06, 0xD8, 0xFC, 0x66, 0x01, 0x80,
-0xFF, 0x1E, 0x00, 0xFE, 0xFF, 0x01, 0x00, 0x07, 0x00, 0xBD, 0xFF,
-0xED, 0x00, 0x9E, 0xFD, 0x6C, 0x05, 0x1F, 0xF3, 0xC0, 0x3C, 0x9E,
-0x21, 0x28, 0xF3, 0xE2, 0x06, 0x3A, 0xFC, 0xE6, 0x01, 0x37, 0xFF,
-0x36, 0x00, 0xFD, 0xFF, 0x12, 0x00, 0xB3, 0xFF, 0x9B, 0x00, 0x2B,
-0xFF, 0xBD, 0x00, 0x2A, 0x00, 0x5E, 0xFC, 0x9A, 0x47, 0x82, 0x0C,
-0x3D, 0xF9, 0x54, 0x04, 0x50, 0xFD, 0x7A, 0x01, 0x5B, 0xFF, 0x2A,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x2B, 0x00, 0x59, 0xFF, 0x81, 0x01,
-0x42, 0xFD, 0x72, 0x04, 0xFF, 0xF8, 0x2D, 0x0D, 0x69, 0x47, 0xEB,
-0xFB, 0x63, 0x00, 0x9D, 0x00, 0x3C, 0xFF, 0x93, 0x00, 0xB6, 0xFF,
-0x12, 0x00, 0xFD, 0xFF, 0x36, 0x00, 0x37, 0xFF, 0xE6, 0x01, 0x37,
-0xFC, 0xED, 0x06, 0x03, 0xF3, 0x5B, 0x22, 0x37, 0x3C, 0xF4, 0xF2,
-0x8A, 0x05, 0x89, 0xFD, 0xF9, 0x00, 0xB7, 0xFF, 0x0A, 0x00, 0x01,
-0x00, 0xFE, 0xFF, 0x1C, 0x00, 0x84, 0xFF, 0x5C, 0x01, 0xE6, 0xFC,
-0x77, 0x06, 0xD4, 0xF1, 0xC6, 0x36, 0x3E, 0x29, 0xF3, 0xF1, 0x29,
-0x07, 0x38, 0xFC, 0xD7, 0x01, 0x42, 0xFF, 0x33, 0x00, 0xFD, 0xFF,
-0x0B, 0x00, 0xD4, 0xFF, 0x46, 0x00, 0xDA, 0xFF, 0x7D, 0xFF, 0x5D,
-0x02, 0x26, 0xF8, 0xED, 0x44, 0xB1, 0x13, 0xC7, 0xF6, 0x77, 0x05,
-0xC8, 0xFC, 0xB6, 0x01, 0x45, 0xFF, 0x31, 0x00, 0xFF, 0xFF, 0x00,
-0x00, 0x22, 0x00, 0x76, 0xFF, 0x37, 0x01, 0xE4, 0xFD, 0x2C, 0x03,
-0x94, 0xFB, 0x83, 0x06, 0xCE, 0x48, 0x05, 0x01, 0xF5, 0xFD, 0xF0,
-0x01, 0x87, 0xFE, 0xEA, 0x00, 0x94, 0xFF, 0x1A, 0x00, 0xFE, 0xFF,
-0x35, 0x00, 0x38, 0xFF, 0xD9, 0x01, 0x6C, 0xFC, 0x4F, 0x06, 0xC3,
-0xF4, 0xA9, 0x1A, 0x49, 0x41, 0x2C, 0xF5, 0x15, 0x04, 0x76, 0xFE,
-0x6E, 0x00, 0xFC, 0xFF, 0xF0, 0xFF, 0x05, 0x00, 0xFD, 0xFF, 0x2B,
-0x00, 0x5A, 0xFF, 0xAC, 0x01, 0x6E, 0xFC, 0x0A, 0x07, 0x7E, 0xF1,
-0xFF, 0x2F, 0x8A, 0x30, 0x7D, 0xF1, 0x03, 0x07, 0x75, 0xFC, 0xA7,
-0x01, 0x5D, 0xFF, 0x2A, 0x00, 0xFD, 0xFF, 0x05, 0x00, 0xF2, 0xFF,
-0xF7, 0xFF, 0x7A, 0x00, 0x62, 0xFE, 0x35, 0x04, 0xF7, 0xF4, 0xEF,
-0x40, 0x40, 0x1B, 0x9C, 0xF4, 0x5E, 0x06, 0x66, 0xFC, 0xDB, 0x01,
-0x38, 0xFF, 0x36, 0x00, 0xFE, 0xFF, 0x1A, 0x00, 0x96, 0xFF, 0xE3,
-0x00, 0x95, 0xFE, 0xD5, 0x01, 0x26, 0xFE, 0x98, 0x00, 0xBF, 0x48,
-0x00, 0x07, 0x61, 0xFB, 0x46, 0x03, 0xD6, 0xFD, 0x3D, 0x01, 0x73,
-0xFF, 0x23, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x31, 0x00, 0x46, 0xFF,
-0xB2, 0x01, 0xD1, 0xFC, 0x62, 0x05, 0xF6, 0xF6, 0x20, 0x13, 0x2E,
-0x45, 0x70, 0xF8, 0x34, 0x02, 0x94, 0xFF, 0xCD, 0xFF, 0x4C, 0x00,
-0xD2, 0xFF, 0x0B, 0x00, 0xFD, 0xFF, 0x33, 0x00, 0x41, 0xFF, 0xDA,
-0x01, 0x36, 0xFC, 0x27, 0x07, 0x05, 0xF2, 0xAA, 0x28, 0x44, 0x37,
-0xE4, 0xF1, 0x67, 0x06, 0xF2, 0xFC, 0x55, 0x01, 0x88, 0xFF, 0x1B,
-0x00, 0xFE, 0xFF, 0x01, 0x00, 0x0B, 0x00, 0xB2, 0xFF, 0x02, 0x01,
-0x7A, 0xFD, 0xA2, 0x05, 0xD4, 0xF2, 0xC7, 0x3B, 0xF2, 0x22, 0xE7,
-0xF2, 0xF5, 0x06, 0x35, 0xFC, 0xE6, 0x01, 0x38, 0xFF, 0x36, 0x00,
-0xFD, 0xFF, 0x11, 0x00, 0xB9, 0xFF, 0x8C, 0x00, 0x4A, 0xFF, 0x83,
-0x00, 0x91, 0x00, 0x91, 0xFB, 0x3D, 0x47, 0xB7, 0x0D, 0xCD, 0xF8,
-0x89, 0x04, 0x36, 0xFD, 0x86, 0x01, 0x57, 0xFF, 0x2B, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x2A, 0x00, 0x5D, 0xFF, 0x75, 0x01, 0x5C, 0xFD,
-0x3C, 0x04, 0x70, 0xF9, 0xFA, 0x0B, 0xC0, 0x47, 0xBC, 0xFC, 0xFC,
-0xFF, 0xD6, 0x00, 0x1D, 0xFF, 0xA2, 0x00, 0xB0, 0xFF, 0x13, 0x00,
-0xFD, 0xFF, 0x36, 0x00, 0x36, 0xFF, 0xE6, 0x01, 0x3C, 0xFC, 0xD8,
-0x06, 0x47, 0xF3, 0x06, 0x21, 0x2A, 0x3D, 0x44, 0xF3, 0x52, 0x05,
-0xAE, 0xFD, 0xE3, 0x00, 0xC2, 0xFF, 0x06, 0x00, 0x01, 0x00, 0xFE,
-0xFF, 0x1F, 0x00, 0x7C, 0xFF, 0x6D, 0x01, 0xCD, 0xFC, 0x99, 0x06,
-0xB4, 0xF1, 0xA6, 0x35, 0x89, 0x2A, 0xD0, 0xF1, 0x2B, 0x07, 0x3E,
-0xFC, 0xD1, 0x01, 0x46, 0xFF, 0x32, 0x00, 0xFD, 0xFF, 0x0A, 0x00,
-0xD9, 0xFF, 0x37, 0x00, 0xF7, 0xFF, 0x49, 0xFF, 0xB6, 0x02, 0x86,
-0xF7, 0x53, 0x44, 0xFB, 0x14, 0x61, 0xF6, 0xA4, 0x05, 0xB4, 0xFC,
-0xBE, 0x01, 0x42, 0xFF, 0x32, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x21,
-0x00, 0x7B, 0xFF, 0x29, 0x01, 0x01, 0xFE, 0xF1, 0x02, 0x07, 0xFC,
-0x6E, 0x05, 0xE6, 0x48, 0xFF, 0x01, 0x84, 0xFD, 0x2C, 0x02, 0x68,
-0xFE, 0xF9, 0x00, 0x8E, 0xFF, 0x1C, 0x00, 0xFE, 0xFF, 0x35, 0x00,
-0x3A, 0xFF, 0xD4, 0x01, 0x7A, 0xFC, 0x2B, 0x06, 0x1E, 0xF5, 0x56,
-0x19, 0x0C, 0x42, 0xAA, 0xF5, 0xC9, 0x03, 0xA4, 0xFE, 0x54, 0x00,
-0x09, 0x00, 0xEB, 0xFF, 0x06, 0x00, 0xFD, 0xFF, 0x2D, 0x00, 0x55,
-0xFF, 0xB6, 0x01, 0x5F, 0xFC, 0x17, 0x07, 0x87, 0xF1, 0xC2, 0x2E,
-0xC0, 0x31, 0x7E, 0xF1, 0xF1, 0x06, 0x86, 0xFC, 0x9B, 0x01, 0x63,
-0xFF, 0x28, 0x00, 0xFD, 0xFF, 0x04, 0x00, 0xF7, 0xFF, 0xEA, 0xFF,
-0x93, 0x00, 0x36, 0xFE, 0x7D, 0x04, 0x85, 0xF4, 0x1F, 0x40, 0x94,
-0x1C, 0x47, 0xF4, 0x7E, 0x06, 0x5A, 0xFC, 0xDF, 0x01, 0x37, 0xFF,
-0x36, 0x00, 0xFE, 0xFF, 0x18, 0x00, 0x9C, 0xFF, 0xD4, 0x00, 0xB4,
-0xFE, 0x9A, 0x01, 0x95, 0xFE, 0xA8, 0xFF, 0x98, 0x48, 0x1D, 0x08,
-0xEE, 0xFA, 0x80, 0x03, 0xB9, 0xFD, 0x4B, 0x01, 0x6E, 0xFF, 0x25,
-0x00, 0x00, 0x00, 0xFF, 0xFF, 0x30, 0x00, 0x4A, 0xFF, 0xA9, 0x01,
-0xE7, 0xFC, 0x33, 0x05, 0x60, 0xF7, 0xDA, 0x11, 0xB8, 0x45, 0x1C,
-0xF9, 0xD8, 0x01, 0xCA, 0xFF, 0xAF, 0xFF, 0x5A, 0x00, 0xCC, 0xFF,
-0x0D, 0x00, 0xFD, 0xFF, 0x34, 0x00, 0x3E, 0xFF, 0xDE, 0x01, 0x33,
-0xFC, 0x21, 0x07, 0x30, 0xF2, 0x5C, 0x27, 0x5B, 0x38, 0x0F, 0xF2,
-0x40, 0x06, 0x0E, 0xFD, 0x43, 0x01, 0x91, 0xFF, 0x18, 0x00, 0xFF,
-0xFF, 0x00, 0x00, 0x0F, 0x00, 0xA8, 0xFF, 0x17, 0x01, 0x57, 0xFD,
-0xD6, 0x05, 0x90, 0xF2, 0xC8, 0x3A, 0x46, 0x24, 0xAA, 0xF2, 0x06,
-0x07, 0x32, 0xFC, 0xE5, 0x01, 0x39, 0xFF, 0x36, 0x00, 0xFD, 0xFF,
-0x10, 0x00, 0xBE, 0xFF, 0x7D, 0x00, 0x69, 0xFF, 0x4B, 0x00, 0xF6,
-0x00, 0xCB, 0xFA, 0xD3, 0x46, 0xF0, 0x0E, 0x5E, 0xF8, 0xBE, 0x04,
-0x1E, 0xFD, 0x91, 0x01, 0x52, 0xFF, 0x2D, 0x00, 0xFF, 0xFF, 0x00,
-0x00, 0x28, 0x00, 0x62, 0xFF, 0x69, 0x01, 0x77, 0xFD, 0x04, 0x04,
-0xE2, 0xF9, 0xCB, 0x0A, 0x0D, 0x48, 0x94, 0xFD, 0x92, 0xFF, 0x10,
-0x01, 0xFE, 0xFE, 0xB1, 0x00, 0xAA, 0xFF, 0x15, 0x00, 0xFD, 0xFF,
-0x36, 0x00, 0x36, 0xFF, 0xE5, 0x01, 0x43, 0xFC, 0xC0, 0x06, 0x8F,
-0xF3, 0xB1, 0x1F, 0x18, 0x3E, 0x9B, 0xF3, 0x16, 0x05, 0xD5, 0xFD,
-0xCC, 0x00, 0xCE, 0xFF, 0x01, 0x00, 0x02, 0x00, 0xFE, 0xFF, 0x22,
-0x00, 0x74, 0xFF, 0x7C, 0x01, 0xB5, 0xFC, 0xB8, 0x06, 0x9C, 0xF1,
-0x81, 0x34, 0xD1, 0x2B, 0xB3, 0xF1, 0x29, 0x07, 0x46, 0xFC, 0xCA,
-0x01, 0x4A, 0xFF, 0x30, 0x00, 0xFD, 0xFF, 0x09, 0x00, 0xDF, 0xFF,
-0x29, 0x00, 0x14, 0x00, 0x16, 0xFF, 0x0C, 0x03, 0xEE, 0xF6, 0xB0,
-0x43, 0x47, 0x16, 0xFC, 0xF5, 0xCF, 0x05, 0xA1, 0xFC, 0xC6, 0x01,
-0x3F, 0xFF, 0x33, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x1F, 0x00, 0x81,
-0xFF, 0x1B, 0x01, 0x20, 0xFE, 0xB6, 0x02, 0x7A, 0xFC, 0x5F, 0x04,
-0xF4, 0x48, 0xFF, 0x02, 0x13, 0xFD, 0x67, 0x02, 0x49, 0xFE, 0x07,
-0x01, 0x88, 0xFF, 0x1D, 0x00, 0xFE, 0xFF, 0x34, 0x00, 0x3C, 0xFF,
-0xCF, 0x01, 0x8A, 0xFC, 0x05, 0x06, 0x7B, 0xF5, 0x06, 0x18, 0xC7,
-0x42, 0x2F, 0xF6, 0x7A, 0x03, 0xD4, 0xFE, 0x39, 0x00, 0x17, 0x00,
-0xE6, 0xFF, 0x07, 0x00, 0xFD, 0xFF, 0x2E, 0x00, 0x50, 0xFF, 0xC0,
-0x01, 0x53, 0xFC, 0x21, 0x07, 0x96, 0xF1, 0x82, 0x2D, 0xF2, 0x32,
-0x86, 0xF1, 0xDB, 0x06, 0x99, 0xFC, 0x8E, 0x01, 0x6A, 0xFF, 0x25,
-0x00, 0xFD, 0xFF, 0x03, 0x00, 0xFB, 0xFF, 0xDE, 0xFF, 0xAC, 0x00,
-0x0B, 0xFE, 0xC1, 0x04, 0x1B, 0xF4, 0x47, 0x3F, 0xEA, 0x1D, 0xF5,
-0xF3, 0x9C, 0x06, 0x4F, 0xFC, 0xE2, 0x01, 0x36, 0xFF, 0x36, 0x00,
-0xFE, 0xFF, 0x16, 0x00, 0xA2, 0xFF, 0xC5, 0x00, 0xD4, 0xFE, 0x5F,
-0x01, 0x03, 0xFF, 0xBF, 0xFE, 0x63, 0x48, 0x40, 0x09, 0x7B, 0xFA,
-0xB9, 0x03, 0x9D, 0xFD, 0x58, 0x01, 0x69, 0xFF, 0x26, 0x00, 0x00,
-0x00, 0xFF, 0xFF, 0x2E, 0x00, 0x4D, 0xFF, 0x9F, 0x01, 0xFE, 0xFC,
-0x02, 0x05, 0xCB, 0xF7, 0x98, 0x10, 0x39, 0x46, 0xD0, 0xF9, 0x78,
-0x01, 0x00, 0x00, 0x91, 0xFF, 0x69, 0x00, 0xC6, 0xFF, 0x0E, 0x00,
-0xFD, 0xFF, 0x35, 0x00, 0x3B, 0xFF, 0xE2, 0x01, 0x31, 0xFC, 0x17,
-0x07, 0x61, 0xF2, 0x0A, 0x26, 0x6A, 0x39, 0x41, 0xF2, 0x15, 0x06,
-0x2C, 0xFD, 0x31, 0x01, 0x9B, 0xFF, 0x14, 0x00, 0xFF, 0xFF, 0xFF,
-0xFF, 0x13, 0x00, 0x9E, 0xFF, 0x2B, 0x01, 0x37, 0xFD, 0x05, 0x06,
-0x54, 0xF2, 0xC2, 0x39, 0x99, 0x25, 0x73, 0xF2, 0x14, 0x07, 0x31,
-0xFC, 0xE3, 0x01, 0x3B, 0xFF, 0x35, 0x00, 0xFD, 0xFF, 0x0E, 0x00,
-0xC4, 0xFF, 0x6E, 0x00, 0x87, 0xFF, 0x13, 0x00, 0x58, 0x01, 0x0D,
-0xFA, 0x61, 0x46, 0x2D, 0x10, 0xF0, 0xF7, 0xF1, 0x04, 0x05, 0xFD,
-0x9C, 0x01, 0x4E, 0xFF, 0x2E, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x27,
-0x00, 0x67, 0xFF, 0x5C, 0x01, 0x93, 0xFD, 0xCC, 0x03, 0x54, 0xFA,
-0xA2, 0x09, 0x4F, 0x48, 0x73, 0xFE, 0x27, 0xFF, 0x4B, 0x01, 0xDE,
-0xFE, 0xC0, 0x00, 0xA4, 0xFF, 0x16, 0x00, 0xFE, 0xFF, 0x36, 0x00,
-0x36, 0xFF, 0xE3, 0x01, 0x4C, 0xFC, 0xA6, 0x06, 0xDB, 0xF3, 0x5B,
-0x1E, 0xFC, 0x3E, 0xFA, 0xF3, 0xD7, 0x04, 0xFD, 0xFD, 0xB4, 0x00,
-0xD9, 0xFF, 0xFD, 0xFF, 0x03, 0x00, 0xFD, 0xFF, 0x25, 0x00, 0x6D,
-0xFF, 0x8A, 0x01, 0x9F, 0xFC, 0xD3, 0x06, 0x8A, 0xF1, 0x57, 0x33,
-0x17, 0x2D, 0x9C, 0xF1, 0x24, 0x07, 0x4F, 0xFC, 0xC3, 0x01, 0x4E,
-0xFF, 0x2F, 0x00, 0xFD, 0xFF, 0x08, 0x00, 0xE4, 0xFF, 0x1B, 0x00,
-0x30, 0x00, 0xE4, 0xFE, 0x5F, 0x03, 0x5E, 0xF6, 0x02, 0x43, 0x96,
-0x17, 0x9B, 0xF5, 0xF8, 0x05, 0x8F, 0xFC, 0xCC, 0x01, 0x3D, 0xFF,
-0x34, 0x00, 0xFE, 0xFF, 0x1E, 0x00, 0x86, 0xFF, 0x0C, 0x01, 0x3E,
-0xFE, 0x7B, 0x02, 0xED, 0xFC, 0x56, 0x03, 0xF5, 0x48, 0x06, 0x04,
-0xA1, 0xFC, 0xA3, 0x02, 0x2A, 0xFE, 0x16, 0x01, 0x83, 0xFF, 0x1F,
-0x00, 0x00, 0x00, 0xFF, 0xFF, 0x33, 0x00, 0x3E, 0xFF, 0xC8, 0x01,
-0x9B, 0xFC, 0xDD, 0x05, 0xDC, 0xF5, 0xB6, 0x16, 0x77, 0x43, 0xBD,
-0xF6, 0x28, 0x03, 0x05, 0xFF, 0x1D, 0x00, 0x25, 0x00, 0xE1, 0xFF,
-0x08, 0x00, 0xFD, 0xFF, 0x30, 0x00, 0x4B, 0xFF, 0xC8, 0x01, 0x49,
-0xFC, 0x27, 0x07, 0xAB, 0xF1, 0x3E, 0x2C, 0x1E, 0x34, 0x95, 0xF1,
-0xC1, 0x06, 0xAE, 0xFC, 0x81, 0x01, 0x71, 0xFF, 0x23, 0x00, 0xFE,
-0xFF, 0x02, 0x00, 0x00, 0x00, 0xD2, 0xFF, 0xC4, 0x00, 0xE2, 0xFD,
-0x01, 0x05, 0xBA, 0xF3, 0x64, 0x3E, 0x3F, 0x1F, 0xA8, 0xF3, 0xB8,
-0x06, 0x46, 0xFC, 0xE5, 0x01, 0x36, 0xFF, 0x36, 0x00, 0xFD, 0xFF,
-0x15, 0x00, 0xA8, 0xFF, 0xB6, 0x00, 0xF3, 0xFE, 0x24, 0x01, 0x6E,
-0xFF, 0xDE, 0xFD, 0x25, 0x48, 0x68, 0x0A, 0x08, 0xFA, 0xF2, 0x03,
-0x81, 0xFD, 0x65, 0x01, 0x64, 0xFF, 0x28, 0x00, 0x00, 0x00, 0xFF,
-0xFF, 0x2D, 0x00, 0x51, 0xFF, 0x95, 0x01, 0x15, 0xFD, 0xCF, 0x04,
-0x39, 0xF8, 0x59, 0x0F, 0xAF, 0x46, 0x8B, 0xFA, 0x17, 0x01, 0x38,
-0x00, 0x73, 0xFF, 0x78, 0x00, 0xC0, 0xFF, 0x0F, 0x00, 0xFD, 0xFF,
-0x36, 0x00, 0x39, 0xFF, 0xE4, 0x01, 0x32, 0xFC, 0x0B, 0x07, 0x97,
-0xF2, 0xB8, 0x24, 0x71, 0x3A, 0x7B, 0xF2, 0xE6, 0x05, 0x4C, 0xFD,
-0x1D, 0x01, 0xA4, 0xFF, 0x11, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x16,
-0x00, 0x94, 0xFF, 0x3D, 0x01, 0x18, 0xFD, 0x32, 0x06, 0x1F, 0xF2,
-0xB5, 0x38, 0xEB, 0x26, 0x40, 0xF2, 0x1E, 0x07, 0x32, 0xFC, 0xDF,
-0x01, 0x3D, 0xFF, 0x35, 0x00, 0xFD, 0xFF, 0x0D, 0x00, 0xCA, 0xFF,
-0x5F, 0x00, 0xA5, 0xFF, 0xDC, 0xFF, 0xB8, 0x01, 0x57, 0xF9, 0xE5,
-0x45, 0x6E, 0x11, 0x83, 0xF7, 0x23, 0x05, 0xEE, 0xFC, 0xA6, 0x01,
-0x4B, 0xFF, 0x2F, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x25, 0x00, 0x6C,
-0xFF, 0x4F, 0x01, 0xB0, 0xFD, 0x93, 0x03, 0xC7, 0xFA, 0x7D, 0x08,
-0x86, 0x48, 0x5A, 0xFF, 0xBA, 0xFE, 0x86, 0x01, 0xBF, 0xFE, 0xCF,
-0x00, 0x9E, 0xFF, 0x17, 0x00, 0xFE, 0xFF, 0x36, 0x00, 0x37, 0xFF,
-0xE0, 0x01, 0x56, 0xFC, 0x89, 0x06, 0x2B, 0xF4, 0x06, 0x1D, 0xD7,
-0x3F, 0x61, 0xF4, 0x94, 0x04, 0x27, 0xFE, 0x9C, 0x00, 0xE6, 0xFF,
-0xF8, 0xFF, 0x04, 0x00, 0xFD, 0xFF, 0x27, 0x00, 0x66, 0xFF, 0x97,
-0x01, 0x8C, 0xFC, 0xEA, 0x06, 0x80, 0xF1, 0x26, 0x32, 0x58, 0x2E,
-0x8B, 0xF1, 0x1B, 0x07, 0x5B, 0xFC, 0xBA, 0x01, 0x53, 0xFF, 0x2D,
-0x00, 0xFD, 0xFF, 0x07, 0x00, 0xE9, 0xFF, 0x0E, 0x00, 0x4B, 0x00,
-0xB4, 0xFE, 0xAF, 0x03, 0xD5, 0xF5, 0x4D, 0x42, 0xE6, 0x18, 0x3C,
-0xF5, 0x1F, 0x06, 0x7F, 0xFC, 0xD3, 0x01, 0x3B, 0xFF, 0x35, 0x00,
-0xFE, 0xFF, 0x1C, 0x00, 0x8C, 0xFF, 0xFE, 0x00, 0x5D, 0xFE, 0x3F,
-0x02, 0x5E, 0xFD, 0x54, 0x02, 0xEC, 0x48, 0x13, 0x05, 0x2E, 0xFC,
-0xDE, 0x02, 0x0C, 0xFE, 0x24, 0x01, 0x7D, 0xFF, 0x20, 0x00, 0x00,
-0x00, 0xFF, 0xFF, 0x32, 0x00, 0x41, 0xFF, 0xC1, 0x01, 0xAD, 0xFC,
-0xB2, 0x05, 0x3F, 0xF6, 0x69, 0x15, 0x1F, 0x44, 0x53, 0xF7, 0xD3,
-0x02, 0x38, 0xFF, 0x01, 0x00, 0x33, 0x00, 0xDB, 0xFF, 0x09, 0x00,
-0xFD, 0xFF, 0x31, 0x00, 0x47, 0xFF, 0xCF, 0x01, 0x40, 0xFC, 0x2A,
-0x07, 0xC6, 0xF1, 0xF7, 0x2A, 0x46, 0x35, 0xAB, 0xF1, 0xA4, 0x06,
-0xC4, 0xFC, 0x72, 0x01, 0x79, 0xFF, 0x20, 0x00, 0xFE, 0xFF, 0x02,
-0x00, 0x04, 0x00, 0xC6, 0xFF, 0xDB, 0x00, 0xBB, 0xFD, 0x3E, 0x05,
-0x60, 0xF3, 0x7B, 0x3D, 0x94, 0x20, 0x5E, 0xF3, 0xD0, 0x06, 0x3E,
-0xFC, 0xE6, 0x01, 0x36, 0xFF, 0x36, 0x00, 0xFD, 0xFF, 0x14, 0x00,
-0xAE, 0xFF, 0xA7, 0x00, 0x12, 0xFF, 0xEA, 0x00, 0xD9, 0xFF, 0x03,
-0xFD, 0xDC, 0x47, 0x95, 0x0B, 0x96, 0xF9, 0x29, 0x04, 0x65, 0xFD,
-0x71, 0x01, 0x5F, 0xFF, 0x29, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x2C,
-0x00, 0x55, 0xFF, 0x8A, 0x01, 0x2E, 0xFD, 0x9B, 0x04, 0xA8, 0xF8,
-0x1F, 0x0E, 0x1A, 0x47, 0x4E, 0xFB, 0xB3, 0x00, 0x70, 0x00, 0x54,
-0xFF, 0x87, 0x00, 0xBB, 0xFF, 0x11, 0x00, 0xFD, 0xFF, 0x36, 0x00,
-0x38, 0xFF, 0xE6, 0x01, 0x34, 0xFC, 0xFB, 0x06, 0xD2, 0xF2, 0x64,
-0x23, 0x73, 0x3B, 0xBC, 0xF2, 0xB4, 0x05, 0x6E, 0xFD, 0x09, 0x01,
-0xAF, 0xFF, 0x0D, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x1A, 0x00, 0x8B,
-0xFF, 0x4F, 0x01, 0xFB, 0xFC, 0x5A, 0x06, 0xF2, 0xF1, 0xA0, 0x37,
-0x3A, 0x28, 0x13, 0xF2, 0x25, 0x07, 0x35, 0xFC, 0xDB, 0x01, 0x40,
-0xFF, 0x34, 0x00, 0xFD, 0xFF, 0x0C, 0x00, 0xD0, 0xFF, 0x51, 0x00,
-0xC3, 0xFF, 0xA6, 0xFF, 0x16, 0x02, 0xA9, 0xF8, 0x5C, 0x45, 0xB2,
-0x12, 0x19, 0xF7, 0x52, 0x05, 0xD8, 0xFC, 0xAF, 0x01, 0x47, 0xFF,
-0x30, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x24, 0x00, 0x71, 0xFF, 0x42,
-0x01, 0xCD, 0xFD, 0x59, 0x03, 0x3B, 0xFB, 0x5E, 0x07, 0xB3, 0x48,
-0x48, 0x00, 0x4B, 0xFE, 0xC2, 0x01, 0x9F, 0xFE, 0xDE, 0x00, 0x98,
-0xFF, 0x19, 0x00, 0xFE, 0xFF, 0x36, 0x00, 0x38, 0xFF, 0xDD, 0x01,
-0x62, 0xFC, 0x69, 0x06, 0x7F, 0xF4, 0xB2, 0x1B, 0xAB, 0x40, 0xD0,
-0xF4, 0x4E, 0x04, 0x53, 0xFE, 0x83, 0x00, 0xF2, 0xFF, 0xF4, 0xFF,
-0x05, 0x00, 0xFD, 0xFF, 0x29, 0x00, 0x5F, 0xFF, 0xA3, 0x01, 0x7A,
-0xFC, 0xFD, 0x06, 0x7C, 0xF1, 0xF2, 0x30, 0x96, 0x2F, 0x80, 0xF1,
-0x0F, 0x07, 0x69, 0xFC, 0xB0, 0x01, 0x59, 0xFF, 0x2B, 0x00, 0xFD,
-0xFF, 0x06, 0x00, 0xEE, 0xFF, 0x01, 0x00, 0x66, 0x00, 0x85, 0xFE,
-0xFC, 0x03, 0x55, 0xF5, 0x8C, 0x41, 0x38, 0x1A, 0xE1, 0xF4, 0x43,
-0x06, 0x70, 0xFC, 0xD8, 0x01, 0x39, 0xFF, 0x35, 0x00, 0xFE, 0xFF,
-0x1B, 0x00, 0x92, 0xFF, 0xEF, 0x00, 0x7D, 0xFE, 0x04, 0x02, 0xCF,
-0xFD, 0x58, 0x01, 0xD7, 0x48, 0x26, 0x06, 0xBB, 0xFB, 0x19, 0x03,
-0xED, 0xFD, 0x32, 0x01, 0x77, 0xFF, 0x22, 0x00, 0x00, 0x00, 0xFF,
-0xFF, 0x32, 0x00, 0x44, 0xFF, 0xB9, 0x01, 0xC1, 0xFC, 0x86, 0x05,
-0xA5, 0xF6, 0x1E, 0x14, 0xBA, 0x44, 0xF0, 0xF7, 0x7B, 0x02, 0x6B,
-0xFF, 0xE4, 0xFF, 0x41, 0x00, 0xD6, 0xFF, 0x0B, 0x00, 0xFD, 0xFF,
-0x33, 0x00, 0x43, 0xFF, 0xD5, 0x01, 0x3A, 0xFC, 0x2A, 0x07, 0xE7,
-0xF1, 0xAC, 0x29, 0x66, 0x36, 0xC9, 0xF1, 0x83, 0x06, 0xDD, 0xFC,
-0x62, 0x01, 0x81, 0xFF, 0x1D, 0x00, 0xFE, 0xFF, 0x01, 0x00, 0x08,
-0x00, 0xBB, 0xFF, 0xF1, 0x00, 0x96, 0xFD, 0x78, 0x05, 0x0E, 0xF3,
-0x8A, 0x3C, 0xEA, 0x21, 0x19, 0xF3, 0xE6, 0x06, 0x38, 0xFC, 0xE6,
-0x01, 0x37, 0xFF, 0x36, 0x00, 0xFD, 0xFF, 0x12, 0x00, 0xB4, 0xFF,
-0x98, 0x00, 0x32, 0xFF, 0xB0, 0x00, 0x41, 0x00, 0x30, 0xFC, 0x86,
-0x47, 0xC6, 0x0C, 0x24, 0xF9, 0x60, 0x04, 0x4B, 0xFD, 0x7D, 0x01,
-0x5A, 0xFF, 0x2A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2B, 0x00, 0x5A,
-0xFF, 0x7E, 0x01, 0x48, 0xFD, 0x66, 0x04, 0x18, 0xF9, 0xE8, 0x0C,
-0x7C, 0x47, 0x19, 0xFC, 0x4D, 0x00, 0xA9, 0x00, 0x35, 0xFF, 0x96,
-0x00, 0xB5, 0xFF, 0x12, 0x00, 0xFD, 0xFF, 0x36, 0x00, 0x37, 0xFF,
-0xE6, 0x01, 0x38, 0xFC, 0xE9, 0x06, 0x12, 0xF3, 0x10, 0x22, 0x6E,
-0x3C, 0x05, 0xF3, 0x7E, 0x05, 0x91, 0xFD, 0xF4, 0x00, 0xBA, 0xFF,
-0x09, 0x00, 0x01, 0x00, 0xFE, 0xFF, 0x1D, 0x00, 0x82, 0xFF, 0x60,
-0x01, 0xE0, 0xFC, 0x7F, 0x06, 0xCC, 0xF1, 0x85, 0x36, 0x87, 0x29,
-0xEB, 0xF1, 0x2A, 0x07, 0x39, 0xFC, 0xD6, 0x01, 0x43, 0xFF, 0x33,
-0x00, 0xFD, 0xFF, 0x0B, 0x00, 0xD5, 0xFF, 0x42, 0x00, 0xE1, 0xFF,
-0x71, 0xFF, 0x71, 0x02, 0x02, 0xF8, 0xCC, 0x44, 0xFA, 0x13, 0xB0,
-0xF6, 0x81, 0x05, 0xC3, 0xFC, 0xB8, 0x01, 0x44, 0xFF, 0x31, 0x00,
-0xFF, 0xFF, 0x00, 0x00, 0x22, 0x00, 0x77, 0xFF, 0x34, 0x01, 0xEA,
-0xFD, 0x1F, 0x03, 0xAE, 0xFB, 0x45, 0x06, 0xD5, 0x48, 0x3C, 0x01,
-0xDC, 0xFD, 0xFD, 0x01, 0x80, 0xFE, 0xED, 0x00, 0x93, 0xFF, 0x1B,
-0x00, 0xFE, 0xFF, 0x35, 0x00, 0x39, 0xFF, 0xD8, 0x01, 0x6F, 0xFC,
-0x47, 0x06, 0xD7, 0xF4, 0x5D, 0x1A, 0x74, 0x41, 0x48, 0xF5, 0x04,
-0x04, 0x80, 0xFE, 0x69, 0x00, 0xFF, 0xFF, 0xEF, 0xFF, 0x05, 0x00,
-0xFD, 0xFF, 0x2B, 0x00, 0x59, 0xFF, 0xAE, 0x01, 0x6A, 0xFC, 0x0D,
-0x07, 0x80, 0xF1, 0xB8, 0x2F, 0xCF, 0x30, 0x7D, 0xF1, 0xFF, 0x06,
-0x78, 0xFC, 0xA5, 0x01, 0x5F, 0xFF, 0x29, 0x00, 0xFD, 0xFF, 0x05,
-0x00, 0xF3, 0xFF, 0xF4, 0xFF, 0x80, 0x00, 0x58, 0xFE, 0x46, 0x04,
-0xDD, 0xF4, 0xC3, 0x40, 0x8C, 0x1B, 0x89, 0xF4, 0x66, 0x06, 0x63,
-0xFC, 0xDC, 0x01, 0x38, 0xFF, 0x36, 0x00, 0xFE, 0xFF, 0x19, 0x00,
-0x98, 0xFF, 0xE0, 0x00, 0x9C, 0xFE, 0xC8, 0x01, 0x3F, 0xFE, 0x62,
-0x00, 0xB8, 0x48, 0x3F, 0x07, 0x47, 0xFB, 0x53, 0x03, 0xD0, 0xFD,
-0x40, 0x01, 0x72, 0xFF, 0x23, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x30,
-0x00, 0x47, 0xFF, 0xB0, 0x01, 0xD6, 0xFC, 0x58, 0x05, 0x0D, 0xF7,
-0xD7, 0x12, 0x4E, 0x45, 0x96, 0xF8, 0x20, 0x02, 0xA0, 0xFF, 0xC7,
-0xFF, 0x4F, 0x00, 0xD0, 0xFF, 0x0C, 0x00, 0xFD, 0xFF, 0x34, 0x00,
-0x40, 0xFF, 0xDB, 0x01, 0x35, 0xFC, 0x26, 0x07, 0x0E, 0xF2, 0x60,
-0x28, 0x82, 0x37, 0xED, 0xF1, 0x5E, 0x06, 0xF8, 0xFC, 0x51, 0x01,
-0x8A, 0xFF, 0x1A, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x0C, 0x00, 0xB0,
-0xFF, 0x07, 0x01, 0x72, 0xFD, 0xAE, 0x05, 0xC4, 0xF2, 0x90, 0x3B,
-0x3F, 0x23, 0xD9, 0xF2, 0xF9, 0x06, 0x34, 0xFC, 0xE6, 0x01, 0x38,
-0xFF, 0x36, 0x00, 0xFD, 0xFF, 0x11, 0x00, 0xBA, 0xFF, 0x89, 0x00,
-0x51, 0xFF, 0x77, 0x00, 0xA7, 0x00, 0x64, 0xFB, 0x26, 0x47, 0xFC,
-0x0D, 0xB4, 0xF8, 0x95, 0x04, 0x31, 0xFD, 0x88, 0x01, 0x56, 0xFF,
-0x2C, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x29, 0x00, 0x5E, 0xFF, 0x72,
-0x01, 0x62, 0xFD, 0x2F, 0x04, 0x89, 0xF9, 0xB6, 0x0B, 0xD2, 0x47,
-0xEB, 0xFC, 0xE4, 0xFF, 0xE3, 0x00, 0x16, 0xFF, 0xA5, 0x00, 0xAF,
-0xFF, 0x13, 0x00, 0xFD, 0xFF, 0x36, 0x00, 0x36, 0xFF, 0xE6, 0x01,
-0x3E, 0xFC, 0xD3, 0x06, 0x56, 0xF3, 0xBA, 0x20, 0x61, 0x3D, 0x56,
-0xF3, 0x45, 0x05, 0xB7, 0xFD, 0xDE, 0x00, 0xC5, 0xFF, 0x05, 0x00,
-0x02, 0x00, 0xFE, 0xFF, 0x20, 0x00, 0x7A, 0xFF, 0x70, 0x01, 0xC7,
-0xFC, 0xA0, 0x06, 0xAE, 0xF1, 0x65, 0x35, 0xD1, 0x2A, 0xCA, 0xF1,
-0x2A, 0x07, 0x40, 0xFC, 0xD0, 0x01, 0x47, 0xFF, 0x32, 0x00, 0xFD,
-0xFF, 0x09, 0x00, 0xDB, 0xFF, 0x34, 0x00, 0xFE, 0xFF, 0x3D, 0xFF,
-0xC9, 0x02, 0x64, 0xF7, 0x2F, 0x44, 0x44, 0x15, 0x4A, 0xF6, 0xAD,
-0x05, 0xAF, 0xFC, 0xC0, 0x01, 0x41, 0xFF, 0x32, 0x00, 0xFF, 0xFF,
-0x00, 0x00, 0x21, 0x00, 0x7C, 0xFF, 0x26, 0x01, 0x08, 0xFE, 0xE4,
-0x02, 0x21, 0xFC, 0x31, 0x05, 0xEB, 0x48, 0x37, 0x02, 0x6B, 0xFD,
-0x39, 0x02, 0x61, 0xFE, 0xFC, 0x00, 0x8D, 0xFF, 0x1C, 0x00, 0xFE,
-0xFF, 0x35, 0x00, 0x3A, 0xFF, 0xD3, 0x01, 0x7D, 0xFC, 0x23, 0x06,
-0x32, 0xF5, 0x0C, 0x19, 0x38, 0x42, 0xC7, 0xF5, 0xB8, 0x03, 0xAF,
-0xFE, 0x4E, 0x00, 0x0C, 0x00, 0xEA, 0xFF, 0x06, 0x00, 0xFD, 0xFF,
-0x2D, 0x00, 0x54, 0xFF, 0xB8, 0x01, 0x5D, 0xFC, 0x1A, 0x07, 0x8A,
-0xF1, 0x7B, 0x2E, 0x04, 0x32, 0x7F, 0xF1, 0xEC, 0x06, 0x8A, 0xFC,
-0x98, 0x01, 0x65, 0xFF, 0x27, 0x00, 0xFD, 0xFF, 0x04, 0x00, 0xF8,
-0xFF, 0xE7, 0xFF, 0x99, 0x00, 0x2C, 0xFE, 0x8C, 0x04, 0x6D, 0xF4,
-0xF0, 0x3F, 0xE0, 0x1C, 0x34, 0xF4, 0x85, 0x06, 0x57, 0xFC, 0xE0,
-0x01, 0x37, 0xFF, 0x36, 0x00, 0xFE, 0xFF, 0x18, 0x00, 0x9E, 0xFF,
-0xD1, 0x00, 0xBB, 0xFE, 0x8D, 0x01, 0xAE, 0xFE, 0x74, 0xFF, 0x8D,
-0x48, 0x5D, 0x08, 0xD4, 0xFA, 0x8D, 0x03, 0xB3, 0xFD, 0x4E, 0x01,
-0x6D, 0xFF, 0x25, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x2F, 0x00, 0x4A,
-0xFF, 0xA7, 0x01, 0xEC, 0xFC, 0x28, 0x05, 0x77, 0xF7, 0x92, 0x11,
-0xD7, 0x45, 0x43, 0xF9, 0xC3, 0x01, 0xD6, 0xFF, 0xA9, 0xFF, 0x5E,
-0x00, 0xCB, 0xFF, 0x0D, 0x00, 0xFD, 0xFF, 0x34, 0x00, 0x3D, 0xFF,
-0xDF, 0x01, 0x32, 0xFC, 0x1F, 0x07, 0x3B, 0xF2, 0x11, 0x27, 0x97,
-0x38, 0x19, 0xF2, 0x36, 0x06, 0x15, 0xFD, 0x3F, 0x01, 0x93, 0xFF,
-0x17, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x10, 0x00, 0xA6, 0xFF, 0x1B,
-0x01, 0x50, 0xFD, 0xE1, 0x05, 0x82, 0xF2, 0x8F, 0x3A, 0x92, 0x24,
-0x9D, 0xF2, 0x09, 0x07, 0x32, 0xFC, 0xE4, 0x01, 0x39, 0xFF, 0x36,
-0x00, 0xFD, 0xFF, 0x0F, 0x00, 0xC0, 0xFF, 0x7A, 0x00, 0x70, 0xFF,
-0x3E, 0x00, 0x0C, 0x01, 0xA1, 0xFA, 0xBB, 0x46, 0x36, 0x0F, 0x45,
-0xF8, 0xC9, 0x04, 0x18, 0xFD, 0x93, 0x01, 0x52, 0xFF, 0x2D, 0x00,
-0xFF, 0xFF, 0x00, 0x00, 0x28, 0x00, 0x63, 0xFF, 0x66, 0x01, 0x7D,
-0xFD, 0xF8, 0x03, 0xFB, 0xF9, 0x89, 0x0A, 0x1D, 0x48, 0xC5, 0xFD,
-0x7A, 0xFF, 0x1D, 0x01, 0xF7, 0xFE, 0xB4, 0x00, 0xA9, 0xFF, 0x15,
-0x00, 0xFD, 0xFF, 0x36, 0x00, 0x36, 0xFF, 0xE5, 0x01, 0x45, 0xFC,
-0xBB, 0x06, 0xA0, 0xF3, 0x64, 0x1F, 0x4A, 0x3E, 0xB0, 0xF3, 0x08,
-0x05, 0xDE, 0xFD, 0xC7, 0x00, 0xD0, 0xFF, 0x00, 0x00, 0x02, 0x00,
-0xFE, 0xFF, 0x23, 0x00, 0x72, 0xFF, 0x7F, 0x01, 0xB0, 0xFC, 0xBE,
-0x06, 0x97, 0xF1, 0x3F, 0x34, 0x19, 0x2C, 0xAD, 0xF1, 0x28, 0x07,
-0x48, 0xFC, 0xC9, 0x01, 0x4B, 0xFF, 0x30, 0x00, 0xFD, 0xFF, 0x08,
-0x00, 0xE0, 0xFF, 0x26, 0x00, 0x1A, 0x00, 0x0B, 0xFF, 0x1E, 0x03,
-0xCD, 0xF6, 0x89, 0x43, 0x91, 0x16, 0xE7, 0xF5, 0xD8, 0x05, 0x9D,
-0xFC, 0xC7, 0x01, 0x3E, 0xFF, 0x33, 0x00, 0xFF, 0xFF, 0x00, 0x00,
-0x1F, 0x00, 0x82, 0xFF, 0x18, 0x01, 0x27, 0xFE, 0xA9, 0x02, 0x94,
-0xFC, 0x24, 0x04, 0xF5, 0x48, 0x39, 0x03, 0xF9, 0xFC, 0x74, 0x02,
-0x42, 0xFE, 0x0B, 0x01, 0x87, 0xFF, 0x1E, 0x00, 0xFE, 0xFF, 0x34,
-0x00, 0x3C, 0xFF, 0xCD, 0x01, 0x8E, 0xFC, 0xFC, 0x05, 0x90, 0xF5,
-0xBB, 0x17, 0xEE, 0x42, 0x4E, 0xF6, 0x68, 0x03, 0xDF, 0xFE, 0x33,
-0x00, 0x1A, 0x00, 0xE5, 0xFF, 0x07, 0x00, 0xFD, 0xFF, 0x2F, 0x00,
-0x4F, 0xFF, 0xC2, 0x01, 0x51, 0xFC, 0x23, 0x07, 0x9A, 0xF1, 0x3A,
-0x2D, 0x35, 0x33, 0x89, 0xF1, 0xD5, 0x06, 0x9D, 0xFC, 0x8B, 0x01,
-0x6C, 0xFF, 0x25, 0x00, 0xFD, 0xFF, 0x03, 0x00, 0xFC, 0xFF, 0xDB,
-0xFF, 0xB2, 0x00, 0x02, 0xFE, 0xCF, 0x04, 0x05, 0xF4, 0x16, 0x3F,
-0x36, 0x1E, 0xE4, 0xF3, 0xA3, 0x06, 0x4D, 0xFC, 0xE3, 0x01, 0x36,
-0xFF, 0x36, 0x00, 0xFE, 0xFF, 0x16, 0x00, 0xA4, 0xFF, 0xC2, 0x00,
-0xDB, 0xFE, 0x52, 0x01, 0x1B, 0xFF, 0x8D, 0xFE, 0x57, 0x48, 0x81,
-0x09, 0x61, 0xFA, 0xC6, 0x03, 0x96, 0xFD, 0x5B, 0x01, 0x68, 0xFF,
-0x26, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x2E, 0x00, 0x4E, 0xFF, 0x9D,
-0x01, 0x03, 0xFD, 0xF7, 0x04, 0xE3, 0xF7, 0x51, 0x10, 0x55, 0x46,
-0xF9, 0xF9, 0x63, 0x01, 0x0D, 0x00, 0x8B, 0xFF, 0x6D, 0x00, 0xC5,
-0xFF, 0x0E, 0x00, 0xFD, 0xFF, 0x35, 0x00, 0x3B, 0xFF, 0xE2, 0x01,
-0x31, 0xFC, 0x15, 0x07, 0x6D, 0xF2, 0xBF, 0x25, 0xA5, 0x39, 0x4D,
-0xF2, 0x0B, 0x06, 0x33, 0xFD, 0x2D, 0x01, 0x9D, 0xFF, 0x13, 0x00,
-0xFF, 0xFF, 0xFF, 0xFF, 0x14, 0x00, 0x9C, 0xFF, 0x2F, 0x01, 0x30,
-0xFD, 0x10, 0x06, 0x47, 0xF2, 0x87, 0x39, 0xE5, 0x25, 0x67, 0xF2,
-0x16, 0x07, 0x31, 0xFC, 0xE2, 0x01, 0x3B, 0xFF, 0x35, 0x00, 0xFD,
-0xFF, 0x0E, 0x00, 0xC6, 0xFF, 0x6B, 0x00, 0x8E, 0xFF, 0x06, 0x00,
-0x6E, 0x01, 0xE4, 0xF9, 0x48, 0x46, 0x75, 0x10, 0xD7, 0xF7, 0xFC,
-0x04, 0x00, 0xFD, 0x9E, 0x01, 0x4E, 0xFF, 0x2E, 0x00, 0xFF, 0xFF,
-0x00, 0x00, 0x26, 0x00, 0x68, 0xFF, 0x59, 0x01, 0x99, 0xFD, 0xC0,
-0x03, 0x6E, 0xFA, 0x61, 0x09, 0x5D, 0x48, 0xA6, 0xFE, 0x0F, 0xFF,
-0x58, 0x01, 0xD7, 0xFE, 0xC3, 0x00, 0xA3, 0xFF, 0x16, 0x00, 0xFE,
-0xFF, 0x36, 0x00, 0x36, 0xFF, 0xE3, 0x01, 0x4E, 0xFC, 0xA0, 0x06,
-0xED, 0xF3, 0x0F, 0x1E, 0x2D, 0x3F, 0x10, 0xF4, 0xC8, 0x04, 0x07,
-0xFE, 0xAF, 0x00, 0xDC, 0xFF, 0xFC, 0xFF, 0x03, 0x00, 0xFD, 0xFF,
-0x25, 0x00, 0x6B, 0xFF, 0x8D, 0x01, 0x9B, 0xFC, 0xD8, 0x06, 0x87,
-0xF1, 0x13, 0x33, 0x5E, 0x2D, 0x98, 0xF1, 0x22, 0x07, 0x52, 0xFC,
-0xC1, 0x01, 0x4F, 0xFF, 0x2F, 0x00, 0xFD, 0xFF, 0x07, 0x00, 0xE5,
-0xFF, 0x18, 0x00, 0x36, 0x00, 0xD9, 0xFE, 0x71, 0x03, 0x3F, 0xF6,
-0xDB, 0x42, 0xE0, 0x17, 0x86, 0xF5, 0x00, 0x06, 0x8C, 0xFC, 0xCE,
-0x01, 0x3C, 0xFF, 0x34, 0x00, 0xFE, 0xFF, 0x1D, 0x00, 0x88, 0xFF,
-0x09, 0x01, 0x45, 0xFE, 0x6E, 0x02, 0x06, 0xFD, 0x1C, 0x03, 0xF4,
-0x48, 0x41, 0x04, 0x87, 0xFC, 0xB0, 0x02, 0x23, 0xFE, 0x19, 0x01,
-0x81, 0xFF, 0x1F, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x33, 0x00, 0x3F,
-0xFF, 0xC6, 0x01, 0x9F, 0xFC, 0xD3, 0x05, 0xF1, 0xF5, 0x6C, 0x16,
-0x9E, 0x43, 0xDD, 0xF6, 0x15, 0x03, 0x10, 0xFF, 0x17, 0x00, 0x28,
-0x00, 0xDF, 0xFF, 0x09, 0x00, 0xFD, 0xFF, 0x30, 0x00, 0x4A, 0xFF,
-0xCA, 0x01, 0x47, 0xFC, 0x28, 0x07, 0xB0, 0xF1, 0xF5, 0x2B, 0x60,
-0x34, 0x9A, 0xF1, 0xBB, 0x06, 0xB3, 0xFC, 0x7D, 0x01, 0x73, 0xFF,
-0x22, 0x00, 0xFE, 0xFF, 0x02, 0x00, 0x01, 0x00, 0xCF, 0xFF, 0xC9,
-0x00, 0xDA, 0xFD, 0x0F, 0x05, 0xA5, 0xF3, 0x31, 0x3E, 0x8A, 0x1F,
-0x97, 0xF3, 0xBD, 0x06, 0x44, 0xFC, 0xE5, 0x01, 0x36, 0xFF, 0x36,
-0x00, 0xFD, 0xFF, 0x15, 0x00, 0xAA, 0xFF, 0xB3, 0x00, 0xFA, 0xFE,
-0x17, 0x01, 0x86, 0xFF, 0xAC, 0xFD, 0x16, 0x48, 0xAA, 0x0A, 0xEE,
-0xF9, 0xFE, 0x03, 0x7A, 0xFD, 0x67, 0x01, 0x63, 0xFF, 0x28, 0x00,
-0x00, 0x00, 0xFF, 0xFF, 0x2D, 0x00, 0x52, 0xFF, 0x92, 0x01, 0x1B,
-0xFD, 0xC4, 0x04, 0x51, 0xF8, 0x13, 0x0F, 0xC8, 0x46, 0xB6, 0xFA,
-0x01, 0x01, 0x44, 0x00, 0x6C, 0xFF, 0x7B, 0x00, 0xBF, 0xFF, 0x10,
-0x00, 0xFD, 0xFF, 0x36, 0x00, 0x39, 0xFF, 0xE5, 0x01, 0x32, 0xFC,
-0x08, 0x07, 0xA4, 0xF2, 0x6D, 0x24, 0xAD, 0x3A, 0x88, 0xF2, 0xDB,
-0x05, 0x53, 0xFD, 0x19, 0x01, 0xA7, 0xFF, 0x10, 0x00, 0x00, 0x00,
-0xFF, 0xFF, 0x17, 0x00, 0x92, 0xFF, 0x41, 0x01, 0x11, 0xFD, 0x3B,
-0x06, 0x14, 0xF2, 0x78, 0x38, 0x36, 0x27, 0x35, 0xF2, 0x20, 0x07,
-0x33, 0xFC, 0xDF, 0x01, 0x3E, 0xFF, 0x34, 0x00, 0xFD, 0xFF, 0x0D,
-0x00, 0xCB, 0xFF, 0x5C, 0x00, 0xAC, 0xFF, 0xD0, 0xFF, 0xCD, 0x01,
-0x30, 0xF9, 0xC8, 0x45, 0xB6, 0x11, 0x6B, 0xF7, 0x2D, 0x05, 0xE9,
-0xFC, 0xA8, 0x01, 0x4A, 0xFF, 0x30, 0x00, 0xFF, 0xFF, 0x00, 0x00,
-0x25, 0x00, 0x6D, 0xFF, 0x4C, 0x01, 0xB6, 0xFD, 0x86, 0x03, 0xE1,
-0xFA, 0x3D, 0x08, 0x92, 0x48, 0x8E, 0xFF, 0xA1, 0xFE, 0x93, 0x01,
-0xB8, 0xFE, 0xD3, 0x00, 0x9D, 0xFF, 0x18, 0x00, 0xFE, 0xFF, 0x36,
-0x00, 0x37, 0xFF, 0xE0, 0x01, 0x58, 0xFC, 0x82, 0x06, 0x3E, 0xF4,
-0xBA, 0x1C, 0x07, 0x40, 0x79, 0xF4, 0x84, 0x04, 0x31, 0xFE, 0x96,
-0x00, 0xE8, 0xFF, 0xF7, 0xFF, 0x04, 0x00, 0xFD, 0xFF, 0x28, 0x00,
-0x64, 0xFF, 0x9A, 0x01, 0x88, 0xFC, 0xEE, 0x06, 0x7E, 0xF1, 0xE3,
-0x31, 0x9F, 0x2E, 0x88, 0xF1, 0x19, 0x07, 0x5E, 0xFC, 0xB7, 0x01,
-0x54, 0xFF, 0x2D, 0x00, 0xFD, 0xFF, 0x06, 0x00, 0xEA, 0xFF, 0x0B,
-0x00, 0x51, 0x00, 0xAA, 0xFE, 0xC0, 0x03, 0xB8, 0xF5, 0x21, 0x42,
-0x31, 0x19, 0x28, 0xF5, 0x27, 0x06, 0x7C, 0xFC, 0xD4, 0x01, 0x3A,
-0xFF, 0x35, 0x00, 0xFE, 0xFF, 0x1C, 0x00, 0x8D, 0xFF, 0xFA, 0x00,
-0x64, 0xFE, 0x32, 0x02, 0x78, 0xFD, 0x1B, 0x02, 0xEA, 0x48, 0x50,
-0x05, 0x14, 0xFC, 0xEB, 0x02, 0x05, 0xFE, 0x27, 0x01, 0x7C, 0xFF,
-0x21, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x32, 0x00, 0x41, 0xFF, 0xBF,
-0x01, 0xB2, 0xFC, 0xA9, 0x05, 0x55, 0xF6, 0x20, 0x15, 0x42, 0x44,
-0x75, 0xF7, 0xBF, 0x02, 0x43, 0xFF, 0xFA, 0xFF, 0x36, 0x00, 0xDA,
-0xFF, 0x0A, 0x00, 0xFD, 0xFF, 0x32, 0x00, 0x46, 0xFF, 0xD1, 0x01,
-0x3F, 0xFC, 0x2B, 0x07, 0xCD, 0xF1, 0xAE, 0x2A, 0x86, 0x35, 0xB1,
-0xF1, 0x9D, 0x06, 0xCA, 0xFC, 0x6E, 0x01, 0x7B, 0xFF, 0x20, 0x00,
-0xFE, 0xFF, 0x02, 0x00, 0x05, 0x00, 0xC3, 0xFF, 0xE0, 0x00, 0xB3,
-0xFD, 0x4B, 0x05, 0x4D, 0xF3, 0x45, 0x3D, 0xE0, 0x20, 0x4F, 0xF3,
-0xD5, 0x06, 0x3D, 0xFC, 0xE6, 0x01, 0x36, 0xFF, 0x36, 0x00, 0xFD,
-0xFF, 0x13, 0x00, 0xAF, 0xFF, 0xA4, 0x00, 0x19, 0xFF, 0xDD, 0x00,
-0xF0, 0xFF, 0xD4, 0xFC, 0xC9, 0x47, 0xD8, 0x0B, 0x7C, 0xF9, 0x35,
-0x04, 0x5F, 0xFD, 0x74, 0x01, 0x5E, 0xFF, 0x29, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x2C, 0x00, 0x56, 0xFF, 0x87, 0x01, 0x34, 0xFD, 0x8F,
-0x04, 0xC0, 0xF8, 0xD9, 0x0D, 0x31, 0x47, 0x7B, 0xFB, 0x9C, 0x00,
-0x7D, 0x00, 0x4D, 0xFF, 0x8A, 0x00, 0xB9, 0xFF, 0x11, 0x00, 0xFD,
-0xFF, 0x36, 0x00, 0x38, 0xFF, 0xE6, 0x01, 0x35, 0xFC, 0xF7, 0x06,
-0xE0, 0xF2, 0x18, 0x23, 0xAB, 0x3B, 0xCC, 0xF2, 0xA8, 0x05, 0x76,
-0xFD, 0x04, 0x01, 0xB1, 0xFF, 0x0C, 0x00, 0x00, 0x00, 0xFE, 0xFF,
-0x1A, 0x00, 0x89, 0xFF, 0x53, 0x01, 0xF5, 0xFC, 0x63, 0x06, 0xE9,
-0xF1, 0x63, 0x37, 0x85, 0x28, 0x09, 0xF2, 0x27, 0x07, 0x35, 0xFC,
-0xDA, 0x01, 0x40, 0xFF, 0x34, 0x00, 0xFD, 0xFF, 0x0C, 0x00, 0xD1,
-0xFF, 0x4E, 0x00, 0xCA, 0xFF, 0x9A, 0xFF, 0x2A, 0x02, 0x83, 0xF8,
-0x3F, 0x45, 0xFB, 0x12, 0x01, 0xF7, 0x5D, 0x05, 0xD3, 0xFC, 0xB1,
-0x01, 0x46, 0xFF, 0x31, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x23, 0x00,
-0x73, 0xFF, 0x3F, 0x01, 0xD3, 0xFD, 0x4C, 0x03, 0x54, 0xFB, 0x1F,
-0x07, 0xBB, 0x48, 0x7D, 0x00, 0x33, 0xFE, 0xCF, 0x01, 0x98, 0xFE,
-0xE2, 0x00, 0x97, 0xFF, 0x19, 0x00, 0xFE, 0xFF, 0x36, 0x00, 0x38,
-0xFF, 0xDC, 0x01, 0x64, 0xFC, 0x62, 0x06, 0x93, 0xF4, 0x66, 0x1B,
-0xD9, 0x40, 0xEA, 0xF4, 0x3E, 0x04, 0x5D, 0xFE, 0x7D, 0x00, 0xF5,
-0xFF, 0xF3, 0xFF, 0x05, 0x00, 0xFD, 0xFF, 0x2A, 0x00, 0x5E, 0xFF,
-0xA6, 0x01, 0x76, 0xFC, 0x01, 0x07, 0x7D, 0xF1, 0xAD, 0x30, 0xDC,
-0x2F, 0x7F, 0xF1, 0x0C, 0x07, 0x6C, 0xFC, 0xAD, 0x01, 0x5A, 0xFF,
-0x2B, 0x00, 0xFD, 0xFF, 0x05, 0x00, 0xEF, 0xFF, 0xFE, 0xFF, 0x6C,
-0x00, 0x7B, 0xFE, 0x0C, 0x04, 0x3A, 0xF5, 0x5F, 0x41, 0x83, 0x1A,
-0xCD, 0xF4, 0x4B, 0x06, 0x6D, 0xFC, 0xD9, 0x01, 0x39, 0xFF, 0x35,
-0x00, 0xFE, 0xFF, 0x1A, 0x00, 0x93, 0xFF, 0xEC, 0x00, 0x83, 0xFE,
-0xF7, 0x01, 0xE8, 0xFD, 0x21, 0x01, 0xD2, 0x48, 0x64, 0x06, 0xA1,
-0xFB, 0x26, 0x03, 0xE7, 0xFD, 0x35, 0x01, 0x76, 0xFF, 0x22, 0x00,
-0x00, 0x00, 0xFF, 0xFF, 0x31, 0x00, 0x44, 0xFF, 0xB7, 0x01, 0xC5,
-0xFC, 0x7C, 0x05, 0xBC, 0xF6, 0xD5, 0x13, 0xDC, 0x44, 0x14, 0xF8,
-0x67, 0x02, 0x77, 0xFF, 0xDD, 0xFF, 0x44, 0x00, 0xD5, 0xFF, 0x0B,
-0x00, 0xFD, 0xFF, 0x33, 0x00, 0x42, 0xFF, 0xD7, 0x01, 0x39, 0xFC,
-0x29, 0x07, 0xEF, 0xF1, 0x62, 0x29, 0xA5, 0x36, 0xD0, 0xF1, 0x7B,
-0x06, 0xE3, 0xFC, 0x5E, 0x01, 0x83, 0xFF, 0x1D, 0x00, 0xFE, 0xFF,
-0x01, 0x00, 0x09, 0x00, 0xB8, 0xFF, 0xF6, 0x00, 0x8D, 0xFD, 0x84,
-0x05, 0xFD, 0xF2, 0x52, 0x3C, 0x35, 0x22, 0x0B, 0xF3, 0xEB, 0x06,
-0x37, 0xFC, 0xE6, 0x01, 0x37, 0xFF, 0x36, 0x00, 0xFD, 0xFF, 0x12,
-0x00, 0xB5, 0xFF, 0x94, 0x00, 0x39, 0xFF, 0xA3, 0x00, 0x58, 0x00,
-0x02, 0xFC, 0x73, 0x47, 0x0B, 0x0D, 0x0B, 0xF9, 0x6C, 0x04, 0x45,
-0xFD, 0x80, 0x01, 0x59, 0xFF, 0x2B, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x2A, 0x00, 0x5B, 0xFF, 0x7C, 0x01, 0x4E, 0xFD, 0x5A, 0x04, 0x31,
-0xF9, 0xA4, 0x0C, 0x90, 0x47, 0x47, 0xFC, 0x36, 0x00, 0xB6, 0x00,
-0x2E, 0xFF, 0x99, 0x00, 0xB3, 0xFF, 0x12, 0x00, 0xFD, 0xFF, 0x36,
-0x00, 0x37, 0xFF, 0xE6, 0x01, 0x39, 0xFC, 0xE4, 0x06, 0x21, 0xF3,
-0xC4, 0x21, 0xA5, 0x3C, 0x16, 0xF3, 0x72, 0x05, 0x9A, 0xFD, 0xEF,
-0x00, 0xBC, 0xFF, 0x08, 0x00, 0x01, 0x00, 0xFE, 0xFF, 0x1E, 0x00,
-0x80, 0xFF, 0x64, 0x01, 0xDA, 0xFC, 0x87, 0x06, 0xC5, 0xF1, 0x46,
-0x36, 0xD1, 0x29, 0xE3, 0xF1, 0x2A, 0x07, 0x3A, 0xFC, 0xD5, 0x01,
-0x44, 0xFF, 0x32, 0x00, 0xFD, 0xFF, 0x0A, 0x00, 0xD6, 0xFF, 0x3F,
-0x00, 0xE7, 0xFF, 0x65, 0xFF, 0x85, 0x02, 0xDE, 0xF7, 0xA9, 0x44,
-0x43, 0x14, 0x99, 0xF6, 0x8B, 0x05, 0xBF, 0xFC, 0xBA, 0x01, 0x43,
-0xFF, 0x32, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x22, 0x00, 0x78, 0xFF,
-0x31, 0x01, 0xF1, 0xFD, 0x12, 0x03, 0xC7, 0xFB, 0x07, 0x06, 0xDB,
-0x48, 0x73, 0x01, 0xC3, 0xFD, 0x0A, 0x02, 0x79, 0xFE, 0xF1, 0x00,
-0x91, 0xFF, 0x1B, 0x00, 0xFE, 0xFF, 0x35, 0x00, 0x39, 0xFF, 0xD7,
-0x01, 0x72, 0xFC, 0x3F, 0x06, 0xEB, 0xF4, 0x12, 0x1A, 0xA1, 0x41,
-0x63, 0xF5, 0xF3, 0x03, 0x8A, 0xFE, 0x63, 0x00, 0x02, 0x00, 0xEE,
-0xFF, 0x06, 0x00, 0xFD, 0xFF, 0x2C, 0x00, 0x58, 0xFF, 0xB1, 0x01,
-0x67, 0xFC, 0x10, 0x07, 0x81, 0xF1, 0x73, 0x2F, 0x15, 0x31, 0x7C,
-0xF1, 0xFB, 0x06, 0x7C, 0xFC, 0xA2, 0x01, 0x60, 0xFF, 0x29, 0x00,
-0xFD, 0xFF, 0x04, 0x00, 0xF4, 0xFF, 0xF1, 0xFF, 0x85, 0x00, 0x4E,
-0xFE, 0x56, 0x04, 0xC3, 0xF4, 0x95, 0x40, 0xD8, 0x1B, 0x76, 0xF4,
-0x6D, 0x06, 0x60, 0xFC, 0xDD, 0x01, 0x37, 0xFF, 0x36, 0x00, 0xFE,
-0xFF, 0x19, 0x00, 0x99, 0xFF, 0xDD, 0x00, 0xA3, 0xFE, 0xBB, 0x01,
-0x58, 0xFE, 0x2D, 0x00, 0xAF, 0x48, 0x7E, 0x07, 0x2E, 0xFB, 0x60,
-0x03, 0xC9, 0xFD, 0x43, 0x01, 0x71, 0xFF, 0x24, 0x00, 0x00, 0x00,
-0xFF, 0xFF, 0x30, 0x00, 0x48, 0xFF, 0xAE, 0x01, 0xDB, 0xFC, 0x4D,
-0x05, 0x24, 0xF7, 0x8E, 0x12, 0x6D, 0x45, 0xBC, 0xF8, 0x0C, 0x02,
-0xAC, 0xFF, 0xC0, 0xFF, 0x52, 0x00, 0xCF, 0xFF, 0x0C, 0x00, 0xFD,
-0xFF, 0x34, 0x00, 0x3F, 0xFF, 0xDC, 0x01, 0x34, 0xFC, 0x25, 0x07,
-0x18, 0xF2, 0x15, 0x28, 0xBF, 0x37, 0xF7, 0xF1, 0x56, 0x06, 0xFE,
-0xFC, 0x4D, 0x01, 0x8C, 0xFF, 0x19, 0x00, 0xFF, 0xFF, 0x00, 0x00,
-0x0D, 0x00, 0xAE, 0xFF, 0x0B, 0x01, 0x6A, 0xFD, 0xBA, 0x05, 0xB4,
-0xF2, 0x58, 0x3B, 0x8A, 0x23, 0xCB, 0xF2, 0xFD, 0x06, 0x34, 0xFC,
-0xE6, 0x01, 0x38, 0xFF, 0x36, 0x00, 0xFD, 0xFF, 0x10, 0x00, 0xBB,
-0xFF, 0x85, 0x00, 0x58, 0xFF, 0x6A, 0x00, 0xBE, 0x00, 0x38, 0xFB,
-0x0F, 0x47, 0x42, 0x0E, 0x9B, 0xF8, 0xA1, 0x04, 0x2B, 0xFD, 0x8B,
-0x01, 0x55, 0xFF, 0x2C, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x29, 0x00,
-0x5F, 0xFF, 0x70, 0x01, 0x68, 0xFD, 0x23, 0x04, 0xA2, 0xF9, 0x73,
-0x0B, 0xE4, 0x47, 0x1B, 0xFD, 0xCD, 0xFF, 0xF0, 0x00, 0x0F, 0xFF,
-0xA9, 0x00, 0xAE, 0xFF, 0x14, 0x00, 0xFD, 0xFF, 0x36, 0x00, 0x36,
-0xFF, 0xE6, 0x01, 0x3F, 0xFC, 0xCE, 0x06, 0x66, 0xF3, 0x6F, 0x20,
-0x96, 0x3D, 0x69, 0xF3, 0x38, 0x05, 0xBF, 0xFD, 0xD9, 0x00, 0xC7,
-0xFF, 0x04, 0x00, 0x02, 0x00, 0xFE, 0xFF, 0x20, 0x00, 0x78, 0xFF,
-0x74, 0x01, 0xC2, 0xFC, 0xA7, 0x06, 0xA8, 0xF1, 0x25, 0x35, 0x1B,
-0x2B, 0xC2, 0xF1, 0x2A, 0x07, 0x41, 0xFC, 0xCE, 0x01, 0x47, 0xFF,
-0x31, 0x00, 0xFD, 0xFF, 0x09, 0x00, 0xDC, 0xFF, 0x31, 0x00, 0x04,
-0x00, 0x32, 0xFF, 0xDC, 0x02, 0x42, 0xF7, 0x0B, 0x44, 0x8E, 0x15,
-0x34, 0xF6, 0xB7, 0x05, 0xAB, 0xFC, 0xC1, 0x01, 0x40, 0xFF, 0x33,
-0x00, 0xFF, 0xFF, 0x00, 0x00, 0x20, 0x00, 0x7E, 0xFF, 0x23, 0x01,
-0x0F, 0xFE, 0xD7, 0x02, 0x3B, 0xFC, 0xF5, 0x04, 0xED, 0x48, 0x70,
-0x02, 0x52, 0xFD, 0x46, 0x02, 0x5A, 0xFE, 0xFF, 0x00, 0x8B, 0xFF,
-0x1C, 0x00, 0xFE, 0xFF, 0x35, 0x00, 0x3B, 0xFF, 0xD2, 0x01, 0x81,
-0xFC, 0x1A, 0x06, 0x47, 0xF5, 0xC1, 0x18, 0x60, 0x42, 0xE4, 0xF5,
-0xA6, 0x03, 0xB9, 0xFE, 0x48, 0x00, 0x0F, 0x00, 0xE9, 0xFF, 0x07,
-0x00, 0xFD, 0xFF, 0x2E, 0x00, 0x53, 0xFF, 0xBB, 0x01, 0x5A, 0xFC,
-0x1C, 0x07, 0x8D, 0xF1, 0x34, 0x2E, 0x48, 0x32, 0x81, 0xF1, 0xE7,
-0x06, 0x8E, 0xFC, 0x96, 0x01, 0x66, 0xFF, 0x27, 0x00, 0xFD, 0xFF,
-0x04, 0x00, 0xF9, 0xFF, 0xE4, 0xFF, 0x9F, 0x00, 0x23, 0xFE, 0x9B,
-0x04, 0x55, 0xF4, 0xC0, 0x3F, 0x2C, 0x1D, 0x22, 0xF4, 0x8C, 0x06,
-0x55, 0xFC, 0xE1, 0x01, 0x37, 0xFF, 0x36, 0x00, 0xFE, 0xFF, 0x17,
-0x00, 0x9F, 0xFF, 0xCE, 0x00, 0xC2, 0xFE, 0x80, 0x01, 0xC6, 0xFE,
-0x40, 0xFF, 0x81, 0x48, 0x9E, 0x08, 0xBA, 0xFA, 0x9A, 0x03, 0xAC,
-0xFD, 0x51, 0x01, 0x6C, 0xFF, 0x25, 0x00, 0x00, 0x00, 0xFF, 0xFF,
-0x2F, 0x00, 0x4B, 0xFF, 0xA4, 0x01, 0xF1, 0xFC, 0x1D, 0x05, 0x8F,
-0xF7, 0x4A, 0x11, 0xF2, 0x45, 0x6B, 0xF9, 0xAE, 0x01, 0xE2, 0xFF,
-0xA2, 0xFF, 0x61, 0x00, 0xC9, 0xFF, 0x0D, 0x00, 0xFD, 0xFF, 0x35,
-0x00, 0x3D, 0xFF, 0xE0, 0x01, 0x32, 0xFC, 0x1D, 0x07, 0x45, 0xF2,
-0xC6, 0x26, 0xD3, 0x38, 0x24, 0xF2, 0x2D, 0x06, 0x1B, 0xFD, 0x3B,
-0x01, 0x95, 0xFF, 0x16, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x11, 0x00,
-0xA3, 0xFF, 0x20, 0x01, 0x49, 0xFD, 0xEB, 0x05, 0x74, 0xF2, 0x54,
-0x3A, 0xDD, 0x24, 0x91, 0xF2, 0x0C, 0x07, 0x32, 0xFC, 0xE4, 0x01,
-0x3A, 0xFF, 0x36, 0x00, 0xFD, 0xFF, 0x0F, 0x00, 0xC1, 0xFF, 0x76,
-0x00, 0x76, 0xFF, 0x32, 0x00, 0x22, 0x01, 0x76, 0xFA, 0xA3, 0x46,
-0x7D, 0x0F, 0x2C, 0xF8, 0xD5, 0x04, 0x13, 0xFD, 0x96, 0x01, 0x51,
-0xFF, 0x2D, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x27, 0x00, 0x64, 0xFF,
-0x63, 0x01, 0x84, 0xFD, 0xEB, 0x03, 0x14, 0xFA, 0x47, 0x0A, 0x2C,
-0x48, 0xF6, 0xFD, 0x63, 0xFF, 0x2B, 0x01, 0xF0, 0xFE, 0xB8, 0x00,
-0xA8, 0xFF, 0x15, 0x00, 0xFD, 0xFF, 0x36, 0x00, 0x36, 0xFF, 0xE4,
-0x01, 0x47, 0xFC, 0xB5, 0x06, 0xB0, 0xF3, 0x19, 0x1F, 0x7E, 0x3E,
-0xC4, 0xF3, 0xFA, 0x04, 0xE7, 0xFD, 0xC1, 0x00, 0xD3, 0xFF, 0xFF,
-0xFF, 0x02, 0x00, 0xFE, 0xFF, 0x23, 0x00, 0x71, 0xFF, 0x82, 0x01,
-0xAB, 0xFC, 0xC4, 0x06, 0x93, 0xF1, 0xFD, 0x33, 0x62, 0x2C, 0xA8,
-0xF1, 0x27, 0x07, 0x4A, 0xFC, 0xC7, 0x01, 0x4C, 0xFF, 0x30, 0x00,
-0xFD, 0xFF, 0x08, 0x00, 0xE1, 0xFF, 0x23, 0x00, 0x20, 0x00, 0x00,
-0xFF, 0x31, 0x03, 0xAD, 0xF6, 0x65, 0x43, 0xDC, 0x16, 0xD1, 0xF5,
-0xE1, 0x05, 0x99, 0xFC, 0xC9, 0x01, 0x3E, 0xFF, 0x33, 0x00, 0xFF,
-0xFF, 0x00, 0x00, 0x1F, 0x00, 0x83, 0xFF, 0x14, 0x01, 0x2D, 0xFE,
-0x9C, 0x02, 0xAD, 0xFC, 0xE9, 0x03, 0xF6, 0x48, 0x73, 0x03, 0xE0,
-0xFC, 0x82, 0x02, 0x3B, 0xFE, 0x0E, 0x01, 0x86, 0xFF, 0x1E, 0x00,
-0xFE, 0xFF, 0x34, 0x00, 0x3D, 0xFF, 0xCC, 0x01, 0x91, 0xFC, 0xF3,
-0x05, 0xA6, 0xF5, 0x70, 0x17, 0x17, 0x43, 0x6D, 0xF6, 0x56, 0x03,
-0xEA, 0xFE, 0x2D, 0x00, 0x1D, 0x00, 0xE4, 0xFF, 0x08, 0x00, 0xFD,
-0xFF, 0x2F, 0x00, 0x4E, 0xFF, 0xC3, 0x01, 0x4E, 0xFC, 0x24, 0x07,
-0x9E, 0xF1, 0xF2, 0x2C, 0x78, 0x33, 0x8C, 0xF1, 0xD0, 0x06, 0xA2,
-0xFC, 0x88, 0x01, 0x6D, 0xFF, 0x24, 0x00, 0xFD, 0xFF, 0x03, 0x00,
-0xFD, 0xFF, 0xD8, 0xFF, 0xB7, 0x00, 0xF9, 0xFD, 0xDE, 0x04, 0xEF,
-0xF3, 0xE4, 0x3E, 0x81, 0x1E, 0xD2, 0xF3, 0xA9, 0x06, 0x4B, 0xFC,
-0xE3, 0x01, 0x36, 0xFF, 0x36, 0x00, 0xFE, 0xFF, 0x16, 0x00, 0xA5,
-0xFF, 0xBE, 0x00, 0xE2, 0xFE, 0x45, 0x01, 0x33, 0xFF, 0x5A, 0xFE,
-0x48, 0x48, 0xC3, 0x09, 0x47, 0xFA, 0xD2, 0x03, 0x90, 0xFD, 0x5E,
-0x01, 0x66, 0xFF, 0x27, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x2E, 0x00,
-0x4F, 0xFF, 0x9A, 0x01, 0x08, 0xFD, 0xEB, 0x04, 0xFC, 0xF7, 0x0A,
-0x10, 0x70, 0x46, 0x22, 0xFA, 0x4D, 0x01, 0x19, 0x00, 0x84, 0xFF,
-0x70, 0x00, 0xC4, 0xFF, 0x0F, 0x00, 0xFD, 0xFF, 0x35, 0x00, 0x3B,
-0xFF, 0xE3, 0x01, 0x31, 0xFC, 0x12, 0x07, 0x79, 0xF2, 0x73, 0x25,
-0xDF, 0x39, 0x5A, 0xF2, 0x00, 0x06, 0x3A, 0xFD, 0x28, 0x01, 0x9F,
-0xFF, 0x13, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x15, 0x00, 0x99, 0xFF,
-0x33, 0x01, 0x29, 0xFD, 0x1A, 0x06, 0x3B, 0xF2, 0x4B, 0x39, 0x30,
-0x26, 0x5B, 0xF2, 0x19, 0x07, 0x31, 0xFC, 0xE1, 0x01, 0x3C, 0xFF,
-0x35, 0x00, 0xFD, 0xFF, 0x0E, 0x00, 0xC7, 0xFF, 0x68, 0x00, 0x95,
-0xFF, 0xFA, 0xFF, 0x83, 0x01, 0xBB, 0xF9, 0x2B, 0x46, 0xBB, 0x10,
-0xBF, 0xF7, 0x07, 0x05, 0xFB, 0xFC, 0xA0, 0x01, 0x4D, 0xFF, 0x2F,
-0x00, 0xFF, 0xFF, 0x00, 0x00, 0x26, 0x00, 0x69, 0xFF, 0x56, 0x01,
-0xA0, 0xFD, 0xB3, 0x03, 0x87, 0xFA, 0x1F, 0x09, 0x6A, 0x48, 0xD9,
-0xFE, 0xF6, 0xFE, 0x65, 0x01, 0xD0, 0xFE, 0xC7, 0x00, 0xA2, 0xFF,
-0x17, 0x00, 0xFE, 0xFF, 0x36, 0x00, 0x36, 0xFF, 0xE2, 0x01, 0x50,
-0xFC, 0x99, 0x06, 0xFE, 0xF3, 0xC3, 0x1D, 0x5E, 0x3F, 0x27, 0xF4,
-0xB9, 0x04, 0x10, 0xFE, 0xA9, 0x00, 0xDF, 0xFF, 0xFB, 0xFF, 0x03,
-0x00, 0xFD, 0xFF, 0x26, 0x00, 0x69, 0xFF, 0x90, 0x01, 0x96, 0xFC,
-0xDD, 0x06, 0x85, 0xF1, 0xD0, 0x32, 0xA6, 0x2D, 0x94, 0xF1, 0x20,
-0x07, 0x54, 0xFC, 0xBF, 0x01, 0x50, 0xFF, 0x2E, 0x00, 0xFD, 0xFF,
-0x07, 0x00, 0xE6, 0xFF, 0x15, 0x00, 0x3C, 0x00, 0xCF, 0xFE, 0x83,
-0x03, 0x20, 0xF6, 0xB2, 0x42, 0x2B, 0x18, 0x71, 0xF5, 0x09, 0x06,
-0x88, 0xFC, 0xCF, 0x01, 0x3C, 0xFF, 0x34, 0x00, 0xFE, 0xFF, 0x1D,
-0x00, 0x89, 0xFF, 0x06, 0x01, 0x4C, 0xFE, 0x60, 0x02, 0x1F, 0xFD,
-0xE2, 0x02, 0xF3, 0x48, 0x7D, 0x04, 0x6E, 0xFC, 0xBD, 0x02, 0x1C,
-0xFE, 0x1C, 0x01, 0x80, 0xFF, 0x20, 0x00, 0x00, 0x00, 0xFF, 0xFF,
-0x33, 0x00, 0x3F, 0xFF, 0xC5, 0x01, 0xA3, 0xFC, 0xCA, 0x05, 0x07,
-0xF6, 0x22, 0x16, 0xC3, 0x43, 0xFE, 0xF6, 0x02, 0x03, 0x1B, 0xFF,
-0x11, 0x00, 0x2B, 0x00, 0xDE, 0xFF, 0x09, 0x00, 0xFD, 0xFF, 0x31,
-0x00, 0x49, 0xFF, 0xCB, 0x01, 0x45, 0xFC, 0x29, 0x07, 0xB6, 0xF1,
-0xAD, 0x2B, 0xA2, 0x34, 0x9E, 0xF1, 0xB4, 0x06, 0xB8, 0xFC, 0x7A,
-0x01, 0x75, 0xFF, 0x22, 0x00, 0xFE, 0xFF, 0x02, 0x00, 0x02, 0x00,
-0xCC, 0xFF, 0xCE, 0x00, 0xD1, 0xFD, 0x1D, 0x05, 0x91, 0xF3, 0xFE,
-0x3D, 0xD7, 0x1F, 0x87, 0xF3, 0xC3, 0x06, 0x42, 0xFC, 0xE5, 0x01,
-0x36, 0xFF, 0x36, 0x00, 0xFD, 0xFF, 0x14, 0x00, 0xAB, 0xFF, 0xAF,
-0x00, 0x01, 0xFF, 0x0A, 0x01, 0x9E, 0xFF, 0x7C, 0xFD, 0x03, 0x48,
-0xED, 0x0A, 0xD5, 0xF9, 0x0A, 0x04, 0x74, 0xFD, 0x6A, 0x01, 0x62,
-0xFF, 0x28, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x2D, 0x00, 0x53, 0xFF,
-0x90, 0x01, 0x20, 0xFD, 0xB8, 0x04, 0x6A, 0xF8, 0xCD, 0x0E, 0xE1,
-0x46, 0xE1, 0xFA, 0xEB, 0x00, 0x51, 0x00, 0x65, 0xFF, 0x7F, 0x00,
-0xBE, 0xFF, 0x10, 0x00, 0xFD, 0xFF, 0x36, 0x00, 0x39, 0xFF, 0xE5,
-0x01, 0x33, 0xFC, 0x04, 0x07, 0xB1, 0xF2, 0x21, 0x24, 0xE6, 0x3A,
-0x97, 0xF2, 0xD0, 0x05, 0x5B, 0xFD, 0x15, 0x01, 0xA9, 0xFF, 0x0F,
-0x00, 0x00, 0x00, 0xFF, 0xFF, 0x18, 0x00, 0x90, 0xFF, 0x45, 0x01,
-0x0B, 0xFD, 0x44, 0x06, 0x0A, 0xF2, 0x3B, 0x38, 0x80, 0x27, 0x2B,
-0xF2, 0x22, 0x07, 0x33, 0xFC, 0xDE, 0x01, 0x3E, 0xFF, 0x34, 0x00,
-0xFD, 0xFF, 0x0D, 0x00, 0xCD, 0xFF, 0x59, 0x00, 0xB3, 0xFF, 0xC4,
-0xFF, 0xE2, 0x01, 0x09, 0xF9, 0xAA, 0x45, 0xFE, 0x11, 0x54, 0xF7,
-0x38, 0x05, 0xE4, 0xFC, 0xAA, 0x01, 0x49, 0xFF, 0x30, 0x00, 0xFF,
-0xFF, 0x00, 0x00, 0x24, 0x00, 0x6E, 0xFF, 0x49, 0x01, 0xBC, 0xFD,
-0x7A, 0x03, 0xFA, 0xFA, 0xFD, 0x07, 0x9C, 0x48, 0xC3, 0xFF, 0x89,
-0xFE, 0xA1, 0x01, 0xB1, 0xFE, 0xD6, 0x00, 0x9C, 0xFF, 0x18, 0x00,
-0xFE, 0xFF, 0x36, 0x00, 0x37, 0xFF, 0xDF, 0x01, 0x5B, 0xFC, 0x7B,
-0x06, 0x50, 0xF4, 0x6E, 0x1C, 0x36, 0x40, 0x92, 0xF4, 0x75, 0x04,
-0x3B, 0xFE, 0x91, 0x00, 0xEB, 0xFF, 0xF6, 0xFF, 0x04, 0x00, 0xFD,
-0xFF, 0x28, 0x00, 0x63, 0xFF, 0x9D, 0x01, 0x84, 0xFC, 0xF3, 0x06,
-0x7D, 0xF1, 0x9E, 0x31, 0xE6, 0x2E, 0x85, 0xF1, 0x16, 0x07, 0x61,
-0xFC, 0xB5, 0x01, 0x55, 0xFF, 0x2D, 0x00, 0xFD, 0xFF, 0x06, 0x00,
-0xEC, 0xFF, 0x08, 0x00, 0x57, 0x00, 0x9F, 0xFE, 0xD1, 0x03, 0x9B,
-0xF5, 0xF7, 0x41, 0x7C, 0x19, 0x13, 0xF5, 0x2F, 0x06, 0x78, 0xFC,
-0xD5, 0x01, 0x3A, 0xFF, 0x35, 0x00, 0xFE, 0xFF, 0x1C, 0x00, 0x8F,
-0xFF, 0xF7, 0x00, 0x6B, 0xFE, 0x25, 0x02, 0x91, 0xFD, 0xE3, 0x01,
-0xE5, 0x48, 0x8D, 0x05, 0xFB, 0xFB, 0xF8, 0x02, 0xFE, 0xFD, 0x2B,
-0x01, 0x7A, 0xFF, 0x21, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x32, 0x00,
-0x42, 0xFF, 0xBD, 0x01, 0xB6, 0xFC, 0x9F, 0x05, 0x6C, 0xF6, 0xD6,
-0x14, 0x65, 0x44, 0x98, 0xF7, 0xAC, 0x02, 0x4E, 0xFF, 0xF4, 0xFF,
-0x39, 0x00, 0xD9, 0xFF, 0x0A, 0x00, 0xFD, 0xFF, 0x32, 0x00, 0x45,
-0xFF, 0xD2, 0x01, 0x3D, 0xFC, 0x2B, 0x07, 0xD4, 0xF1, 0x64, 0x2A,
-0xC6, 0x35, 0xB7, 0xF1, 0x96, 0x06, 0xCF, 0xFC, 0x6B, 0x01, 0x7D,
-0xFF, 0x1F, 0x00, 0xFE, 0xFF, 0x01, 0x00, 0x06, 0x00, 0xC1, 0xFF,
-0xE5, 0x00, 0xAA, 0xFD, 0x58, 0x05, 0x3A, 0xF3, 0x11, 0x3D, 0x2C,
-0x21, 0x3F, 0xF3, 0xDA, 0x06, 0x3B, 0xFC, 0xE6, 0x01, 0x36, 0xFF,
-0x36, 0x00, 0xFD, 0xFF, 0x13, 0x00, 0xB1, 0xFF, 0xA0, 0x00, 0x20,
-0xFF, 0xD0, 0x00, 0x07, 0x00, 0xA4, 0xFC, 0xB6, 0x47, 0x1C, 0x0C,
-0x63, 0xF9, 0x42, 0x04, 0x59, 0xFD, 0x76, 0x01, 0x5D, 0xFF, 0x2A,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x2B, 0x00, 0x57, 0xFF, 0x85, 0x01,
-0x39, 0xFD, 0x84, 0x04, 0xD9, 0xF8, 0x95, 0x0D, 0x48, 0x47, 0xA7,
-0xFB, 0x86, 0x00, 0x8A, 0x00, 0x46, 0xFF, 0x8E, 0x00, 0xB8, 0xFF,
-0x11, 0x00, 0xFD, 0xFF, 0x36, 0x00, 0x37, 0xFF, 0xE6, 0x01, 0x35,
-0xFC, 0xF3, 0x06, 0xEE, 0xF2, 0xCD, 0x22, 0xE4, 0x3B, 0xDC, 0xF2,
-0x9C, 0x05, 0x7E, 0xFD, 0x00, 0x01, 0xB4, 0xFF, 0x0B, 0x00, 0x01,
-0x00, 0xFE, 0xFF, 0x1B, 0x00, 0x87, 0xFF, 0x57, 0x01, 0xEF, 0xFC,
-0x6B, 0x06, 0xE0, 0xF1, 0x23, 0x37, 0xCE, 0x28, 0x01, 0xF2, 0x28,
-0x07, 0x36, 0xFC, 0xD9, 0x01, 0x41, 0xFF, 0x33, 0x00, 0xFD, 0xFF,
-0x0B, 0x00, 0xD2, 0xFF, 0x4A, 0x00, 0xD0, 0xFF, 0x8E, 0xFF, 0x3F,
-0x02, 0x5E, 0xF8, 0x1E, 0x45, 0x44, 0x13, 0xEA, 0xF6, 0x67, 0x05,
-0xCF, 0xFC, 0xB3, 0x01, 0x46, 0xFF, 0x31, 0x00, 0xFF, 0xFF, 0x00,
-0x00, 0x23, 0x00, 0x74, 0xFF, 0x3C, 0x01, 0xDA, 0xFD, 0x40, 0x03,
-0x6E, 0xFB, 0xE1, 0x06, 0xC3, 0x48, 0xB3, 0x00, 0x1A, 0xFE, 0xDC,
-0x01, 0x91, 0xFE, 0xE5, 0x00, 0x96, 0xFF, 0x1A, 0x00, 0xFE, 0xFF,
-0x36, 0x00, 0x38, 0xFF, 0xDB, 0x01, 0x67, 0xFC, 0x5A, 0x06, 0xA6,
-0xF4, 0x1B, 0x1B, 0x07, 0x41, 0x04, 0xF5, 0x2D, 0x04, 0x67, 0xFE,
-0x77, 0x00, 0xF8, 0xFF, 0xF2, 0xFF, 0x05, 0x00, 0xFD, 0xFF, 0x2A,
-0x00, 0x5C, 0xFF, 0xA8, 0x01, 0x73, 0xFC, 0x05, 0x07, 0x7D, 0xF1,
-0x67, 0x30, 0x21, 0x30, 0x7E, 0xF1, 0x08, 0x07, 0x6F, 0xFC, 0xAB,
-0x01, 0x5B, 0xFF, 0x2B, 0x00, 0xFD, 0xFF, 0x05, 0x00, 0xF0, 0xFF,
-0xFB, 0xFF, 0x71, 0x00, 0x71, 0xFE, 0x1D, 0x04, 0x1F, 0xF5, 0x32,
-0x41, 0xCE, 0x1A, 0xBA, 0xF4, 0x53, 0x06, 0x6A, 0xFC, 0xDA, 0x01,
-0x38, 0xFF, 0x35, 0x00, 0xFE, 0xFF, 0x1A, 0x00, 0x95, 0xFF, 0xE8,
-0x00, 0x8A, 0xFE, 0xE9, 0x01, 0x01, 0xFE, 0xEA, 0x00, 0xCB, 0x48,
-0xA2, 0x06, 0x87, 0xFB, 0x33, 0x03, 0xE0, 0xFD, 0x39, 0x01, 0x75,
-0xFF, 0x23, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x31, 0x00, 0x45, 0xFF,
-0xB5, 0x01, 0xCA, 0xFC, 0x72, 0x05, 0xD3, 0xF6, 0x8D, 0x13, 0xFD,
-0x44, 0x39, 0xF8, 0x53, 0x02, 0x82, 0xFF, 0xD7, 0xFF, 0x47, 0x00,
-0xD3, 0xFF, 0x0B, 0x00, 0xFD, 0xFF, 0x33, 0x00, 0x42, 0xFF, 0xD8,
-0x01, 0x37, 0xFC, 0x29, 0x07, 0xF8, 0xF1, 0x19, 0x29, 0xE5, 0x36,
-0xD8, 0xF1, 0x73, 0x06, 0xE9, 0xFC, 0x5B, 0x01, 0x85, 0xFF, 0x1C,
-0x00, 0xFE, 0xFF, 0x01, 0x00, 0x0A, 0x00, 0xB6, 0xFF, 0xFB, 0x00,
-0x85, 0xFD, 0x90, 0x05, 0xEC, 0xF2, 0x1C, 0x3C, 0x81, 0x22, 0xFC,
-0xF2, 0xEF, 0x06, 0x36, 0xFC, 0xE6, 0x01, 0x37, 0xFF, 0x36, 0x00,
-0xFD, 0xFF, 0x12, 0x00, 0xB7, 0xFF, 0x91, 0x00, 0x40, 0xFF, 0x96,
-0x00, 0x6F, 0x00, 0xD5, 0xFB, 0x5E, 0x47, 0x50, 0x0D, 0xF2, 0xF8,
-0x78, 0x04, 0x3F, 0xFD, 0x82, 0x01, 0x58, 0xFF, 0x2B, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x2A, 0x00, 0x5C, 0xFF, 0x79, 0x01, 0x53, 0xFD,
-0x4E, 0x04, 0x4A, 0xF9, 0x60, 0x0C, 0xA3, 0x47, 0x76, 0xFC, 0x1F,
-0x00, 0xC3, 0x00, 0x27, 0xFF, 0x9D, 0x00, 0xB2, 0xFF, 0x13, 0x00,
-0xFD, 0xFF, 0x36, 0x00, 0x37, 0xFF, 0xE6, 0x01, 0x3A, 0xFC, 0xDF,
-0x06, 0x30, 0xF3, 0x78, 0x21, 0xDB, 0x3C, 0x28, 0xF3, 0x65, 0x05,
-0xA2, 0xFD, 0xEA, 0x00, 0xBE, 0xFF, 0x07, 0x00, 0x01, 0x00, 0xFE,
-0xFF, 0x1E, 0x00, 0x7F, 0xFF, 0x67, 0x01, 0xD5, 0xFC, 0x8E, 0x06,
-0xBE, 0xF1, 0x06, 0x36, 0x1A, 0x2A, 0xDC, 0xF1, 0x2A, 0x07, 0x3C,
-0xFC, 0xD3, 0x01, 0x44, 0xFF, 0x32, 0x00, 0xFD, 0xFF, 0x0A, 0x00,
-0xD8, 0xFF, 0x3C, 0x00, 0xEE, 0xFF, 0x5A, 0xFF, 0x98, 0x02, 0xBB,
-0xF7, 0x87, 0x44, 0x8C, 0x14, 0x83, 0xF6, 0x95, 0x05, 0xBA, 0xFC,
-0xBB, 0x01, 0x43, 0xFF, 0x32, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x21,
-0x00, 0x79, 0xFF, 0x2E, 0x01, 0xF7, 0xFD, 0x05, 0x03, 0xE1, 0xFB,
-0xCA, 0x05, 0xDF, 0x48, 0xAB, 0x01, 0xAA, 0xFD, 0x18, 0x02, 0x72,
-0xFE, 0xF4, 0x00, 0x90, 0xFF, 0x1B, 0x00, 0xFE, 0xFF, 0x35, 0x00,
-0x39, 0xFF, 0xD6, 0x01, 0x75, 0xFC, 0x37, 0x06, 0xFF, 0xF4, 0xC7,
-0x19, 0xCC, 0x41, 0x7F, 0xF5, 0xE2, 0x03, 0x95, 0xFE, 0x5D, 0x00,
-0x05, 0x00, 0xED, 0xFF, 0x06, 0x00, 0xFD, 0xFF, 0x2C, 0x00, 0x57,
-0xFF, 0xB3, 0x01, 0x64, 0xFC, 0x13, 0x07, 0x83, 0xF1, 0x2C, 0x2F,
-0x5A, 0x31, 0x7D, 0xF1, 0xF7, 0x06, 0x80, 0xFC, 0x9F, 0x01, 0x61,
-0xFF, 0x29, 0x00, 0xFD, 0xFF, 0x04, 0x00, 0xF5, 0xFF, 0xEE, 0xFF,
-0x8B, 0x00, 0x44, 0xFE, 0x65, 0x04, 0xAA, 0xF4, 0x66, 0x40, 0x23,
-0x1C, 0x63, 0xF4, 0x74, 0x06, 0x5D, 0xFC, 0xDE, 0x01, 0x37, 0xFF,
-0x36, 0x00, 0xFE, 0xFF, 0x19, 0x00, 0x9A, 0xFF, 0xD9, 0x00, 0xAA,
-0xFE, 0xAE, 0x01, 0x70, 0xFE, 0xF8, 0xFF, 0xA6, 0x48, 0xBE, 0x07,
-0x14, 0xFB, 0x6D, 0x03, 0xC3, 0xFD, 0x46, 0x01, 0x70, 0xFF, 0x24,
-0x00, 0x00, 0x00, 0xFF, 0xFF, 0x30, 0x00, 0x48, 0xFF, 0xAC, 0x01,
-0xDF, 0xFC, 0x43, 0x05, 0x3C, 0xF7, 0x46, 0x12, 0x8D, 0x45, 0xE2,
-0xF8, 0xF7, 0x01, 0xB8, 0xFF, 0xB9, 0xFF, 0x56, 0x00, 0xCE, 0xFF,
-0x0C, 0x00, 0xFD, 0xFF, 0x34, 0x00, 0x3F, 0xFF, 0xDD, 0x01, 0x34,
-0xFC, 0x23, 0x07, 0x21, 0xF2, 0xCB, 0x27, 0xFE, 0x37, 0x00, 0xF2,
-0x4D, 0x06, 0x04, 0xFD, 0x49, 0x01, 0x8E, 0xFF, 0x19, 0x00, 0xFF,
-0xFF, 0x00, 0x00, 0x0E, 0x00, 0xAB, 0xFF, 0x10, 0x01, 0x62, 0xFD,
-0xC5, 0x05, 0xA5, 0xF2, 0x1F, 0x3B, 0xD6, 0x23, 0xBE, 0xF2, 0x01,
-0x07, 0x33, 0xFC, 0xE5, 0x01, 0x38, 0xFF, 0x36, 0x00, 0xFD, 0xFF,
-0x10, 0x00, 0xBD, 0xFF, 0x82, 0x00, 0x5E, 0xFF, 0x5D, 0x00, 0xD4,
-0x00, 0x0C, 0xFB, 0xF9, 0x46, 0x87, 0x0E, 0x82, 0xF8, 0xAD, 0x04,
-0x26, 0xFD, 0x8D, 0x01, 0x54, 0xFF, 0x2C, 0x00, 0xFF, 0xFF, 0x00,
-0x00, 0x29, 0x00, 0x60, 0xFF, 0x6D, 0x01, 0x6E, 0xFD, 0x17, 0x04,
-0xBC, 0xF9, 0x30, 0x0B, 0xF4, 0x47, 0x4B, 0xFD, 0xB5, 0xFF, 0xFD,
-0x00, 0x08, 0xFF, 0xAC, 0x00, 0xAC, 0xFF, 0x14, 0x00, 0xFD, 0xFF,
-0x36, 0x00, 0x36, 0xFF, 0xE6, 0x01, 0x41, 0xFC, 0xC8, 0x06, 0x76,
-0xF3, 0x22, 0x20, 0xCA, 0x3D, 0x7D, 0xF3, 0x2A, 0x05, 0xC8, 0xFD,
-0xD4, 0x00, 0xCA, 0xFF, 0x03, 0x00, 0x02, 0x00, 0xFE, 0xFF, 0x21,
-0x00, 0x77, 0xFF, 0x77, 0x01, 0xBD, 0xFC, 0xAE, 0x06, 0xA3, 0xF1,
-0xE3, 0x34, 0x64, 0x2B, 0xBC, 0xF1, 0x2A, 0x07, 0x43, 0xFC, 0xCD,
-0x01, 0x48, 0xFF, 0x31, 0x00, 0xFD, 0xFF, 0x09, 0x00, 0xDD, 0xFF,
-0x2E, 0x00, 0x0A, 0x00, 0x27, 0xFF, 0xEF, 0x02, 0x20, 0xF7, 0xE7,
-0x43, 0xD8, 0x15, 0x1E, 0xF6, 0xC0, 0x05, 0xA7, 0xFC, 0xC3, 0x01,
-0x40, 0xFF, 0x33, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x20, 0x00, 0x7F,
-0xFF, 0x20, 0x01, 0x16, 0xFE, 0xCA, 0x02, 0x54, 0xFC, 0xB9, 0x04,
-0xF2, 0x48, 0xA9, 0x02, 0x39, 0xFD, 0x53, 0x02, 0x53, 0xFE, 0x03,
-0x01, 0x8A, 0xFF, 0x1D, 0x00, 0xFE, 0xFF, 0x34, 0x00, 0x3B, 0xFF,
-0xD1, 0x01, 0x84, 0xFC, 0x12, 0x06, 0x5C, 0xF5, 0x76, 0x18, 0x89,
-0x42, 0x02, 0xF6, 0x94, 0x03, 0xC4, 0xFE, 0x42, 0x00, 0x12, 0x00,
-0xE8, 0xFF, 0x07, 0x00, 0xFD, 0xFF, 0x2E, 0x00, 0x51, 0xFF, 0xBD,
-0x01, 0x57, 0xFC, 0x1E, 0x07, 0x90, 0xF1, 0xED, 0x2D, 0x8C, 0x32,
-0x83, 0xF1, 0xE2, 0x06, 0x92, 0xFC, 0x93, 0x01, 0x68, 0xFF, 0x26,
-0x00, 0xFD, 0xFF, 0x03, 0x00, 0xFA, 0xFF, 0xE2, 0xFF, 0xA4, 0x00,
-0x19, 0xFE, 0xAA, 0x04, 0x3E, 0xF4, 0x90, 0x3F, 0x78, 0x1D, 0x10,
-0xF4, 0x93, 0x06, 0x52, 0xFC, 0xE1, 0x01, 0x36, 0xFF, 0x36, 0x00,
-0xFE, 0xFF, 0x17, 0x00, 0xA0, 0xFF, 0xCA, 0x00, 0xC9, 0xFE, 0x73,
-0x01, 0xDE, 0xFE, 0x0C, 0xFF, 0x76, 0x48, 0xDE, 0x08, 0xA1, 0xFA,
-0xA6, 0x03, 0xA6, 0xFD, 0x53, 0x01, 0x6A, 0xFF, 0x26, 0x00, 0x00,
-0x00, 0xFF, 0xFF, 0x2F, 0x00, 0x4C, 0xFF, 0xA2, 0x01, 0xF6, 0xFC,
-0x12, 0x05, 0xA7, 0xF7, 0x03, 0x11, 0x10, 0x46, 0x93, 0xF9, 0x98,
-0x01, 0xEE, 0xFF, 0x9B, 0xFF, 0x64, 0x00, 0xC8, 0xFF, 0x0E, 0x00,
-0xFD, 0xFF, 0x35, 0x00, 0x3C, 0xFF, 0xE1, 0x01, 0x32, 0xFC, 0x1B,
-0x07, 0x50, 0xF2, 0x7B, 0x26, 0x11, 0x39, 0x2F, 0xF2, 0x23, 0x06,
-0x22, 0xFD, 0x37, 0x01, 0x97, 0xFF, 0x15, 0x00, 0xFF, 0xFF, 0x00,
-0x00, 0x12, 0x00, 0xA1, 0xFF, 0x24, 0x01, 0x41, 0xFD, 0xF6, 0x05,
-0x67, 0xF2, 0x1A, 0x3A, 0x29, 0x25, 0x84, 0xF2, 0x0F, 0x07, 0x31,
-0xFC, 0xE3, 0x01, 0x3A, 0xFF, 0x35, 0x00, 0xFD, 0xFF, 0x0F, 0x00,
-0xC2, 0xFF, 0x73, 0x00, 0x7D, 0xFF, 0x25, 0x00, 0x38, 0x01, 0x4C,
-0xFA, 0x89, 0x46, 0xC3, 0x0F, 0x14, 0xF8, 0xE0, 0x04, 0x0D, 0xFD,
-0x98, 0x01, 0x50, 0xFF, 0x2E, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x27,
-0x00, 0x65, 0xFF, 0x60, 0x01, 0x8A, 0xFD, 0xDF, 0x03, 0x2E, 0xFA,
-0x04, 0x0A, 0x3A, 0x48, 0x28, 0xFE, 0x4B, 0xFF, 0x38, 0x01, 0xE9,
-0xFE, 0xBB, 0x00, 0xA6, 0xFF, 0x16, 0x00, 0xFE, 0xFF, 0x36, 0x00,
-0x36, 0xFF, 0xE4, 0x01, 0x49, 0xFC, 0xAF, 0x06, 0xC1, 0xF3, 0xCD,
-0x1E, 0xB1, 0x3E, 0xD9, 0xF3, 0xEC, 0x04, 0xF0, 0xFD, 0xBC, 0x00,
-0xD5, 0xFF, 0xFE, 0xFF, 0x03, 0x00, 0xFD, 0xFF, 0x24, 0x00, 0x6F,
-0xFF, 0x85, 0x01, 0xA6, 0xFC, 0xCA, 0x06, 0x8F, 0xF1, 0xBB, 0x33,
-0xAB, 0x2C, 0xA3, 0xF1, 0x26, 0x07, 0x4C, 0xFC, 0xC5, 0x01, 0x4D,
-0xFF, 0x30, 0x00, 0xFD, 0xFF, 0x08, 0x00, 0xE2, 0xFF, 0x20, 0x00,
-0x26, 0x00, 0xF5, 0xFE, 0x43, 0x03, 0x8D, 0xF6, 0x3C, 0x43, 0x25,
-0x17, 0xBB, 0xF5, 0xEA, 0x05, 0x95, 0xFC, 0xCA, 0x01, 0x3D, 0xFF,
-0x34, 0x00, 0xFE, 0xFF, 0x00, 0x00, 0x1E, 0x00, 0x84, 0xFF, 0x11,
-0x01, 0x34, 0xFE, 0x8F, 0x02, 0xC7, 0xFC, 0xAE, 0x03, 0xF7, 0x48,
-0xAE, 0x03, 0xC7, 0xFC, 0x8F, 0x02, 0x34, 0xFE, 0x11, 0x01, 0x84,
-0xFF, 0x1E, 0x00, 0xFD, 0xFF, 0x36, 0x00, 0x36, 0xFF, 0xE6, 0x01,
-0x3D, 0xFC, 0xD6, 0x06, 0x4C, 0xF3, 0xED, 0x20, 0x3D, 0x3D, 0x4A,
-0xF3, 0x4E, 0x05, 0xB1, 0xFD, 0xE1, 0x00, 0xC3, 0xFF, 0x05, 0x00,
-0x02, 0x00, 0x02, 0x00, 0x05, 0x00, 0xC3, 0xFF, 0xE1, 0x00, 0xB1,
-0xFD, 0x4E, 0x05, 0x4A, 0xF3, 0x3D, 0x3D, 0xED, 0x20, 0x4C, 0xF3,
-0xD6, 0x06, 0x3D, 0xFC, 0xE6, 0x01, 0x36, 0xFF, 0x36, 0x00, 0xFD,
-0xFF, 0x00, 0x00, 0x1E, 0x00, 0x84, 0xFF, 0x11, 0x01, 0x34, 0xFE,
-0x8F, 0x02, 0xC7, 0xFC, 0xAE, 0x03, 0xF7, 0x48, 0xAE, 0x03, 0xC7,
-0xFC, 0x8F, 0x02, 0x34, 0xFE, 0x11, 0x01, 0x84, 0xFF, 0x1E, 0x00,
-0xFD, 0xFF, 0x30, 0x00, 0x4D, 0xFF, 0xC5, 0x01, 0x4C, 0xFC, 0x26,
-0x07, 0xA3, 0xF1, 0xAB, 0x2C, 0xBB, 0x33, 0x8F, 0xF1, 0xCA, 0x06,
-0xA6, 0xFC, 0x85, 0x01, 0x6F, 0xFF, 0x24, 0x00, 0xFD, 0xFF, 0x16,
-0x00, 0xA6, 0xFF, 0xBB, 0x00, 0xE9, 0xFE, 0x38, 0x01, 0x4B, 0xFF,
-0x28, 0xFE, 0x3A, 0x48, 0x04, 0x0A, 0x2E, 0xFA, 0xDF, 0x03, 0x8A,
-0xFD, 0x60, 0x01, 0x65, 0xFF, 0x27, 0x00, 0x00, 0x00, 0xFD, 0xFF,
-0x35, 0x00, 0x3A, 0xFF, 0xE3, 0x01, 0x31, 0xFC, 0x0F, 0x07, 0x84,
-0xF2, 0x29, 0x25, 0x1A, 0x3A, 0x67, 0xF2, 0xF6, 0x05, 0x41, 0xFD,
-0x24, 0x01, 0xA1, 0xFF, 0x12, 0x00, 0x00, 0x00, 0x0E, 0x00, 0xC8,
-0xFF, 0x64, 0x00, 0x9B, 0xFF, 0xEE, 0xFF, 0x98, 0x01, 0x93, 0xF9,
-0x10, 0x46, 0x03, 0x11, 0xA7, 0xF7, 0x12, 0x05, 0xF6, 0xFC, 0xA2,
-0x01, 0x4C, 0xFF, 0x2F, 0x00, 0xFF, 0xFF, 0xFE, 0xFF, 0x36, 0x00,
-0x36, 0xFF, 0xE1, 0x01, 0x52, 0xFC, 0x93, 0x06, 0x10, 0xF4, 0x78,
-0x1D, 0x90, 0x3F, 0x3E, 0xF4, 0xAA, 0x04, 0x19, 0xFE, 0xA4, 0x00,
-0xE2, 0xFF, 0xFA, 0xFF, 0x03, 0x00, 0x07, 0x00, 0xE8, 0xFF, 0x12,
-0x00, 0x42, 0x00, 0xC4, 0xFE, 0x94, 0x03, 0x02, 0xF6, 0x89, 0x42,
-0x76, 0x18, 0x5C, 0xF5, 0x12, 0x06, 0x84, 0xFC, 0xD1, 0x01, 0x3B,
-0xFF, 0x34, 0x00, 0xFE, 0xFF, 0xFF, 0xFF, 0x33, 0x00, 0x40, 0xFF,
-0xC3, 0x01, 0xA7, 0xFC, 0xC0, 0x05, 0x1E, 0xF6, 0xD8, 0x15, 0xE7,
-0x43, 0x20, 0xF7, 0xEF, 0x02, 0x27, 0xFF, 0x0A, 0x00, 0x2E, 0x00,
-0xDD, 0xFF, 0x09, 0x00, 0x02, 0x00, 0x03, 0x00, 0xCA, 0xFF, 0xD4,
-0x00, 0xC8, 0xFD, 0x2A, 0x05, 0x7D, 0xF3, 0xCA, 0x3D, 0x22, 0x20,
-0x76, 0xF3, 0xC8, 0x06, 0x41, 0xFC, 0xE6, 0x01, 0x36, 0xFF, 0x36,
-0x00, 0xFD, 0xFF, 0xFF, 0xFF, 0x2C, 0x00, 0x54, 0xFF, 0x8D, 0x01,
-0x26, 0xFD, 0xAD, 0x04, 0x82, 0xF8, 0x87, 0x0E, 0xF9, 0x46, 0x0C,
-0xFB, 0xD4, 0x00, 0x5D, 0x00, 0x5E, 0xFF, 0x82, 0x00, 0xBD, 0xFF,
-0x10, 0x00, 0xFF, 0xFF, 0x19, 0x00, 0x8E, 0xFF, 0x49, 0x01, 0x04,
-0xFD, 0x4D, 0x06, 0x00, 0xF2, 0xFE, 0x37, 0xCB, 0x27, 0x21, 0xF2,
-0x23, 0x07, 0x34, 0xFC, 0xDD, 0x01, 0x3F, 0xFF, 0x34, 0x00, 0xFD,
-0xFF, 0x00, 0x00, 0x24, 0x00, 0x70, 0xFF, 0x46, 0x01, 0xC3, 0xFD,
-0x6D, 0x03, 0x14, 0xFB, 0xBE, 0x07, 0xA6, 0x48, 0xF8, 0xFF, 0x70,
-0xFE, 0xAE, 0x01, 0xAA, 0xFE, 0xD9, 0x00, 0x9A, 0xFF, 0x19, 0x00,
-0xFD, 0xFF, 0x29, 0x00, 0x61, 0xFF, 0x9F, 0x01, 0x80, 0xFC, 0xF7,
-0x06, 0x7D, 0xF1, 0x5A, 0x31, 0x2C, 0x2F, 0x83, 0xF1, 0x13, 0x07,
-0x64, 0xFC, 0xB3, 0x01, 0x57, 0xFF, 0x2C, 0x00, 0xFD, 0xFF, 0x1B,
-0x00, 0x90, 0xFF, 0xF4, 0x00, 0x72, 0xFE, 0x18, 0x02, 0xAA, 0xFD,
-0xAB, 0x01, 0xDF, 0x48, 0xCA, 0x05, 0xE1, 0xFB, 0x05, 0x03, 0xF7,
-0xFD, 0x2E, 0x01, 0x79, 0xFF, 0x21, 0x00, 0x00, 0x00, 0xFD, 0xFF,
-0x32, 0x00, 0x44, 0xFF, 0xD3, 0x01, 0x3C, 0xFC, 0x2A, 0x07, 0xDC,
-0xF1, 0x1A, 0x2A, 0x06, 0x36, 0xBE, 0xF1, 0x8E, 0x06, 0xD5, 0xFC,
-0x67, 0x01, 0x7F, 0xFF, 0x1E, 0x00, 0xFE, 0xFF, 0x13, 0x00, 0xB2,
-0xFF, 0x9D, 0x00, 0x27, 0xFF, 0xC3, 0x00, 0x1F, 0x00, 0x76, 0xFC,
-0xA3, 0x47, 0x60, 0x0C, 0x4A, 0xF9, 0x4E, 0x04, 0x53, 0xFD, 0x79,
-0x01, 0x5C, 0xFF, 0x2A, 0x00, 0x00, 0x00, 0xFD, 0xFF, 0x36, 0x00,
-0x37, 0xFF, 0xE6, 0x01, 0x36, 0xFC, 0xEF, 0x06, 0xFC, 0xF2, 0x81,
-0x22, 0x1C, 0x3C, 0xEC, 0xF2, 0x90, 0x05, 0x85, 0xFD, 0xFB, 0x00,
-0xB6, 0xFF, 0x0A, 0x00, 0x01, 0x00, 0x0B, 0x00, 0xD3, 0xFF, 0x47,
-0x00, 0xD7, 0xFF, 0x82, 0xFF, 0x53, 0x02, 0x39, 0xF8, 0xFD, 0x44,
-0x8D, 0x13, 0xD3, 0xF6, 0x72, 0x05, 0xCA, 0xFC, 0xB5, 0x01, 0x45,
-0xFF, 0x31, 0x00, 0xFF, 0xFF, 0xFE, 0xFF, 0x35, 0x00, 0x38, 0xFF,
-0xDA, 0x01, 0x6A, 0xFC, 0x53, 0x06, 0xBA, 0xF4, 0xCE, 0x1A, 0x32,
-0x41, 0x1F, 0xF5, 0x1D, 0x04, 0x71, 0xFE, 0x71, 0x00, 0xFB, 0xFF,
-0xF0, 0xFF, 0x05, 0x00, 0x05, 0x00, 0xF2, 0xFF, 0xF8, 0xFF, 0x77,
-0x00, 0x67, 0xFE, 0x2D, 0x04, 0x04, 0xF5, 0x07, 0x41, 0x1B, 0x1B,
-0xA6, 0xF4, 0x5A, 0x06, 0x67, 0xFC, 0xDB, 0x01, 0x38, 0xFF, 0x36,
-0x00, 0xFE, 0xFF, 0xFF, 0xFF, 0x31, 0x00, 0x46, 0xFF, 0xB3, 0x01,
-0xCF, 0xFC, 0x67, 0x05, 0xEA, 0xF6, 0x44, 0x13, 0x1E, 0x45, 0x5E,
-0xF8, 0x3F, 0x02, 0x8E, 0xFF, 0xD0, 0xFF, 0x4A, 0x00, 0xD2, 0xFF,
-0x0B, 0x00, 0x01, 0x00, 0x0B, 0x00, 0xB4, 0xFF, 0x00, 0x01, 0x7E,
-0xFD, 0x9C, 0x05, 0xDC, 0xF2, 0xE4, 0x3B, 0xCD, 0x22, 0xEE, 0xF2,
-0xF3, 0x06, 0x35, 0xFC, 0xE6, 0x01, 0x37, 0xFF, 0x36, 0x00, 0xFD,
-0xFF, 0x00, 0x00, 0x2A, 0x00, 0x5D, 0xFF, 0x76, 0x01, 0x59, 0xFD,
-0x42, 0x04, 0x63, 0xF9, 0x1C, 0x0C, 0xB6, 0x47, 0xA4, 0xFC, 0x07,
-0x00, 0xD0, 0x00, 0x20, 0xFF, 0xA0, 0x00, 0xB1, 0xFF, 0x13, 0x00,
-0xFE, 0xFF, 0x1F, 0x00, 0x7D, 0xFF, 0x6B, 0x01, 0xCF, 0xFC, 0x96,
-0x06, 0xB7, 0xF1, 0xC6, 0x35, 0x64, 0x2A, 0xD4, 0xF1, 0x2B, 0x07,
-0x3D, 0xFC, 0xD2, 0x01, 0x45, 0xFF, 0x32, 0x00, 0xFD, 0xFF, 0x00,
-0x00, 0x21, 0x00, 0x7A, 0xFF, 0x2B, 0x01, 0xFE, 0xFD, 0xF8, 0x02,
-0xFB, 0xFB, 0x8D, 0x05, 0xE5, 0x48, 0xE3, 0x01, 0x91, 0xFD, 0x25,
-0x02, 0x6B, 0xFE, 0xF7, 0x00, 0x8F, 0xFF, 0x1C, 0x00, 0xFD, 0xFF,
-0x2D, 0x00, 0x55, 0xFF, 0xB5, 0x01, 0x61, 0xFC, 0x16, 0x07, 0x85,
-0xF1, 0xE6, 0x2E, 0x9E, 0x31, 0x7D, 0xF1, 0xF3, 0x06, 0x84, 0xFC,
-0x9D, 0x01, 0x63, 0xFF, 0x28, 0x00, 0xFD, 0xFF, 0x18, 0x00, 0x9C,
-0xFF, 0xD6, 0x00, 0xB1, 0xFE, 0xA1, 0x01, 0x89, 0xFE, 0xC3, 0xFF,
-0x9C, 0x48, 0xFD, 0x07, 0xFA, 0xFA, 0x7A, 0x03, 0xBC, 0xFD, 0x49,
-0x01, 0x6E, 0xFF, 0x24, 0x00, 0x00, 0x00, 0xFD, 0xFF, 0x34, 0x00,
-0x3E, 0xFF, 0xDE, 0x01, 0x33, 0xFC, 0x22, 0x07, 0x2B, 0xF2, 0x80,
-0x27, 0x3B, 0x38, 0x0A, 0xF2, 0x44, 0x06, 0x0B, 0xFD, 0x45, 0x01,
-0x90, 0xFF, 0x18, 0x00, 0xFF, 0xFF, 0x10, 0x00, 0xBE, 0xFF, 0x7F,
-0x00, 0x65, 0xFF, 0x51, 0x00, 0xEB, 0x00, 0xE1, 0xFA, 0xE1, 0x46,
-0xCD, 0x0E, 0x6A, 0xF8, 0xB8, 0x04, 0x20, 0xFD, 0x90, 0x01, 0x53,
-0xFF, 0x2D, 0x00, 0xFF, 0xFF, 0xFD, 0xFF, 0x36, 0x00, 0x36, 0xFF,
-0xE5, 0x01, 0x42, 0xFC, 0xC3, 0x06, 0x87, 0xF3, 0xD7, 0x1F, 0xFE,
-0x3D, 0x91, 0xF3, 0x1D, 0x05, 0xD1, 0xFD, 0xCE, 0x00, 0xCC, 0xFF,
-0x02, 0x00, 0x02, 0x00, 0x09, 0x00, 0xDE, 0xFF, 0x2B, 0x00, 0x11,
-0x00, 0x1B, 0xFF, 0x02, 0x03, 0xFE, 0xF6, 0xC3, 0x43, 0x22, 0x16,
-0x07, 0xF6, 0xCA, 0x05, 0xA3, 0xFC, 0xC5, 0x01, 0x3F, 0xFF, 0x33,
-0x00, 0xFF, 0xFF, 0xFE, 0xFF, 0x34, 0x00, 0x3C, 0xFF, 0xCF, 0x01,
-0x88, 0xFC, 0x09, 0x06, 0x71, 0xF5, 0x2B, 0x18, 0xB2, 0x42, 0x20,
-0xF6, 0x83, 0x03, 0xCF, 0xFE, 0x3C, 0x00, 0x15, 0x00, 0xE6, 0xFF,
-0x07, 0x00, 0x03, 0x00, 0xFB, 0xFF, 0xDF, 0xFF, 0xA9, 0x00, 0x10,
-0xFE, 0xB9, 0x04, 0x27, 0xF4, 0x5E, 0x3F, 0xC3, 0x1D, 0xFE, 0xF3,
-0x99, 0x06, 0x50, 0xFC, 0xE2, 0x01, 0x36, 0xFF, 0x36, 0x00, 0xFE,
-0xFF, 0xFF, 0xFF, 0x2F, 0x00, 0x4D, 0xFF, 0xA0, 0x01, 0xFB, 0xFC,
-0x07, 0x05, 0xBF, 0xF7, 0xBB, 0x10, 0x2B, 0x46, 0xBB, 0xF9, 0x83,
-0x01, 0xFA, 0xFF, 0x95, 0xFF, 0x68, 0x00, 0xC7, 0xFF, 0x0E, 0x00,
-0x00, 0x00, 0x13, 0x00, 0x9F, 0xFF, 0x28, 0x01, 0x3A, 0xFD, 0x00,
-0x06, 0x5A, 0xF2, 0xDF, 0x39, 0x73, 0x25, 0x79, 0xF2, 0x12, 0x07,
-0x31, 0xFC, 0xE3, 0x01, 0x3B, 0xFF, 0x35, 0x00, 0xFD, 0xFF, 0x00,
-0x00, 0x27, 0x00, 0x66, 0xFF, 0x5E, 0x01, 0x90, 0xFD, 0xD2, 0x03,
-0x47, 0xFA, 0xC3, 0x09, 0x48, 0x48, 0x5A, 0xFE, 0x33, 0xFF, 0x45,
-0x01, 0xE2, 0xFE, 0xBE, 0x00, 0xA5, 0xFF, 0x16, 0x00, 0xFD, 0xFF,
-0x24, 0x00, 0x6D, 0xFF, 0x88, 0x01, 0xA2, 0xFC, 0xD0, 0x06, 0x8C,
-0xF1, 0x78, 0x33, 0xF2, 0x2C, 0x9E, 0xF1, 0x24, 0x07, 0x4E, 0xFC,
-0xC3, 0x01, 0x4E, 0xFF, 0x2F, 0x00, 0xFD, 0xFF, 0x1E, 0x00, 0x86,
-0xFF, 0x0E, 0x01, 0x3B, 0xFE, 0x82, 0x02, 0xE0, 0xFC, 0x73, 0x03,
-0xF6, 0x48, 0xE9, 0x03, 0xAD, 0xFC, 0x9C, 0x02, 0x2D, 0xFE, 0x14,
-0x01, 0x83, 0xFF, 0x1F, 0x00, 0x00, 0x00, 0xFD, 0xFF, 0x30, 0x00,
-0x4C, 0xFF, 0xC7, 0x01, 0x4A, 0xFC, 0x27, 0x07, 0xA8, 0xF1, 0x62,
-0x2C, 0xFD, 0x33, 0x93, 0xF1, 0xC4, 0x06, 0xAB, 0xFC, 0x82, 0x01,
-0x71, 0xFF, 0x23, 0x00, 0xFE, 0xFF, 0x15, 0x00, 0xA8, 0xFF, 0xB8,
-0x00, 0xF0, 0xFE, 0x2B, 0x01, 0x63, 0xFF, 0xF6, 0xFD, 0x2C, 0x48,
-0x47, 0x0A, 0x14, 0xFA, 0xEB, 0x03, 0x84, 0xFD, 0x63, 0x01, 0x64,
-0xFF, 0x27, 0x00, 0x00, 0x00, 0xFD, 0xFF, 0x36, 0x00, 0x3A, 0xFF,
-0xE4, 0x01, 0x32, 0xFC, 0x0C, 0x07, 0x91, 0xF2, 0xDD, 0x24, 0x54,
-0x3A, 0x74, 0xF2, 0xEB, 0x05, 0x49, 0xFD, 0x20, 0x01, 0xA3, 0xFF,
-0x11, 0x00, 0x00, 0x00, 0x0D, 0x00, 0xC9, 0xFF, 0x61, 0x00, 0xA2,
-0xFF, 0xE2, 0xFF, 0xAE, 0x01, 0x6B, 0xF9, 0xF2, 0x45, 0x4A, 0x11,
-0x8F, 0xF7, 0x1D, 0x05, 0xF1, 0xFC, 0xA4, 0x01, 0x4B, 0xFF, 0x2F,
-0x00, 0xFF, 0xFF, 0xFE, 0xFF, 0x36, 0x00, 0x37, 0xFF, 0xE1, 0x01,
-0x55, 0xFC, 0x8C, 0x06, 0x22, 0xF4, 0x2C, 0x1D, 0xC0, 0x3F, 0x55,
-0xF4, 0x9B, 0x04, 0x23, 0xFE, 0x9F, 0x00, 0xE4, 0xFF, 0xF9, 0xFF,
-0x04, 0x00, 0x07, 0x00, 0xE9, 0xFF, 0x0F, 0x00, 0x48, 0x00, 0xB9,
-0xFE, 0xA6, 0x03, 0xE4, 0xF5, 0x60, 0x42, 0xC1, 0x18, 0x47, 0xF5,
-0x1A, 0x06, 0x81, 0xFC, 0xD2, 0x01, 0x3B, 0xFF, 0x35, 0x00, 0xFE,
-0xFF, 0xFF, 0xFF, 0x33, 0x00, 0x40, 0xFF, 0xC1, 0x01, 0xAB, 0xFC,
-0xB7, 0x05, 0x34, 0xF6, 0x8E, 0x15, 0x0B, 0x44, 0x42, 0xF7, 0xDC,
-0x02, 0x32, 0xFF, 0x04, 0x00, 0x31, 0x00, 0xDC, 0xFF, 0x09, 0x00,
-0x02, 0x00, 0x04, 0x00, 0xC7, 0xFF, 0xD9, 0x00, 0xBF, 0xFD, 0x38,
-0x05, 0x69, 0xF3, 0x96, 0x3D, 0x6F, 0x20, 0x66, 0xF3, 0xCE, 0x06,
-0x3F, 0xFC, 0xE6, 0x01, 0x36, 0xFF, 0x36, 0x00, 0xFD, 0xFF, 0xFF,
-0xFF, 0x2C, 0x00, 0x55, 0xFF, 0x8B, 0x01, 0x2B, 0xFD, 0xA1, 0x04,
-0x9B, 0xF8, 0x42, 0x0E, 0x0F, 0x47, 0x38, 0xFB, 0xBE, 0x00, 0x6A,
-0x00, 0x58, 0xFF, 0x85, 0x00, 0xBB, 0xFF, 0x10, 0x00, 0xFF, 0xFF,
-0x19, 0x00, 0x8C, 0xFF, 0x4D, 0x01, 0xFE, 0xFC, 0x56, 0x06, 0xF7,
-0xF1, 0xBF, 0x37, 0x15, 0x28, 0x18, 0xF2, 0x25, 0x07, 0x34, 0xFC,
-0xDC, 0x01, 0x3F, 0xFF, 0x34, 0x00, 0xFD, 0xFF, 0x00, 0x00, 0x24,
-0x00, 0x71, 0xFF, 0x43, 0x01, 0xC9, 0xFD, 0x60, 0x03, 0x2E, 0xFB,
-0x7E, 0x07, 0xAF, 0x48, 0x2D, 0x00, 0x58, 0xFE, 0xBB, 0x01, 0xA3,
-0xFE, 0xDD, 0x00, 0x99, 0xFF, 0x19, 0x00, 0xFD, 0xFF, 0x29, 0x00,
-0x60, 0xFF, 0xA2, 0x01, 0x7C, 0xFC, 0xFB, 0x06, 0x7C, 0xF1, 0x15,
-0x31, 0x73, 0x2F, 0x81, 0xF1, 0x10, 0x07, 0x67, 0xFC, 0xB1, 0x01,
-0x58, 0xFF, 0x2C, 0x00, 0xFD, 0xFF, 0x1B, 0x00, 0x91, 0xFF, 0xF1,
-0x00, 0x79, 0xFE, 0x0A, 0x02, 0xC3, 0xFD, 0x73, 0x01, 0xDB, 0x48,
-0x07, 0x06, 0xC7, 0xFB, 0x12, 0x03, 0xF1, 0xFD, 0x31, 0x01, 0x78,
-0xFF, 0x22, 0x00, 0x00, 0x00, 0xFD, 0xFF, 0x32, 0x00, 0x44, 0xFF,
-0xD5, 0x01, 0x3A, 0xFC, 0x2A, 0x07, 0xE3, 0xF1, 0xD1, 0x29, 0x46,
-0x36, 0xC5, 0xF1, 0x87, 0x06, 0xDA, 0xFC, 0x64, 0x01, 0x80, 0xFF,
-0x1E, 0x00, 0xFE, 0xFF, 0x12, 0x00, 0xB3, 0xFF, 0x99, 0x00, 0x2E,
-0xFF, 0xB6, 0x00, 0x36, 0x00, 0x47, 0xFC, 0x90, 0x47, 0xA4, 0x0C,
-0x31, 0xF9, 0x5A, 0x04, 0x4E, 0xFD, 0x7C, 0x01, 0x5B, 0xFF, 0x2A,
-0x00, 0x00, 0x00, 0xFD, 0xFF, 0x36, 0x00, 0x37, 0xFF, 0xE6, 0x01,
-0x37, 0xFC, 0xEB, 0x06, 0x0B, 0xF3, 0x35, 0x22, 0x52, 0x3C, 0xFD,
-0xF2, 0x84, 0x05, 0x8D, 0xFD, 0xF6, 0x00, 0xB8, 0xFF, 0x09, 0x00,
-0x01, 0x00, 0x0B, 0x00, 0xD5, 0xFF, 0x44, 0x00, 0xDD, 0xFF, 0x77,
-0xFF, 0x67, 0x02, 0x14, 0xF8, 0xDC, 0x44, 0xD5, 0x13, 0xBC, 0xF6,
-0x7C, 0x05, 0xC5, 0xFC, 0xB7, 0x01, 0x44, 0xFF, 0x31, 0x00, 0xFF,
-0xFF, 0xFE, 0xFF, 0x35, 0x00, 0x39, 0xFF, 0xD9, 0x01, 0x6D, 0xFC,
-0x4B, 0x06, 0xCD, 0xF4, 0x83, 0x1A, 0x5F, 0x41, 0x3A, 0xF5, 0x0C,
-0x04, 0x7B, 0xFE, 0x6C, 0x00, 0xFE, 0xFF, 0xEF, 0xFF, 0x05, 0x00,
-0x05, 0x00, 0xF3, 0xFF, 0xF5, 0xFF, 0x7D, 0x00, 0x5D, 0xFE, 0x3E,
-0x04, 0xEA, 0xF4, 0xD9, 0x40, 0x66, 0x1B, 0x93, 0xF4, 0x62, 0x06,
-0x64, 0xFC, 0xDC, 0x01, 0x38, 0xFF, 0x36, 0x00, 0xFE, 0xFF, 0xFF,
-0xFF, 0x31, 0x00, 0x46, 0xFF, 0xB1, 0x01, 0xD3, 0xFC, 0x5D, 0x05,
-0x01, 0xF7, 0xFB, 0x12, 0x3F, 0x45, 0x83, 0xF8, 0x2A, 0x02, 0x9A,
-0xFF, 0xCA, 0xFF, 0x4E, 0x00, 0xD1, 0xFF, 0x0C, 0x00, 0x00, 0x00,
-0x0C, 0x00, 0xB1, 0xFF, 0x04, 0x01, 0x76, 0xFD, 0xA8, 0x05, 0xCC,
-0xF2, 0xAB, 0x3B, 0x18, 0x23, 0xE0, 0xF2, 0xF7, 0x06, 0x35, 0xFC,
-0xE6, 0x01, 0x38, 0xFF, 0x36, 0x00, 0xFD, 0xFF, 0x00, 0x00, 0x29,
-0x00, 0x5E, 0xFF, 0x74, 0x01, 0x5F, 0xFD, 0x35, 0x04, 0x7C, 0xF9,
-0xD8, 0x0B, 0xC9, 0x47, 0xD4, 0xFC, 0xF0, 0xFF, 0xDD, 0x00, 0x19,
-0xFF, 0xA4, 0x00, 0xAF, 0xFF, 0x13, 0x00, 0xFE, 0xFF, 0x20, 0x00,
-0x7B, 0xFF, 0x6E, 0x01, 0xCA, 0xFC, 0x9D, 0x06, 0xB1, 0xF1, 0x86,
-0x35, 0xAE, 0x2A, 0xCD, 0xF1, 0x2B, 0x07, 0x3F, 0xFC, 0xD1, 0x01,
-0x46, 0xFF, 0x32, 0x00, 0xFD, 0xFF, 0x00, 0x00, 0x21, 0x00, 0x7C,
-0xFF, 0x27, 0x01, 0x05, 0xFE, 0xEB, 0x02, 0x14, 0xFC, 0x50, 0x05,
-0xEA, 0x48, 0x1B, 0x02, 0x78, 0xFD, 0x32, 0x02, 0x64, 0xFE, 0xFA,
-0x00, 0x8D, 0xFF, 0x1C, 0x00, 0xFD, 0xFF, 0x2D, 0x00, 0x54, 0xFF,
-0xB7, 0x01, 0x5E, 0xFC, 0x19, 0x07, 0x88, 0xF1, 0x9F, 0x2E, 0xE3,
-0x31, 0x7E, 0xF1, 0xEE, 0x06, 0x88, 0xFC, 0x9A, 0x01, 0x64, 0xFF,
-0x28, 0x00, 0xFD, 0xFF, 0x18, 0x00, 0x9D, 0xFF, 0xD3, 0x00, 0xB8,
-0xFE, 0x93, 0x01, 0xA1, 0xFE, 0x8E, 0xFF, 0x92, 0x48, 0x3D, 0x08,
-0xE1, 0xFA, 0x86, 0x03, 0xB6, 0xFD, 0x4C, 0x01, 0x6D, 0xFF, 0x25,
-0x00, 0x00, 0x00, 0xFD, 0xFF, 0x34, 0x00, 0x3E, 0xFF, 0xDF, 0x01,
-0x33, 0xFC, 0x20, 0x07, 0x35, 0xF2, 0x36, 0x27, 0x78, 0x38, 0x14,
-0xF2, 0x3B, 0x06, 0x11, 0xFD, 0x41, 0x01, 0x92, 0xFF, 0x17, 0x00,
-0xFF, 0xFF, 0x10, 0x00, 0xBF, 0xFF, 0x7B, 0x00, 0x6C, 0xFF, 0x44,
-0x00, 0x01, 0x01, 0xB6, 0xFA, 0xC8, 0x46, 0x13, 0x0F, 0x51, 0xF8,
-0xC4, 0x04, 0x1B, 0xFD, 0x92, 0x01, 0x52, 0xFF, 0x2D, 0x00, 0xFF,
-0xFF, 0xFD, 0xFF, 0x36, 0x00, 0x36, 0xFF, 0xE5, 0x01, 0x44, 0xFC,
-0xBD, 0x06, 0x97, 0xF3, 0x8A, 0x1F, 0x31, 0x3E, 0xA5, 0xF3, 0x0F,
-0x05, 0xDA, 0xFD, 0xC9, 0x00, 0xCF, 0xFF, 0x01, 0x00, 0x02, 0x00,
-0x09, 0x00, 0xDF, 0xFF, 0x28, 0x00, 0x17, 0x00, 0x10, 0xFF, 0x15,
-0x03, 0xDD, 0xF6, 0x9E, 0x43, 0x6C, 0x16, 0xF1, 0xF5, 0xD3, 0x05,
-0x9F, 0xFC, 0xC6, 0x01, 0x3F, 0xFF, 0x33, 0x00, 0xFF, 0xFF, 0xFE,
-0xFF, 0x34, 0x00, 0x3C, 0xFF, 0xCE, 0x01, 0x8C, 0xFC, 0x00, 0x06,
-0x86, 0xF5, 0xE0, 0x17, 0xDB, 0x42, 0x3F, 0xF6, 0x71, 0x03, 0xD9,
-0xFE, 0x36, 0x00, 0x18, 0x00, 0xE5, 0xFF, 0x07, 0x00, 0x03, 0x00,
-0xFC, 0xFF, 0xDC, 0xFF, 0xAF, 0x00, 0x07, 0xFE, 0xC8, 0x04, 0x10,
-0xF4, 0x2D, 0x3F, 0x0F, 0x1E, 0xED, 0xF3, 0xA0, 0x06, 0x4E, 0xFC,
-0xE3, 0x01, 0x36, 0xFF, 0x36, 0x00, 0xFE, 0xFF, 0xFF, 0xFF, 0x2E,
-0x00, 0x4E, 0xFF, 0x9E, 0x01, 0x00, 0xFD, 0xFC, 0x04, 0xD7, 0xF7,
-0x75, 0x10, 0x48, 0x46, 0xE4, 0xF9, 0x6E, 0x01, 0x06, 0x00, 0x8E,
-0xFF, 0x6B, 0x00, 0xC6, 0xFF, 0x0E, 0x00, 0xFF, 0xFF, 0x13, 0x00,
-0x9D, 0xFF, 0x2D, 0x01, 0x33, 0xFD, 0x0B, 0x06, 0x4D, 0xF2, 0xA5,
-0x39, 0xBF, 0x25, 0x6D, 0xF2, 0x15, 0x07, 0x31, 0xFC, 0xE2, 0x01,
-0x3B, 0xFF, 0x35, 0x00, 0xFD, 0xFF, 0x00, 0x00, 0x26, 0x00, 0x68,
-0xFF, 0x5B, 0x01, 0x96, 0xFD, 0xC6, 0x03, 0x61, 0xFA, 0x81, 0x09,
-0x57, 0x48, 0x8D, 0xFE, 0x1B, 0xFF, 0x52, 0x01, 0xDB, 0xFE, 0xC2,
-0x00, 0xA4, 0xFF, 0x16, 0x00, 0xFD, 0xFF, 0x25, 0x00, 0x6C, 0xFF,
-0x8B, 0x01, 0x9D, 0xFC, 0xD5, 0x06, 0x89, 0xF1, 0x35, 0x33, 0x3A,
-0x2D, 0x9A, 0xF1, 0x23, 0x07, 0x51, 0xFC, 0xC2, 0x01, 0x4F, 0xFF,
-0x2F, 0x00, 0xFD, 0xFF, 0x1E, 0x00, 0x87, 0xFF, 0x0B, 0x01, 0x42,
-0xFE, 0x74, 0x02, 0xF9, 0xFC, 0x39, 0x03, 0xF5, 0x48, 0x24, 0x04,
-0x94, 0xFC, 0xA9, 0x02, 0x27, 0xFE, 0x18, 0x01, 0x82, 0xFF, 0x1F,
-0x00, 0x00, 0x00, 0xFD, 0xFF, 0x30, 0x00, 0x4B, 0xFF, 0xC9, 0x01,
-0x48, 0xFC, 0x28, 0x07, 0xAD, 0xF1, 0x19, 0x2C, 0x3F, 0x34, 0x97,
-0xF1, 0xBE, 0x06, 0xB0, 0xFC, 0x7F, 0x01, 0x72, 0xFF, 0x23, 0x00,
-0xFE, 0xFF, 0x15, 0x00, 0xA9, 0xFF, 0xB4, 0x00, 0xF7, 0xFE, 0x1D,
-0x01, 0x7A, 0xFF, 0xC5, 0xFD, 0x1D, 0x48, 0x89, 0x0A, 0xFB, 0xF9,
-0xF8, 0x03, 0x7D, 0xFD, 0x66, 0x01, 0x63, 0xFF, 0x28, 0x00, 0x00,
-0x00, 0xFD, 0xFF, 0x36, 0x00, 0x39, 0xFF, 0xE4, 0x01, 0x32, 0xFC,
-0x09, 0x07, 0x9D, 0xF2, 0x92, 0x24, 0x8F, 0x3A, 0x82, 0xF2, 0xE1,
-0x05, 0x50, 0xFD, 0x1B, 0x01, 0xA6, 0xFF, 0x10, 0x00, 0x00, 0x00,
-0x0D, 0x00, 0xCB, 0xFF, 0x5E, 0x00, 0xA9, 0xFF, 0xD6, 0xFF, 0xC3,
-0x01, 0x43, 0xF9, 0xD7, 0x45, 0x92, 0x11, 0x77, 0xF7, 0x28, 0x05,
-0xEC, 0xFC, 0xA7, 0x01, 0x4A, 0xFF, 0x2F, 0x00, 0xFF, 0xFF, 0xFE,
-0xFF, 0x36, 0x00, 0x37, 0xFF, 0xE0, 0x01, 0x57, 0xFC, 0x85, 0x06,
-0x34, 0xF4, 0xE0, 0x1C, 0xF0, 0x3F, 0x6D, 0xF4, 0x8C, 0x04, 0x2C,
-0xFE, 0x99, 0x00, 0xE7, 0xFF, 0xF8, 0xFF, 0x04, 0x00, 0x06, 0x00,
-0xEA, 0xFF, 0x0C, 0x00, 0x4E, 0x00, 0xAF, 0xFE, 0xB8, 0x03, 0xC7,
-0xF5, 0x38, 0x42, 0x0C, 0x19, 0x32, 0xF5, 0x23, 0x06, 0x7D, 0xFC,
-0xD3, 0x01, 0x3A, 0xFF, 0x35, 0x00, 0xFE, 0xFF, 0xFF, 0xFF, 0x32,
-0x00, 0x41, 0xFF, 0xC0, 0x01, 0xAF, 0xFC, 0xAD, 0x05, 0x4A, 0xF6,
-0x44, 0x15, 0x2F, 0x44, 0x64, 0xF7, 0xC9, 0x02, 0x3D, 0xFF, 0xFE,
-0xFF, 0x34, 0x00, 0xDB, 0xFF, 0x09, 0x00, 0x02, 0x00, 0x05, 0x00,
-0xC5, 0xFF, 0xDE, 0x00, 0xB7, 0xFD, 0x45, 0x05, 0x56, 0xF3, 0x61,
-0x3D, 0xBA, 0x20, 0x56, 0xF3, 0xD3, 0x06, 0x3E, 0xFC, 0xE6, 0x01,
-0x36, 0xFF, 0x36, 0x00, 0xFD, 0xFF, 0xFF, 0xFF, 0x2C, 0x00, 0x56,
-0xFF, 0x88, 0x01, 0x31, 0xFD, 0x95, 0x04, 0xB4, 0xF8, 0xFC, 0x0D,
-0x26, 0x47, 0x64, 0xFB, 0xA7, 0x00, 0x77, 0x00, 0x51, 0xFF, 0x89,
-0x00, 0xBA, 0xFF, 0x11, 0x00, 0xFF, 0xFF, 0x1A, 0x00, 0x8A, 0xFF,
-0x51, 0x01, 0xF8, 0xFC, 0x5E, 0x06, 0xED, 0xF1, 0x82, 0x37, 0x60,
-0x28, 0x0E, 0xF2, 0x26, 0x07, 0x35, 0xFC, 0xDB, 0x01, 0x40, 0xFF,
-0x34, 0x00, 0xFD, 0xFF, 0x00, 0x00, 0x23, 0x00, 0x72, 0xFF, 0x40,
-0x01, 0xD0, 0xFD, 0x53, 0x03, 0x47, 0xFB, 0x3F, 0x07, 0xB8, 0x48,
-0x62, 0x00, 0x3F, 0xFE, 0xC8, 0x01, 0x9C, 0xFE, 0xE0, 0x00, 0x98,
-0xFF, 0x19, 0x00, 0xFD, 0xFF, 0x29, 0x00, 0x5F, 0xFF, 0xA5, 0x01,
-0x78, 0xFC, 0xFF, 0x06, 0x7D, 0xF1, 0xCF, 0x30, 0xB8, 0x2F, 0x80,
-0xF1, 0x0D, 0x07, 0x6A, 0xFC, 0xAE, 0x01, 0x59, 0xFF, 0x2B, 0x00,
-0xFD, 0xFF, 0x1B, 0x00, 0x93, 0xFF, 0xED, 0x00, 0x80, 0xFE, 0xFD,
-0x01, 0xDC, 0xFD, 0x3C, 0x01, 0xD5, 0x48, 0x45, 0x06, 0xAE, 0xFB,
-0x1F, 0x03, 0xEA, 0xFD, 0x34, 0x01, 0x77, 0xFF, 0x22, 0x00, 0x00,
-0x00, 0xFD, 0xFF, 0x33, 0x00, 0x43, 0xFF, 0xD6, 0x01, 0x39, 0xFC,
-0x2A, 0x07, 0xEB, 0xF1, 0x87, 0x29, 0x85, 0x36, 0xCC, 0xF1, 0x7F,
-0x06, 0xE0, 0xFC, 0x60, 0x01, 0x82, 0xFF, 0x1D, 0x00, 0xFE, 0xFF,
-0x12, 0x00, 0xB5, 0xFF, 0x96, 0x00, 0x35, 0xFF, 0xA9, 0x00, 0x4D,
-0x00, 0x19, 0xFC, 0x7C, 0x47, 0xE8, 0x0C, 0x18, 0xF9, 0x66, 0x04,
-0x48, 0xFD, 0x7E, 0x01, 0x5A, 0xFF, 0x2B, 0x00, 0x00, 0x00, 0xFD,
-0xFF, 0x36, 0x00, 0x37, 0xFF, 0xE6, 0x01, 0x38, 0xFC, 0xE6, 0x06,
-0x19, 0xF3, 0xEA, 0x21, 0x8A, 0x3C, 0x0E, 0xF3, 0x78, 0x05, 0x96,
-0xFD, 0xF1, 0x00, 0xBB, 0xFF, 0x08, 0x00, 0x01, 0x00, 0x0B, 0x00,
-0xD6, 0xFF, 0x41, 0x00, 0xE4, 0xFF, 0x6B, 0xFF, 0x7B, 0x02, 0xF0,
-0xF7, 0xBA, 0x44, 0x1E, 0x14, 0xA5, 0xF6, 0x86, 0x05, 0xC1, 0xFC,
-0xB9, 0x01, 0x44, 0xFF, 0x32, 0x00, 0xFF, 0xFF, 0xFE, 0xFF, 0x35,
-0x00, 0x39, 0xFF, 0xD8, 0x01, 0x70, 0xFC, 0x43, 0x06, 0xE1, 0xF4,
-0x38, 0x1A, 0x8C, 0x41, 0x55, 0xF5, 0xFC, 0x03, 0x85, 0xFE, 0x66,
-0x00, 0x01, 0x00, 0xEE, 0xFF, 0x06, 0x00, 0x05, 0x00, 0xF4, 0xFF,
-0xF2, 0xFF, 0x83, 0x00, 0x53, 0xFE, 0x4E, 0x04, 0xD0, 0xF4, 0xAB,
-0x40, 0xB2, 0x1B, 0x7F, 0xF4, 0x69, 0x06, 0x62, 0xFC, 0xDD, 0x01,
-0x38, 0xFF, 0x36, 0x00, 0xFE, 0xFF, 0xFF, 0xFF, 0x30, 0x00, 0x47,
-0xFF, 0xAF, 0x01, 0xD8, 0xFC, 0x52, 0x05, 0x19, 0xF7, 0xB2, 0x12,
-0x5C, 0x45, 0xA9, 0xF8, 0x16, 0x02, 0xA6, 0xFF, 0xC3, 0xFF, 0x51,
-0x00, 0xD0, 0xFF, 0x0C, 0x00, 0x00, 0x00, 0x0D, 0x00, 0xAF, 0xFF,
-0x09, 0x01, 0x6E, 0xFD, 0xB4, 0x05, 0xBC, 0xF2, 0x73, 0x3B, 0x64,
-0x23, 0xD2, 0xF2, 0xFB, 0x06, 0x34, 0xFC, 0xE6, 0x01, 0x38, 0xFF,
-0x36, 0x00, 0xFD, 0xFF, 0x00, 0x00, 0x29, 0x00, 0x5F, 0xFF, 0x71,
-0x01, 0x65, 0xFD, 0x29, 0x04, 0x96, 0xF9, 0x95, 0x0B, 0xDC, 0x47,
-0x03, 0xFD, 0xD9, 0xFF, 0xEA, 0x00, 0x12, 0xFF, 0xA7, 0x00, 0xAE,
-0xFF, 0x14, 0x00, 0xFE, 0xFF, 0x20, 0x00, 0x79, 0xFF, 0x72, 0x01,
-0xC4, 0xFC, 0xA4, 0x06, 0xAB, 0xF1, 0x46, 0x35, 0xF7, 0x2A, 0xC6,
-0xF1, 0x2A, 0x07, 0x40, 0xFC, 0xCF, 0x01, 0x47, 0xFF, 0x31, 0x00,
-0xFD, 0xFF, 0x00, 0x00, 0x20, 0x00, 0x7D, 0xFF, 0x24, 0x01, 0x0C,
-0xFE, 0xDE, 0x02, 0x2E, 0xFC, 0x13, 0x05, 0xEC, 0x48, 0x54, 0x02,
-0x5E, 0xFD, 0x3F, 0x02, 0x5D, 0xFE, 0xFE, 0x00, 0x8C, 0xFF, 0x1C,
-0x00, 0xFD, 0xFF, 0x2D, 0x00, 0x53, 0xFF, 0xBA, 0x01, 0x5B, 0xFC,
-0x1B, 0x07, 0x8B, 0xF1, 0x58, 0x2E, 0x26, 0x32, 0x80, 0xF1, 0xEA,
-0x06, 0x8C, 0xFC, 0x97, 0x01, 0x66, 0xFF, 0x27, 0x00, 0xFD, 0xFF,
-0x17, 0x00, 0x9E, 0xFF, 0xCF, 0x00, 0xBF, 0xFE, 0x86, 0x01, 0xBA,
-0xFE, 0x5A, 0xFF, 0x86, 0x48, 0x7D, 0x08, 0xC7, 0xFA, 0x93, 0x03,
-0xB0, 0xFD, 0x4F, 0x01, 0x6C, 0xFF, 0x25, 0x00, 0x00, 0x00, 0xFD,
-0xFF, 0x35, 0x00, 0x3D, 0xFF, 0xDF, 0x01, 0x32, 0xFC, 0x1E, 0x07,
-0x40, 0xF2, 0xEB, 0x26, 0xB5, 0x38, 0x1F, 0xF2, 0x32, 0x06, 0x18,
-0xFD, 0x3D, 0x01, 0x94, 0xFF, 0x16, 0x00, 0xFF, 0xFF, 0x0F, 0x00,
-0xC0, 0xFF, 0x78, 0x00, 0x73, 0xFF, 0x38, 0x00, 0x17, 0x01, 0x8B,
-0xFA, 0xAF, 0x46, 0x59, 0x0F, 0x39, 0xF8, 0xCF, 0x04, 0x15, 0xFD,
-0x95, 0x01, 0x51, 0xFF, 0x2D, 0x00, 0xFF, 0xFF, 0xFD, 0xFF, 0x36,
-0x00, 0x36, 0xFF, 0xE5, 0x01, 0x46, 0xFC, 0xB8, 0x06, 0xA8, 0xF3,
-0x3F, 0x1F, 0x64, 0x3E, 0xBA, 0xF3, 0x01, 0x05, 0xE2, 0xFD, 0xC4,
-0x00, 0xD2, 0xFF, 0x00, 0x00, 0x02, 0x00, 0x08, 0x00, 0xE1, 0xFF,
-0x25, 0x00, 0x1D, 0x00, 0x05, 0xFF, 0x28, 0x03, 0xBD, 0xF6, 0x77,
-0x43, 0xB6, 0x16, 0xDC, 0xF5, 0xDD, 0x05, 0x9B, 0xFC, 0xC8, 0x01,
-0x3E, 0xFF, 0x33, 0x00, 0xFF, 0xFF, 0xFE, 0xFF, 0x34, 0x00, 0x3D,
-0xFF, 0xCC, 0x01, 0x8F, 0xFC, 0xF8, 0x05, 0x9B, 0xF5, 0x96, 0x17,
-0x02, 0x43, 0x5E, 0xF6, 0x5F, 0x03, 0xE4, 0xFE, 0x30, 0x00, 0x1B,
-0x00, 0xE4, 0xFF, 0x08, 0x00, 0x03, 0x00, 0xFD, 0xFF, 0xD9, 0xFF,
-0xB4, 0x00, 0xFD, 0xFD, 0xD7, 0x04, 0xFA, 0xF3, 0xFC, 0x3E, 0x5B,
-0x1E, 0xDB, 0xF3, 0xA6, 0x06, 0x4C, 0xFC, 0xE3, 0x01, 0x36, 0xFF,
-0x36, 0x00, 0xFE, 0xFF, 0xFF, 0xFF, 0x2E, 0x00, 0x4E, 0xFF, 0x9C,
-0x01, 0x05, 0xFD, 0xF1, 0x04, 0xF0, 0xF7, 0x2D, 0x10, 0x61, 0x46,
-0x0D, 0xFA, 0x58, 0x01, 0x13, 0x00, 0x87, 0xFF, 0x6E, 0x00, 0xC4,
-0xFF, 0x0E, 0x00, 0xFF, 0xFF, 0x14, 0x00, 0x9B, 0xFF, 0x31, 0x01,
-0x2C, 0xFD, 0x15, 0x06, 0x41, 0xF2, 0x6A, 0x39, 0x0A, 0x26, 0x61,
-0xF2, 0x17, 0x07, 0x31, 0xFC, 0xE2, 0x01, 0x3B, 0xFF, 0x35, 0x00,
-0xFD, 0xFF, 0x00, 0x00, 0x26, 0x00, 0x69, 0xFF, 0x58, 0x01, 0x9D,
-0xFD, 0xB9, 0x03, 0x7B, 0xFA, 0x40, 0x09, 0x63, 0x48, 0xBF, 0xFE,
-0x03, 0xFF, 0x5F, 0x01, 0xD4, 0xFE, 0xC5, 0x00, 0xA2, 0xFF, 0x16,
-0x00, 0xFD, 0xFF, 0x25, 0x00, 0x6A, 0xFF, 0x8E, 0x01, 0x99, 0xFC,
-0xDB, 0x06, 0x86, 0xF1, 0xF2, 0x32, 0x82, 0x2D, 0x96, 0xF1, 0x21,
-0x07, 0x53, 0xFC, 0xC0, 0x01, 0x50, 0xFF, 0x2E, 0x00, 0xFD, 0xFF,
-0x1D, 0x00, 0x88, 0xFF, 0x07, 0x01, 0x49, 0xFE, 0x67, 0x02, 0x13,
-0xFD, 0xFF, 0x02, 0xF4, 0x48, 0x5F, 0x04, 0x7A, 0xFC, 0xB6, 0x02,
-0x20, 0xFE, 0x1B, 0x01, 0x81, 0xFF, 0x1F, 0x00, 0x00, 0x00, 0xFD,
-0xFF, 0x30, 0x00, 0x4A, 0xFF, 0xCA, 0x01, 0x46, 0xFC, 0x29, 0x07,
-0xB3, 0xF1, 0xD1, 0x2B, 0x81, 0x34, 0x9C, 0xF1, 0xB8, 0x06, 0xB5,
-0xFC, 0x7C, 0x01, 0x74, 0xFF, 0x22, 0x00, 0xFE, 0xFF, 0x15, 0x00,
-0xAA, 0xFF, 0xB1, 0x00, 0xFE, 0xFE, 0x10, 0x01, 0x92, 0xFF, 0x94,
-0xFD, 0x0D, 0x48, 0xCB, 0x0A, 0xE2, 0xF9, 0x04, 0x04, 0x77, 0xFD,
-0x69, 0x01, 0x62, 0xFF, 0x28, 0x00, 0x00, 0x00, 0xFD, 0xFF, 0x36,
-0x00, 0x39, 0xFF, 0xE5, 0x01, 0x32, 0xFC, 0x06, 0x07, 0xAA, 0xF2,
-0x46, 0x24, 0xC8, 0x3A, 0x90, 0xF2, 0xD6, 0x05, 0x57, 0xFD, 0x17,
-0x01, 0xA8, 0xFF, 0x0F, 0x00, 0x00, 0x00, 0x0D, 0x00, 0xCC, 0xFF,
-0x5A, 0x00, 0xAF, 0xFF, 0xCA, 0xFF, 0xD8, 0x01, 0x1C, 0xF9, 0xB8,
-0x45, 0xDA, 0x11, 0x60, 0xF7, 0x33, 0x05, 0xE7, 0xFC, 0xA9, 0x01,
-0x4A, 0xFF, 0x30, 0x00, 0xFF, 0xFF, 0xFE, 0xFF, 0x36, 0x00, 0x37,
-0xFF, 0xDF, 0x01, 0x5A, 0xFC, 0x7E, 0x06, 0x47, 0xF4, 0x94, 0x1C,
-0x1F, 0x40, 0x85, 0xF4, 0x7D, 0x04, 0x36, 0xFE, 0x93, 0x00, 0xEA,
-0xFF, 0xF7, 0xFF, 0x04, 0x00, 0x06, 0x00, 0xEB, 0xFF, 0x09, 0x00,
-0x54, 0x00, 0xA4, 0xFE, 0xC9, 0x03, 0xAA, 0xF5, 0x0C, 0x42, 0x56,
-0x19, 0x1E, 0xF5, 0x2B, 0x06, 0x7A, 0xFC, 0xD4, 0x01, 0x3A, 0xFF,
-0x35, 0x00, 0xFE, 0xFF, 0xFF, 0xFF, 0x32, 0x00, 0x42, 0xFF, 0xBE,
-0x01, 0xB4, 0xFC, 0xA4, 0x05, 0x61, 0xF6, 0xFB, 0x14, 0x53, 0x44,
-0x86, 0xF7, 0xB6, 0x02, 0x49, 0xFF, 0xF7, 0xFF, 0x37, 0x00, 0xD9,
-0xFF, 0x0A, 0x00, 0x01, 0x00, 0x06, 0x00, 0xC2, 0xFF, 0xE3, 0x00,
-0xAE, 0xFD, 0x52, 0x05, 0x44, 0xF3, 0x2A, 0x3D, 0x06, 0x21, 0x47,
-0xF3, 0xD8, 0x06, 0x3C, 0xFC, 0xE6, 0x01, 0x36, 0xFF, 0x36, 0x00,
-0xFD, 0xFF, 0x00, 0x00, 0x2B, 0x00, 0x57, 0xFF, 0x86, 0x01, 0x36,
-0xFD, 0x89, 0x04, 0xCD, 0xF8, 0xB7, 0x0D, 0x3D, 0x47, 0x91, 0xFB,
-0x91, 0x00, 0x83, 0x00, 0x4A, 0xFF, 0x8C, 0x00, 0xB9, 0xFF, 0x11,
-0x00, 0xFE, 0xFF, 0x1B, 0x00, 0x88, 0xFF, 0x55, 0x01, 0xF2, 0xFC,
-0x67, 0x06, 0xE4, 0xF1, 0x44, 0x37, 0xAA, 0x28, 0x05, 0xF2, 0x27,
-0x07, 0x36, 0xFC, 0xDA, 0x01, 0x41, 0xFF, 0x33, 0x00, 0xFD, 0xFF,
-0x00, 0x00, 0x23, 0x00, 0x73, 0xFF, 0x3D, 0x01, 0xD6, 0xFD, 0x46,
-0x03, 0x61, 0xFB, 0x00, 0x07, 0xBF, 0x48, 0x98, 0x00, 0x26, 0xFE,
-0xD5, 0x01, 0x95, 0xFE, 0xE3, 0x00, 0x96, 0xFF, 0x1A, 0x00, 0xFD,
-0xFF, 0x2A, 0x00, 0x5D, 0xFF, 0xA7, 0x01, 0x75, 0xFC, 0x03, 0x07,
-0x7D, 0xF1, 0x8A, 0x30, 0xFF, 0x2F, 0x7E, 0xF1, 0x0A, 0x07, 0x6E,
-0xFC, 0xAC, 0x01, 0x5A, 0xFF, 0x2B, 0x00, 0xFD, 0xFF, 0x1A, 0x00,
-0x94, 0xFF, 0xEA, 0x00, 0x87, 0xFE, 0xF0, 0x01, 0xF5, 0xFD, 0x05,
-0x01, 0xCE, 0x48, 0x83, 0x06, 0x94, 0xFB, 0x2C, 0x03, 0xE4, 0xFD,
-0x37, 0x01, 0x76, 0xFF, 0x22, 0x00, 0x00, 0x00, 0xFD, 0xFF, 0x33,
-0x00, 0x42, 0xFF, 0xD7, 0x01, 0x38, 0xFC, 0x29, 0x07, 0xF3, 0xF1,
-0x3E, 0x29, 0xC6, 0x36, 0xD4, 0xF1, 0x77, 0x06, 0xE6, 0xFC, 0x5C,
-0x01, 0x84, 0xFF, 0x1C, 0x00, 0xFE, 0xFF, 0x12, 0x00, 0xB6, 0xFF,
-0x93, 0x00, 0x3C, 0xFF, 0x9D, 0x00, 0x63, 0x00, 0xEB, 0xFB, 0x69,
-0x47, 0x2D, 0x0D, 0xFF, 0xF8, 0x72, 0x04, 0x42, 0xFD, 0x81, 0x01,
-0x59, 0xFF, 0x2B, 0x00, 0x00, 0x00, 0xFD, 0xFF, 0x36, 0x00, 0x37,
-0xFF, 0xE6, 0x01, 0x3A, 0xFC, 0xE2, 0x06, 0x28, 0xF3, 0x9E, 0x21,
-0xC0, 0x3C, 0x1F, 0xF3, 0x6C, 0x05, 0x9E, 0xFD, 0xED, 0x00, 0xBD,
-0xFF, 0x07, 0x00, 0x01, 0x00, 0x0A, 0x00, 0xD7, 0xFF, 0x3E, 0x00,
-0xEA, 0xFF, 0x60, 0xFF, 0x8F, 0x02, 0xCD, 0xF7, 0x99, 0x44, 0x68,
-0x14, 0x8E, 0xF6, 0x90, 0x05, 0xBC, 0xFC, 0xBA, 0x01, 0x43, 0xFF,
-0x32, 0x00, 0xFF, 0xFF, 0xFE, 0xFF, 0x35, 0x00, 0x39, 0xFF, 0xD7,
-0x01, 0x73, 0xFC, 0x3B, 0x06, 0xF5, 0xF4, 0xED, 0x19, 0xB7, 0x41,
-0x71, 0xF5, 0xEB, 0x03, 0x90, 0xFE, 0x60, 0x00, 0x04, 0x00, 0xED,
-0xFF, 0x06, 0x00, 0x04, 0x00, 0xF5, 0xFF, 0xEF, 0xFF, 0x88, 0x00,
-0x49, 0xFE, 0x5D, 0x04, 0xB7, 0xF4, 0x7D, 0x40, 0xFD, 0x1B, 0x6C,
-0xF4, 0x70, 0x06, 0x5F, 0xFC, 0xDE, 0x01, 0x37, 0xFF, 0x36, 0x00,
-0xFE, 0xFF, 0xFF, 0xFF, 0x30, 0x00, 0x48, 0xFF, 0xAD, 0x01, 0xDD,
-0xFC, 0x48, 0x05, 0x30, 0xF7, 0x6B, 0x12, 0x7D, 0x45, 0xCF, 0xF8,
-0x01, 0x02, 0xB2, 0xFF, 0xBD, 0xFF, 0x54, 0x00, 0xCE, 0xFF, 0x0C,
-0x00, 0x00, 0x00, 0x0E, 0x00, 0xAC, 0xFF, 0x0E, 0x01, 0x66, 0xFD,
-0xBF, 0x05, 0xAD, 0xF2, 0x3B, 0x3B, 0xB0, 0x23, 0xC4, 0xF2, 0xFF,
-0x06, 0x33, 0xFC, 0xE5, 0x01, 0x38, 0xFF, 0x36, 0x00, 0xFD, 0xFF,
-0x00, 0x00, 0x29, 0x00, 0x60, 0xFF, 0x6E, 0x01, 0x6B, 0xFD, 0x1D,
-0x04, 0xAF, 0xF9, 0x51, 0x0B, 0xEC, 0x47, 0x33, 0xFD, 0xC1, 0xFF,
-0xF7, 0x00, 0x0C, 0xFF, 0xAA, 0x00, 0xAD, 0xFF, 0x14, 0x00, 0xFE,
-0xFF, 0x21, 0x00, 0x77, 0xFF, 0x75, 0x01, 0xBF, 0xFC, 0xAB, 0x06,
-0xA6, 0xF1, 0x05, 0x35, 0x40, 0x2B, 0xBF, 0xF1, 0x2A, 0x07, 0x42,
-0xFC, 0xCE, 0x01, 0x48, 0xFF, 0x31, 0x00, 0xFD, 0xFF, 0x00, 0x00,
-0x20, 0x00, 0x7E, 0xFF, 0x21, 0x01, 0x12, 0xFE, 0xD1, 0x02, 0x47,
-0xFC, 0xD7, 0x04, 0xF0, 0x48, 0x8D, 0x02, 0x45, 0xFD, 0x4D, 0x02,
-0x56, 0xFE, 0x01, 0x01, 0x8B, 0xFF, 0x1D, 0x00, 0xFD, 0xFF, 0x2E,
-0x00, 0x52, 0xFF, 0xBC, 0x01, 0x58, 0xFC, 0x1D, 0x07, 0x8E, 0xF1,
-0x11, 0x2E, 0x6B, 0x32, 0x81, 0xF1, 0xE5, 0x06, 0x90, 0xFC, 0x94,
-0x01, 0x67, 0xFF, 0x26, 0x00, 0xFD, 0xFF, 0x17, 0x00, 0xA0, 0xFF,
-0xCC, 0x00, 0xC6, 0xFE, 0x79, 0x01, 0xD2, 0xFE, 0x26, 0xFF, 0x7C,
-0x48, 0xBE, 0x08, 0xAE, 0xFA, 0xA0, 0x03, 0xA9, 0xFD, 0x52, 0x01,
-0x6B, 0xFF, 0x25, 0x00, 0x00, 0x00, 0xFD, 0xFF, 0x35, 0x00, 0x3C,
-0xFF, 0xE0, 0x01, 0x32, 0xFC, 0x1C, 0x07, 0x4B, 0xF2, 0xA0, 0x26,
-0xF2, 0x38, 0x2A, 0xF2, 0x28, 0x06, 0x1F, 0xFD, 0x39, 0x01, 0x96,
-0xFF, 0x16, 0x00, 0xFF, 0xFF, 0x0F, 0x00, 0xC2, 0xFF, 0x75, 0x00,
-0x7A, 0xFF, 0x2B, 0x00, 0x2D, 0x01, 0x61, 0xFA, 0x97, 0x46, 0xA0,
-0x0F, 0x20, 0xF8, 0xDA, 0x04, 0x10, 0xFD, 0x97, 0x01, 0x50, 0xFF,
-0x2E, 0x00, 0xFF, 0xFF, 0xFE, 0xFF, 0x36, 0x00, 0x36, 0xFF, 0xE4,
-0x01, 0x48, 0xFC, 0xB2, 0x06, 0xB9, 0xF3, 0xF3, 0x1E, 0x98, 0x3E,
-0xCF, 0xF3, 0xF3, 0x04, 0xEB, 0xFD, 0xBF, 0x00, 0xD4, 0xFF, 0xFF,
-0xFF, 0x03, 0x00, 0x08, 0x00, 0xE2, 0xFF, 0x21, 0x00, 0x23, 0x00,
-0xFA, 0xFE, 0x3A, 0x03, 0x9D, 0xF6, 0x50, 0x43, 0x00, 0x17, 0xC6,
-0xF5, 0xE6, 0x05, 0x97, 0xFC, 0xC9, 0x01, 0x3E, 0xFF, 0x34, 0x00,
-0xFE, 0xFF, 0xFE, 0xFF, 0x34, 0x00, 0x3D, 0xFF, 0xCB, 0x01, 0x93,
-0xFC, 0xEF, 0x05, 0xB0, 0xF5, 0x4B, 0x17, 0x2A, 0x43, 0x7D, 0xF6,
-0x4D, 0x03, 0xEF, 0xFE, 0x2A, 0x00, 0x1E, 0x00, 0xE3, 0xFF, 0x08,
-0x00, 0x03, 0x00, 0xFE, 0xFF, 0xD7, 0xFF, 0xBA, 0x00, 0xF4, 0xFD,
-0xE5, 0x04, 0xE4, 0xF3, 0xCA, 0x3E, 0xA7, 0x1E, 0xCA, 0xF3, 0xAC,
-0x06, 0x4A, 0xFC, 0xE4, 0x01, 0x36, 0xFF, 0x36, 0x00, 0xFE, 0xFF,
-0xFF, 0xFF, 0x2E, 0x00, 0x4F, 0xFF, 0x99, 0x01, 0x0B, 0xFD, 0xE6,
-0x04, 0x08, 0xF8, 0xE7, 0x0F, 0x7C, 0x46, 0x37, 0xFA, 0x42, 0x01,
-0x1F, 0x00, 0x81, 0xFF, 0x71, 0x00, 0xC3, 0xFF, 0x0F, 0x00, 0xFF,
-0xFF, 0x15, 0x00, 0x98, 0xFF, 0x35, 0x01, 0x25, 0xFD, 0x1E, 0x06,
-0x35, 0xF2, 0x2E, 0x39, 0x55, 0x26, 0x56, 0xF2, 0x1A, 0x07, 0x31,
-0xFC, 0xE1, 0x01, 0x3C, 0xFF, 0x35, 0x00, 0xFD, 0xFF, 0x00, 0x00,
-0x26, 0x00, 0x6A, 0xFF, 0x55, 0x01, 0xA3, 0xFD, 0xAD, 0x03, 0x94,
-0xFA, 0xFF, 0x08, 0x70, 0x48, 0xF3, 0xFE, 0xEA, 0xFE, 0x6C, 0x01,
-0xCD, 0xFE, 0xC9, 0x00, 0xA1, 0xFF, 0x17, 0x00, 0xFD, 0xFF, 0x26,
-0x00, 0x69, 0xFF, 0x91, 0x01, 0x94, 0xFC, 0xE0, 0x06, 0x84, 0xF1,
-0xAF, 0x32, 0xCA, 0x2D, 0x92, 0xF1, 0x1F, 0x07, 0x56, 0xFC, 0xBE,
-0x01, 0x51, 0xFF, 0x2E, 0x00, 0xFD, 0xFF, 0x1D, 0x00, 0x8A, 0xFF,
-0x04, 0x01, 0x50, 0xFE, 0x5A, 0x02, 0x2C, 0xFD, 0xC6, 0x02, 0xF2,
-0x48, 0x9B, 0x04, 0x61, 0xFC, 0xC3, 0x02, 0x19, 0xFE, 0x1E, 0x01,
-0x7F, 0xFF, 0x20, 0x00, 0x00, 0x00, 0xFD, 0xFF, 0x31, 0x00, 0x49,
-0xFF, 0xCC, 0x01, 0x44, 0xFC, 0x29, 0x07, 0xB9, 0xF1, 0x89, 0x2B,
-0xC3, 0x34, 0xA0, 0xF1, 0xB1, 0x06, 0xBA, 0xFC, 0x79, 0x01, 0x76,
-0xFF, 0x21, 0x00, 0xFE, 0xFF, 0x14, 0x00, 0xAC, 0xFF, 0xAE, 0x00,
-0x05, 0xFF, 0x03, 0x01, 0xAA, 0xFF, 0x63, 0xFD, 0xFD, 0x47, 0x0E,
-0x0B, 0xC8, 0xF9, 0x11, 0x04, 0x71, 0xFD, 0x6C, 0x01, 0x61, 0xFF,
-0x28, 0x00, 0x00, 0x00, 0xFD, 0xFF, 0x36, 0x00, 0x39, 0xFF, 0xE5,
-0x01, 0x33, 0xFC, 0x03, 0x07, 0xB7, 0xF2, 0xFC, 0x23, 0x03, 0x3B,
-0x9E, 0xF2, 0xCB, 0x05, 0x5F, 0xFD, 0x12, 0x01, 0xAA, 0xFF, 0x0E,
-0x00, 0x00, 0x00, 0x0C, 0x00, 0xCD, 0xFF, 0x57, 0x00, 0xB6, 0xFF,
-0xBE, 0xFF, 0xED, 0x01, 0xF5, 0xF8, 0x9B, 0x45, 0x22, 0x12, 0x48,
-0xF7, 0x3D, 0x05, 0xE2, 0xFC, 0xAB, 0x01, 0x49, 0xFF, 0x30, 0x00,
-0xFF, 0xFF, 0xFE, 0xFF, 0x36, 0x00, 0x37, 0xFF, 0xDF, 0x01, 0x5C,
-0xFC, 0x78, 0x06, 0x5A, 0xF4, 0x49, 0x1C, 0x4E, 0x40, 0x9E, 0xF4,
-0x6D, 0x04, 0x3F, 0xFE, 0x8E, 0x00, 0xED, 0xFF, 0xF6, 0xFF, 0x04,
-0x00, 0x06, 0x00, 0xEC, 0xFF, 0x06, 0x00, 0x5A, 0x00, 0x9A, 0xFE,
-0xDA, 0x03, 0x8D, 0xF5, 0xE1, 0x41, 0xA1, 0x19, 0x09, 0xF5, 0x33,
-0x06, 0x77, 0xFC, 0xD6, 0x01, 0x3A, 0xFF, 0x35, 0x00, 0xFE, 0xFF,
-0xFF, 0xFF, 0x32, 0x00, 0x42, 0xFF, 0xBC, 0x01, 0xB8, 0xFC, 0x9A,
-0x05, 0x77, 0xF6, 0xB1, 0x14, 0x77, 0x44, 0xA9, 0xF7, 0xA2, 0x02,
-0x54, 0xFF, 0xF1, 0xFF, 0x3A, 0x00, 0xD8, 0xFF, 0x0A, 0x00, 0x01,
-0x00, 0x07, 0x00, 0xC0, 0xFF, 0xE8, 0x00, 0xA6, 0xFD, 0x5F, 0x05,
-0x31, 0xF3, 0xF6, 0x3C, 0x52, 0x21, 0x37, 0xF3, 0xDD, 0x06, 0x3B,
-0xFC, 0xE6, 0x01, 0x36, 0xFF, 0x36, 0x00, 0xFD, 0xFF, 0x00, 0x00,
-0x2B, 0x00, 0x58, 0xFF, 0x83, 0x01, 0x3C, 0xFD, 0x7E, 0x04, 0xE6,
-0xF8, 0x72, 0x0D, 0x52, 0x47, 0xBE, 0xFB, 0x7A, 0x00, 0x90, 0x00,
-0x43, 0xFF, 0x8F, 0x00, 0xB7, 0xFF, 0x11, 0x00, 0xFE, 0xFF, 0x1C,
-0x00, 0x86, 0xFF, 0x59, 0x01, 0xEC, 0xFC, 0x6F, 0x06, 0xDC, 0xF1,
-0x04, 0x37, 0xF3, 0x28, 0xFC, 0xF1, 0x28, 0x07, 0x37, 0xFC, 0xD8,
-0x01, 0x41, 0xFF, 0x33, 0x00, 0xFD, 0xFF, 0x00, 0x00, 0x23, 0x00,
-0x74, 0xFF, 0x3A, 0x01, 0xDD, 0xFD, 0x39, 0x03, 0x7B, 0xFB, 0xC1,
-0x06, 0xC7, 0x48, 0xCF, 0x00, 0x0D, 0xFE, 0xE3, 0x01, 0x8E, 0xFE,
-0xE7, 0x00, 0x95, 0xFF, 0x1A, 0x00, 0xFD, 0xFF, 0x2A, 0x00, 0x5C,
-0xFF, 0xAA, 0x01, 0x71, 0xFC, 0x07, 0x07, 0x7E, 0xF1, 0x44, 0x30,
-0x44, 0x30, 0x7E, 0xF1, 0x07, 0x07, 0x71, 0xFC, 0xAA, 0x01, 0x5C,
-0xFF, 0x2A, 0x00, 0xFD, 0xFF, 0x1A, 0x00, 0x95, 0xFF, 0xE7, 0x00,
-0x8E, 0xFE, 0xE3, 0x01, 0x0D, 0xFE, 0xCF, 0x00, 0xC7, 0x48, 0xC1,
-0x06, 0x7B, 0xFB, 0x39, 0x03, 0xDD, 0xFD, 0x3A, 0x01, 0x74, 0xFF,
-0x23, 0x00, 0x00, 0x00, 0xFD, 0xFF, 0x33, 0x00, 0x41, 0xFF, 0xD8,
-0x01, 0x37, 0xFC, 0x28, 0x07, 0xFC, 0xF1, 0xF3, 0x28, 0x04, 0x37,
-0xDC, 0xF1, 0x6F, 0x06, 0xEC, 0xFC, 0x59, 0x01, 0x86, 0xFF, 0x1C,
-0x00, 0xFE, 0xFF, 0x11, 0x00, 0xB7, 0xFF, 0x8F, 0x00, 0x43, 0xFF,
-0x90, 0x00, 0x7A, 0x00, 0xBE, 0xFB, 0x52, 0x47, 0x72, 0x0D, 0xE6,
-0xF8, 0x7E, 0x04, 0x3C, 0xFD, 0x83, 0x01, 0x58, 0xFF, 0x2B, 0x00,
-0x00, 0x00, 0xFD, 0xFF, 0x36, 0x00, 0x36, 0xFF, 0xE6, 0x01, 0x3B,
-0xFC, 0xDD, 0x06, 0x37, 0xF3, 0x52, 0x21, 0xF6, 0x3C, 0x31, 0xF3,
-0x5F, 0x05, 0xA6, 0xFD, 0xE8, 0x00, 0xC0, 0xFF, 0x07, 0x00, 0x01,
-0x00, 0x0A, 0x00, 0xD8, 0xFF, 0x3A, 0x00, 0xF1, 0xFF, 0x54, 0xFF,
-0xA2, 0x02, 0xA9, 0xF7, 0x77, 0x44, 0xB1, 0x14, 0x77, 0xF6, 0x9A,
-0x05, 0xB8, 0xFC, 0xBC, 0x01, 0x42, 0xFF, 0x32, 0x00, 0xFF, 0xFF,
-0xFE, 0xFF, 0x35, 0x00, 0x3A, 0xFF, 0xD6, 0x01, 0x77, 0xFC, 0x33,
-0x06, 0x09, 0xF5, 0xA1, 0x19, 0xE1, 0x41, 0x8D, 0xF5, 0xDA, 0x03,
-0x9A, 0xFE, 0x5A, 0x00, 0x06, 0x00, 0xEC, 0xFF, 0x06, 0x00, 0x04,
-0x00, 0xF6, 0xFF, 0xED, 0xFF, 0x8E, 0x00, 0x3F, 0xFE, 0x6D, 0x04,
-0x9E, 0xF4, 0x4E, 0x40, 0x49, 0x1C, 0x5A, 0xF4, 0x78, 0x06, 0x5C,
-0xFC, 0xDF, 0x01, 0x37, 0xFF, 0x36, 0x00, 0xFE, 0xFF, 0xFF, 0xFF,
-0x30, 0x00, 0x49, 0xFF, 0xAB, 0x01, 0xE2, 0xFC, 0x3D, 0x05, 0x48,
-0xF7, 0x22, 0x12, 0x9B, 0x45, 0xF5, 0xF8, 0xED, 0x01, 0xBE, 0xFF,
-0xB6, 0xFF, 0x57, 0x00, 0xCD, 0xFF, 0x0C, 0x00, 0x00, 0x00, 0x0E,
-0x00, 0xAA, 0xFF, 0x12, 0x01, 0x5F, 0xFD, 0xCB, 0x05, 0x9E, 0xF2,
-0x03, 0x3B, 0xFC, 0x23, 0xB7, 0xF2, 0x03, 0x07, 0x33, 0xFC, 0xE5,
-0x01, 0x39, 0xFF, 0x36, 0x00, 0xFD, 0xFF, 0x00, 0x00, 0x28, 0x00,
-0x61, 0xFF, 0x6C, 0x01, 0x71, 0xFD, 0x11, 0x04, 0xC8, 0xF9, 0x0E,
-0x0B, 0xFD, 0x47, 0x63, 0xFD, 0xAA, 0xFF, 0x03, 0x01, 0x05, 0xFF,
-0xAE, 0x00, 0xAC, 0xFF, 0x14, 0x00, 0xFE, 0xFF, 0x21, 0x00, 0x76,
-0xFF, 0x79, 0x01, 0xBA, 0xFC, 0xB1, 0x06, 0xA0, 0xF1, 0xC3, 0x34,
-0x89, 0x2B, 0xB9, 0xF1, 0x29, 0x07, 0x44, 0xFC, 0xCC, 0x01, 0x49,
-0xFF, 0x31, 0x00, 0xFD, 0xFF, 0x00, 0x00, 0x20, 0x00, 0x7F, 0xFF,
-0x1E, 0x01, 0x19, 0xFE, 0xC3, 0x02, 0x61, 0xFC, 0x9B, 0x04, 0xF2,
-0x48, 0xC6, 0x02, 0x2C, 0xFD, 0x5A, 0x02, 0x50, 0xFE, 0x04, 0x01,
-0x8A, 0xFF, 0x1D, 0x00, 0xFD, 0xFF, 0x2E, 0x00, 0x51, 0xFF, 0xBE,
-0x01, 0x56, 0xFC, 0x1F, 0x07, 0x92, 0xF1, 0xCA, 0x2D, 0xAF, 0x32,
-0x84, 0xF1, 0xE0, 0x06, 0x94, 0xFC, 0x91, 0x01, 0x69, 0xFF, 0x26,
-0x00, 0xFD, 0xFF, 0x17, 0x00, 0xA1, 0xFF, 0xC9, 0x00, 0xCD, 0xFE,
-0x6C, 0x01, 0xEA, 0xFE, 0xF3, 0xFE, 0x70, 0x48, 0xFF, 0x08, 0x94,
-0xFA, 0xAD, 0x03, 0xA3, 0xFD, 0x55, 0x01, 0x6A, 0xFF, 0x26, 0x00,
-0x00, 0x00, 0xFD, 0xFF, 0x35, 0x00, 0x3C, 0xFF, 0xE1, 0x01, 0x31,
-0xFC, 0x1A, 0x07, 0x56, 0xF2, 0x55, 0x26, 0x2E, 0x39, 0x35, 0xF2,
-0x1E, 0x06, 0x25, 0xFD, 0x35, 0x01, 0x98, 0xFF, 0x15, 0x00, 0xFF,
-0xFF, 0x0F, 0x00, 0xC3, 0xFF, 0x71, 0x00, 0x81, 0xFF, 0x1F, 0x00,
-0x42, 0x01, 0x37, 0xFA, 0x7C, 0x46, 0xE7, 0x0F, 0x08, 0xF8, 0xE6,
-0x04, 0x0B, 0xFD, 0x99, 0x01, 0x4F, 0xFF, 0x2E, 0x00, 0xFF, 0xFF,
-0xFE, 0xFF, 0x36, 0x00, 0x36, 0xFF, 0xE4, 0x01, 0x4A, 0xFC, 0xAC,
-0x06, 0xCA, 0xF3, 0xA7, 0x1E, 0xCA, 0x3E, 0xE4, 0xF3, 0xE5, 0x04,
-0xF4, 0xFD, 0xBA, 0x00, 0xD7, 0xFF, 0xFE, 0xFF, 0x03, 0x00, 0x08,
-0x00, 0xE3, 0xFF, 0x1E, 0x00, 0x2A, 0x00, 0xEF, 0xFE, 0x4D, 0x03,
-0x7D, 0xF6, 0x2A, 0x43, 0x4B, 0x17, 0xB0, 0xF5, 0xEF, 0x05, 0x93,
-0xFC, 0xCB, 0x01, 0x3D, 0xFF, 0x34, 0x00, 0xFE, 0xFF, 0xFE, 0xFF,
-0x34, 0x00, 0x3E, 0xFF, 0xC9, 0x01, 0x97, 0xFC, 0xE6, 0x05, 0xC6,
-0xF5, 0x00, 0x17, 0x50, 0x43, 0x9D, 0xF6, 0x3A, 0x03, 0xFA, 0xFE,
-0x23, 0x00, 0x21, 0x00, 0xE2, 0xFF, 0x08, 0x00, 0x03, 0x00, 0xFF,
-0xFF, 0xD4, 0xFF, 0xBF, 0x00, 0xEB, 0xFD, 0xF3, 0x04, 0xCF, 0xF3,
-0x98, 0x3E, 0xF3, 0x1E, 0xB9, 0xF3, 0xB2, 0x06, 0x48, 0xFC, 0xE4,
-0x01, 0x36, 0xFF, 0x36, 0x00, 0xFE, 0xFF, 0xFF, 0xFF, 0x2E, 0x00,
-0x50, 0xFF, 0x97, 0x01, 0x10, 0xFD, 0xDA, 0x04, 0x20, 0xF8, 0xA0,
-0x0F, 0x97, 0x46, 0x61, 0xFA, 0x2D, 0x01, 0x2B, 0x00, 0x7A, 0xFF,
-0x75, 0x00, 0xC2, 0xFF, 0x0F, 0x00, 0xFF, 0xFF, 0x16, 0x00, 0x96,
-0xFF, 0x39, 0x01, 0x1F, 0xFD, 0x28, 0x06, 0x2A, 0xF2, 0xF2, 0x38,
-0xA0, 0x26, 0x4B, 0xF2, 0x1C, 0x07, 0x32, 0xFC, 0xE0, 0x01, 0x3C,
-0xFF, 0x35, 0x00, 0xFD, 0xFF, 0x00, 0x00, 0x25, 0x00, 0x6B, 0xFF,
-0x52, 0x01, 0xA9, 0xFD, 0xA0, 0x03, 0xAE, 0xFA, 0xBE, 0x08, 0x7C,
-0x48, 0x26, 0xFF, 0xD2, 0xFE, 0x79, 0x01, 0xC6, 0xFE, 0xCC, 0x00,
-0xA0, 0xFF, 0x17, 0x00, 0xFD, 0xFF, 0x26, 0x00, 0x67, 0xFF, 0x94,
-0x01, 0x90, 0xFC, 0xE5, 0x06, 0x81, 0xF1, 0x6B, 0x32, 0x11, 0x2E,
-0x8E, 0xF1, 0x1D, 0x07, 0x58, 0xFC, 0xBC, 0x01, 0x52, 0xFF, 0x2E,
-0x00, 0xFD, 0xFF, 0x1D, 0x00, 0x8B, 0xFF, 0x01, 0x01, 0x56, 0xFE,
-0x4D, 0x02, 0x45, 0xFD, 0x8D, 0x02, 0xF0, 0x48, 0xD7, 0x04, 0x47,
-0xFC, 0xD1, 0x02, 0x12, 0xFE, 0x21, 0x01, 0x7E, 0xFF, 0x20, 0x00,
-0x00, 0x00, 0xFD, 0xFF, 0x31, 0x00, 0x48, 0xFF, 0xCE, 0x01, 0x42,
-0xFC, 0x2A, 0x07, 0xBF, 0xF1, 0x40, 0x2B, 0x05, 0x35, 0xA6, 0xF1,
-0xAB, 0x06, 0xBF, 0xFC, 0x75, 0x01, 0x77, 0xFF, 0x21, 0x00, 0xFE,
-0xFF, 0x14, 0x00, 0xAD, 0xFF, 0xAA, 0x00, 0x0C, 0xFF, 0xF7, 0x00,
-0xC1, 0xFF, 0x33, 0xFD, 0xEC, 0x47, 0x51, 0x0B, 0xAF, 0xF9, 0x1D,
-0x04, 0x6B, 0xFD, 0x6E, 0x01, 0x60, 0xFF, 0x29, 0x00, 0x00, 0x00,
-0xFD, 0xFF, 0x36, 0x00, 0x38, 0xFF, 0xE5, 0x01, 0x33, 0xFC, 0xFF,
-0x06, 0xC4, 0xF2, 0xB0, 0x23, 0x3B, 0x3B, 0xAD, 0xF2, 0xBF, 0x05,
-0x66, 0xFD, 0x0E, 0x01, 0xAC, 0xFF, 0x0E, 0x00, 0x00, 0x00, 0x0C,
-0x00, 0xCE, 0xFF, 0x54, 0x00, 0xBD, 0xFF, 0xB2, 0xFF, 0x01, 0x02,
-0xCF, 0xF8, 0x7D, 0x45, 0x6B, 0x12, 0x30, 0xF7, 0x48, 0x05, 0xDD,
-0xFC, 0xAD, 0x01, 0x48, 0xFF, 0x30, 0x00, 0xFF, 0xFF, 0xFE, 0xFF,
-0x36, 0x00, 0x37, 0xFF, 0xDE, 0x01, 0x5F, 0xFC, 0x70, 0x06, 0x6C,
-0xF4, 0xFD, 0x1B, 0x7D, 0x40, 0xB7, 0xF4, 0x5D, 0x04, 0x49, 0xFE,
-0x88, 0x00, 0xEF, 0xFF, 0xF5, 0xFF, 0x04, 0x00, 0x06, 0x00, 0xED,
-0xFF, 0x04, 0x00, 0x60, 0x00, 0x90, 0xFE, 0xEB, 0x03, 0x71, 0xF5,
-0xB7, 0x41, 0xED, 0x19, 0xF5, 0xF4, 0x3B, 0x06, 0x73, 0xFC, 0xD7,
-0x01, 0x39, 0xFF, 0x35, 0x00, 0xFE, 0xFF, 0xFF, 0xFF, 0x32, 0x00,
-0x43, 0xFF, 0xBA, 0x01, 0xBC, 0xFC, 0x90, 0x05, 0x8E, 0xF6, 0x68,
-0x14, 0x99, 0x44, 0xCD, 0xF7, 0x8F, 0x02, 0x60, 0xFF, 0xEA, 0xFF,
-0x3E, 0x00, 0xD7, 0xFF, 0x0A, 0x00, 0x01, 0x00, 0x07, 0x00, 0xBD,
-0xFF, 0xED, 0x00, 0x9E, 0xFD, 0x6C, 0x05, 0x1F, 0xF3, 0xC0, 0x3C,
-0x9E, 0x21, 0x28, 0xF3, 0xE2, 0x06, 0x3A, 0xFC, 0xE6, 0x01, 0x37,
-0xFF, 0x36, 0x00, 0xFD, 0xFF, 0x00, 0x00, 0x2B, 0x00, 0x59, 0xFF,
-0x81, 0x01, 0x42, 0xFD, 0x72, 0x04, 0xFF, 0xF8, 0x2D, 0x0D, 0x69,
-0x47, 0xEB, 0xFB, 0x63, 0x00, 0x9D, 0x00, 0x3C, 0xFF, 0x93, 0x00,
-0xB6, 0xFF, 0x12, 0x00, 0xFE, 0xFF, 0x1C, 0x00, 0x84, 0xFF, 0x5C,
-0x01, 0xE6, 0xFC, 0x77, 0x06, 0xD4, 0xF1, 0xC6, 0x36, 0x3E, 0x29,
-0xF3, 0xF1, 0x29, 0x07, 0x38, 0xFC, 0xD7, 0x01, 0x42, 0xFF, 0x33,
-0x00, 0xFD, 0xFF, 0x00, 0x00, 0x22, 0x00, 0x76, 0xFF, 0x37, 0x01,
-0xE4, 0xFD, 0x2C, 0x03, 0x94, 0xFB, 0x83, 0x06, 0xCE, 0x48, 0x05,
-0x01, 0xF5, 0xFD, 0xF0, 0x01, 0x87, 0xFE, 0xEA, 0x00, 0x94, 0xFF,
-0x1A, 0x00, 0xFD, 0xFF, 0x2B, 0x00, 0x5A, 0xFF, 0xAC, 0x01, 0x6E,
-0xFC, 0x0A, 0x07, 0x7E, 0xF1, 0xFF, 0x2F, 0x8A, 0x30, 0x7D, 0xF1,
-0x03, 0x07, 0x75, 0xFC, 0xA7, 0x01, 0x5D, 0xFF, 0x2A, 0x00, 0xFD,
-0xFF, 0x1A, 0x00, 0x96, 0xFF, 0xE3, 0x00, 0x95, 0xFE, 0xD5, 0x01,
-0x26, 0xFE, 0x98, 0x00, 0xBF, 0x48, 0x00, 0x07, 0x61, 0xFB, 0x46,
-0x03, 0xD6, 0xFD, 0x3D, 0x01, 0x73, 0xFF, 0x23, 0x00, 0x00, 0x00,
-0xFD, 0xFF, 0x33, 0x00, 0x41, 0xFF, 0xDA, 0x01, 0x36, 0xFC, 0x27,
-0x07, 0x05, 0xF2, 0xAA, 0x28, 0x44, 0x37, 0xE4, 0xF1, 0x67, 0x06,
-0xF2, 0xFC, 0x55, 0x01, 0x88, 0xFF, 0x1B, 0x00, 0xFE, 0xFF, 0x11,
-0x00, 0xB9, 0xFF, 0x8C, 0x00, 0x4A, 0xFF, 0x83, 0x00, 0x91, 0x00,
-0x91, 0xFB, 0x3D, 0x47, 0xB7, 0x0D, 0xCD, 0xF8, 0x89, 0x04, 0x36,
-0xFD, 0x86, 0x01, 0x57, 0xFF, 0x2B, 0x00, 0x00, 0x00, 0xFD, 0xFF,
-0x36, 0x00, 0x36, 0xFF, 0xE6, 0x01, 0x3C, 0xFC, 0xD8, 0x06, 0x47,
-0xF3, 0x06, 0x21, 0x2A, 0x3D, 0x44, 0xF3, 0x52, 0x05, 0xAE, 0xFD,
-0xE3, 0x00, 0xC2, 0xFF, 0x06, 0x00, 0x01, 0x00, 0x0A, 0x00, 0xD9,
-0xFF, 0x37, 0x00, 0xF7, 0xFF, 0x49, 0xFF, 0xB6, 0x02, 0x86, 0xF7,
-0x53, 0x44, 0xFB, 0x14, 0x61, 0xF6, 0xA4, 0x05, 0xB4, 0xFC, 0xBE,
-0x01, 0x42, 0xFF, 0x32, 0x00, 0xFF, 0xFF, 0xFE, 0xFF, 0x35, 0x00,
-0x3A, 0xFF, 0xD4, 0x01, 0x7A, 0xFC, 0x2B, 0x06, 0x1E, 0xF5, 0x56,
-0x19, 0x0C, 0x42, 0xAA, 0xF5, 0xC9, 0x03, 0xA4, 0xFE, 0x54, 0x00,
-0x09, 0x00, 0xEB, 0xFF, 0x06, 0x00, 0x04, 0x00, 0xF7, 0xFF, 0xEA,
-0xFF, 0x93, 0x00, 0x36, 0xFE, 0x7D, 0x04, 0x85, 0xF4, 0x1F, 0x40,
-0x94, 0x1C, 0x47, 0xF4, 0x7E, 0x06, 0x5A, 0xFC, 0xDF, 0x01, 0x37,
-0xFF, 0x36, 0x00, 0xFE, 0xFF, 0xFF, 0xFF, 0x30, 0x00, 0x4A, 0xFF,
-0xA9, 0x01, 0xE7, 0xFC, 0x33, 0x05, 0x60, 0xF7, 0xDA, 0x11, 0xB8,
-0x45, 0x1C, 0xF9, 0xD8, 0x01, 0xCA, 0xFF, 0xAF, 0xFF, 0x5A, 0x00,
-0xCC, 0xFF, 0x0D, 0x00, 0x00, 0x00, 0x0F, 0x00, 0xA8, 0xFF, 0x17,
-0x01, 0x57, 0xFD, 0xD6, 0x05, 0x90, 0xF2, 0xC8, 0x3A, 0x46, 0x24,
-0xAA, 0xF2, 0x06, 0x07, 0x32, 0xFC, 0xE5, 0x01, 0x39, 0xFF, 0x36,
-0x00, 0xFD, 0xFF, 0x00, 0x00, 0x28, 0x00, 0x62, 0xFF, 0x69, 0x01,
-0x77, 0xFD, 0x04, 0x04, 0xE2, 0xF9, 0xCB, 0x0A, 0x0D, 0x48, 0x94,
-0xFD, 0x92, 0xFF, 0x10, 0x01, 0xFE, 0xFE, 0xB1, 0x00, 0xAA, 0xFF,
-0x15, 0x00, 0xFE, 0xFF, 0x22, 0x00, 0x74, 0xFF, 0x7C, 0x01, 0xB5,
-0xFC, 0xB8, 0x06, 0x9C, 0xF1, 0x81, 0x34, 0xD1, 0x2B, 0xB3, 0xF1,
-0x29, 0x07, 0x46, 0xFC, 0xCA, 0x01, 0x4A, 0xFF, 0x30, 0x00, 0xFD,
-0xFF, 0x00, 0x00, 0x1F, 0x00, 0x81, 0xFF, 0x1B, 0x01, 0x20, 0xFE,
-0xB6, 0x02, 0x7A, 0xFC, 0x5F, 0x04, 0xF4, 0x48, 0xFF, 0x02, 0x13,
-0xFD, 0x67, 0x02, 0x49, 0xFE, 0x07, 0x01, 0x88, 0xFF, 0x1D, 0x00,
-0xFD, 0xFF, 0x2E, 0x00, 0x50, 0xFF, 0xC0, 0x01, 0x53, 0xFC, 0x21,
-0x07, 0x96, 0xF1, 0x82, 0x2D, 0xF2, 0x32, 0x86, 0xF1, 0xDB, 0x06,
-0x99, 0xFC, 0x8E, 0x01, 0x6A, 0xFF, 0x25, 0x00, 0xFD, 0xFF, 0x16,
-0x00, 0xA2, 0xFF, 0xC5, 0x00, 0xD4, 0xFE, 0x5F, 0x01, 0x03, 0xFF,
-0xBF, 0xFE, 0x63, 0x48, 0x40, 0x09, 0x7B, 0xFA, 0xB9, 0x03, 0x9D,
-0xFD, 0x58, 0x01, 0x69, 0xFF, 0x26, 0x00, 0x00, 0x00, 0xFD, 0xFF,
-0x35, 0x00, 0x3B, 0xFF, 0xE2, 0x01, 0x31, 0xFC, 0x17, 0x07, 0x61,
-0xF2, 0x0A, 0x26, 0x6A, 0x39, 0x41, 0xF2, 0x15, 0x06, 0x2C, 0xFD,
-0x31, 0x01, 0x9B, 0xFF, 0x14, 0x00, 0xFF, 0xFF, 0x0E, 0x00, 0xC4,
-0xFF, 0x6E, 0x00, 0x87, 0xFF, 0x13, 0x00, 0x58, 0x01, 0x0D, 0xFA,
-0x61, 0x46, 0x2D, 0x10, 0xF0, 0xF7, 0xF1, 0x04, 0x05, 0xFD, 0x9C,
-0x01, 0x4E, 0xFF, 0x2E, 0x00, 0xFF, 0xFF, 0xFE, 0xFF, 0x36, 0x00,
-0x36, 0xFF, 0xE3, 0x01, 0x4C, 0xFC, 0xA6, 0x06, 0xDB, 0xF3, 0x5B,
-0x1E, 0xFC, 0x3E, 0xFA, 0xF3, 0xD7, 0x04, 0xFD, 0xFD, 0xB4, 0x00,
-0xD9, 0xFF, 0xFD, 0xFF, 0x03, 0x00, 0x08, 0x00, 0xE4, 0xFF, 0x1B,
-0x00, 0x30, 0x00, 0xE4, 0xFE, 0x5F, 0x03, 0x5E, 0xF6, 0x02, 0x43,
-0x96, 0x17, 0x9B, 0xF5, 0xF8, 0x05, 0x8F, 0xFC, 0xCC, 0x01, 0x3D,
-0xFF, 0x34, 0x00, 0xFE, 0xFF, 0xFF, 0xFF, 0x33, 0x00, 0x3E, 0xFF,
-0xC8, 0x01, 0x9B, 0xFC, 0xDD, 0x05, 0xDC, 0xF5, 0xB6, 0x16, 0x77,
-0x43, 0xBD, 0xF6, 0x28, 0x03, 0x05, 0xFF, 0x1D, 0x00, 0x25, 0x00,
-0xE1, 0xFF, 0x08, 0x00, 0x02, 0x00, 0x00, 0x00, 0xD2, 0xFF, 0xC4,
-0x00, 0xE2, 0xFD, 0x01, 0x05, 0xBA, 0xF3, 0x64, 0x3E, 0x3F, 0x1F,
-0xA8, 0xF3, 0xB8, 0x06, 0x46, 0xFC, 0xE5, 0x01, 0x36, 0xFF, 0x36,
-0x00, 0xFD, 0xFF, 0xFF, 0xFF, 0x2D, 0x00, 0x51, 0xFF, 0x95, 0x01,
-0x15, 0xFD, 0xCF, 0x04, 0x39, 0xF8, 0x59, 0x0F, 0xAF, 0x46, 0x8B,
-0xFA, 0x17, 0x01, 0x38, 0x00, 0x73, 0xFF, 0x78, 0x00, 0xC0, 0xFF,
-0x0F, 0x00, 0xFF, 0xFF, 0x16, 0x00, 0x94, 0xFF, 0x3D, 0x01, 0x18,
-0xFD, 0x32, 0x06, 0x1F, 0xF2, 0xB5, 0x38, 0xEB, 0x26, 0x40, 0xF2,
-0x1E, 0x07, 0x32, 0xFC, 0xDF, 0x01, 0x3D, 0xFF, 0x35, 0x00, 0xFD,
-0xFF, 0x00, 0x00, 0x25, 0x00, 0x6C, 0xFF, 0x4F, 0x01, 0xB0, 0xFD,
-0x93, 0x03, 0xC7, 0xFA, 0x7D, 0x08, 0x86, 0x48, 0x5A, 0xFF, 0xBA,
-0xFE, 0x86, 0x01, 0xBF, 0xFE, 0xCF, 0x00, 0x9E, 0xFF, 0x17, 0x00,
-0xFD, 0xFF, 0x27, 0x00, 0x66, 0xFF, 0x97, 0x01, 0x8C, 0xFC, 0xEA,
-0x06, 0x80, 0xF1, 0x26, 0x32, 0x58, 0x2E, 0x8B, 0xF1, 0x1B, 0x07,
-0x5B, 0xFC, 0xBA, 0x01, 0x53, 0xFF, 0x2D, 0x00, 0xFD, 0xFF, 0x1C,
-0x00, 0x8C, 0xFF, 0xFE, 0x00, 0x5D, 0xFE, 0x3F, 0x02, 0x5E, 0xFD,
-0x54, 0x02, 0xEC, 0x48, 0x13, 0x05, 0x2E, 0xFC, 0xDE, 0x02, 0x0C,
-0xFE, 0x24, 0x01, 0x7D, 0xFF, 0x20, 0x00, 0x00, 0x00, 0xFD, 0xFF,
-0x31, 0x00, 0x47, 0xFF, 0xCF, 0x01, 0x40, 0xFC, 0x2A, 0x07, 0xC6,
-0xF1, 0xF7, 0x2A, 0x46, 0x35, 0xAB, 0xF1, 0xA4, 0x06, 0xC4, 0xFC,
-0x72, 0x01, 0x79, 0xFF, 0x20, 0x00, 0xFE, 0xFF, 0x14, 0x00, 0xAE,
-0xFF, 0xA7, 0x00, 0x12, 0xFF, 0xEA, 0x00, 0xD9, 0xFF, 0x03, 0xFD,
-0xDC, 0x47, 0x95, 0x0B, 0x96, 0xF9, 0x29, 0x04, 0x65, 0xFD, 0x71,
-0x01, 0x5F, 0xFF, 0x29, 0x00, 0x00, 0x00, 0xFD, 0xFF, 0x36, 0x00,
-0x38, 0xFF, 0xE6, 0x01, 0x34, 0xFC, 0xFB, 0x06, 0xD2, 0xF2, 0x64,
-0x23, 0x73, 0x3B, 0xBC, 0xF2, 0xB4, 0x05, 0x6E, 0xFD, 0x09, 0x01,
-0xAF, 0xFF, 0x0D, 0x00, 0x00, 0x00, 0x0C, 0x00, 0xD0, 0xFF, 0x51,
-0x00, 0xC3, 0xFF, 0xA6, 0xFF, 0x16, 0x02, 0xA9, 0xF8, 0x5C, 0x45,
-0xB2, 0x12, 0x19, 0xF7, 0x52, 0x05, 0xD8, 0xFC, 0xAF, 0x01, 0x47,
-0xFF, 0x30, 0x00, 0xFF, 0xFF, 0xFE, 0xFF, 0x36, 0x00, 0x38, 0xFF,
-0xDD, 0x01, 0x62, 0xFC, 0x69, 0x06, 0x7F, 0xF4, 0xB2, 0x1B, 0xAB,
-0x40, 0xD0, 0xF4, 0x4E, 0x04, 0x53, 0xFE, 0x83, 0x00, 0xF2, 0xFF,
-0xF4, 0xFF, 0x05, 0x00, 0x06, 0x00, 0xEE, 0xFF, 0x01, 0x00, 0x66,
-0x00, 0x85, 0xFE, 0xFC, 0x03, 0x55, 0xF5, 0x8C, 0x41, 0x38, 0x1A,
-0xE1, 0xF4, 0x43, 0x06, 0x70, 0xFC, 0xD8, 0x01, 0x39, 0xFF, 0x35,
-0x00, 0xFE, 0xFF, 0xFF, 0xFF, 0x32, 0x00, 0x44, 0xFF, 0xB9, 0x01,
-0xC1, 0xFC, 0x86, 0x05, 0xA5, 0xF6, 0x1E, 0x14, 0xBA, 0x44, 0xF0,
-0xF7, 0x7B, 0x02, 0x6B, 0xFF, 0xE4, 0xFF, 0x41, 0x00, 0xD6, 0xFF,
-0x0B, 0x00, 0x01, 0x00, 0x08, 0x00, 0xBB, 0xFF, 0xF1, 0x00, 0x96,
-0xFD, 0x78, 0x05, 0x0E, 0xF3, 0x8A, 0x3C, 0xEA, 0x21, 0x19, 0xF3,
-0xE6, 0x06, 0x38, 0xFC, 0xE6, 0x01, 0x37, 0xFF, 0x36, 0x00, 0xFD,
-0xFF, 0x00, 0x00, 0x2B, 0x00, 0x5A, 0xFF, 0x7E, 0x01, 0x48, 0xFD,
-0x66, 0x04, 0x18, 0xF9, 0xE8, 0x0C, 0x7C, 0x47, 0x19, 0xFC, 0x4D,
-0x00, 0xA9, 0x00, 0x35, 0xFF, 0x96, 0x00, 0xB5, 0xFF, 0x12, 0x00,
-0xFE, 0xFF, 0x1D, 0x00, 0x82, 0xFF, 0x60, 0x01, 0xE0, 0xFC, 0x7F,
-0x06, 0xCC, 0xF1, 0x85, 0x36, 0x87, 0x29, 0xEB, 0xF1, 0x2A, 0x07,
-0x39, 0xFC, 0xD6, 0x01, 0x43, 0xFF, 0x33, 0x00, 0xFD, 0xFF, 0x00,
-0x00, 0x22, 0x00, 0x77, 0xFF, 0x34, 0x01, 0xEA, 0xFD, 0x1F, 0x03,
-0xAE, 0xFB, 0x45, 0x06, 0xD5, 0x48, 0x3C, 0x01, 0xDC, 0xFD, 0xFD,
-0x01, 0x80, 0xFE, 0xED, 0x00, 0x93, 0xFF, 0x1B, 0x00, 0xFD, 0xFF,
-0x2B, 0x00, 0x59, 0xFF, 0xAE, 0x01, 0x6A, 0xFC, 0x0D, 0x07, 0x80,
-0xF1, 0xB8, 0x2F, 0xCF, 0x30, 0x7D, 0xF1, 0xFF, 0x06, 0x78, 0xFC,
-0xA5, 0x01, 0x5F, 0xFF, 0x29, 0x00, 0xFD, 0xFF, 0x19, 0x00, 0x98,
-0xFF, 0xE0, 0x00, 0x9C, 0xFE, 0xC8, 0x01, 0x3F, 0xFE, 0x62, 0x00,
-0xB8, 0x48, 0x3F, 0x07, 0x47, 0xFB, 0x53, 0x03, 0xD0, 0xFD, 0x40,
-0x01, 0x72, 0xFF, 0x23, 0x00, 0x00, 0x00, 0xFD, 0xFF, 0x34, 0x00,
-0x40, 0xFF, 0xDB, 0x01, 0x35, 0xFC, 0x26, 0x07, 0x0E, 0xF2, 0x60,
-0x28, 0x82, 0x37, 0xED, 0xF1, 0x5E, 0x06, 0xF8, 0xFC, 0x51, 0x01,
-0x8A, 0xFF, 0x1A, 0x00, 0xFF, 0xFF, 0x11, 0x00, 0xBA, 0xFF, 0x89,
-0x00, 0x51, 0xFF, 0x77, 0x00, 0xA7, 0x00, 0x64, 0xFB, 0x26, 0x47,
-0xFC, 0x0D, 0xB4, 0xF8, 0x95, 0x04, 0x31, 0xFD, 0x88, 0x01, 0x56,
-0xFF, 0x2C, 0x00, 0xFF, 0xFF, 0xFD, 0xFF, 0x36, 0x00, 0x36, 0xFF,
-0xE6, 0x01, 0x3E, 0xFC, 0xD3, 0x06, 0x56, 0xF3, 0xBA, 0x20, 0x61,
-0x3D, 0x56, 0xF3, 0x45, 0x05, 0xB7, 0xFD, 0xDE, 0x00, 0xC5, 0xFF,
-0x05, 0x00, 0x02, 0x00, 0x09, 0x00, 0xDB, 0xFF, 0x34, 0x00, 0xFE,
-0xFF, 0x3D, 0xFF, 0xC9, 0x02, 0x64, 0xF7, 0x2F, 0x44, 0x44, 0x15,
-0x4A, 0xF6, 0xAD, 0x05, 0xAF, 0xFC, 0xC0, 0x01, 0x41, 0xFF, 0x32,
-0x00, 0xFF, 0xFF, 0xFE, 0xFF, 0x35, 0x00, 0x3A, 0xFF, 0xD3, 0x01,
-0x7D, 0xFC, 0x23, 0x06, 0x32, 0xF5, 0x0C, 0x19, 0x38, 0x42, 0xC7,
-0xF5, 0xB8, 0x03, 0xAF, 0xFE, 0x4E, 0x00, 0x0C, 0x00, 0xEA, 0xFF,
-0x06, 0x00, 0x04, 0x00, 0xF8, 0xFF, 0xE7, 0xFF, 0x99, 0x00, 0x2C,
-0xFE, 0x8C, 0x04, 0x6D, 0xF4, 0xF0, 0x3F, 0xE0, 0x1C, 0x34, 0xF4,
-0x85, 0x06, 0x57, 0xFC, 0xE0, 0x01, 0x37, 0xFF, 0x36, 0x00, 0xFE,
-0xFF, 0xFF, 0xFF, 0x2F, 0x00, 0x4A, 0xFF, 0xA7, 0x01, 0xEC, 0xFC,
-0x28, 0x05, 0x77, 0xF7, 0x92, 0x11, 0xD7, 0x45, 0x43, 0xF9, 0xC3,
-0x01, 0xD6, 0xFF, 0xA9, 0xFF, 0x5E, 0x00, 0xCB, 0xFF, 0x0D, 0x00,
-0x00, 0x00, 0x10, 0x00, 0xA6, 0xFF, 0x1B, 0x01, 0x50, 0xFD, 0xE1,
-0x05, 0x82, 0xF2, 0x8F, 0x3A, 0x92, 0x24, 0x9D, 0xF2, 0x09, 0x07,
-0x32, 0xFC, 0xE4, 0x01, 0x39, 0xFF, 0x36, 0x00, 0xFD, 0xFF, 0x00,
-0x00, 0x28, 0x00, 0x63, 0xFF, 0x66, 0x01, 0x7D, 0xFD, 0xF8, 0x03,
-0xFB, 0xF9, 0x89, 0x0A, 0x1D, 0x48, 0xC5, 0xFD, 0x7A, 0xFF, 0x1D,
-0x01, 0xF7, 0xFE, 0xB4, 0x00, 0xA9, 0xFF, 0x15, 0x00, 0xFE, 0xFF,
-0x23, 0x00, 0x72, 0xFF, 0x7F, 0x01, 0xB0, 0xFC, 0xBE, 0x06, 0x97,
-0xF1, 0x3F, 0x34, 0x19, 0x2C, 0xAD, 0xF1, 0x28, 0x07, 0x48, 0xFC,
-0xC9, 0x01, 0x4B, 0xFF, 0x30, 0x00, 0xFD, 0xFF, 0x00, 0x00, 0x1F,
-0x00, 0x82, 0xFF, 0x18, 0x01, 0x27, 0xFE, 0xA9, 0x02, 0x94, 0xFC,
-0x24, 0x04, 0xF5, 0x48, 0x39, 0x03, 0xF9, 0xFC, 0x74, 0x02, 0x42,
-0xFE, 0x0B, 0x01, 0x87, 0xFF, 0x1E, 0x00, 0xFD, 0xFF, 0x2F, 0x00,
-0x4F, 0xFF, 0xC2, 0x01, 0x51, 0xFC, 0x23, 0x07, 0x9A, 0xF1, 0x3A,
-0x2D, 0x35, 0x33, 0x89, 0xF1, 0xD5, 0x06, 0x9D, 0xFC, 0x8B, 0x01,
-0x6C, 0xFF, 0x25, 0x00, 0xFD, 0xFF, 0x16, 0x00, 0xA4, 0xFF, 0xC2,
-0x00, 0xDB, 0xFE, 0x52, 0x01, 0x1B, 0xFF, 0x8D, 0xFE, 0x57, 0x48,
-0x81, 0x09, 0x61, 0xFA, 0xC6, 0x03, 0x96, 0xFD, 0x5B, 0x01, 0x68,
-0xFF, 0x26, 0x00, 0x00, 0x00, 0xFD, 0xFF, 0x35, 0x00, 0x3B, 0xFF,
-0xE2, 0x01, 0x31, 0xFC, 0x15, 0x07, 0x6D, 0xF2, 0xBF, 0x25, 0xA5,
-0x39, 0x4D, 0xF2, 0x0B, 0x06, 0x33, 0xFD, 0x2D, 0x01, 0x9D, 0xFF,
-0x13, 0x00, 0xFF, 0xFF, 0x0E, 0x00, 0xC6, 0xFF, 0x6B, 0x00, 0x8E,
-0xFF, 0x06, 0x00, 0x6E, 0x01, 0xE4, 0xF9, 0x48, 0x46, 0x75, 0x10,
-0xD7, 0xF7, 0xFC, 0x04, 0x00, 0xFD, 0x9E, 0x01, 0x4E, 0xFF, 0x2E,
-0x00, 0xFF, 0xFF, 0xFE, 0xFF, 0x36, 0x00, 0x36, 0xFF, 0xE3, 0x01,
-0x4E, 0xFC, 0xA0, 0x06, 0xED, 0xF3, 0x0F, 0x1E, 0x2D, 0x3F, 0x10,
-0xF4, 0xC8, 0x04, 0x07, 0xFE, 0xAF, 0x00, 0xDC, 0xFF, 0xFC, 0xFF,
-0x03, 0x00, 0x07, 0x00, 0xE5, 0xFF, 0x18, 0x00, 0x36, 0x00, 0xD9,
-0xFE, 0x71, 0x03, 0x3F, 0xF6, 0xDB, 0x42, 0xE0, 0x17, 0x86, 0xF5,
-0x00, 0x06, 0x8C, 0xFC, 0xCE, 0x01, 0x3C, 0xFF, 0x34, 0x00, 0xFE,
-0xFF, 0xFF, 0xFF, 0x33, 0x00, 0x3F, 0xFF, 0xC6, 0x01, 0x9F, 0xFC,
-0xD3, 0x05, 0xF1, 0xF5, 0x6C, 0x16, 0x9E, 0x43, 0xDD, 0xF6, 0x15,
-0x03, 0x10, 0xFF, 0x17, 0x00, 0x28, 0x00, 0xDF, 0xFF, 0x09, 0x00,
-0x02, 0x00, 0x01, 0x00, 0xCF, 0xFF, 0xC9, 0x00, 0xDA, 0xFD, 0x0F,
-0x05, 0xA5, 0xF3, 0x31, 0x3E, 0x8A, 0x1F, 0x97, 0xF3, 0xBD, 0x06,
-0x44, 0xFC, 0xE5, 0x01, 0x36, 0xFF, 0x36, 0x00, 0xFD, 0xFF, 0xFF,
-0xFF, 0x2D, 0x00, 0x52, 0xFF, 0x92, 0x01, 0x1B, 0xFD, 0xC4, 0x04,
-0x51, 0xF8, 0x13, 0x0F, 0xC8, 0x46, 0xB6, 0xFA, 0x01, 0x01, 0x44,
-0x00, 0x6C, 0xFF, 0x7B, 0x00, 0xBF, 0xFF, 0x10, 0x00, 0xFF, 0xFF,
-0x17, 0x00, 0x92, 0xFF, 0x41, 0x01, 0x11, 0xFD, 0x3B, 0x06, 0x14,
-0xF2, 0x78, 0x38, 0x36, 0x27, 0x35, 0xF2, 0x20, 0x07, 0x33, 0xFC,
-0xDF, 0x01, 0x3E, 0xFF, 0x34, 0x00, 0xFD, 0xFF, 0x00, 0x00, 0x25,
-0x00, 0x6D, 0xFF, 0x4C, 0x01, 0xB6, 0xFD, 0x86, 0x03, 0xE1, 0xFA,
-0x3D, 0x08, 0x92, 0x48, 0x8E, 0xFF, 0xA1, 0xFE, 0x93, 0x01, 0xB8,
-0xFE, 0xD3, 0x00, 0x9D, 0xFF, 0x18, 0x00, 0xFD, 0xFF, 0x28, 0x00,
-0x64, 0xFF, 0x9A, 0x01, 0x88, 0xFC, 0xEE, 0x06, 0x7E, 0xF1, 0xE3,
-0x31, 0x9F, 0x2E, 0x88, 0xF1, 0x19, 0x07, 0x5E, 0xFC, 0xB7, 0x01,
-0x54, 0xFF, 0x2D, 0x00, 0xFD, 0xFF, 0x1C, 0x00, 0x8D, 0xFF, 0xFA,
-0x00, 0x64, 0xFE, 0x32, 0x02, 0x78, 0xFD, 0x1B, 0x02, 0xEA, 0x48,
-0x50, 0x05, 0x14, 0xFC, 0xEB, 0x02, 0x05, 0xFE, 0x27, 0x01, 0x7C,
-0xFF, 0x21, 0x00, 0x00, 0x00, 0xFD, 0xFF, 0x32, 0x00, 0x46, 0xFF,
-0xD1, 0x01, 0x3F, 0xFC, 0x2B, 0x07, 0xCD, 0xF1, 0xAE, 0x2A, 0x86,
-0x35, 0xB1, 0xF1, 0x9D, 0x06, 0xCA, 0xFC, 0x6E, 0x01, 0x7B, 0xFF,
-0x20, 0x00, 0xFE, 0xFF, 0x13, 0x00, 0xAF, 0xFF, 0xA4, 0x00, 0x19,
-0xFF, 0xDD, 0x00, 0xF0, 0xFF, 0xD4, 0xFC, 0xC9, 0x47, 0xD8, 0x0B,
-0x7C, 0xF9, 0x35, 0x04, 0x5F, 0xFD, 0x74, 0x01, 0x5E, 0xFF, 0x29,
-0x00, 0x00, 0x00, 0xFD, 0xFF, 0x36, 0x00, 0x38, 0xFF, 0xE6, 0x01,
-0x35, 0xFC, 0xF7, 0x06, 0xE0, 0xF2, 0x18, 0x23, 0xAB, 0x3B, 0xCC,
-0xF2, 0xA8, 0x05, 0x76, 0xFD, 0x04, 0x01, 0xB1, 0xFF, 0x0C, 0x00,
-0x00, 0x00, 0x0C, 0x00, 0xD1, 0xFF, 0x4E, 0x00, 0xCA, 0xFF, 0x9A,
-0xFF, 0x2A, 0x02, 0x83, 0xF8, 0x3F, 0x45, 0xFB, 0x12, 0x01, 0xF7,
-0x5D, 0x05, 0xD3, 0xFC, 0xB1, 0x01, 0x46, 0xFF, 0x31, 0x00, 0xFF,
-0xFF, 0xFE, 0xFF, 0x36, 0x00, 0x38, 0xFF, 0xDC, 0x01, 0x64, 0xFC,
-0x62, 0x06, 0x93, 0xF4, 0x66, 0x1B, 0xD9, 0x40, 0xEA, 0xF4, 0x3E,
-0x04, 0x5D, 0xFE, 0x7D, 0x00, 0xF5, 0xFF, 0xF3, 0xFF, 0x05, 0x00,
-0x05, 0x00, 0xEF, 0xFF, 0xFE, 0xFF, 0x6C, 0x00, 0x7B, 0xFE, 0x0C,
-0x04, 0x3A, 0xF5, 0x5F, 0x41, 0x83, 0x1A, 0xCD, 0xF4, 0x4B, 0x06,
-0x6D, 0xFC, 0xD9, 0x01, 0x39, 0xFF, 0x35, 0x00, 0xFE, 0xFF, 0xFF,
-0xFF, 0x31, 0x00, 0x44, 0xFF, 0xB7, 0x01, 0xC5, 0xFC, 0x7C, 0x05,
-0xBC, 0xF6, 0xD5, 0x13, 0xDC, 0x44, 0x14, 0xF8, 0x67, 0x02, 0x77,
-0xFF, 0xDD, 0xFF, 0x44, 0x00, 0xD5, 0xFF, 0x0B, 0x00, 0x01, 0x00,
-0x09, 0x00, 0xB8, 0xFF, 0xF6, 0x00, 0x8D, 0xFD, 0x84, 0x05, 0xFD,
-0xF2, 0x52, 0x3C, 0x35, 0x22, 0x0B, 0xF3, 0xEB, 0x06, 0x37, 0xFC,
-0xE6, 0x01, 0x37, 0xFF, 0x36, 0x00, 0xFD, 0xFF, 0x00, 0x00, 0x2A,
-0x00, 0x5B, 0xFF, 0x7C, 0x01, 0x4E, 0xFD, 0x5A, 0x04, 0x31, 0xF9,
-0xA4, 0x0C, 0x90, 0x47, 0x47, 0xFC, 0x36, 0x00, 0xB6, 0x00, 0x2E,
-0xFF, 0x99, 0x00, 0xB3, 0xFF, 0x12, 0x00, 0xFE, 0xFF, 0x1E, 0x00,
-0x80, 0xFF, 0x64, 0x01, 0xDA, 0xFC, 0x87, 0x06, 0xC5, 0xF1, 0x46,
-0x36, 0xD1, 0x29, 0xE3, 0xF1, 0x2A, 0x07, 0x3A, 0xFC, 0xD5, 0x01,
-0x44, 0xFF, 0x32, 0x00, 0xFD, 0xFF, 0x00, 0x00, 0x22, 0x00, 0x78,
-0xFF, 0x31, 0x01, 0xF1, 0xFD, 0x12, 0x03, 0xC7, 0xFB, 0x07, 0x06,
-0xDB, 0x48, 0x73, 0x01, 0xC3, 0xFD, 0x0A, 0x02, 0x79, 0xFE, 0xF1,
-0x00, 0x91, 0xFF, 0x1B, 0x00, 0xFD, 0xFF, 0x2C, 0x00, 0x58, 0xFF,
-0xB1, 0x01, 0x67, 0xFC, 0x10, 0x07, 0x81, 0xF1, 0x73, 0x2F, 0x15,
-0x31, 0x7C, 0xF1, 0xFB, 0x06, 0x7C, 0xFC, 0xA2, 0x01, 0x60, 0xFF,
-0x29, 0x00, 0xFD, 0xFF, 0x19, 0x00, 0x99, 0xFF, 0xDD, 0x00, 0xA3,
-0xFE, 0xBB, 0x01, 0x58, 0xFE, 0x2D, 0x00, 0xAF, 0x48, 0x7E, 0x07,
-0x2E, 0xFB, 0x60, 0x03, 0xC9, 0xFD, 0x43, 0x01, 0x71, 0xFF, 0x24,
-0x00, 0x00, 0x00, 0xFD, 0xFF, 0x34, 0x00, 0x3F, 0xFF, 0xDC, 0x01,
-0x34, 0xFC, 0x25, 0x07, 0x18, 0xF2, 0x15, 0x28, 0xBF, 0x37, 0xF7,
-0xF1, 0x56, 0x06, 0xFE, 0xFC, 0x4D, 0x01, 0x8C, 0xFF, 0x19, 0x00,
-0xFF, 0xFF, 0x10, 0x00, 0xBB, 0xFF, 0x85, 0x00, 0x58, 0xFF, 0x6A,
-0x00, 0xBE, 0x00, 0x38, 0xFB, 0x0F, 0x47, 0x42, 0x0E, 0x9B, 0xF8,
-0xA1, 0x04, 0x2B, 0xFD, 0x8B, 0x01, 0x55, 0xFF, 0x2C, 0x00, 0xFF,
-0xFF, 0xFD, 0xFF, 0x36, 0x00, 0x36, 0xFF, 0xE6, 0x01, 0x3F, 0xFC,
-0xCE, 0x06, 0x66, 0xF3, 0x6F, 0x20, 0x96, 0x3D, 0x69, 0xF3, 0x38,
-0x05, 0xBF, 0xFD, 0xD9, 0x00, 0xC7, 0xFF, 0x04, 0x00, 0x02, 0x00,
-0x09, 0x00, 0xDC, 0xFF, 0x31, 0x00, 0x04, 0x00, 0x32, 0xFF, 0xDC,
-0x02, 0x42, 0xF7, 0x0B, 0x44, 0x8E, 0x15, 0x34, 0xF6, 0xB7, 0x05,
-0xAB, 0xFC, 0xC1, 0x01, 0x40, 0xFF, 0x33, 0x00, 0xFF, 0xFF, 0xFE,
-0xFF, 0x35, 0x00, 0x3B, 0xFF, 0xD2, 0x01, 0x81, 0xFC, 0x1A, 0x06,
-0x47, 0xF5, 0xC1, 0x18, 0x60, 0x42, 0xE4, 0xF5, 0xA6, 0x03, 0xB9,
-0xFE, 0x48, 0x00, 0x0F, 0x00, 0xE9, 0xFF, 0x07, 0x00, 0x04, 0x00,
-0xF9, 0xFF, 0xE4, 0xFF, 0x9F, 0x00, 0x23, 0xFE, 0x9B, 0x04, 0x55,
-0xF4, 0xC0, 0x3F, 0x2C, 0x1D, 0x22, 0xF4, 0x8C, 0x06, 0x55, 0xFC,
-0xE1, 0x01, 0x37, 0xFF, 0x36, 0x00, 0xFE, 0xFF, 0xFF, 0xFF, 0x2F,
-0x00, 0x4B, 0xFF, 0xA4, 0x01, 0xF1, 0xFC, 0x1D, 0x05, 0x8F, 0xF7,
-0x4A, 0x11, 0xF2, 0x45, 0x6B, 0xF9, 0xAE, 0x01, 0xE2, 0xFF, 0xA2,
-0xFF, 0x61, 0x00, 0xC9, 0xFF, 0x0D, 0x00, 0x00, 0x00, 0x11, 0x00,
-0xA3, 0xFF, 0x20, 0x01, 0x49, 0xFD, 0xEB, 0x05, 0x74, 0xF2, 0x54,
-0x3A, 0xDD, 0x24, 0x91, 0xF2, 0x0C, 0x07, 0x32, 0xFC, 0xE4, 0x01,
-0x3A, 0xFF, 0x36, 0x00, 0xFD, 0xFF, 0x00, 0x00, 0x27, 0x00, 0x64,
-0xFF, 0x63, 0x01, 0x84, 0xFD, 0xEB, 0x03, 0x14, 0xFA, 0x47, 0x0A,
-0x2C, 0x48, 0xF6, 0xFD, 0x63, 0xFF, 0x2B, 0x01, 0xF0, 0xFE, 0xB8,
-0x00, 0xA8, 0xFF, 0x15, 0x00, 0xFE, 0xFF, 0x23, 0x00, 0x71, 0xFF,
-0x82, 0x01, 0xAB, 0xFC, 0xC4, 0x06, 0x93, 0xF1, 0xFD, 0x33, 0x62,
-0x2C, 0xA8, 0xF1, 0x27, 0x07, 0x4A, 0xFC, 0xC7, 0x01, 0x4C, 0xFF,
-0x30, 0x00, 0xFD, 0xFF, 0x00, 0x00, 0x1F, 0x00, 0x83, 0xFF, 0x14,
-0x01, 0x2D, 0xFE, 0x9C, 0x02, 0xAD, 0xFC, 0xE9, 0x03, 0xF6, 0x48,
-0x73, 0x03, 0xE0, 0xFC, 0x82, 0x02, 0x3B, 0xFE, 0x0E, 0x01, 0x86,
-0xFF, 0x1E, 0x00, 0xFD, 0xFF, 0x2F, 0x00, 0x4E, 0xFF, 0xC3, 0x01,
-0x4E, 0xFC, 0x24, 0x07, 0x9E, 0xF1, 0xF2, 0x2C, 0x78, 0x33, 0x8C,
-0xF1, 0xD0, 0x06, 0xA2, 0xFC, 0x88, 0x01, 0x6D, 0xFF, 0x24, 0x00,
-0xFD, 0xFF, 0x16, 0x00, 0xA5, 0xFF, 0xBE, 0x00, 0xE2, 0xFE, 0x45,
-0x01, 0x33, 0xFF, 0x5A, 0xFE, 0x48, 0x48, 0xC3, 0x09, 0x47, 0xFA,
-0xD2, 0x03, 0x90, 0xFD, 0x5E, 0x01, 0x66, 0xFF, 0x27, 0x00, 0x00,
-0x00, 0xFD, 0xFF, 0x35, 0x00, 0x3B, 0xFF, 0xE3, 0x01, 0x31, 0xFC,
-0x12, 0x07, 0x79, 0xF2, 0x73, 0x25, 0xDF, 0x39, 0x5A, 0xF2, 0x00,
-0x06, 0x3A, 0xFD, 0x28, 0x01, 0x9F, 0xFF, 0x13, 0x00, 0x00, 0x00,
-0x0E, 0x00, 0xC7, 0xFF, 0x68, 0x00, 0x95, 0xFF, 0xFA, 0xFF, 0x83,
-0x01, 0xBB, 0xF9, 0x2B, 0x46, 0xBB, 0x10, 0xBF, 0xF7, 0x07, 0x05,
-0xFB, 0xFC, 0xA0, 0x01, 0x4D, 0xFF, 0x2F, 0x00, 0xFF, 0xFF, 0xFE,
-0xFF, 0x36, 0x00, 0x36, 0xFF, 0xE2, 0x01, 0x50, 0xFC, 0x99, 0x06,
-0xFE, 0xF3, 0xC3, 0x1D, 0x5E, 0x3F, 0x27, 0xF4, 0xB9, 0x04, 0x10,
-0xFE, 0xA9, 0x00, 0xDF, 0xFF, 0xFB, 0xFF, 0x03, 0x00, 0x07, 0x00,
-0xE6, 0xFF, 0x15, 0x00, 0x3C, 0x00, 0xCF, 0xFE, 0x83, 0x03, 0x20,
-0xF6, 0xB2, 0x42, 0x2B, 0x18, 0x71, 0xF5, 0x09, 0x06, 0x88, 0xFC,
-0xCF, 0x01, 0x3C, 0xFF, 0x34, 0x00, 0xFE, 0xFF, 0xFF, 0xFF, 0x33,
-0x00, 0x3F, 0xFF, 0xC5, 0x01, 0xA3, 0xFC, 0xCA, 0x05, 0x07, 0xF6,
-0x22, 0x16, 0xC3, 0x43, 0xFE, 0xF6, 0x02, 0x03, 0x1B, 0xFF, 0x11,
-0x00, 0x2B, 0x00, 0xDE, 0xFF, 0x09, 0x00, 0x02, 0x00, 0x02, 0x00,
-0xCC, 0xFF, 0xCE, 0x00, 0xD1, 0xFD, 0x1D, 0x05, 0x91, 0xF3, 0xFE,
-0x3D, 0xD7, 0x1F, 0x87, 0xF3, 0xC3, 0x06, 0x42, 0xFC, 0xE5, 0x01,
-0x36, 0xFF, 0x36, 0x00, 0xFD, 0xFF, 0xFF, 0xFF, 0x2D, 0x00, 0x53,
-0xFF, 0x90, 0x01, 0x20, 0xFD, 0xB8, 0x04, 0x6A, 0xF8, 0xCD, 0x0E,
-0xE1, 0x46, 0xE1, 0xFA, 0xEB, 0x00, 0x51, 0x00, 0x65, 0xFF, 0x7F,
-0x00, 0xBE, 0xFF, 0x10, 0x00, 0xFF, 0xFF, 0x18, 0x00, 0x90, 0xFF,
-0x45, 0x01, 0x0B, 0xFD, 0x44, 0x06, 0x0A, 0xF2, 0x3B, 0x38, 0x80,
-0x27, 0x2B, 0xF2, 0x22, 0x07, 0x33, 0xFC, 0xDE, 0x01, 0x3E, 0xFF,
-0x34, 0x00, 0xFD, 0xFF, 0x00, 0x00, 0x24, 0x00, 0x6E, 0xFF, 0x49,
-0x01, 0xBC, 0xFD, 0x7A, 0x03, 0xFA, 0xFA, 0xFD, 0x07, 0x9C, 0x48,
-0xC3, 0xFF, 0x89, 0xFE, 0xA1, 0x01, 0xB1, 0xFE, 0xD6, 0x00, 0x9C,
-0xFF, 0x18, 0x00, 0xFD, 0xFF, 0x28, 0x00, 0x63, 0xFF, 0x9D, 0x01,
-0x84, 0xFC, 0xF3, 0x06, 0x7D, 0xF1, 0x9E, 0x31, 0xE6, 0x2E, 0x85,
-0xF1, 0x16, 0x07, 0x61, 0xFC, 0xB5, 0x01, 0x55, 0xFF, 0x2D, 0x00,
-0xFD, 0xFF, 0x1C, 0x00, 0x8F, 0xFF, 0xF7, 0x00, 0x6B, 0xFE, 0x25,
-0x02, 0x91, 0xFD, 0xE3, 0x01, 0xE5, 0x48, 0x8D, 0x05, 0xFB, 0xFB,
-0xF8, 0x02, 0xFE, 0xFD, 0x2B, 0x01, 0x7A, 0xFF, 0x21, 0x00, 0x00,
-0x00, 0xFD, 0xFF, 0x32, 0x00, 0x45, 0xFF, 0xD2, 0x01, 0x3D, 0xFC,
-0x2B, 0x07, 0xD4, 0xF1, 0x64, 0x2A, 0xC6, 0x35, 0xB7, 0xF1, 0x96,
-0x06, 0xCF, 0xFC, 0x6B, 0x01, 0x7D, 0xFF, 0x1F, 0x00, 0xFE, 0xFF,
-0x13, 0x00, 0xB1, 0xFF, 0xA0, 0x00, 0x20, 0xFF, 0xD0, 0x00, 0x07,
-0x00, 0xA4, 0xFC, 0xB6, 0x47, 0x1C, 0x0C, 0x63, 0xF9, 0x42, 0x04,
-0x59, 0xFD, 0x76, 0x01, 0x5D, 0xFF, 0x2A, 0x00, 0x00, 0x00, 0xFD,
-0xFF, 0x36, 0x00, 0x37, 0xFF, 0xE6, 0x01, 0x35, 0xFC, 0xF3, 0x06,
-0xEE, 0xF2, 0xCD, 0x22, 0xE4, 0x3B, 0xDC, 0xF2, 0x9C, 0x05, 0x7E,
-0xFD, 0x00, 0x01, 0xB4, 0xFF, 0x0B, 0x00, 0x01, 0x00, 0x0B, 0x00,
-0xD2, 0xFF, 0x4A, 0x00, 0xD0, 0xFF, 0x8E, 0xFF, 0x3F, 0x02, 0x5E,
-0xF8, 0x1E, 0x45, 0x44, 0x13, 0xEA, 0xF6, 0x67, 0x05, 0xCF, 0xFC,
-0xB3, 0x01, 0x46, 0xFF, 0x31, 0x00, 0xFF, 0xFF, 0xFE, 0xFF, 0x36,
-0x00, 0x38, 0xFF, 0xDB, 0x01, 0x67, 0xFC, 0x5A, 0x06, 0xA6, 0xF4,
-0x1B, 0x1B, 0x07, 0x41, 0x04, 0xF5, 0x2D, 0x04, 0x67, 0xFE, 0x77,
-0x00, 0xF8, 0xFF, 0xF2, 0xFF, 0x05, 0x00, 0x05, 0x00, 0xF0, 0xFF,
-0xFB, 0xFF, 0x71, 0x00, 0x71, 0xFE, 0x1D, 0x04, 0x1F, 0xF5, 0x32,
-0x41, 0xCE, 0x1A, 0xBA, 0xF4, 0x53, 0x06, 0x6A, 0xFC, 0xDA, 0x01,
-0x38, 0xFF, 0x35, 0x00, 0xFE, 0xFF, 0xFF, 0xFF, 0x31, 0x00, 0x45,
-0xFF, 0xB5, 0x01, 0xCA, 0xFC, 0x72, 0x05, 0xD3, 0xF6, 0x8D, 0x13,
-0xFD, 0x44, 0x39, 0xF8, 0x53, 0x02, 0x82, 0xFF, 0xD7, 0xFF, 0x47,
-0x00, 0xD3, 0xFF, 0x0B, 0x00, 0x01, 0x00, 0x0A, 0x00, 0xB6, 0xFF,
-0xFB, 0x00, 0x85, 0xFD, 0x90, 0x05, 0xEC, 0xF2, 0x1C, 0x3C, 0x81,
-0x22, 0xFC, 0xF2, 0xEF, 0x06, 0x36, 0xFC, 0xE6, 0x01, 0x37, 0xFF,
-0x36, 0x00, 0xFD, 0xFF, 0x00, 0x00, 0x2A, 0x00, 0x5C, 0xFF, 0x79,
-0x01, 0x53, 0xFD, 0x4E, 0x04, 0x4A, 0xF9, 0x60, 0x0C, 0xA3, 0x47,
-0x76, 0xFC, 0x1F, 0x00, 0xC3, 0x00, 0x27, 0xFF, 0x9D, 0x00, 0xB2,
-0xFF, 0x13, 0x00, 0xFE, 0xFF, 0x1E, 0x00, 0x7F, 0xFF, 0x67, 0x01,
-0xD5, 0xFC, 0x8E, 0x06, 0xBE, 0xF1, 0x06, 0x36, 0x1A, 0x2A, 0xDC,
-0xF1, 0x2A, 0x07, 0x3C, 0xFC, 0xD3, 0x01, 0x44, 0xFF, 0x32, 0x00,
-0xFD, 0xFF, 0x00, 0x00, 0x21, 0x00, 0x79, 0xFF, 0x2E, 0x01, 0xF7,
-0xFD, 0x05, 0x03, 0xE1, 0xFB, 0xCA, 0x05, 0xDF, 0x48, 0xAB, 0x01,
-0xAA, 0xFD, 0x18, 0x02, 0x72, 0xFE, 0xF4, 0x00, 0x90, 0xFF, 0x1B,
-0x00, 0xFD, 0xFF, 0x2C, 0x00, 0x57, 0xFF, 0xB3, 0x01, 0x64, 0xFC,
-0x13, 0x07, 0x83, 0xF1, 0x2C, 0x2F, 0x5A, 0x31, 0x7D, 0xF1, 0xF7,
-0x06, 0x80, 0xFC, 0x9F, 0x01, 0x61, 0xFF, 0x29, 0x00, 0xFD, 0xFF,
-0x19, 0x00, 0x9A, 0xFF, 0xD9, 0x00, 0xAA, 0xFE, 0xAE, 0x01, 0x70,
-0xFE, 0xF8, 0xFF, 0xA6, 0x48, 0xBE, 0x07, 0x14, 0xFB, 0x6D, 0x03,
-0xC3, 0xFD, 0x46, 0x01, 0x70, 0xFF, 0x24, 0x00, 0x00, 0x00, 0xFD,
-0xFF, 0x34, 0x00, 0x3F, 0xFF, 0xDD, 0x01, 0x34, 0xFC, 0x23, 0x07,
-0x21, 0xF2, 0xCB, 0x27, 0xFE, 0x37, 0x00, 0xF2, 0x4D, 0x06, 0x04,
-0xFD, 0x49, 0x01, 0x8E, 0xFF, 0x19, 0x00, 0xFF, 0xFF, 0x10, 0x00,
-0xBD, 0xFF, 0x82, 0x00, 0x5E, 0xFF, 0x5D, 0x00, 0xD4, 0x00, 0x0C,
-0xFB, 0xF9, 0x46, 0x87, 0x0E, 0x82, 0xF8, 0xAD, 0x04, 0x26, 0xFD,
-0x8D, 0x01, 0x54, 0xFF, 0x2C, 0x00, 0xFF, 0xFF, 0xFD, 0xFF, 0x36,
-0x00, 0x36, 0xFF, 0xE6, 0x01, 0x41, 0xFC, 0xC8, 0x06, 0x76, 0xF3,
-0x22, 0x20, 0xCA, 0x3D, 0x7D, 0xF3, 0x2A, 0x05, 0xC8, 0xFD, 0xD4,
-0x00, 0xCA, 0xFF, 0x03, 0x00, 0x02, 0x00, 0x09, 0x00, 0xDD, 0xFF,
-0x2E, 0x00, 0x0A, 0x00, 0x27, 0xFF, 0xEF, 0x02, 0x20, 0xF7, 0xE7,
-0x43, 0xD8, 0x15, 0x1E, 0xF6, 0xC0, 0x05, 0xA7, 0xFC, 0xC3, 0x01,
-0x40, 0xFF, 0x33, 0x00, 0xFF, 0xFF, 0xFE, 0xFF, 0x34, 0x00, 0x3B,
-0xFF, 0xD1, 0x01, 0x84, 0xFC, 0x12, 0x06, 0x5C, 0xF5, 0x76, 0x18,
-0x89, 0x42, 0x02, 0xF6, 0x94, 0x03, 0xC4, 0xFE, 0x42, 0x00, 0x12,
-0x00, 0xE8, 0xFF, 0x07, 0x00, 0x03, 0x00, 0xFA, 0xFF, 0xE2, 0xFF,
-0xA4, 0x00, 0x19, 0xFE, 0xAA, 0x04, 0x3E, 0xF4, 0x90, 0x3F, 0x78,
-0x1D, 0x10, 0xF4, 0x93, 0x06, 0x52, 0xFC, 0xE1, 0x01, 0x36, 0xFF,
-0x36, 0x00, 0xFE, 0xFF, 0xFF, 0xFF, 0x2F, 0x00, 0x4C, 0xFF, 0xA2,
-0x01, 0xF6, 0xFC, 0x12, 0x05, 0xA7, 0xF7, 0x03, 0x11, 0x10, 0x46,
-0x93, 0xF9, 0x98, 0x01, 0xEE, 0xFF, 0x9B, 0xFF, 0x64, 0x00, 0xC8,
-0xFF, 0x0E, 0x00, 0x00, 0x00, 0x12, 0x00, 0xA1, 0xFF, 0x24, 0x01,
-0x41, 0xFD, 0xF6, 0x05, 0x67, 0xF2, 0x1A, 0x3A, 0x29, 0x25, 0x84,
-0xF2, 0x0F, 0x07, 0x31, 0xFC, 0xE3, 0x01, 0x3A, 0xFF, 0x35, 0x00,
-0xFD, 0xFF, 0x00, 0x00, 0x27, 0x00, 0x65, 0xFF, 0x60, 0x01, 0x8A,
-0xFD, 0xDF, 0x03, 0x2E, 0xFA, 0x04, 0x0A, 0x3A, 0x48, 0x28, 0xFE,
-0x4B, 0xFF, 0x38, 0x01, 0xE9, 0xFE, 0xBB, 0x00, 0xA6, 0xFF, 0x16,
-0x00, 0xFD, 0xFF, 0x24, 0x00, 0x6F, 0xFF, 0x85, 0x01, 0xA6, 0xFC,
-0xCA, 0x06, 0x8F, 0xF1, 0xBB, 0x33, 0xAB, 0x2C, 0xA3, 0xF1, 0x26,
-0x07, 0x4C, 0xFC, 0xC5, 0x01, 0x4D, 0xFF, 0x30, 0x00, 0xFD, 0xFF,
-0x00, 0x00, 0x1E, 0x00, 0x84, 0xFF, 0x11, 0x01, 0x34, 0xFE, 0x8F,
-0x02, 0xC7, 0xFC, 0xAE, 0x03, 0xF7, 0x48, 0xAE, 0x03, 0xC7, 0xFC,
-0x8F, 0x02, 0x34, 0xFE, 0x11, 0x01, 0x84, 0xFF, 0x1E, 0x00, 0xFD,
-0xFF, 0x2A, 0x00, 0x5C, 0xFF, 0xAA, 0x01, 0x71, 0xFC, 0x07, 0x07,
-0x7E, 0xF1, 0x44, 0x30, 0x44, 0x30, 0x7E, 0xF1, 0x07, 0x07, 0x71,
-0xFC, 0xAA, 0x01, 0x5C, 0xFF, 0x2A, 0x00, 0xFD, 0xFF, 0x00, 0x00,
-0x1E, 0x00, 0x84, 0xFF, 0x11, 0x01, 0x34, 0xFE, 0x8F, 0x02, 0xC7,
-0xFC, 0xAE, 0x03, 0xF7, 0x48, 0xAE, 0x03, 0xC7, 0xFC, 0x8F, 0x02,
-0x34, 0xFE, 0x11, 0x01, 0x84, 0xFF, 0x1E, 0x00, 0x02, 0x00, 0x05,
-0x00, 0xC3, 0xFF, 0xE1, 0x00, 0xB1, 0xFD, 0x4E, 0x05, 0x4A, 0xF3,
-0x3D, 0x3D, 0xED, 0x20, 0x4C, 0xF3, 0xD6, 0x06, 0x3D, 0xFC, 0xE6,
-0x01, 0x36, 0xFF, 0x36, 0x00, 0xFD, 0xFF, 0xFD, 0xFF, 0x36, 0x00,
-0x36, 0xFF, 0xE6, 0x01, 0x3D, 0xFC, 0xD6, 0x06, 0x4C, 0xF3, 0xED,
-0x20, 0x3D, 0x3D, 0x4A, 0xF3, 0x4E, 0x05, 0xB1, 0xFD, 0xE1, 0x00,
-0xC3, 0xFF, 0x05, 0x00, 0x02, 0x00, 0x00, 0x00, 0x1E, 0x00, 0x84,
-0xFF, 0x11, 0x01, 0x34, 0xFE, 0x8F, 0x02, 0xC7, 0xFC, 0xAE, 0x03,
-0xF7, 0x48, 0xAE, 0x03, 0xC7, 0xFC, 0x8F, 0x02, 0x34, 0xFE, 0x11,
-0x01, 0x84, 0xFF, 0x1E, 0x00, 0x16, 0x00, 0xA6, 0xFF, 0xBB, 0x00,
-0xE9, 0xFE, 0x38, 0x01, 0x4B, 0xFF, 0x28, 0xFE, 0x3A, 0x48, 0x04,
-0x0A, 0x2E, 0xFA, 0xDF, 0x03, 0x8A, 0xFD, 0x60, 0x01, 0x65, 0xFF,
-0x27, 0x00, 0x00, 0x00, 0x0E, 0x00, 0xC8, 0xFF, 0x64, 0x00, 0x9B,
-0xFF, 0xEE, 0xFF, 0x98, 0x01, 0x93, 0xF9, 0x10, 0x46, 0x03, 0x11,
-0xA7, 0xF7, 0x12, 0x05, 0xF6, 0xFC, 0xA2, 0x01, 0x4C, 0xFF, 0x2F,
-0x00, 0xFF, 0xFF, 0x07, 0x00, 0xE8, 0xFF, 0x12, 0x00, 0x42, 0x00,
-0xC4, 0xFE, 0x94, 0x03, 0x02, 0xF6, 0x89, 0x42, 0x76, 0x18, 0x5C,
-0xF5, 0x12, 0x06, 0x84, 0xFC, 0xD1, 0x01, 0x3B, 0xFF, 0x34, 0x00,
-0xFE, 0xFF, 0x02, 0x00, 0x03, 0x00, 0xCA, 0xFF, 0xD4, 0x00, 0xC8,
-0xFD, 0x2A, 0x05, 0x7D, 0xF3, 0xCA, 0x3D, 0x22, 0x20, 0x76, 0xF3,
-0xC8, 0x06, 0x41, 0xFC, 0xE6, 0x01, 0x36, 0xFF, 0x36, 0x00, 0xFD,
-0xFF, 0xFF, 0xFF, 0x19, 0x00, 0x8E, 0xFF, 0x49, 0x01, 0x04, 0xFD,
-0x4D, 0x06, 0x00, 0xF2, 0xFE, 0x37, 0xCB, 0x27, 0x21, 0xF2, 0x23,
-0x07, 0x34, 0xFC, 0xDD, 0x01, 0x3F, 0xFF, 0x34, 0x00, 0xFD, 0xFF,
-0xFD, 0xFF, 0x29, 0x00, 0x61, 0xFF, 0x9F, 0x01, 0x80, 0xFC, 0xF7,
-0x06, 0x7D, 0xF1, 0x5A, 0x31, 0x2C, 0x2F, 0x83, 0xF1, 0x13, 0x07,
-0x64, 0xFC, 0xB3, 0x01, 0x57, 0xFF, 0x2C, 0x00, 0xFD, 0xFF, 0xFD,
-0xFF, 0x32, 0x00, 0x44, 0xFF, 0xD3, 0x01, 0x3C, 0xFC, 0x2A, 0x07,
-0xDC, 0xF1, 0x1A, 0x2A, 0x06, 0x36, 0xBE, 0xF1, 0x8E, 0x06, 0xD5,
-0xFC, 0x67, 0x01, 0x7F, 0xFF, 0x1E, 0x00, 0xFE, 0xFF, 0xFD, 0xFF,
-0x36, 0x00, 0x37, 0xFF, 0xE6, 0x01, 0x36, 0xFC, 0xEF, 0x06, 0xFC,
-0xF2, 0x81, 0x22, 0x1C, 0x3C, 0xEC, 0xF2, 0x90, 0x05, 0x85, 0xFD,
-0xFB, 0x00, 0xB6, 0xFF, 0x0A, 0x00, 0x01, 0x00, 0xFE, 0xFF, 0x35,
-0x00, 0x38, 0xFF, 0xDA, 0x01, 0x6A, 0xFC, 0x53, 0x06, 0xBA, 0xF4,
-0xCE, 0x1A, 0x32, 0x41, 0x1F, 0xF5, 0x1D, 0x04, 0x71, 0xFE, 0x71,
-0x00, 0xFB, 0xFF, 0xF0, 0xFF, 0x05, 0x00, 0xFF, 0xFF, 0x31, 0x00,
-0x46, 0xFF, 0xB3, 0x01, 0xCF, 0xFC, 0x67, 0x05, 0xEA, 0xF6, 0x44,
-0x13, 0x1E, 0x45, 0x5E, 0xF8, 0x3F, 0x02, 0x8E, 0xFF, 0xD0, 0xFF,
-0x4A, 0x00, 0xD2, 0xFF, 0x0B, 0x00, 0x00, 0x00, 0x2A, 0x00, 0x5D,
-0xFF, 0x76, 0x01, 0x59, 0xFD, 0x42, 0x04, 0x63, 0xF9, 0x1C, 0x0C,
-0xB6, 0x47, 0xA4, 0xFC, 0x07, 0x00, 0xD0, 0x00, 0x20, 0xFF, 0xA0,
-0x00, 0xB1, 0xFF, 0x13, 0x00, 0x00, 0x00, 0x21, 0x00, 0x7A, 0xFF,
-0x2B, 0x01, 0xFE, 0xFD, 0xF8, 0x02, 0xFB, 0xFB, 0x8D, 0x05, 0xE5,
-0x48, 0xE3, 0x01, 0x91, 0xFD, 0x25, 0x02, 0x6B, 0xFE, 0xF7, 0x00,
-0x8F, 0xFF, 0x1C, 0x00, 0x18, 0x00, 0x9C, 0xFF, 0xD6, 0x00, 0xB1,
-0xFE, 0xA1, 0x01, 0x89, 0xFE, 0xC3, 0xFF, 0x9C, 0x48, 0xFD, 0x07,
-0xFA, 0xFA, 0x7A, 0x03, 0xBC, 0xFD, 0x49, 0x01, 0x6E, 0xFF, 0x24,
-0x00, 0x00, 0x00, 0x10, 0x00, 0xBE, 0xFF, 0x7F, 0x00, 0x65, 0xFF,
-0x51, 0x00, 0xEB, 0x00, 0xE1, 0xFA, 0xE1, 0x46, 0xCD, 0x0E, 0x6A,
-0xF8, 0xB8, 0x04, 0x20, 0xFD, 0x90, 0x01, 0x53, 0xFF, 0x2D, 0x00,
-0xFF, 0xFF, 0x09, 0x00, 0xDE, 0xFF, 0x2B, 0x00, 0x11, 0x00, 0x1B,
-0xFF, 0x02, 0x03, 0xFE, 0xF6, 0xC3, 0x43, 0x22, 0x16, 0x07, 0xF6,
-0xCA, 0x05, 0xA3, 0xFC, 0xC5, 0x01, 0x3F, 0xFF, 0x33, 0x00, 0xFF,
-0xFF, 0x03, 0x00, 0xFB, 0xFF, 0xDF, 0xFF, 0xA9, 0x00, 0x10, 0xFE,
-0xB9, 0x04, 0x27, 0xF4, 0x5E, 0x3F, 0xC3, 0x1D, 0xFE, 0xF3, 0x99,
-0x06, 0x50, 0xFC, 0xE2, 0x01, 0x36, 0xFF, 0x36, 0x00, 0xFE, 0xFF,
-0x00, 0x00, 0x13, 0x00, 0x9F, 0xFF, 0x28, 0x01, 0x3A, 0xFD, 0x00,
-0x06, 0x5A, 0xF2, 0xDF, 0x39, 0x73, 0x25, 0x79, 0xF2, 0x12, 0x07,
-0x31, 0xFC, 0xE3, 0x01, 0x3B, 0xFF, 0x35, 0x00, 0xFD, 0xFF, 0xFD,
-0xFF, 0x24, 0x00, 0x6D, 0xFF, 0x88, 0x01, 0xA2, 0xFC, 0xD0, 0x06,
-0x8C, 0xF1, 0x78, 0x33, 0xF2, 0x2C, 0x9E, 0xF1, 0x24, 0x07, 0x4E,
-0xFC, 0xC3, 0x01, 0x4E, 0xFF, 0x2F, 0x00, 0xFD, 0xFF, 0xFD, 0xFF,
-0x30, 0x00, 0x4C, 0xFF, 0xC7, 0x01, 0x4A, 0xFC, 0x27, 0x07, 0xA8,
-0xF1, 0x62, 0x2C, 0xFD, 0x33, 0x93, 0xF1, 0xC4, 0x06, 0xAB, 0xFC,
-0x82, 0x01, 0x71, 0xFF, 0x23, 0x00, 0xFE, 0xFF, 0xFD, 0xFF, 0x36,
-0x00, 0x3A, 0xFF, 0xE4, 0x01, 0x32, 0xFC, 0x0C, 0x07, 0x91, 0xF2,
-0xDD, 0x24, 0x54, 0x3A, 0x74, 0xF2, 0xEB, 0x05, 0x49, 0xFD, 0x20,
-0x01, 0xA3, 0xFF, 0x11, 0x00, 0x00, 0x00, 0xFE, 0xFF, 0x36, 0x00,
-0x37, 0xFF, 0xE1, 0x01, 0x55, 0xFC, 0x8C, 0x06, 0x22, 0xF4, 0x2C,
-0x1D, 0xC0, 0x3F, 0x55, 0xF4, 0x9B, 0x04, 0x23, 0xFE, 0x9F, 0x00,
-0xE4, 0xFF, 0xF9, 0xFF, 0x04, 0x00, 0xFF, 0xFF, 0x33, 0x00, 0x40,
-0xFF, 0xC1, 0x01, 0xAB, 0xFC, 0xB7, 0x05, 0x34, 0xF6, 0x8E, 0x15,
-0x0B, 0x44, 0x42, 0xF7, 0xDC, 0x02, 0x32, 0xFF, 0x04, 0x00, 0x31,
-0x00, 0xDC, 0xFF, 0x09, 0x00, 0xFF, 0xFF, 0x2C, 0x00, 0x55, 0xFF,
-0x8B, 0x01, 0x2B, 0xFD, 0xA1, 0x04, 0x9B, 0xF8, 0x42, 0x0E, 0x0F,
-0x47, 0x38, 0xFB, 0xBE, 0x00, 0x6A, 0x00, 0x58, 0xFF, 0x85, 0x00,
-0xBB, 0xFF, 0x10, 0x00, 0x00, 0x00, 0x24, 0x00, 0x71, 0xFF, 0x43,
-0x01, 0xC9, 0xFD, 0x60, 0x03, 0x2E, 0xFB, 0x7E, 0x07, 0xAF, 0x48,
-0x2D, 0x00, 0x58, 0xFE, 0xBB, 0x01, 0xA3, 0xFE, 0xDD, 0x00, 0x99,
-0xFF, 0x19, 0x00, 0x1B, 0x00, 0x91, 0xFF, 0xF1, 0x00, 0x79, 0xFE,
-0x0A, 0x02, 0xC3, 0xFD, 0x73, 0x01, 0xDB, 0x48, 0x07, 0x06, 0xC7,
-0xFB, 0x12, 0x03, 0xF1, 0xFD, 0x31, 0x01, 0x78, 0xFF, 0x22, 0x00,
-0x00, 0x00, 0x12, 0x00, 0xB3, 0xFF, 0x99, 0x00, 0x2E, 0xFF, 0xB6,
-0x00, 0x36, 0x00, 0x47, 0xFC, 0x90, 0x47, 0xA4, 0x0C, 0x31, 0xF9,
-0x5A, 0x04, 0x4E, 0xFD, 0x7C, 0x01, 0x5B, 0xFF, 0x2A, 0x00, 0x00,
-0x00, 0x0B, 0x00, 0xD5, 0xFF, 0x44, 0x00, 0xDD, 0xFF, 0x77, 0xFF,
-0x67, 0x02, 0x14, 0xF8, 0xDC, 0x44, 0xD5, 0x13, 0xBC, 0xF6, 0x7C,
-0x05, 0xC5, 0xFC, 0xB7, 0x01, 0x44, 0xFF, 0x31, 0x00, 0xFF, 0xFF,
-0x05, 0x00, 0xF3, 0xFF, 0xF5, 0xFF, 0x7D, 0x00, 0x5D, 0xFE, 0x3E,
-0x04, 0xEA, 0xF4, 0xD9, 0x40, 0x66, 0x1B, 0x93, 0xF4, 0x62, 0x06,
-0x64, 0xFC, 0xDC, 0x01, 0x38, 0xFF, 0x36, 0x00, 0xFE, 0xFF, 0x00,
-0x00, 0x0C, 0x00, 0xB1, 0xFF, 0x04, 0x01, 0x76, 0xFD, 0xA8, 0x05,
-0xCC, 0xF2, 0xAB, 0x3B, 0x18, 0x23, 0xE0, 0xF2, 0xF7, 0x06, 0x35,
-0xFC, 0xE6, 0x01, 0x38, 0xFF, 0x36, 0x00, 0xFD, 0xFF, 0xFE, 0xFF,
-0x20, 0x00, 0x7B, 0xFF, 0x6E, 0x01, 0xCA, 0xFC, 0x9D, 0x06, 0xB1,
-0xF1, 0x86, 0x35, 0xAE, 0x2A, 0xCD, 0xF1, 0x2B, 0x07, 0x3F, 0xFC,
-0xD1, 0x01, 0x46, 0xFF, 0x32, 0x00, 0xFD, 0xFF, 0xFD, 0xFF, 0x2D,
-0x00, 0x54, 0xFF, 0xB7, 0x01, 0x5E, 0xFC, 0x19, 0x07, 0x88, 0xF1,
-0x9F, 0x2E, 0xE3, 0x31, 0x7E, 0xF1, 0xEE, 0x06, 0x88, 0xFC, 0x9A,
-0x01, 0x64, 0xFF, 0x28, 0x00, 0xFD, 0xFF, 0xFD, 0xFF, 0x34, 0x00,
-0x3E, 0xFF, 0xDF, 0x01, 0x33, 0xFC, 0x20, 0x07, 0x35, 0xF2, 0x36,
-0x27, 0x78, 0x38, 0x14, 0xF2, 0x3B, 0x06, 0x11, 0xFD, 0x41, 0x01,
-0x92, 0xFF, 0x17, 0x00, 0xFF, 0xFF, 0xFD, 0xFF, 0x36, 0x00, 0x36,
-0xFF, 0xE5, 0x01, 0x44, 0xFC, 0xBD, 0x06, 0x97, 0xF3, 0x8A, 0x1F,
-0x31, 0x3E, 0xA5, 0xF3, 0x0F, 0x05, 0xDA, 0xFD, 0xC9, 0x00, 0xCF,
-0xFF, 0x01, 0x00, 0x02, 0x00, 0xFE, 0xFF, 0x34, 0x00, 0x3C, 0xFF,
-0xCE, 0x01, 0x8C, 0xFC, 0x00, 0x06, 0x86, 0xF5, 0xE0, 0x17, 0xDB,
-0x42, 0x3F, 0xF6, 0x71, 0x03, 0xD9, 0xFE, 0x36, 0x00, 0x18, 0x00,
-0xE5, 0xFF, 0x07, 0x00, 0xFF, 0xFF, 0x2E, 0x00, 0x4E, 0xFF, 0x9E,
-0x01, 0x00, 0xFD, 0xFC, 0x04, 0xD7, 0xF7, 0x75, 0x10, 0x48, 0x46,
-0xE4, 0xF9, 0x6E, 0x01, 0x06, 0x00, 0x8E, 0xFF, 0x6B, 0x00, 0xC6,
-0xFF, 0x0E, 0x00, 0x00, 0x00, 0x26, 0x00, 0x68, 0xFF, 0x5B, 0x01,
-0x96, 0xFD, 0xC6, 0x03, 0x61, 0xFA, 0x81, 0x09, 0x57, 0x48, 0x8D,
-0xFE, 0x1B, 0xFF, 0x52, 0x01, 0xDB, 0xFE, 0xC2, 0x00, 0xA4, 0xFF,
-0x16, 0x00, 0x1E, 0x00, 0x87, 0xFF, 0x0B, 0x01, 0x42, 0xFE, 0x74,
-0x02, 0xF9, 0xFC, 0x39, 0x03, 0xF5, 0x48, 0x24, 0x04, 0x94, 0xFC,
-0xA9, 0x02, 0x27, 0xFE, 0x18, 0x01, 0x82, 0xFF, 0x1F, 0x00, 0x00,
-0x00, 0x15, 0x00, 0xA9, 0xFF, 0xB4, 0x00, 0xF7, 0xFE, 0x1D, 0x01,
-0x7A, 0xFF, 0xC5, 0xFD, 0x1D, 0x48, 0x89, 0x0A, 0xFB, 0xF9, 0xF8,
-0x03, 0x7D, 0xFD, 0x66, 0x01, 0x63, 0xFF, 0x28, 0x00, 0x00, 0x00,
-0x0D, 0x00, 0xCB, 0xFF, 0x5E, 0x00, 0xA9, 0xFF, 0xD6, 0xFF, 0xC3,
-0x01, 0x43, 0xF9, 0xD7, 0x45, 0x92, 0x11, 0x77, 0xF7, 0x28, 0x05,
-0xEC, 0xFC, 0xA7, 0x01, 0x4A, 0xFF, 0x2F, 0x00, 0xFF, 0xFF, 0x06,
-0x00, 0xEA, 0xFF, 0x0C, 0x00, 0x4E, 0x00, 0xAF, 0xFE, 0xB8, 0x03,
-0xC7, 0xF5, 0x38, 0x42, 0x0C, 0x19, 0x32, 0xF5, 0x23, 0x06, 0x7D,
-0xFC, 0xD3, 0x01, 0x3A, 0xFF, 0x35, 0x00, 0xFE, 0xFF, 0x02, 0x00,
-0x05, 0x00, 0xC5, 0xFF, 0xDE, 0x00, 0xB7, 0xFD, 0x45, 0x05, 0x56,
-0xF3, 0x61, 0x3D, 0xBA, 0x20, 0x56, 0xF3, 0xD3, 0x06, 0x3E, 0xFC,
-0xE6, 0x01, 0x36, 0xFF, 0x36, 0x00, 0xFD, 0xFF, 0xFF, 0xFF, 0x1A,
-0x00, 0x8A, 0xFF, 0x51, 0x01, 0xF8, 0xFC, 0x5E, 0x06, 0xED, 0xF1,
-0x82, 0x37, 0x60, 0x28, 0x0E, 0xF2, 0x26, 0x07, 0x35, 0xFC, 0xDB,
-0x01, 0x40, 0xFF, 0x34, 0x00, 0xFD, 0xFF, 0xFD, 0xFF, 0x29, 0x00,
-0x5F, 0xFF, 0xA5, 0x01, 0x78, 0xFC, 0xFF, 0x06, 0x7D, 0xF1, 0xCF,
-0x30, 0xB8, 0x2F, 0x80, 0xF1, 0x0D, 0x07, 0x6A, 0xFC, 0xAE, 0x01,
-0x59, 0xFF, 0x2B, 0x00, 0xFD, 0xFF, 0xFD, 0xFF, 0x33, 0x00, 0x43,
-0xFF, 0xD6, 0x01, 0x39, 0xFC, 0x2A, 0x07, 0xEB, 0xF1, 0x87, 0x29,
-0x85, 0x36, 0xCC, 0xF1, 0x7F, 0x06, 0xE0, 0xFC, 0x60, 0x01, 0x82,
-0xFF, 0x1D, 0x00, 0xFE, 0xFF, 0xFD, 0xFF, 0x36, 0x00, 0x37, 0xFF,
-0xE6, 0x01, 0x38, 0xFC, 0xE6, 0x06, 0x19, 0xF3, 0xEA, 0x21, 0x8A,
-0x3C, 0x0E, 0xF3, 0x78, 0x05, 0x96, 0xFD, 0xF1, 0x00, 0xBB, 0xFF,
-0x08, 0x00, 0x01, 0x00, 0xFE, 0xFF, 0x35, 0x00, 0x39, 0xFF, 0xD8,
-0x01, 0x70, 0xFC, 0x43, 0x06, 0xE1, 0xF4, 0x38, 0x1A, 0x8C, 0x41,
-0x55, 0xF5, 0xFC, 0x03, 0x85, 0xFE, 0x66, 0x00, 0x01, 0x00, 0xEE,
-0xFF, 0x06, 0x00, 0xFF, 0xFF, 0x30, 0x00, 0x47, 0xFF, 0xAF, 0x01,
-0xD8, 0xFC, 0x52, 0x05, 0x19, 0xF7, 0xB2, 0x12, 0x5C, 0x45, 0xA9,
-0xF8, 0x16, 0x02, 0xA6, 0xFF, 0xC3, 0xFF, 0x51, 0x00, 0xD0, 0xFF,
-0x0C, 0x00, 0x00, 0x00, 0x29, 0x00, 0x5F, 0xFF, 0x71, 0x01, 0x65,
-0xFD, 0x29, 0x04, 0x96, 0xF9, 0x95, 0x0B, 0xDC, 0x47, 0x03, 0xFD,
-0xD9, 0xFF, 0xEA, 0x00, 0x12, 0xFF, 0xA7, 0x00, 0xAE, 0xFF, 0x14,
-0x00, 0x00, 0x00, 0x20, 0x00, 0x7D, 0xFF, 0x24, 0x01, 0x0C, 0xFE,
-0xDE, 0x02, 0x2E, 0xFC, 0x13, 0x05, 0xEC, 0x48, 0x54, 0x02, 0x5E,
-0xFD, 0x3F, 0x02, 0x5D, 0xFE, 0xFE, 0x00, 0x8C, 0xFF, 0x1C, 0x00,
-0x17, 0x00, 0x9E, 0xFF, 0xCF, 0x00, 0xBF, 0xFE, 0x86, 0x01, 0xBA,
-0xFE, 0x5A, 0xFF, 0x86, 0x48, 0x7D, 0x08, 0xC7, 0xFA, 0x93, 0x03,
-0xB0, 0xFD, 0x4F, 0x01, 0x6C, 0xFF, 0x25, 0x00, 0x00, 0x00, 0x0F,
-0x00, 0xC0, 0xFF, 0x78, 0x00, 0x73, 0xFF, 0x38, 0x00, 0x17, 0x01,
-0x8B, 0xFA, 0xAF, 0x46, 0x59, 0x0F, 0x39, 0xF8, 0xCF, 0x04, 0x15,
-0xFD, 0x95, 0x01, 0x51, 0xFF, 0x2D, 0x00, 0xFF, 0xFF, 0x08, 0x00,
-0xE1, 0xFF, 0x25, 0x00, 0x1D, 0x00, 0x05, 0xFF, 0x28, 0x03, 0xBD,
-0xF6, 0x77, 0x43, 0xB6, 0x16, 0xDC, 0xF5, 0xDD, 0x05, 0x9B, 0xFC,
-0xC8, 0x01, 0x3E, 0xFF, 0x33, 0x00, 0xFF, 0xFF, 0x03, 0x00, 0xFD,
-0xFF, 0xD9, 0xFF, 0xB4, 0x00, 0xFD, 0xFD, 0xD7, 0x04, 0xFA, 0xF3,
-0xFC, 0x3E, 0x5B, 0x1E, 0xDB, 0xF3, 0xA6, 0x06, 0x4C, 0xFC, 0xE3,
-0x01, 0x36, 0xFF, 0x36, 0x00, 0xFE, 0xFF, 0xFF, 0xFF, 0x14, 0x00,
-0x9B, 0xFF, 0x31, 0x01, 0x2C, 0xFD, 0x15, 0x06, 0x41, 0xF2, 0x6A,
-0x39, 0x0A, 0x26, 0x61, 0xF2, 0x17, 0x07, 0x31, 0xFC, 0xE2, 0x01,
-0x3B, 0xFF, 0x35, 0x00, 0xFD, 0xFF, 0xFD, 0xFF, 0x25, 0x00, 0x6A,
-0xFF, 0x8E, 0x01, 0x99, 0xFC, 0xDB, 0x06, 0x86, 0xF1, 0xF2, 0x32,
-0x82, 0x2D, 0x96, 0xF1, 0x21, 0x07, 0x53, 0xFC, 0xC0, 0x01, 0x50,
-0xFF, 0x2E, 0x00, 0xFD, 0xFF, 0xFD, 0xFF, 0x30, 0x00, 0x4A, 0xFF,
-0xCA, 0x01, 0x46, 0xFC, 0x29, 0x07, 0xB3, 0xF1, 0xD1, 0x2B, 0x81,
-0x34, 0x9C, 0xF1, 0xB8, 0x06, 0xB5, 0xFC, 0x7C, 0x01, 0x74, 0xFF,
-0x22, 0x00, 0xFE, 0xFF, 0xFD, 0xFF, 0x36, 0x00, 0x39, 0xFF, 0xE5,
-0x01, 0x32, 0xFC, 0x06, 0x07, 0xAA, 0xF2, 0x46, 0x24, 0xC8, 0x3A,
-0x90, 0xF2, 0xD6, 0x05, 0x57, 0xFD, 0x17, 0x01, 0xA8, 0xFF, 0x0F,
-0x00, 0x00, 0x00, 0xFE, 0xFF, 0x36, 0x00, 0x37, 0xFF, 0xDF, 0x01,
-0x5A, 0xFC, 0x7E, 0x06, 0x47, 0xF4, 0x94, 0x1C, 0x1F, 0x40, 0x85,
-0xF4, 0x7D, 0x04, 0x36, 0xFE, 0x93, 0x00, 0xEA, 0xFF, 0xF7, 0xFF,
-0x04, 0x00, 0xFF, 0xFF, 0x32, 0x00, 0x42, 0xFF, 0xBE, 0x01, 0xB4,
-0xFC, 0xA4, 0x05, 0x61, 0xF6, 0xFB, 0x14, 0x53, 0x44, 0x86, 0xF7,
-0xB6, 0x02, 0x49, 0xFF, 0xF7, 0xFF, 0x37, 0x00, 0xD9, 0xFF, 0x0A,
-0x00, 0x00, 0x00, 0x2B, 0x00, 0x57, 0xFF, 0x86, 0x01, 0x36, 0xFD,
-0x89, 0x04, 0xCD, 0xF8, 0xB7, 0x0D, 0x3D, 0x47, 0x91, 0xFB, 0x91,
-0x00, 0x83, 0x00, 0x4A, 0xFF, 0x8C, 0x00, 0xB9, 0xFF, 0x11, 0x00,
-0x00, 0x00, 0x23, 0x00, 0x73, 0xFF, 0x3D, 0x01, 0xD6, 0xFD, 0x46,
-0x03, 0x61, 0xFB, 0x00, 0x07, 0xBF, 0x48, 0x98, 0x00, 0x26, 0xFE,
-0xD5, 0x01, 0x95, 0xFE, 0xE3, 0x00, 0x96, 0xFF, 0x1A, 0x00, 0x1A,
-0x00, 0x94, 0xFF, 0xEA, 0x00, 0x87, 0xFE, 0xF0, 0x01, 0xF5, 0xFD,
-0x05, 0x01, 0xCE, 0x48, 0x83, 0x06, 0x94, 0xFB, 0x2C, 0x03, 0xE4,
-0xFD, 0x37, 0x01, 0x76, 0xFF, 0x22, 0x00, 0x00, 0x00, 0x12, 0x00,
-0xB6, 0xFF, 0x93, 0x00, 0x3C, 0xFF, 0x9D, 0x00, 0x63, 0x00, 0xEB,
-0xFB, 0x69, 0x47, 0x2D, 0x0D, 0xFF, 0xF8, 0x72, 0x04, 0x42, 0xFD,
-0x81, 0x01, 0x59, 0xFF, 0x2B, 0x00, 0x00, 0x00, 0x0A, 0x00, 0xD7,
-0xFF, 0x3E, 0x00, 0xEA, 0xFF, 0x60, 0xFF, 0x8F, 0x02, 0xCD, 0xF7,
-0x99, 0x44, 0x68, 0x14, 0x8E, 0xF6, 0x90, 0x05, 0xBC, 0xFC, 0xBA,
-0x01, 0x43, 0xFF, 0x32, 0x00, 0xFF, 0xFF, 0x04, 0x00, 0xF5, 0xFF,
-0xEF, 0xFF, 0x88, 0x00, 0x49, 0xFE, 0x5D, 0x04, 0xB7, 0xF4, 0x7D,
-0x40, 0xFD, 0x1B, 0x6C, 0xF4, 0x70, 0x06, 0x5F, 0xFC, 0xDE, 0x01,
-0x37, 0xFF, 0x36, 0x00, 0xFE, 0xFF, 0x00, 0x00, 0x0E, 0x00, 0xAC,
-0xFF, 0x0E, 0x01, 0x66, 0xFD, 0xBF, 0x05, 0xAD, 0xF2, 0x3B, 0x3B,
-0xB0, 0x23, 0xC4, 0xF2, 0xFF, 0x06, 0x33, 0xFC, 0xE5, 0x01, 0x38,
-0xFF, 0x36, 0x00, 0xFD, 0xFF, 0xFE, 0xFF, 0x21, 0x00, 0x77, 0xFF,
-0x75, 0x01, 0xBF, 0xFC, 0xAB, 0x06, 0xA6, 0xF1, 0x05, 0x35, 0x40,
-0x2B, 0xBF, 0xF1, 0x2A, 0x07, 0x42, 0xFC, 0xCE, 0x01, 0x48, 0xFF,
-0x31, 0x00, 0xFD, 0xFF, 0xFD, 0xFF, 0x2E, 0x00, 0x52, 0xFF, 0xBC,
-0x01, 0x58, 0xFC, 0x1D, 0x07, 0x8E, 0xF1, 0x11, 0x2E, 0x6B, 0x32,
-0x81, 0xF1, 0xE5, 0x06, 0x90, 0xFC, 0x94, 0x01, 0x67, 0xFF, 0x26,
-0x00, 0xFD, 0xFF, 0xFD, 0xFF, 0x35, 0x00, 0x3C, 0xFF, 0xE0, 0x01,
-0x32, 0xFC, 0x1C, 0x07, 0x4B, 0xF2, 0xA0, 0x26, 0xF2, 0x38, 0x2A,
-0xF2, 0x28, 0x06, 0x1F, 0xFD, 0x39, 0x01, 0x96, 0xFF, 0x16, 0x00,
-0xFF, 0xFF, 0xFE, 0xFF, 0x36, 0x00, 0x36, 0xFF, 0xE4, 0x01, 0x48,
-0xFC, 0xB2, 0x06, 0xB9, 0xF3, 0xF3, 0x1E, 0x98, 0x3E, 0xCF, 0xF3,
-0xF3, 0x04, 0xEB, 0xFD, 0xBF, 0x00, 0xD4, 0xFF, 0xFF, 0xFF, 0x03,
-0x00, 0xFE, 0xFF, 0x34, 0x00, 0x3D, 0xFF, 0xCB, 0x01, 0x93, 0xFC,
-0xEF, 0x05, 0xB0, 0xF5, 0x4B, 0x17, 0x2A, 0x43, 0x7D, 0xF6, 0x4D,
-0x03, 0xEF, 0xFE, 0x2A, 0x00, 0x1E, 0x00, 0xE3, 0xFF, 0x08, 0x00,
-0xFF, 0xFF, 0x2E, 0x00, 0x4F, 0xFF, 0x99, 0x01, 0x0B, 0xFD, 0xE6,
-0x04, 0x08, 0xF8, 0xE7, 0x0F, 0x7C, 0x46, 0x37, 0xFA, 0x42, 0x01,
-0x1F, 0x00, 0x81, 0xFF, 0x71, 0x00, 0xC3, 0xFF, 0x0F, 0x00, 0x00,
-0x00, 0x26, 0x00, 0x6A, 0xFF, 0x55, 0x01, 0xA3, 0xFD, 0xAD, 0x03,
-0x94, 0xFA, 0xFF, 0x08, 0x70, 0x48, 0xF3, 0xFE, 0xEA, 0xFE, 0x6C,
-0x01, 0xCD, 0xFE, 0xC9, 0x00, 0xA1, 0xFF, 0x17, 0x00, 0x1D, 0x00,
-0x8A, 0xFF, 0x04, 0x01, 0x50, 0xFE, 0x5A, 0x02, 0x2C, 0xFD, 0xC6,
-0x02, 0xF2, 0x48, 0x9B, 0x04, 0x61, 0xFC, 0xC3, 0x02, 0x19, 0xFE,
-0x1E, 0x01, 0x7F, 0xFF, 0x20, 0x00, 0x00, 0x00, 0x14, 0x00, 0xAC,
-0xFF, 0xAE, 0x00, 0x05, 0xFF, 0x03, 0x01, 0xAA, 0xFF, 0x63, 0xFD,
-0xFD, 0x47, 0x0E, 0x0B, 0xC8, 0xF9, 0x11, 0x04, 0x71, 0xFD, 0x6C,
-0x01, 0x61, 0xFF, 0x28, 0x00, 0x00, 0x00, 0x0C, 0x00, 0xCD, 0xFF,
-0x57, 0x00, 0xB6, 0xFF, 0xBE, 0xFF, 0xED, 0x01, 0xF5, 0xF8, 0x9B,
-0x45, 0x22, 0x12, 0x48, 0xF7, 0x3D, 0x05, 0xE2, 0xFC, 0xAB, 0x01,
-0x49, 0xFF, 0x30, 0x00, 0xFF, 0xFF, 0x06, 0x00, 0xEC, 0xFF, 0x06,
-0x00, 0x5A, 0x00, 0x9A, 0xFE, 0xDA, 0x03, 0x8D, 0xF5, 0xE1, 0x41,
-0xA1, 0x19, 0x09, 0xF5, 0x33, 0x06, 0x77, 0xFC, 0xD6, 0x01, 0x3A,
-0xFF, 0x35, 0x00, 0xFE, 0xFF, 0x01, 0x00, 0x07, 0x00, 0xC0, 0xFF,
-0xE8, 0x00, 0xA6, 0xFD, 0x5F, 0x05, 0x31, 0xF3, 0xF6, 0x3C, 0x52,
-0x21, 0x37, 0xF3, 0xDD, 0x06, 0x3B, 0xFC, 0xE6, 0x01, 0x36, 0xFF,
-0x36, 0x00, 0xFD, 0xFF, 0xFE, 0xFF, 0x1C, 0x00, 0x86, 0xFF, 0x59,
-0x01, 0xEC, 0xFC, 0x6F, 0x06, 0xDC, 0xF1, 0x04, 0x37, 0xF3, 0x28,
-0xFC, 0xF1, 0x28, 0x07, 0x37, 0xFC, 0xD8, 0x01, 0x41, 0xFF, 0x33,
-0x00, 0xFD, 0xFF, 0xFD, 0xFF, 0x2A, 0x00, 0x5C, 0xFF, 0xAA, 0x01,
-0x71, 0xFC, 0x07, 0x07, 0x7E, 0xF1, 0x44, 0x30, 0x44, 0x30, 0x7E,
-0xF1, 0x07, 0x07, 0x71, 0xFC, 0xAA, 0x01, 0x5C, 0xFF, 0x2A, 0x00,
-0xFD, 0xFF, 0xFD, 0xFF, 0x33, 0x00, 0x41, 0xFF, 0xD8, 0x01, 0x37,
-0xFC, 0x28, 0x07, 0xFC, 0xF1, 0xF3, 0x28, 0x04, 0x37, 0xDC, 0xF1,
-0x6F, 0x06, 0xEC, 0xFC, 0x59, 0x01, 0x86, 0xFF, 0x1C, 0x00, 0xFE,
-0xFF, 0xFD, 0xFF, 0x36, 0x00, 0x36, 0xFF, 0xE6, 0x01, 0x3B, 0xFC,
-0xDD, 0x06, 0x37, 0xF3, 0x52, 0x21, 0xF6, 0x3C, 0x31, 0xF3, 0x5F,
-0x05, 0xA6, 0xFD, 0xE8, 0x00, 0xC0, 0xFF, 0x07, 0x00, 0x01, 0x00,
-0xFE, 0xFF, 0x35, 0x00, 0x3A, 0xFF, 0xD6, 0x01, 0x77, 0xFC, 0x33,
-0x06, 0x09, 0xF5, 0xA1, 0x19, 0xE1, 0x41, 0x8D, 0xF5, 0xDA, 0x03,
-0x9A, 0xFE, 0x5A, 0x00, 0x06, 0x00, 0xEC, 0xFF, 0x06, 0x00, 0xFF,
-0xFF, 0x30, 0x00, 0x49, 0xFF, 0xAB, 0x01, 0xE2, 0xFC, 0x3D, 0x05,
-0x48, 0xF7, 0x22, 0x12, 0x9B, 0x45, 0xF5, 0xF8, 0xED, 0x01, 0xBE,
-0xFF, 0xB6, 0xFF, 0x57, 0x00, 0xCD, 0xFF, 0x0C, 0x00, 0x00, 0x00,
-0x28, 0x00, 0x61, 0xFF, 0x6C, 0x01, 0x71, 0xFD, 0x11, 0x04, 0xC8,
-0xF9, 0x0E, 0x0B, 0xFD, 0x47, 0x63, 0xFD, 0xAA, 0xFF, 0x03, 0x01,
-0x05, 0xFF, 0xAE, 0x00, 0xAC, 0xFF, 0x14, 0x00, 0x00, 0x00, 0x20,
-0x00, 0x7F, 0xFF, 0x1E, 0x01, 0x19, 0xFE, 0xC3, 0x02, 0x61, 0xFC,
-0x9B, 0x04, 0xF2, 0x48, 0xC6, 0x02, 0x2C, 0xFD, 0x5A, 0x02, 0x50,
-0xFE, 0x04, 0x01, 0x8A, 0xFF, 0x1D, 0x00, 0x17, 0x00, 0xA1, 0xFF,
-0xC9, 0x00, 0xCD, 0xFE, 0x6C, 0x01, 0xEA, 0xFE, 0xF3, 0xFE, 0x70,
-0x48, 0xFF, 0x08, 0x94, 0xFA, 0xAD, 0x03, 0xA3, 0xFD, 0x55, 0x01,
-0x6A, 0xFF, 0x26, 0x00, 0x00, 0x00, 0x0F, 0x00, 0xC3, 0xFF, 0x71,
-0x00, 0x81, 0xFF, 0x1F, 0x00, 0x42, 0x01, 0x37, 0xFA, 0x7C, 0x46,
-0xE7, 0x0F, 0x08, 0xF8, 0xE6, 0x04, 0x0B, 0xFD, 0x99, 0x01, 0x4F,
-0xFF, 0x2E, 0x00, 0xFF, 0xFF, 0x08, 0x00, 0xE3, 0xFF, 0x1E, 0x00,
-0x2A, 0x00, 0xEF, 0xFE, 0x4D, 0x03, 0x7D, 0xF6, 0x2A, 0x43, 0x4B,
-0x17, 0xB0, 0xF5, 0xEF, 0x05, 0x93, 0xFC, 0xCB, 0x01, 0x3D, 0xFF,
-0x34, 0x00, 0xFE, 0xFF, 0x03, 0x00, 0xFF, 0xFF, 0xD4, 0xFF, 0xBF,
-0x00, 0xEB, 0xFD, 0xF3, 0x04, 0xCF, 0xF3, 0x98, 0x3E, 0xF3, 0x1E,
-0xB9, 0xF3, 0xB2, 0x06, 0x48, 0xFC, 0xE4, 0x01, 0x36, 0xFF, 0x36,
-0x00, 0xFE, 0xFF, 0xFF, 0xFF, 0x16, 0x00, 0x96, 0xFF, 0x39, 0x01,
-0x1F, 0xFD, 0x28, 0x06, 0x2A, 0xF2, 0xF2, 0x38, 0xA0, 0x26, 0x4B,
-0xF2, 0x1C, 0x07, 0x32, 0xFC, 0xE0, 0x01, 0x3C, 0xFF, 0x35, 0x00,
-0xFD, 0xFF, 0xFD, 0xFF, 0x26, 0x00, 0x67, 0xFF, 0x94, 0x01, 0x90,
-0xFC, 0xE5, 0x06, 0x81, 0xF1, 0x6B, 0x32, 0x11, 0x2E, 0x8E, 0xF1,
-0x1D, 0x07, 0x58, 0xFC, 0xBC, 0x01, 0x52, 0xFF, 0x2E, 0x00, 0xFD,
-0xFF, 0xFD, 0xFF, 0x31, 0x00, 0x48, 0xFF, 0xCE, 0x01, 0x42, 0xFC,
-0x2A, 0x07, 0xBF, 0xF1, 0x40, 0x2B, 0x05, 0x35, 0xA6, 0xF1, 0xAB,
-0x06, 0xBF, 0xFC, 0x75, 0x01, 0x77, 0xFF, 0x21, 0x00, 0xFE, 0xFF,
-0xFD, 0xFF, 0x36, 0x00, 0x38, 0xFF, 0xE5, 0x01, 0x33, 0xFC, 0xFF,
-0x06, 0xC4, 0xF2, 0xB0, 0x23, 0x3B, 0x3B, 0xAD, 0xF2, 0xBF, 0x05,
-0x66, 0xFD, 0x0E, 0x01, 0xAC, 0xFF, 0x0E, 0x00, 0x00, 0x00, 0xFE,
-0xFF, 0x36, 0x00, 0x37, 0xFF, 0xDE, 0x01, 0x5F, 0xFC, 0x70, 0x06,
-0x6C, 0xF4, 0xFD, 0x1B, 0x7D, 0x40, 0xB7, 0xF4, 0x5D, 0x04, 0x49,
-0xFE, 0x88, 0x00, 0xEF, 0xFF, 0xF5, 0xFF, 0x04, 0x00, 0xFF, 0xFF,
-0x32, 0x00, 0x43, 0xFF, 0xBA, 0x01, 0xBC, 0xFC, 0x90, 0x05, 0x8E,
-0xF6, 0x68, 0x14, 0x99, 0x44, 0xCD, 0xF7, 0x8F, 0x02, 0x60, 0xFF,
-0xEA, 0xFF, 0x3E, 0x00, 0xD7, 0xFF, 0x0A, 0x00, 0x00, 0x00, 0x2B,
-0x00, 0x59, 0xFF, 0x81, 0x01, 0x42, 0xFD, 0x72, 0x04, 0xFF, 0xF8,
-0x2D, 0x0D, 0x69, 0x47, 0xEB, 0xFB, 0x63, 0x00, 0x9D, 0x00, 0x3C,
-0xFF, 0x93, 0x00, 0xB6, 0xFF, 0x12, 0x00, 0x00, 0x00, 0x22, 0x00,
-0x76, 0xFF, 0x37, 0x01, 0xE4, 0xFD, 0x2C, 0x03, 0x94, 0xFB, 0x83,
-0x06, 0xCE, 0x48, 0x05, 0x01, 0xF5, 0xFD, 0xF0, 0x01, 0x87, 0xFE,
-0xEA, 0x00, 0x94, 0xFF, 0x1A, 0x00, 0x1A, 0x00, 0x96, 0xFF, 0xE3,
-0x00, 0x95, 0xFE, 0xD5, 0x01, 0x26, 0xFE, 0x98, 0x00, 0xBF, 0x48,
-0x00, 0x07, 0x61, 0xFB, 0x46, 0x03, 0xD6, 0xFD, 0x3D, 0x01, 0x73,
-0xFF, 0x23, 0x00, 0x00, 0x00, 0x11, 0x00, 0xB9, 0xFF, 0x8C, 0x00,
-0x4A, 0xFF, 0x83, 0x00, 0x91, 0x00, 0x91, 0xFB, 0x3D, 0x47, 0xB7,
-0x0D, 0xCD, 0xF8, 0x89, 0x04, 0x36, 0xFD, 0x86, 0x01, 0x57, 0xFF,
-0x2B, 0x00, 0x00, 0x00, 0x0A, 0x00, 0xD9, 0xFF, 0x37, 0x00, 0xF7,
-0xFF, 0x49, 0xFF, 0xB6, 0x02, 0x86, 0xF7, 0x53, 0x44, 0xFB, 0x14,
-0x61, 0xF6, 0xA4, 0x05, 0xB4, 0xFC, 0xBE, 0x01, 0x42, 0xFF, 0x32,
-0x00, 0xFF, 0xFF, 0x04, 0x00, 0xF7, 0xFF, 0xEA, 0xFF, 0x93, 0x00,
-0x36, 0xFE, 0x7D, 0x04, 0x85, 0xF4, 0x1F, 0x40, 0x94, 0x1C, 0x47,
-0xF4, 0x7E, 0x06, 0x5A, 0xFC, 0xDF, 0x01, 0x37, 0xFF, 0x36, 0x00,
-0xFE, 0xFF, 0x00, 0x00, 0x0F, 0x00, 0xA8, 0xFF, 0x17, 0x01, 0x57,
-0xFD, 0xD6, 0x05, 0x90, 0xF2, 0xC8, 0x3A, 0x46, 0x24, 0xAA, 0xF2,
-0x06, 0x07, 0x32, 0xFC, 0xE5, 0x01, 0x39, 0xFF, 0x36, 0x00, 0xFD,
-0xFF, 0xFE, 0xFF, 0x22, 0x00, 0x74, 0xFF, 0x7C, 0x01, 0xB5, 0xFC,
-0xB8, 0x06, 0x9C, 0xF1, 0x81, 0x34, 0xD1, 0x2B, 0xB3, 0xF1, 0x29,
-0x07, 0x46, 0xFC, 0xCA, 0x01, 0x4A, 0xFF, 0x30, 0x00, 0xFD, 0xFF,
-0xFD, 0xFF, 0x2E, 0x00, 0x50, 0xFF, 0xC0, 0x01, 0x53, 0xFC, 0x21,
-0x07, 0x96, 0xF1, 0x82, 0x2D, 0xF2, 0x32, 0x86, 0xF1, 0xDB, 0x06,
-0x99, 0xFC, 0x8E, 0x01, 0x6A, 0xFF, 0x25, 0x00, 0xFD, 0xFF, 0xFD,
-0xFF, 0x35, 0x00, 0x3B, 0xFF, 0xE2, 0x01, 0x31, 0xFC, 0x17, 0x07,
-0x61, 0xF2, 0x0A, 0x26, 0x6A, 0x39, 0x41, 0xF2, 0x15, 0x06, 0x2C,
-0xFD, 0x31, 0x01, 0x9B, 0xFF, 0x14, 0x00, 0xFF, 0xFF, 0xFE, 0xFF,
-0x36, 0x00, 0x36, 0xFF, 0xE3, 0x01, 0x4C, 0xFC, 0xA6, 0x06, 0xDB,
-0xF3, 0x5B, 0x1E, 0xFC, 0x3E, 0xFA, 0xF3, 0xD7, 0x04, 0xFD, 0xFD,
-0xB4, 0x00, 0xD9, 0xFF, 0xFD, 0xFF, 0x03, 0x00, 0xFF, 0xFF, 0x33,
-0x00, 0x3E, 0xFF, 0xC8, 0x01, 0x9B, 0xFC, 0xDD, 0x05, 0xDC, 0xF5,
-0xB6, 0x16, 0x77, 0x43, 0xBD, 0xF6, 0x28, 0x03, 0x05, 0xFF, 0x1D,
-0x00, 0x25, 0x00, 0xE1, 0xFF, 0x08, 0x00, 0xFF, 0xFF, 0x2D, 0x00,
-0x51, 0xFF, 0x95, 0x01, 0x15, 0xFD, 0xCF, 0x04, 0x39, 0xF8, 0x59,
-0x0F, 0xAF, 0x46, 0x8B, 0xFA, 0x17, 0x01, 0x38, 0x00, 0x73, 0xFF,
-0x78, 0x00, 0xC0, 0xFF, 0x0F, 0x00, 0x00, 0x00, 0x25, 0x00, 0x6C,
-0xFF, 0x4F, 0x01, 0xB0, 0xFD, 0x93, 0x03, 0xC7, 0xFA, 0x7D, 0x08,
-0x86, 0x48, 0x5A, 0xFF, 0xBA, 0xFE, 0x86, 0x01, 0xBF, 0xFE, 0xCF,
-0x00, 0x9E, 0xFF, 0x17, 0x00, 0x1C, 0x00, 0x8C, 0xFF, 0xFE, 0x00,
-0x5D, 0xFE, 0x3F, 0x02, 0x5E, 0xFD, 0x54, 0x02, 0xEC, 0x48, 0x13,
-0x05, 0x2E, 0xFC, 0xDE, 0x02, 0x0C, 0xFE, 0x24, 0x01, 0x7D, 0xFF,
-0x20, 0x00, 0x00, 0x00, 0x14, 0x00, 0xAE, 0xFF, 0xA7, 0x00, 0x12,
-0xFF, 0xEA, 0x00, 0xD9, 0xFF, 0x03, 0xFD, 0xDC, 0x47, 0x95, 0x0B,
-0x96, 0xF9, 0x29, 0x04, 0x65, 0xFD, 0x71, 0x01, 0x5F, 0xFF, 0x29,
-0x00, 0x00, 0x00, 0x0C, 0x00, 0xD0, 0xFF, 0x51, 0x00, 0xC3, 0xFF,
-0xA6, 0xFF, 0x16, 0x02, 0xA9, 0xF8, 0x5C, 0x45, 0xB2, 0x12, 0x19,
-0xF7, 0x52, 0x05, 0xD8, 0xFC, 0xAF, 0x01, 0x47, 0xFF, 0x30, 0x00,
-0xFF, 0xFF, 0x06, 0x00, 0xEE, 0xFF, 0x01, 0x00, 0x66, 0x00, 0x85,
-0xFE, 0xFC, 0x03, 0x55, 0xF5, 0x8C, 0x41, 0x38, 0x1A, 0xE1, 0xF4,
-0x43, 0x06, 0x70, 0xFC, 0xD8, 0x01, 0x39, 0xFF, 0x35, 0x00, 0xFE,
-0xFF, 0x01, 0x00, 0x08, 0x00, 0xBB, 0xFF, 0xF1, 0x00, 0x96, 0xFD,
-0x78, 0x05, 0x0E, 0xF3, 0x8A, 0x3C, 0xEA, 0x21, 0x19, 0xF3, 0xE6,
-0x06, 0x38, 0xFC, 0xE6, 0x01, 0x37, 0xFF, 0x36, 0x00, 0xFD, 0xFF,
-0xFE, 0xFF, 0x1D, 0x00, 0x82, 0xFF, 0x60, 0x01, 0xE0, 0xFC, 0x7F,
-0x06, 0xCC, 0xF1, 0x85, 0x36, 0x87, 0x29, 0xEB, 0xF1, 0x2A, 0x07,
-0x39, 0xFC, 0xD6, 0x01, 0x43, 0xFF, 0x33, 0x00, 0xFD, 0xFF, 0xFD,
-0xFF, 0x2B, 0x00, 0x59, 0xFF, 0xAE, 0x01, 0x6A, 0xFC, 0x0D, 0x07,
-0x80, 0xF1, 0xB8, 0x2F, 0xCF, 0x30, 0x7D, 0xF1, 0xFF, 0x06, 0x78,
-0xFC, 0xA5, 0x01, 0x5F, 0xFF, 0x29, 0x00, 0xFD, 0xFF, 0xFD, 0xFF,
-0x34, 0x00, 0x40, 0xFF, 0xDB, 0x01, 0x35, 0xFC, 0x26, 0x07, 0x0E,
-0xF2, 0x60, 0x28, 0x82, 0x37, 0xED, 0xF1, 0x5E, 0x06, 0xF8, 0xFC,
-0x51, 0x01, 0x8A, 0xFF, 0x1A, 0x00, 0xFF, 0xFF, 0xFD, 0xFF, 0x36,
-0x00, 0x36, 0xFF, 0xE6, 0x01, 0x3E, 0xFC, 0xD3, 0x06, 0x56, 0xF3,
-0xBA, 0x20, 0x61, 0x3D, 0x56, 0xF3, 0x45, 0x05, 0xB7, 0xFD, 0xDE,
-0x00, 0xC5, 0xFF, 0x05, 0x00, 0x02, 0x00, 0xFE, 0xFF, 0x35, 0x00,
-0x3A, 0xFF, 0xD3, 0x01, 0x7D, 0xFC, 0x23, 0x06, 0x32, 0xF5, 0x0C,
-0x19, 0x38, 0x42, 0xC7, 0xF5, 0xB8, 0x03, 0xAF, 0xFE, 0x4E, 0x00,
-0x0C, 0x00, 0xEA, 0xFF, 0x06, 0x00, 0xFF, 0xFF, 0x2F, 0x00, 0x4A,
-0xFF, 0xA7, 0x01, 0xEC, 0xFC, 0x28, 0x05, 0x77, 0xF7, 0x92, 0x11,
-0xD7, 0x45, 0x43, 0xF9, 0xC3, 0x01, 0xD6, 0xFF, 0xA9, 0xFF, 0x5E,
-0x00, 0xCB, 0xFF, 0x0D, 0x00, 0x00, 0x00, 0x28, 0x00, 0x63, 0xFF,
-0x66, 0x01, 0x7D, 0xFD, 0xF8, 0x03, 0xFB, 0xF9, 0x89, 0x0A, 0x1D,
-0x48, 0xC5, 0xFD, 0x7A, 0xFF, 0x1D, 0x01, 0xF7, 0xFE, 0xB4, 0x00,
-0xA9, 0xFF, 0x15, 0x00, 0x00, 0x00, 0x1F, 0x00, 0x82, 0xFF, 0x18,
-0x01, 0x27, 0xFE, 0xA9, 0x02, 0x94, 0xFC, 0x24, 0x04, 0xF5, 0x48,
-0x39, 0x03, 0xF9, 0xFC, 0x74, 0x02, 0x42, 0xFE, 0x0B, 0x01, 0x87,
-0xFF, 0x1E, 0x00, 0x16, 0x00, 0xA4, 0xFF, 0xC2, 0x00, 0xDB, 0xFE,
-0x52, 0x01, 0x1B, 0xFF, 0x8D, 0xFE, 0x57, 0x48, 0x81, 0x09, 0x61,
-0xFA, 0xC6, 0x03, 0x96, 0xFD, 0x5B, 0x01, 0x68, 0xFF, 0x26, 0x00,
-0x00, 0x00, 0x0E, 0x00, 0xC6, 0xFF, 0x6B, 0x00, 0x8E, 0xFF, 0x06,
-0x00, 0x6E, 0x01, 0xE4, 0xF9, 0x48, 0x46, 0x75, 0x10, 0xD7, 0xF7,
-0xFC, 0x04, 0x00, 0xFD, 0x9E, 0x01, 0x4E, 0xFF, 0x2E, 0x00, 0xFF,
-0xFF, 0x07, 0x00, 0xE5, 0xFF, 0x18, 0x00, 0x36, 0x00, 0xD9, 0xFE,
-0x71, 0x03, 0x3F, 0xF6, 0xDB, 0x42, 0xE0, 0x17, 0x86, 0xF5, 0x00,
-0x06, 0x8C, 0xFC, 0xCE, 0x01, 0x3C, 0xFF, 0x34, 0x00, 0xFE, 0xFF,
-0x02, 0x00, 0x01, 0x00, 0xCF, 0xFF, 0xC9, 0x00, 0xDA, 0xFD, 0x0F,
-0x05, 0xA5, 0xF3, 0x31, 0x3E, 0x8A, 0x1F, 0x97, 0xF3, 0xBD, 0x06,
-0x44, 0xFC, 0xE5, 0x01, 0x36, 0xFF, 0x36, 0x00, 0xFD, 0xFF, 0xFF,
-0xFF, 0x17, 0x00, 0x92, 0xFF, 0x41, 0x01, 0x11, 0xFD, 0x3B, 0x06,
-0x14, 0xF2, 0x78, 0x38, 0x36, 0x27, 0x35, 0xF2, 0x20, 0x07, 0x33,
-0xFC, 0xDF, 0x01, 0x3E, 0xFF, 0x34, 0x00, 0xFD, 0xFF, 0xFD, 0xFF,
-0x28, 0x00, 0x64, 0xFF, 0x9A, 0x01, 0x88, 0xFC, 0xEE, 0x06, 0x7E,
-0xF1, 0xE3, 0x31, 0x9F, 0x2E, 0x88, 0xF1, 0x19, 0x07, 0x5E, 0xFC,
-0xB7, 0x01, 0x54, 0xFF, 0x2D, 0x00, 0xFD, 0xFF, 0xFD, 0xFF, 0x32,
-0x00, 0x46, 0xFF, 0xD1, 0x01, 0x3F, 0xFC, 0x2B, 0x07, 0xCD, 0xF1,
-0xAE, 0x2A, 0x86, 0x35, 0xB1, 0xF1, 0x9D, 0x06, 0xCA, 0xFC, 0x6E,
-0x01, 0x7B, 0xFF, 0x20, 0x00, 0xFE, 0xFF, 0xFD, 0xFF, 0x36, 0x00,
-0x38, 0xFF, 0xE6, 0x01, 0x35, 0xFC, 0xF7, 0x06, 0xE0, 0xF2, 0x18,
-0x23, 0xAB, 0x3B, 0xCC, 0xF2, 0xA8, 0x05, 0x76, 0xFD, 0x04, 0x01,
-0xB1, 0xFF, 0x0C, 0x00, 0x00, 0x00, 0xFE, 0xFF, 0x36, 0x00, 0x38,
-0xFF, 0xDC, 0x01, 0x64, 0xFC, 0x62, 0x06, 0x93, 0xF4, 0x66, 0x1B,
-0xD9, 0x40, 0xEA, 0xF4, 0x3E, 0x04, 0x5D, 0xFE, 0x7D, 0x00, 0xF5,
-0xFF, 0xF3, 0xFF, 0x05, 0x00, 0xFF, 0xFF, 0x31, 0x00, 0x44, 0xFF,
-0xB7, 0x01, 0xC5, 0xFC, 0x7C, 0x05, 0xBC, 0xF6, 0xD5, 0x13, 0xDC,
-0x44, 0x14, 0xF8, 0x67, 0x02, 0x77, 0xFF, 0xDD, 0xFF, 0x44, 0x00,
-0xD5, 0xFF, 0x0B, 0x00, 0x00, 0x00, 0x2A, 0x00, 0x5B, 0xFF, 0x7C,
-0x01, 0x4E, 0xFD, 0x5A, 0x04, 0x31, 0xF9, 0xA4, 0x0C, 0x90, 0x47,
-0x47, 0xFC, 0x36, 0x00, 0xB6, 0x00, 0x2E, 0xFF, 0x99, 0x00, 0xB3,
-0xFF, 0x12, 0x00, 0x00, 0x00, 0x22, 0x00, 0x78, 0xFF, 0x31, 0x01,
-0xF1, 0xFD, 0x12, 0x03, 0xC7, 0xFB, 0x07, 0x06, 0xDB, 0x48, 0x73,
-0x01, 0xC3, 0xFD, 0x0A, 0x02, 0x79, 0xFE, 0xF1, 0x00, 0x91, 0xFF,
-0x1B, 0x00, 0x19, 0x00, 0x99, 0xFF, 0xDD, 0x00, 0xA3, 0xFE, 0xBB,
-0x01, 0x58, 0xFE, 0x2D, 0x00, 0xAF, 0x48, 0x7E, 0x07, 0x2E, 0xFB,
-0x60, 0x03, 0xC9, 0xFD, 0x43, 0x01, 0x71, 0xFF, 0x24, 0x00, 0x00,
-0x00, 0x10, 0x00, 0xBB, 0xFF, 0x85, 0x00, 0x58, 0xFF, 0x6A, 0x00,
-0xBE, 0x00, 0x38, 0xFB, 0x0F, 0x47, 0x42, 0x0E, 0x9B, 0xF8, 0xA1,
-0x04, 0x2B, 0xFD, 0x8B, 0x01, 0x55, 0xFF, 0x2C, 0x00, 0xFF, 0xFF,
-0x09, 0x00, 0xDC, 0xFF, 0x31, 0x00, 0x04, 0x00, 0x32, 0xFF, 0xDC,
-0x02, 0x42, 0xF7, 0x0B, 0x44, 0x8E, 0x15, 0x34, 0xF6, 0xB7, 0x05,
-0xAB, 0xFC, 0xC1, 0x01, 0x40, 0xFF, 0x33, 0x00, 0xFF, 0xFF, 0x04,
-0x00, 0xF9, 0xFF, 0xE4, 0xFF, 0x9F, 0x00, 0x23, 0xFE, 0x9B, 0x04,
-0x55, 0xF4, 0xC0, 0x3F, 0x2C, 0x1D, 0x22, 0xF4, 0x8C, 0x06, 0x55,
-0xFC, 0xE1, 0x01, 0x37, 0xFF, 0x36, 0x00, 0xFE, 0xFF, 0x00, 0x00,
-0x11, 0x00, 0xA3, 0xFF, 0x20, 0x01, 0x49, 0xFD, 0xEB, 0x05, 0x74,
-0xF2, 0x54, 0x3A, 0xDD, 0x24, 0x91, 0xF2, 0x0C, 0x07, 0x32, 0xFC,
-0xE4, 0x01, 0x3A, 0xFF, 0x36, 0x00, 0xFD, 0xFF, 0xFE, 0xFF, 0x23,
-0x00, 0x71, 0xFF, 0x82, 0x01, 0xAB, 0xFC, 0xC4, 0x06, 0x93, 0xF1,
-0xFD, 0x33, 0x62, 0x2C, 0xA8, 0xF1, 0x27, 0x07, 0x4A, 0xFC, 0xC7,
-0x01, 0x4C, 0xFF, 0x30, 0x00, 0xFD, 0xFF, 0xFD, 0xFF, 0x2F, 0x00,
-0x4E, 0xFF, 0xC3, 0x01, 0x4E, 0xFC, 0x24, 0x07, 0x9E, 0xF1, 0xF2,
-0x2C, 0x78, 0x33, 0x8C, 0xF1, 0xD0, 0x06, 0xA2, 0xFC, 0x88, 0x01,
-0x6D, 0xFF, 0x24, 0x00, 0xFD, 0xFF, 0xFD, 0xFF, 0x35, 0x00, 0x3B,
-0xFF, 0xE3, 0x01, 0x31, 0xFC, 0x12, 0x07, 0x79, 0xF2, 0x73, 0x25,
-0xDF, 0x39, 0x5A, 0xF2, 0x00, 0x06, 0x3A, 0xFD, 0x28, 0x01, 0x9F,
-0xFF, 0x13, 0x00, 0x00, 0x00, 0xFE, 0xFF, 0x36, 0x00, 0x36, 0xFF,
-0xE2, 0x01, 0x50, 0xFC, 0x99, 0x06, 0xFE, 0xF3, 0xC3, 0x1D, 0x5E,
-0x3F, 0x27, 0xF4, 0xB9, 0x04, 0x10, 0xFE, 0xA9, 0x00, 0xDF, 0xFF,
-0xFB, 0xFF, 0x03, 0x00, 0xFF, 0xFF, 0x33, 0x00, 0x3F, 0xFF, 0xC5,
-0x01, 0xA3, 0xFC, 0xCA, 0x05, 0x07, 0xF6, 0x22, 0x16, 0xC3, 0x43,
-0xFE, 0xF6, 0x02, 0x03, 0x1B, 0xFF, 0x11, 0x00, 0x2B, 0x00, 0xDE,
-0xFF, 0x09, 0x00, 0xFF, 0xFF, 0x2D, 0x00, 0x53, 0xFF, 0x90, 0x01,
-0x20, 0xFD, 0xB8, 0x04, 0x6A, 0xF8, 0xCD, 0x0E, 0xE1, 0x46, 0xE1,
-0xFA, 0xEB, 0x00, 0x51, 0x00, 0x65, 0xFF, 0x7F, 0x00, 0xBE, 0xFF,
-0x10, 0x00, 0x00, 0x00, 0x24, 0x00, 0x6E, 0xFF, 0x49, 0x01, 0xBC,
-0xFD, 0x7A, 0x03, 0xFA, 0xFA, 0xFD, 0x07, 0x9C, 0x48, 0xC3, 0xFF,
-0x89, 0xFE, 0xA1, 0x01, 0xB1, 0xFE, 0xD6, 0x00, 0x9C, 0xFF, 0x18,
-0x00, 0x1C, 0x00, 0x8F, 0xFF, 0xF7, 0x00, 0x6B, 0xFE, 0x25, 0x02,
-0x91, 0xFD, 0xE3, 0x01, 0xE5, 0x48, 0x8D, 0x05, 0xFB, 0xFB, 0xF8,
-0x02, 0xFE, 0xFD, 0x2B, 0x01, 0x7A, 0xFF, 0x21, 0x00, 0x00, 0x00,
-0x13, 0x00, 0xB1, 0xFF, 0xA0, 0x00, 0x20, 0xFF, 0xD0, 0x00, 0x07,
-0x00, 0xA4, 0xFC, 0xB6, 0x47, 0x1C, 0x0C, 0x63, 0xF9, 0x42, 0x04,
-0x59, 0xFD, 0x76, 0x01, 0x5D, 0xFF, 0x2A, 0x00, 0x00, 0x00, 0x0B,
-0x00, 0xD2, 0xFF, 0x4A, 0x00, 0xD0, 0xFF, 0x8E, 0xFF, 0x3F, 0x02,
-0x5E, 0xF8, 0x1E, 0x45, 0x44, 0x13, 0xEA, 0xF6, 0x67, 0x05, 0xCF,
-0xFC, 0xB3, 0x01, 0x46, 0xFF, 0x31, 0x00, 0xFF, 0xFF, 0x05, 0x00,
-0xF0, 0xFF, 0xFB, 0xFF, 0x71, 0x00, 0x71, 0xFE, 0x1D, 0x04, 0x1F,
-0xF5, 0x32, 0x41, 0xCE, 0x1A, 0xBA, 0xF4, 0x53, 0x06, 0x6A, 0xFC,
-0xDA, 0x01, 0x38, 0xFF, 0x35, 0x00, 0xFE, 0xFF, 0x01, 0x00, 0x0A,
-0x00, 0xB6, 0xFF, 0xFB, 0x00, 0x85, 0xFD, 0x90, 0x05, 0xEC, 0xF2,
-0x1C, 0x3C, 0x81, 0x22, 0xFC, 0xF2, 0xEF, 0x06, 0x36, 0xFC, 0xE6,
-0x01, 0x37, 0xFF, 0x36, 0x00, 0xFD, 0xFF, 0xFE, 0xFF, 0x1E, 0x00,
-0x7F, 0xFF, 0x67, 0x01, 0xD5, 0xFC, 0x8E, 0x06, 0xBE, 0xF1, 0x06,
-0x36, 0x1A, 0x2A, 0xDC, 0xF1, 0x2A, 0x07, 0x3C, 0xFC, 0xD3, 0x01,
-0x44, 0xFF, 0x32, 0x00, 0xFD, 0xFF, 0xFD, 0xFF, 0x2C, 0x00, 0x57,
-0xFF, 0xB3, 0x01, 0x64, 0xFC, 0x13, 0x07, 0x83, 0xF1, 0x2C, 0x2F,
-0x5A, 0x31, 0x7D, 0xF1, 0xF7, 0x06, 0x80, 0xFC, 0x9F, 0x01, 0x61,
-0xFF, 0x29, 0x00, 0xFD, 0xFF, 0xFD, 0xFF, 0x34, 0x00, 0x3F, 0xFF,
-0xDD, 0x01, 0x34, 0xFC, 0x23, 0x07, 0x21, 0xF2, 0xCB, 0x27, 0xFE,
-0x37, 0x00, 0xF2, 0x4D, 0x06, 0x04, 0xFD, 0x49, 0x01, 0x8E, 0xFF,
-0x19, 0x00, 0xFF, 0xFF, 0xFD, 0xFF, 0x36, 0x00, 0x36, 0xFF, 0xE6,
-0x01, 0x41, 0xFC, 0xC8, 0x06, 0x76, 0xF3, 0x22, 0x20, 0xCA, 0x3D,
-0x7D, 0xF3, 0x2A, 0x05, 0xC8, 0xFD, 0xD4, 0x00, 0xCA, 0xFF, 0x03,
-0x00, 0x02, 0x00, 0xFE, 0xFF, 0x34, 0x00, 0x3B, 0xFF, 0xD1, 0x01,
-0x84, 0xFC, 0x12, 0x06, 0x5C, 0xF5, 0x76, 0x18, 0x89, 0x42, 0x02,
-0xF6, 0x94, 0x03, 0xC4, 0xFE, 0x42, 0x00, 0x12, 0x00, 0xE8, 0xFF,
-0x07, 0x00, 0xFF, 0xFF, 0x2F, 0x00, 0x4C, 0xFF, 0xA2, 0x01, 0xF6,
-0xFC, 0x12, 0x05, 0xA7, 0xF7, 0x03, 0x11, 0x10, 0x46, 0x93, 0xF9,
-0x98, 0x01, 0xEE, 0xFF, 0x9B, 0xFF, 0x64, 0x00, 0xC8, 0xFF, 0x0E,
-0x00, 0x00, 0x00, 0x27, 0x00, 0x65, 0xFF, 0x60, 0x01, 0x8A, 0xFD,
-0xDF, 0x03, 0x2E, 0xFA, 0x04, 0x0A, 0x3A, 0x48, 0x28, 0xFE, 0x4B,
-0xFF, 0x38, 0x01, 0xE9, 0xFE, 0xBB, 0x00, 0xA6, 0xFF, 0x16, 0x00,
-0x00, 0x00, 0x1E, 0x00, 0x84, 0xFF, 0x11, 0x01, 0x34, 0xFE, 0x8F,
-0x02, 0xC7, 0xFC, 0xAE, 0x03, 0xF7, 0x48, 0xAE, 0x03, 0xC7, 0xFC,
-0x8F, 0x02, 0x34, 0xFE, 0x11, 0x01, 0x84, 0xFF, 0x1E, 0x00, 0x00,
-0x00, 0xF4, 0xFF, 0x1A, 0x00, 0xFF, 0x00, 0x07, 0x03, 0x16, 0x06,
-0x7C, 0x09, 0x2A, 0x0C, 0x2E, 0x0D, 0x2A, 0x0C, 0x7C, 0x09, 0x16,
-0x06, 0x07, 0x03, 0xFF, 0x00, 0x1A, 0x00, 0xF4, 0xFF, 0xF2, 0xFF,
-0xA0, 0xFF, 0x71, 0xFF, 0x71, 0x00, 0x86, 0x03, 0x73, 0x08, 0x88,
-0x0D, 0x78, 0x10, 0xC9, 0x0F, 0xD5, 0x0B, 0x8B, 0x06, 0x28, 0x02,
-0xDF, 0xFF, 0x6F, 0xFF, 0xC3, 0xFF, 0xFD, 0xFF, 0x00, 0x00, 0xDC,
-0xFF, 0x80, 0xFF, 0x9A, 0xFF, 0x46, 0x01, 0x1E, 0x05, 0x5A, 0x0A,
-0xED, 0x0E, 0xAA, 0x10, 0xAF, 0x0E, 0xFD, 0x09, 0xCB, 0x04, 0x18,
-0x01, 0x8E, 0xFF, 0x85, 0xFF, 0xE1, 0xFF, 0xFC, 0xFF, 0xBD, 0xFF,
-0x6D, 0xFF, 0xF6, 0xFF, 0x65, 0x02, 0xE5, 0x06, 0x2B, 0x0C, 0xF3,
-0x0F, 0x60, 0x10, 0x3B, 0x0D, 0x16, 0x08, 0x3F, 0x03, 0x50, 0x00,
-0x6E, 0xFF, 0xA7, 0xFF, 0xF5, 0xFF, 0xEF, 0xFF, 0x9A, 0xFF, 0x75,
-0xFF, 0x91, 0x00, 0xC9, 0x03, 0xC8, 0x08, 0xCC, 0x0D, 0x89, 0x10,
-0x9F, 0x0F, 0x85, 0x0B, 0x3B, 0x06, 0xF4, 0x01, 0xCD, 0xFF, 0x72,
-0xFF, 0xC9, 0xFF, 0xFE, 0xFF, 0x00, 0x00, 0xD7, 0xFF, 0x7B, 0xFF,
-0xA5, 0xFF, 0x73, 0x01, 0x6A, 0x05, 0xAD, 0x0A, 0x21, 0x0F, 0xA6,
-0x10, 0x74, 0x0E, 0xA9, 0x09, 0x83, 0x04, 0xF0, 0x00, 0x85, 0xFF,
-0x8B, 0xFF, 0xE5, 0xFF, 0xFA, 0xFF, 0xB7, 0xFF, 0x6C, 0xFF, 0x0C,
-0x00, 0x9D, 0x02, 0x37, 0x07, 0x78, 0x0C, 0x15, 0x10, 0x47, 0x10,
-0xF3, 0x0C, 0xC2, 0x07, 0x01, 0x03, 0x35, 0x00, 0x6D, 0xFF, 0xAD,
-0xFF, 0xF7, 0xFF, 0xEB, 0xFF, 0x94, 0xFF, 0x7A, 0xFF, 0xB3, 0x00,
-0x0D, 0x04, 0x1C, 0x09, 0x0D, 0x0E, 0x97, 0x10, 0x73, 0x0F, 0x35,
-0x0B, 0xEB, 0x05, 0xC1, 0x01, 0xBD, 0xFF, 0x75, 0xFF, 0xCE, 0xFF,
-0xFF, 0xFF, 0xFF, 0xFF, 0xD2, 0xFF, 0x77, 0xFF, 0xB3, 0xFF, 0xA1,
-0x01, 0xB7, 0x05, 0xFF, 0x0A, 0x53, 0x0F, 0x9E, 0x10, 0x37, 0x0E,
-0x55, 0x09, 0x3B, 0x04, 0xCB, 0x00, 0x7E, 0xFF, 0x90, 0xFF, 0xE9,
-0xFF, 0xF8, 0xFF, 0xB1, 0xFF, 0x6C, 0xFF, 0x24, 0x00, 0xD8, 0x02,
-0x8A, 0x07, 0xC2, 0x0C, 0x34, 0x10, 0x2A, 0x10, 0xAA, 0x0C, 0x6F,
-0x07, 0xC4, 0x02, 0x1C, 0x00, 0x6C, 0xFF, 0xB3, 0xFF, 0xF9, 0xFF,
-0xE8, 0xFF, 0x8E, 0xFF, 0x80, 0xFF, 0xD7, 0x00, 0x53, 0x04, 0x71,
-0x09, 0x4C, 0x0E, 0xA1, 0x10, 0x43, 0x0F, 0xE3, 0x0A, 0x9D, 0x05,
-0x91, 0x01, 0xAE, 0xFF, 0x79, 0xFF, 0xD4, 0xFF, 0x00, 0x00, 0xFF,
-0xFF, 0xCD, 0xFF, 0x74, 0xFF, 0xC2, 0xFF, 0xD2, 0x01, 0x06, 0x06,
-0x50, 0x0B, 0x82, 0x0F, 0x93, 0x10, 0xF8, 0x0D, 0x00, 0x09, 0xF6,
-0x03, 0xA7, 0x00, 0x78, 0xFF, 0x96, 0xFF, 0xEC, 0xFF, 0xF6, 0xFF,
-0xAB, 0xFF, 0x6D, 0xFF, 0x3E, 0x00, 0x15, 0x03, 0xDE, 0x07, 0x0B,
-0x0D, 0x50, 0x10, 0x0A, 0x10, 0x5E, 0x0C, 0x1C, 0x07, 0x8A, 0x02,
-0x04, 0x00, 0x6C, 0xFF, 0xB9, 0xFF, 0xFB, 0xFF, 0xE4, 0xFF, 0x89,
-0xFF, 0x88, 0xFF, 0xFD, 0x00, 0x9B, 0x04, 0xC5, 0x09, 0x88, 0x0E,
-0xA8, 0x10, 0x10, 0x0F, 0x91, 0x0A, 0x50, 0x05, 0x64, 0x01, 0xA1,
-0xFF, 0x7D, 0xFF, 0xD9, 0xFF, 0x00, 0x00, 0xFE, 0xFF, 0xC7, 0xFF,
-0x71, 0xFF, 0xD3, 0xFF, 0x05, 0x02, 0x55, 0x06, 0xA0, 0x0B, 0xAD,
-0x0F, 0x84, 0x10, 0xB6, 0x0D, 0xAC, 0x08, 0xB3, 0x03, 0x86, 0x00,
-0x74, 0xFF, 0x9C, 0xFF, 0xF0, 0xFF, 0xF4, 0xFF, 0xA5, 0xFF, 0x6F,
-0xFF, 0x5A, 0x00, 0x54, 0x03, 0x32, 0x08, 0x52, 0x0D, 0x68, 0x10,
-0xE6, 0x0F, 0x11, 0x0C, 0xCA, 0x06, 0x52, 0x02, 0xEF, 0xFF, 0x6E,
-0xFF, 0xBF, 0xFF, 0xFC, 0xFF, 0xDF, 0xFF, 0x84, 0xFF, 0x91, 0xFF,
-0x25, 0x01, 0xE4, 0x04, 0x19, 0x0A, 0xC2, 0x0E, 0xAA, 0x10, 0xDA,
-0x0E, 0x3E, 0x0A, 0x05, 0x05, 0x38, 0x01, 0x96, 0xFF, 0x81, 0xFF,
-0xDD, 0xFF, 0x00, 0x00, 0xFD, 0xFF, 0xC1, 0xFF, 0x6E, 0xFF, 0xE6,
-0xFF, 0x3A, 0x02, 0xA6, 0x06, 0xEF, 0x0B, 0xD6, 0x0F, 0x71, 0x10,
-0x71, 0x0D, 0x57, 0x08, 0x71, 0x03, 0x67, 0x00, 0x70, 0xFF, 0xA2,
-0xFF, 0xF3, 0xFF, 0xF1, 0xFF, 0x9F, 0xFF, 0x72, 0xFF, 0x78, 0x00,
-0x95, 0x03, 0x86, 0x08, 0x98, 0x0D, 0x7C, 0x10, 0xC0, 0x0F, 0xC3,
-0x0B, 0x79, 0x06, 0x1C, 0x02, 0xDB, 0xFF, 0x70, 0xFF, 0xC5, 0xFF,
-0xFE, 0xFF, 0x00, 0x00, 0xDB, 0xFF, 0x7F, 0xFF, 0x9C, 0xFF, 0x50,
-0x01, 0x2F, 0x05, 0x6C, 0x0A, 0xF9, 0x0E, 0xA9, 0x10, 0xA2, 0x0E,
-0xEA, 0x09, 0xBB, 0x04, 0x0F, 0x01, 0x8C, 0xFF, 0x87, 0xFF, 0xE2,
-0xFF, 0xFC, 0xFF, 0xBC, 0xFF, 0x6D, 0xFF, 0xFA, 0xFF, 0x71, 0x02,
-0xF7, 0x06, 0x3C, 0x0C, 0xFB, 0x0F, 0x5B, 0x10, 0x2B, 0x0D, 0x03,
-0x08, 0x31, 0x03, 0x4A, 0x00, 0x6E, 0xFF, 0xA8, 0xFF, 0xF5, 0xFF,
-0xEE, 0xFF, 0x99, 0xFF, 0x76, 0xFF, 0x98, 0x00, 0xD8, 0x03, 0xDB,
-0x08, 0xDB, 0x0D, 0x8D, 0x10, 0x96, 0x0F, 0x73, 0x0B, 0x29, 0x06,
-0xE8, 0x01, 0xC9, 0xFF, 0x72, 0xFF, 0xCA, 0xFF, 0xFE, 0xFF, 0x00,
-0x00, 0xD6, 0xFF, 0x7A, 0xFF, 0xA8, 0xFF, 0x7D, 0x01, 0x7B, 0x05,
-0xBF, 0x0A, 0x2D, 0x0F, 0xA5, 0x10, 0x67, 0x0E, 0x96, 0x09, 0x73,
-0x04, 0xE7, 0x00, 0x84, 0xFF, 0x8C, 0xFF, 0xE6, 0xFF, 0xFA, 0xFF,
-0xB6, 0xFF, 0x6C, 0xFF, 0x11, 0x00, 0xAA, 0x02, 0x4A, 0x07, 0x88,
-0x0C, 0x1C, 0x10, 0x41, 0x10, 0xE3, 0x0C, 0xAF, 0x07, 0xF3, 0x02,
-0x2F, 0x00, 0x6C, 0xFF, 0xAE, 0xFF, 0xF7, 0xFF, 0xEA, 0xFF, 0x93,
-0xFF, 0x7B, 0xFF, 0xBB, 0x00, 0x1C, 0x04, 0x2F, 0x09, 0x1B, 0x0E,
-0x9A, 0x10, 0x68, 0x0F, 0x23, 0x0B, 0xDA, 0x05, 0xB7, 0x01, 0xB9,
-0xFF, 0x76, 0xFF, 0xD0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xD1, 0xFF,
-0x76, 0xFF, 0xB6, 0xFF, 0xAC, 0x01, 0xC8, 0x05, 0x11, 0x0B, 0x5E,
-0x0F, 0x9C, 0x10, 0x29, 0x0E, 0x42, 0x09, 0x2C, 0x04, 0xC2, 0x00,
-0x7D, 0xFF, 0x92, 0xFF, 0xEA, 0xFF, 0xF8, 0xFF, 0xB0, 0xFF, 0x6C,
-0xFF, 0x29, 0x00, 0xE6, 0x02, 0x9D, 0x07, 0xD3, 0x0C, 0x3B, 0x10,
-0x23, 0x10, 0x99, 0x0C, 0x5C, 0x07, 0xB7, 0x02, 0x16, 0x00, 0x6C,
-0xFF, 0xB4, 0xFF, 0xF9, 0xFF, 0xE7, 0xFF, 0x8D, 0xFF, 0x82, 0xFF,
-0xDF, 0x00, 0x63, 0x04, 0x84, 0x09, 0x59, 0x0E, 0xA3, 0x10, 0x38,
-0x0F, 0xD1, 0x0A, 0x8C, 0x05, 0x87, 0x01, 0xAB, 0xFF, 0x79, 0xFF,
-0xD5, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0xCB, 0xFF, 0x73, 0xFF, 0xC6,
-0xFF, 0xDD, 0x01, 0x17, 0x06, 0x62, 0x0B, 0x8C, 0x0F, 0x90, 0x10,
-0xE9, 0x0D, 0xED, 0x08, 0xE7, 0x03, 0xA0, 0x00, 0x77, 0xFF, 0x97,
-0xFF, 0xED, 0xFF, 0xF6, 0xFF, 0xA9, 0xFF, 0x6D, 0xFF, 0x44, 0x00,
-0x23, 0x03, 0xF1, 0x07, 0x1B, 0x0D, 0x55, 0x10, 0x02, 0x10, 0x4D,
-0x0C, 0x0A, 0x07, 0x7E, 0x02, 0xFF, 0xFF, 0x6D, 0xFF, 0xBA, 0xFF,
-0xFB, 0xFF, 0xE3, 0xFF, 0x88, 0xFF, 0x8A, 0xFF, 0x06, 0x01, 0xAB,
-0x04, 0xD8, 0x09, 0x95, 0x0E, 0xA9, 0x10, 0x05, 0x0F, 0x7F, 0x0A,
-0x40, 0x05, 0x5A, 0x01, 0x9F, 0xFF, 0x7E, 0xFF, 0xDA, 0xFF, 0x00,
-0x00, 0xFE, 0xFF, 0xC6, 0xFF, 0x70, 0xFF, 0xD7, 0xFF, 0x10, 0x02,
-0x67, 0x06, 0xB1, 0x0B, 0xB7, 0x0F, 0x80, 0x10, 0xA7, 0x0D, 0x99,
-0x08, 0xA4, 0x03, 0x7F, 0x00, 0x73, 0xFF, 0x9D, 0xFF, 0xF0, 0xFF,
-0xF3, 0xFF, 0xA3, 0xFF, 0x70, 0xFF, 0x60, 0x00, 0x62, 0x03, 0x45,
-0x08, 0x62, 0x0D, 0x6C, 0x10, 0xDE, 0x0F, 0x00, 0x0C, 0xB8, 0x06,
-0x46, 0x02, 0xEA, 0xFF, 0x6E, 0xFF, 0xC0, 0xFF, 0xFD, 0xFF, 0x00,
-0x00, 0xDE, 0xFF, 0x83, 0xFF, 0x94, 0xFF, 0x2F, 0x01, 0xF4, 0x04,
-0x2B, 0x0A, 0xCE, 0x0E, 0xAA, 0x10, 0xCE, 0x0E, 0x2B, 0x0A, 0xF4,
-0x04, 0x2F, 0x01, 0x94, 0xFF, 0x83, 0xFF, 0xDE, 0xFF, 0xFD, 0xFF,
-0xC0, 0xFF, 0x6E, 0xFF, 0xEA, 0xFF, 0x46, 0x02, 0xB8, 0x06, 0x00,
-0x0C, 0xDE, 0x0F, 0x6C, 0x10, 0x62, 0x0D, 0x45, 0x08, 0x62, 0x03,
-0x60, 0x00, 0x70, 0xFF, 0xA3, 0xFF, 0xF3, 0xFF, 0xF0, 0xFF, 0x9D,
-0xFF, 0x73, 0xFF, 0x7F, 0x00, 0xA4, 0x03, 0x99, 0x08, 0xA7, 0x0D,
-0x80, 0x10, 0xB7, 0x0F, 0xB1, 0x0B, 0x67, 0x06, 0x10, 0x02, 0xD7,
-0xFF, 0x70, 0xFF, 0xC6, 0xFF, 0xFE, 0xFF, 0x00, 0x00, 0xDA, 0xFF,
-0x7E, 0xFF, 0x9F, 0xFF, 0x5A, 0x01, 0x40, 0x05, 0x7F, 0x0A, 0x05,
-0x0F, 0xA9, 0x10, 0x95, 0x0E, 0xD8, 0x09, 0xAB, 0x04, 0x06, 0x01,
-0x8A, 0xFF, 0x88, 0xFF, 0xE3, 0xFF, 0xFB, 0xFF, 0xBA, 0xFF, 0x6D,
-0xFF, 0xFF, 0xFF, 0x7E, 0x02, 0x0A, 0x07, 0x4D, 0x0C, 0x02, 0x10,
-0x55, 0x10, 0x1B, 0x0D, 0xF1, 0x07, 0x23, 0x03, 0x44, 0x00, 0x6D,
-0xFF, 0xA9, 0xFF, 0xF6, 0xFF, 0xED, 0xFF, 0x97, 0xFF, 0x77, 0xFF,
-0xA0, 0x00, 0xE7, 0x03, 0xED, 0x08, 0xE9, 0x0D, 0x90, 0x10, 0x8C,
-0x0F, 0x62, 0x0B, 0x17, 0x06, 0xDD, 0x01, 0xC6, 0xFF, 0x73, 0xFF,
-0xCB, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0xD5, 0xFF, 0x79, 0xFF, 0xAB,
-0xFF, 0x87, 0x01, 0x8C, 0x05, 0xD1, 0x0A, 0x38, 0x0F, 0xA3, 0x10,
-0x59, 0x0E, 0x84, 0x09, 0x63, 0x04, 0xDF, 0x00, 0x82, 0xFF, 0x8D,
-0xFF, 0xE7, 0xFF, 0xF9, 0xFF, 0xB4, 0xFF, 0x6C, 0xFF, 0x16, 0x00,
-0xB7, 0x02, 0x5C, 0x07, 0x99, 0x0C, 0x23, 0x10, 0x3B, 0x10, 0xD3,
-0x0C, 0x9D, 0x07, 0xE6, 0x02, 0x29, 0x00, 0x6C, 0xFF, 0xB0, 0xFF,
-0xF8, 0xFF, 0xEA, 0xFF, 0x92, 0xFF, 0x7D, 0xFF, 0xC2, 0x00, 0x2C,
-0x04, 0x42, 0x09, 0x29, 0x0E, 0x9C, 0x10, 0x5E, 0x0F, 0x11, 0x0B,
-0xC8, 0x05, 0xAC, 0x01, 0xB6, 0xFF, 0x76, 0xFF, 0xD1, 0xFF, 0xFF,
-0xFF, 0xFF, 0xFF, 0xD0, 0xFF, 0x76, 0xFF, 0xB9, 0xFF, 0xB7, 0x01,
-0xDA, 0x05, 0x23, 0x0B, 0x68, 0x0F, 0x9A, 0x10, 0x1B, 0x0E, 0x2F,
-0x09, 0x1C, 0x04, 0xBB, 0x00, 0x7B, 0xFF, 0x93, 0xFF, 0xEA, 0xFF,
-0xF7, 0xFF, 0xAE, 0xFF, 0x6C, 0xFF, 0x2F, 0x00, 0xF3, 0x02, 0xAF,
-0x07, 0xE3, 0x0C, 0x41, 0x10, 0x1C, 0x10, 0x88, 0x0C, 0x4A, 0x07,
-0xAA, 0x02, 0x11, 0x00, 0x6C, 0xFF, 0xB6, 0xFF, 0xFA, 0xFF, 0xE6,
-0xFF, 0x8C, 0xFF, 0x84, 0xFF, 0xE7, 0x00, 0x73, 0x04, 0x96, 0x09,
-0x67, 0x0E, 0xA5, 0x10, 0x2D, 0x0F, 0xBF, 0x0A, 0x7B, 0x05, 0x7D,
-0x01, 0xA8, 0xFF, 0x7A, 0xFF, 0xD6, 0xFF, 0x00, 0x00, 0xFE, 0xFF,
-0xCA, 0xFF, 0x72, 0xFF, 0xC9, 0xFF, 0xE8, 0x01, 0x29, 0x06, 0x73,
-0x0B, 0x96, 0x0F, 0x8D, 0x10, 0xDB, 0x0D, 0xDB, 0x08, 0xD8, 0x03,
-0x98, 0x00, 0x76, 0xFF, 0x99, 0xFF, 0xEE, 0xFF, 0xF5, 0xFF, 0xA8,
-0xFF, 0x6E, 0xFF, 0x4A, 0x00, 0x31, 0x03, 0x03, 0x08, 0x2B, 0x0D,
-0x5B, 0x10, 0xFB, 0x0F, 0x3C, 0x0C, 0xF7, 0x06, 0x71, 0x02, 0xFA,
-0xFF, 0x6D, 0xFF, 0xBC, 0xFF, 0xFC, 0xFF, 0xE2, 0xFF, 0x87, 0xFF,
-0x8C, 0xFF, 0x0F, 0x01, 0xBB, 0x04, 0xEA, 0x09, 0xA2, 0x0E, 0xA9,
-0x10, 0xF9, 0x0E, 0x6C, 0x0A, 0x2F, 0x05, 0x50, 0x01, 0x9C, 0xFF,
-0x7F, 0xFF, 0xDB, 0xFF, 0x00, 0x00, 0xFE, 0xFF, 0xC5, 0xFF, 0x70,
-0xFF, 0xDB, 0xFF, 0x1C, 0x02, 0x79, 0x06, 0xC3, 0x0B, 0xC0, 0x0F,
-0x7C, 0x10, 0x98, 0x0D, 0x86, 0x08, 0x95, 0x03, 0x78, 0x00, 0x72,
-0xFF, 0x9F, 0xFF, 0xF1, 0xFF, 0xF3, 0xFF, 0xA2, 0xFF, 0x70, 0xFF,
-0x67, 0x00, 0x71, 0x03, 0x57, 0x08, 0x71, 0x0D, 0x71, 0x10, 0xD6,
-0x0F, 0xEF, 0x0B, 0xA6, 0x06, 0x3A, 0x02, 0xE6, 0xFF, 0x6E, 0xFF,
-0xC1, 0xFF, 0xFD, 0xFF, 0x00, 0x00, 0xDD, 0xFF, 0x81, 0xFF, 0x96,
-0xFF, 0x38, 0x01, 0x05, 0x05, 0x3E, 0x0A, 0xDA, 0x0E, 0xAA, 0x10,
-0xC2, 0x0E, 0x19, 0x0A, 0xE4, 0x04, 0x25, 0x01, 0x91, 0xFF, 0x84,
-0xFF, 0xDF, 0xFF, 0xFC, 0xFF, 0xBF, 0xFF, 0x6E, 0xFF, 0xEF, 0xFF,
-0x52, 0x02, 0xCA, 0x06, 0x11, 0x0C, 0xE6, 0x0F, 0x68, 0x10, 0x52,
-0x0D, 0x32, 0x08, 0x54, 0x03, 0x5A, 0x00, 0x6F, 0xFF, 0xA5, 0xFF,
-0xF4, 0xFF, 0xF0, 0xFF, 0x9C, 0xFF, 0x74, 0xFF, 0x86, 0x00, 0xB3,
-0x03, 0xAC, 0x08, 0xB6, 0x0D, 0x84, 0x10, 0xAD, 0x0F, 0xA0, 0x0B,
-0x55, 0x06, 0x05, 0x02, 0xD3, 0xFF, 0x71, 0xFF, 0xC7, 0xFF, 0xFE,
-0xFF, 0x00, 0x00, 0xD9, 0xFF, 0x7D, 0xFF, 0xA1, 0xFF, 0x64, 0x01,
-0x50, 0x05, 0x91, 0x0A, 0x10, 0x0F, 0xA8, 0x10, 0x88, 0x0E, 0xC5,
-0x09, 0x9B, 0x04, 0xFD, 0x00, 0x88, 0xFF, 0x89, 0xFF, 0xE4, 0xFF,
-0xFB, 0xFF, 0xB9, 0xFF, 0x6C, 0xFF, 0x04, 0x00, 0x8A, 0x02, 0x1C,
-0x07, 0x5E, 0x0C, 0x0A, 0x10, 0x50, 0x10, 0x0B, 0x0D, 0xDE, 0x07,
-0x15, 0x03, 0x3E, 0x00, 0x6D, 0xFF, 0xAB, 0xFF, 0xF6, 0xFF, 0xEC,
-0xFF, 0x96, 0xFF, 0x78, 0xFF, 0xA7, 0x00, 0xF6, 0x03, 0x00, 0x09,
-0xF8, 0x0D, 0x93, 0x10, 0x82, 0x0F, 0x50, 0x0B, 0x06, 0x06, 0xD2,
-0x01, 0xC2, 0xFF, 0x74, 0xFF, 0xCD, 0xFF, 0xFF, 0xFF, 0x00, 0x00,
-0xD4, 0xFF, 0x79, 0xFF, 0xAE, 0xFF, 0x91, 0x01, 0x9D, 0x05, 0xE3,
-0x0A, 0x43, 0x0F, 0xA1, 0x10, 0x4C, 0x0E, 0x71, 0x09, 0x53, 0x04,
-0xD7, 0x00, 0x80, 0xFF, 0x8E, 0xFF, 0xE8, 0xFF, 0xF9, 0xFF, 0xB3,
-0xFF, 0x6C, 0xFF, 0x1C, 0x00, 0xC4, 0x02, 0x6F, 0x07, 0xAA, 0x0C,
-0x2A, 0x10, 0x34, 0x10, 0xC2, 0x0C, 0x8A, 0x07, 0xD8, 0x02, 0x24,
-0x00, 0x6C, 0xFF, 0xB1, 0xFF, 0xF8, 0xFF, 0xE9, 0xFF, 0x90, 0xFF,
-0x7E, 0xFF, 0xCB, 0x00, 0x3B, 0x04, 0x55, 0x09, 0x37, 0x0E, 0x9E,
-0x10, 0x53, 0x0F, 0xFF, 0x0A, 0xB7, 0x05, 0xA1, 0x01, 0xB3, 0xFF,
-0x77, 0xFF, 0xD2, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xCE, 0xFF, 0x75,
-0xFF, 0xBD, 0xFF, 0xC1, 0x01, 0xEB, 0x05, 0x35, 0x0B, 0x73, 0x0F,
-0x97, 0x10, 0x0D, 0x0E, 0x1C, 0x09, 0x0D, 0x04, 0xB3, 0x00, 0x7A,
-0xFF, 0x94, 0xFF, 0xEB, 0xFF, 0xF7, 0xFF, 0xAD, 0xFF, 0x6D, 0xFF,
-0x35, 0x00, 0x01, 0x03, 0xC2, 0x07, 0xF3, 0x0C, 0x47, 0x10, 0x15,
-0x10, 0x78, 0x0C, 0x37, 0x07, 0x9D, 0x02, 0x0C, 0x00, 0x6C, 0xFF,
-0xB7, 0xFF, 0xFA, 0xFF, 0xE5, 0xFF, 0x8B, 0xFF, 0x85, 0xFF, 0xF0,
-0x00, 0x83, 0x04, 0xA9, 0x09, 0x74, 0x0E, 0xA6, 0x10, 0x21, 0x0F,
-0xAD, 0x0A, 0x6A, 0x05, 0x73, 0x01, 0xA5, 0xFF, 0x7B, 0xFF, 0xD7,
-0xFF, 0x00, 0x00, 0xFE, 0xFF, 0xC9, 0xFF, 0x72, 0xFF, 0xCD, 0xFF,
-0xF4, 0x01, 0x3B, 0x06, 0x85, 0x0B, 0x9F, 0x0F, 0x89, 0x10, 0xCC,
-0x0D, 0xC8, 0x08, 0xC9, 0x03, 0x91, 0x00, 0x75, 0xFF, 0x9A, 0xFF,
-0xEF, 0xFF, 0xF5, 0xFF, 0xA7, 0xFF, 0x6E, 0xFF, 0x50, 0x00, 0x3F,
-0x03, 0x16, 0x08, 0x3B, 0x0D, 0x60, 0x10, 0xF3, 0x0F, 0x2B, 0x0C,
-0xE5, 0x06, 0x65, 0x02, 0xF6, 0xFF, 0x6D, 0xFF, 0xBD, 0xFF, 0xFC,
-0xFF, 0xE1, 0xFF, 0x85, 0xFF, 0x8E, 0xFF, 0x18, 0x01, 0xCB, 0x04,
-0xFD, 0x09, 0xAF, 0x0E, 0xAA, 0x10, 0xED, 0x0E, 0x5A, 0x0A, 0x1E,
-0x05, 0x46, 0x01, 0x9A, 0xFF, 0x80, 0xFF, 0xDC, 0xFF, 0x00, 0x00,
-0xFD, 0xFF, 0xC3, 0xFF, 0x6F, 0xFF, 0xDF, 0xFF, 0x28, 0x02, 0x8B,
-0x06, 0xD5, 0x0B, 0xC9, 0x0F, 0x78, 0x10, 0x88, 0x0D, 0x73, 0x08,
-0x86, 0x03, 0x71, 0x00, 0x71, 0xFF, 0xA0, 0xFF, 0xF2, 0xFF, 0xF2,
-0xFF, 0xA1, 0xFF, 0x71, 0xFF, 0x6E, 0x00, 0x7F, 0x03, 0x6A, 0x08,
-0x81, 0x0D, 0x76, 0x10, 0xCD, 0x0F, 0xDD, 0x0B, 0x94, 0x06, 0x2E,
-0x02, 0xE1, 0xFF, 0x6F, 0xFF, 0xC3, 0xFF, 0xFD, 0xFF, 0x00, 0x00,
-0xDC, 0xFF, 0x80, 0xFF, 0x98, 0xFF, 0x42, 0x01, 0x16, 0x05, 0x50,
-0x0A, 0xE7, 0x0E, 0xAA, 0x10, 0xB5, 0x0E, 0x06, 0x0A, 0xD3, 0x04,
-0x1C, 0x01, 0x8F, 0xFF, 0x85, 0xFF, 0xE0, 0xFF, 0xFC, 0xFF, 0xBE,
-0xFF, 0x6D, 0xFF, 0xF3, 0xFF, 0x5E, 0x02, 0xDC, 0x06, 0x23, 0x0C,
-0xEF, 0x0F, 0x63, 0x10, 0x43, 0x0D, 0x1F, 0x08, 0x46, 0x03, 0x53,
-0x00, 0x6E, 0xFF, 0xA6, 0xFF, 0xF4, 0xFF, 0xEF, 0xFF, 0x9B, 0xFF,
-0x75, 0xFF, 0x8D, 0x00, 0xC1, 0x03, 0xBE, 0x08, 0xC4, 0x0D, 0x88,
-0x10, 0xA4, 0x0F, 0x8E, 0x0B, 0x43, 0x06, 0xF9, 0x01, 0xCF, 0xFF,
-0x71, 0xFF, 0xC8, 0xFF, 0xFE, 0xFF, 0x00, 0x00, 0xD8, 0xFF, 0x7C,
-0xFF, 0xA4, 0xFF, 0x6E, 0x01, 0x61, 0x05, 0xA3, 0x0A, 0x1C, 0x0F,
-0xA7, 0x10, 0x7B, 0x0E, 0xB2, 0x09, 0x8B, 0x04, 0xF4, 0x00, 0x86,
-0xFF, 0x8A, 0xFF, 0xE4, 0xFF, 0xFA, 0xFF, 0xB8, 0xFF, 0x6C, 0xFF,
-0x09, 0x00, 0x97, 0x02, 0x2E, 0x07, 0x6F, 0x0C, 0x11, 0x10, 0x4A,
-0x10, 0xFB, 0x0C, 0xCB, 0x07, 0x07, 0x03, 0x38, 0x00, 0x6D, 0xFF,
-0xAC, 0xFF, 0xF7, 0xFF, 0xEC, 0xFF, 0x95, 0xFF, 0x79, 0xFF, 0xAF,
-0x00, 0x05, 0x04, 0x13, 0x09, 0x06, 0x0E, 0x96, 0x10, 0x78, 0x0F,
-0x3E, 0x0B, 0xF4, 0x05, 0xC7, 0x01, 0xBF, 0xFF, 0x74, 0xFF, 0xCE,
-0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xD2, 0xFF, 0x78, 0xFF, 0xB1, 0xFF,
-0x9C, 0x01, 0xAE, 0x05, 0xF6, 0x0A, 0x4E, 0x0F, 0x9F, 0x10, 0x3E,
-0x0E, 0x5E, 0x09, 0x43, 0x04, 0xCF, 0x00, 0x7F, 0xFF, 0x90, 0xFF,
-0xE8, 0xFF, 0xF9, 0xFF, 0xB2, 0xFF, 0x6C, 0xFF, 0x21, 0x00, 0xD2,
-0x02, 0x81, 0x07, 0xBA, 0x0C, 0x31, 0x10, 0x2E, 0x10, 0xB2, 0x0C,
-0x78, 0x07, 0xCB, 0x02, 0x1E, 0x00, 0x6C, 0xFF, 0xB2, 0xFF, 0xF9,
-0xFF, 0xE8, 0xFF, 0x8F, 0xFF, 0x80, 0xFF, 0xD3, 0x00, 0x4B, 0x04,
-0x67, 0x09, 0x45, 0x0E, 0xA0, 0x10, 0x48, 0x0F, 0xEC, 0x0A, 0xA6,
-0x05, 0x97, 0x01, 0xB0, 0xFF, 0x78, 0xFF, 0xD3, 0xFF, 0x00, 0x00,
-0xFF, 0xFF, 0xCD, 0xFF, 0x74, 0xFF, 0xC0, 0xFF, 0xCC, 0x01, 0xFD,
-0x05, 0x47, 0x0B, 0x7D, 0x0F, 0x94, 0x10, 0xFF, 0x0D, 0x0A, 0x09,
-0xFE, 0x03, 0xAB, 0x00, 0x79, 0xFF, 0x95, 0xFF, 0xEC, 0xFF, 0xF7,
-0xFF, 0xAC, 0xFF, 0x6D, 0xFF, 0x3B, 0x00, 0x0E, 0x03, 0xD5, 0x07,
-0x03, 0x0D, 0x4D, 0x10, 0x0E, 0x10, 0x67, 0x0C, 0x25, 0x07, 0x91,
-0x02, 0x07, 0x00, 0x6C, 0xFF, 0xB8, 0xFF, 0xFB, 0xFF, 0xE4, 0xFF,
-0x89, 0xFF, 0x87, 0xFF, 0xF9, 0x00, 0x93, 0x04, 0xBC, 0x09, 0x82,
-0x0E, 0xA7, 0x10, 0x16, 0x0F, 0x9A, 0x0A, 0x59, 0x05, 0x69, 0x01,
-0xA3, 0xFF, 0x7C, 0xFF, 0xD8, 0xFF, 0x00, 0x00, 0xFE, 0xFF, 0xC8,
-0xFF, 0x71, 0xFF, 0xD1, 0xFF, 0xFF, 0x01, 0x4C, 0x06, 0x97, 0x0B,
-0xA9, 0x0F, 0x86, 0x10, 0xBD, 0x0D, 0xB5, 0x08, 0xBA, 0x03, 0x8A,
-0x00, 0x74, 0xFF, 0x9B, 0xFF, 0xEF, 0xFF, 0xF4, 0xFF, 0xA5, 0xFF,
-0x6F, 0xFF, 0x57, 0x00, 0x4D, 0x03, 0x29, 0x08, 0x4B, 0x0D, 0x65,
-0x10, 0xEB, 0x0F, 0x1A, 0x0C, 0xD3, 0x06, 0x58, 0x02, 0xF1, 0xFF,
-0x6D, 0xFF, 0xBE, 0xFF, 0xFC, 0xFF, 0xE0, 0xFF, 0x84, 0xFF, 0x90,
-0xFF, 0x21, 0x01, 0xDC, 0x04, 0x10, 0x0A, 0xBB, 0x0E, 0xAA, 0x10,
-0xE1, 0x0E, 0x47, 0x0A, 0x0D, 0x05, 0x3D, 0x01, 0x97, 0xFF, 0x81,
-0xFF, 0xDD, 0xFF, 0x00, 0x00, 0xFD, 0xFF, 0xC2, 0xFF, 0x6F, 0xFF,
-0xE4, 0xFF, 0x34, 0x02, 0x9D, 0x06, 0xE6, 0x0B, 0xD1, 0x0F, 0x73,
-0x10, 0x79, 0x0D, 0x61, 0x08, 0x78, 0x03, 0x6A, 0x00, 0x70, 0xFF,
-0xA1, 0xFF, 0xF2, 0xFF, 0xF1, 0xFF, 0x9F, 0xFF, 0x72, 0xFF, 0x74,
-0x00, 0x8E, 0x03, 0x7D, 0x08, 0x90, 0x0D, 0x7A, 0x10, 0xC4, 0x0F,
-0xCC, 0x0B, 0x82, 0x06, 0x22, 0x02, 0xDD, 0xFF, 0x6F, 0xFF, 0xC4,
-0xFF, 0xFD, 0xFF, 0x00, 0x00, 0xDB, 0xFF, 0x7F, 0xFF, 0x9B, 0xFF,
-0x4B, 0x01, 0x26, 0x05, 0x63, 0x0A, 0xF3, 0x0E, 0xAA, 0x10, 0xA8,
-0x0E, 0xF4, 0x09, 0xC3, 0x04, 0x13, 0x01, 0x8D, 0xFF, 0x86, 0xFF,
-0xE1, 0xFF, 0xFC, 0xFF, 0xBC, 0xFF, 0x6D, 0xFF, 0xF8, 0xFF, 0x6B,
-0x02, 0xEE, 0x06, 0x34, 0x0C, 0xF7, 0x0F, 0x5D, 0x10, 0x33, 0x0D,
-0x0D, 0x08, 0x38, 0x03, 0x4D, 0x00, 0x6E, 0xFF, 0xA7, 0xFF, 0xF5,
-0xFF, 0xEE, 0xFF, 0x99, 0xFF, 0x76, 0xFF, 0x94, 0x00, 0xD0, 0x03,
-0xD1, 0x08, 0xD3, 0x0D, 0x8B, 0x10, 0x9A, 0x0F, 0x7C, 0x0B, 0x32,
-0x06, 0xEE, 0x01, 0xCB, 0xFF, 0x72, 0xFF, 0xCA, 0xFF, 0xFE, 0xFF,
-0x00, 0x00, 0xD6, 0xFF, 0x7B, 0xFF, 0xA7, 0xFF, 0x78, 0x01, 0x72,
-0x05, 0xB6, 0x0A, 0x27, 0x0F, 0xA5, 0x10, 0x6E, 0x0E, 0xA0, 0x09,
-0x7B, 0x04, 0xEC, 0x00, 0x85, 0xFF, 0x8B, 0xFF, 0xE5, 0xFF, 0xFA,
-0xFF, 0xB6, 0xFF, 0x6C, 0xFF, 0x0E, 0x00, 0xA4, 0x02, 0x41, 0x07,
-0x80, 0x0C, 0x19, 0x10, 0x44, 0x10, 0xEB, 0x0C, 0xB9, 0x07, 0xFA,
-0x02, 0x32, 0x00, 0x6D, 0xFF, 0xAE, 0xFF, 0xF7, 0xFF, 0xEB, 0xFF,
-0x93, 0xFF, 0x7B, 0xFF, 0xB7, 0x00, 0x15, 0x04, 0x26, 0x09, 0x14,
-0x0E, 0x98, 0x10, 0x6D, 0x0F, 0x2C, 0x0B, 0xE3, 0x05, 0xBC, 0x01,
-0xBB, 0xFF, 0x75, 0xFF, 0xCF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xD1,
-0xFF, 0x77, 0xFF, 0xB5, 0xFF, 0xA6, 0x01, 0xC0, 0x05, 0x08, 0x0B,
-0x58, 0x0F, 0x9D, 0x10, 0x30, 0x0E, 0x4B, 0x09, 0x34, 0x04, 0xC6,
-0x00, 0x7D, 0xFF, 0x91, 0xFF, 0xE9, 0xFF, 0xF8, 0xFF, 0xB0, 0xFF,
-0x6C, 0xFF, 0x27, 0x00, 0xDF, 0x02, 0x94, 0x07, 0xCA, 0x0C, 0x37,
-0x10, 0x27, 0x10, 0xA1, 0x0C, 0x65, 0x07, 0xBE, 0x02, 0x19, 0x00,
-0x6C, 0xFF, 0xB4, 0xFF, 0xF9, 0xFF, 0xE7, 0xFF, 0x8E, 0xFF, 0x81,
-0xFF, 0xDB, 0x00, 0x5B, 0x04, 0x7A, 0x09, 0x53, 0x0E, 0xA2, 0x10,
-0x3D, 0x0F, 0xDA, 0x0A, 0x95, 0x05, 0x8C, 0x01, 0xAD, 0xFF, 0x79,
-0xFF, 0xD4, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0xCC, 0xFF, 0x73, 0xFF,
-0xC4, 0xFF, 0xD7, 0x01, 0x0E, 0x06, 0x59, 0x0B, 0x87, 0x0F, 0x91,
-0x10, 0xF0, 0x0D, 0xF7, 0x08, 0xEF, 0x03, 0xA3, 0x00, 0x78, 0xFF,
-0x97, 0xFF, 0xED, 0xFF, 0xF6, 0xFF, 0xAA, 0xFF, 0x6D, 0xFF, 0x41,
-0x00, 0x1C, 0x03, 0xE7, 0x07, 0x13, 0x0D, 0x52, 0x10, 0x06, 0x10,
-0x56, 0x0C, 0x13, 0x07, 0x84, 0x02, 0x02, 0x00, 0x6D, 0xFF, 0xBA,
-0xFF, 0xFB, 0xFF, 0xE3, 0xFF, 0x88, 0xFF, 0x89, 0xFF, 0x01, 0x01,
-0xA3, 0x04, 0xCE, 0x09, 0x8F, 0x0E, 0xA8, 0x10, 0x0A, 0x0F, 0x88,
-0x0A, 0x48, 0x05, 0x5F, 0x01, 0xA0, 0xFF, 0x7D, 0xFF, 0xD9, 0xFF,
-0x00, 0x00, 0xFE, 0xFF, 0xC7, 0xFF, 0x70, 0xFF, 0xD5, 0xFF, 0x0B,
-0x02, 0x5E, 0x06, 0xA9, 0x0B, 0xB2, 0x0F, 0x82, 0x10, 0xAE, 0x0D,
-0xA2, 0x08, 0xAB, 0x03, 0x82, 0x00, 0x73, 0xFF, 0x9D, 0xFF, 0xF0,
-0xFF, 0xF3, 0xFF, 0xA4, 0xFF, 0x6F, 0xFF, 0x5D, 0x00, 0x5B, 0x03,
-0x3B, 0x08, 0x5A, 0x0D, 0x6A, 0x10, 0xE2, 0x0F, 0x09, 0x0C, 0xC1,
-0x06, 0x4C, 0x02, 0xEC, 0xFF, 0x6E, 0xFF, 0xC0, 0xFF, 0xFC, 0xFF,
-0xDF, 0xFF, 0x83, 0xFF, 0x93, 0xFF, 0x2A, 0x01, 0xEC, 0x04, 0x22,
-0x0A, 0xC8, 0x0E, 0xAB, 0x10, 0xD4, 0x0E, 0x35, 0x0A, 0xFD, 0x04,
-0x33, 0x01, 0x95, 0xFF, 0x82, 0xFF, 0xDE, 0xFF, 0x00, 0x00, 0xFD,
-0xFF, 0xC1, 0xFF, 0x6E, 0xFF, 0xE8, 0xFF, 0x40, 0x02, 0xAF, 0x06,
-0xF7, 0x0B, 0xDA, 0x0F, 0x6F, 0x10, 0x6A, 0x0D, 0x4E, 0x08, 0x6A,
-0x03, 0x64, 0x00, 0x70, 0xFF, 0xA3, 0xFF, 0xF3, 0xFF, 0xF1, 0xFF,
-0x9E, 0xFF, 0x72, 0xFF, 0x7B, 0x00, 0x9C, 0x03, 0x90, 0x08, 0x9F,
-0x0D, 0x7E, 0x10, 0xBB, 0x0F, 0xBA, 0x0B, 0x70, 0x06, 0x16, 0x02,
-0xD9, 0xFF, 0x70, 0xFF, 0xC5, 0xFF, 0xFE, 0xFF, 0x00, 0x00, 0xDA,
-0xFF, 0x7E, 0xFF, 0x9D, 0xFF, 0x55, 0x01, 0x37, 0x05, 0x75, 0x0A,
-0xFF, 0x0E, 0xA9, 0x10, 0x9C, 0x0E, 0xE1, 0x09, 0xB3, 0x04, 0x0A,
-0x01, 0x8B, 0xFF, 0x87, 0xFF, 0xE2, 0xFF, 0xFB, 0xFF, 0xBB, 0xFF,
-0x6D, 0xFF, 0xFD, 0xFF, 0x77, 0x02, 0x01, 0x07, 0x45, 0x0C, 0xFF,
-0x0F, 0x58, 0x10, 0x23, 0x0D, 0xFA, 0x07, 0x2A, 0x03, 0x47, 0x00,
-0x6E, 0xFF, 0xA9, 0xFF, 0xF5, 0xFF, 0xED, 0xFF, 0x98, 0xFF, 0x77,
-0xFF, 0x9C, 0x00, 0xDF, 0x03, 0xE4, 0x08, 0xE2, 0x0D, 0x8E, 0x10,
-0x91, 0x0F, 0x6B, 0x0B, 0x20, 0x06, 0xE3, 0x01, 0xC8, 0xFF, 0x73,
-0xFF, 0xCB, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0xD5, 0xFF, 0x7A, 0xFF,
-0xAA, 0xFF, 0x82, 0x01, 0x83, 0x05, 0xC8, 0x0A, 0x32, 0x0F, 0xA4,
-0x10, 0x60, 0x0E, 0x8D, 0x09, 0x6B, 0x04, 0xE3, 0x00, 0x83, 0xFF,
-0x8D, 0xFF, 0xE6, 0xFF, 0xFA, 0xFF, 0xB5, 0xFF, 0x6C, 0xFF, 0x14,
-0x00, 0xB1, 0x02, 0x53, 0x07, 0x91, 0x0C, 0x20, 0x10, 0x3E, 0x10,
-0xDB, 0x0C, 0xA6, 0x07, 0xEC, 0x02, 0x2C, 0x00, 0x6C, 0xFF, 0xAF,
-0xFF, 0xF8, 0xFF, 0xEA, 0xFF, 0x92, 0xFF, 0x7C, 0xFF, 0xBE, 0x00,
-0x24, 0x04, 0x38, 0x09, 0x22, 0x0E, 0x9B, 0x10, 0x63, 0x0F, 0x1A,
-0x0B, 0xD1, 0x05, 0xB1, 0x01, 0xB8, 0xFF, 0x76, 0xFF, 0xD0, 0xFF,
-0xFF, 0xFF, 0xFF, 0xFF, 0xD0, 0xFF, 0x76, 0xFF, 0xB8, 0xFF, 0xB1,
-0x01, 0xD1, 0x05, 0x1A, 0x0B, 0x63, 0x0F, 0x9B, 0x10, 0x22, 0x0E,
-0x38, 0x09, 0x24, 0x04, 0xBE, 0x00, 0x7C, 0xFF, 0x92, 0xFF, 0xEA,
-0xFF, 0xF8, 0xFF, 0xAF, 0xFF, 0x6C, 0xFF, 0x2C, 0x00, 0xEC, 0x02,
-0xA6, 0x07, 0xDB, 0x0C, 0x3E, 0x10, 0x20, 0x10, 0x91, 0x0C, 0x53,
-0x07, 0xB1, 0x02, 0x14, 0x00, 0x6C, 0xFF, 0xB5, 0xFF, 0xFA, 0xFF,
-0xE6, 0xFF, 0x8D, 0xFF, 0x83, 0xFF, 0xE3, 0x00, 0x6B, 0x04, 0x8D,
-0x09, 0x60, 0x0E, 0xA4, 0x10, 0x32, 0x0F, 0xC8, 0x0A, 0x83, 0x05,
-0x82, 0x01, 0xAA, 0xFF, 0x7A, 0xFF, 0xD5, 0xFF, 0x00, 0x00, 0xFF,
-0xFF, 0xCB, 0xFF, 0x73, 0xFF, 0xC8, 0xFF, 0xE3, 0x01, 0x20, 0x06,
-0x6B, 0x0B, 0x91, 0x0F, 0x8E, 0x10, 0xE2, 0x0D, 0xE4, 0x08, 0xDF,
-0x03, 0x9C, 0x00, 0x77, 0xFF, 0x98, 0xFF, 0xED, 0xFF, 0xF5, 0xFF,
-0xA9, 0xFF, 0x6E, 0xFF, 0x47, 0x00, 0x2A, 0x03, 0xFA, 0x07, 0x23,
-0x0D, 0x58, 0x10, 0xFF, 0x0F, 0x45, 0x0C, 0x01, 0x07, 0x77, 0x02,
-0xFD, 0xFF, 0x6D, 0xFF, 0xBB, 0xFF, 0xFB, 0xFF, 0xE2, 0xFF, 0x87,
-0xFF, 0x8B, 0xFF, 0x0A, 0x01, 0xB3, 0x04, 0xE1, 0x09, 0x9C, 0x0E,
-0xA9, 0x10, 0xFF, 0x0E, 0x75, 0x0A, 0x37, 0x05, 0x55, 0x01, 0x9D,
-0xFF, 0x7E, 0xFF, 0xDA, 0xFF, 0x00, 0x00, 0xFE, 0xFF, 0xC5, 0xFF,
-0x70, 0xFF, 0xD9, 0xFF, 0x16, 0x02, 0x70, 0x06, 0xBA, 0x0B, 0xBB,
-0x0F, 0x7E, 0x10, 0x9F, 0x0D, 0x90, 0x08, 0x9C, 0x03, 0x7B, 0x00,
-0x72, 0xFF, 0x9E, 0xFF, 0xF1, 0xFF, 0xF3, 0xFF, 0xA3, 0xFF, 0x70,
-0xFF, 0x64, 0x00, 0x6A, 0x03, 0x4E, 0x08, 0x6A, 0x0D, 0x6F, 0x10,
-0xDA, 0x0F, 0xF7, 0x0B, 0xAF, 0x06, 0x40, 0x02, 0xE8, 0xFF, 0x6E,
-0xFF, 0xC1, 0xFF, 0xFD, 0xFF, 0x00, 0x00, 0xDE, 0xFF, 0x82, 0xFF,
-0x95, 0xFF, 0x33, 0x01, 0xFD, 0x04, 0x35, 0x0A, 0xD4, 0x0E, 0xAB,
-0x10, 0xC8, 0x0E, 0x22, 0x0A, 0xEC, 0x04, 0x2A, 0x01, 0x93, 0xFF,
-0x83, 0xFF, 0xDF, 0xFF, 0xFC, 0xFF, 0xC0, 0xFF, 0x6E, 0xFF, 0xEC,
-0xFF, 0x4C, 0x02, 0xC1, 0x06, 0x09, 0x0C, 0xE2, 0x0F, 0x6A, 0x10,
-0x5A, 0x0D, 0x3B, 0x08, 0x5B, 0x03, 0x5D, 0x00, 0x6F, 0xFF, 0xA4,
-0xFF, 0xF3, 0xFF, 0xF0, 0xFF, 0x9D, 0xFF, 0x73, 0xFF, 0x82, 0x00,
-0xAB, 0x03, 0xA2, 0x08, 0xAE, 0x0D, 0x82, 0x10, 0xB2, 0x0F, 0xA9,
-0x0B, 0x5E, 0x06, 0x0B, 0x02, 0xD5, 0xFF, 0x70, 0xFF, 0xC7, 0xFF,
-0xFE, 0xFF, 0x00, 0x00, 0xD9, 0xFF, 0x7D, 0xFF, 0xA0, 0xFF, 0x5F,
-0x01, 0x48, 0x05, 0x88, 0x0A, 0x0A, 0x0F, 0xA8, 0x10, 0x8F, 0x0E,
-0xCE, 0x09, 0xA3, 0x04, 0x01, 0x01, 0x89, 0xFF, 0x88, 0xFF, 0xE3,
-0xFF, 0xFB, 0xFF, 0xBA, 0xFF, 0x6D, 0xFF, 0x02, 0x00, 0x84, 0x02,
-0x13, 0x07, 0x56, 0x0C, 0x06, 0x10, 0x52, 0x10, 0x13, 0x0D, 0xE7,
-0x07, 0x1C, 0x03, 0x41, 0x00, 0x6D, 0xFF, 0xAA, 0xFF, 0xF6, 0xFF,
-0xED, 0xFF, 0x97, 0xFF, 0x78, 0xFF, 0xA3, 0x00, 0xEF, 0x03, 0xF7,
-0x08, 0xF0, 0x0D, 0x91, 0x10, 0x87, 0x0F, 0x59, 0x0B, 0x0E, 0x06,
-0xD7, 0x01, 0xC4, 0xFF, 0x73, 0xFF, 0xCC, 0xFF, 0xFF, 0xFF, 0x00,
-0x00, 0xD4, 0xFF, 0x79, 0xFF, 0xAD, 0xFF, 0x8C, 0x01, 0x95, 0x05,
-0xDA, 0x0A, 0x3D, 0x0F, 0xA2, 0x10, 0x53, 0x0E, 0x7A, 0x09, 0x5B,
-0x04, 0xDB, 0x00, 0x81, 0xFF, 0x8E, 0xFF, 0xE7, 0xFF, 0xF9, 0xFF,
-0xB4, 0xFF, 0x6C, 0xFF, 0x19, 0x00, 0xBE, 0x02, 0x65, 0x07, 0xA1,
-0x0C, 0x27, 0x10, 0x37, 0x10, 0xCA, 0x0C, 0x94, 0x07, 0xDF, 0x02,
-0x27, 0x00, 0x6C, 0xFF, 0xB0, 0xFF, 0xF8, 0xFF, 0xE9, 0xFF, 0x91,
-0xFF, 0x7D, 0xFF, 0xC6, 0x00, 0x34, 0x04, 0x4B, 0x09, 0x30, 0x0E,
-0x9D, 0x10, 0x58, 0x0F, 0x08, 0x0B, 0xC0, 0x05, 0xA6, 0x01, 0xB5,
-0xFF, 0x77, 0xFF, 0xD1, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xCF, 0xFF,
-0x75, 0xFF, 0xBB, 0xFF, 0xBC, 0x01, 0xE3, 0x05, 0x2C, 0x0B, 0x6D,
-0x0F, 0x98, 0x10, 0x14, 0x0E, 0x26, 0x09, 0x15, 0x04, 0xB7, 0x00,
-0x7B, 0xFF, 0x93, 0xFF, 0xEB, 0xFF, 0xF7, 0xFF, 0xAE, 0xFF, 0x6D,
-0xFF, 0x32, 0x00, 0xFA, 0x02, 0xB9, 0x07, 0xEB, 0x0C, 0x44, 0x10,
-0x19, 0x10, 0x80, 0x0C, 0x41, 0x07, 0xA4, 0x02, 0x0E, 0x00, 0x6C,
-0xFF, 0xB6, 0xFF, 0xFA, 0xFF, 0xE5, 0xFF, 0x8B, 0xFF, 0x85, 0xFF,
-0xEC, 0x00, 0x7B, 0x04, 0xA0, 0x09, 0x6E, 0x0E, 0xA5, 0x10, 0x27,
-0x0F, 0xB6, 0x0A, 0x72, 0x05, 0x78, 0x01, 0xA7, 0xFF, 0x7B, 0xFF,
-0xD6, 0xFF, 0x00, 0x00, 0xFE, 0xFF, 0xCA, 0xFF, 0x72, 0xFF, 0xCB,
-0xFF, 0xEE, 0x01, 0x32, 0x06, 0x7C, 0x0B, 0x9A, 0x0F, 0x8B, 0x10,
-0xD3, 0x0D, 0xD1, 0x08, 0xD0, 0x03, 0x94, 0x00, 0x76, 0xFF, 0x99,
-0xFF, 0xEE, 0xFF, 0xF5, 0xFF, 0xA7, 0xFF, 0x6E, 0xFF, 0x4D, 0x00,
-0x38, 0x03, 0x0D, 0x08, 0x33, 0x0D, 0x5D, 0x10, 0xF7, 0x0F, 0x34,
-0x0C, 0xEE, 0x06, 0x6B, 0x02, 0xF8, 0xFF, 0x6D, 0xFF, 0xBC, 0xFF,
-0xFC, 0xFF, 0xE1, 0xFF, 0x86, 0xFF, 0x8D, 0xFF, 0x13, 0x01, 0xC3,
-0x04, 0xF4, 0x09, 0xA8, 0x0E, 0xAA, 0x10, 0xF3, 0x0E, 0x63, 0x0A,
-0x26, 0x05, 0x4B, 0x01, 0x9B, 0xFF, 0x7F, 0xFF, 0xDB, 0xFF, 0x00,
-0x00, 0xFD, 0xFF, 0xC4, 0xFF, 0x6F, 0xFF, 0xDD, 0xFF, 0x22, 0x02,
-0x82, 0x06, 0xCC, 0x0B, 0xC4, 0x0F, 0x7A, 0x10, 0x90, 0x0D, 0x7D,
-0x08, 0x8E, 0x03, 0x74, 0x00, 0x72, 0xFF, 0x9F, 0xFF, 0xF1, 0xFF,
-0xF2, 0xFF, 0xA1, 0xFF, 0x70, 0xFF, 0x6A, 0x00, 0x78, 0x03, 0x61,
-0x08, 0x79, 0x0D, 0x73, 0x10, 0xD1, 0x0F, 0xE6, 0x0B, 0x9D, 0x06,
-0x34, 0x02, 0xE4, 0xFF, 0x6F, 0xFF, 0xC2, 0xFF, 0xFD, 0xFF, 0x00,
-0x00, 0xDD, 0xFF, 0x81, 0xFF, 0x97, 0xFF, 0x3D, 0x01, 0x0D, 0x05,
-0x47, 0x0A, 0xE1, 0x0E, 0xAA, 0x10, 0xBB, 0x0E, 0x10, 0x0A, 0xDC,
-0x04, 0x21, 0x01, 0x90, 0xFF, 0x84, 0xFF, 0xE0, 0xFF, 0xFC, 0xFF,
-0xBE, 0xFF, 0x6D, 0xFF, 0xF1, 0xFF, 0x58, 0x02, 0xD3, 0x06, 0x1A,
-0x0C, 0xEB, 0x0F, 0x65, 0x10, 0x4B, 0x0D, 0x29, 0x08, 0x4D, 0x03,
-0x57, 0x00, 0x6F, 0xFF, 0xA5, 0xFF, 0xF4, 0xFF, 0xEF, 0xFF, 0x9B,
-0xFF, 0x74, 0xFF, 0x8A, 0x00, 0xBA, 0x03, 0xB5, 0x08, 0xBD, 0x0D,
-0x86, 0x10, 0xA9, 0x0F, 0x97, 0x0B, 0x4C, 0x06, 0xFF, 0x01, 0xD1,
-0xFF, 0x71, 0xFF, 0xC8, 0xFF, 0xFE, 0xFF, 0x00, 0x00, 0xD8, 0xFF,
-0x7C, 0xFF, 0xA3, 0xFF, 0x69, 0x01, 0x59, 0x05, 0x9A, 0x0A, 0x16,
-0x0F, 0xA7, 0x10, 0x82, 0x0E, 0xBC, 0x09, 0x93, 0x04, 0xF9, 0x00,
-0x87, 0xFF, 0x89, 0xFF, 0xE4, 0xFF, 0xFB, 0xFF, 0xB8, 0xFF, 0x6C,
-0xFF, 0x07, 0x00, 0x91, 0x02, 0x25, 0x07, 0x67, 0x0C, 0x0E, 0x10,
-0x4D, 0x10, 0x03, 0x0D, 0xD5, 0x07, 0x0E, 0x03, 0x3B, 0x00, 0x6D,
-0xFF, 0xAC, 0xFF, 0xF7, 0xFF, 0xEC, 0xFF, 0x95, 0xFF, 0x79, 0xFF,
-0xAB, 0x00, 0xFE, 0x03, 0x0A, 0x09, 0xFF, 0x0D, 0x94, 0x10, 0x7D,
-0x0F, 0x47, 0x0B, 0xFD, 0x05, 0xCC, 0x01, 0xC0, 0xFF, 0x74, 0xFF,
-0xCD, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0xD3, 0xFF, 0x78, 0xFF, 0xB0,
-0xFF, 0x97, 0x01, 0xA6, 0x05, 0xEC, 0x0A, 0x48, 0x0F, 0xA0, 0x10,
-0x45, 0x0E, 0x67, 0x09, 0x4B, 0x04, 0xD3, 0x00, 0x80, 0xFF, 0x8F,
-0xFF, 0xE8, 0xFF, 0xF9, 0xFF, 0xB2, 0xFF, 0x6C, 0xFF, 0x1E, 0x00,
-0xCB, 0x02, 0x78, 0x07, 0xB2, 0x0C, 0x2E, 0x10, 0x31, 0x10, 0xBA,
-0x0C, 0x81, 0x07, 0xD2, 0x02, 0x21, 0x00, 0x6C, 0xFF, 0xB2, 0xFF,
-0xF9, 0xFF, 0xE8, 0xFF, 0x90, 0xFF, 0x7F, 0xFF, 0xCF, 0x00, 0x43,
-0x04, 0x5E, 0x09, 0x3E, 0x0E, 0x9F, 0x10, 0x4E, 0x0F, 0xF6, 0x0A,
-0xAE, 0x05, 0x9C, 0x01, 0xB1, 0xFF, 0x78, 0xFF, 0xD2, 0xFF, 0xFF,
-0xFF, 0xFF, 0xFF, 0xCE, 0xFF, 0x74, 0xFF, 0xBF, 0xFF, 0xC7, 0x01,
-0xF4, 0x05, 0x3E, 0x0B, 0x78, 0x0F, 0x96, 0x10, 0x06, 0x0E, 0x13,
-0x09, 0x05, 0x04, 0xAF, 0x00, 0x79, 0xFF, 0x95, 0xFF, 0xEC, 0xFF,
-0xF7, 0xFF, 0xAC, 0xFF, 0x6D, 0xFF, 0x38, 0x00, 0x07, 0x03, 0xCB,
-0x07, 0xFB, 0x0C, 0x4A, 0x10, 0x11, 0x10, 0x6F, 0x0C, 0x2E, 0x07,
-0x97, 0x02, 0x09, 0x00, 0x6C, 0xFF, 0xB8, 0xFF, 0xFA, 0xFF, 0xE4,
-0xFF, 0x8A, 0xFF, 0x86, 0xFF, 0xF4, 0x00, 0x8B, 0x04, 0xB2, 0x09,
-0x7B, 0x0E, 0xA7, 0x10, 0x1C, 0x0F, 0xA3, 0x0A, 0x61, 0x05, 0x6E,
-0x01, 0xA4, 0xFF, 0x7C, 0xFF, 0xD8, 0xFF, 0x00, 0x00, 0xFE, 0xFF,
-0xC8, 0xFF, 0x71, 0xFF, 0xCF, 0xFF, 0xF9, 0x01, 0x43, 0x06, 0x8E,
-0x0B, 0xA4, 0x0F, 0x88, 0x10, 0xC4, 0x0D, 0xBE, 0x08, 0xC1, 0x03,
-0x8D, 0x00, 0x75, 0xFF, 0x9B, 0xFF, 0xEF, 0xFF, 0xF4, 0xFF, 0xA6,
-0xFF, 0x6E, 0xFF, 0x53, 0x00, 0x46, 0x03, 0x1F, 0x08, 0x43, 0x0D,
-0x63, 0x10, 0xEF, 0x0F, 0x23, 0x0C, 0xDC, 0x06, 0x5E, 0x02, 0xF3,
-0xFF, 0x6D, 0xFF, 0xBE, 0xFF, 0xFC, 0xFF, 0xE0, 0xFF, 0x85, 0xFF,
-0x8F, 0xFF, 0x1C, 0x01, 0xD3, 0x04, 0x06, 0x0A, 0xB5, 0x0E, 0xAA,
-0x10, 0xE7, 0x0E, 0x50, 0x0A, 0x16, 0x05, 0x42, 0x01, 0x98, 0xFF,
-0x80, 0xFF, 0xDC, 0xFF, 0x00, 0x00, 0xFD, 0xFF, 0xC3, 0xFF, 0x6F,
-0xFF, 0xE1, 0xFF, 0x2E, 0x02, 0x94, 0x06, 0xDD, 0x0B, 0xCD, 0x0F,
-0x76, 0x10, 0x81, 0x0D, 0x6A, 0x08, 0x7F, 0x03, 0x6E, 0x00, 0x71,
-0xFF, 0xA1, 0xFF, 0xF2, 0xFF, 0x00, 0x00, 0x15, 0x00, 0xD1, 0xFF,
-0x8B, 0xFE, 0xBC, 0xFD, 0xE1, 0x00, 0x84, 0x09, 0xB0, 0x13, 0x47,
-0x18, 0xB0, 0x13, 0x84, 0x09, 0xE1, 0x00, 0xBC, 0xFD, 0x8B, 0xFE,
-0xD1, 0xFF, 0x15, 0x00, 0xFD, 0xFF, 0x13, 0x00, 0xDA, 0x00, 0x30,
-0x00, 0x5D, 0xFC, 0xB3, 0xFC, 0x35, 0x0A, 0xC2, 0x1C, 0x24, 0x20,
-0x48, 0x10, 0x5D, 0xFF, 0x74, 0xFB, 0x3A, 0xFF, 0xFB, 0x00, 0x42,
-0x00, 0xF8, 0xFF, 0xFA, 0xFF, 0x2C, 0x00, 0xF3, 0x00, 0xAD, 0xFF,
-0xC5, 0xFB, 0x11, 0xFE, 0xAF, 0x0D, 0xEF, 0x1E, 0x68, 0x1E, 0xBC,
-0x0C, 0xA7, 0xFD, 0xEA, 0xFB, 0xD3, 0xFF, 0xEE, 0x00, 0x24, 0x00,
-0xFA, 0xFF, 0xF7, 0xFF, 0x4C, 0x00, 0xFB, 0x00, 0x0C, 0xFF, 0x5F,
-0xFB, 0xE8, 0xFF, 0x3D, 0x11, 0x7E, 0x20, 0x13, 0x1C, 0x4C, 0x09,
-0x6A, 0xFC, 0x8C, 0xFC, 0x4E, 0x00, 0xD1, 0x00, 0x0E, 0x00, 0xFD,
-0xFF, 0xF7, 0xFF, 0x72, 0x00, 0xEC, 0x00, 0x55, 0xFE, 0x3D, 0xFB,
-0x37, 0x02, 0xBE, 0x14, 0x5D, 0x21, 0x40, 0x19, 0x18, 0x06, 0xA2,
-0xFB, 0x47, 0xFD, 0xA7, 0x00, 0xAB, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0xFC, 0xFF, 0x9B, 0x00, 0xC0, 0x00, 0x92, 0xFD, 0x73,
-0xFB, 0xF2, 0x04, 0x0E, 0x18, 0x81, 0x21, 0x0C, 0x16, 0x37, 0x03,
-0x47, 0xFB, 0x0B, 0xFE, 0xDF, 0x00, 0x82, 0x00, 0xF9, 0xFF, 0xFE,
-0xFF, 0x08, 0x00, 0xC3, 0x00, 0x74, 0x00, 0xD2, 0xFC, 0x10, 0xFC,
-0x08, 0x08, 0x0A, 0x1B, 0xE9, 0x20, 0x9A, 0x12, 0xBE, 0x00, 0x49,
-0xFB, 0xC8, 0xFE, 0xF9, 0x00, 0x5A, 0x00, 0xF7, 0xFF, 0xFC, 0xFF,
-0x1B, 0x00, 0xE4, 0x00, 0x06, 0x00, 0x24, 0xFC, 0x1E, 0xFD, 0x65,
-0x0B, 0x94, 0x1D, 0x9D, 0x1F, 0x0D, 0x0F, 0xB8, 0xFE, 0x96, 0xFB,
-0x72, 0xFF, 0xF9, 0x00, 0x37, 0x00, 0xF8, 0xFF, 0xF9, 0xFF, 0x36,
-0x00, 0xF8, 0x00, 0x78, 0xFF, 0x9B, 0xFB, 0xA6, 0xFE, 0xE9, 0x0E,
-0x8D, 0x1F, 0xAA, 0x1D, 0x87, 0x0B, 0x2B, 0xFD, 0x1E, 0xFC, 0x02,
-0x00, 0xE5, 0x00, 0x1C, 0x00, 0xFB, 0xFF, 0xF7, 0xFF, 0x58, 0x00,
-0xF9, 0x00, 0xCF, 0xFE, 0x4A, 0xFB, 0xA7, 0x00, 0x77, 0x12, 0xE0,
-0x20, 0x26, 0x1B, 0x28, 0x08, 0x18, 0xFC, 0xCB, 0xFC, 0x71, 0x00,
-0xC5, 0x00, 0x08, 0x00, 0xFE, 0xFF, 0xF8, 0xFF, 0x80, 0x00, 0xE1,
-0x00, 0x13, 0xFE, 0x45, 0xFB, 0x1D, 0x03, 0xEB, 0x15, 0x7F, 0x21,
-0x2D, 0x18, 0x0E, 0x05, 0x77, 0xFB, 0x8B, 0xFD, 0xBE, 0x00, 0x9D,
-0x00, 0xFD, 0xFF, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xA9, 0x00,
-0xAA, 0x00, 0x4F, 0xFD, 0x9D, 0xFB, 0xFA, 0x05, 0x22, 0x19, 0x62,
-0x21, 0xE0, 0x14, 0x50, 0x02, 0x3E, 0xFB, 0x4E, 0xFE, 0xEB, 0x00,
-0x73, 0x00, 0xF7, 0xFF, 0xFE, 0xFF, 0x0D, 0x00, 0xD0, 0x00, 0x52,
-0x00, 0x93, 0xFC, 0x60, 0xFC, 0x2C, 0x09, 0xFA, 0x1B, 0x8A, 0x20,
-0x60, 0x11, 0xFD, 0xFF, 0x5C, 0xFB, 0x06, 0xFF, 0xFB, 0x00, 0x4D,
-0x00, 0xF7, 0xFF, 0xFA, 0xFF, 0x23, 0x00, 0xED, 0x00, 0xD9, 0xFF,
-0xEF, 0xFB, 0x98, 0xFD, 0x99, 0x0C, 0x54, 0x1E, 0x02, 0x1F, 0xD2,
-0x0D, 0x20, 0xFE, 0xC0, 0xFB, 0xA7, 0xFF, 0xF4, 0x00, 0x2D, 0x00,
-0xF9, 0xFF, 0xF8, 0xFF, 0x41, 0x00, 0xFB, 0x00, 0x41, 0xFF, 0x78,
-0xFB, 0x4A, 0xFF, 0x25, 0x10, 0x16, 0x20, 0xDA, 0x1C, 0x56, 0x0A,
-0xBE, 0xFC, 0x56, 0xFC, 0x2C, 0x00, 0xDB, 0x00, 0x14, 0x00, 0xFD,
-0xFF, 0xF7, 0xFF, 0x66, 0x00, 0xF4, 0x00, 0x8F, 0xFE, 0x3F, 0xFB,
-0x75, 0x01, 0xAE, 0x13, 0x2C, 0x21, 0x2A, 0x1A, 0x0D, 0x07, 0xD4,
-0xFB, 0x0C, 0xFD, 0x8F, 0x00, 0xB7, 0x00, 0x03, 0x00, 0xFF, 0xFF,
-0x00, 0x00, 0xFA, 0xFF, 0x8E, 0x00, 0xD1, 0x00, 0xCF, 0xFD, 0x58,
-0xFB, 0x10, 0x04, 0x10, 0x17, 0x8A, 0x21, 0x10, 0x17, 0x10, 0x04,
-0x58, 0xFB, 0xCF, 0xFD, 0xD1, 0x00, 0x8E, 0x00, 0xFA, 0xFF, 0xFF,
-0xFF, 0x03, 0x00, 0xB7, 0x00, 0x8F, 0x00, 0x0C, 0xFD, 0xD4, 0xFB,
-0x0D, 0x07, 0x2A, 0x1A, 0x2C, 0x21, 0xAE, 0x13, 0x75, 0x01, 0x3F,
-0xFB, 0x8F, 0xFE, 0xF4, 0x00, 0x66, 0x00, 0xF7, 0xFF, 0xFD, 0xFF,
-0x14, 0x00, 0xDB, 0x00, 0x2C, 0x00, 0x56, 0xFC, 0xBE, 0xFC, 0x56,
-0x0A, 0xDA, 0x1C, 0x16, 0x20, 0x25, 0x10, 0x4A, 0xFF, 0x78, 0xFB,
-0x41, 0xFF, 0xFB, 0x00, 0x41, 0x00, 0xF8, 0xFF, 0xF9, 0xFF, 0x2D,
-0x00, 0xF4, 0x00, 0xA7, 0xFF, 0xC0, 0xFB, 0x20, 0xFE, 0xD2, 0x0D,
-0x02, 0x1F, 0x54, 0x1E, 0x99, 0x0C, 0x98, 0xFD, 0xEF, 0xFB, 0xD9,
-0xFF, 0xED, 0x00, 0x23, 0x00, 0xFA, 0xFF, 0xF7, 0xFF, 0x4D, 0x00,
-0xFB, 0x00, 0x06, 0xFF, 0x5C, 0xFB, 0xFD, 0xFF, 0x60, 0x11, 0x8A,
-0x20, 0xFA, 0x1B, 0x2C, 0x09, 0x60, 0xFC, 0x93, 0xFC, 0x52, 0x00,
-0xD0, 0x00, 0x0D, 0x00, 0xFE, 0xFF, 0xF7, 0xFF, 0x73, 0x00, 0xEB,
-0x00, 0x4E, 0xFE, 0x3E, 0xFB, 0x50, 0x02, 0xE0, 0x14, 0x62, 0x21,
-0x22, 0x19, 0xFA, 0x05, 0x9D, 0xFB, 0x4F, 0xFD, 0xAA, 0x00, 0xA9,
-0x00, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0xFD, 0xFF, 0x9D, 0x00,
-0xBE, 0x00, 0x8B, 0xFD, 0x77, 0xFB, 0x0E, 0x05, 0x2D, 0x18, 0x7F,
-0x21, 0xEB, 0x15, 0x1D, 0x03, 0x45, 0xFB, 0x13, 0xFE, 0xE1, 0x00,
-0x80, 0x00, 0xF8, 0xFF, 0xFE, 0xFF, 0x08, 0x00, 0xC5, 0x00, 0x71,
-0x00, 0xCB, 0xFC, 0x18, 0xFC, 0x28, 0x08, 0x26, 0x1B, 0xE0, 0x20,
-0x77, 0x12, 0xA7, 0x00, 0x4A, 0xFB, 0xCF, 0xFE, 0xF9, 0x00, 0x58,
-0x00, 0xF7, 0xFF, 0xFB, 0xFF, 0x1C, 0x00, 0xE5, 0x00, 0x02, 0x00,
-0x1E, 0xFC, 0x2B, 0xFD, 0x87, 0x0B, 0xAA, 0x1D, 0x8D, 0x1F, 0xE9,
-0x0E, 0xA6, 0xFE, 0x9B, 0xFB, 0x78, 0xFF, 0xF8, 0x00, 0x36, 0x00,
-0xF9, 0xFF, 0xF8, 0xFF, 0x37, 0x00, 0xF9, 0x00, 0x72, 0xFF, 0x96,
-0xFB, 0xB8, 0xFE, 0x0D, 0x0F, 0x9D, 0x1F, 0x94, 0x1D, 0x65, 0x0B,
-0x1E, 0xFD, 0x24, 0xFC, 0x06, 0x00, 0xE4, 0x00, 0x1B, 0x00, 0xFC,
-0xFF, 0xF7, 0xFF, 0x5A, 0x00, 0xF9, 0x00, 0xC8, 0xFE, 0x49, 0xFB,
-0xBE, 0x00, 0x9A, 0x12, 0xE9, 0x20, 0x0A, 0x1B, 0x08, 0x08, 0x10,
-0xFC, 0xD2, 0xFC, 0x74, 0x00, 0xC3, 0x00, 0x08, 0x00, 0xFE, 0xFF,
-0xF9, 0xFF, 0x82, 0x00, 0xDF, 0x00, 0x0B, 0xFE, 0x47, 0xFB, 0x37,
-0x03, 0x0C, 0x16, 0x81, 0x21, 0x0E, 0x18, 0xF2, 0x04, 0x73, 0xFB,
-0x92, 0xFD, 0xC0, 0x00, 0x9B, 0x00, 0xFC, 0xFF, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0xAB, 0x00, 0xA7, 0x00, 0x47, 0xFD, 0xA2, 0xFB,
-0x18, 0x06, 0x40, 0x19, 0x5D, 0x21, 0xBE, 0x14, 0x37, 0x02, 0x3D,
-0xFB, 0x55, 0xFE, 0xEC, 0x00, 0x72, 0x00, 0xF7, 0xFF, 0xFD, 0xFF,
-0x0E, 0x00, 0xD1, 0x00, 0x4E, 0x00, 0x8C, 0xFC, 0x6A, 0xFC, 0x4C,
-0x09, 0x13, 0x1C, 0x7E, 0x20, 0x3D, 0x11, 0xE8, 0xFF, 0x5F, 0xFB,
-0x0C, 0xFF, 0xFB, 0x00, 0x4C, 0x00, 0xF7, 0xFF, 0xFA, 0xFF, 0x24,
-0x00, 0xEE, 0x00, 0xD3, 0xFF, 0xEA, 0xFB, 0xA7, 0xFD, 0xBC, 0x0C,
-0x68, 0x1E, 0xEF, 0x1E, 0xAF, 0x0D, 0x11, 0xFE, 0xC5, 0xFB, 0xAD,
-0xFF, 0xF3, 0x00, 0x2C, 0x00, 0xFA, 0xFF, 0xF8, 0xFF, 0x42, 0x00,
-0xFB, 0x00, 0x3A, 0xFF, 0x74, 0xFB, 0x5D, 0xFF, 0x48, 0x10, 0x24,
-0x20, 0xC2, 0x1C, 0x35, 0x0A, 0xB3, 0xFC, 0x5D, 0xFC, 0x30, 0x00,
-0xDA, 0x00, 0x13, 0x00, 0xFD, 0xFF, 0xF7, 0xFF, 0x67, 0x00, 0xF3,
-0x00, 0x88, 0xFE, 0x3E, 0xFB, 0x8C, 0x01, 0xD0, 0x13, 0x33, 0x21,
-0x0D, 0x1A, 0xEE, 0x06, 0xCD, 0xFB, 0x13, 0xFD, 0x92, 0x00, 0xB6,
-0x00, 0x03, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0xFA, 0xFF, 0x90, 0x00,
-0xCF, 0x00, 0xC7, 0xFD, 0x5B, 0xFB, 0x2B, 0x04, 0x31, 0x17, 0x8A,
-0x21, 0xF0, 0x16, 0xF4, 0x03, 0x56, 0xFB, 0xD6, 0xFD, 0xD3, 0x00,
-0x8D, 0x00, 0xFA, 0xFF, 0xFF, 0xFF, 0x04, 0x00, 0xB9, 0x00, 0x8C,
-0x00, 0x05, 0xFD, 0xDB, 0xFB, 0x2C, 0x07, 0x47, 0x1A, 0x25, 0x21,
-0x8B, 0x13, 0x5D, 0x01, 0x40, 0xFB, 0x97, 0xFE, 0xF5, 0x00, 0x64,
-0x00, 0xF7, 0xFF, 0xFC, 0xFF, 0x15, 0x00, 0xDC, 0x00, 0x27, 0x00,
-0x50, 0xFC, 0xCA, 0xFC, 0x78, 0x0A, 0xF2, 0x1C, 0x07, 0x20, 0x02,
-0x10, 0x37, 0xFF, 0x7B, 0xFB, 0x47, 0xFF, 0xFB, 0x00, 0x40, 0x00,
-0xF8, 0xFF, 0xF9, 0xFF, 0x2E, 0x00, 0xF5, 0x00, 0xA2, 0xFF, 0xBB,
-0xFB, 0x31, 0xFE, 0xF5, 0x0D, 0x14, 0x1F, 0x3F, 0x1E, 0x77, 0x0C,
-0x8A, 0xFD, 0xF5, 0xFB, 0xDE, 0xFF, 0xEC, 0x00, 0x22, 0x00, 0xFB,
-0xFF, 0xF7, 0xFF, 0x4E, 0x00, 0xFB, 0x00, 0xFF, 0xFE, 0x59, 0xFB,
-0x11, 0x00, 0x83, 0x11, 0x96, 0x20, 0xE0, 0x1B, 0x0B, 0x09, 0x56,
-0xFC, 0x99, 0xFC, 0x56, 0x00, 0xCE, 0x00, 0x0D, 0x00, 0xFE, 0xFF,
-0xF8, 0xFF, 0x75, 0x00, 0xEA, 0x00, 0x47, 0xFE, 0x3E, 0xFB, 0x69,
-0x02, 0x02, 0x15, 0x66, 0x21, 0x04, 0x19, 0xDC, 0x05, 0x98, 0xFB,
-0x56, 0xFD, 0xAD, 0x00, 0xA8, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x00,
-0x00, 0xFD, 0xFF, 0x9E, 0x00, 0xBC, 0x00, 0x83, 0xFD, 0x7B, 0xFB,
-0x2B, 0x05, 0x4C, 0x18, 0x7C, 0x21, 0xCA, 0x15, 0x03, 0x03, 0x44,
-0xFB, 0x1A, 0xFE, 0xE2, 0x00, 0x7E, 0x00, 0xF8, 0xFF, 0xFE, 0xFF,
-0x09, 0x00, 0xC6, 0x00, 0x6D, 0x00, 0xC3, 0xFC, 0x20, 0xFC, 0x49,
-0x08, 0x41, 0x1B, 0xD6, 0x20, 0x54, 0x12, 0x92, 0x00, 0x4C, 0xFB,
-0xD6, 0xFE, 0xFA, 0x00, 0x57, 0x00, 0xF7, 0xFF, 0xFB, 0xFF, 0x1D,
-0x00, 0xE6, 0x00, 0xFD, 0xFF, 0x18, 0xFC, 0x38, 0xFD, 0xA9, 0x0B,
-0xC0, 0x1D, 0x7C, 0x1F, 0xC6, 0x0E, 0x95, 0xFE, 0x9F, 0xFB, 0x7E,
-0xFF, 0xF8, 0x00, 0x35, 0x00, 0xF9, 0xFF, 0xF8, 0xFF, 0x38, 0x00,
-0xF9, 0x00, 0x6C, 0xFF, 0x92, 0xFB, 0xC9, 0xFE, 0x2F, 0x0F, 0xAD,
-0x1F, 0x7D, 0x1D, 0x42, 0x0B, 0x12, 0xFD, 0x2A, 0xFC, 0x0B, 0x00,
-0xE3, 0x00, 0x1A, 0x00, 0xFC, 0xFF, 0xF7, 0xFF, 0x5B, 0x00, 0xF8,
-0x00, 0xC1, 0xFE, 0x47, 0xFB, 0xD4, 0x00, 0xBC, 0x12, 0xF3, 0x20,
-0xEF, 0x1A, 0xE9, 0x07, 0x08, 0xFC, 0xD9, 0xFC, 0x78, 0x00, 0xC2,
-0x00, 0x07, 0x00, 0xFF, 0xFF, 0xF9, 0xFF, 0x83, 0x00, 0xDD, 0x00,
-0x04, 0xFE, 0x49, 0xFB, 0x52, 0x03, 0x2D, 0x16, 0x83, 0x21, 0xEF,
-0x17, 0xD5, 0x04, 0x6F, 0xFB, 0x9A, 0xFD, 0xC3, 0x00, 0x9A, 0x00,
-0xFC, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0xAD, 0x00, 0xA4,
-0x00, 0x40, 0xFD, 0xA8, 0xFB, 0x36, 0x06, 0x5E, 0x19, 0x58, 0x21,
-0x9C, 0x14, 0x1E, 0x02, 0x3D, 0xFB, 0x5D, 0xFE, 0xED, 0x00, 0x70,
-0x00, 0xF7, 0xFF, 0xFD, 0xFF, 0x0F, 0x00, 0xD2, 0x00, 0x4A, 0x00,
-0x85, 0xFC, 0x74, 0xFC, 0x6D, 0x09, 0x2D, 0x1C, 0x72, 0x20, 0x1A,
-0x11, 0xD4, 0xFF, 0x61, 0xFB, 0x13, 0xFF, 0xFC, 0x00, 0x4A, 0x00,
-0xF7, 0xFF, 0xFA, 0xFF, 0x25, 0x00, 0xEF, 0x00, 0xCE, 0xFF, 0xE4,
-0xFB, 0xB5, 0xFD, 0xDE, 0x0C, 0x7C, 0x1E, 0xDD, 0x1E, 0x8C, 0x0D,
-0x01, 0xFE, 0xCA, 0xFB, 0xB3, 0xFF, 0xF3, 0x00, 0x2B, 0x00, 0xFA,
-0xFF, 0xF8, 0xFF, 0x44, 0x00, 0xFB, 0x00, 0x34, 0xFF, 0x71, 0xFB,
-0x71, 0xFF, 0x6B, 0x10, 0x32, 0x20, 0xA9, 0x1C, 0x13, 0x0A, 0xA8,
-0xFC, 0x63, 0xFC, 0x35, 0x00, 0xD9, 0x00, 0x12, 0x00, 0xFD, 0xFF,
-0xF7, 0xFF, 0x69, 0x00, 0xF2, 0x00, 0x81, 0xFE, 0x3E, 0xFB, 0xA4,
-0x01, 0xF2, 0x13, 0x3A, 0x21, 0xF0, 0x19, 0xCF, 0x06, 0xC7, 0xFB,
-0x1B, 0xFD, 0x96, 0x00, 0xB4, 0x00, 0x02, 0x00, 0xFF, 0xFF, 0x00,
-0x00, 0xFB, 0xFF, 0x92, 0x00, 0xCD, 0x00, 0xC0, 0xFD, 0x5E, 0xFB,
-0x47, 0x04, 0x51, 0x17, 0x8A, 0x21, 0xD0, 0x16, 0xD9, 0x03, 0x53,
-0xFB, 0xDE, 0xFD, 0xD5, 0x00, 0x8B, 0x00, 0xFA, 0xFF, 0xFF, 0xFF,
-0x04, 0x00, 0xBA, 0x00, 0x89, 0x00, 0xFD, 0xFC, 0xE2, 0xFB, 0x4B,
-0x07, 0x63, 0x1A, 0x1D, 0x21, 0x69, 0x13, 0x46, 0x01, 0x41, 0xFB,
-0x9E, 0xFE, 0xF5, 0x00, 0x63, 0x00, 0xF7, 0xFF, 0xFC, 0xFF, 0x16,
-0x00, 0xDD, 0x00, 0x23, 0x00, 0x49, 0xFC, 0xD5, 0xFC, 0x99, 0x0A,
-0x09, 0x1D, 0xF9, 0x1F, 0xDF, 0x0F, 0x24, 0xFF, 0x7F, 0xFB, 0x4D,
-0xFF, 0xFB, 0x00, 0x3F, 0x00, 0xF8, 0xFF, 0xF9, 0xFF, 0x2F, 0x00,
-0xF5, 0x00, 0x9C, 0xFF, 0xB6, 0xFB, 0x41, 0xFE, 0x17, 0x0E, 0x26,
-0x1F, 0x2B, 0x1E, 0x54, 0x0C, 0x7C, 0xFD, 0xFA, 0xFB, 0xE3, 0xFF,
-0xEB, 0x00, 0x21, 0x00, 0xFB, 0xFF, 0xF7, 0xFF, 0x50, 0x00, 0xFB,
-0x00, 0xF8, 0xFE, 0x57, 0xFB, 0x26, 0x00, 0xA6, 0x11, 0xA1, 0x20,
-0xC6, 0x1B, 0xEA, 0x08, 0x4D, 0xFC, 0xA0, 0xFC, 0x5A, 0x00, 0xCD,
-0x00, 0x0C, 0x00, 0xFE, 0xFF, 0xF8, 0xFF, 0x77, 0x00, 0xE9, 0x00,
-0x3F, 0xFE, 0x3F, 0xFB, 0x82, 0x02, 0x23, 0x15, 0x6B, 0x21, 0xE5,
-0x18, 0xBE, 0x05, 0x93, 0xFB, 0x5E, 0xFD, 0xAF, 0x00, 0xA6, 0x00,
-0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0xFD, 0xFF, 0xA0, 0x00, 0xB9,
-0x00, 0x7C, 0xFD, 0x80, 0xFB, 0x48, 0x05, 0x6B, 0x18, 0x79, 0x21,
-0xA9, 0x15, 0xE9, 0x02, 0x43, 0xFB, 0x21, 0xFE, 0xE3, 0x00, 0x7D,
-0x00, 0xF8, 0xFF, 0xFE, 0xFF, 0x09, 0x00, 0xC7, 0x00, 0x69, 0x00,
-0xBC, 0xFC, 0x29, 0xFC, 0x69, 0x08, 0x5C, 0x1B, 0xCC, 0x20, 0x32,
-0x12, 0x7C, 0x00, 0x4E, 0xFB, 0xDD, 0xFE, 0xFA, 0x00, 0x56, 0x00,
-0xF7, 0xFF, 0xFB, 0xFF, 0x1D, 0x00, 0xE7, 0x00, 0xF8, 0xFF, 0x12,
-0xFC, 0x45, 0xFD, 0xCB, 0x0B, 0xD6, 0x1D, 0x6C, 0x1F, 0xA3, 0x0E,
-0x84, 0xFE, 0xA4, 0xFB, 0x84, 0xFF, 0xF7, 0x00, 0x34, 0x00, 0xF9,
-0xFF, 0xF8, 0xFF, 0x3A, 0x00, 0xFA, 0x00, 0x66, 0xFF, 0x8E, 0xFB,
-0xDB, 0xFE, 0x53, 0x0F, 0xBD, 0x1F, 0x66, 0x1D, 0x21, 0x0B, 0x05,
-0xFD, 0x30, 0xFC, 0x10, 0x00, 0xE2, 0x00, 0x19, 0x00, 0xFC, 0xFF,
-0xF7, 0xFF, 0x5D, 0x00, 0xF8, 0x00, 0xBA, 0xFE, 0x46, 0xFB, 0xEA,
-0x00, 0xDF, 0x12, 0xFC, 0x20, 0xD3, 0x1A, 0xC9, 0x07, 0x00, 0xFC,
-0xE0, 0xFC, 0x7B, 0x00, 0xC0, 0x00, 0x07, 0x00, 0xFF, 0xFF, 0xF9,
-0xFF, 0x85, 0x00, 0xDC, 0x00, 0xFC, 0xFD, 0x4A, 0xFB, 0x6C, 0x03,
-0x4E, 0x16, 0x85, 0x21, 0xCF, 0x17, 0xB8, 0x04, 0x6C, 0xFB, 0xA2,
-0xFD, 0xC5, 0x00, 0x98, 0x00, 0xFC, 0xFF, 0x00, 0x00, 0xFF, 0xFF,
-0x01, 0x00, 0xAE, 0x00, 0xA1, 0x00, 0x38, 0xFD, 0xAE, 0xFB, 0x54,
-0x06, 0x7C, 0x19, 0x53, 0x21, 0x7B, 0x14, 0x05, 0x02, 0x3D, 0xFB,
-0x64, 0xFE, 0xEE, 0x00, 0x6F, 0x00, 0xF7, 0xFF, 0xFD, 0xFF, 0x0F,
-0x00, 0xD4, 0x00, 0x46, 0x00, 0x7E, 0xFC, 0x7E, 0xFC, 0x8E, 0x09,
-0x46, 0x1C, 0x66, 0x20, 0xF7, 0x10, 0xC0, 0xFF, 0x64, 0xFB, 0x1A,
-0xFF, 0xFC, 0x00, 0x49, 0x00, 0xF7, 0xFF, 0xFA, 0xFF, 0x26, 0x00,
-0xF0, 0x00, 0xC9, 0xFF, 0xDF, 0xFB, 0xC4, 0xFD, 0x01, 0x0D, 0x90,
-0x1E, 0xCA, 0x1E, 0x69, 0x0D, 0xF1, 0xFD, 0xCF, 0xFB, 0xB8, 0xFF,
-0xF2, 0x00, 0x29, 0x00, 0xFA, 0xFF, 0xF7, 0xFF, 0x45, 0x00, 0xFC,
-0x00, 0x2D, 0xFF, 0x6D, 0xFB, 0x84, 0xFF, 0x8E, 0x10, 0x3F, 0x20,
-0x91, 0x1C, 0xF2, 0x09, 0x9D, 0xFC, 0x6A, 0xFC, 0x39, 0x00, 0xD7,
-0x00, 0x12, 0x00, 0xFD, 0xFF, 0xF7, 0xFF, 0x6A, 0x00, 0xF1, 0x00,
-0x7A, 0xFE, 0x3D, 0xFB, 0xBC, 0x01, 0x14, 0x14, 0x41, 0x21, 0xD4,
-0x19, 0xB0, 0x06, 0xC0, 0xFB, 0x22, 0xFD, 0x99, 0x00, 0xB3, 0x00,
-0x02, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0xFB, 0xFF, 0x93, 0x00, 0xCB,
-0x00, 0xB8, 0xFD, 0x61, 0xFB, 0x63, 0x04, 0x71, 0x17, 0x89, 0x21,
-0xB0, 0x16, 0xBD, 0x03, 0x51, 0xFB, 0xE6, 0xFD, 0xD7, 0x00, 0x8A,
-0x00, 0xFA, 0xFF, 0xFF, 0xFF, 0x05, 0x00, 0xBC, 0x00, 0x86, 0x00,
-0xF6, 0xFC, 0xE9, 0xFB, 0x6A, 0x07, 0x80, 0x1A, 0x15, 0x21, 0x47,
-0x13, 0x2F, 0x01, 0x42, 0xFB, 0xA5, 0xFE, 0xF6, 0x00, 0x61, 0x00,
-0xF7, 0xFF, 0xFC, 0xFF, 0x16, 0x00, 0xDF, 0x00, 0x1E, 0x00, 0x43,
-0xFC, 0xE1, 0xFC, 0xBB, 0x0A, 0x21, 0x1D, 0xEA, 0x1F, 0xBC, 0x0F,
-0x12, 0xFF, 0x82, 0xFB, 0x54, 0xFF, 0xFA, 0x00, 0x3D, 0x00, 0xF8,
-0xFF, 0xF9, 0xFF, 0x30, 0x00, 0xF6, 0x00, 0x96, 0xFF, 0xB1, 0xFB,
-0x51, 0xFE, 0x3A, 0x0E, 0x38, 0x1F, 0x16, 0x1E, 0x32, 0x0C, 0x6E,
-0xFD, 0x00, 0xFC, 0xE8, 0xFF, 0xEA, 0x00, 0x20, 0x00, 0xFB, 0xFF,
-0xF7, 0xFF, 0x51, 0x00, 0xFB, 0x00, 0xF1, 0xFE, 0x54, 0xFB, 0x3B,
-0x00, 0xC9, 0x11, 0xAD, 0x20, 0xAC, 0x1B, 0xCA, 0x08, 0x44, 0xFC,
-0xA7, 0xFC, 0x5E, 0x00, 0xCC, 0x00, 0x0B, 0x00, 0xFE, 0xFF, 0xF8,
-0xFF, 0x78, 0x00, 0xE7, 0x00, 0x38, 0xFE, 0x40, 0xFB, 0x9B, 0x02,
-0x45, 0x15, 0x6F, 0x21, 0xC7, 0x18, 0xA1, 0x05, 0x8E, 0xFB, 0x65,
-0xFD, 0xB2, 0x00, 0xA5, 0x00, 0xFE, 0xFF, 0x00, 0x00, 0x00, 0x00,
-0xFE, 0xFF, 0xA2, 0x00, 0xB7, 0x00, 0x74, 0xFD, 0x84, 0xFB, 0x66,
-0x05, 0x8A, 0x18, 0x76, 0x21, 0x87, 0x15, 0xCF, 0x02, 0x41, 0xFB,
-0x29, 0xFE, 0xE5, 0x00, 0x7B, 0x00, 0xF8, 0xFF, 0xFE, 0xFF, 0x0A,
-0x00, 0xC9, 0x00, 0x66, 0x00, 0xB5, 0xFC, 0x32, 0xFC, 0x89, 0x08,
-0x77, 0x1B, 0xC2, 0x20, 0x0F, 0x12, 0x66, 0x00, 0x50, 0xFB, 0xE4,
-0xFE, 0xFA, 0x00, 0x54, 0x00, 0xF7, 0xFF, 0xFB, 0xFF, 0x1E, 0x00,
-0xE8, 0x00, 0xF3, 0xFF, 0x0C, 0xFC, 0x53, 0xFD, 0xED, 0x0B, 0xEB,
-0x1D, 0x5A, 0x1F, 0x80, 0x0E, 0x73, 0xFE, 0xA8, 0xFB, 0x8A, 0xFF,
-0xF7, 0x00, 0x32, 0x00, 0xF9, 0xFF, 0xF8, 0xFF, 0x3B, 0x00, 0xFA,
-0x00, 0x60, 0xFF, 0x8A, 0xFB, 0xED, 0xFE, 0x76, 0x0F, 0xCC, 0x1F,
-0x4F, 0x1D, 0xFF, 0x0A, 0xF9, 0xFC, 0x36, 0xFC, 0x15, 0x00, 0xE1,
-0x00, 0x18, 0x00, 0xFC, 0xFF, 0xF7, 0xFF, 0x5E, 0x00, 0xF7, 0x00,
-0xB3, 0xFE, 0x44, 0xFB, 0x01, 0x01, 0x02, 0x13, 0x04, 0x21, 0xB8,
-0x1A, 0xA9, 0x07, 0xF8, 0xFB, 0xE7, 0xFC, 0x7F, 0x00, 0xBF, 0x00,
-0x06, 0x00, 0xFF, 0xFF, 0xF9, 0xFF, 0x86, 0x00, 0xDA, 0x00, 0xF5,
-0xFD, 0x4C, 0xFB, 0x87, 0x03, 0x6E, 0x16, 0x86, 0x21, 0xB0, 0x17,
-0x9C, 0x04, 0x68, 0xFB, 0xA9, 0xFD, 0xC7, 0x00, 0x96, 0x00, 0xFB,
-0xFF, 0x00, 0x00, 0xFF, 0xFF, 0x01, 0x00, 0xB0, 0x00, 0x9F, 0x00,
-0x31, 0xFD, 0xB4, 0xFB, 0x73, 0x06, 0x99, 0x19, 0x4D, 0x21, 0x59,
-0x14, 0xED, 0x01, 0x3D, 0xFB, 0x6B, 0xFE, 0xEF, 0x00, 0x6D, 0x00,
-0xF7, 0xFF, 0xFD, 0xFF, 0x10, 0x00, 0xD5, 0x00, 0x42, 0x00, 0x77,
-0xFC, 0x88, 0xFC, 0xAF, 0x09, 0x5F, 0x1C, 0x59, 0x20, 0xD4, 0x10,
-0xAC, 0xFF, 0x67, 0xFB, 0x20, 0xFF, 0xFC, 0x00, 0x48, 0x00, 0xF7,
-0xFF, 0xFA, 0xFF, 0x27, 0x00, 0xF0, 0x00, 0xC3, 0xFF, 0xD9, 0xFB,
-0xD3, 0xFD, 0x24, 0x0D, 0xA3, 0x1E, 0xB7, 0x1E, 0x46, 0x0D, 0xE2,
-0xFD, 0xD4, 0xFB, 0xBE, 0xFF, 0xF1, 0x00, 0x28, 0x00, 0xFA, 0xFF,
-0xF7, 0xFF, 0x46, 0x00, 0xFC, 0x00, 0x27, 0xFF, 0x6A, 0xFB, 0x98,
-0xFF, 0xB1, 0x10, 0x4C, 0x20, 0x78, 0x1C, 0xD1, 0x09, 0x93, 0xFC,
-0x71, 0xFC, 0x3D, 0x00, 0xD6, 0x00, 0x11, 0x00, 0xFD, 0xFF, 0xF7,
-0xFF, 0x6C, 0x00, 0xF0, 0x00, 0x72, 0xFE, 0x3D, 0xFB, 0xD4, 0x01,
-0x36, 0x14, 0x47, 0x21, 0xB6, 0x19, 0x91, 0x06, 0xBA, 0xFB, 0x29,
-0xFD, 0x9C, 0x00, 0xB1, 0x00, 0x02, 0x00, 0xFF, 0xFF, 0x00, 0x00,
-0xFB, 0xFF, 0x95, 0x00, 0xC9, 0x00, 0xB1, 0xFD, 0x65, 0xFB, 0x80,
-0x04, 0x90, 0x17, 0x88, 0x21, 0x8F, 0x16, 0xA2, 0x03, 0x4E, 0xFB,
-0xED, 0xFD, 0xD9, 0x00, 0x88, 0x00, 0xF9, 0xFF, 0xFF, 0xFF, 0x05,
-0x00, 0xBD, 0x00, 0x82, 0x00, 0xEF, 0xFC, 0xF0, 0xFB, 0x8A, 0x07,
-0x9C, 0x1A, 0x0D, 0x21, 0x24, 0x13, 0x18, 0x01, 0x43, 0xFB, 0xAC,
-0xFE, 0xF7, 0x00, 0x60, 0x00, 0xF7, 0xFF, 0xFC, 0xFF, 0x17, 0x00,
-0xE0, 0x00, 0x1A, 0x00, 0x3D, 0xFC, 0xED, 0xFC, 0xDD, 0x0A, 0x38,
-0x1D, 0xDB, 0x1F, 0x99, 0x0F, 0xFF, 0xFE, 0x86, 0xFB, 0x5A, 0xFF,
-0xFA, 0x00, 0x3C, 0x00, 0xF8, 0xFF, 0xF9, 0xFF, 0x31, 0x00, 0xF6,
-0x00, 0x90, 0xFF, 0xAD, 0xFB, 0x62, 0xFE, 0x5D, 0x0E, 0x49, 0x1F,
-0x01, 0x1E, 0x10, 0x0C, 0x60, 0xFD, 0x06, 0xFC, 0xEE, 0xFF, 0xE9,
-0x00, 0x1F, 0x00, 0xFB, 0xFF, 0xF7, 0xFF, 0x53, 0x00, 0xFB, 0x00,
-0xEB, 0xFE, 0x52, 0xFB, 0x51, 0x00, 0xEC, 0x11, 0xB7, 0x20, 0x91,
-0x1B, 0xA9, 0x08, 0x3B, 0xFC, 0xAE, 0xFC, 0x62, 0x00, 0xCA, 0x00,
-0x0B, 0x00, 0xFE, 0xFF, 0xF8, 0xFF, 0x7A, 0x00, 0xE6, 0x00, 0x30,
-0xFE, 0x40, 0xFB, 0xB5, 0x02, 0x66, 0x15, 0x73, 0x21, 0xA9, 0x18,
-0x83, 0x05, 0x89, 0xFB, 0x6D, 0xFD, 0xB4, 0x00, 0xA3, 0x00, 0xFE,
-0xFF, 0x00, 0x00, 0x00, 0x00, 0xFE, 0xFF, 0xA3, 0x00, 0xB4, 0x00,
-0x6D, 0xFD, 0x89, 0xFB, 0x83, 0x05, 0xA9, 0x18, 0x73, 0x21, 0x66,
-0x15, 0xB5, 0x02, 0x40, 0xFB, 0x30, 0xFE, 0xE6, 0x00, 0x7A, 0x00,
-0xF8, 0xFF, 0xFE, 0xFF, 0x0B, 0x00, 0xCA, 0x00, 0x62, 0x00, 0xAE,
-0xFC, 0x3B, 0xFC, 0xA9, 0x08, 0x91, 0x1B, 0xB7, 0x20, 0xEC, 0x11,
-0x51, 0x00, 0x52, 0xFB, 0xEB, 0xFE, 0xFB, 0x00, 0x53, 0x00, 0xF7,
-0xFF, 0xFB, 0xFF, 0x1F, 0x00, 0xE9, 0x00, 0xEE, 0xFF, 0x06, 0xFC,
-0x60, 0xFD, 0x10, 0x0C, 0x01, 0x1E, 0x49, 0x1F, 0x5D, 0x0E, 0x62,
-0xFE, 0xAD, 0xFB, 0x90, 0xFF, 0xF6, 0x00, 0x31, 0x00, 0xF9, 0xFF,
-0xF8, 0xFF, 0x3C, 0x00, 0xFA, 0x00, 0x5A, 0xFF, 0x86, 0xFB, 0xFF,
-0xFE, 0x99, 0x0F, 0xDB, 0x1F, 0x38, 0x1D, 0xDD, 0x0A, 0xED, 0xFC,
-0x3D, 0xFC, 0x1A, 0x00, 0xE0, 0x00, 0x17, 0x00, 0xFC, 0xFF, 0xF7,
-0xFF, 0x60, 0x00, 0xF7, 0x00, 0xAC, 0xFE, 0x43, 0xFB, 0x18, 0x01,
-0x24, 0x13, 0x0D, 0x21, 0x9C, 0x1A, 0x8A, 0x07, 0xF0, 0xFB, 0xEF,
-0xFC, 0x82, 0x00, 0xBD, 0x00, 0x05, 0x00, 0xFF, 0xFF, 0xF9, 0xFF,
-0x88, 0x00, 0xD9, 0x00, 0xED, 0xFD, 0x4E, 0xFB, 0xA2, 0x03, 0x8F,
-0x16, 0x88, 0x21, 0x90, 0x17, 0x80, 0x04, 0x65, 0xFB, 0xB1, 0xFD,
-0xC9, 0x00, 0x95, 0x00, 0xFB, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0x02,
-0x00, 0xB1, 0x00, 0x9C, 0x00, 0x29, 0xFD, 0xBA, 0xFB, 0x91, 0x06,
-0xB6, 0x19, 0x47, 0x21, 0x36, 0x14, 0xD4, 0x01, 0x3D, 0xFB, 0x72,
-0xFE, 0xF0, 0x00, 0x6C, 0x00, 0xF7, 0xFF, 0xFD, 0xFF, 0x11, 0x00,
-0xD6, 0x00, 0x3D, 0x00, 0x71, 0xFC, 0x93, 0xFC, 0xD1, 0x09, 0x78,
-0x1C, 0x4C, 0x20, 0xB1, 0x10, 0x98, 0xFF, 0x6A, 0xFB, 0x27, 0xFF,
-0xFC, 0x00, 0x46, 0x00, 0xF7, 0xFF, 0xFA, 0xFF, 0x28, 0x00, 0xF1,
-0x00, 0xBE, 0xFF, 0xD4, 0xFB, 0xE2, 0xFD, 0x46, 0x0D, 0xB7, 0x1E,
-0xA3, 0x1E, 0x24, 0x0D, 0xD3, 0xFD, 0xD9, 0xFB, 0xC3, 0xFF, 0xF0,
-0x00, 0x27, 0x00, 0xFA, 0xFF, 0xF7, 0xFF, 0x48, 0x00, 0xFC, 0x00,
-0x20, 0xFF, 0x67, 0xFB, 0xAC, 0xFF, 0xD4, 0x10, 0x59, 0x20, 0x5F,
-0x1C, 0xAF, 0x09, 0x88, 0xFC, 0x77, 0xFC, 0x42, 0x00, 0xD5, 0x00,
-0x10, 0x00, 0xFD, 0xFF, 0xF7, 0xFF, 0x6D, 0x00, 0xEF, 0x00, 0x6B,
-0xFE, 0x3D, 0xFB, 0xED, 0x01, 0x59, 0x14, 0x4D, 0x21, 0x99, 0x19,
-0x73, 0x06, 0xB4, 0xFB, 0x31, 0xFD, 0x9F, 0x00, 0xB0, 0x00, 0x01,
-0x00, 0xFF, 0xFF, 0x00, 0x00, 0xFB, 0xFF, 0x96, 0x00, 0xC7, 0x00,
-0xA9, 0xFD, 0x68, 0xFB, 0x9C, 0x04, 0xB0, 0x17, 0x86, 0x21, 0x6E,
-0x16, 0x87, 0x03, 0x4C, 0xFB, 0xF5, 0xFD, 0xDA, 0x00, 0x86, 0x00,
-0xF9, 0xFF, 0xFF, 0xFF, 0x06, 0x00, 0xBF, 0x00, 0x7F, 0x00, 0xE7,
-0xFC, 0xF8, 0xFB, 0xA9, 0x07, 0xB8, 0x1A, 0x04, 0x21, 0x02, 0x13,
-0x01, 0x01, 0x44, 0xFB, 0xB3, 0xFE, 0xF7, 0x00, 0x5E, 0x00, 0xF7,
-0xFF, 0xFC, 0xFF, 0x18, 0x00, 0xE1, 0x00, 0x15, 0x00, 0x36, 0xFC,
-0xF9, 0xFC, 0xFF, 0x0A, 0x4F, 0x1D, 0xCC, 0x1F, 0x76, 0x0F, 0xED,
-0xFE, 0x8A, 0xFB, 0x60, 0xFF, 0xFA, 0x00, 0x3B, 0x00, 0xF8, 0xFF,
-0xF9, 0xFF, 0x32, 0x00, 0xF7, 0x00, 0x8A, 0xFF, 0xA8, 0xFB, 0x73,
-0xFE, 0x80, 0x0E, 0x5A, 0x1F, 0xEB, 0x1D, 0xED, 0x0B, 0x53, 0xFD,
-0x0C, 0xFC, 0xF3, 0xFF, 0xE8, 0x00, 0x1E, 0x00, 0xFB, 0xFF, 0xF7,
-0xFF, 0x54, 0x00, 0xFA, 0x00, 0xE4, 0xFE, 0x50, 0xFB, 0x66, 0x00,
-0x0F, 0x12, 0xC2, 0x20, 0x77, 0x1B, 0x89, 0x08, 0x32, 0xFC, 0xB5,
-0xFC, 0x66, 0x00, 0xC9, 0x00, 0x0A, 0x00, 0xFE, 0xFF, 0xF8, 0xFF,
-0x7B, 0x00, 0xE5, 0x00, 0x29, 0xFE, 0x41, 0xFB, 0xCF, 0x02, 0x87,
-0x15, 0x76, 0x21, 0x8A, 0x18, 0x66, 0x05, 0x84, 0xFB, 0x74, 0xFD,
-0xB7, 0x00, 0xA2, 0x00, 0xFE, 0xFF, 0x00, 0x00, 0x00, 0x00, 0xFE,
-0xFF, 0xA5, 0x00, 0xB2, 0x00, 0x65, 0xFD, 0x8E, 0xFB, 0xA1, 0x05,
-0xC7, 0x18, 0x6F, 0x21, 0x45, 0x15, 0x9B, 0x02, 0x40, 0xFB, 0x38,
-0xFE, 0xE7, 0x00, 0x78, 0x00, 0xF8, 0xFF, 0xFE, 0xFF, 0x0B, 0x00,
-0xCC, 0x00, 0x5E, 0x00, 0xA7, 0xFC, 0x44, 0xFC, 0xCA, 0x08, 0xAC,
-0x1B, 0xAD, 0x20, 0xC9, 0x11, 0x3B, 0x00, 0x54, 0xFB, 0xF1, 0xFE,
-0xFB, 0x00, 0x51, 0x00, 0xF7, 0xFF, 0xFB, 0xFF, 0x20, 0x00, 0xEA,
-0x00, 0xE8, 0xFF, 0x00, 0xFC, 0x6E, 0xFD, 0x32, 0x0C, 0x16, 0x1E,
-0x38, 0x1F, 0x3A, 0x0E, 0x51, 0xFE, 0xB1, 0xFB, 0x96, 0xFF, 0xF6,
-0x00, 0x30, 0x00, 0xF9, 0xFF, 0xF8, 0xFF, 0x3D, 0x00, 0xFA, 0x00,
-0x54, 0xFF, 0x82, 0xFB, 0x12, 0xFF, 0xBC, 0x0F, 0xEA, 0x1F, 0x21,
-0x1D, 0xBB, 0x0A, 0xE1, 0xFC, 0x43, 0xFC, 0x1E, 0x00, 0xDF, 0x00,
-0x16, 0x00, 0xFC, 0xFF, 0xF7, 0xFF, 0x61, 0x00, 0xF6, 0x00, 0xA5,
-0xFE, 0x42, 0xFB, 0x2F, 0x01, 0x47, 0x13, 0x15, 0x21, 0x80, 0x1A,
-0x6A, 0x07, 0xE9, 0xFB, 0xF6, 0xFC, 0x86, 0x00, 0xBC, 0x00, 0x05,
-0x00, 0xFF, 0xFF, 0xFA, 0xFF, 0x8A, 0x00, 0xD7, 0x00, 0xE6, 0xFD,
-0x51, 0xFB, 0xBD, 0x03, 0xB0, 0x16, 0x89, 0x21, 0x71, 0x17, 0x63,
-0x04, 0x61, 0xFB, 0xB8, 0xFD, 0xCB, 0x00, 0x93, 0x00, 0xFB, 0xFF,
-0x00, 0x00, 0xFF, 0xFF, 0x02, 0x00, 0xB3, 0x00, 0x99, 0x00, 0x22,
-0xFD, 0xC0, 0xFB, 0xB0, 0x06, 0xD4, 0x19, 0x41, 0x21, 0x14, 0x14,
-0xBC, 0x01, 0x3D, 0xFB, 0x7A, 0xFE, 0xF1, 0x00, 0x6A, 0x00, 0xF7,
-0xFF, 0xFD, 0xFF, 0x12, 0x00, 0xD7, 0x00, 0x39, 0x00, 0x6A, 0xFC,
-0x9D, 0xFC, 0xF2, 0x09, 0x91, 0x1C, 0x3F, 0x20, 0x8E, 0x10, 0x84,
-0xFF, 0x6D, 0xFB, 0x2D, 0xFF, 0xFC, 0x00, 0x45, 0x00, 0xF7, 0xFF,
-0xFA, 0xFF, 0x29, 0x00, 0xF2, 0x00, 0xB8, 0xFF, 0xCF, 0xFB, 0xF1,
-0xFD, 0x69, 0x0D, 0xCA, 0x1E, 0x90, 0x1E, 0x01, 0x0D, 0xC4, 0xFD,
-0xDF, 0xFB, 0xC9, 0xFF, 0xF0, 0x00, 0x26, 0x00, 0xFA, 0xFF, 0xF7,
-0xFF, 0x49, 0x00, 0xFC, 0x00, 0x1A, 0xFF, 0x64, 0xFB, 0xC0, 0xFF,
-0xF7, 0x10, 0x66, 0x20, 0x46, 0x1C, 0x8E, 0x09, 0x7E, 0xFC, 0x7E,
-0xFC, 0x46, 0x00, 0xD4, 0x00, 0x0F, 0x00, 0xFD, 0xFF, 0xF7, 0xFF,
-0x6F, 0x00, 0xEE, 0x00, 0x64, 0xFE, 0x3D, 0xFB, 0x05, 0x02, 0x7B,
-0x14, 0x53, 0x21, 0x7C, 0x19, 0x54, 0x06, 0xAE, 0xFB, 0x38, 0xFD,
-0xA1, 0x00, 0xAE, 0x00, 0x01, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0xFC,
-0xFF, 0x98, 0x00, 0xC5, 0x00, 0xA2, 0xFD, 0x6C, 0xFB, 0xB8, 0x04,
-0xCF, 0x17, 0x85, 0x21, 0x4E, 0x16, 0x6C, 0x03, 0x4A, 0xFB, 0xFC,
-0xFD, 0xDC, 0x00, 0x85, 0x00, 0xF9, 0xFF, 0xFF, 0xFF, 0x07, 0x00,
-0xC0, 0x00, 0x7B, 0x00, 0xE0, 0xFC, 0x00, 0xFC, 0xC9, 0x07, 0xD3,
-0x1A, 0xFC, 0x20, 0xDF, 0x12, 0xEA, 0x00, 0x46, 0xFB, 0xBA, 0xFE,
-0xF8, 0x00, 0x5D, 0x00, 0xF7, 0xFF, 0xFC, 0xFF, 0x19, 0x00, 0xE2,
-0x00, 0x10, 0x00, 0x30, 0xFC, 0x05, 0xFD, 0x21, 0x0B, 0x66, 0x1D,
-0xBD, 0x1F, 0x53, 0x0F, 0xDB, 0xFE, 0x8E, 0xFB, 0x66, 0xFF, 0xFA,
-0x00, 0x3A, 0x00, 0xF8, 0xFF, 0xF9, 0xFF, 0x34, 0x00, 0xF7, 0x00,
-0x84, 0xFF, 0xA4, 0xFB, 0x84, 0xFE, 0xA3, 0x0E, 0x6C, 0x1F, 0xD6,
-0x1D, 0xCB, 0x0B, 0x45, 0xFD, 0x12, 0xFC, 0xF8, 0xFF, 0xE7, 0x00,
-0x1D, 0x00, 0xFB, 0xFF, 0xF7, 0xFF, 0x56, 0x00, 0xFA, 0x00, 0xDD,
-0xFE, 0x4E, 0xFB, 0x7C, 0x00, 0x32, 0x12, 0xCC, 0x20, 0x5C, 0x1B,
-0x69, 0x08, 0x29, 0xFC, 0xBC, 0xFC, 0x69, 0x00, 0xC7, 0x00, 0x09,
-0x00, 0xFE, 0xFF, 0xF8, 0xFF, 0x7D, 0x00, 0xE3, 0x00, 0x21, 0xFE,
-0x43, 0xFB, 0xE9, 0x02, 0xA9, 0x15, 0x79, 0x21, 0x6B, 0x18, 0x48,
-0x05, 0x80, 0xFB, 0x7C, 0xFD, 0xB9, 0x00, 0xA0, 0x00, 0xFD, 0xFF,
-0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xA6, 0x00, 0xAF, 0x00, 0x5E,
-0xFD, 0x93, 0xFB, 0xBE, 0x05, 0xE5, 0x18, 0x6B, 0x21, 0x23, 0x15,
-0x82, 0x02, 0x3F, 0xFB, 0x3F, 0xFE, 0xE9, 0x00, 0x77, 0x00, 0xF8,
-0xFF, 0xFE, 0xFF, 0x0C, 0x00, 0xCD, 0x00, 0x5A, 0x00, 0xA0, 0xFC,
-0x4D, 0xFC, 0xEA, 0x08, 0xC6, 0x1B, 0xA1, 0x20, 0xA6, 0x11, 0x26,
-0x00, 0x57, 0xFB, 0xF8, 0xFE, 0xFB, 0x00, 0x50, 0x00, 0xF7, 0xFF,
-0xFB, 0xFF, 0x21, 0x00, 0xEB, 0x00, 0xE3, 0xFF, 0xFA, 0xFB, 0x7C,
-0xFD, 0x54, 0x0C, 0x2B, 0x1E, 0x26, 0x1F, 0x17, 0x0E, 0x41, 0xFE,
-0xB6, 0xFB, 0x9C, 0xFF, 0xF5, 0x00, 0x2F, 0x00, 0xF9, 0xFF, 0xF8,
-0xFF, 0x3F, 0x00, 0xFB, 0x00, 0x4D, 0xFF, 0x7F, 0xFB, 0x24, 0xFF,
-0xDF, 0x0F, 0xF9, 0x1F, 0x09, 0x1D, 0x99, 0x0A, 0xD5, 0xFC, 0x49,
-0xFC, 0x23, 0x00, 0xDD, 0x00, 0x16, 0x00, 0xFC, 0xFF, 0xF7, 0xFF,
-0x63, 0x00, 0xF5, 0x00, 0x9E, 0xFE, 0x41, 0xFB, 0x46, 0x01, 0x69,
-0x13, 0x1D, 0x21, 0x63, 0x1A, 0x4B, 0x07, 0xE2, 0xFB, 0xFD, 0xFC,
-0x89, 0x00, 0xBA, 0x00, 0x04, 0x00, 0xFF, 0xFF, 0xFA, 0xFF, 0x8B,
-0x00, 0xD5, 0x00, 0xDE, 0xFD, 0x53, 0xFB, 0xD9, 0x03, 0xD0, 0x16,
-0x8A, 0x21, 0x51, 0x17, 0x47, 0x04, 0x5E, 0xFB, 0xC0, 0xFD, 0xCD,
-0x00, 0x92, 0x00, 0xFB, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0x02, 0x00,
-0xB4, 0x00, 0x96, 0x00, 0x1B, 0xFD, 0xC7, 0xFB, 0xCF, 0x06, 0xF0,
-0x19, 0x3A, 0x21, 0xF2, 0x13, 0xA4, 0x01, 0x3E, 0xFB, 0x81, 0xFE,
-0xF2, 0x00, 0x69, 0x00, 0xF7, 0xFF, 0xFD, 0xFF, 0x12, 0x00, 0xD9,
-0x00, 0x35, 0x00, 0x63, 0xFC, 0xA8, 0xFC, 0x13, 0x0A, 0xA9, 0x1C,
-0x32, 0x20, 0x6B, 0x10, 0x71, 0xFF, 0x71, 0xFB, 0x34, 0xFF, 0xFB,
-0x00, 0x44, 0x00, 0xF8, 0xFF, 0xFA, 0xFF, 0x2B, 0x00, 0xF3, 0x00,
-0xB3, 0xFF, 0xCA, 0xFB, 0x01, 0xFE, 0x8C, 0x0D, 0xDD, 0x1E, 0x7C,
-0x1E, 0xDE, 0x0C, 0xB5, 0xFD, 0xE4, 0xFB, 0xCE, 0xFF, 0xEF, 0x00,
-0x25, 0x00, 0xFA, 0xFF, 0xF7, 0xFF, 0x4A, 0x00, 0xFC, 0x00, 0x13,
-0xFF, 0x61, 0xFB, 0xD4, 0xFF, 0x1A, 0x11, 0x72, 0x20, 0x2D, 0x1C,
-0x6D, 0x09, 0x74, 0xFC, 0x85, 0xFC, 0x4A, 0x00, 0xD2, 0x00, 0x0F,
-0x00, 0xFD, 0xFF, 0xF7, 0xFF, 0x70, 0x00, 0xED, 0x00, 0x5D, 0xFE,
-0x3D, 0xFB, 0x1E, 0x02, 0x9C, 0x14, 0x58, 0x21, 0x5E, 0x19, 0x36,
-0x06, 0xA8, 0xFB, 0x40, 0xFD, 0xA4, 0x00, 0xAD, 0x00, 0x00, 0x00,
-0xFF, 0xFF, 0x00, 0x00, 0xFC, 0xFF, 0x9A, 0x00, 0xC3, 0x00, 0x9A,
-0xFD, 0x6F, 0xFB, 0xD5, 0x04, 0xEF, 0x17, 0x83, 0x21, 0x2D, 0x16,
-0x52, 0x03, 0x49, 0xFB, 0x04, 0xFE, 0xDD, 0x00, 0x83, 0x00, 0xF9,
-0xFF, 0xFF, 0xFF, 0x07, 0x00, 0xC2, 0x00, 0x78, 0x00, 0xD9, 0xFC,
-0x08, 0xFC, 0xE9, 0x07, 0xEF, 0x1A, 0xF3, 0x20, 0xBC, 0x12, 0xD4,
-0x00, 0x47, 0xFB, 0xC1, 0xFE, 0xF8, 0x00, 0x5B, 0x00, 0xF7, 0xFF,
-0xFC, 0xFF, 0x1A, 0x00, 0xE3, 0x00, 0x0B, 0x00, 0x2A, 0xFC, 0x12,
-0xFD, 0x42, 0x0B, 0x7D, 0x1D, 0xAD, 0x1F, 0x2F, 0x0F, 0xC9, 0xFE,
-0x92, 0xFB, 0x6C, 0xFF, 0xF9, 0x00, 0x38, 0x00, 0xF8, 0xFF, 0xF9,
-0xFF, 0x35, 0x00, 0xF8, 0x00, 0x7E, 0xFF, 0x9F, 0xFB, 0x95, 0xFE,
-0xC6, 0x0E, 0x7C, 0x1F, 0xC0, 0x1D, 0xA9, 0x0B, 0x38, 0xFD, 0x18,
-0xFC, 0xFD, 0xFF, 0xE6, 0x00, 0x1D, 0x00, 0xFB, 0xFF, 0xF7, 0xFF,
-0x57, 0x00, 0xFA, 0x00, 0xD6, 0xFE, 0x4C, 0xFB, 0x92, 0x00, 0x54,
-0x12, 0xD6, 0x20, 0x41, 0x1B, 0x49, 0x08, 0x20, 0xFC, 0xC3, 0xFC,
-0x6D, 0x00, 0xC6, 0x00, 0x09, 0x00, 0xFE, 0xFF, 0xF8, 0xFF, 0x7E,
-0x00, 0xE2, 0x00, 0x1A, 0xFE, 0x44, 0xFB, 0x03, 0x03, 0xCA, 0x15,
-0x7C, 0x21, 0x4C, 0x18, 0x2B, 0x05, 0x7B, 0xFB, 0x83, 0xFD, 0xBC,
-0x00, 0x9E, 0x00, 0xFD, 0xFF, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF,
-0xA8, 0x00, 0xAD, 0x00, 0x56, 0xFD, 0x98, 0xFB, 0xDC, 0x05, 0x04,
-0x19, 0x66, 0x21, 0x02, 0x15, 0x69, 0x02, 0x3E, 0xFB, 0x47, 0xFE,
-0xEA, 0x00, 0x75, 0x00, 0xF8, 0xFF, 0xFE, 0xFF, 0x0D, 0x00, 0xCE,
-0x00, 0x56, 0x00, 0x99, 0xFC, 0x56, 0xFC, 0x0B, 0x09, 0xE0, 0x1B,
-0x96, 0x20, 0x83, 0x11, 0x11, 0x00, 0x59, 0xFB, 0xFF, 0xFE, 0xFB,
-0x00, 0x4E, 0x00, 0xF7, 0xFF, 0xFB, 0xFF, 0x22, 0x00, 0xEC, 0x00,
-0xDE, 0xFF, 0xF5, 0xFB, 0x8A, 0xFD, 0x77, 0x0C, 0x3F, 0x1E, 0x14,
-0x1F, 0xF5, 0x0D, 0x31, 0xFE, 0xBB, 0xFB, 0xA2, 0xFF, 0xF5, 0x00,
-0x2E, 0x00, 0xF9, 0xFF, 0xF8, 0xFF, 0x40, 0x00, 0xFB, 0x00, 0x47,
-0xFF, 0x7B, 0xFB, 0x37, 0xFF, 0x02, 0x10, 0x07, 0x20, 0xF2, 0x1C,
-0x78, 0x0A, 0xCA, 0xFC, 0x50, 0xFC, 0x27, 0x00, 0xDC, 0x00, 0x15,
-0x00, 0xFC, 0xFF, 0xF7, 0xFF, 0x64, 0x00, 0xF5, 0x00, 0x97, 0xFE,
-0x40, 0xFB, 0x5D, 0x01, 0x8B, 0x13, 0x25, 0x21, 0x47, 0x1A, 0x2C,
-0x07, 0xDB, 0xFB, 0x05, 0xFD, 0x8C, 0x00, 0xB9, 0x00, 0x04, 0x00,
-0xFF, 0xFF, 0xFA, 0xFF, 0x8D, 0x00, 0xD3, 0x00, 0xD6, 0xFD, 0x56,
-0xFB, 0xF4, 0x03, 0xF0, 0x16, 0x8A, 0x21, 0x31, 0x17, 0x2B, 0x04,
-0x5B, 0xFB, 0xC7, 0xFD, 0xCF, 0x00, 0x90, 0x00, 0xFA, 0xFF, 0x00,
-0x00, 0xFF, 0xFF, 0x03, 0x00, 0xB6, 0x00, 0x92, 0x00, 0x13, 0xFD,
-0xCD, 0xFB, 0xEE, 0x06, 0x0D, 0x1A, 0x33, 0x21, 0xD0, 0x13, 0x8C,
-0x01, 0x3E, 0xFB, 0x88, 0xFE, 0xF3, 0x00, 0x67, 0x00, 0xF7, 0xFF,
-0x06, 0x00, 0x1D, 0x00, 0x03, 0xFF, 0xFE, 0x00, 0xA1, 0x02, 0xA6,
-0xF8, 0x56, 0x02, 0xA5, 0x28, 0xA5, 0x28, 0x56, 0x02, 0xA6, 0xF8,
-0xA1, 0x02, 0xFE, 0x00, 0x03, 0xFF, 0x1D, 0x00, 0x06, 0x00, 0x00,
-0x00, 0x21, 0x00, 0xA6, 0xFF, 0x3F, 0xFF, 0x0B, 0x03, 0x42, 0xFE,
-0x3E, 0xF8, 0x7F, 0x15, 0xAC, 0x30, 0x7F, 0x15, 0x3E, 0xF8, 0x42,
-0xFE, 0x0B, 0x03, 0x3F, 0xFF, 0xA6, 0xFF, 0x21, 0x00, 0x00, 0x00,
-0xFA, 0xFF, 0xCE, 0xFF, 0x14, 0x01, 0x00, 0xFD, 0x35, 0x06, 0xD5,
-0xF4, 0xDA, 0x15, 0x92, 0x40, 0xAE, 0xFE, 0xF3, 0xFC, 0x68, 0x03,
-0x86, 0xFD, 0x51, 0x01, 0x8B, 0xFF, 0x11, 0x00, 0x01, 0x00, 0xEC,
-0xFF, 0xF9, 0xFF, 0xC6, 0x00, 0x55, 0xFD, 0x35, 0x06, 0x90, 0xF3,
-0xE5, 0x1C, 0x6B, 0x3D, 0x71, 0xFA, 0x34, 0xFF, 0x46, 0x02, 0xFF,
-0xFD, 0x2D, 0x01, 0x90, 0xFF, 0x10, 0x00, 0x03, 0x00, 0xDB, 0xFF,
-0x2D, 0x00, 0x60, 0x00, 0xE1, 0xFD, 0xCE, 0x05, 0xED, 0xF2, 0xF3,
-0x23, 0x20, 0x39, 0x22, 0xF7, 0x44, 0x01, 0x1F, 0x01, 0x89, 0xFE,
-0xFB, 0x00, 0x9C, 0xFF, 0x0D, 0x00, 0x06, 0x00, 0xC9, 0xFF, 0x68,
-0x00, 0xE5, 0xFF, 0xA0, 0xFE, 0xFB, 0x04, 0x0C, 0xF3, 0xC5, 0x2A,
-0xD8, 0x33, 0xC9, 0xF4, 0x0B, 0x03, 0x05, 0x00, 0x1A, 0xFF, 0xC1,
-0x00, 0xAD, 0xFF, 0x0A, 0x00, 0x09, 0x00, 0xB5, 0xFF, 0xA5, 0x00,
-0x5C, 0xFF, 0x8C, 0xFF, 0xBF, 0x03, 0x06, 0xF4, 0x22, 0x31, 0xC8,
-0x2D, 0x63, 0xF3, 0x76, 0x04, 0x08, 0xFF, 0xA7, 0xFF, 0x84, 0x00,
-0xC0, 0xFF, 0x07, 0x00, 0x0C, 0x00, 0xA4, 0xFF, 0xE1, 0x00, 0xCB,
-0xFE, 0x9B, 0x00, 0x21, 0x02, 0xEE, 0xF5, 0xCD, 0x36, 0x24, 0x27,
-0xE1, 0xF2, 0x7A, 0x05, 0x33, 0xFE, 0x2A, 0x00, 0x47, 0x00, 0xD3,
-0xFF, 0x04, 0x00, 0x0F, 0x00, 0x95, 0xFF, 0x17, 0x01, 0x3D, 0xFE,
-0xBD, 0x01, 0x30, 0x00, 0xCC, 0xF8, 0x92, 0x3B, 0x2A, 0x20, 0x2E,
-0xF3, 0x12, 0x06, 0x8F, 0xFD, 0x9A, 0x00, 0x10, 0x00, 0xE5, 0xFF,
-0x02, 0x00, 0x10, 0x00, 0x8C, 0xFF, 0x42, 0x01, 0xBB, 0xFD, 0xE4,
-0x02, 0x01, 0xFE, 0x9C, 0xFC, 0x45, 0x3F, 0x16, 0x19, 0x2D, 0xF4,
-0x41, 0x06, 0x21, 0xFD, 0xF3, 0x00, 0xE0, 0xFF, 0xF4, 0xFF, 0x01,
-0x00, 0x10, 0x00, 0x8B, 0xFF, 0x5D, 0x01, 0x4F, 0xFD, 0xFB, 0x03,
-0xB2, 0xFB, 0x53, 0x01, 0xC2, 0x41, 0x24, 0x12, 0xBA, 0xF5, 0x0F,
-0x06, 0xE9, 0xFC, 0x33, 0x01, 0xBB, 0xFF, 0x00, 0x00, 0x00, 0x00,
-0x0D, 0x00, 0x93, 0xFF, 0x63, 0x01, 0x04, 0xFD, 0xEF, 0x04, 0x62,
-0xF9, 0xD7, 0x06, 0xF2, 0x42, 0x8D, 0x0B, 0xB0, 0xF7, 0x87, 0x05,
-0xE6, 0xFC, 0x58, 0x01, 0xA0, 0xFF, 0x09, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x07, 0x00, 0xA5, 0xFF, 0x52, 0x01, 0xE2, 0xFC, 0xAD, 0x05,
-0x35, 0xF7, 0x08, 0x0D, 0xCB, 0x42, 0x81, 0x05, 0xE8, 0xF9, 0xBB,
-0x04, 0x12, 0xFD, 0x64, 0x01, 0x90, 0xFF, 0x0E, 0x00, 0x00, 0x00,
-0xFE, 0xFF, 0xC2, 0xFF, 0x27, 0x01, 0xF1, 0xFC, 0x22, 0x06, 0x54,
-0xF5, 0xB8, 0x13, 0x4A, 0x41, 0x29, 0x00, 0x3C, 0xFC, 0xBD, 0x03,
-0x66, 0xFD, 0x58, 0x01, 0x8A, 0xFF, 0x11, 0x00, 0x01, 0x00, 0xF1,
-0xFF, 0xEB, 0xFF, 0xE1, 0x00, 0x35, 0xFD, 0x40, 0x06, 0xE4, 0xF3,
-0xB7, 0x1A, 0x85, 0x3E, 0xA6, 0xFB, 0x86, 0xFE, 0xA0, 0x02, 0xD7,
-0xFD, 0x39, 0x01, 0x8E, 0xFF, 0x10, 0x00, 0x03, 0x00, 0xE1, 0xFF,
-0x1C, 0x00, 0x82, 0x00, 0xB0, 0xFD, 0xF9, 0x05, 0x0C, 0xF3, 0xCB,
-0x21, 0x8F, 0x3A, 0x0D, 0xF8, 0xA9, 0x00, 0x79, 0x01, 0x5D, 0xFE,
-0x0B, 0x01, 0x98, 0xFF, 0x0E, 0x00, 0x05, 0x00, 0xCE, 0xFF, 0x55,
-0x00, 0x0D, 0x00, 0x60, 0xFE, 0x48, 0x05, 0xEC, 0xF2, 0xB6, 0x28,
-0x91, 0x35, 0x68, 0xF5, 0x88, 0x02, 0x5A, 0x00, 0xED, 0xFE, 0xD4,
-0x00, 0xA8, 0xFF, 0x0B, 0x00, 0x08, 0x00, 0xBB, 0xFF, 0x92, 0x00,
-0x87, 0xFF, 0x3F, 0xFF, 0x2B, 0x04, 0xA1, 0xF3, 0x3D, 0x2F, 0xB8,
-0x2F, 0xB8, 0xF3, 0x11, 0x04, 0x52, 0xFF, 0x7C, 0xFF, 0x97, 0x00,
-0xBA, 0xFF, 0x08, 0x00, 0x0B, 0x00, 0xA9, 0xFF, 0xCF, 0x00, 0xF8,
-0xFE, 0x44, 0x00, 0xAA, 0x02, 0x3E, 0xF5, 0x24, 0x35, 0x3B, 0x29,
-0xF2, 0xF2, 0x35, 0x05, 0x70, 0xFE, 0x03, 0x00, 0x5A, 0x00, 0xCD,
-0xFF, 0x05, 0x00, 0x0E, 0x00, 0x99, 0xFF, 0x07, 0x01, 0x68, 0xFE,
-0x63, 0x01, 0xD0, 0x00, 0xD0, 0xF7, 0x35, 0x3A, 0x55, 0x22, 0x02,
-0xF3, 0xEF, 0x05, 0xBC, 0xFD, 0x7A, 0x00, 0x20, 0x00, 0xDF, 0xFF,
-0x03, 0x00, 0x10, 0x00, 0x8E, 0xFF, 0x36, 0x01, 0xE1, 0xFD, 0x8A,
-0x02, 0xB2, 0xFE, 0x56, 0xFB, 0x40, 0x3E, 0x42, 0x1B, 0xCE, 0xF3,
-0x3E, 0x06, 0x3D, 0xFD, 0xDB, 0x00, 0xEE, 0xFF, 0xF0, 0xFF, 0x01,
-0x00, 0x11, 0x00, 0x8A, 0xFF, 0x57, 0x01, 0x6D, 0xFD, 0xA8, 0x03,
-0x69, 0xFC, 0xC8, 0xFF, 0x20, 0x41, 0x40, 0x14, 0x33, 0xF5, 0x28,
-0x06, 0xF5, 0xFC, 0x22, 0x01, 0xC5, 0xFF, 0xFD, 0xFF, 0x00, 0x00,
-0x0F, 0x00, 0x8F, 0xFF, 0x64, 0x01, 0x17, 0xFD, 0xA9, 0x04, 0x16,
-0xFA, 0x10, 0x05, 0xB8, 0x42, 0x87, 0x0D, 0x0D, 0xF7, 0xB9, 0x05,
-0xE2, 0xFC, 0x50, 0x01, 0xA7, 0xFF, 0x07, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x0A, 0x00, 0x9E, 0xFF, 0x5A, 0x01, 0xE8, 0xFC, 0x7A, 0x05,
-0xDA, 0xF7, 0x10, 0x0B, 0xFB, 0x42, 0x4B, 0x07, 0x35, 0xF9, 0x00,
-0x05, 0x00, 0xFD, 0x63, 0x01, 0x94, 0xFF, 0x0D, 0x00, 0x00, 0x00,
-0x01, 0x00, 0xB8, 0xFF, 0x37, 0x01, 0xE7, 0xFC, 0x07, 0x06, 0xDE,
-0xF5, 0x9F, 0x11, 0xE4, 0x41, 0xB8, 0x01, 0x84, 0xFB, 0x0F, 0x04,
-0x48, 0xFD, 0x5E, 0x01, 0x8B, 0xFF, 0x10, 0x00, 0x01, 0x00, 0xF5,
-0xFF, 0xDD, 0xFF, 0xF9, 0x00, 0x1B, 0xFD, 0x41, 0x06, 0x47, 0xF4,
-0x8B, 0x18, 0x81, 0x3F, 0xF1, 0xFC, 0xD5, 0xFD, 0xFA, 0x02, 0xB2,
-0xFD, 0x45, 0x01, 0x8C, 0xFF, 0x11, 0x00, 0x02, 0x00, 0xE6, 0xFF,
-0x0C, 0x00, 0xA2, 0x00, 0x85, 0xFD, 0x1A, 0x06, 0x3C, 0xF3, 0x9F,
-0x1F, 0xE6, 0x3B, 0x0E, 0xF9, 0x07, 0x00, 0xD4, 0x01, 0x33, 0xFE,
-0x1B, 0x01, 0x94, 0xFF, 0x0F, 0x00, 0x04, 0x00, 0xD4, 0xFF, 0x43,
-0x00, 0x33, 0x00, 0x25, 0xFE, 0x89, 0x05, 0xE0, 0xF2, 0x9C, 0x26,
-0x33, 0x37, 0x1E, 0xF6, 0xFD, 0x01, 0xB0, 0x00, 0xC0, 0xFE, 0xE6,
-0x00, 0xA2, 0xFF, 0x0C, 0x00, 0x07, 0x00, 0xC1, 0xFF, 0x7F, 0x00,
-0xB2, 0xFF, 0xF6, 0xFE, 0x8E, 0x04, 0x51, 0xF3, 0x49, 0x2D, 0x98,
-0x31, 0x23, 0xF4, 0xA2, 0x03, 0xA0, 0xFF, 0x51, 0xFF, 0xAA, 0x00,
-0xB4, 0xFF, 0x09, 0x00, 0x0A, 0x00, 0xAE, 0xFF, 0xBD, 0x00, 0x25,
-0xFF, 0xF1, 0xFF, 0x2B, 0x03, 0xA5, 0xF4, 0x68, 0x33, 0x48, 0x2B,
-0x17, 0xF3, 0xE7, 0x04, 0xB1, 0xFE, 0xDB, 0xFF, 0x6C, 0x00, 0xC7,
-0xFF, 0x06, 0x00, 0x0D, 0x00, 0x9E, 0xFF, 0xF7, 0x00, 0x94, 0xFE,
-0x09, 0x01, 0x6A, 0x01, 0xEB, 0xF6, 0xC1, 0x38, 0x7D, 0x24, 0xE8,
-0xF2, 0xC1, 0x05, 0xEE, 0xFD, 0x57, 0x00, 0x31, 0x00, 0xDA, 0xFF,
-0x03, 0x00, 0x10, 0x00, 0x91, 0xFF, 0x29, 0x01, 0x09, 0xFE, 0x2F,
-0x02, 0x5F, 0xFF, 0x27, 0xFA, 0x20, 0x3D, 0x70, 0x1D, 0x7D, 0xF3,
-0x31, 0x06, 0x5E, 0xFD, 0xBF, 0x00, 0xFD, 0xFF, 0xEB, 0xFF, 0x02,
-0x00, 0x11, 0x00, 0x8B, 0xFF, 0x4E, 0x01, 0x8E, 0xFD, 0x52, 0x03,
-0x20, 0xFD, 0x52, 0xFE, 0x60, 0x40, 0x63, 0x16, 0xB7, 0xF4, 0x39,
-0x06, 0x05, 0xFD, 0x0F, 0x01, 0xD1, 0xFF, 0xF9, 0xFF, 0x00, 0x00,
-0x10, 0x00, 0x8D, 0xFF, 0x62, 0x01, 0x2E, 0xFD, 0x5E, 0x04, 0xCC,
-0xFA, 0x5B, 0x03, 0x5E, 0x42, 0x8E, 0x0F, 0x71, 0xF6, 0xE4, 0x05,
-0xE2, 0xFC, 0x45, 0x01, 0xAF, 0xFF, 0x04, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x0B, 0x00, 0x99, 0xFF, 0x60, 0x01, 0xF2, 0xFC, 0x40, 0x05,
-0x85, 0xF8, 0x26, 0x09, 0x0C, 0x43, 0x26, 0x09, 0x85, 0xF8, 0x40,
-0x05, 0xF2, 0xFC, 0x60, 0x01, 0x99, 0xFF, 0x0B, 0x00, 0x00, 0x00,
-0x04, 0x00, 0xAF, 0xFF, 0x45, 0x01, 0xE2, 0xFC, 0xE4, 0x05, 0x71,
-0xF6, 0x8E, 0x0F, 0x5E, 0x42, 0x5B, 0x03, 0xCC, 0xFA, 0x5E, 0x04,
-0x2E, 0xFD, 0x62, 0x01, 0x8D, 0xFF, 0x10, 0x00, 0x00, 0x00, 0xF9,
-0xFF, 0xD1, 0xFF, 0x0F, 0x01, 0x05, 0xFD, 0x39, 0x06, 0xB7, 0xF4,
-0x63, 0x16, 0x60, 0x40, 0x52, 0xFE, 0x20, 0xFD, 0x52, 0x03, 0x8E,
-0xFD, 0x4E, 0x01, 0x8B, 0xFF, 0x11, 0x00, 0x02, 0x00, 0xEB, 0xFF,
-0xFD, 0xFF, 0xBF, 0x00, 0x5E, 0xFD, 0x31, 0x06, 0x7D, 0xF3, 0x70,
-0x1D, 0x20, 0x3D, 0x27, 0xFA, 0x5F, 0xFF, 0x2F, 0x02, 0x09, 0xFE,
-0x29, 0x01, 0x91, 0xFF, 0x10, 0x00, 0x03, 0x00, 0xDA, 0xFF, 0x31,
-0x00, 0x57, 0x00, 0xEE, 0xFD, 0xC1, 0x05, 0xE8, 0xF2, 0x7D, 0x24,
-0xC1, 0x38, 0xEB, 0xF6, 0x6A, 0x01, 0x09, 0x01, 0x94, 0xFE, 0xF7,
-0x00, 0x9E, 0xFF, 0x0D, 0x00, 0x06, 0x00, 0xC7, 0xFF, 0x6C, 0x00,
-0xDB, 0xFF, 0xB1, 0xFE, 0xE7, 0x04, 0x17, 0xF3, 0x48, 0x2B, 0x68,
-0x33, 0xA5, 0xF4, 0x2B, 0x03, 0xF1, 0xFF, 0x25, 0xFF, 0xBD, 0x00,
-0xAE, 0xFF, 0x0A, 0x00, 0x09, 0x00, 0xB4, 0xFF, 0xAA, 0x00, 0x51,
-0xFF, 0xA0, 0xFF, 0xA2, 0x03, 0x23, 0xF4, 0x98, 0x31, 0x49, 0x2D,
-0x51, 0xF3, 0x8E, 0x04, 0xF6, 0xFE, 0xB2, 0xFF, 0x7F, 0x00, 0xC1,
-0xFF, 0x07, 0x00, 0x0C, 0x00, 0xA2, 0xFF, 0xE6, 0x00, 0xC0, 0xFE,
-0xB0, 0x00, 0xFD, 0x01, 0x1E, 0xF6, 0x33, 0x37, 0x9C, 0x26, 0xE0,
-0xF2, 0x89, 0x05, 0x25, 0xFE, 0x33, 0x00, 0x43, 0x00, 0xD4, 0xFF,
-0x04, 0x00, 0x0F, 0x00, 0x94, 0xFF, 0x1B, 0x01, 0x33, 0xFE, 0xD4,
-0x01, 0x07, 0x00, 0x0E, 0xF9, 0xE6, 0x3B, 0x9F, 0x1F, 0x3C, 0xF3,
-0x1A, 0x06, 0x85, 0xFD, 0xA2, 0x00, 0x0C, 0x00, 0xE6, 0xFF, 0x02,
-0x00, 0x11, 0x00, 0x8C, 0xFF, 0x45, 0x01, 0xB2, 0xFD, 0xFA, 0x02,
-0xD5, 0xFD, 0xF1, 0xFC, 0x81, 0x3F, 0x8B, 0x18, 0x47, 0xF4, 0x41,
-0x06, 0x1B, 0xFD, 0xF9, 0x00, 0xDD, 0xFF, 0xF5, 0xFF, 0x01, 0x00,
-0x10, 0x00, 0x8B, 0xFF, 0x5E, 0x01, 0x48, 0xFD, 0x0F, 0x04, 0x84,
-0xFB, 0xB8, 0x01, 0xE4, 0x41, 0x9F, 0x11, 0xDE, 0xF5, 0x07, 0x06,
-0xE7, 0xFC, 0x37, 0x01, 0xB8, 0xFF, 0x01, 0x00, 0x00, 0x00, 0x0D,
-0x00, 0x94, 0xFF, 0x63, 0x01, 0x00, 0xFD, 0x00, 0x05, 0x35, 0xF9,
-0x4B, 0x07, 0xFB, 0x42, 0x10, 0x0B, 0xDA, 0xF7, 0x7A, 0x05, 0xE8,
-0xFC, 0x5A, 0x01, 0x9E, 0xFF, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x07, 0x00, 0xA7, 0xFF, 0x50, 0x01, 0xE2, 0xFC, 0xB9, 0x05, 0x0D,
-0xF7, 0x87, 0x0D, 0xB8, 0x42, 0x10, 0x05, 0x16, 0xFA, 0xA9, 0x04,
-0x17, 0xFD, 0x64, 0x01, 0x8F, 0xFF, 0x0F, 0x00, 0x00, 0x00, 0xFD,
-0xFF, 0xC5, 0xFF, 0x22, 0x01, 0xF5, 0xFC, 0x28, 0x06, 0x33, 0xF5,
-0x40, 0x14, 0x20, 0x41, 0xC8, 0xFF, 0x69, 0xFC, 0xA8, 0x03, 0x6D,
-0xFD, 0x57, 0x01, 0x8A, 0xFF, 0x11, 0x00, 0x01, 0x00, 0xF0, 0xFF,
-0xEE, 0xFF, 0xDB, 0x00, 0x3D, 0xFD, 0x3E, 0x06, 0xCE, 0xF3, 0x42,
-0x1B, 0x40, 0x3E, 0x56, 0xFB, 0xB2, 0xFE, 0x8A, 0x02, 0xE1, 0xFD,
-0x36, 0x01, 0x8E, 0xFF, 0x10, 0x00, 0x03, 0x00, 0xDF, 0xFF, 0x20,
-0x00, 0x7A, 0x00, 0xBC, 0xFD, 0xEF, 0x05, 0x02, 0xF3, 0x55, 0x22,
-0x35, 0x3A, 0xD0, 0xF7, 0xD0, 0x00, 0x63, 0x01, 0x68, 0xFE, 0x07,
-0x01, 0x99, 0xFF, 0x0E, 0x00, 0x05, 0x00, 0xCD, 0xFF, 0x5A, 0x00,
-0x03, 0x00, 0x70, 0xFE, 0x35, 0x05, 0xF2, 0xF2, 0x3B, 0x29, 0x24,
-0x35, 0x3E, 0xF5, 0xAA, 0x02, 0x44, 0x00, 0xF8, 0xFE, 0xCF, 0x00,
-0xA9, 0xFF, 0x0B, 0x00, 0x08, 0x00, 0xBA, 0xFF, 0x97, 0x00, 0x7C,
-0xFF, 0x52, 0xFF, 0x11, 0x04, 0xB8, 0xF3, 0xB8, 0x2F, 0x3D, 0x2F,
-0xA1, 0xF3, 0x2B, 0x04, 0x3F, 0xFF, 0x87, 0xFF, 0x92, 0x00, 0xBB,
-0xFF, 0x08, 0x00, 0x0B, 0x00, 0xA8, 0xFF, 0xD4, 0x00, 0xED, 0xFE,
-0x5A, 0x00, 0x88, 0x02, 0x68, 0xF5, 0x91, 0x35, 0xB6, 0x28, 0xEC,
-0xF2, 0x48, 0x05, 0x60, 0xFE, 0x0D, 0x00, 0x55, 0x00, 0xCE, 0xFF,
-0x05, 0x00, 0x0E, 0x00, 0x98, 0xFF, 0x0B, 0x01, 0x5D, 0xFE, 0x79,
-0x01, 0xA9, 0x00, 0x0D, 0xF8, 0x8F, 0x3A, 0xCB, 0x21, 0x0C, 0xF3,
-0xF9, 0x05, 0xB0, 0xFD, 0x82, 0x00, 0x1C, 0x00, 0xE1, 0xFF, 0x03,
-0x00, 0x10, 0x00, 0x8E, 0xFF, 0x39, 0x01, 0xD7, 0xFD, 0xA0, 0x02,
-0x86, 0xFE, 0xA6, 0xFB, 0x85, 0x3E, 0xB7, 0x1A, 0xE4, 0xF3, 0x40,
-0x06, 0x35, 0xFD, 0xE1, 0x00, 0xEB, 0xFF, 0xF1, 0xFF, 0x01, 0x00,
-0x11, 0x00, 0x8A, 0xFF, 0x58, 0x01, 0x66, 0xFD, 0xBD, 0x03, 0x3C,
-0xFC, 0x29, 0x00, 0x4A, 0x41, 0xB8, 0x13, 0x54, 0xF5, 0x22, 0x06,
-0xF1, 0xFC, 0x27, 0x01, 0xC2, 0xFF, 0xFE, 0xFF, 0x00, 0x00, 0x0E,
-0x00, 0x90, 0xFF, 0x64, 0x01, 0x12, 0xFD, 0xBB, 0x04, 0xE8, 0xF9,
-0x81, 0x05, 0xCB, 0x42, 0x08, 0x0D, 0x35, 0xF7, 0xAD, 0x05, 0xE2,
-0xFC, 0x52, 0x01, 0xA5, 0xFF, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x09, 0x00, 0xA0, 0xFF, 0x58, 0x01, 0xE6, 0xFC, 0x87, 0x05, 0xB0,
-0xF7, 0x8D, 0x0B, 0xF2, 0x42, 0xD7, 0x06, 0x62, 0xF9, 0xEF, 0x04,
-0x04, 0xFD, 0x63, 0x01, 0x93, 0xFF, 0x0D, 0x00, 0x00, 0x00, 0x00,
-0x00, 0xBB, 0xFF, 0x33, 0x01, 0xE9, 0xFC, 0x0F, 0x06, 0xBA, 0xF5,
-0x24, 0x12, 0xC2, 0x41, 0x53, 0x01, 0xB2, 0xFB, 0xFB, 0x03, 0x4F,
-0xFD, 0x5D, 0x01, 0x8B, 0xFF, 0x10, 0x00, 0x01, 0x00, 0xF4, 0xFF,
-0xE0, 0xFF, 0xF3, 0x00, 0x21, 0xFD, 0x41, 0x06, 0x2D, 0xF4, 0x16,
-0x19, 0x45, 0x3F, 0x9C, 0xFC, 0x01, 0xFE, 0xE4, 0x02, 0xBB, 0xFD,
-0x42, 0x01, 0x8C, 0xFF, 0x10, 0x00, 0x02, 0x00, 0xE5, 0xFF, 0x10,
-0x00, 0x9A, 0x00, 0x8F, 0xFD, 0x12, 0x06, 0x2E, 0xF3, 0x2A, 0x20,
-0x92, 0x3B, 0xCC, 0xF8, 0x30, 0x00, 0xBD, 0x01, 0x3D, 0xFE, 0x17,
-0x01, 0x95, 0xFF, 0x0F, 0x00, 0x04, 0x00, 0xD3, 0xFF, 0x47, 0x00,
-0x2A, 0x00, 0x33, 0xFE, 0x7A, 0x05, 0xE1, 0xF2, 0x24, 0x27, 0xCD,
-0x36, 0xEE, 0xF5, 0x21, 0x02, 0x9B, 0x00, 0xCB, 0xFE, 0xE1, 0x00,
-0xA4, 0xFF, 0x0C, 0x00, 0x07, 0x00, 0xC0, 0xFF, 0x84, 0x00, 0xA7,
-0xFF, 0x08, 0xFF, 0x76, 0x04, 0x63, 0xF3, 0xC8, 0x2D, 0x22, 0x31,
-0x06, 0xF4, 0xBF, 0x03, 0x8C, 0xFF, 0x5C, 0xFF, 0xA5, 0x00, 0xB5,
-0xFF, 0x09, 0x00, 0x0A, 0x00, 0xAD, 0xFF, 0xC1, 0x00, 0x1A, 0xFF,
-0x05, 0x00, 0x0B, 0x03, 0xC9, 0xF4, 0xD8, 0x33, 0xC5, 0x2A, 0x0C,
-0xF3, 0xFB, 0x04, 0xA0, 0xFE, 0xE5, 0xFF, 0x68, 0x00, 0xC9, 0xFF,
-0x06, 0x00, 0x0D, 0x00, 0x9C, 0xFF, 0xFB, 0x00, 0x89, 0xFE, 0x1F,
-0x01, 0x44, 0x01, 0x22, 0xF7, 0x20, 0x39, 0xF3, 0x23, 0xED, 0xF2,
-0xCE, 0x05, 0xE1, 0xFD, 0x60, 0x00, 0x2D, 0x00, 0xDB, 0xFF, 0x03,
-0x00, 0x10, 0x00, 0x90, 0xFF, 0x2D, 0x01, 0xFF, 0xFD, 0x46, 0x02,
-0x34, 0xFF, 0x71, 0xFA, 0x6B, 0x3D, 0xE5, 0x1C, 0x90, 0xF3, 0x35,
-0x06, 0x55, 0xFD, 0xC6, 0x00, 0xF9, 0xFF, 0xEC, 0xFF, 0x01, 0x00,
-0x11, 0x00, 0x8B, 0xFF, 0x51, 0x01, 0x86, 0xFD, 0x68, 0x03, 0xF3,
-0xFC, 0xAE, 0xFE, 0x92, 0x40, 0xDA, 0x15, 0xD5, 0xF4, 0x35, 0x06,
-0x00, 0xFD, 0x14, 0x01, 0xCE, 0xFF, 0xFA, 0xFF, 0x00, 0x00, 0x0F,
-0x00, 0x8D, 0xFF, 0x63, 0x01, 0x28, 0xFD, 0x71, 0x04, 0x9E, 0xFA,
-0xC7, 0x03, 0x79, 0x42, 0x0B, 0x0F, 0x97, 0xF6, 0xDA, 0x05, 0xE2,
-0xFC, 0x48, 0x01, 0xAD, 0xFF, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x0B, 0x00, 0x9A, 0xFF, 0x5F, 0x01, 0xEF, 0xFC, 0x4F, 0x05, 0x5A,
-0xF8, 0x9F, 0x09, 0x0A, 0x43, 0xAE, 0x08, 0xB1, 0xF8, 0x30, 0x05,
-0xF5, 0xFC, 0x61, 0x01, 0x97, 0xFF, 0x0C, 0x00, 0x00, 0x00, 0x03,
-0x00, 0xB1, 0xFF, 0x41, 0x01, 0xE3, 0xFC, 0xED, 0x05, 0x4C, 0xF6,
-0x11, 0x10, 0x42, 0x42, 0xF1, 0x02, 0xFA, 0xFA, 0x4B, 0x04, 0x34,
-0xFD, 0x61, 0x01, 0x8C, 0xFF, 0x10, 0x00, 0x01, 0x00, 0xF8, 0xFF,
-0xD4, 0xFF, 0x0A, 0x01, 0x0A, 0xFD, 0x3C, 0x06, 0x9A, 0xF4, 0xED,
-0x16, 0x2A, 0x40, 0xF8, 0xFD, 0x4D, 0xFD, 0x3C, 0x03, 0x97, 0xFD,
-0x4C, 0x01, 0x8B, 0xFF, 0x11, 0x00, 0x02, 0x00, 0xEA, 0xFF, 0x00,
-0x00, 0xB8, 0x00, 0x67, 0xFD, 0x2C, 0x06, 0x6B, 0xF3, 0xFC, 0x1D,
-0xD3, 0x3C, 0xDF, 0xF9, 0x89, 0xFF, 0x18, 0x02, 0x13, 0xFE, 0x26,
-0x01, 0x92, 0xFF, 0x0F, 0x00, 0x04, 0x00, 0xD9, 0xFF, 0x36, 0x00,
-0x4E, 0x00, 0xFB, 0xFD, 0xB4, 0x05, 0xE4, 0xF2, 0x04, 0x25, 0x5F,
-0x38, 0xB6, 0xF6, 0x90, 0x01, 0xF3, 0x00, 0x9F, 0xFE, 0xF3, 0x00,
-0x9F, 0xFF, 0x0D, 0x00, 0x06, 0x00, 0xC6, 0xFF, 0x71, 0x00, 0xD1,
-0xFF, 0xC2, 0xFE, 0xD1, 0x04, 0x23, 0xF3, 0xC9, 0x2B, 0xF5, 0x32,
-0x83, 0xF4, 0x49, 0x03, 0xDC, 0xFF, 0x30, 0xFF, 0xB8, 0x00, 0xB0,
-0xFF, 0x0A, 0x00, 0x09, 0x00, 0xB3, 0xFF, 0xAE, 0x00, 0x46, 0xFF,
-0xB4, 0xFF, 0x85, 0x03, 0x42, 0xF4, 0x0E, 0x32, 0xCA, 0x2C, 0x41,
-0xF3, 0xA5, 0x04, 0xE4, 0xFE, 0xBC, 0xFF, 0x7A, 0x00, 0xC3, 0xFF,
-0x07, 0x00, 0x0D, 0x00, 0xA1, 0xFF, 0xEA, 0x00, 0xB5, 0xFE, 0xC6,
-0x00, 0xD9, 0x01, 0x4F, 0xF6, 0x99, 0x37, 0x16, 0x26, 0xE0, 0xF2,
-0x98, 0x05, 0x16, 0xFE, 0x3C, 0x00, 0x3F, 0x00, 0xD6, 0xFF, 0x04,
-0x00, 0x0F, 0x00, 0x93, 0xFF, 0x1F, 0x01, 0x28, 0xFE, 0xEB, 0x01,
-0xDD, 0xFF, 0x52, 0xF9, 0x36, 0x3C, 0x13, 0x1F, 0x4B, 0xF3, 0x20,
-0x06, 0x7B, 0xFD, 0xA9, 0x00, 0x08, 0x00, 0xE7, 0xFF, 0x02, 0x00,
-0x11, 0x00, 0x8C, 0xFF, 0x47, 0x01, 0xA9, 0xFD, 0x10, 0x03, 0xA8,
-0xFD, 0x47, 0xFD, 0xBB, 0x3F, 0x01, 0x18, 0x62, 0xF4, 0x40, 0x06,
-0x15, 0xFD, 0xFF, 0x00, 0xDA, 0xFF, 0xF6, 0xFF, 0x01, 0x00, 0x10,
-0x00, 0x8B, 0xFF, 0x5F, 0x01, 0x41, 0xFD, 0x23, 0x04, 0x56, 0xFB,
-0x1F, 0x02, 0x06, 0x42, 0x19, 0x11, 0x02, 0xF6, 0xFF, 0x05, 0xE5,
-0xFC, 0x3B, 0x01, 0xB6, 0xFF, 0x02, 0x00, 0x00, 0x00, 0x0D, 0x00,
-0x95, 0xFF, 0x62, 0x01, 0xFC, 0xFC, 0x10, 0x05, 0x09, 0xF9, 0xC1,
-0x07, 0x03, 0x43, 0x94, 0x0A, 0x05, 0xF8, 0x6C, 0x05, 0xEA, 0xFC,
-0x5C, 0x01, 0x9D, 0xFF, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06,
-0x00, 0xA9, 0xFF, 0x4D, 0x01, 0xE1, 0xFC, 0xC4, 0x05, 0xE6, 0xF6,
-0x08, 0x0E, 0xA5, 0x42, 0xA1, 0x04, 0x43, 0xFA, 0x97, 0x04, 0x1D,
-0xFD, 0x64, 0x01, 0x8F, 0xFF, 0x0F, 0x00, 0x00, 0x00, 0xFC, 0xFF,
-0xC8, 0xFF, 0x1E, 0x01, 0xF8, 0xFC, 0x2D, 0x06, 0x13, 0xF5, 0xC8,
-0x14, 0xF2, 0x40, 0x69, 0xFF, 0x97, 0xFC, 0x92, 0x03, 0x75, 0xFD,
-0x55, 0x01, 0x8A, 0xFF, 0x11, 0x00, 0x01, 0x00, 0xEF, 0xFF, 0xF2,
-0xFF, 0xD4, 0x00, 0x45, 0xFD, 0x3B, 0x06, 0xB8, 0xF3, 0xCE, 0x1B,
-0xFB, 0x3D, 0x08, 0xFB, 0xDE, 0xFE, 0x73, 0x02, 0xEB, 0xFD, 0x33,
-0x01, 0x8F, 0xFF, 0x10, 0x00, 0x03, 0x00, 0xDE, 0xFF, 0x25, 0x00,
-0x71, 0x00, 0xC8, 0xFD, 0xE5, 0x05, 0xFA, 0xF2, 0xDF, 0x22, 0xDB,
-0x39, 0x94, 0xF7, 0xF7, 0x00, 0x4C, 0x01, 0x73, 0xFE, 0x03, 0x01,
-0x9A, 0xFF, 0x0E, 0x00, 0x05, 0x00, 0xCC, 0xFF, 0x5E, 0x00, 0xF9,
-0xFF, 0x80, 0xFE, 0x23, 0x05, 0xF9, 0xF2, 0xC0, 0x29, 0xB8, 0x34,
-0x16, 0xF5, 0xCB, 0x02, 0x2F, 0x00, 0x03, 0xFF, 0xCA, 0x00, 0xAA,
-0xFF, 0x0B, 0x00, 0x08, 0x00, 0xB8, 0xFF, 0x9B, 0x00, 0x72, 0xFF,
-0x65, 0xFF, 0xF6, 0x03, 0xD1, 0xF3, 0x31, 0x30, 0xC1, 0x2E, 0x8B,
-0xF3, 0x45, 0x04, 0x2D, 0xFF, 0x92, 0xFF, 0x8D, 0x00, 0xBD, 0xFF,
-0x08, 0x00, 0x0C, 0x00, 0xA6, 0xFF, 0xD8, 0x00, 0xE2, 0xFE, 0x6F,
-0x00, 0x66, 0x02, 0x93, 0xF5, 0xFB, 0x35, 0x31, 0x28, 0xE7, 0xF2,
-0x59, 0x05, 0x51, 0xFE, 0x17, 0x00, 0x50, 0x00, 0xD0, 0xFF, 0x05,
-0x00, 0x0E, 0x00, 0x97, 0xFF, 0x0F, 0x01, 0x53, 0xFE, 0x90, 0x01,
-0x81, 0x00, 0x4B, 0xF8, 0xE6, 0x3A, 0x3F, 0x21, 0x16, 0xF3, 0x02,
-0x06, 0xA5, 0xFD, 0x8A, 0x00, 0x18, 0x00, 0xE2, 0xFF, 0x02, 0x00,
-0x10, 0x00, 0x8D, 0xFF, 0x3C, 0x01, 0xCE, 0xFD, 0xB7, 0x02, 0x5A,
-0xFE, 0xF7, 0xFB, 0xC6, 0x3E, 0x2C, 0x1A, 0xFC, 0xF3, 0x41, 0x06,
-0x2E, 0xFD, 0xE7, 0x00, 0xE7, 0xFF, 0xF2, 0xFF, 0x01, 0x00, 0x10,
-0x00, 0x8B, 0xFF, 0x5A, 0x01, 0x5E, 0xFD, 0xD2, 0x03, 0x0E, 0xFC,
-0x8B, 0x00, 0x75, 0x41, 0x32, 0x13, 0x75, 0xF5, 0x1C, 0x06, 0xEE,
-0xFC, 0x2B, 0x01, 0xC0, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x0E, 0x00,
-0x91, 0xFF, 0x64, 0x01, 0x0D, 0xFD, 0xCD, 0x04, 0xBB, 0xF9, 0xF2,
-0x05, 0xD9, 0x42, 0x88, 0x0C, 0x5E, 0xF7, 0xA1, 0x05, 0xE3, 0xFC,
-0x54, 0x01, 0xA3, 0xFF, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09,
-0x00, 0xA2, 0xFF, 0x56, 0x01, 0xE5, 0xFC, 0x94, 0x05, 0x87, 0xF7,
-0x0A, 0x0C, 0xE6, 0x42, 0x64, 0x06, 0x8E, 0xF9, 0xDE, 0x04, 0x09,
-0xFD, 0x64, 0x01, 0x92, 0xFF, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00,
-0xBD, 0xFF, 0x2F, 0x01, 0xEC, 0xFC, 0x16, 0x06, 0x98, 0xF5, 0xAB,
-0x12, 0x9C, 0x41, 0xEE, 0x00, 0xE0, 0xFB, 0xE6, 0x03, 0x57, 0xFD,
-0x5B, 0x01, 0x8B, 0xFF, 0x10, 0x00, 0x01, 0x00, 0xF3, 0xFF, 0xE4,
-0xFF, 0xED, 0x00, 0x27, 0xFD, 0x41, 0x06, 0x14, 0xF4, 0xA1, 0x19,
-0x06, 0x3F, 0x49, 0xFC, 0x2E, 0xFE, 0xCD, 0x02, 0xC4, 0xFD, 0x3F,
-0x01, 0x8D, 0xFF, 0x10, 0x00, 0x02, 0x00, 0xE3, 0xFF, 0x14, 0x00,
-0x92, 0x00, 0x9A, 0xFD, 0x0A, 0x06, 0x22, 0xF3, 0xB4, 0x20, 0x3C,
-0x3B, 0x8B, 0xF8, 0x58, 0x00, 0xA7, 0x01, 0x48, 0xFE, 0x13, 0x01,
-0x96, 0xFF, 0x0F, 0x00, 0x04, 0x00, 0xD1, 0xFF, 0x4C, 0x00, 0x20,
-0x00, 0x42, 0xFE, 0x6A, 0x05, 0xE3, 0xF2, 0xAB, 0x27, 0x66, 0x36,
-0xC0, 0xF5, 0x44, 0x02, 0x85, 0x00, 0xD7, 0xFE, 0xDD, 0x00, 0xA5,
-0xFF, 0x0C, 0x00, 0x07, 0x00, 0xBE, 0xFF, 0x89, 0x00, 0x9D, 0xFF,
-0x1A, 0xFF, 0x5E, 0x04, 0x76, 0xF3, 0x45, 0x2E, 0xAA, 0x30, 0xEB,
-0xF3, 0xDB, 0x03, 0x79, 0xFF, 0x67, 0xFF, 0xA0, 0x00, 0xB7, 0xFF,
-0x09, 0x00, 0x0B, 0x00, 0xAC, 0xFF, 0xC6, 0x00, 0x0E, 0xFF, 0x1A,
-0x00, 0xEB, 0x02, 0xEF, 0xF4, 0x49, 0x34, 0x43, 0x2A, 0x02, 0xF3,
-0x0F, 0x05, 0x90, 0xFE, 0xEF, 0xFF, 0x63, 0x00, 0xCA, 0xFF, 0x06,
-0x00, 0x0E, 0x00, 0x9B, 0xFF, 0xFF, 0x00, 0x7E, 0xFE, 0x36, 0x01,
-0x1E, 0x01, 0x5B, 0xF7, 0x7E, 0x39, 0x69, 0x23, 0xF3, 0xF2, 0xD9,
-0x05, 0xD4, 0xFD, 0x69, 0x00, 0x29, 0x00, 0xDD, 0xFF, 0x03, 0x00,
-0x10, 0x00, 0x90, 0xFF, 0x30, 0x01, 0xF5, 0xFD, 0x5C, 0x02, 0x09,
-0xFF, 0xBC, 0xFA, 0xB5, 0x3D, 0x5A, 0x1C, 0xA3, 0xF3, 0x38, 0x06,
-0x4D, 0xFD, 0xCD, 0x00, 0xF5, 0xFF, 0xED, 0xFF, 0x01, 0x00, 0x11,
-0x00, 0x8B, 0xFF, 0x53, 0x01, 0x7E, 0xFD, 0x7D, 0x03, 0xC5, 0xFC,
-0x0B, 0xFF, 0xC3, 0x40, 0x51, 0x15, 0xF4, 0xF4, 0x31, 0x06, 0xFC,
-0xFC, 0x19, 0x01, 0xCB, 0xFF, 0xFB, 0xFF, 0x00, 0x00, 0x0F, 0x00,
-0x8E, 0xFF, 0x63, 0x01, 0x22, 0xFD, 0x84, 0x04, 0x71, 0xFA, 0x34,
-0x04, 0x90, 0x42, 0x89, 0x0E, 0xBE, 0xF6, 0xCF, 0x05, 0xE1, 0xFC,
-0x4A, 0x01, 0xAB, 0xFF, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0B,
-0x00, 0x9B, 0xFF, 0x5D, 0x01, 0xEC, 0xFC, 0x5D, 0x05, 0x2F, 0xF8,
-0x19, 0x0A, 0x07, 0x43, 0x37, 0x08, 0xDD, 0xF8, 0x21, 0x05, 0xF8,
-0xFC, 0x62, 0x01, 0x96, 0xFF, 0x0C, 0x00, 0x00, 0x00, 0x03, 0x00,
-0xB4, 0xFF, 0x3E, 0x01, 0xE4, 0xFC, 0xF6, 0x05, 0x26, 0xF6, 0x95,
-0x10, 0x26, 0x42, 0x87, 0x02, 0x28, 0xFB, 0x37, 0x04, 0x3B, 0xFD,
-0x60, 0x01, 0x8C, 0xFF, 0x10, 0x00, 0x01, 0x00, 0xF7, 0xFF, 0xD7,
-0xFF, 0x04, 0x01, 0x0F, 0xFD, 0x3E, 0x06, 0x7D, 0xF4, 0x76, 0x17,
-0xF4, 0x3F, 0x9F, 0xFD, 0x7B, 0xFD, 0x26, 0x03, 0xA0, 0xFD, 0x4A,
-0x01, 0x8B, 0xFF, 0x11, 0x00, 0x02, 0x00, 0xE9, 0xFF, 0x04, 0x00,
-0xB1, 0x00, 0x71, 0xFD, 0x26, 0x06, 0x5A, 0xF3, 0x88, 0x1E, 0x87,
-0x3C, 0x98, 0xF9, 0xB3, 0xFF, 0x02, 0x02, 0x1E, 0xFE, 0x22, 0x01,
-0x93, 0xFF, 0x0F, 0x00, 0x04, 0x00, 0xD7, 0xFF, 0x3A, 0x00, 0x45,
-0x00, 0x09, 0xFE, 0xA7, 0x05, 0xE1, 0xF2, 0x8D, 0x25, 0xFD, 0x37,
-0x82, 0xF6, 0xB5, 0x01, 0xDC, 0x00, 0xAA, 0xFE, 0xEE, 0x00, 0xA0,
-0xFF, 0x0D, 0x00, 0x06, 0x00, 0xC4, 0xFF, 0x76, 0x00, 0xC7, 0xFF,
-0xD3, 0xFE, 0xBC, 0x04, 0x31, 0xF3, 0x4A, 0x2C, 0x83, 0x32, 0x61,
-0xF4, 0x68, 0x03, 0xC8, 0xFF, 0x3B, 0xFF, 0xB3, 0x00, 0xB1, 0xFF,
-0x0A, 0x00, 0x0A, 0x00, 0xB1, 0xFF, 0xB3, 0x00, 0x3B, 0xFF, 0xC8,
-0xFF, 0x68, 0x03, 0x61, 0xF4, 0x83, 0x32, 0x4A, 0x2C, 0x31, 0xF3,
-0xBC, 0x04, 0xD3, 0xFE, 0xC7, 0xFF, 0x76, 0x00, 0xC4, 0xFF, 0x06,
-0x00, 0x0D, 0x00, 0xA0, 0xFF, 0xEE, 0x00, 0xAA, 0xFE, 0xDC, 0x00,
-0xB5, 0x01, 0x82, 0xF6, 0xFD, 0x37, 0x8D, 0x25, 0xE1, 0xF2, 0xA7,
-0x05, 0x09, 0xFE, 0x45, 0x00, 0x3A, 0x00, 0xD7, 0xFF, 0x04, 0x00,
-0x0F, 0x00, 0x93, 0xFF, 0x22, 0x01, 0x1E, 0xFE, 0x02, 0x02, 0xB3,
-0xFF, 0x98, 0xF9, 0x87, 0x3C, 0x88, 0x1E, 0x5A, 0xF3, 0x26, 0x06,
-0x71, 0xFD, 0xB1, 0x00, 0x04, 0x00, 0xE9, 0xFF, 0x02, 0x00, 0x11,
-0x00, 0x8B, 0xFF, 0x4A, 0x01, 0xA0, 0xFD, 0x26, 0x03, 0x7B, 0xFD,
-0x9F, 0xFD, 0xF4, 0x3F, 0x76, 0x17, 0x7D, 0xF4, 0x3E, 0x06, 0x0F,
-0xFD, 0x04, 0x01, 0xD7, 0xFF, 0xF7, 0xFF, 0x01, 0x00, 0x10, 0x00,
-0x8C, 0xFF, 0x60, 0x01, 0x3B, 0xFD, 0x37, 0x04, 0x28, 0xFB, 0x87,
-0x02, 0x26, 0x42, 0x95, 0x10, 0x26, 0xF6, 0xF6, 0x05, 0xE4, 0xFC,
-0x3E, 0x01, 0xB4, 0xFF, 0x03, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x96,
-0xFF, 0x62, 0x01, 0xF8, 0xFC, 0x21, 0x05, 0xDD, 0xF8, 0x37, 0x08,
-0x07, 0x43, 0x19, 0x0A, 0x2F, 0xF8, 0x5D, 0x05, 0xEC, 0xFC, 0x5D,
-0x01, 0x9B, 0xFF, 0x0B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00,
-0xAB, 0xFF, 0x4A, 0x01, 0xE1, 0xFC, 0xCF, 0x05, 0xBE, 0xF6, 0x89,
-0x0E, 0x90, 0x42, 0x34, 0x04, 0x71, 0xFA, 0x84, 0x04, 0x22, 0xFD,
-0x63, 0x01, 0x8E, 0xFF, 0x0F, 0x00, 0x00, 0x00, 0xFB, 0xFF, 0xCB,
-0xFF, 0x19, 0x01, 0xFC, 0xFC, 0x31, 0x06, 0xF4, 0xF4, 0x51, 0x15,
-0xC3, 0x40, 0x0B, 0xFF, 0xC5, 0xFC, 0x7D, 0x03, 0x7E, 0xFD, 0x53,
-0x01, 0x8B, 0xFF, 0x11, 0x00, 0x01, 0x00, 0xED, 0xFF, 0xF5, 0xFF,
-0xCD, 0x00, 0x4D, 0xFD, 0x38, 0x06, 0xA3, 0xF3, 0x5A, 0x1C, 0xB5,
-0x3D, 0xBC, 0xFA, 0x09, 0xFF, 0x5C, 0x02, 0xF5, 0xFD, 0x30, 0x01,
-0x90, 0xFF, 0x10, 0x00, 0x03, 0x00, 0xDD, 0xFF, 0x29, 0x00, 0x69,
-0x00, 0xD4, 0xFD, 0xD9, 0x05, 0xF3, 0xF2, 0x69, 0x23, 0x7E, 0x39,
-0x5B, 0xF7, 0x1E, 0x01, 0x36, 0x01, 0x7E, 0xFE, 0xFF, 0x00, 0x9B,
-0xFF, 0x0E, 0x00, 0x06, 0x00, 0xCA, 0xFF, 0x63, 0x00, 0xEF, 0xFF,
-0x90, 0xFE, 0x0F, 0x05, 0x02, 0xF3, 0x43, 0x2A, 0x49, 0x34, 0xEF,
-0xF4, 0xEB, 0x02, 0x1A, 0x00, 0x0E, 0xFF, 0xC6, 0x00, 0xAC, 0xFF,
-0x0B, 0x00, 0x09, 0x00, 0xB7, 0xFF, 0xA0, 0x00, 0x67, 0xFF, 0x79,
-0xFF, 0xDB, 0x03, 0xEB, 0xF3, 0xAA, 0x30, 0x45, 0x2E, 0x76, 0xF3,
-0x5E, 0x04, 0x1A, 0xFF, 0x9D, 0xFF, 0x89, 0x00, 0xBE, 0xFF, 0x07,
-0x00, 0x0C, 0x00, 0xA5, 0xFF, 0xDD, 0x00, 0xD7, 0xFE, 0x85, 0x00,
-0x44, 0x02, 0xC0, 0xF5, 0x66, 0x36, 0xAB, 0x27, 0xE3, 0xF2, 0x6A,
-0x05, 0x42, 0xFE, 0x20, 0x00, 0x4C, 0x00, 0xD1, 0xFF, 0x04, 0x00,
-0x0F, 0x00, 0x96, 0xFF, 0x13, 0x01, 0x48, 0xFE, 0xA7, 0x01, 0x58,
-0x00, 0x8B, 0xF8, 0x3C, 0x3B, 0xB4, 0x20, 0x22, 0xF3, 0x0A, 0x06,
-0x9A, 0xFD, 0x92, 0x00, 0x14, 0x00, 0xE3, 0xFF, 0x02, 0x00, 0x10,
-0x00, 0x8D, 0xFF, 0x3F, 0x01, 0xC4, 0xFD, 0xCD, 0x02, 0x2E, 0xFE,
-0x49, 0xFC, 0x06, 0x3F, 0xA1, 0x19, 0x14, 0xF4, 0x41, 0x06, 0x27,
-0xFD, 0xED, 0x00, 0xE4, 0xFF, 0xF3, 0xFF, 0x01, 0x00, 0x10, 0x00,
-0x8B, 0xFF, 0x5B, 0x01, 0x57, 0xFD, 0xE6, 0x03, 0xE0, 0xFB, 0xEE,
-0x00, 0x9C, 0x41, 0xAB, 0x12, 0x98, 0xF5, 0x16, 0x06, 0xEC, 0xFC,
-0x2F, 0x01, 0xBD, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x92,
-0xFF, 0x64, 0x01, 0x09, 0xFD, 0xDE, 0x04, 0x8E, 0xF9, 0x64, 0x06,
-0xE6, 0x42, 0x0A, 0x0C, 0x87, 0xF7, 0x94, 0x05, 0xE5, 0xFC, 0x56,
-0x01, 0xA2, 0xFF, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00,
-0xA3, 0xFF, 0x54, 0x01, 0xE3, 0xFC, 0xA1, 0x05, 0x5E, 0xF7, 0x88,
-0x0C, 0xD9, 0x42, 0xF2, 0x05, 0xBB, 0xF9, 0xCD, 0x04, 0x0D, 0xFD,
-0x64, 0x01, 0x91, 0xFF, 0x0E, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xC0,
-0xFF, 0x2B, 0x01, 0xEE, 0xFC, 0x1C, 0x06, 0x75, 0xF5, 0x32, 0x13,
-0x75, 0x41, 0x8B, 0x00, 0x0E, 0xFC, 0xD2, 0x03, 0x5E, 0xFD, 0x5A,
-0x01, 0x8B, 0xFF, 0x10, 0x00, 0x01, 0x00, 0xF2, 0xFF, 0xE7, 0xFF,
-0xE7, 0x00, 0x2E, 0xFD, 0x41, 0x06, 0xFC, 0xF3, 0x2C, 0x1A, 0xC6,
-0x3E, 0xF7, 0xFB, 0x5A, 0xFE, 0xB7, 0x02, 0xCE, 0xFD, 0x3C, 0x01,
-0x8D, 0xFF, 0x10, 0x00, 0x02, 0x00, 0xE2, 0xFF, 0x18, 0x00, 0x8A,
-0x00, 0xA5, 0xFD, 0x02, 0x06, 0x16, 0xF3, 0x3F, 0x21, 0xE6, 0x3A,
-0x4B, 0xF8, 0x81, 0x00, 0x90, 0x01, 0x53, 0xFE, 0x0F, 0x01, 0x97,
-0xFF, 0x0E, 0x00, 0x05, 0x00, 0xD0, 0xFF, 0x50, 0x00, 0x17, 0x00,
-0x51, 0xFE, 0x59, 0x05, 0xE7, 0xF2, 0x31, 0x28, 0xFB, 0x35, 0x93,
-0xF5, 0x66, 0x02, 0x6F, 0x00, 0xE2, 0xFE, 0xD8, 0x00, 0xA6, 0xFF,
-0x0C, 0x00, 0x08, 0x00, 0xBD, 0xFF, 0x8D, 0x00, 0x92, 0xFF, 0x2D,
-0xFF, 0x45, 0x04, 0x8B, 0xF3, 0xC1, 0x2E, 0x31, 0x30, 0xD1, 0xF3,
-0xF6, 0x03, 0x65, 0xFF, 0x72, 0xFF, 0x9B, 0x00, 0xB8, 0xFF, 0x08,
-0x00, 0x0B, 0x00, 0xAA, 0xFF, 0xCA, 0x00, 0x03, 0xFF, 0x2F, 0x00,
-0xCB, 0x02, 0x16, 0xF5, 0xB8, 0x34, 0xC0, 0x29, 0xF9, 0xF2, 0x23,
-0x05, 0x80, 0xFE, 0xF9, 0xFF, 0x5E, 0x00, 0xCC, 0xFF, 0x05, 0x00,
-0x0E, 0x00, 0x9A, 0xFF, 0x03, 0x01, 0x73, 0xFE, 0x4C, 0x01, 0xF7,
-0x00, 0x94, 0xF7, 0xDB, 0x39, 0xDF, 0x22, 0xFA, 0xF2, 0xE5, 0x05,
-0xC8, 0xFD, 0x71, 0x00, 0x25, 0x00, 0xDE, 0xFF, 0x03, 0x00, 0x10,
-0x00, 0x8F, 0xFF, 0x33, 0x01, 0xEB, 0xFD, 0x73, 0x02, 0xDE, 0xFE,
-0x08, 0xFB, 0xFB, 0x3D, 0xCE, 0x1B, 0xB8, 0xF3, 0x3B, 0x06, 0x45,
-0xFD, 0xD4, 0x00, 0xF2, 0xFF, 0xEF, 0xFF, 0x01, 0x00, 0x11, 0x00,
-0x8A, 0xFF, 0x55, 0x01, 0x75, 0xFD, 0x92, 0x03, 0x97, 0xFC, 0x69,
-0xFF, 0xF2, 0x40, 0xC8, 0x14, 0x13, 0xF5, 0x2D, 0x06, 0xF8, 0xFC,
-0x1E, 0x01, 0xC8, 0xFF, 0xFC, 0xFF, 0x00, 0x00, 0x0F, 0x00, 0x8F,
-0xFF, 0x64, 0x01, 0x1D, 0xFD, 0x97, 0x04, 0x43, 0xFA, 0xA1, 0x04,
-0xA5, 0x42, 0x08, 0x0E, 0xE6, 0xF6, 0xC4, 0x05, 0xE1, 0xFC, 0x4D,
-0x01, 0xA9, 0xFF, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x00,
-0x9D, 0xFF, 0x5C, 0x01, 0xEA, 0xFC, 0x6C, 0x05, 0x05, 0xF8, 0x94,
-0x0A, 0x03, 0x43, 0xC1, 0x07, 0x09, 0xF9, 0x10, 0x05, 0xFC, 0xFC,
-0x62, 0x01, 0x95, 0xFF, 0x0D, 0x00, 0x00, 0x00, 0x02, 0x00, 0xB6,
-0xFF, 0x3B, 0x01, 0xE5, 0xFC, 0xFF, 0x05, 0x02, 0xF6, 0x19, 0x11,
-0x06, 0x42, 0x1F, 0x02, 0x56, 0xFB, 0x23, 0x04, 0x41, 0xFD, 0x5F,
-0x01, 0x8B, 0xFF, 0x10, 0x00, 0x01, 0x00, 0xF6, 0xFF, 0xDA, 0xFF,
-0xFF, 0x00, 0x15, 0xFD, 0x40, 0x06, 0x62, 0xF4, 0x01, 0x18, 0xBB,
-0x3F, 0x47, 0xFD, 0xA8, 0xFD, 0x10, 0x03, 0xA9, 0xFD, 0x47, 0x01,
-0x8C, 0xFF, 0x11, 0x00, 0x02, 0x00, 0xE7, 0xFF, 0x08, 0x00, 0xA9,
-0x00, 0x7B, 0xFD, 0x20, 0x06, 0x4B, 0xF3, 0x13, 0x1F, 0x36, 0x3C,
-0x52, 0xF9, 0xDD, 0xFF, 0xEB, 0x01, 0x28, 0xFE, 0x1F, 0x01, 0x93,
-0xFF, 0x0F, 0x00, 0x04, 0x00, 0xD6, 0xFF, 0x3F, 0x00, 0x3C, 0x00,
-0x16, 0xFE, 0x98, 0x05, 0xE0, 0xF2, 0x16, 0x26, 0x99, 0x37, 0x4F,
-0xF6, 0xD9, 0x01, 0xC6, 0x00, 0xB5, 0xFE, 0xEA, 0x00, 0xA1, 0xFF,
-0x0D, 0x00, 0x07, 0x00, 0xC3, 0xFF, 0x7A, 0x00, 0xBC, 0xFF, 0xE4,
-0xFE, 0xA5, 0x04, 0x41, 0xF3, 0xCA, 0x2C, 0x0E, 0x32, 0x42, 0xF4,
-0x85, 0x03, 0xB4, 0xFF, 0x46, 0xFF, 0xAE, 0x00, 0xB3, 0xFF, 0x09,
-0x00, 0x0A, 0x00, 0xB0, 0xFF, 0xB8, 0x00, 0x30, 0xFF, 0xDC, 0xFF,
-0x49, 0x03, 0x83, 0xF4, 0xF5, 0x32, 0xC9, 0x2B, 0x23, 0xF3, 0xD1,
-0x04, 0xC2, 0xFE, 0xD1, 0xFF, 0x71, 0x00, 0xC6, 0xFF, 0x06, 0x00,
-0x0D, 0x00, 0x9F, 0xFF, 0xF3, 0x00, 0x9F, 0xFE, 0xF3, 0x00, 0x90,
-0x01, 0xB6, 0xF6, 0x5F, 0x38, 0x04, 0x25, 0xE4, 0xF2, 0xB4, 0x05,
-0xFB, 0xFD, 0x4E, 0x00, 0x36, 0x00, 0xD9, 0xFF, 0x04, 0x00, 0x0F,
-0x00, 0x92, 0xFF, 0x26, 0x01, 0x13, 0xFE, 0x18, 0x02, 0x89, 0xFF,
-0xDF, 0xF9, 0xD3, 0x3C, 0xFC, 0x1D, 0x6B, 0xF3, 0x2C, 0x06, 0x67,
-0xFD, 0xB8, 0x00, 0x00, 0x00, 0xEA, 0xFF, 0x02, 0x00, 0x11, 0x00,
-0x8B, 0xFF, 0x4C, 0x01, 0x97, 0xFD, 0x3C, 0x03, 0x4D, 0xFD, 0xF8,
-0xFD, 0x2A, 0x40, 0xED, 0x16, 0x9A, 0xF4, 0x3C, 0x06, 0x0A, 0xFD,
-0x0A, 0x01, 0xD4, 0xFF, 0xF8, 0xFF, 0x01, 0x00, 0x10, 0x00, 0x8C,
-0xFF, 0x61, 0x01, 0x34, 0xFD, 0x4B, 0x04, 0xFA, 0xFA, 0xF1, 0x02,
-0x42, 0x42, 0x11, 0x10, 0x4C, 0xF6, 0xED, 0x05, 0xE3, 0xFC, 0x41,
-0x01, 0xB1, 0xFF, 0x03, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x97, 0xFF,
-0x61, 0x01, 0xF5, 0xFC, 0x30, 0x05, 0xB1, 0xF8, 0xAE, 0x08, 0x0A,
-0x43, 0x9F, 0x09, 0x5A, 0xF8, 0x4F, 0x05, 0xEF, 0xFC, 0x5F, 0x01,
-0x9A, 0xFF, 0x0B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0xAD,
-0xFF, 0x48, 0x01, 0xE2, 0xFC, 0xDA, 0x05, 0x97, 0xF6, 0x0B, 0x0F,
-0x79, 0x42, 0xC7, 0x03, 0x9E, 0xFA, 0x71, 0x04, 0x28, 0xFD, 0x63,
-0x01, 0x8D, 0xFF, 0x0F, 0x00
+ 0xFF, 0xFF, 0x2F, 0x00, 0x4B, 0xFF, 0xA5, 0x01, 0xEF, 0xFC, 0x21,
+ 0x05, 0x87, 0xF7, 0x62, 0x11, 0xE9, 0x45, 0x5E, 0xF9, 0xB5, 0x01,
+ 0xDE, 0xFF, 0xA4, 0xFF, 0x60, 0x00, 0xCA, 0xFF, 0x0D, 0x00, 0xFD,
+ 0xFF, 0x36, 0x00, 0x36, 0xFF, 0xE6, 0x01, 0x3D, 0xFC, 0xD6, 0x06,
+ 0x4C, 0xF3, 0xED, 0x20, 0x3D, 0x3D, 0x4A, 0xF3, 0x4E, 0x05, 0xB1,
+ 0xFD, 0xE1, 0x00, 0xC3, 0xFF, 0x05, 0x00, 0x02, 0x00, 0xFD, 0xFF,
+ 0x2A, 0x00, 0x5C, 0xFF, 0xAA, 0x01, 0x71, 0xFC, 0x07, 0x07, 0x7E,
+ 0xF1, 0x44, 0x30, 0x44, 0x30, 0x7E, 0xF1, 0x07, 0x07, 0x71, 0xFC,
+ 0xAA, 0x01, 0x5C, 0xFF, 0x2A, 0x00, 0xFD, 0xFF, 0x02, 0x00, 0x05,
+ 0x00, 0xC3, 0xFF, 0xE1, 0x00, 0xB1, 0xFD, 0x4E, 0x05, 0x4A, 0xF3,
+ 0x3D, 0x3D, 0xED, 0x20, 0x4C, 0xF3, 0xD6, 0x06, 0x3D, 0xFC, 0xE6,
+ 0x01, 0x36, 0xFF, 0x36, 0x00, 0xFD, 0xFF, 0x0D, 0x00, 0xCA, 0xFF,
+ 0x60, 0x00, 0xA4, 0xFF, 0xDE, 0xFF, 0xB5, 0x01, 0x5E, 0xF9, 0xE9,
+ 0x45, 0x62, 0x11, 0x87, 0xF7, 0x21, 0x05, 0xEF, 0xFC, 0xA5, 0x01,
+ 0x4B, 0xFF, 0x2F, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x1E, 0x00, 0x84,
+ 0xFF, 0x11, 0x01, 0x34, 0xFE, 0x8F, 0x02, 0xC7, 0xFC, 0xAE, 0x03,
+ 0xF7, 0x48, 0xAE, 0x03, 0xC7, 0xFC, 0x8F, 0x02, 0x34, 0xFE, 0x11,
+ 0x01, 0x84, 0xFF, 0x1E, 0x00, 0xFE, 0xFF, 0x34, 0x00, 0x3D, 0xFF,
+ 0xCA, 0x01, 0x95, 0xFC, 0xEA, 0x05, 0xBB, 0xF5, 0x25, 0x17, 0x3C,
+ 0x43, 0x8D, 0xF6, 0x43, 0x03, 0xF5, 0xFE, 0x26, 0x00, 0x20, 0x00,
+ 0xE2, 0xFF, 0x08, 0x00, 0xFD, 0xFF, 0x30, 0x00, 0x4D, 0xFF, 0xC5,
+ 0x01, 0x4C, 0xFC, 0x26, 0x07, 0xA3, 0xF1, 0xAB, 0x2C, 0xBB, 0x33,
+ 0x8F, 0xF1, 0xCA, 0x06, 0xA6, 0xFC, 0x85, 0x01, 0x6F, 0xFF, 0x24,
+ 0x00, 0xFD, 0xFF, 0x03, 0x00, 0xFE, 0xFF, 0xD5, 0xFF, 0xBC, 0x00,
+ 0xF0, 0xFD, 0xEC, 0x04, 0xD9, 0xF3, 0xB1, 0x3E, 0xCD, 0x1E, 0xC1,
+ 0xF3, 0xAF, 0x06, 0x49, 0xFC, 0xE4, 0x01, 0x36, 0xFF, 0x36, 0x00,
+ 0xFE, 0xFF, 0x16, 0x00, 0xA6, 0xFF, 0xBB, 0x00, 0xE9, 0xFE, 0x38,
+ 0x01, 0x4B, 0xFF, 0x28, 0xFE, 0x3A, 0x48, 0x04, 0x0A, 0x2E, 0xFA,
+ 0xDF, 0x03, 0x8A, 0xFD, 0x60, 0x01, 0x65, 0xFF, 0x27, 0x00, 0x00,
+ 0x00, 0xFF, 0xFF, 0x2E, 0x00, 0x50, 0xFF, 0x98, 0x01, 0x0D, 0xFD,
+ 0xE0, 0x04, 0x14, 0xF8, 0xC3, 0x0F, 0x89, 0x46, 0x4C, 0xFA, 0x38,
+ 0x01, 0x25, 0x00, 0x7D, 0xFF, 0x73, 0x00, 0xC2, 0xFF, 0x0F, 0x00,
+ 0xFD, 0xFF, 0x35, 0x00, 0x3A, 0xFF, 0xE3, 0x01, 0x31, 0xFC, 0x0F,
+ 0x07, 0x84, 0xF2, 0x29, 0x25, 0x1A, 0x3A, 0x67, 0xF2, 0xF6, 0x05,
+ 0x41, 0xFD, 0x24, 0x01, 0xA1, 0xFF, 0x12, 0x00, 0x00, 0x00, 0xFF,
+ 0xFF, 0x15, 0x00, 0x97, 0xFF, 0x37, 0x01, 0x22, 0xFD, 0x23, 0x06,
+ 0x2F, 0xF2, 0x11, 0x39, 0x7B, 0x26, 0x50, 0xF2, 0x1B, 0x07, 0x32,
+ 0xFC, 0xE1, 0x01, 0x3C, 0xFF, 0x35, 0x00, 0xFD, 0xFF, 0x0E, 0x00,
+ 0xC8, 0xFF, 0x64, 0x00, 0x9B, 0xFF, 0xEE, 0xFF, 0x98, 0x01, 0x93,
+ 0xF9, 0x10, 0x46, 0x03, 0x11, 0xA7, 0xF7, 0x12, 0x05, 0xF6, 0xFC,
+ 0xA2, 0x01, 0x4C, 0xFF, 0x2F, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x26,
+ 0x00, 0x6A, 0xFF, 0x53, 0x01, 0xA6, 0xFD, 0xA6, 0x03, 0xA1, 0xFA,
+ 0xDE, 0x08, 0x76, 0x48, 0x0C, 0xFF, 0xDE, 0xFE, 0x73, 0x01, 0xC9,
+ 0xFE, 0xCA, 0x00, 0xA0, 0xFF, 0x17, 0x00, 0xFE, 0xFF, 0x36, 0x00,
+ 0x36, 0xFF, 0xE1, 0x01, 0x52, 0xFC, 0x93, 0x06, 0x10, 0xF4, 0x78,
+ 0x1D, 0x90, 0x3F, 0x3E, 0xF4, 0xAA, 0x04, 0x19, 0xFE, 0xA4, 0x00,
+ 0xE2, 0xFF, 0xFA, 0xFF, 0x03, 0x00, 0xFD, 0xFF, 0x26, 0x00, 0x68,
+ 0xFF, 0x93, 0x01, 0x92, 0xFC, 0xE2, 0x06, 0x83, 0xF1, 0x8C, 0x32,
+ 0xED, 0x2D, 0x90, 0xF1, 0x1E, 0x07, 0x57, 0xFC, 0xBD, 0x01, 0x51,
+ 0xFF, 0x2E, 0x00, 0xFD, 0xFF, 0x07, 0x00, 0xE8, 0xFF, 0x12, 0x00,
+ 0x42, 0x00, 0xC4, 0xFE, 0x94, 0x03, 0x02, 0xF6, 0x89, 0x42, 0x76,
+ 0x18, 0x5C, 0xF5, 0x12, 0x06, 0x84, 0xFC, 0xD1, 0x01, 0x3B, 0xFF,
+ 0x34, 0x00, 0xFE, 0xFF, 0x1D, 0x00, 0x8A, 0xFF, 0x03, 0x01, 0x53,
+ 0xFE, 0x53, 0x02, 0x39, 0xFD, 0xA9, 0x02, 0xF2, 0x48, 0xB9, 0x04,
+ 0x54, 0xFC, 0xCA, 0x02, 0x16, 0xFE, 0x20, 0x01, 0x7F, 0xFF, 0x20,
+ 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x33, 0x00, 0x40, 0xFF, 0xC3, 0x01,
+ 0xA7, 0xFC, 0xC0, 0x05, 0x1E, 0xF6, 0xD8, 0x15, 0xE7, 0x43, 0x20,
+ 0xF7, 0xEF, 0x02, 0x27, 0xFF, 0x0A, 0x00, 0x2E, 0x00, 0xDD, 0xFF,
+ 0x09, 0x00, 0xFD, 0xFF, 0x31, 0x00, 0x48, 0xFF, 0xCD, 0x01, 0x43,
+ 0xFC, 0x2A, 0x07, 0xBC, 0xF1, 0x64, 0x2B, 0xE3, 0x34, 0xA3, 0xF1,
+ 0xAE, 0x06, 0xBD, 0xFC, 0x77, 0x01, 0x77, 0xFF, 0x21, 0x00, 0xFE,
+ 0xFF, 0x02, 0x00, 0x03, 0x00, 0xCA, 0xFF, 0xD4, 0x00, 0xC8, 0xFD,
+ 0x2A, 0x05, 0x7D, 0xF3, 0xCA, 0x3D, 0x22, 0x20, 0x76, 0xF3, 0xC8,
+ 0x06, 0x41, 0xFC, 0xE6, 0x01, 0x36, 0xFF, 0x36, 0x00, 0xFD, 0xFF,
+ 0x14, 0x00, 0xAC, 0xFF, 0xAC, 0x00, 0x08, 0xFF, 0xFD, 0x00, 0xB5,
+ 0xFF, 0x4B, 0xFD, 0xF4, 0x47, 0x30, 0x0B, 0xBC, 0xF9, 0x17, 0x04,
+ 0x6E, 0xFD, 0x6D, 0x01, 0x60, 0xFF, 0x29, 0x00, 0x00, 0x00, 0xFF,
+ 0xFF, 0x2C, 0x00, 0x54, 0xFF, 0x8D, 0x01, 0x26, 0xFD, 0xAD, 0x04,
+ 0x82, 0xF8, 0x87, 0x0E, 0xF9, 0x46, 0x0C, 0xFB, 0xD4, 0x00, 0x5D,
+ 0x00, 0x5E, 0xFF, 0x82, 0x00, 0xBD, 0xFF, 0x10, 0x00, 0xFD, 0xFF,
+ 0x36, 0x00, 0x38, 0xFF, 0xE5, 0x01, 0x33, 0xFC, 0x01, 0x07, 0xBE,
+ 0xF2, 0xD6, 0x23, 0x1F, 0x3B, 0xA5, 0xF2, 0xC5, 0x05, 0x62, 0xFD,
+ 0x10, 0x01, 0xAB, 0xFF, 0x0E, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x19,
+ 0x00, 0x8E, 0xFF, 0x49, 0x01, 0x04, 0xFD, 0x4D, 0x06, 0x00, 0xF2,
+ 0xFE, 0x37, 0xCB, 0x27, 0x21, 0xF2, 0x23, 0x07, 0x34, 0xFC, 0xDD,
+ 0x01, 0x3F, 0xFF, 0x34, 0x00, 0xFD, 0xFF, 0x0C, 0x00, 0xCE, 0xFF,
+ 0x56, 0x00, 0xB9, 0xFF, 0xB8, 0xFF, 0xF7, 0x01, 0xE2, 0xF8, 0x8D,
+ 0x45, 0x46, 0x12, 0x3C, 0xF7, 0x43, 0x05, 0xDF, 0xFC, 0xAC, 0x01,
+ 0x48, 0xFF, 0x30, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x24, 0x00, 0x70,
+ 0xFF, 0x46, 0x01, 0xC3, 0xFD, 0x6D, 0x03, 0x14, 0xFB, 0xBE, 0x07,
+ 0xA6, 0x48, 0xF8, 0xFF, 0x70, 0xFE, 0xAE, 0x01, 0xAA, 0xFE, 0xD9,
+ 0x00, 0x9A, 0xFF, 0x19, 0x00, 0xFE, 0xFF, 0x36, 0x00, 0x37, 0xFF,
+ 0xDE, 0x01, 0x5D, 0xFC, 0x74, 0x06, 0x63, 0xF4, 0x23, 0x1C, 0x66,
+ 0x40, 0xAA, 0xF4, 0x65, 0x04, 0x44, 0xFE, 0x8B, 0x00, 0xEE, 0xFF,
+ 0xF5, 0xFF, 0x04, 0x00, 0xFD, 0xFF, 0x29, 0x00, 0x61, 0xFF, 0x9F,
+ 0x01, 0x80, 0xFC, 0xF7, 0x06, 0x7D, 0xF1, 0x5A, 0x31, 0x2C, 0x2F,
+ 0x83, 0xF1, 0x13, 0x07, 0x64, 0xFC, 0xB3, 0x01, 0x57, 0xFF, 0x2C,
+ 0x00, 0xFD, 0xFF, 0x06, 0x00, 0xED, 0xFF, 0x05, 0x00, 0x5D, 0x00,
+ 0x95, 0xFE, 0xE2, 0x03, 0x7F, 0xF5, 0xCC, 0x41, 0xC7, 0x19, 0xFF,
+ 0xF4, 0x37, 0x06, 0x75, 0xFC, 0xD6, 0x01, 0x39, 0xFF, 0x35, 0x00,
+ 0xFE, 0xFF, 0x1B, 0x00, 0x90, 0xFF, 0xF4, 0x00, 0x72, 0xFE, 0x18,
+ 0x02, 0xAA, 0xFD, 0xAB, 0x01, 0xDF, 0x48, 0xCA, 0x05, 0xE1, 0xFB,
+ 0x05, 0x03, 0xF7, 0xFD, 0x2E, 0x01, 0x79, 0xFF, 0x21, 0x00, 0x00,
+ 0x00, 0xFF, 0xFF, 0x32, 0x00, 0x43, 0xFF, 0xBB, 0x01, 0xBA, 0xFC,
+ 0x95, 0x05, 0x83, 0xF6, 0x8C, 0x14, 0x87, 0x44, 0xBB, 0xF7, 0x98,
+ 0x02, 0x5A, 0xFF, 0xEE, 0xFF, 0x3C, 0x00, 0xD8, 0xFF, 0x0A, 0x00,
+ 0xFD, 0xFF, 0x32, 0x00, 0x44, 0xFF, 0xD3, 0x01, 0x3C, 0xFC, 0x2A,
+ 0x07, 0xDC, 0xF1, 0x1A, 0x2A, 0x06, 0x36, 0xBE, 0xF1, 0x8E, 0x06,
+ 0xD5, 0xFC, 0x67, 0x01, 0x7F, 0xFF, 0x1E, 0x00, 0xFE, 0xFF, 0x01,
+ 0x00, 0x07, 0x00, 0xBE, 0xFF, 0xEA, 0x00, 0xA2, 0xFD, 0x65, 0x05,
+ 0x28, 0xF3, 0xDB, 0x3C, 0x78, 0x21, 0x30, 0xF3, 0xDF, 0x06, 0x3A,
+ 0xFC, 0xE6, 0x01, 0x37, 0xFF, 0x36, 0x00, 0xFD, 0xFF, 0x13, 0x00,
+ 0xB2, 0xFF, 0x9D, 0x00, 0x27, 0xFF, 0xC3, 0x00, 0x1F, 0x00, 0x76,
+ 0xFC, 0xA3, 0x47, 0x60, 0x0C, 0x4A, 0xF9, 0x4E, 0x04, 0x53, 0xFD,
+ 0x79, 0x01, 0x5C, 0xFF, 0x2A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2B,
+ 0x00, 0x58, 0xFF, 0x82, 0x01, 0x3F, 0xFD, 0x78, 0x04, 0xF2, 0xF8,
+ 0x50, 0x0D, 0x5E, 0x47, 0xD5, 0xFB, 0x6F, 0x00, 0x96, 0x00, 0x40,
+ 0xFF, 0x91, 0x00, 0xB7, 0xFF, 0x12, 0x00, 0xFD, 0xFF, 0x36, 0x00,
+ 0x37, 0xFF, 0xE6, 0x01, 0x36, 0xFC, 0xEF, 0x06, 0xFC, 0xF2, 0x81,
+ 0x22, 0x1C, 0x3C, 0xEC, 0xF2, 0x90, 0x05, 0x85, 0xFD, 0xFB, 0x00,
+ 0xB6, 0xFF, 0x0A, 0x00, 0x01, 0x00, 0xFE, 0xFF, 0x1C, 0x00, 0x85,
+ 0xFF, 0x5B, 0x01, 0xE9, 0xFC, 0x73, 0x06, 0xD8, 0xF1, 0xE5, 0x36,
+ 0x19, 0x29, 0xF8, 0xF1, 0x29, 0x07, 0x37, 0xFC, 0xD8, 0x01, 0x42,
+ 0xFF, 0x33, 0x00, 0xFD, 0xFF, 0x0B, 0x00, 0xD3, 0xFF, 0x47, 0x00,
+ 0xD7, 0xFF, 0x82, 0xFF, 0x53, 0x02, 0x39, 0xF8, 0xFD, 0x44, 0x8D,
+ 0x13, 0xD3, 0xF6, 0x72, 0x05, 0xCA, 0xFC, 0xB5, 0x01, 0x45, 0xFF,
+ 0x31, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x23, 0x00, 0x75, 0xFF, 0x39,
+ 0x01, 0xE0, 0xFD, 0x33, 0x03, 0x87, 0xFB, 0xA2, 0x06, 0xCB, 0x48,
+ 0xEA, 0x00, 0x01, 0xFE, 0xE9, 0x01, 0x8A, 0xFE, 0xE8, 0x00, 0x95,
+ 0xFF, 0x1A, 0x00, 0xFE, 0xFF, 0x35, 0x00, 0x38, 0xFF, 0xDA, 0x01,
+ 0x6A, 0xFC, 0x53, 0x06, 0xBA, 0xF4, 0xCE, 0x1A, 0x32, 0x41, 0x1F,
+ 0xF5, 0x1D, 0x04, 0x71, 0xFE, 0x71, 0x00, 0xFB, 0xFF, 0xF0, 0xFF,
+ 0x05, 0x00, 0xFD, 0xFF, 0x2B, 0x00, 0x5B, 0xFF, 0xAB, 0x01, 0x6F,
+ 0xFC, 0x08, 0x07, 0x7E, 0xF1, 0x21, 0x30, 0x67, 0x30, 0x7D, 0xF1,
+ 0x05, 0x07, 0x73, 0xFC, 0xA8, 0x01, 0x5C, 0xFF, 0x2A, 0x00, 0xFD,
+ 0xFF, 0x05, 0x00, 0xF2, 0xFF, 0xF8, 0xFF, 0x77, 0x00, 0x67, 0xFE,
+ 0x2D, 0x04, 0x04, 0xF5, 0x07, 0x41, 0x1B, 0x1B, 0xA6, 0xF4, 0x5A,
+ 0x06, 0x67, 0xFC, 0xDB, 0x01, 0x38, 0xFF, 0x36, 0x00, 0xFE, 0xFF,
+ 0x1A, 0x00, 0x96, 0xFF, 0xE5, 0x00, 0x91, 0xFE, 0xDC, 0x01, 0x1A,
+ 0xFE, 0xB3, 0x00, 0xC3, 0x48, 0xE1, 0x06, 0x6E, 0xFB, 0x40, 0x03,
+ 0xDA, 0xFD, 0x3C, 0x01, 0x74, 0xFF, 0x23, 0x00, 0x00, 0x00, 0xFF,
+ 0xFF, 0x31, 0x00, 0x46, 0xFF, 0xB3, 0x01, 0xCF, 0xFC, 0x67, 0x05,
+ 0xEA, 0xF6, 0x44, 0x13, 0x1E, 0x45, 0x5E, 0xF8, 0x3F, 0x02, 0x8E,
+ 0xFF, 0xD0, 0xFF, 0x4A, 0x00, 0xD2, 0xFF, 0x0B, 0x00, 0xFD, 0xFF,
+ 0x33, 0x00, 0x41, 0xFF, 0xD9, 0x01, 0x36, 0xFC, 0x28, 0x07, 0x01,
+ 0xF2, 0xCE, 0x28, 0x23, 0x37, 0xE0, 0xF1, 0x6B, 0x06, 0xEF, 0xFC,
+ 0x57, 0x01, 0x87, 0xFF, 0x1B, 0x00, 0xFE, 0xFF, 0x01, 0x00, 0x0B,
+ 0x00, 0xB4, 0xFF, 0x00, 0x01, 0x7E, 0xFD, 0x9C, 0x05, 0xDC, 0xF2,
+ 0xE4, 0x3B, 0xCD, 0x22, 0xEE, 0xF2, 0xF3, 0x06, 0x35, 0xFC, 0xE6,
+ 0x01, 0x37, 0xFF, 0x36, 0x00, 0xFD, 0xFF, 0x11, 0x00, 0xB8, 0xFF,
+ 0x8E, 0x00, 0x46, 0xFF, 0x8A, 0x00, 0x86, 0x00, 0xA7, 0xFB, 0x48,
+ 0x47, 0x95, 0x0D, 0xD9, 0xF8, 0x84, 0x04, 0x39, 0xFD, 0x85, 0x01,
+ 0x57, 0xFF, 0x2B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2A, 0x00, 0x5D,
+ 0xFF, 0x76, 0x01, 0x59, 0xFD, 0x42, 0x04, 0x63, 0xF9, 0x1C, 0x0C,
+ 0xB6, 0x47, 0xA4, 0xFC, 0x07, 0x00, 0xD0, 0x00, 0x20, 0xFF, 0xA0,
+ 0x00, 0xB1, 0xFF, 0x13, 0x00, 0xFD, 0xFF, 0x36, 0x00, 0x36, 0xFF,
+ 0xE6, 0x01, 0x3B, 0xFC, 0xDA, 0x06, 0x3F, 0xF3, 0x2C, 0x21, 0x11,
+ 0x3D, 0x3A, 0xF3, 0x58, 0x05, 0xAA, 0xFD, 0xE5, 0x00, 0xC1, 0xFF,
+ 0x06, 0x00, 0x01, 0x00, 0xFE, 0xFF, 0x1F, 0x00, 0x7D, 0xFF, 0x6B,
+ 0x01, 0xCF, 0xFC, 0x96, 0x06, 0xB7, 0xF1, 0xC6, 0x35, 0x64, 0x2A,
+ 0xD4, 0xF1, 0x2B, 0x07, 0x3D, 0xFC, 0xD2, 0x01, 0x45, 0xFF, 0x32,
+ 0x00, 0xFD, 0xFF, 0x0A, 0x00, 0xD9, 0xFF, 0x39, 0x00, 0xF4, 0xFF,
+ 0x4E, 0xFF, 0xAC, 0x02, 0x98, 0xF7, 0x65, 0x44, 0xD6, 0x14, 0x6C,
+ 0xF6, 0x9F, 0x05, 0xB6, 0xFC, 0xBD, 0x01, 0x42, 0xFF, 0x32, 0x00,
+ 0xFF, 0xFF, 0x00, 0x00, 0x21, 0x00, 0x7A, 0xFF, 0x2B, 0x01, 0xFE,
+ 0xFD, 0xF8, 0x02, 0xFB, 0xFB, 0x8D, 0x05, 0xE5, 0x48, 0xE3, 0x01,
+ 0x91, 0xFD, 0x25, 0x02, 0x6B, 0xFE, 0xF7, 0x00, 0x8F, 0xFF, 0x1C,
+ 0x00, 0xFE, 0xFF, 0x35, 0x00, 0x3A, 0xFF, 0xD5, 0x01, 0x78, 0xFC,
+ 0x2F, 0x06, 0x13, 0xF5, 0x7C, 0x19, 0xF7, 0x41, 0x9B, 0xF5, 0xD1,
+ 0x03, 0x9F, 0xFE, 0x57, 0x00, 0x08, 0x00, 0xEC, 0xFF, 0x06, 0x00,
+ 0xFD, 0xFF, 0x2D, 0x00, 0x55, 0xFF, 0xB5, 0x01, 0x61, 0xFC, 0x16,
+ 0x07, 0x85, 0xF1, 0xE6, 0x2E, 0x9E, 0x31, 0x7D, 0xF1, 0xF3, 0x06,
+ 0x84, 0xFC, 0x9D, 0x01, 0x63, 0xFF, 0x28, 0x00, 0xFD, 0xFF, 0x04,
+ 0x00, 0xF6, 0xFF, 0xEB, 0xFF, 0x91, 0x00, 0x3B, 0xFE, 0x75, 0x04,
+ 0x92, 0xF4, 0x36, 0x40, 0x6E, 0x1C, 0x50, 0xF4, 0x7B, 0x06, 0x5B,
+ 0xFC, 0xDF, 0x01, 0x37, 0xFF, 0x36, 0x00, 0xFE, 0xFF, 0x18, 0x00,
+ 0x9C, 0xFF, 0xD6, 0x00, 0xB1, 0xFE, 0xA1, 0x01, 0x89, 0xFE, 0xC3,
+ 0xFF, 0x9C, 0x48, 0xFD, 0x07, 0xFA, 0xFA, 0x7A, 0x03, 0xBC, 0xFD,
+ 0x49, 0x01, 0x6E, 0xFF, 0x24, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x30,
+ 0x00, 0x49, 0xFF, 0xAA, 0x01, 0xE4, 0xFC, 0x38, 0x05, 0x54, 0xF7,
+ 0xFE, 0x11, 0xAA, 0x45, 0x09, 0xF9, 0xE2, 0x01, 0xC4, 0xFF, 0xB3,
+ 0xFF, 0x59, 0x00, 0xCD, 0xFF, 0x0D, 0x00, 0xFD, 0xFF, 0x34, 0x00,
+ 0x3E, 0xFF, 0xDE, 0x01, 0x33, 0xFC, 0x22, 0x07, 0x2B, 0xF2, 0x80,
+ 0x27, 0x3B, 0x38, 0x0A, 0xF2, 0x44, 0x06, 0x0B, 0xFD, 0x45, 0x01,
+ 0x90, 0xFF, 0x18, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x0F, 0x00, 0xA9,
+ 0xFF, 0x15, 0x01, 0x5B, 0xFD, 0xD0, 0x05, 0x97, 0xF2, 0xE6, 0x3A,
+ 0x21, 0x24, 0xB1, 0xF2, 0x04, 0x07, 0x33, 0xFC, 0xE5, 0x01, 0x39,
+ 0xFF, 0x36, 0x00, 0xFD, 0xFF, 0x10, 0x00, 0xBE, 0xFF, 0x7F, 0x00,
+ 0x65, 0xFF, 0x51, 0x00, 0xEB, 0x00, 0xE1, 0xFA, 0xE1, 0x46, 0xCD,
+ 0x0E, 0x6A, 0xF8, 0xB8, 0x04, 0x20, 0xFD, 0x90, 0x01, 0x53, 0xFF,
+ 0x2D, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x28, 0x00, 0x62, 0xFF, 0x6A,
+ 0x01, 0x74, 0xFD, 0x0A, 0x04, 0xD5, 0xF9, 0xED, 0x0A, 0x03, 0x48,
+ 0x7C, 0xFD, 0x9E, 0xFF, 0x0A, 0x01, 0x01, 0xFF, 0xAF, 0x00, 0xAB,
+ 0xFF, 0x14, 0x00, 0xFD, 0xFF, 0x36, 0x00, 0x36, 0xFF, 0xE5, 0x01,
+ 0x42, 0xFC, 0xC3, 0x06, 0x87, 0xF3, 0xD7, 0x1F, 0xFE, 0x3D, 0x91,
+ 0xF3, 0x1D, 0x05, 0xD1, 0xFD, 0xCE, 0x00, 0xCC, 0xFF, 0x02, 0x00,
+ 0x02, 0x00, 0xFE, 0xFF, 0x22, 0x00, 0x75, 0xFF, 0x7A, 0x01, 0xB8,
+ 0xFC, 0xB4, 0x06, 0x9E, 0xF1, 0xA2, 0x34, 0xAD, 0x2B, 0xB6, 0xF1,
+ 0x29, 0x07, 0x45, 0xFC, 0xCB, 0x01, 0x49, 0xFF, 0x31, 0x00, 0xFD,
+ 0xFF, 0x09, 0x00, 0xDE, 0xFF, 0x2B, 0x00, 0x11, 0x00, 0x1B, 0xFF,
+ 0x02, 0x03, 0xFE, 0xF6, 0xC3, 0x43, 0x22, 0x16, 0x07, 0xF6, 0xCA,
+ 0x05, 0xA3, 0xFC, 0xC5, 0x01, 0x3F, 0xFF, 0x33, 0x00, 0xFF, 0xFF,
+ 0x00, 0x00, 0x20, 0x00, 0x80, 0xFF, 0x1C, 0x01, 0x1C, 0xFE, 0xBD,
+ 0x02, 0x6E, 0xFC, 0x7D, 0x04, 0xF3, 0x48, 0xE2, 0x02, 0x1F, 0xFD,
+ 0x60, 0x02, 0x4C, 0xFE, 0x06, 0x01, 0x89, 0xFF, 0x1D, 0x00, 0xFE,
+ 0xFF, 0x34, 0x00, 0x3C, 0xFF, 0xCF, 0x01, 0x88, 0xFC, 0x09, 0x06,
+ 0x71, 0xF5, 0x2B, 0x18, 0xB2, 0x42, 0x20, 0xF6, 0x83, 0x03, 0xCF,
+ 0xFE, 0x3C, 0x00, 0x15, 0x00, 0xE6, 0xFF, 0x07, 0x00, 0xFD, 0xFF,
+ 0x2E, 0x00, 0x50, 0xFF, 0xBF, 0x01, 0x54, 0xFC, 0x20, 0x07, 0x94,
+ 0xF1, 0xA6, 0x2D, 0xD0, 0x32, 0x85, 0xF1, 0xDD, 0x06, 0x96, 0xFC,
+ 0x90, 0x01, 0x69, 0xFF, 0x26, 0x00, 0xFD, 0xFF, 0x03, 0x00, 0xFB,
+ 0xFF, 0xDF, 0xFF, 0xA9, 0x00, 0x10, 0xFE, 0xB9, 0x04, 0x27, 0xF4,
+ 0x5E, 0x3F, 0xC3, 0x1D, 0xFE, 0xF3, 0x99, 0x06, 0x50, 0xFC, 0xE2,
+ 0x01, 0x36, 0xFF, 0x36, 0x00, 0xFE, 0xFF, 0x17, 0x00, 0xA2, 0xFF,
+ 0xC7, 0x00, 0xD0, 0xFE, 0x65, 0x01, 0xF6, 0xFE, 0xD9, 0xFE, 0x6A,
+ 0x48, 0x1F, 0x09, 0x87, 0xFA, 0xB3, 0x03, 0xA0, 0xFD, 0x56, 0x01,
+ 0x69, 0xFF, 0x26, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x2F, 0x00, 0x4D,
+ 0xFF, 0xA0, 0x01, 0xFB, 0xFC, 0x07, 0x05, 0xBF, 0xF7, 0xBB, 0x10,
+ 0x2B, 0x46, 0xBB, 0xF9, 0x83, 0x01, 0xFA, 0xFF, 0x95, 0xFF, 0x68,
+ 0x00, 0xC7, 0xFF, 0x0E, 0x00, 0xFD, 0xFF, 0x35, 0x00, 0x3C, 0xFF,
+ 0xE1, 0x01, 0x31, 0xFC, 0x19, 0x07, 0x5B, 0xF2, 0x30, 0x26, 0x4B,
+ 0x39, 0x3B, 0xF2, 0x1A, 0x06, 0x29, 0xFD, 0x33, 0x01, 0x99, 0xFF,
+ 0x15, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x13, 0x00, 0x9F, 0xFF, 0x28,
+ 0x01, 0x3A, 0xFD, 0x00, 0x06, 0x5A, 0xF2, 0xDF, 0x39, 0x73, 0x25,
+ 0x79, 0xF2, 0x12, 0x07, 0x31, 0xFC, 0xE3, 0x01, 0x3B, 0xFF, 0x35,
+ 0x00, 0xFD, 0xFF, 0x0F, 0x00, 0xC4, 0xFF, 0x70, 0x00, 0x84, 0xFF,
+ 0x19, 0x00, 0x4D, 0x01, 0x22, 0xFA, 0x70, 0x46, 0x0A, 0x10, 0xFC,
+ 0xF7, 0xEB, 0x04, 0x08, 0xFD, 0x9A, 0x01, 0x4F, 0xFF, 0x2E, 0x00,
+ 0xFF, 0xFF, 0x00, 0x00, 0x27, 0x00, 0x66, 0xFF, 0x5E, 0x01, 0x90,
+ 0xFD, 0xD2, 0x03, 0x47, 0xFA, 0xC3, 0x09, 0x48, 0x48, 0x5A, 0xFE,
+ 0x33, 0xFF, 0x45, 0x01, 0xE2, 0xFE, 0xBE, 0x00, 0xA5, 0xFF, 0x16,
+ 0x00, 0xFE, 0xFF, 0x36, 0x00, 0x36, 0xFF, 0xE3, 0x01, 0x4B, 0xFC,
+ 0xA9, 0x06, 0xD2, 0xF3, 0x81, 0x1E, 0xE4, 0x3E, 0xEF, 0xF3, 0xDE,
+ 0x04, 0xF9, 0xFD, 0xB7, 0x00, 0xD8, 0xFF, 0xFD, 0xFF, 0x03, 0x00,
+ 0xFD, 0xFF, 0x24, 0x00, 0x6D, 0xFF, 0x88, 0x01, 0xA2, 0xFC, 0xD0,
+ 0x06, 0x8C, 0xF1, 0x78, 0x33, 0xF2, 0x2C, 0x9E, 0xF1, 0x24, 0x07,
+ 0x4E, 0xFC, 0xC3, 0x01, 0x4E, 0xFF, 0x2F, 0x00, 0xFD, 0xFF, 0x08,
+ 0x00, 0xE4, 0xFF, 0x1D, 0x00, 0x2D, 0x00, 0xEA, 0xFE, 0x56, 0x03,
+ 0x6D, 0xF6, 0x17, 0x43, 0x70, 0x17, 0xA6, 0xF5, 0xF3, 0x05, 0x91,
+ 0xFC, 0xCC, 0x01, 0x3D, 0xFF, 0x34, 0x00, 0xFE, 0xFF, 0x1E, 0x00,
+ 0x86, 0xFF, 0x0E, 0x01, 0x3B, 0xFE, 0x82, 0x02, 0xE0, 0xFC, 0x73,
+ 0x03, 0xF6, 0x48, 0xE9, 0x03, 0xAD, 0xFC, 0x9C, 0x02, 0x2D, 0xFE,
+ 0x14, 0x01, 0x83, 0xFF, 0x1F, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x33,
+ 0x00, 0x3E, 0xFF, 0xC9, 0x01, 0x99, 0xFC, 0xE1, 0x05, 0xD1, 0xF5,
+ 0xDC, 0x16, 0x65, 0x43, 0xAD, 0xF6, 0x31, 0x03, 0x00, 0xFF, 0x20,
+ 0x00, 0x23, 0x00, 0xE1, 0xFF, 0x08, 0x00, 0xFD, 0xFF, 0x30, 0x00,
+ 0x4C, 0xFF, 0xC7, 0x01, 0x4A, 0xFC, 0x27, 0x07, 0xA8, 0xF1, 0x62,
+ 0x2C, 0xFD, 0x33, 0x93, 0xF1, 0xC4, 0x06, 0xAB, 0xFC, 0x82, 0x01,
+ 0x71, 0xFF, 0x23, 0x00, 0xFE, 0xFF, 0x02, 0x00, 0xFF, 0xFF, 0xD3,
+ 0xFF, 0xC1, 0x00, 0xE7, 0xFD, 0xFA, 0x04, 0xC4, 0xF3, 0x7E, 0x3E,
+ 0x19, 0x1F, 0xB0, 0xF3, 0xB5, 0x06, 0x47, 0xFC, 0xE4, 0x01, 0x36,
+ 0xFF, 0x36, 0x00, 0xFD, 0xFF, 0x15, 0x00, 0xA8, 0xFF, 0xB8, 0x00,
+ 0xF0, 0xFE, 0x2B, 0x01, 0x63, 0xFF, 0xF6, 0xFD, 0x2C, 0x48, 0x47,
+ 0x0A, 0x14, 0xFA, 0xEB, 0x03, 0x84, 0xFD, 0x63, 0x01, 0x64, 0xFF,
+ 0x27, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x2D, 0x00, 0x51, 0xFF, 0x96,
+ 0x01, 0x13, 0xFD, 0xD5, 0x04, 0x2C, 0xF8, 0x7D, 0x0F, 0xA3, 0x46,
+ 0x76, 0xFA, 0x22, 0x01, 0x32, 0x00, 0x76, 0xFF, 0x76, 0x00, 0xC1,
+ 0xFF, 0x0F, 0x00, 0xFD, 0xFF, 0x36, 0x00, 0x3A, 0xFF, 0xE4, 0x01,
+ 0x32, 0xFC, 0x0C, 0x07, 0x91, 0xF2, 0xDD, 0x24, 0x54, 0x3A, 0x74,
+ 0xF2, 0xEB, 0x05, 0x49, 0xFD, 0x20, 0x01, 0xA3, 0xFF, 0x11, 0x00,
+ 0x00, 0x00, 0xFF, 0xFF, 0x16, 0x00, 0x95, 0xFF, 0x3B, 0x01, 0x1B,
+ 0xFD, 0x2D, 0x06, 0x24, 0xF2, 0xD3, 0x38, 0xC6, 0x26, 0x45, 0xF2,
+ 0x1D, 0x07, 0x32, 0xFC, 0xE0, 0x01, 0x3D, 0xFF, 0x35, 0x00, 0xFD,
+ 0xFF, 0x0D, 0x00, 0xC9, 0xFF, 0x61, 0x00, 0xA2, 0xFF, 0xE2, 0xFF,
+ 0xAE, 0x01, 0x6B, 0xF9, 0xF2, 0x45, 0x4A, 0x11, 0x8F, 0xF7, 0x1D,
+ 0x05, 0xF1, 0xFC, 0xA4, 0x01, 0x4B, 0xFF, 0x2F, 0x00, 0xFF, 0xFF,
+ 0x00, 0x00, 0x25, 0x00, 0x6C, 0xFF, 0x51, 0x01, 0xAC, 0xFD, 0x9A,
+ 0x03, 0xBA, 0xFA, 0x9E, 0x08, 0x81, 0x48, 0x40, 0xFF, 0xC6, 0xFE,
+ 0x80, 0x01, 0xC2, 0xFE, 0xCE, 0x00, 0x9F, 0xFF, 0x17, 0x00, 0xFE,
+ 0xFF, 0x36, 0x00, 0x37, 0xFF, 0xE1, 0x01, 0x55, 0xFC, 0x8C, 0x06,
+ 0x22, 0xF4, 0x2C, 0x1D, 0xC0, 0x3F, 0x55, 0xF4, 0x9B, 0x04, 0x23,
+ 0xFE, 0x9F, 0x00, 0xE4, 0xFF, 0xF9, 0xFF, 0x04, 0x00, 0xFD, 0xFF,
+ 0x27, 0x00, 0x66, 0xFF, 0x96, 0x01, 0x8E, 0xFC, 0xE7, 0x06, 0x81,
+ 0xF1, 0x48, 0x32, 0x34, 0x2E, 0x8D, 0xF1, 0x1C, 0x07, 0x5A, 0xFC,
+ 0xBB, 0x01, 0x53, 0xFF, 0x2E, 0x00, 0xFD, 0xFF, 0x07, 0x00, 0xE9,
+ 0xFF, 0x0F, 0x00, 0x48, 0x00, 0xB9, 0xFE, 0xA6, 0x03, 0xE4, 0xF5,
+ 0x60, 0x42, 0xC1, 0x18, 0x47, 0xF5, 0x1A, 0x06, 0x81, 0xFC, 0xD2,
+ 0x01, 0x3B, 0xFF, 0x35, 0x00, 0xFE, 0xFF, 0x1C, 0x00, 0x8B, 0xFF,
+ 0xFF, 0x00, 0x5A, 0xFE, 0x46, 0x02, 0x52, 0xFD, 0x70, 0x02, 0xED,
+ 0x48, 0xF5, 0x04, 0x3B, 0xFC, 0xD7, 0x02, 0x0F, 0xFE, 0x23, 0x01,
+ 0x7E, 0xFF, 0x20, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x33, 0x00, 0x40,
+ 0xFF, 0xC1, 0x01, 0xAB, 0xFC, 0xB7, 0x05, 0x34, 0xF6, 0x8E, 0x15,
+ 0x0B, 0x44, 0x42, 0xF7, 0xDC, 0x02, 0x32, 0xFF, 0x04, 0x00, 0x31,
+ 0x00, 0xDC, 0xFF, 0x09, 0x00, 0xFD, 0xFF, 0x31, 0x00, 0x47, 0xFF,
+ 0xCE, 0x01, 0x41, 0xFC, 0x2A, 0x07, 0xC2, 0xF1, 0x1B, 0x2B, 0x25,
+ 0x35, 0xA8, 0xF1, 0xA7, 0x06, 0xC2, 0xFC, 0x74, 0x01, 0x78, 0xFF,
+ 0x20, 0x00, 0xFE, 0xFF, 0x02, 0x00, 0x04, 0x00, 0xC7, 0xFF, 0xD9,
+ 0x00, 0xBF, 0xFD, 0x38, 0x05, 0x69, 0xF3, 0x96, 0x3D, 0x6F, 0x20,
+ 0x66, 0xF3, 0xCE, 0x06, 0x3F, 0xFC, 0xE6, 0x01, 0x36, 0xFF, 0x36,
+ 0x00, 0xFD, 0xFF, 0x14, 0x00, 0xAE, 0xFF, 0xA9, 0x00, 0x0F, 0xFF,
+ 0xF0, 0x00, 0xCD, 0xFF, 0x1B, 0xFD, 0xE4, 0x47, 0x73, 0x0B, 0xA2,
+ 0xF9, 0x23, 0x04, 0x68, 0xFD, 0x70, 0x01, 0x5F, 0xFF, 0x29, 0x00,
+ 0x00, 0x00, 0xFF, 0xFF, 0x2C, 0x00, 0x55, 0xFF, 0x8B, 0x01, 0x2B,
+ 0xFD, 0xA1, 0x04, 0x9B, 0xF8, 0x42, 0x0E, 0x0F, 0x47, 0x38, 0xFB,
+ 0xBE, 0x00, 0x6A, 0x00, 0x58, 0xFF, 0x85, 0x00, 0xBB, 0xFF, 0x10,
+ 0x00, 0xFD, 0xFF, 0x36, 0x00, 0x38, 0xFF, 0xE6, 0x01, 0x34, 0xFC,
+ 0xFD, 0x06, 0xCB, 0xF2, 0x8A, 0x23, 0x58, 0x3B, 0xB4, 0xF2, 0xBA,
+ 0x05, 0x6A, 0xFD, 0x0B, 0x01, 0xAE, 0xFF, 0x0D, 0x00, 0x00, 0x00,
+ 0xFF, 0xFF, 0x19, 0x00, 0x8C, 0xFF, 0x4D, 0x01, 0xFE, 0xFC, 0x56,
+ 0x06, 0xF7, 0xF1, 0xBF, 0x37, 0x15, 0x28, 0x18, 0xF2, 0x25, 0x07,
+ 0x34, 0xFC, 0xDC, 0x01, 0x3F, 0xFF, 0x34, 0x00, 0xFD, 0xFF, 0x0C,
+ 0x00, 0xCF, 0xFF, 0x52, 0x00, 0xC0, 0xFF, 0xAC, 0xFF, 0x0C, 0x02,
+ 0xBC, 0xF8, 0x6D, 0x45, 0x8E, 0x12, 0x24, 0xF7, 0x4D, 0x05, 0xDB,
+ 0xFC, 0xAE, 0x01, 0x48, 0xFF, 0x30, 0x00, 0xFF, 0xFF, 0x00, 0x00,
+ 0x24, 0x00, 0x71, 0xFF, 0x43, 0x01, 0xC9, 0xFD, 0x60, 0x03, 0x2E,
+ 0xFB, 0x7E, 0x07, 0xAF, 0x48, 0x2D, 0x00, 0x58, 0xFE, 0xBB, 0x01,
+ 0xA3, 0xFE, 0xDD, 0x00, 0x99, 0xFF, 0x19, 0x00, 0xFE, 0xFF, 0x36,
+ 0x00, 0x37, 0xFF, 0xDD, 0x01, 0x60, 0xFC, 0x6D, 0x06, 0x76, 0xF4,
+ 0xD8, 0x1B, 0x95, 0x40, 0xC3, 0xF4, 0x56, 0x04, 0x4E, 0xFE, 0x85,
+ 0x00, 0xF1, 0xFF, 0xF4, 0xFF, 0x04, 0x00, 0xFD, 0xFF, 0x29, 0x00,
+ 0x60, 0xFF, 0xA2, 0x01, 0x7C, 0xFC, 0xFB, 0x06, 0x7C, 0xF1, 0x15,
+ 0x31, 0x73, 0x2F, 0x81, 0xF1, 0x10, 0x07, 0x67, 0xFC, 0xB1, 0x01,
+ 0x58, 0xFF, 0x2C, 0x00, 0xFD, 0xFF, 0x06, 0x00, 0xEE, 0xFF, 0x02,
+ 0x00, 0x63, 0x00, 0x8A, 0xFE, 0xF3, 0x03, 0x63, 0xF5, 0xA1, 0x41,
+ 0x12, 0x1A, 0xEB, 0xF4, 0x3F, 0x06, 0x72, 0xFC, 0xD7, 0x01, 0x39,
+ 0xFF, 0x35, 0x00, 0xFE, 0xFF, 0x1B, 0x00, 0x91, 0xFF, 0xF1, 0x00,
+ 0x79, 0xFE, 0x0A, 0x02, 0xC3, 0xFD, 0x73, 0x01, 0xDB, 0x48, 0x07,
+ 0x06, 0xC7, 0xFB, 0x12, 0x03, 0xF1, 0xFD, 0x31, 0x01, 0x78, 0xFF,
+ 0x22, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x32, 0x00, 0x43, 0xFF, 0xBA,
+ 0x01, 0xBF, 0xFC, 0x8B, 0x05, 0x99, 0xF6, 0x43, 0x14, 0xA9, 0x44,
+ 0xDE, 0xF7, 0x85, 0x02, 0x65, 0xFF, 0xE7, 0xFF, 0x3F, 0x00, 0xD6,
+ 0xFF, 0x0A, 0x00, 0xFD, 0xFF, 0x32, 0x00, 0x44, 0xFF, 0xD5, 0x01,
+ 0x3A, 0xFC, 0x2A, 0x07, 0xE3, 0xF1, 0xD1, 0x29, 0x46, 0x36, 0xC5,
+ 0xF1, 0x87, 0x06, 0xDA, 0xFC, 0x64, 0x01, 0x80, 0xFF, 0x1E, 0x00,
+ 0xFE, 0xFF, 0x01, 0x00, 0x08, 0x00, 0xBC, 0xFF, 0xEF, 0x00, 0x9A,
+ 0xFD, 0x72, 0x05, 0x16, 0xF3, 0xA5, 0x3C, 0xC4, 0x21, 0x21, 0xF3,
+ 0xE4, 0x06, 0x39, 0xFC, 0xE6, 0x01, 0x37, 0xFF, 0x36, 0x00, 0xFD,
+ 0xFF, 0x12, 0x00, 0xB3, 0xFF, 0x99, 0x00, 0x2E, 0xFF, 0xB6, 0x00,
+ 0x36, 0x00, 0x47, 0xFC, 0x90, 0x47, 0xA4, 0x0C, 0x31, 0xF9, 0x5A,
+ 0x04, 0x4E, 0xFD, 0x7C, 0x01, 0x5B, 0xFF, 0x2A, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x2B, 0x00, 0x59, 0xFF, 0x80, 0x01, 0x45, 0xFD, 0x6C,
+ 0x04, 0x0B, 0xF9, 0x0B, 0x0D, 0x73, 0x47, 0x02, 0xFC, 0x58, 0x00,
+ 0xA3, 0x00, 0x39, 0xFF, 0x94, 0x00, 0xB5, 0xFF, 0x12, 0x00, 0xFD,
+ 0xFF, 0x36, 0x00, 0x37, 0xFF, 0xE6, 0x01, 0x37, 0xFC, 0xEB, 0x06,
+ 0x0B, 0xF3, 0x35, 0x22, 0x52, 0x3C, 0xFD, 0xF2, 0x84, 0x05, 0x8D,
+ 0xFD, 0xF6, 0x00, 0xB8, 0xFF, 0x09, 0x00, 0x01, 0x00, 0xFE, 0xFF,
+ 0x1D, 0x00, 0x83, 0xFF, 0x5E, 0x01, 0xE3, 0xFC, 0x7B, 0x06, 0xD0,
+ 0xF1, 0xA5, 0x36, 0x62, 0x29, 0xEF, 0xF1, 0x29, 0x07, 0x39, 0xFC,
+ 0xD7, 0x01, 0x42, 0xFF, 0x33, 0x00, 0xFD, 0xFF, 0x0B, 0x00, 0xD5,
+ 0xFF, 0x44, 0x00, 0xDD, 0xFF, 0x77, 0xFF, 0x67, 0x02, 0x14, 0xF8,
+ 0xDC, 0x44, 0xD5, 0x13, 0xBC, 0xF6, 0x7C, 0x05, 0xC5, 0xFC, 0xB7,
+ 0x01, 0x44, 0xFF, 0x31, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x22, 0x00,
+ 0x76, 0xFF, 0x35, 0x01, 0xE7, 0xFD, 0x26, 0x03, 0xA1, 0xFB, 0x64,
+ 0x06, 0xD2, 0x48, 0x21, 0x01, 0xE8, 0xFD, 0xF7, 0x01, 0x83, 0xFE,
+ 0xEC, 0x00, 0x93, 0xFF, 0x1A, 0x00, 0xFE, 0xFF, 0x35, 0x00, 0x39,
+ 0xFF, 0xD9, 0x01, 0x6D, 0xFC, 0x4B, 0x06, 0xCD, 0xF4, 0x83, 0x1A,
+ 0x5F, 0x41, 0x3A, 0xF5, 0x0C, 0x04, 0x7B, 0xFE, 0x6C, 0x00, 0xFE,
+ 0xFF, 0xEF, 0xFF, 0x05, 0x00, 0xFD, 0xFF, 0x2B, 0x00, 0x5A, 0xFF,
+ 0xAD, 0x01, 0x6C, 0xFC, 0x0C, 0x07, 0x7F, 0xF1, 0xDC, 0x2F, 0xAD,
+ 0x30, 0x7D, 0xF1, 0x01, 0x07, 0x76, 0xFC, 0xA6, 0x01, 0x5E, 0xFF,
+ 0x2A, 0x00, 0xFD, 0xFF, 0x05, 0x00, 0xF3, 0xFF, 0xF5, 0xFF, 0x7D,
+ 0x00, 0x5D, 0xFE, 0x3E, 0x04, 0xEA, 0xF4, 0xD9, 0x40, 0x66, 0x1B,
+ 0x93, 0xF4, 0x62, 0x06, 0x64, 0xFC, 0xDC, 0x01, 0x38, 0xFF, 0x36,
+ 0x00, 0xFE, 0xFF, 0x19, 0x00, 0x97, 0xFF, 0xE2, 0x00, 0x98, 0xFE,
+ 0xCF, 0x01, 0x33, 0xFE, 0x7D, 0x00, 0xBB, 0x48, 0x1F, 0x07, 0x54,
+ 0xFB, 0x4C, 0x03, 0xD3, 0xFD, 0x3F, 0x01, 0x73, 0xFF, 0x23, 0x00,
+ 0x00, 0x00, 0xFF, 0xFF, 0x31, 0x00, 0x46, 0xFF, 0xB1, 0x01, 0xD3,
+ 0xFC, 0x5D, 0x05, 0x01, 0xF7, 0xFB, 0x12, 0x3F, 0x45, 0x83, 0xF8,
+ 0x2A, 0x02, 0x9A, 0xFF, 0xCA, 0xFF, 0x4E, 0x00, 0xD1, 0xFF, 0x0C,
+ 0x00, 0xFD, 0xFF, 0x34, 0x00, 0x40, 0xFF, 0xDA, 0x01, 0x35, 0xFC,
+ 0x27, 0x07, 0x09, 0xF2, 0x85, 0x28, 0x63, 0x37, 0xE9, 0xF1, 0x63,
+ 0x06, 0xF5, 0xFC, 0x53, 0x01, 0x89, 0xFF, 0x1A, 0x00, 0xFE, 0xFF,
+ 0x00, 0x00, 0x0C, 0x00, 0xB1, 0xFF, 0x04, 0x01, 0x76, 0xFD, 0xA8,
+ 0x05, 0xCC, 0xF2, 0xAB, 0x3B, 0x18, 0x23, 0xE0, 0xF2, 0xF7, 0x06,
+ 0x35, 0xFC, 0xE6, 0x01, 0x38, 0xFF, 0x36, 0x00, 0xFD, 0xFF, 0x11,
+ 0x00, 0xB9, 0xFF, 0x8A, 0x00, 0x4D, 0xFF, 0x7D, 0x00, 0x9C, 0x00,
+ 0x7B, 0xFB, 0x31, 0x47, 0xD9, 0x0D, 0xC0, 0xF8, 0x8F, 0x04, 0x34,
+ 0xFD, 0x87, 0x01, 0x56, 0xFF, 0x2C, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x29, 0x00, 0x5E, 0xFF, 0x74, 0x01, 0x5F, 0xFD, 0x35, 0x04, 0x7C,
+ 0xF9, 0xD8, 0x0B, 0xC9, 0x47, 0xD4, 0xFC, 0xF0, 0xFF, 0xDD, 0x00,
+ 0x19, 0xFF, 0xA4, 0x00, 0xAF, 0xFF, 0x13, 0x00, 0xFD, 0xFF, 0x36,
+ 0x00, 0x36, 0xFF, 0xE6, 0x01, 0x3D, 0xFC, 0xD5, 0x06, 0x4F, 0xF3,
+ 0xE0, 0x20, 0x45, 0x3D, 0x4D, 0xF3, 0x4B, 0x05, 0xB3, 0xFD, 0xE0,
+ 0x00, 0xC3, 0xFF, 0x05, 0x00, 0x02, 0x00, 0xFE, 0xFF, 0x20, 0x00,
+ 0x7B, 0xFF, 0x6E, 0x01, 0xCA, 0xFC, 0x9D, 0x06, 0xB1, 0xF1, 0x86,
+ 0x35, 0xAE, 0x2A, 0xCD, 0xF1, 0x2B, 0x07, 0x3F, 0xFC, 0xD1, 0x01,
+ 0x46, 0xFF, 0x32, 0x00, 0xFD, 0xFF, 0x0A, 0x00, 0xDA, 0xFF, 0x36,
+ 0x00, 0xFA, 0xFF, 0x43, 0xFF, 0xBF, 0x02, 0x75, 0xF7, 0x42, 0x44,
+ 0x20, 0x15, 0x55, 0xF6, 0xA9, 0x05, 0xB2, 0xFC, 0xBF, 0x01, 0x41,
+ 0xFF, 0x32, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x21, 0x00, 0x7C, 0xFF,
+ 0x27, 0x01, 0x05, 0xFE, 0xEB, 0x02, 0x14, 0xFC, 0x50, 0x05, 0xEA,
+ 0x48, 0x1B, 0x02, 0x78, 0xFD, 0x32, 0x02, 0x64, 0xFE, 0xFA, 0x00,
+ 0x8D, 0xFF, 0x1C, 0x00, 0xFE, 0xFF, 0x35, 0x00, 0x3A, 0xFF, 0xD4,
+ 0x01, 0x7C, 0xFC, 0x27, 0x06, 0x28, 0xF5, 0x31, 0x19, 0x21, 0x42,
+ 0xB8, 0xF5, 0xC0, 0x03, 0xAA, 0xFE, 0x51, 0x00, 0x0B, 0x00, 0xEA,
+ 0xFF, 0x06, 0x00, 0xFD, 0xFF, 0x2D, 0x00, 0x54, 0xFF, 0xB7, 0x01,
+ 0x5E, 0xFC, 0x19, 0x07, 0x88, 0xF1, 0x9F, 0x2E, 0xE3, 0x31, 0x7E,
+ 0xF1, 0xEE, 0x06, 0x88, 0xFC, 0x9A, 0x01, 0x64, 0xFF, 0x28, 0x00,
+ 0xFD, 0xFF, 0x04, 0x00, 0xF7, 0xFF, 0xE8, 0xFF, 0x96, 0x00, 0x31,
+ 0xFE, 0x84, 0x04, 0x79, 0xF4, 0x07, 0x40, 0xBA, 0x1C, 0x3E, 0xF4,
+ 0x82, 0x06, 0x58, 0xFC, 0xE0, 0x01, 0x37, 0xFF, 0x36, 0x00, 0xFE,
+ 0xFF, 0x18, 0x00, 0x9D, 0xFF, 0xD3, 0x00, 0xB8, 0xFE, 0x93, 0x01,
+ 0xA1, 0xFE, 0x8E, 0xFF, 0x92, 0x48, 0x3D, 0x08, 0xE1, 0xFA, 0x86,
+ 0x03, 0xB6, 0xFD, 0x4C, 0x01, 0x6D, 0xFF, 0x25, 0x00, 0x00, 0x00,
+ 0xFF, 0xFF, 0x30, 0x00, 0x4A, 0xFF, 0xA8, 0x01, 0xE9, 0xFC, 0x2D,
+ 0x05, 0x6B, 0xF7, 0xB6, 0x11, 0xC8, 0x45, 0x30, 0xF9, 0xCD, 0x01,
+ 0xD0, 0xFF, 0xAC, 0xFF, 0x5C, 0x00, 0xCB, 0xFF, 0x0D, 0x00, 0xFD,
+ 0xFF, 0x34, 0x00, 0x3E, 0xFF, 0xDF, 0x01, 0x33, 0xFC, 0x20, 0x07,
+ 0x35, 0xF2, 0x36, 0x27, 0x78, 0x38, 0x14, 0xF2, 0x3B, 0x06, 0x11,
+ 0xFD, 0x41, 0x01, 0x92, 0xFF, 0x17, 0x00, 0xFF, 0xFF, 0x00, 0x00,
+ 0x10, 0x00, 0xA7, 0xFF, 0x19, 0x01, 0x53, 0xFD, 0xDB, 0x05, 0x88,
+ 0xF2, 0xAD, 0x3A, 0x6D, 0x24, 0xA4, 0xF2, 0x08, 0x07, 0x32, 0xFC,
+ 0xE5, 0x01, 0x39, 0xFF, 0x36, 0x00, 0xFD, 0xFF, 0x10, 0x00, 0xBF,
+ 0xFF, 0x7B, 0x00, 0x6C, 0xFF, 0x44, 0x00, 0x01, 0x01, 0xB6, 0xFA,
+ 0xC8, 0x46, 0x13, 0x0F, 0x51, 0xF8, 0xC4, 0x04, 0x1B, 0xFD, 0x92,
+ 0x01, 0x52, 0xFF, 0x2D, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x28, 0x00,
+ 0x63, 0xFF, 0x67, 0x01, 0x7A, 0xFD, 0xFE, 0x03, 0xEE, 0xF9, 0xAA,
+ 0x0A, 0x16, 0x48, 0xAC, 0xFD, 0x86, 0xFF, 0x17, 0x01, 0xFA, 0xFE,
+ 0xB3, 0x00, 0xAA, 0xFF, 0x15, 0x00, 0xFD, 0xFF, 0x36, 0x00, 0x36,
+ 0xFF, 0xE5, 0x01, 0x44, 0xFC, 0xBD, 0x06, 0x97, 0xF3, 0x8A, 0x1F,
+ 0x31, 0x3E, 0xA5, 0xF3, 0x0F, 0x05, 0xDA, 0xFD, 0xC9, 0x00, 0xCF,
+ 0xFF, 0x01, 0x00, 0x02, 0x00, 0xFE, 0xFF, 0x22, 0x00, 0x73, 0xFF,
+ 0x7D, 0x01, 0xB3, 0xFC, 0xBB, 0x06, 0x9A, 0xF1, 0x60, 0x34, 0xF5,
+ 0x2B, 0xB0, 0xF1, 0x28, 0x07, 0x47, 0xFC, 0xCA, 0x01, 0x4A, 0xFF,
+ 0x30, 0x00, 0xFD, 0xFF, 0x09, 0x00, 0xDF, 0xFF, 0x28, 0x00, 0x17,
+ 0x00, 0x10, 0xFF, 0x15, 0x03, 0xDD, 0xF6, 0x9E, 0x43, 0x6C, 0x16,
+ 0xF1, 0xF5, 0xD3, 0x05, 0x9F, 0xFC, 0xC6, 0x01, 0x3F, 0xFF, 0x33,
+ 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x1F, 0x00, 0x81, 0xFF, 0x19, 0x01,
+ 0x23, 0xFE, 0xB0, 0x02, 0x87, 0xFC, 0x41, 0x04, 0xF4, 0x48, 0x1C,
+ 0x03, 0x06, 0xFD, 0x6E, 0x02, 0x45, 0xFE, 0x09, 0x01, 0x88, 0xFF,
+ 0x1D, 0x00, 0xFE, 0xFF, 0x34, 0x00, 0x3C, 0xFF, 0xCE, 0x01, 0x8C,
+ 0xFC, 0x00, 0x06, 0x86, 0xF5, 0xE0, 0x17, 0xDB, 0x42, 0x3F, 0xF6,
+ 0x71, 0x03, 0xD9, 0xFE, 0x36, 0x00, 0x18, 0x00, 0xE5, 0xFF, 0x07,
+ 0x00, 0xFD, 0xFF, 0x2F, 0x00, 0x4F, 0xFF, 0xC1, 0x01, 0x52, 0xFC,
+ 0x22, 0x07, 0x98, 0xF1, 0x5E, 0x2D, 0x13, 0x33, 0x87, 0xF1, 0xD8,
+ 0x06, 0x9B, 0xFC, 0x8D, 0x01, 0x6B, 0xFF, 0x25, 0x00, 0xFD, 0xFF,
+ 0x03, 0x00, 0xFC, 0xFF, 0xDC, 0xFF, 0xAF, 0x00, 0x07, 0xFE, 0xC8,
+ 0x04, 0x10, 0xF4, 0x2D, 0x3F, 0x0F, 0x1E, 0xED, 0xF3, 0xA0, 0x06,
+ 0x4E, 0xFC, 0xE3, 0x01, 0x36, 0xFF, 0x36, 0x00, 0xFE, 0xFF, 0x16,
+ 0x00, 0xA3, 0xFF, 0xC3, 0x00, 0xD7, 0xFE, 0x58, 0x01, 0x0F, 0xFF,
+ 0xA6, 0xFE, 0x5D, 0x48, 0x61, 0x09, 0x6E, 0xFA, 0xC0, 0x03, 0x99,
+ 0xFD, 0x59, 0x01, 0x68, 0xFF, 0x26, 0x00, 0x00, 0x00, 0xFF, 0xFF,
+ 0x2E, 0x00, 0x4E, 0xFF, 0x9E, 0x01, 0x00, 0xFD, 0xFC, 0x04, 0xD7,
+ 0xF7, 0x75, 0x10, 0x48, 0x46, 0xE4, 0xF9, 0x6E, 0x01, 0x06, 0x00,
+ 0x8E, 0xFF, 0x6B, 0x00, 0xC6, 0xFF, 0x0E, 0x00, 0xFD, 0xFF, 0x35,
+ 0x00, 0x3B, 0xFF, 0xE2, 0x01, 0x31, 0xFC, 0x16, 0x07, 0x67, 0xF2,
+ 0xE5, 0x25, 0x87, 0x39, 0x47, 0xF2, 0x10, 0x06, 0x30, 0xFD, 0x2F,
+ 0x01, 0x9C, 0xFF, 0x14, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x13, 0x00,
+ 0x9D, 0xFF, 0x2D, 0x01, 0x33, 0xFD, 0x0B, 0x06, 0x4D, 0xF2, 0xA5,
+ 0x39, 0xBF, 0x25, 0x6D, 0xF2, 0x15, 0x07, 0x31, 0xFC, 0xE2, 0x01,
+ 0x3B, 0xFF, 0x35, 0x00, 0xFD, 0xFF, 0x0E, 0x00, 0xC5, 0xFF, 0x6D,
+ 0x00, 0x8B, 0xFF, 0x0D, 0x00, 0x63, 0x01, 0xF9, 0xF9, 0x55, 0x46,
+ 0x51, 0x10, 0xE3, 0xF7, 0xF7, 0x04, 0x03, 0xFD, 0x9D, 0x01, 0x4E,
+ 0xFF, 0x2E, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x26, 0x00, 0x68, 0xFF,
+ 0x5B, 0x01, 0x96, 0xFD, 0xC6, 0x03, 0x61, 0xFA, 0x81, 0x09, 0x57,
+ 0x48, 0x8D, 0xFE, 0x1B, 0xFF, 0x52, 0x01, 0xDB, 0xFE, 0xC2, 0x00,
+ 0xA4, 0xFF, 0x16, 0x00, 0xFE, 0xFF, 0x36, 0x00, 0x36, 0xFF, 0xE3,
+ 0x01, 0x4D, 0xFC, 0xA3, 0x06, 0xE4, 0xF3, 0x36, 0x1E, 0x16, 0x3F,
+ 0x05, 0xF4, 0xCF, 0x04, 0x02, 0xFE, 0xB2, 0x00, 0xDB, 0xFF, 0xFC,
+ 0xFF, 0x03, 0x00, 0xFD, 0xFF, 0x25, 0x00, 0x6C, 0xFF, 0x8B, 0x01,
+ 0x9D, 0xFC, 0xD5, 0x06, 0x89, 0xF1, 0x35, 0x33, 0x3A, 0x2D, 0x9A,
+ 0xF1, 0x23, 0x07, 0x51, 0xFC, 0xC2, 0x01, 0x4F, 0xFF, 0x2F, 0x00,
+ 0xFD, 0xFF, 0x07, 0x00, 0xE5, 0xFF, 0x1A, 0x00, 0x33, 0x00, 0xDF,
+ 0xFE, 0x68, 0x03, 0x4E, 0xF6, 0xEE, 0x42, 0xBB, 0x17, 0x90, 0xF5,
+ 0xFC, 0x05, 0x8E, 0xFC, 0xCD, 0x01, 0x3C, 0xFF, 0x34, 0x00, 0xFE,
+ 0xFF, 0x1E, 0x00, 0x87, 0xFF, 0x0B, 0x01, 0x42, 0xFE, 0x74, 0x02,
+ 0xF9, 0xFC, 0x39, 0x03, 0xF5, 0x48, 0x24, 0x04, 0x94, 0xFC, 0xA9,
+ 0x02, 0x27, 0xFE, 0x18, 0x01, 0x82, 0xFF, 0x1F, 0x00, 0x00, 0x00,
+ 0xFF, 0xFF, 0x33, 0x00, 0x3E, 0xFF, 0xC7, 0x01, 0x9D, 0xFC, 0xD8,
+ 0x05, 0xE7, 0xF5, 0x91, 0x16, 0x89, 0x43, 0xCD, 0xF6, 0x1E, 0x03,
+ 0x0B, 0xFF, 0x1A, 0x00, 0x26, 0x00, 0xE0, 0xFF, 0x08, 0x00, 0xFD,
+ 0xFF, 0x30, 0x00, 0x4B, 0xFF, 0xC9, 0x01, 0x48, 0xFC, 0x28, 0x07,
+ 0xAD, 0xF1, 0x19, 0x2C, 0x3F, 0x34, 0x97, 0xF1, 0xBE, 0x06, 0xB0,
+ 0xFC, 0x7F, 0x01, 0x72, 0xFF, 0x23, 0x00, 0xFE, 0xFF, 0x02, 0x00,
+ 0x00, 0x00, 0xD0, 0xFF, 0xC7, 0x00, 0xDE, 0xFD, 0x08, 0x05, 0xB0,
+ 0xF3, 0x4A, 0x3E, 0x64, 0x1F, 0xA0, 0xF3, 0xBB, 0x06, 0x45, 0xFC,
+ 0xE5, 0x01, 0x36, 0xFF, 0x36, 0x00, 0xFD, 0xFF, 0x15, 0x00, 0xA9,
+ 0xFF, 0xB4, 0x00, 0xF7, 0xFE, 0x1D, 0x01, 0x7A, 0xFF, 0xC5, 0xFD,
+ 0x1D, 0x48, 0x89, 0x0A, 0xFB, 0xF9, 0xF8, 0x03, 0x7D, 0xFD, 0x66,
+ 0x01, 0x63, 0xFF, 0x28, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x2D, 0x00,
+ 0x52, 0xFF, 0x93, 0x01, 0x18, 0xFD, 0xC9, 0x04, 0x45, 0xF8, 0x36,
+ 0x0F, 0xBB, 0x46, 0xA1, 0xFA, 0x0C, 0x01, 0x3E, 0x00, 0x70, 0xFF,
+ 0x7A, 0x00, 0xC0, 0xFF, 0x0F, 0x00, 0xFD, 0xFF, 0x36, 0x00, 0x39,
+ 0xFF, 0xE4, 0x01, 0x32, 0xFC, 0x09, 0x07, 0x9D, 0xF2, 0x92, 0x24,
+ 0x8F, 0x3A, 0x82, 0xF2, 0xE1, 0x05, 0x50, 0xFD, 0x1B, 0x01, 0xA6,
+ 0xFF, 0x10, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x17, 0x00, 0x93, 0xFF,
+ 0x3F, 0x01, 0x15, 0xFD, 0x36, 0x06, 0x19, 0xF2, 0x97, 0x38, 0x11,
+ 0x27, 0x3B, 0xF2, 0x1F, 0x07, 0x32, 0xFC, 0xDF, 0x01, 0x3D, 0xFF,
+ 0x34, 0x00, 0xFD, 0xFF, 0x0D, 0x00, 0xCB, 0xFF, 0x5E, 0x00, 0xA9,
+ 0xFF, 0xD6, 0xFF, 0xC3, 0x01, 0x43, 0xF9, 0xD7, 0x45, 0x92, 0x11,
+ 0x77, 0xF7, 0x28, 0x05, 0xEC, 0xFC, 0xA7, 0x01, 0x4A, 0xFF, 0x2F,
+ 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x25, 0x00, 0x6D, 0xFF, 0x4E, 0x01,
+ 0xB3, 0xFD, 0x8D, 0x03, 0xD4, 0xFA, 0x5D, 0x08, 0x8D, 0x48, 0x74,
+ 0xFF, 0xAE, 0xFE, 0x8D, 0x01, 0xBB, 0xFE, 0xD1, 0x00, 0x9E, 0xFF,
+ 0x18, 0x00, 0xFE, 0xFF, 0x36, 0x00, 0x37, 0xFF, 0xE0, 0x01, 0x57,
+ 0xFC, 0x85, 0x06, 0x34, 0xF4, 0xE0, 0x1C, 0xF0, 0x3F, 0x6D, 0xF4,
+ 0x8C, 0x04, 0x2C, 0xFE, 0x99, 0x00, 0xE7, 0xFF, 0xF8, 0xFF, 0x04,
+ 0x00, 0xFD, 0xFF, 0x27, 0x00, 0x65, 0xFF, 0x98, 0x01, 0x8A, 0xFC,
+ 0xEC, 0x06, 0x7F, 0xF1, 0x04, 0x32, 0x7B, 0x2E, 0x8A, 0xF1, 0x1A,
+ 0x07, 0x5D, 0xFC, 0xB8, 0x01, 0x54, 0xFF, 0x2D, 0x00, 0xFD, 0xFF,
+ 0x06, 0x00, 0xEA, 0xFF, 0x0C, 0x00, 0x4E, 0x00, 0xAF, 0xFE, 0xB8,
+ 0x03, 0xC7, 0xF5, 0x38, 0x42, 0x0C, 0x19, 0x32, 0xF5, 0x23, 0x06,
+ 0x7D, 0xFC, 0xD3, 0x01, 0x3A, 0xFF, 0x35, 0x00, 0xFE, 0xFF, 0x1C,
+ 0x00, 0x8D, 0xFF, 0xFC, 0x00, 0x61, 0xFE, 0x39, 0x02, 0x6B, 0xFD,
+ 0x37, 0x02, 0xEB, 0x48, 0x31, 0x05, 0x21, 0xFC, 0xE4, 0x02, 0x08,
+ 0xFE, 0x26, 0x01, 0x7C, 0xFF, 0x21, 0x00, 0x00, 0x00, 0xFF, 0xFF,
+ 0x32, 0x00, 0x41, 0xFF, 0xC0, 0x01, 0xAF, 0xFC, 0xAD, 0x05, 0x4A,
+ 0xF6, 0x44, 0x15, 0x2F, 0x44, 0x64, 0xF7, 0xC9, 0x02, 0x3D, 0xFF,
+ 0xFE, 0xFF, 0x34, 0x00, 0xDB, 0xFF, 0x09, 0x00, 0xFD, 0xFF, 0x32,
+ 0x00, 0x47, 0xFF, 0xD0, 0x01, 0x40, 0xFC, 0x2A, 0x07, 0xCA, 0xF1,
+ 0xD1, 0x2A, 0x65, 0x35, 0xAE, 0xF1, 0xA0, 0x06, 0xC7, 0xFC, 0x70,
+ 0x01, 0x7A, 0xFF, 0x20, 0x00, 0xFE, 0xFF, 0x02, 0x00, 0x05, 0x00,
+ 0xC5, 0xFF, 0xDE, 0x00, 0xB7, 0xFD, 0x45, 0x05, 0x56, 0xF3, 0x61,
+ 0x3D, 0xBA, 0x20, 0x56, 0xF3, 0xD3, 0x06, 0x3E, 0xFC, 0xE6, 0x01,
+ 0x36, 0xFF, 0x36, 0x00, 0xFD, 0xFF, 0x13, 0x00, 0xAF, 0xFF, 0xA5,
+ 0x00, 0x16, 0xFF, 0xE3, 0x00, 0xE4, 0xFF, 0xEB, 0xFC, 0xD2, 0x47,
+ 0xB6, 0x0B, 0x89, 0xF9, 0x2F, 0x04, 0x62, 0xFD, 0x72, 0x01, 0x5E,
+ 0xFF, 0x29, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x2C, 0x00, 0x56, 0xFF,
+ 0x88, 0x01, 0x31, 0xFD, 0x95, 0x04, 0xB4, 0xF8, 0xFC, 0x0D, 0x26,
+ 0x47, 0x64, 0xFB, 0xA7, 0x00, 0x77, 0x00, 0x51, 0xFF, 0x89, 0x00,
+ 0xBA, 0xFF, 0x11, 0x00, 0xFD, 0xFF, 0x36, 0x00, 0x38, 0xFF, 0xE6,
+ 0x01, 0x34, 0xFC, 0xF9, 0x06, 0xD9, 0xF2, 0x3F, 0x23, 0x90, 0x3B,
+ 0xC4, 0xF2, 0xAE, 0x05, 0x72, 0xFD, 0x07, 0x01, 0xB0, 0xFF, 0x0C,
+ 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x1A, 0x00, 0x8A, 0xFF, 0x51, 0x01,
+ 0xF8, 0xFC, 0x5E, 0x06, 0xED, 0xF1, 0x82, 0x37, 0x60, 0x28, 0x0E,
+ 0xF2, 0x26, 0x07, 0x35, 0xFC, 0xDB, 0x01, 0x40, 0xFF, 0x34, 0x00,
+ 0xFD, 0xFF, 0x0C, 0x00, 0xD0, 0xFF, 0x4F, 0x00, 0xC7, 0xFF, 0xA0,
+ 0xFF, 0x20, 0x02, 0x96, 0xF8, 0x4E, 0x45, 0xD7, 0x12, 0x0D, 0xF7,
+ 0x58, 0x05, 0xD6, 0xFC, 0xB0, 0x01, 0x47, 0xFF, 0x30, 0x00, 0xFF,
+ 0xFF, 0x00, 0x00, 0x23, 0x00, 0x72, 0xFF, 0x40, 0x01, 0xD0, 0xFD,
+ 0x53, 0x03, 0x47, 0xFB, 0x3F, 0x07, 0xB8, 0x48, 0x62, 0x00, 0x3F,
+ 0xFE, 0xC8, 0x01, 0x9C, 0xFE, 0xE0, 0x00, 0x98, 0xFF, 0x19, 0x00,
+ 0xFE, 0xFF, 0x36, 0x00, 0x38, 0xFF, 0xDC, 0x01, 0x63, 0xFC, 0x66,
+ 0x06, 0x89, 0xF4, 0x8C, 0x1B, 0xC3, 0x40, 0xDD, 0xF4, 0x46, 0x04,
+ 0x58, 0xFE, 0x80, 0x00, 0xF4, 0xFF, 0xF3, 0xFF, 0x05, 0x00, 0xFD,
+ 0xFF, 0x29, 0x00, 0x5F, 0xFF, 0xA5, 0x01, 0x78, 0xFC, 0xFF, 0x06,
+ 0x7D, 0xF1, 0xCF, 0x30, 0xB8, 0x2F, 0x80, 0xF1, 0x0D, 0x07, 0x6A,
+ 0xFC, 0xAE, 0x01, 0x59, 0xFF, 0x2B, 0x00, 0xFD, 0xFF, 0x05, 0x00,
+ 0xEF, 0xFF, 0xFF, 0xFF, 0x69, 0x00, 0x80, 0xFE, 0x04, 0x04, 0x48,
+ 0xF5, 0x74, 0x41, 0x5D, 0x1A, 0xD7, 0xF4, 0x47, 0x06, 0x6F, 0xFC,
+ 0xD8, 0x01, 0x39, 0xFF, 0x35, 0x00, 0xFE, 0xFF, 0x1B, 0x00, 0x93,
+ 0xFF, 0xED, 0x00, 0x80, 0xFE, 0xFD, 0x01, 0xDC, 0xFD, 0x3C, 0x01,
+ 0xD5, 0x48, 0x45, 0x06, 0xAE, 0xFB, 0x1F, 0x03, 0xEA, 0xFD, 0x34,
+ 0x01, 0x77, 0xFF, 0x22, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x31, 0x00,
+ 0x44, 0xFF, 0xB8, 0x01, 0xC3, 0xFC, 0x81, 0x05, 0xB0, 0xF6, 0xFA,
+ 0x13, 0xCC, 0x44, 0x02, 0xF8, 0x71, 0x02, 0x71, 0xFF, 0xE1, 0xFF,
+ 0x42, 0x00, 0xD5, 0xFF, 0x0B, 0x00, 0xFD, 0xFF, 0x33, 0x00, 0x43,
+ 0xFF, 0xD6, 0x01, 0x39, 0xFC, 0x2A, 0x07, 0xEB, 0xF1, 0x87, 0x29,
+ 0x85, 0x36, 0xCC, 0xF1, 0x7F, 0x06, 0xE0, 0xFC, 0x60, 0x01, 0x82,
+ 0xFF, 0x1D, 0x00, 0xFE, 0xFF, 0x01, 0x00, 0x09, 0x00, 0xBA, 0xFF,
+ 0xF4, 0x00, 0x91, 0xFD, 0x7E, 0x05, 0x05, 0xF3, 0x6E, 0x3C, 0x10,
+ 0x22, 0x12, 0xF3, 0xE9, 0x06, 0x38, 0xFC, 0xE6, 0x01, 0x37, 0xFF,
+ 0x36, 0x00, 0xFD, 0xFF, 0x12, 0x00, 0xB5, 0xFF, 0x96, 0x00, 0x35,
+ 0xFF, 0xA9, 0x00, 0x4D, 0x00, 0x19, 0xFC, 0x7C, 0x47, 0xE8, 0x0C,
+ 0x18, 0xF9, 0x66, 0x04, 0x48, 0xFD, 0x7E, 0x01, 0x5A, 0xFF, 0x2B,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x2A, 0x00, 0x5A, 0xFF, 0x7D, 0x01,
+ 0x4B, 0xFD, 0x60, 0x04, 0x24, 0xF9, 0xC6, 0x0C, 0x86, 0x47, 0x30,
+ 0xFC, 0x41, 0x00, 0xB0, 0x00, 0x32, 0xFF, 0x98, 0x00, 0xB4, 0xFF,
+ 0x12, 0x00, 0xFD, 0xFF, 0x36, 0x00, 0x37, 0xFF, 0xE6, 0x01, 0x38,
+ 0xFC, 0xE6, 0x06, 0x19, 0xF3, 0xEA, 0x21, 0x8A, 0x3C, 0x0E, 0xF3,
+ 0x78, 0x05, 0x96, 0xFD, 0xF1, 0x00, 0xBB, 0xFF, 0x08, 0x00, 0x01,
+ 0x00, 0xFE, 0xFF, 0x1D, 0x00, 0x81, 0xFF, 0x62, 0x01, 0xDD, 0xFC,
+ 0x83, 0x06, 0xC9, 0xF1, 0x66, 0x36, 0xAC, 0x29, 0xE7, 0xF1, 0x2A,
+ 0x07, 0x3A, 0xFC, 0xD5, 0x01, 0x43, 0xFF, 0x33, 0x00, 0xFD, 0xFF,
+ 0x0B, 0x00, 0xD6, 0xFF, 0x41, 0x00, 0xE4, 0xFF, 0x6B, 0xFF, 0x7B,
+ 0x02, 0xF0, 0xF7, 0xBA, 0x44, 0x1E, 0x14, 0xA5, 0xF6, 0x86, 0x05,
+ 0xC1, 0xFC, 0xB9, 0x01, 0x44, 0xFF, 0x32, 0x00, 0xFF, 0xFF, 0x00,
+ 0x00, 0x22, 0x00, 0x77, 0xFF, 0x32, 0x01, 0xED, 0xFD, 0x19, 0x03,
+ 0xBB, 0xFB, 0x26, 0x06, 0xD7, 0x48, 0x58, 0x01, 0xCF, 0xFD, 0x04,
+ 0x02, 0x7D, 0xFE, 0xEF, 0x00, 0x92, 0xFF, 0x1B, 0x00, 0xFE, 0xFF,
+ 0x35, 0x00, 0x39, 0xFF, 0xD8, 0x01, 0x70, 0xFC, 0x43, 0x06, 0xE1,
+ 0xF4, 0x38, 0x1A, 0x8C, 0x41, 0x55, 0xF5, 0xFC, 0x03, 0x85, 0xFE,
+ 0x66, 0x00, 0x01, 0x00, 0xEE, 0xFF, 0x06, 0x00, 0xFD, 0xFF, 0x2B,
+ 0x00, 0x59, 0xFF, 0xB0, 0x01, 0x69, 0xFC, 0x0F, 0x07, 0x80, 0xF1,
+ 0x96, 0x2F, 0xF2, 0x30, 0x7C, 0xF1, 0xFD, 0x06, 0x7A, 0xFC, 0xA3,
+ 0x01, 0x5F, 0xFF, 0x29, 0x00, 0xFD, 0xFF, 0x05, 0x00, 0xF4, 0xFF,
+ 0xF2, 0xFF, 0x83, 0x00, 0x53, 0xFE, 0x4E, 0x04, 0xD0, 0xF4, 0xAB,
+ 0x40, 0xB2, 0x1B, 0x7F, 0xF4, 0x69, 0x06, 0x62, 0xFC, 0xDD, 0x01,
+ 0x38, 0xFF, 0x36, 0x00, 0xFE, 0xFF, 0x19, 0x00, 0x98, 0xFF, 0xDE,
+ 0x00, 0x9F, 0xFE, 0xC2, 0x01, 0x4B, 0xFE, 0x48, 0x00, 0xB3, 0x48,
+ 0x5E, 0x07, 0x3B, 0xFB, 0x59, 0x03, 0xCD, 0xFD, 0x42, 0x01, 0x71,
+ 0xFF, 0x24, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x30, 0x00, 0x47, 0xFF,
+ 0xAF, 0x01, 0xD8, 0xFC, 0x52, 0x05, 0x19, 0xF7, 0xB2, 0x12, 0x5C,
+ 0x45, 0xA9, 0xF8, 0x16, 0x02, 0xA6, 0xFF, 0xC3, 0xFF, 0x51, 0x00,
+ 0xD0, 0xFF, 0x0C, 0x00, 0xFD, 0xFF, 0x34, 0x00, 0x40, 0xFF, 0xDB,
+ 0x01, 0x35, 0xFC, 0x25, 0x07, 0x13, 0xF2, 0x3A, 0x28, 0xA0, 0x37,
+ 0xF2, 0xF1, 0x5A, 0x06, 0xFB, 0xFC, 0x4F, 0x01, 0x8B, 0xFF, 0x1A,
+ 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x0D, 0x00, 0xAF, 0xFF, 0x09, 0x01,
+ 0x6E, 0xFD, 0xB4, 0x05, 0xBC, 0xF2, 0x73, 0x3B, 0x64, 0x23, 0xD2,
+ 0xF2, 0xFB, 0x06, 0x34, 0xFC, 0xE6, 0x01, 0x38, 0xFF, 0x36, 0x00,
+ 0xFD, 0xFF, 0x11, 0x00, 0xBB, 0xFF, 0x87, 0x00, 0x54, 0xFF, 0x70,
+ 0x00, 0xB3, 0x00, 0x4E, 0xFB, 0x1A, 0x47, 0x1F, 0x0E, 0xA8, 0xF8,
+ 0x9B, 0x04, 0x2E, 0xFD, 0x8A, 0x01, 0x55, 0xFF, 0x2C, 0x00, 0xFF,
+ 0xFF, 0x00, 0x00, 0x29, 0x00, 0x5F, 0xFF, 0x71, 0x01, 0x65, 0xFD,
+ 0x29, 0x04, 0x96, 0xF9, 0x95, 0x0B, 0xDC, 0x47, 0x03, 0xFD, 0xD9,
+ 0xFF, 0xEA, 0x00, 0x12, 0xFF, 0xA7, 0x00, 0xAE, 0xFF, 0x14, 0x00,
+ 0xFD, 0xFF, 0x36, 0x00, 0x36, 0xFF, 0xE6, 0x01, 0x3E, 0xFC, 0xD0,
+ 0x06, 0x5E, 0xF3, 0x94, 0x20, 0x7B, 0x3D, 0x60, 0xF3, 0x3E, 0x05,
+ 0xBB, 0xFD, 0xDB, 0x00, 0xC6, 0xFF, 0x04, 0x00, 0x02, 0x00, 0xFE,
+ 0xFF, 0x20, 0x00, 0x79, 0xFF, 0x72, 0x01, 0xC4, 0xFC, 0xA4, 0x06,
+ 0xAB, 0xF1, 0x46, 0x35, 0xF7, 0x2A, 0xC6, 0xF1, 0x2A, 0x07, 0x40,
+ 0xFC, 0xCF, 0x01, 0x47, 0xFF, 0x31, 0x00, 0xFD, 0xFF, 0x09, 0x00,
+ 0xDB, 0xFF, 0x33, 0x00, 0x01, 0x00, 0x38, 0xFF, 0xD3, 0x02, 0x53,
+ 0xF7, 0x1F, 0x44, 0x69, 0x15, 0x3F, 0xF6, 0xB2, 0x05, 0xAD, 0xFC,
+ 0xC1, 0x01, 0x41, 0xFF, 0x32, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x20,
+ 0x00, 0x7D, 0xFF, 0x24, 0x01, 0x0C, 0xFE, 0xDE, 0x02, 0x2E, 0xFC,
+ 0x13, 0x05, 0xEC, 0x48, 0x54, 0x02, 0x5E, 0xFD, 0x3F, 0x02, 0x5D,
+ 0xFE, 0xFE, 0x00, 0x8C, 0xFF, 0x1C, 0x00, 0xFE, 0xFF, 0x35, 0x00,
+ 0x3B, 0xFF, 0xD3, 0x01, 0x7F, 0xFC, 0x1F, 0x06, 0x3C, 0xF5, 0xE6,
+ 0x18, 0x4D, 0x42, 0xD5, 0xF5, 0xAF, 0x03, 0xB4, 0xFE, 0x4B, 0x00,
+ 0x0E, 0x00, 0xE9, 0xFF, 0x07, 0x00, 0xFD, 0xFF, 0x2D, 0x00, 0x53,
+ 0xFF, 0xBA, 0x01, 0x5B, 0xFC, 0x1B, 0x07, 0x8B, 0xF1, 0x58, 0x2E,
+ 0x26, 0x32, 0x80, 0xF1, 0xEA, 0x06, 0x8C, 0xFC, 0x97, 0x01, 0x66,
+ 0xFF, 0x27, 0x00, 0xFD, 0xFF, 0x04, 0x00, 0xF8, 0xFF, 0xE6, 0xFF,
+ 0x9C, 0x00, 0x27, 0xFE, 0x94, 0x04, 0x61, 0xF4, 0xD7, 0x3F, 0x06,
+ 0x1D, 0x2B, 0xF4, 0x89, 0x06, 0x56, 0xFC, 0xE0, 0x01, 0x37, 0xFF,
+ 0x36, 0x00, 0xFE, 0xFF, 0x17, 0x00, 0x9E, 0xFF, 0xCF, 0x00, 0xBF,
+ 0xFE, 0x86, 0x01, 0xBA, 0xFE, 0x5A, 0xFF, 0x86, 0x48, 0x7D, 0x08,
+ 0xC7, 0xFA, 0x93, 0x03, 0xB0, 0xFD, 0x4F, 0x01, 0x6C, 0xFF, 0x25,
+ 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x2F, 0x00, 0x4B, 0xFF, 0xA6, 0x01,
+ 0xEE, 0xFC, 0x23, 0x05, 0x83, 0xF7, 0x6E, 0x11, 0xE5, 0x45, 0x57,
+ 0xF9, 0xB8, 0x01, 0xDC, 0xFF, 0xA5, 0xFF, 0x5F, 0x00, 0xCA, 0xFF,
+ 0x0D, 0x00, 0xFD, 0xFF, 0x35, 0x00, 0x3D, 0xFF, 0xDF, 0x01, 0x32,
+ 0xFC, 0x1E, 0x07, 0x40, 0xF2, 0xEB, 0x26, 0xB5, 0x38, 0x1F, 0xF2,
+ 0x32, 0x06, 0x18, 0xFD, 0x3D, 0x01, 0x94, 0xFF, 0x16, 0x00, 0xFF,
+ 0xFF, 0x00, 0x00, 0x11, 0x00, 0xA4, 0xFF, 0x1D, 0x01, 0x4C, 0xFD,
+ 0xE6, 0x05, 0x7B, 0xF2, 0x71, 0x3A, 0xB8, 0x24, 0x97, 0xF2, 0x0B,
+ 0x07, 0x32, 0xFC, 0xE4, 0x01, 0x39, 0xFF, 0x36, 0x00, 0xFD, 0xFF,
+ 0x0F, 0x00, 0xC0, 0xFF, 0x78, 0x00, 0x73, 0xFF, 0x38, 0x00, 0x17,
+ 0x01, 0x8B, 0xFA, 0xAF, 0x46, 0x59, 0x0F, 0x39, 0xF8, 0xCF, 0x04,
+ 0x15, 0xFD, 0x95, 0x01, 0x51, 0xFF, 0x2D, 0x00, 0xFF, 0xFF, 0x00,
+ 0x00, 0x28, 0x00, 0x64, 0xFF, 0x65, 0x01, 0x81, 0xFD, 0xF2, 0x03,
+ 0x08, 0xFA, 0x68, 0x0A, 0x25, 0x48, 0xDE, 0xFD, 0x6E, 0xFF, 0x24,
+ 0x01, 0xF3, 0xFE, 0xB6, 0x00, 0xA8, 0xFF, 0x15, 0x00, 0xFD, 0xFF,
+ 0x36, 0x00, 0x36, 0xFF, 0xE5, 0x01, 0x46, 0xFC, 0xB8, 0x06, 0xA8,
+ 0xF3, 0x3F, 0x1F, 0x64, 0x3E, 0xBA, 0xF3, 0x01, 0x05, 0xE2, 0xFD,
+ 0xC4, 0x00, 0xD2, 0xFF, 0x00, 0x00, 0x02, 0x00, 0xFE, 0xFF, 0x23,
+ 0x00, 0x71, 0xFF, 0x81, 0x01, 0xAE, 0xFC, 0xC1, 0x06, 0x95, 0xF1,
+ 0x1E, 0x34, 0x3E, 0x2C, 0xAB, 0xF1, 0x27, 0x07, 0x49, 0xFC, 0xC8,
+ 0x01, 0x4B, 0xFF, 0x30, 0x00, 0xFD, 0xFF, 0x08, 0x00, 0xE1, 0xFF,
+ 0x25, 0x00, 0x1D, 0x00, 0x05, 0xFF, 0x28, 0x03, 0xBD, 0xF6, 0x77,
+ 0x43, 0xB6, 0x16, 0xDC, 0xF5, 0xDD, 0x05, 0x9B, 0xFC, 0xC8, 0x01,
+ 0x3E, 0xFF, 0x33, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x1F, 0x00, 0x83,
+ 0xFF, 0x16, 0x01, 0x2A, 0xFE, 0xA3, 0x02, 0xA1, 0xFC, 0x06, 0x04,
+ 0xF5, 0x48, 0x56, 0x03, 0xED, 0xFC, 0x7B, 0x02, 0x3E, 0xFE, 0x0C,
+ 0x01, 0x86, 0xFF, 0x1E, 0x00, 0xFE, 0xFF, 0x34, 0x00, 0x3D, 0xFF,
+ 0xCC, 0x01, 0x8F, 0xFC, 0xF8, 0x05, 0x9B, 0xF5, 0x96, 0x17, 0x02,
+ 0x43, 0x5E, 0xF6, 0x5F, 0x03, 0xE4, 0xFE, 0x30, 0x00, 0x1B, 0x00,
+ 0xE4, 0xFF, 0x08, 0x00, 0xFD, 0xFF, 0x2F, 0x00, 0x4E, 0xFF, 0xC3,
+ 0x01, 0x4F, 0xFC, 0x24, 0x07, 0x9C, 0xF1, 0x17, 0x2D, 0x57, 0x33,
+ 0x8A, 0xF1, 0xD3, 0x06, 0x9F, 0xFC, 0x8A, 0x01, 0x6D, 0xFF, 0x25,
+ 0x00, 0xFD, 0xFF, 0x03, 0x00, 0xFD, 0xFF, 0xD9, 0xFF, 0xB4, 0x00,
+ 0xFD, 0xFD, 0xD7, 0x04, 0xFA, 0xF3, 0xFC, 0x3E, 0x5B, 0x1E, 0xDB,
+ 0xF3, 0xA6, 0x06, 0x4C, 0xFC, 0xE3, 0x01, 0x36, 0xFF, 0x36, 0x00,
+ 0xFE, 0xFF, 0x16, 0x00, 0xA4, 0xFF, 0xC0, 0x00, 0xDE, 0xFE, 0x4B,
+ 0x01, 0x27, 0xFF, 0x73, 0xFE, 0x4F, 0x48, 0xA2, 0x09, 0x54, 0xFA,
+ 0xCC, 0x03, 0x93, 0xFD, 0x5C, 0x01, 0x67, 0xFF, 0x27, 0x00, 0x00,
+ 0x00, 0xFF, 0xFF, 0x2E, 0x00, 0x4E, 0xFF, 0x9C, 0x01, 0x05, 0xFD,
+ 0xF1, 0x04, 0xF0, 0xF7, 0x2D, 0x10, 0x61, 0x46, 0x0D, 0xFA, 0x58,
+ 0x01, 0x13, 0x00, 0x87, 0xFF, 0x6E, 0x00, 0xC4, 0xFF, 0x0E, 0x00,
+ 0xFD, 0xFF, 0x35, 0x00, 0x3B, 0xFF, 0xE3, 0x01, 0x31, 0xFC, 0x14,
+ 0x07, 0x73, 0xF2, 0x99, 0x25, 0xC2, 0x39, 0x54, 0xF2, 0x05, 0x06,
+ 0x37, 0xFD, 0x2B, 0x01, 0x9E, 0xFF, 0x13, 0x00, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0x14, 0x00, 0x9B, 0xFF, 0x31, 0x01, 0x2C, 0xFD, 0x15, 0x06,
+ 0x41, 0xF2, 0x6A, 0x39, 0x0A, 0x26, 0x61, 0xF2, 0x17, 0x07, 0x31,
+ 0xFC, 0xE2, 0x01, 0x3B, 0xFF, 0x35, 0x00, 0xFD, 0xFF, 0x0E, 0x00,
+ 0xC6, 0xFF, 0x69, 0x00, 0x91, 0xFF, 0x00, 0x00, 0x78, 0x01, 0xD0,
+ 0xF9, 0x39, 0x46, 0x98, 0x10, 0xCB, 0xF7, 0x02, 0x05, 0xFE, 0xFC,
+ 0x9F, 0x01, 0x4D, 0xFF, 0x2E, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x26,
+ 0x00, 0x69, 0xFF, 0x58, 0x01, 0x9D, 0xFD, 0xB9, 0x03, 0x7B, 0xFA,
+ 0x40, 0x09, 0x63, 0x48, 0xBF, 0xFE, 0x03, 0xFF, 0x5F, 0x01, 0xD4,
+ 0xFE, 0xC5, 0x00, 0xA2, 0xFF, 0x16, 0x00, 0xFE, 0xFF, 0x36, 0x00,
+ 0x36, 0xFF, 0xE2, 0x01, 0x4F, 0xFC, 0x9C, 0x06, 0xF5, 0xF3, 0xEA,
+ 0x1D, 0x47, 0x3F, 0x1B, 0xF4, 0xC1, 0x04, 0x0B, 0xFE, 0xAC, 0x00,
+ 0xDE, 0xFF, 0xFB, 0xFF, 0x03, 0x00, 0xFD, 0xFF, 0x25, 0x00, 0x6A,
+ 0xFF, 0x8E, 0x01, 0x99, 0xFC, 0xDB, 0x06, 0x86, 0xF1, 0xF2, 0x32,
+ 0x82, 0x2D, 0x96, 0xF1, 0x21, 0x07, 0x53, 0xFC, 0xC0, 0x01, 0x50,
+ 0xFF, 0x2E, 0x00, 0xFD, 0xFF, 0x07, 0x00, 0xE6, 0xFF, 0x17, 0x00,
+ 0x39, 0x00, 0xD4, 0xFE, 0x7A, 0x03, 0x2F, 0xF6, 0xC7, 0x42, 0x06,
+ 0x18, 0x7B, 0xF5, 0x05, 0x06, 0x8A, 0xFC, 0xCF, 0x01, 0x3C, 0xFF,
+ 0x34, 0x00, 0xFE, 0xFF, 0x1D, 0x00, 0x88, 0xFF, 0x07, 0x01, 0x49,
+ 0xFE, 0x67, 0x02, 0x13, 0xFD, 0xFF, 0x02, 0xF4, 0x48, 0x5F, 0x04,
+ 0x7A, 0xFC, 0xB6, 0x02, 0x20, 0xFE, 0x1B, 0x01, 0x81, 0xFF, 0x1F,
+ 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x33, 0x00, 0x3F, 0xFF, 0xC6, 0x01,
+ 0xA1, 0xFC, 0xCF, 0x05, 0xFC, 0xF5, 0x47, 0x16, 0xB0, 0x43, 0xEE,
+ 0xF6, 0x0C, 0x03, 0x16, 0xFF, 0x14, 0x00, 0x29, 0x00, 0xDF, 0xFF,
+ 0x09, 0x00, 0xFD, 0xFF, 0x30, 0x00, 0x4A, 0xFF, 0xCA, 0x01, 0x46,
+ 0xFC, 0x29, 0x07, 0xB3, 0xF1, 0xD1, 0x2B, 0x81, 0x34, 0x9C, 0xF1,
+ 0xB8, 0x06, 0xB5, 0xFC, 0x7C, 0x01, 0x74, 0xFF, 0x22, 0x00, 0xFE,
+ 0xFF, 0x02, 0x00, 0x01, 0x00, 0xCE, 0xFF, 0xCC, 0x00, 0xD5, 0xFD,
+ 0x16, 0x05, 0x9B, 0xF3, 0x18, 0x3E, 0xB1, 0x1F, 0x8F, 0xF3, 0xC0,
+ 0x06, 0x43, 0xFC, 0xE5, 0x01, 0x36, 0xFF, 0x36, 0x00, 0xFD, 0xFF,
+ 0x15, 0x00, 0xAA, 0xFF, 0xB1, 0x00, 0xFE, 0xFE, 0x10, 0x01, 0x92,
+ 0xFF, 0x94, 0xFD, 0x0D, 0x48, 0xCB, 0x0A, 0xE2, 0xF9, 0x04, 0x04,
+ 0x77, 0xFD, 0x69, 0x01, 0x62, 0xFF, 0x28, 0x00, 0x00, 0x00, 0xFF,
+ 0xFF, 0x2D, 0x00, 0x52, 0xFF, 0x91, 0x01, 0x1E, 0xFD, 0xBE, 0x04,
+ 0x5E, 0xF8, 0xF0, 0x0E, 0xD3, 0x46, 0xCB, 0xFA, 0xF6, 0x00, 0x4B,
+ 0x00, 0x69, 0xFF, 0x7D, 0x00, 0xBE, 0xFF, 0x10, 0x00, 0xFD, 0xFF,
+ 0x36, 0x00, 0x39, 0xFF, 0xE5, 0x01, 0x32, 0xFC, 0x06, 0x07, 0xAA,
+ 0xF2, 0x46, 0x24, 0xC8, 0x3A, 0x90, 0xF2, 0xD6, 0x05, 0x57, 0xFD,
+ 0x17, 0x01, 0xA8, 0xFF, 0x0F, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x18,
+ 0x00, 0x91, 0xFF, 0x43, 0x01, 0x0E, 0xFD, 0x40, 0x06, 0x0F, 0xF2,
+ 0x5B, 0x38, 0x5C, 0x27, 0x30, 0xF2, 0x21, 0x07, 0x33, 0xFC, 0xDE,
+ 0x01, 0x3E, 0xFF, 0x34, 0x00, 0xFD, 0xFF, 0x0D, 0x00, 0xCC, 0xFF,
+ 0x5A, 0x00, 0xAF, 0xFF, 0xCA, 0xFF, 0xD8, 0x01, 0x1C, 0xF9, 0xB8,
+ 0x45, 0xDA, 0x11, 0x60, 0xF7, 0x33, 0x05, 0xE7, 0xFC, 0xA9, 0x01,
+ 0x4A, 0xFF, 0x30, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x25, 0x00, 0x6E,
+ 0xFF, 0x4B, 0x01, 0xB9, 0xFD, 0x80, 0x03, 0xEE, 0xFA, 0x1D, 0x08,
+ 0x98, 0x48, 0xA8, 0xFF, 0x95, 0xFE, 0x9A, 0x01, 0xB4, 0xFE, 0xD4,
+ 0x00, 0x9C, 0xFF, 0x18, 0x00, 0xFE, 0xFF, 0x36, 0x00, 0x37, 0xFF,
+ 0xDF, 0x01, 0x5A, 0xFC, 0x7E, 0x06, 0x47, 0xF4, 0x94, 0x1C, 0x1F,
+ 0x40, 0x85, 0xF4, 0x7D, 0x04, 0x36, 0xFE, 0x93, 0x00, 0xEA, 0xFF,
+ 0xF7, 0xFF, 0x04, 0x00, 0xFD, 0xFF, 0x28, 0x00, 0x63, 0xFF, 0x9B,
+ 0x01, 0x86, 0xFC, 0xF1, 0x06, 0x7E, 0xF1, 0xC0, 0x31, 0xC2, 0x2E,
+ 0x87, 0xF1, 0x17, 0x07, 0x5F, 0xFC, 0xB6, 0x01, 0x55, 0xFF, 0x2D,
+ 0x00, 0xFD, 0xFF, 0x06, 0x00, 0xEB, 0xFF, 0x09, 0x00, 0x54, 0x00,
+ 0xA4, 0xFE, 0xC9, 0x03, 0xAA, 0xF5, 0x0C, 0x42, 0x56, 0x19, 0x1E,
+ 0xF5, 0x2B, 0x06, 0x7A, 0xFC, 0xD4, 0x01, 0x3A, 0xFF, 0x35, 0x00,
+ 0xFE, 0xFF, 0x1C, 0x00, 0x8E, 0xFF, 0xF9, 0x00, 0x68, 0xFE, 0x2C,
+ 0x02, 0x84, 0xFD, 0xFF, 0x01, 0xE6, 0x48, 0x6E, 0x05, 0x07, 0xFC,
+ 0xF1, 0x02, 0x01, 0xFE, 0x29, 0x01, 0x7B, 0xFF, 0x21, 0x00, 0x00,
+ 0x00, 0xFF, 0xFF, 0x32, 0x00, 0x42, 0xFF, 0xBE, 0x01, 0xB4, 0xFC,
+ 0xA4, 0x05, 0x61, 0xF6, 0xFB, 0x14, 0x53, 0x44, 0x86, 0xF7, 0xB6,
+ 0x02, 0x49, 0xFF, 0xF7, 0xFF, 0x37, 0x00, 0xD9, 0xFF, 0x0A, 0x00,
+ 0xFD, 0xFF, 0x32, 0x00, 0x46, 0xFF, 0xD1, 0x01, 0x3E, 0xFC, 0x2B,
+ 0x07, 0xD0, 0xF1, 0x89, 0x2A, 0xA6, 0x35, 0xB4, 0xF1, 0x99, 0x06,
+ 0xCD, 0xFC, 0x6D, 0x01, 0x7C, 0xFF, 0x1F, 0x00, 0xFE, 0xFF, 0x01,
+ 0x00, 0x06, 0x00, 0xC2, 0xFF, 0xE3, 0x00, 0xAE, 0xFD, 0x52, 0x05,
+ 0x44, 0xF3, 0x2A, 0x3D, 0x06, 0x21, 0x47, 0xF3, 0xD8, 0x06, 0x3C,
+ 0xFC, 0xE6, 0x01, 0x36, 0xFF, 0x36, 0x00, 0xFD, 0xFF, 0x13, 0x00,
+ 0xB0, 0xFF, 0xA2, 0x00, 0x1D, 0xFF, 0xD6, 0x00, 0xFC, 0xFF, 0xBC,
+ 0xFC, 0xC0, 0x47, 0xFA, 0x0B, 0x70, 0xF9, 0x3C, 0x04, 0x5C, 0xFD,
+ 0x75, 0x01, 0x5D, 0xFF, 0x2A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2B,
+ 0x00, 0x57, 0xFF, 0x86, 0x01, 0x36, 0xFD, 0x89, 0x04, 0xCD, 0xF8,
+ 0xB7, 0x0D, 0x3D, 0x47, 0x91, 0xFB, 0x91, 0x00, 0x83, 0x00, 0x4A,
+ 0xFF, 0x8C, 0x00, 0xB9, 0xFF, 0x11, 0x00, 0xFD, 0xFF, 0x36, 0x00,
+ 0x38, 0xFF, 0xE6, 0x01, 0x35, 0xFC, 0xF5, 0x06, 0xE7, 0xF2, 0xF2,
+ 0x22, 0xC7, 0x3B, 0xD4, 0xF2, 0xA2, 0x05, 0x7A, 0xFD, 0x02, 0x01,
+ 0xB2, 0xFF, 0x0B, 0x00, 0x01, 0x00, 0xFE, 0xFF, 0x1B, 0x00, 0x88,
+ 0xFF, 0x55, 0x01, 0xF2, 0xFC, 0x67, 0x06, 0xE4, 0xF1, 0x44, 0x37,
+ 0xAA, 0x28, 0x05, 0xF2, 0x27, 0x07, 0x36, 0xFC, 0xDA, 0x01, 0x41,
+ 0xFF, 0x33, 0x00, 0xFD, 0xFF, 0x0B, 0x00, 0xD2, 0xFF, 0x4C, 0x00,
+ 0xCD, 0xFF, 0x94, 0xFF, 0x34, 0x02, 0x70, 0xF8, 0x2E, 0x45, 0x20,
+ 0x13, 0xF6, 0xF6, 0x62, 0x05, 0xD1, 0xFC, 0xB2, 0x01, 0x46, 0xFF,
+ 0x31, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x23, 0x00, 0x73, 0xFF, 0x3D,
+ 0x01, 0xD6, 0xFD, 0x46, 0x03, 0x61, 0xFB, 0x00, 0x07, 0xBF, 0x48,
+ 0x98, 0x00, 0x26, 0xFE, 0xD5, 0x01, 0x95, 0xFE, 0xE3, 0x00, 0x96,
+ 0xFF, 0x1A, 0x00, 0xFE, 0xFF, 0x36, 0x00, 0x38, 0xFF, 0xDB, 0x01,
+ 0x66, 0xFC, 0x5E, 0x06, 0x9C, 0xF4, 0x40, 0x1B, 0xEF, 0x40, 0xF7,
+ 0xF4, 0x35, 0x04, 0x62, 0xFE, 0x7A, 0x00, 0xF7, 0xFF, 0xF2, 0xFF,
+ 0x05, 0x00, 0xFD, 0xFF, 0x2A, 0x00, 0x5D, 0xFF, 0xA7, 0x01, 0x75,
+ 0xFC, 0x03, 0x07, 0x7D, 0xF1, 0x8A, 0x30, 0xFF, 0x2F, 0x7E, 0xF1,
+ 0x0A, 0x07, 0x6E, 0xFC, 0xAC, 0x01, 0x5A, 0xFF, 0x2B, 0x00, 0xFD,
+ 0xFF, 0x05, 0x00, 0xF0, 0xFF, 0xFC, 0xFF, 0x6E, 0x00, 0x76, 0xFE,
+ 0x15, 0x04, 0x2C, 0xF5, 0x49, 0x41, 0xA9, 0x1A, 0xC3, 0xF4, 0x4F,
+ 0x06, 0x6C, 0xFC, 0xD9, 0x01, 0x38, 0xFF, 0x35, 0x00, 0xFE, 0xFF,
+ 0x1A, 0x00, 0x94, 0xFF, 0xEA, 0x00, 0x87, 0xFE, 0xF0, 0x01, 0xF5,
+ 0xFD, 0x05, 0x01, 0xCE, 0x48, 0x83, 0x06, 0x94, 0xFB, 0x2C, 0x03,
+ 0xE4, 0xFD, 0x37, 0x01, 0x76, 0xFF, 0x22, 0x00, 0x00, 0x00, 0xFF,
+ 0xFF, 0x31, 0x00, 0x45, 0xFF, 0xB6, 0x01, 0xC8, 0xFC, 0x77, 0x05,
+ 0xC7, 0xF6, 0xB1, 0x13, 0xED, 0x44, 0x26, 0xF8, 0x5D, 0x02, 0x7D,
+ 0xFF, 0xDA, 0xFF, 0x46, 0x00, 0xD4, 0xFF, 0x0B, 0x00, 0xFD, 0xFF,
+ 0x33, 0x00, 0x42, 0xFF, 0xD7, 0x01, 0x38, 0xFC, 0x29, 0x07, 0xF3,
+ 0xF1, 0x3E, 0x29, 0xC6, 0x36, 0xD4, 0xF1, 0x77, 0x06, 0xE6, 0xFC,
+ 0x5C, 0x01, 0x84, 0xFF, 0x1C, 0x00, 0xFE, 0xFF, 0x01, 0x00, 0x0A,
+ 0x00, 0xB7, 0xFF, 0xF9, 0x00, 0x89, 0xFD, 0x8A, 0x05, 0xF4, 0xF2,
+ 0x37, 0x3C, 0x5B, 0x22, 0x03, 0xF3, 0xED, 0x06, 0x37, 0xFC, 0xE6,
+ 0x01, 0x37, 0xFF, 0x36, 0x00, 0xFD, 0xFF, 0x12, 0x00, 0xB6, 0xFF,
+ 0x93, 0x00, 0x3C, 0xFF, 0x9D, 0x00, 0x63, 0x00, 0xEB, 0xFB, 0x69,
+ 0x47, 0x2D, 0x0D, 0xFF, 0xF8, 0x72, 0x04, 0x42, 0xFD, 0x81, 0x01,
+ 0x59, 0xFF, 0x2B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2A, 0x00, 0x5B,
+ 0xFF, 0x7A, 0x01, 0x50, 0xFD, 0x54, 0x04, 0x3D, 0xF9, 0x82, 0x0C,
+ 0x9A, 0x47, 0x5E, 0xFC, 0x2A, 0x00, 0xBD, 0x00, 0x2B, 0xFF, 0x9B,
+ 0x00, 0xB3, 0xFF, 0x12, 0x00, 0xFD, 0xFF, 0x36, 0x00, 0x37, 0xFF,
+ 0xE6, 0x01, 0x3A, 0xFC, 0xE2, 0x06, 0x28, 0xF3, 0x9E, 0x21, 0xC0,
+ 0x3C, 0x1F, 0xF3, 0x6C, 0x05, 0x9E, 0xFD, 0xED, 0x00, 0xBD, 0xFF,
+ 0x07, 0x00, 0x01, 0x00, 0xFE, 0xFF, 0x1E, 0x00, 0x80, 0xFF, 0x66,
+ 0x01, 0xD8, 0xFC, 0x8B, 0x06, 0xC1, 0xF1, 0x27, 0x36, 0xF6, 0x29,
+ 0xDF, 0xF1, 0x2A, 0x07, 0x3B, 0xFC, 0xD4, 0x01, 0x44, 0xFF, 0x32,
+ 0x00, 0xFD, 0xFF, 0x0A, 0x00, 0xD7, 0xFF, 0x3E, 0x00, 0xEA, 0xFF,
+ 0x60, 0xFF, 0x8F, 0x02, 0xCD, 0xF7, 0x99, 0x44, 0x68, 0x14, 0x8E,
+ 0xF6, 0x90, 0x05, 0xBC, 0xFC, 0xBA, 0x01, 0x43, 0xFF, 0x32, 0x00,
+ 0xFF, 0xFF, 0x00, 0x00, 0x22, 0x00, 0x79, 0xFF, 0x2F, 0x01, 0xF4,
+ 0xFD, 0x0C, 0x03, 0xD4, 0xFB, 0xE9, 0x05, 0xDE, 0x48, 0x8F, 0x01,
+ 0xB6, 0xFD, 0x11, 0x02, 0x76, 0xFE, 0xF2, 0x00, 0x91, 0xFF, 0x1B,
+ 0x00, 0xFE, 0xFF, 0x35, 0x00, 0x39, 0xFF, 0xD7, 0x01, 0x73, 0xFC,
+ 0x3B, 0x06, 0xF5, 0xF4, 0xED, 0x19, 0xB7, 0x41, 0x71, 0xF5, 0xEB,
+ 0x03, 0x90, 0xFE, 0x60, 0x00, 0x04, 0x00, 0xED, 0xFF, 0x06, 0x00,
+ 0xFD, 0xFF, 0x2C, 0x00, 0x57, 0xFF, 0xB2, 0x01, 0x65, 0xFC, 0x12,
+ 0x07, 0x82, 0xF1, 0x50, 0x2F, 0x38, 0x31, 0x7C, 0xF1, 0xF9, 0x06,
+ 0x7E, 0xFC, 0xA1, 0x01, 0x61, 0xFF, 0x29, 0x00, 0xFD, 0xFF, 0x04,
+ 0x00, 0xF5, 0xFF, 0xEF, 0xFF, 0x88, 0x00, 0x49, 0xFE, 0x5D, 0x04,
+ 0xB7, 0xF4, 0x7D, 0x40, 0xFD, 0x1B, 0x6C, 0xF4, 0x70, 0x06, 0x5F,
+ 0xFC, 0xDE, 0x01, 0x37, 0xFF, 0x36, 0x00, 0xFE, 0xFF, 0x19, 0x00,
+ 0x9A, 0xFF, 0xDB, 0x00, 0xA6, 0xFE, 0xB4, 0x01, 0x64, 0xFE, 0x12,
+ 0x00, 0xAA, 0x48, 0x9E, 0x07, 0x21, 0xFB, 0x66, 0x03, 0xC6, 0xFD,
+ 0x45, 0x01, 0x70, 0xFF, 0x24, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x30,
+ 0x00, 0x48, 0xFF, 0xAD, 0x01, 0xDD, 0xFC, 0x48, 0x05, 0x30, 0xF7,
+ 0x6B, 0x12, 0x7D, 0x45, 0xCF, 0xF8, 0x01, 0x02, 0xB2, 0xFF, 0xBD,
+ 0xFF, 0x54, 0x00, 0xCE, 0xFF, 0x0C, 0x00, 0xFD, 0xFF, 0x34, 0x00,
+ 0x3F, 0xFF, 0xDC, 0x01, 0x34, 0xFC, 0x24, 0x07, 0x1C, 0xF2, 0xF0,
+ 0x27, 0xDF, 0x37, 0xFB, 0xF1, 0x51, 0x06, 0x01, 0xFD, 0x4B, 0x01,
+ 0x8D, 0xFF, 0x19, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x0E, 0x00, 0xAC,
+ 0xFF, 0x0E, 0x01, 0x66, 0xFD, 0xBF, 0x05, 0xAD, 0xF2, 0x3B, 0x3B,
+ 0xB0, 0x23, 0xC4, 0xF2, 0xFF, 0x06, 0x33, 0xFC, 0xE5, 0x01, 0x38,
+ 0xFF, 0x36, 0x00, 0xFD, 0xFF, 0x10, 0x00, 0xBC, 0xFF, 0x84, 0x00,
+ 0x5B, 0xFF, 0x64, 0x00, 0xC9, 0x00, 0x22, 0xFB, 0x02, 0x47, 0x64,
+ 0x0E, 0x8F, 0xF8, 0xA7, 0x04, 0x29, 0xFD, 0x8C, 0x01, 0x54, 0xFF,
+ 0x2C, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x29, 0x00, 0x60, 0xFF, 0x6E,
+ 0x01, 0x6B, 0xFD, 0x1D, 0x04, 0xAF, 0xF9, 0x51, 0x0B, 0xEC, 0x47,
+ 0x33, 0xFD, 0xC1, 0xFF, 0xF7, 0x00, 0x0C, 0xFF, 0xAA, 0x00, 0xAD,
+ 0xFF, 0x14, 0x00, 0xFD, 0xFF, 0x36, 0x00, 0x36, 0xFF, 0xE6, 0x01,
+ 0x40, 0xFC, 0xCB, 0x06, 0x6E, 0xF3, 0x49, 0x20, 0xB0, 0x3D, 0x73,
+ 0xF3, 0x31, 0x05, 0xC4, 0xFD, 0xD6, 0x00, 0xC8, 0xFF, 0x03, 0x00,
+ 0x02, 0x00, 0xFE, 0xFF, 0x21, 0x00, 0x77, 0xFF, 0x75, 0x01, 0xBF,
+ 0xFC, 0xAB, 0x06, 0xA6, 0xF1, 0x05, 0x35, 0x40, 0x2B, 0xBF, 0xF1,
+ 0x2A, 0x07, 0x42, 0xFC, 0xCE, 0x01, 0x48, 0xFF, 0x31, 0x00, 0xFD,
+ 0xFF, 0x09, 0x00, 0xDC, 0xFF, 0x2F, 0x00, 0x07, 0x00, 0x2C, 0xFF,
+ 0xE6, 0x02, 0x31, 0xF7, 0xFA, 0x43, 0xB3, 0x15, 0x29, 0xF6, 0xBC,
+ 0x05, 0xA9, 0xFC, 0xC2, 0x01, 0x40, 0xFF, 0x33, 0x00, 0xFF, 0xFF,
+ 0x00, 0x00, 0x20, 0x00, 0x7E, 0xFF, 0x21, 0x01, 0x12, 0xFE, 0xD1,
+ 0x02, 0x47, 0xFC, 0xD7, 0x04, 0xF0, 0x48, 0x8D, 0x02, 0x45, 0xFD,
+ 0x4D, 0x02, 0x56, 0xFE, 0x01, 0x01, 0x8B, 0xFF, 0x1D, 0x00, 0xFE,
+ 0xFF, 0x34, 0x00, 0x3B, 0xFF, 0xD1, 0x01, 0x83, 0xFC, 0x16, 0x06,
+ 0x51, 0xF5, 0x9B, 0x18, 0x75, 0x42, 0xF3, 0xF5, 0x9D, 0x03, 0xBF,
+ 0xFE, 0x45, 0x00, 0x11, 0x00, 0xE8, 0xFF, 0x07, 0x00, 0xFD, 0xFF,
+ 0x2E, 0x00, 0x52, 0xFF, 0xBC, 0x01, 0x58, 0xFC, 0x1D, 0x07, 0x8E,
+ 0xF1, 0x11, 0x2E, 0x6B, 0x32, 0x81, 0xF1, 0xE5, 0x06, 0x90, 0xFC,
+ 0x94, 0x01, 0x67, 0xFF, 0x26, 0x00, 0xFD, 0xFF, 0x04, 0x00, 0xF9,
+ 0xFF, 0xE3, 0xFF, 0xA1, 0x00, 0x1E, 0xFE, 0xA3, 0x04, 0x49, 0xF4,
+ 0xA8, 0x3F, 0x52, 0x1D, 0x19, 0xF4, 0x90, 0x06, 0x53, 0xFC, 0xE1,
+ 0x01, 0x36, 0xFF, 0x36, 0x00, 0xFE, 0xFF, 0x17, 0x00, 0xA0, 0xFF,
+ 0xCC, 0x00, 0xC6, 0xFE, 0x79, 0x01, 0xD2, 0xFE, 0x26, 0xFF, 0x7C,
+ 0x48, 0xBE, 0x08, 0xAE, 0xFA, 0xA0, 0x03, 0xA9, 0xFD, 0x52, 0x01,
+ 0x6B, 0xFF, 0x25, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x2F, 0x00, 0x4C,
+ 0xFF, 0xA3, 0x01, 0xF3, 0xFC, 0x18, 0x05, 0x9B, 0xF7, 0x27, 0x11,
+ 0x02, 0x46, 0x7F, 0xF9, 0xA3, 0x01, 0xE8, 0xFF, 0x9F, 0xFF, 0x63,
+ 0x00, 0xC9, 0xFF, 0x0D, 0x00, 0xFD, 0xFF, 0x35, 0x00, 0x3C, 0xFF,
+ 0xE0, 0x01, 0x32, 0xFC, 0x1C, 0x07, 0x4B, 0xF2, 0xA0, 0x26, 0xF2,
+ 0x38, 0x2A, 0xF2, 0x28, 0x06, 0x1F, 0xFD, 0x39, 0x01, 0x96, 0xFF,
+ 0x16, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x11, 0x00, 0xA2, 0xFF, 0x22,
+ 0x01, 0x45, 0xFD, 0xF1, 0x05, 0x6D, 0xF2, 0x38, 0x3A, 0x03, 0x25,
+ 0x8B, 0xF2, 0x0E, 0x07, 0x32, 0xFC, 0xE4, 0x01, 0x3A, 0xFF, 0x36,
+ 0x00, 0xFD, 0xFF, 0x0F, 0x00, 0xC2, 0xFF, 0x75, 0x00, 0x7A, 0xFF,
+ 0x2B, 0x00, 0x2D, 0x01, 0x61, 0xFA, 0x97, 0x46, 0xA0, 0x0F, 0x20,
+ 0xF8, 0xDA, 0x04, 0x10, 0xFD, 0x97, 0x01, 0x50, 0xFF, 0x2E, 0x00,
+ 0xFF, 0xFF, 0x00, 0x00, 0x27, 0x00, 0x65, 0xFF, 0x62, 0x01, 0x87,
+ 0xFD, 0xE5, 0x03, 0x21, 0xFA, 0x25, 0x0A, 0x33, 0x48, 0x0F, 0xFE,
+ 0x57, 0xFF, 0x31, 0x01, 0xEC, 0xFE, 0xB9, 0x00, 0xA7, 0xFF, 0x15,
+ 0x00, 0xFE, 0xFF, 0x36, 0x00, 0x36, 0xFF, 0xE4, 0x01, 0x48, 0xFC,
+ 0xB2, 0x06, 0xB9, 0xF3, 0xF3, 0x1E, 0x98, 0x3E, 0xCF, 0xF3, 0xF3,
+ 0x04, 0xEB, 0xFD, 0xBF, 0x00, 0xD4, 0xFF, 0xFF, 0xFF, 0x03, 0x00,
+ 0xFE, 0xFF, 0x23, 0x00, 0x70, 0xFF, 0x84, 0x01, 0xA9, 0xFC, 0xC7,
+ 0x06, 0x91, 0xF1, 0xDC, 0x33, 0x87, 0x2C, 0xA5, 0xF1, 0x26, 0x07,
+ 0x4B, 0xFC, 0xC6, 0x01, 0x4C, 0xFF, 0x30, 0x00, 0xFD, 0xFF, 0x08,
+ 0x00, 0xE2, 0xFF, 0x21, 0x00, 0x23, 0x00, 0xFA, 0xFE, 0x3A, 0x03,
+ 0x9D, 0xF6, 0x50, 0x43, 0x00, 0x17, 0xC6, 0xF5, 0xE6, 0x05, 0x97,
+ 0xFC, 0xC9, 0x01, 0x3E, 0xFF, 0x34, 0x00, 0xFE, 0xFF, 0x00, 0x00,
+ 0x1E, 0x00, 0x84, 0xFF, 0x13, 0x01, 0x31, 0xFE, 0x95, 0x02, 0xBA,
+ 0xFC, 0xCB, 0x03, 0xF7, 0x48, 0x91, 0x03, 0xD3, 0xFC, 0x88, 0x02,
+ 0x38, 0xFE, 0x10, 0x01, 0x85, 0xFF, 0x1E, 0x00, 0xFE, 0xFF, 0x34,
+ 0x00, 0x3D, 0xFF, 0xCB, 0x01, 0x93, 0xFC, 0xEF, 0x05, 0xB0, 0xF5,
+ 0x4B, 0x17, 0x2A, 0x43, 0x7D, 0xF6, 0x4D, 0x03, 0xEF, 0xFE, 0x2A,
+ 0x00, 0x1E, 0x00, 0xE3, 0xFF, 0x08, 0x00, 0xFD, 0xFF, 0x2F, 0x00,
+ 0x4D, 0xFF, 0xC4, 0x01, 0x4D, 0xFC, 0x25, 0x07, 0xA1, 0xF1, 0xCE,
+ 0x2C, 0x99, 0x33, 0x8E, 0xF1, 0xCD, 0x06, 0xA4, 0xFC, 0x87, 0x01,
+ 0x6E, 0xFF, 0x24, 0x00, 0xFD, 0xFF, 0x03, 0x00, 0xFE, 0xFF, 0xD7,
+ 0xFF, 0xBA, 0x00, 0xF4, 0xFD, 0xE5, 0x04, 0xE4, 0xF3, 0xCA, 0x3E,
+ 0xA7, 0x1E, 0xCA, 0xF3, 0xAC, 0x06, 0x4A, 0xFC, 0xE4, 0x01, 0x36,
+ 0xFF, 0x36, 0x00, 0xFE, 0xFF, 0x16, 0x00, 0xA6, 0xFF, 0xBD, 0x00,
+ 0xE5, 0xFE, 0x3E, 0x01, 0x3F, 0xFF, 0x41, 0xFE, 0x41, 0x48, 0xE4,
+ 0x09, 0x3B, 0xFA, 0xD9, 0x03, 0x8D, 0xFD, 0x5F, 0x01, 0x66, 0xFF,
+ 0x27, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x2E, 0x00, 0x4F, 0xFF, 0x99,
+ 0x01, 0x0B, 0xFD, 0xE6, 0x04, 0x08, 0xF8, 0xE7, 0x0F, 0x7C, 0x46,
+ 0x37, 0xFA, 0x42, 0x01, 0x1F, 0x00, 0x81, 0xFF, 0x71, 0x00, 0xC3,
+ 0xFF, 0x0F, 0x00, 0xFD, 0xFF, 0x35, 0x00, 0x3A, 0xFF, 0xE3, 0x01,
+ 0x31, 0xFC, 0x11, 0x07, 0x7F, 0xF2, 0x4E, 0x25, 0xFD, 0x39, 0x60,
+ 0xF2, 0xFB, 0x05, 0x3E, 0xFD, 0x26, 0x01, 0xA0, 0xFF, 0x12, 0x00,
+ 0x00, 0x00, 0xFF, 0xFF, 0x15, 0x00, 0x98, 0xFF, 0x35, 0x01, 0x25,
+ 0xFD, 0x1E, 0x06, 0x35, 0xF2, 0x2E, 0x39, 0x55, 0x26, 0x56, 0xF2,
+ 0x1A, 0x07, 0x31, 0xFC, 0xE1, 0x01, 0x3C, 0xFF, 0x35, 0x00, 0xFD,
+ 0xFF, 0x0E, 0x00, 0xC7, 0xFF, 0x66, 0x00, 0x98, 0xFF, 0xF4, 0xFF,
+ 0x8E, 0x01, 0xA7, 0xF9, 0x1D, 0x46, 0xDF, 0x10, 0xB3, 0xF7, 0x0D,
+ 0x05, 0xF8, 0xFC, 0xA1, 0x01, 0x4C, 0xFF, 0x2F, 0x00, 0xFF, 0xFF,
+ 0x00, 0x00, 0x26, 0x00, 0x6A, 0xFF, 0x55, 0x01, 0xA3, 0xFD, 0xAD,
+ 0x03, 0x94, 0xFA, 0xFF, 0x08, 0x70, 0x48, 0xF3, 0xFE, 0xEA, 0xFE,
+ 0x6C, 0x01, 0xCD, 0xFE, 0xC9, 0x00, 0xA1, 0xFF, 0x17, 0x00, 0xFE,
+ 0xFF, 0x36, 0x00, 0x36, 0xFF, 0xE2, 0x01, 0x51, 0xFC, 0x96, 0x06,
+ 0x07, 0xF4, 0x9E, 0x1D, 0x77, 0x3F, 0x32, 0xF4, 0xB2, 0x04, 0x15,
+ 0xFE, 0xA7, 0x00, 0xE0, 0xFF, 0xFA, 0xFF, 0x03, 0x00, 0xFD, 0xFF,
+ 0x26, 0x00, 0x69, 0xFF, 0x91, 0x01, 0x94, 0xFC, 0xE0, 0x06, 0x84,
+ 0xF1, 0xAF, 0x32, 0xCA, 0x2D, 0x92, 0xF1, 0x1F, 0x07, 0x56, 0xFC,
+ 0xBE, 0x01, 0x51, 0xFF, 0x2E, 0x00, 0xFD, 0xFF, 0x07, 0x00, 0xE7,
+ 0xFF, 0x14, 0x00, 0x3F, 0x00, 0xC9, 0xFE, 0x8C, 0x03, 0x11, 0xF6,
+ 0x9E, 0x42, 0x50, 0x18, 0x66, 0xF5, 0x0D, 0x06, 0x86, 0xFC, 0xD0,
+ 0x01, 0x3B, 0xFF, 0x34, 0x00, 0xFE, 0xFF, 0x1D, 0x00, 0x8A, 0xFF,
+ 0x04, 0x01, 0x50, 0xFE, 0x5A, 0x02, 0x2C, 0xFD, 0xC6, 0x02, 0xF2,
+ 0x48, 0x9B, 0x04, 0x61, 0xFC, 0xC3, 0x02, 0x19, 0xFE, 0x1E, 0x01,
+ 0x7F, 0xFF, 0x20, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x33, 0x00, 0x40,
+ 0xFF, 0xC4, 0x01, 0xA5, 0xFC, 0xC5, 0x05, 0x13, 0xF6, 0xFD, 0x15,
+ 0xD4, 0x43, 0x0F, 0xF7, 0xF9, 0x02, 0x21, 0xFF, 0x0D, 0x00, 0x2C,
+ 0x00, 0xDE, 0xFF, 0x09, 0x00, 0xFD, 0xFF, 0x31, 0x00, 0x49, 0xFF,
+ 0xCC, 0x01, 0x44, 0xFC, 0x29, 0x07, 0xB9, 0xF1, 0x89, 0x2B, 0xC3,
+ 0x34, 0xA0, 0xF1, 0xB1, 0x06, 0xBA, 0xFC, 0x79, 0x01, 0x76, 0xFF,
+ 0x21, 0x00, 0xFE, 0xFF, 0x02, 0x00, 0x02, 0x00, 0xCB, 0xFF, 0xD1,
+ 0x00, 0xCC, 0xFD, 0x24, 0x05, 0x87, 0xF3, 0xE4, 0x3D, 0xFD, 0x1F,
+ 0x7F, 0xF3, 0xC6, 0x06, 0x41, 0xFC, 0xE5, 0x01, 0x36, 0xFF, 0x36,
+ 0x00, 0xFD, 0xFF, 0x14, 0x00, 0xAC, 0xFF, 0xAE, 0x00, 0x05, 0xFF,
+ 0x03, 0x01, 0xAA, 0xFF, 0x63, 0xFD, 0xFD, 0x47, 0x0E, 0x0B, 0xC8,
+ 0xF9, 0x11, 0x04, 0x71, 0xFD, 0x6C, 0x01, 0x61, 0xFF, 0x28, 0x00,
+ 0x00, 0x00, 0xFF, 0xFF, 0x2D, 0x00, 0x53, 0xFF, 0x8F, 0x01, 0x23,
+ 0xFD, 0xB2, 0x04, 0x76, 0xF8, 0xAA, 0x0E, 0xED, 0x46, 0xF7, 0xFA,
+ 0xDF, 0x00, 0x57, 0x00, 0x62, 0xFF, 0x80, 0x00, 0xBD, 0xFF, 0x10,
+ 0x00, 0xFD, 0xFF, 0x36, 0x00, 0x39, 0xFF, 0xE5, 0x01, 0x33, 0xFC,
+ 0x03, 0x07, 0xB7, 0xF2, 0xFC, 0x23, 0x03, 0x3B, 0x9E, 0xF2, 0xCB,
+ 0x05, 0x5F, 0xFD, 0x12, 0x01, 0xAA, 0xFF, 0x0E, 0x00, 0x00, 0x00,
+ 0xFF, 0xFF, 0x18, 0x00, 0x8F, 0xFF, 0x47, 0x01, 0x08, 0xFD, 0x49,
+ 0x06, 0x05, 0xF2, 0x1D, 0x38, 0xA6, 0x27, 0x26, 0xF2, 0x23, 0x07,
+ 0x33, 0xFC, 0xDD, 0x01, 0x3E, 0xFF, 0x34, 0x00, 0xFD, 0xFF, 0x0C,
+ 0x00, 0xCD, 0xFF, 0x57, 0x00, 0xB6, 0xFF, 0xBE, 0xFF, 0xED, 0x01,
+ 0xF5, 0xF8, 0x9B, 0x45, 0x22, 0x12, 0x48, 0xF7, 0x3D, 0x05, 0xE2,
+ 0xFC, 0xAB, 0x01, 0x49, 0xFF, 0x30, 0x00, 0xFF, 0xFF, 0x00, 0x00,
+ 0x24, 0x00, 0x6F, 0xFF, 0x48, 0x01, 0xC0, 0xFD, 0x73, 0x03, 0x07,
+ 0xFB, 0xDD, 0x07, 0xA1, 0x48, 0xDD, 0xFF, 0x7D, 0xFE, 0xA7, 0x01,
+ 0xAD, 0xFE, 0xD8, 0x00, 0x9B, 0xFF, 0x18, 0x00, 0xFE, 0xFF, 0x36,
+ 0x00, 0x37, 0xFF, 0xDF, 0x01, 0x5C, 0xFC, 0x78, 0x06, 0x5A, 0xF4,
+ 0x49, 0x1C, 0x4E, 0x40, 0x9E, 0xF4, 0x6D, 0x04, 0x3F, 0xFE, 0x8E,
+ 0x00, 0xED, 0xFF, 0xF6, 0xFF, 0x04, 0x00, 0xFD, 0xFF, 0x28, 0x00,
+ 0x62, 0xFF, 0x9E, 0x01, 0x82, 0xFC, 0xF5, 0x06, 0x7D, 0xF1, 0x7B,
+ 0x31, 0x09, 0x2F, 0x84, 0xF1, 0x15, 0x07, 0x62, 0xFC, 0xB4, 0x01,
+ 0x56, 0xFF, 0x2C, 0x00, 0xFD, 0xFF, 0x06, 0x00, 0xEC, 0xFF, 0x06,
+ 0x00, 0x5A, 0x00, 0x9A, 0xFE, 0xDA, 0x03, 0x8D, 0xF5, 0xE1, 0x41,
+ 0xA1, 0x19, 0x09, 0xF5, 0x33, 0x06, 0x77, 0xFC, 0xD6, 0x01, 0x3A,
+ 0xFF, 0x35, 0x00, 0xFE, 0xFF, 0x1B, 0x00, 0x8F, 0xFF, 0xF5, 0x00,
+ 0x6F, 0xFE, 0x1E, 0x02, 0x9D, 0xFD, 0xC7, 0x01, 0xE1, 0x48, 0xAB,
+ 0x05, 0xEE, 0xFB, 0xFE, 0x02, 0xFB, 0xFD, 0x2C, 0x01, 0x7A, 0xFF,
+ 0x21, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x32, 0x00, 0x42, 0xFF, 0xBC,
+ 0x01, 0xB8, 0xFC, 0x9A, 0x05, 0x77, 0xF6, 0xB1, 0x14, 0x77, 0x44,
+ 0xA9, 0xF7, 0xA2, 0x02, 0x54, 0xFF, 0xF1, 0xFF, 0x3A, 0x00, 0xD8,
+ 0xFF, 0x0A, 0x00, 0xFD, 0xFF, 0x32, 0x00, 0x45, 0xFF, 0xD3, 0x01,
+ 0x3C, 0xFC, 0x2A, 0x07, 0xD8, 0xF1, 0x3F, 0x2A, 0xE6, 0x35, 0xBB,
+ 0xF1, 0x92, 0x06, 0xD2, 0xFC, 0x69, 0x01, 0x7E, 0xFF, 0x1F, 0x00,
+ 0xFE, 0xFF, 0x01, 0x00, 0x07, 0x00, 0xC0, 0xFF, 0xE8, 0x00, 0xA6,
+ 0xFD, 0x5F, 0x05, 0x31, 0xF3, 0xF6, 0x3C, 0x52, 0x21, 0x37, 0xF3,
+ 0xDD, 0x06, 0x3B, 0xFC, 0xE6, 0x01, 0x36, 0xFF, 0x36, 0x00, 0xFD,
+ 0xFF, 0x13, 0x00, 0xB1, 0xFF, 0x9F, 0x00, 0x24, 0xFF, 0xC9, 0x00,
+ 0x13, 0x00, 0x8D, 0xFC, 0xAE, 0x47, 0x3E, 0x0C, 0x56, 0xF9, 0x48,
+ 0x04, 0x56, 0xFD, 0x78, 0x01, 0x5C, 0xFF, 0x2A, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x2B, 0x00, 0x58, 0xFF, 0x83, 0x01, 0x3C, 0xFD, 0x7E,
+ 0x04, 0xE6, 0xF8, 0x72, 0x0D, 0x52, 0x47, 0xBE, 0xFB, 0x7A, 0x00,
+ 0x90, 0x00, 0x43, 0xFF, 0x8F, 0x00, 0xB7, 0xFF, 0x11, 0x00, 0xFD,
+ 0xFF, 0x36, 0x00, 0x37, 0xFF, 0xE6, 0x01, 0x36, 0xFC, 0xF1, 0x06,
+ 0xF5, 0xF2, 0xA7, 0x22, 0xFF, 0x3B, 0xE4, 0xF2, 0x96, 0x05, 0x81,
+ 0xFD, 0xFD, 0x00, 0xB5, 0xFF, 0x0B, 0x00, 0x01, 0x00, 0xFE, 0xFF,
+ 0x1C, 0x00, 0x86, 0xFF, 0x59, 0x01, 0xEC, 0xFC, 0x6F, 0x06, 0xDC,
+ 0xF1, 0x04, 0x37, 0xF3, 0x28, 0xFC, 0xF1, 0x28, 0x07, 0x37, 0xFC,
+ 0xD8, 0x01, 0x41, 0xFF, 0x33, 0x00, 0xFD, 0xFF, 0x0B, 0x00, 0xD3,
+ 0xFF, 0x49, 0x00, 0xD4, 0xFF, 0x88, 0xFF, 0x49, 0x02, 0x4B, 0xF8,
+ 0x0D, 0x45, 0x68, 0x13, 0xDF, 0xF6, 0x6C, 0x05, 0xCC, 0xFC, 0xB4,
+ 0x01, 0x45, 0xFF, 0x31, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x23, 0x00,
+ 0x74, 0xFF, 0x3A, 0x01, 0xDD, 0xFD, 0x39, 0x03, 0x7B, 0xFB, 0xC1,
+ 0x06, 0xC7, 0x48, 0xCF, 0x00, 0x0D, 0xFE, 0xE3, 0x01, 0x8E, 0xFE,
+ 0xE7, 0x00, 0x95, 0xFF, 0x1A, 0x00, 0xFE, 0xFF, 0x36, 0x00, 0x38,
+ 0xFF, 0xDA, 0x01, 0x69, 0xFC, 0x57, 0x06, 0xAF, 0xF4, 0xF5, 0x1A,
+ 0x1D, 0x41, 0x11, 0xF5, 0x25, 0x04, 0x6C, 0xFE, 0x74, 0x00, 0xF9,
+ 0xFF, 0xF1, 0xFF, 0x05, 0x00, 0xFD, 0xFF, 0x2A, 0x00, 0x5C, 0xFF,
+ 0xAA, 0x01, 0x71, 0xFC, 0x07, 0x07, 0x7E, 0xF1, 0x44, 0x30, 0x44,
+ 0x30, 0x7E, 0xF1, 0x07, 0x07, 0x71, 0xFC, 0xAA, 0x01, 0x5C, 0xFF,
+ 0x2A, 0x00, 0xFD, 0xFF, 0x05, 0x00, 0xF1, 0xFF, 0xF9, 0xFF, 0x74,
+ 0x00, 0x6C, 0xFE, 0x25, 0x04, 0x11, 0xF5, 0x1D, 0x41, 0xF5, 0x1A,
+ 0xAF, 0xF4, 0x57, 0x06, 0x69, 0xFC, 0xDA, 0x01, 0x38, 0xFF, 0x36,
+ 0x00, 0xFE, 0xFF, 0x1A, 0x00, 0x95, 0xFF, 0xE7, 0x00, 0x8E, 0xFE,
+ 0xE3, 0x01, 0x0D, 0xFE, 0xCF, 0x00, 0xC7, 0x48, 0xC1, 0x06, 0x7B,
+ 0xFB, 0x39, 0x03, 0xDD, 0xFD, 0x3A, 0x01, 0x74, 0xFF, 0x23, 0x00,
+ 0x00, 0x00, 0xFF, 0xFF, 0x31, 0x00, 0x45, 0xFF, 0xB4, 0x01, 0xCC,
+ 0xFC, 0x6C, 0x05, 0xDF, 0xF6, 0x68, 0x13, 0x0D, 0x45, 0x4B, 0xF8,
+ 0x49, 0x02, 0x88, 0xFF, 0xD4, 0xFF, 0x49, 0x00, 0xD3, 0xFF, 0x0B,
+ 0x00, 0xFD, 0xFF, 0x33, 0x00, 0x41, 0xFF, 0xD8, 0x01, 0x37, 0xFC,
+ 0x28, 0x07, 0xFC, 0xF1, 0xF3, 0x28, 0x04, 0x37, 0xDC, 0xF1, 0x6F,
+ 0x06, 0xEC, 0xFC, 0x59, 0x01, 0x86, 0xFF, 0x1C, 0x00, 0xFE, 0xFF,
+ 0x01, 0x00, 0x0B, 0x00, 0xB5, 0xFF, 0xFD, 0x00, 0x81, 0xFD, 0x96,
+ 0x05, 0xE4, 0xF2, 0xFF, 0x3B, 0xA7, 0x22, 0xF5, 0xF2, 0xF1, 0x06,
+ 0x36, 0xFC, 0xE6, 0x01, 0x37, 0xFF, 0x36, 0x00, 0xFD, 0xFF, 0x11,
+ 0x00, 0xB7, 0xFF, 0x8F, 0x00, 0x43, 0xFF, 0x90, 0x00, 0x7A, 0x00,
+ 0xBE, 0xFB, 0x52, 0x47, 0x72, 0x0D, 0xE6, 0xF8, 0x7E, 0x04, 0x3C,
+ 0xFD, 0x83, 0x01, 0x58, 0xFF, 0x2B, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x2A, 0x00, 0x5C, 0xFF, 0x78, 0x01, 0x56, 0xFD, 0x48, 0x04, 0x56,
+ 0xF9, 0x3E, 0x0C, 0xAE, 0x47, 0x8D, 0xFC, 0x13, 0x00, 0xC9, 0x00,
+ 0x24, 0xFF, 0x9F, 0x00, 0xB1, 0xFF, 0x13, 0x00, 0xFD, 0xFF, 0x36,
+ 0x00, 0x36, 0xFF, 0xE6, 0x01, 0x3B, 0xFC, 0xDD, 0x06, 0x37, 0xF3,
+ 0x52, 0x21, 0xF6, 0x3C, 0x31, 0xF3, 0x5F, 0x05, 0xA6, 0xFD, 0xE8,
+ 0x00, 0xC0, 0xFF, 0x07, 0x00, 0x01, 0x00, 0xFE, 0xFF, 0x1F, 0x00,
+ 0x7E, 0xFF, 0x69, 0x01, 0xD2, 0xFC, 0x92, 0x06, 0xBB, 0xF1, 0xE6,
+ 0x35, 0x3F, 0x2A, 0xD8, 0xF1, 0x2A, 0x07, 0x3C, 0xFC, 0xD3, 0x01,
+ 0x45, 0xFF, 0x32, 0x00, 0xFD, 0xFF, 0x0A, 0x00, 0xD8, 0xFF, 0x3A,
+ 0x00, 0xF1, 0xFF, 0x54, 0xFF, 0xA2, 0x02, 0xA9, 0xF7, 0x77, 0x44,
+ 0xB1, 0x14, 0x77, 0xF6, 0x9A, 0x05, 0xB8, 0xFC, 0xBC, 0x01, 0x42,
+ 0xFF, 0x32, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x21, 0x00, 0x7A, 0xFF,
+ 0x2C, 0x01, 0xFB, 0xFD, 0xFE, 0x02, 0xEE, 0xFB, 0xAB, 0x05, 0xE1,
+ 0x48, 0xC7, 0x01, 0x9D, 0xFD, 0x1E, 0x02, 0x6F, 0xFE, 0xF5, 0x00,
+ 0x8F, 0xFF, 0x1B, 0x00, 0xFE, 0xFF, 0x35, 0x00, 0x3A, 0xFF, 0xD6,
+ 0x01, 0x77, 0xFC, 0x33, 0x06, 0x09, 0xF5, 0xA1, 0x19, 0xE1, 0x41,
+ 0x8D, 0xF5, 0xDA, 0x03, 0x9A, 0xFE, 0x5A, 0x00, 0x06, 0x00, 0xEC,
+ 0xFF, 0x06, 0x00, 0xFD, 0xFF, 0x2C, 0x00, 0x56, 0xFF, 0xB4, 0x01,
+ 0x62, 0xFC, 0x15, 0x07, 0x84, 0xF1, 0x09, 0x2F, 0x7B, 0x31, 0x7D,
+ 0xF1, 0xF5, 0x06, 0x82, 0xFC, 0x9E, 0x01, 0x62, 0xFF, 0x28, 0x00,
+ 0xFD, 0xFF, 0x04, 0x00, 0xF6, 0xFF, 0xED, 0xFF, 0x8E, 0x00, 0x3F,
+ 0xFE, 0x6D, 0x04, 0x9E, 0xF4, 0x4E, 0x40, 0x49, 0x1C, 0x5A, 0xF4,
+ 0x78, 0x06, 0x5C, 0xFC, 0xDF, 0x01, 0x37, 0xFF, 0x36, 0x00, 0xFE,
+ 0xFF, 0x18, 0x00, 0x9B, 0xFF, 0xD8, 0x00, 0xAD, 0xFE, 0xA7, 0x01,
+ 0x7D, 0xFE, 0xDD, 0xFF, 0xA1, 0x48, 0xDD, 0x07, 0x07, 0xFB, 0x73,
+ 0x03, 0xC0, 0xFD, 0x48, 0x01, 0x6F, 0xFF, 0x24, 0x00, 0x00, 0x00,
+ 0xFF, 0xFF, 0x30, 0x00, 0x49, 0xFF, 0xAB, 0x01, 0xE2, 0xFC, 0x3D,
+ 0x05, 0x48, 0xF7, 0x22, 0x12, 0x9B, 0x45, 0xF5, 0xF8, 0xED, 0x01,
+ 0xBE, 0xFF, 0xB6, 0xFF, 0x57, 0x00, 0xCD, 0xFF, 0x0C, 0x00, 0xFD,
+ 0xFF, 0x34, 0x00, 0x3E, 0xFF, 0xDD, 0x01, 0x33, 0xFC, 0x23, 0x07,
+ 0x26, 0xF2, 0xA6, 0x27, 0x1D, 0x38, 0x05, 0xF2, 0x49, 0x06, 0x08,
+ 0xFD, 0x47, 0x01, 0x8F, 0xFF, 0x18, 0x00, 0xFF, 0xFF, 0x00, 0x00,
+ 0x0E, 0x00, 0xAA, 0xFF, 0x12, 0x01, 0x5F, 0xFD, 0xCB, 0x05, 0x9E,
+ 0xF2, 0x03, 0x3B, 0xFC, 0x23, 0xB7, 0xF2, 0x03, 0x07, 0x33, 0xFC,
+ 0xE5, 0x01, 0x39, 0xFF, 0x36, 0x00, 0xFD, 0xFF, 0x10, 0x00, 0xBD,
+ 0xFF, 0x80, 0x00, 0x62, 0xFF, 0x57, 0x00, 0xDF, 0x00, 0xF7, 0xFA,
+ 0xED, 0x46, 0xAA, 0x0E, 0x76, 0xF8, 0xB2, 0x04, 0x23, 0xFD, 0x8F,
+ 0x01, 0x53, 0xFF, 0x2D, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x28, 0x00,
+ 0x61, 0xFF, 0x6C, 0x01, 0x71, 0xFD, 0x11, 0x04, 0xC8, 0xF9, 0x0E,
+ 0x0B, 0xFD, 0x47, 0x63, 0xFD, 0xAA, 0xFF, 0x03, 0x01, 0x05, 0xFF,
+ 0xAE, 0x00, 0xAC, 0xFF, 0x14, 0x00, 0xFD, 0xFF, 0x36, 0x00, 0x36,
+ 0xFF, 0xE5, 0x01, 0x41, 0xFC, 0xC6, 0x06, 0x7F, 0xF3, 0xFD, 0x1F,
+ 0xE4, 0x3D, 0x87, 0xF3, 0x24, 0x05, 0xCC, 0xFD, 0xD1, 0x00, 0xCB,
+ 0xFF, 0x02, 0x00, 0x02, 0x00, 0xFE, 0xFF, 0x21, 0x00, 0x76, 0xFF,
+ 0x79, 0x01, 0xBA, 0xFC, 0xB1, 0x06, 0xA0, 0xF1, 0xC3, 0x34, 0x89,
+ 0x2B, 0xB9, 0xF1, 0x29, 0x07, 0x44, 0xFC, 0xCC, 0x01, 0x49, 0xFF,
+ 0x31, 0x00, 0xFD, 0xFF, 0x09, 0x00, 0xDE, 0xFF, 0x2C, 0x00, 0x0D,
+ 0x00, 0x21, 0xFF, 0xF9, 0x02, 0x0F, 0xF7, 0xD4, 0x43, 0xFD, 0x15,
+ 0x13, 0xF6, 0xC5, 0x05, 0xA5, 0xFC, 0xC4, 0x01, 0x40, 0xFF, 0x33,
+ 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x20, 0x00, 0x7F, 0xFF, 0x1E, 0x01,
+ 0x19, 0xFE, 0xC3, 0x02, 0x61, 0xFC, 0x9B, 0x04, 0xF2, 0x48, 0xC6,
+ 0x02, 0x2C, 0xFD, 0x5A, 0x02, 0x50, 0xFE, 0x04, 0x01, 0x8A, 0xFF,
+ 0x1D, 0x00, 0xFE, 0xFF, 0x34, 0x00, 0x3B, 0xFF, 0xD0, 0x01, 0x86,
+ 0xFC, 0x0D, 0x06, 0x66, 0xF5, 0x50, 0x18, 0x9E, 0x42, 0x11, 0xF6,
+ 0x8C, 0x03, 0xC9, 0xFE, 0x3F, 0x00, 0x14, 0x00, 0xE7, 0xFF, 0x07,
+ 0x00, 0xFD, 0xFF, 0x2E, 0x00, 0x51, 0xFF, 0xBE, 0x01, 0x56, 0xFC,
+ 0x1F, 0x07, 0x92, 0xF1, 0xCA, 0x2D, 0xAF, 0x32, 0x84, 0xF1, 0xE0,
+ 0x06, 0x94, 0xFC, 0x91, 0x01, 0x69, 0xFF, 0x26, 0x00, 0xFD, 0xFF,
+ 0x03, 0x00, 0xFA, 0xFF, 0xE0, 0xFF, 0xA7, 0x00, 0x15, 0xFE, 0xB2,
+ 0x04, 0x32, 0xF4, 0x77, 0x3F, 0x9E, 0x1D, 0x07, 0xF4, 0x96, 0x06,
+ 0x51, 0xFC, 0xE2, 0x01, 0x36, 0xFF, 0x36, 0x00, 0xFE, 0xFF, 0x17,
+ 0x00, 0xA1, 0xFF, 0xC9, 0x00, 0xCD, 0xFE, 0x6C, 0x01, 0xEA, 0xFE,
+ 0xF3, 0xFE, 0x70, 0x48, 0xFF, 0x08, 0x94, 0xFA, 0xAD, 0x03, 0xA3,
+ 0xFD, 0x55, 0x01, 0x6A, 0xFF, 0x26, 0x00, 0x00, 0x00, 0xFF, 0xFF,
+ 0x2F, 0x00, 0x4C, 0xFF, 0xA1, 0x01, 0xF8, 0xFC, 0x0D, 0x05, 0xB3,
+ 0xF7, 0xDF, 0x10, 0x1D, 0x46, 0xA7, 0xF9, 0x8E, 0x01, 0xF4, 0xFF,
+ 0x98, 0xFF, 0x66, 0x00, 0xC7, 0xFF, 0x0E, 0x00, 0xFD, 0xFF, 0x35,
+ 0x00, 0x3C, 0xFF, 0xE1, 0x01, 0x31, 0xFC, 0x1A, 0x07, 0x56, 0xF2,
+ 0x55, 0x26, 0x2E, 0x39, 0x35, 0xF2, 0x1E, 0x06, 0x25, 0xFD, 0x35,
+ 0x01, 0x98, 0xFF, 0x15, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x12, 0x00,
+ 0xA0, 0xFF, 0x26, 0x01, 0x3E, 0xFD, 0xFB, 0x05, 0x60, 0xF2, 0xFD,
+ 0x39, 0x4E, 0x25, 0x7F, 0xF2, 0x11, 0x07, 0x31, 0xFC, 0xE3, 0x01,
+ 0x3A, 0xFF, 0x35, 0x00, 0xFD, 0xFF, 0x0F, 0x00, 0xC3, 0xFF, 0x71,
+ 0x00, 0x81, 0xFF, 0x1F, 0x00, 0x42, 0x01, 0x37, 0xFA, 0x7C, 0x46,
+ 0xE7, 0x0F, 0x08, 0xF8, 0xE6, 0x04, 0x0B, 0xFD, 0x99, 0x01, 0x4F,
+ 0xFF, 0x2E, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x27, 0x00, 0x66, 0xFF,
+ 0x5F, 0x01, 0x8D, 0xFD, 0xD9, 0x03, 0x3B, 0xFA, 0xE4, 0x09, 0x41,
+ 0x48, 0x41, 0xFE, 0x3F, 0xFF, 0x3E, 0x01, 0xE5, 0xFE, 0xBD, 0x00,
+ 0xA6, 0xFF, 0x16, 0x00, 0xFE, 0xFF, 0x36, 0x00, 0x36, 0xFF, 0xE4,
+ 0x01, 0x4A, 0xFC, 0xAC, 0x06, 0xCA, 0xF3, 0xA7, 0x1E, 0xCA, 0x3E,
+ 0xE4, 0xF3, 0xE5, 0x04, 0xF4, 0xFD, 0xBA, 0x00, 0xD7, 0xFF, 0xFE,
+ 0xFF, 0x03, 0x00, 0xFD, 0xFF, 0x24, 0x00, 0x6E, 0xFF, 0x87, 0x01,
+ 0xA4, 0xFC, 0xCD, 0x06, 0x8E, 0xF1, 0x99, 0x33, 0xCE, 0x2C, 0xA1,
+ 0xF1, 0x25, 0x07, 0x4D, 0xFC, 0xC4, 0x01, 0x4D, 0xFF, 0x2F, 0x00,
+ 0xFD, 0xFF, 0x08, 0x00, 0xE3, 0xFF, 0x1E, 0x00, 0x2A, 0x00, 0xEF,
+ 0xFE, 0x4D, 0x03, 0x7D, 0xF6, 0x2A, 0x43, 0x4B, 0x17, 0xB0, 0xF5,
+ 0xEF, 0x05, 0x93, 0xFC, 0xCB, 0x01, 0x3D, 0xFF, 0x34, 0x00, 0xFE,
+ 0xFF, 0x1E, 0x00, 0x85, 0xFF, 0x10, 0x01, 0x38, 0xFE, 0x88, 0x02,
+ 0xD3, 0xFC, 0x91, 0x03, 0xF7, 0x48, 0xCB, 0x03, 0xBA, 0xFC, 0x95,
+ 0x02, 0x31, 0xFE, 0x13, 0x01, 0x84, 0xFF, 0x1E, 0x00, 0x00, 0x00,
+ 0xFE, 0xFF, 0x34, 0x00, 0x3E, 0xFF, 0xC9, 0x01, 0x97, 0xFC, 0xE6,
+ 0x05, 0xC6, 0xF5, 0x00, 0x17, 0x50, 0x43, 0x9D, 0xF6, 0x3A, 0x03,
+ 0xFA, 0xFE, 0x23, 0x00, 0x21, 0x00, 0xE2, 0xFF, 0x08, 0x00, 0xFD,
+ 0xFF, 0x30, 0x00, 0x4C, 0xFF, 0xC6, 0x01, 0x4B, 0xFC, 0x26, 0x07,
+ 0xA5, 0xF1, 0x87, 0x2C, 0xDC, 0x33, 0x91, 0xF1, 0xC7, 0x06, 0xA9,
+ 0xFC, 0x84, 0x01, 0x70, 0xFF, 0x23, 0x00, 0xFE, 0xFF, 0x03, 0x00,
+ 0xFF, 0xFF, 0xD4, 0xFF, 0xBF, 0x00, 0xEB, 0xFD, 0xF3, 0x04, 0xCF,
+ 0xF3, 0x98, 0x3E, 0xF3, 0x1E, 0xB9, 0xF3, 0xB2, 0x06, 0x48, 0xFC,
+ 0xE4, 0x01, 0x36, 0xFF, 0x36, 0x00, 0xFE, 0xFF, 0x15, 0x00, 0xA7,
+ 0xFF, 0xB9, 0x00, 0xEC, 0xFE, 0x31, 0x01, 0x57, 0xFF, 0x0F, 0xFE,
+ 0x33, 0x48, 0x25, 0x0A, 0x21, 0xFA, 0xE5, 0x03, 0x87, 0xFD, 0x62,
+ 0x01, 0x65, 0xFF, 0x27, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x2E, 0x00,
+ 0x50, 0xFF, 0x97, 0x01, 0x10, 0xFD, 0xDA, 0x04, 0x20, 0xF8, 0xA0,
+ 0x0F, 0x97, 0x46, 0x61, 0xFA, 0x2D, 0x01, 0x2B, 0x00, 0x7A, 0xFF,
+ 0x75, 0x00, 0xC2, 0xFF, 0x0F, 0x00, 0xFD, 0xFF, 0x36, 0x00, 0x3A,
+ 0xFF, 0xE4, 0x01, 0x32, 0xFC, 0x0E, 0x07, 0x8B, 0xF2, 0x03, 0x25,
+ 0x38, 0x3A, 0x6D, 0xF2, 0xF1, 0x05, 0x45, 0xFD, 0x22, 0x01, 0xA2,
+ 0xFF, 0x11, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x16, 0x00, 0x96, 0xFF,
+ 0x39, 0x01, 0x1F, 0xFD, 0x28, 0x06, 0x2A, 0xF2, 0xF2, 0x38, 0xA0,
+ 0x26, 0x4B, 0xF2, 0x1C, 0x07, 0x32, 0xFC, 0xE0, 0x01, 0x3C, 0xFF,
+ 0x35, 0x00, 0xFD, 0xFF, 0x0D, 0x00, 0xC9, 0xFF, 0x63, 0x00, 0x9F,
+ 0xFF, 0xE8, 0xFF, 0xA3, 0x01, 0x7F, 0xF9, 0x02, 0x46, 0x27, 0x11,
+ 0x9B, 0xF7, 0x18, 0x05, 0xF3, 0xFC, 0xA3, 0x01, 0x4C, 0xFF, 0x2F,
+ 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x25, 0x00, 0x6B, 0xFF, 0x52, 0x01,
+ 0xA9, 0xFD, 0xA0, 0x03, 0xAE, 0xFA, 0xBE, 0x08, 0x7C, 0x48, 0x26,
+ 0xFF, 0xD2, 0xFE, 0x79, 0x01, 0xC6, 0xFE, 0xCC, 0x00, 0xA0, 0xFF,
+ 0x17, 0x00, 0xFE, 0xFF, 0x36, 0x00, 0x36, 0xFF, 0xE1, 0x01, 0x53,
+ 0xFC, 0x90, 0x06, 0x19, 0xF4, 0x52, 0x1D, 0xA8, 0x3F, 0x49, 0xF4,
+ 0xA3, 0x04, 0x1E, 0xFE, 0xA1, 0x00, 0xE3, 0xFF, 0xF9, 0xFF, 0x04,
+ 0x00, 0xFD, 0xFF, 0x26, 0x00, 0x67, 0xFF, 0x94, 0x01, 0x90, 0xFC,
+ 0xE5, 0x06, 0x81, 0xF1, 0x6B, 0x32, 0x11, 0x2E, 0x8E, 0xF1, 0x1D,
+ 0x07, 0x58, 0xFC, 0xBC, 0x01, 0x52, 0xFF, 0x2E, 0x00, 0xFD, 0xFF,
+ 0x07, 0x00, 0xE8, 0xFF, 0x11, 0x00, 0x45, 0x00, 0xBF, 0xFE, 0x9D,
+ 0x03, 0xF3, 0xF5, 0x75, 0x42, 0x9B, 0x18, 0x51, 0xF5, 0x16, 0x06,
+ 0x83, 0xFC, 0xD1, 0x01, 0x3B, 0xFF, 0x34, 0x00, 0xFE, 0xFF, 0x1D,
+ 0x00, 0x8B, 0xFF, 0x01, 0x01, 0x56, 0xFE, 0x4D, 0x02, 0x45, 0xFD,
+ 0x8D, 0x02, 0xF0, 0x48, 0xD7, 0x04, 0x47, 0xFC, 0xD1, 0x02, 0x12,
+ 0xFE, 0x21, 0x01, 0x7E, 0xFF, 0x20, 0x00, 0x00, 0x00, 0xFF, 0xFF,
+ 0x33, 0x00, 0x40, 0xFF, 0xC2, 0x01, 0xA9, 0xFC, 0xBC, 0x05, 0x29,
+ 0xF6, 0xB3, 0x15, 0xFA, 0x43, 0x31, 0xF7, 0xE6, 0x02, 0x2C, 0xFF,
+ 0x07, 0x00, 0x2F, 0x00, 0xDC, 0xFF, 0x09, 0x00, 0xFD, 0xFF, 0x31,
+ 0x00, 0x48, 0xFF, 0xCE, 0x01, 0x42, 0xFC, 0x2A, 0x07, 0xBF, 0xF1,
+ 0x40, 0x2B, 0x05, 0x35, 0xA6, 0xF1, 0xAB, 0x06, 0xBF, 0xFC, 0x75,
+ 0x01, 0x77, 0xFF, 0x21, 0x00, 0xFE, 0xFF, 0x02, 0x00, 0x03, 0x00,
+ 0xC8, 0xFF, 0xD6, 0x00, 0xC4, 0xFD, 0x31, 0x05, 0x73, 0xF3, 0xB0,
+ 0x3D, 0x49, 0x20, 0x6E, 0xF3, 0xCB, 0x06, 0x40, 0xFC, 0xE6, 0x01,
+ 0x36, 0xFF, 0x36, 0x00, 0xFD, 0xFF, 0x14, 0x00, 0xAD, 0xFF, 0xAA,
+ 0x00, 0x0C, 0xFF, 0xF7, 0x00, 0xC1, 0xFF, 0x33, 0xFD, 0xEC, 0x47,
+ 0x51, 0x0B, 0xAF, 0xF9, 0x1D, 0x04, 0x6B, 0xFD, 0x6E, 0x01, 0x60,
+ 0xFF, 0x29, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x2C, 0x00, 0x54, 0xFF,
+ 0x8C, 0x01, 0x29, 0xFD, 0xA7, 0x04, 0x8F, 0xF8, 0x64, 0x0E, 0x02,
+ 0x47, 0x22, 0xFB, 0xC9, 0x00, 0x64, 0x00, 0x5B, 0xFF, 0x84, 0x00,
+ 0xBC, 0xFF, 0x10, 0x00, 0xFD, 0xFF, 0x36, 0x00, 0x38, 0xFF, 0xE5,
+ 0x01, 0x33, 0xFC, 0xFF, 0x06, 0xC4, 0xF2, 0xB0, 0x23, 0x3B, 0x3B,
+ 0xAD, 0xF2, 0xBF, 0x05, 0x66, 0xFD, 0x0E, 0x01, 0xAC, 0xFF, 0x0E,
+ 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x19, 0x00, 0x8D, 0xFF, 0x4B, 0x01,
+ 0x01, 0xFD, 0x51, 0x06, 0xFB, 0xF1, 0xDF, 0x37, 0xF0, 0x27, 0x1C,
+ 0xF2, 0x24, 0x07, 0x34, 0xFC, 0xDC, 0x01, 0x3F, 0xFF, 0x34, 0x00,
+ 0xFD, 0xFF, 0x0C, 0x00, 0xCE, 0xFF, 0x54, 0x00, 0xBD, 0xFF, 0xB2,
+ 0xFF, 0x01, 0x02, 0xCF, 0xF8, 0x7D, 0x45, 0x6B, 0x12, 0x30, 0xF7,
+ 0x48, 0x05, 0xDD, 0xFC, 0xAD, 0x01, 0x48, 0xFF, 0x30, 0x00, 0xFF,
+ 0xFF, 0x00, 0x00, 0x24, 0x00, 0x70, 0xFF, 0x45, 0x01, 0xC6, 0xFD,
+ 0x66, 0x03, 0x21, 0xFB, 0x9E, 0x07, 0xAA, 0x48, 0x12, 0x00, 0x64,
+ 0xFE, 0xB4, 0x01, 0xA6, 0xFE, 0xDB, 0x00, 0x9A, 0xFF, 0x19, 0x00,
+ 0xFE, 0xFF, 0x36, 0x00, 0x37, 0xFF, 0xDE, 0x01, 0x5F, 0xFC, 0x70,
+ 0x06, 0x6C, 0xF4, 0xFD, 0x1B, 0x7D, 0x40, 0xB7, 0xF4, 0x5D, 0x04,
+ 0x49, 0xFE, 0x88, 0x00, 0xEF, 0xFF, 0xF5, 0xFF, 0x04, 0x00, 0xFD,
+ 0xFF, 0x29, 0x00, 0x61, 0xFF, 0xA1, 0x01, 0x7E, 0xFC, 0xF9, 0x06,
+ 0x7C, 0xF1, 0x38, 0x31, 0x50, 0x2F, 0x82, 0xF1, 0x12, 0x07, 0x65,
+ 0xFC, 0xB2, 0x01, 0x57, 0xFF, 0x2C, 0x00, 0xFD, 0xFF, 0x06, 0x00,
+ 0xED, 0xFF, 0x04, 0x00, 0x60, 0x00, 0x90, 0xFE, 0xEB, 0x03, 0x71,
+ 0xF5, 0xB7, 0x41, 0xED, 0x19, 0xF5, 0xF4, 0x3B, 0x06, 0x73, 0xFC,
+ 0xD7, 0x01, 0x39, 0xFF, 0x35, 0x00, 0xFE, 0xFF, 0x1B, 0x00, 0x91,
+ 0xFF, 0xF2, 0x00, 0x76, 0xFE, 0x11, 0x02, 0xB6, 0xFD, 0x8F, 0x01,
+ 0xDE, 0x48, 0xE9, 0x05, 0xD4, 0xFB, 0x0C, 0x03, 0xF4, 0xFD, 0x2F,
+ 0x01, 0x79, 0xFF, 0x22, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x32, 0x00,
+ 0x43, 0xFF, 0xBA, 0x01, 0xBC, 0xFC, 0x90, 0x05, 0x8E, 0xF6, 0x68,
+ 0x14, 0x99, 0x44, 0xCD, 0xF7, 0x8F, 0x02, 0x60, 0xFF, 0xEA, 0xFF,
+ 0x3E, 0x00, 0xD7, 0xFF, 0x0A, 0x00, 0xFD, 0xFF, 0x32, 0x00, 0x44,
+ 0xFF, 0xD4, 0x01, 0x3B, 0xFC, 0x2A, 0x07, 0xDF, 0xF1, 0xF6, 0x29,
+ 0x27, 0x36, 0xC1, 0xF1, 0x8B, 0x06, 0xD8, 0xFC, 0x66, 0x01, 0x80,
+ 0xFF, 0x1E, 0x00, 0xFE, 0xFF, 0x01, 0x00, 0x07, 0x00, 0xBD, 0xFF,
+ 0xED, 0x00, 0x9E, 0xFD, 0x6C, 0x05, 0x1F, 0xF3, 0xC0, 0x3C, 0x9E,
+ 0x21, 0x28, 0xF3, 0xE2, 0x06, 0x3A, 0xFC, 0xE6, 0x01, 0x37, 0xFF,
+ 0x36, 0x00, 0xFD, 0xFF, 0x12, 0x00, 0xB3, 0xFF, 0x9B, 0x00, 0x2B,
+ 0xFF, 0xBD, 0x00, 0x2A, 0x00, 0x5E, 0xFC, 0x9A, 0x47, 0x82, 0x0C,
+ 0x3D, 0xF9, 0x54, 0x04, 0x50, 0xFD, 0x7A, 0x01, 0x5B, 0xFF, 0x2A,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x2B, 0x00, 0x59, 0xFF, 0x81, 0x01,
+ 0x42, 0xFD, 0x72, 0x04, 0xFF, 0xF8, 0x2D, 0x0D, 0x69, 0x47, 0xEB,
+ 0xFB, 0x63, 0x00, 0x9D, 0x00, 0x3C, 0xFF, 0x93, 0x00, 0xB6, 0xFF,
+ 0x12, 0x00, 0xFD, 0xFF, 0x36, 0x00, 0x37, 0xFF, 0xE6, 0x01, 0x37,
+ 0xFC, 0xED, 0x06, 0x03, 0xF3, 0x5B, 0x22, 0x37, 0x3C, 0xF4, 0xF2,
+ 0x8A, 0x05, 0x89, 0xFD, 0xF9, 0x00, 0xB7, 0xFF, 0x0A, 0x00, 0x01,
+ 0x00, 0xFE, 0xFF, 0x1C, 0x00, 0x84, 0xFF, 0x5C, 0x01, 0xE6, 0xFC,
+ 0x77, 0x06, 0xD4, 0xF1, 0xC6, 0x36, 0x3E, 0x29, 0xF3, 0xF1, 0x29,
+ 0x07, 0x38, 0xFC, 0xD7, 0x01, 0x42, 0xFF, 0x33, 0x00, 0xFD, 0xFF,
+ 0x0B, 0x00, 0xD4, 0xFF, 0x46, 0x00, 0xDA, 0xFF, 0x7D, 0xFF, 0x5D,
+ 0x02, 0x26, 0xF8, 0xED, 0x44, 0xB1, 0x13, 0xC7, 0xF6, 0x77, 0x05,
+ 0xC8, 0xFC, 0xB6, 0x01, 0x45, 0xFF, 0x31, 0x00, 0xFF, 0xFF, 0x00,
+ 0x00, 0x22, 0x00, 0x76, 0xFF, 0x37, 0x01, 0xE4, 0xFD, 0x2C, 0x03,
+ 0x94, 0xFB, 0x83, 0x06, 0xCE, 0x48, 0x05, 0x01, 0xF5, 0xFD, 0xF0,
+ 0x01, 0x87, 0xFE, 0xEA, 0x00, 0x94, 0xFF, 0x1A, 0x00, 0xFE, 0xFF,
+ 0x35, 0x00, 0x38, 0xFF, 0xD9, 0x01, 0x6C, 0xFC, 0x4F, 0x06, 0xC3,
+ 0xF4, 0xA9, 0x1A, 0x49, 0x41, 0x2C, 0xF5, 0x15, 0x04, 0x76, 0xFE,
+ 0x6E, 0x00, 0xFC, 0xFF, 0xF0, 0xFF, 0x05, 0x00, 0xFD, 0xFF, 0x2B,
+ 0x00, 0x5A, 0xFF, 0xAC, 0x01, 0x6E, 0xFC, 0x0A, 0x07, 0x7E, 0xF1,
+ 0xFF, 0x2F, 0x8A, 0x30, 0x7D, 0xF1, 0x03, 0x07, 0x75, 0xFC, 0xA7,
+ 0x01, 0x5D, 0xFF, 0x2A, 0x00, 0xFD, 0xFF, 0x05, 0x00, 0xF2, 0xFF,
+ 0xF7, 0xFF, 0x7A, 0x00, 0x62, 0xFE, 0x35, 0x04, 0xF7, 0xF4, 0xEF,
+ 0x40, 0x40, 0x1B, 0x9C, 0xF4, 0x5E, 0x06, 0x66, 0xFC, 0xDB, 0x01,
+ 0x38, 0xFF, 0x36, 0x00, 0xFE, 0xFF, 0x1A, 0x00, 0x96, 0xFF, 0xE3,
+ 0x00, 0x95, 0xFE, 0xD5, 0x01, 0x26, 0xFE, 0x98, 0x00, 0xBF, 0x48,
+ 0x00, 0x07, 0x61, 0xFB, 0x46, 0x03, 0xD6, 0xFD, 0x3D, 0x01, 0x73,
+ 0xFF, 0x23, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x31, 0x00, 0x46, 0xFF,
+ 0xB2, 0x01, 0xD1, 0xFC, 0x62, 0x05, 0xF6, 0xF6, 0x20, 0x13, 0x2E,
+ 0x45, 0x70, 0xF8, 0x34, 0x02, 0x94, 0xFF, 0xCD, 0xFF, 0x4C, 0x00,
+ 0xD2, 0xFF, 0x0B, 0x00, 0xFD, 0xFF, 0x33, 0x00, 0x41, 0xFF, 0xDA,
+ 0x01, 0x36, 0xFC, 0x27, 0x07, 0x05, 0xF2, 0xAA, 0x28, 0x44, 0x37,
+ 0xE4, 0xF1, 0x67, 0x06, 0xF2, 0xFC, 0x55, 0x01, 0x88, 0xFF, 0x1B,
+ 0x00, 0xFE, 0xFF, 0x01, 0x00, 0x0B, 0x00, 0xB2, 0xFF, 0x02, 0x01,
+ 0x7A, 0xFD, 0xA2, 0x05, 0xD4, 0xF2, 0xC7, 0x3B, 0xF2, 0x22, 0xE7,
+ 0xF2, 0xF5, 0x06, 0x35, 0xFC, 0xE6, 0x01, 0x38, 0xFF, 0x36, 0x00,
+ 0xFD, 0xFF, 0x11, 0x00, 0xB9, 0xFF, 0x8C, 0x00, 0x4A, 0xFF, 0x83,
+ 0x00, 0x91, 0x00, 0x91, 0xFB, 0x3D, 0x47, 0xB7, 0x0D, 0xCD, 0xF8,
+ 0x89, 0x04, 0x36, 0xFD, 0x86, 0x01, 0x57, 0xFF, 0x2B, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x2A, 0x00, 0x5D, 0xFF, 0x75, 0x01, 0x5C, 0xFD,
+ 0x3C, 0x04, 0x70, 0xF9, 0xFA, 0x0B, 0xC0, 0x47, 0xBC, 0xFC, 0xFC,
+ 0xFF, 0xD6, 0x00, 0x1D, 0xFF, 0xA2, 0x00, 0xB0, 0xFF, 0x13, 0x00,
+ 0xFD, 0xFF, 0x36, 0x00, 0x36, 0xFF, 0xE6, 0x01, 0x3C, 0xFC, 0xD8,
+ 0x06, 0x47, 0xF3, 0x06, 0x21, 0x2A, 0x3D, 0x44, 0xF3, 0x52, 0x05,
+ 0xAE, 0xFD, 0xE3, 0x00, 0xC2, 0xFF, 0x06, 0x00, 0x01, 0x00, 0xFE,
+ 0xFF, 0x1F, 0x00, 0x7C, 0xFF, 0x6D, 0x01, 0xCD, 0xFC, 0x99, 0x06,
+ 0xB4, 0xF1, 0xA6, 0x35, 0x89, 0x2A, 0xD0, 0xF1, 0x2B, 0x07, 0x3E,
+ 0xFC, 0xD1, 0x01, 0x46, 0xFF, 0x32, 0x00, 0xFD, 0xFF, 0x0A, 0x00,
+ 0xD9, 0xFF, 0x37, 0x00, 0xF7, 0xFF, 0x49, 0xFF, 0xB6, 0x02, 0x86,
+ 0xF7, 0x53, 0x44, 0xFB, 0x14, 0x61, 0xF6, 0xA4, 0x05, 0xB4, 0xFC,
+ 0xBE, 0x01, 0x42, 0xFF, 0x32, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x21,
+ 0x00, 0x7B, 0xFF, 0x29, 0x01, 0x01, 0xFE, 0xF1, 0x02, 0x07, 0xFC,
+ 0x6E, 0x05, 0xE6, 0x48, 0xFF, 0x01, 0x84, 0xFD, 0x2C, 0x02, 0x68,
+ 0xFE, 0xF9, 0x00, 0x8E, 0xFF, 0x1C, 0x00, 0xFE, 0xFF, 0x35, 0x00,
+ 0x3A, 0xFF, 0xD4, 0x01, 0x7A, 0xFC, 0x2B, 0x06, 0x1E, 0xF5, 0x56,
+ 0x19, 0x0C, 0x42, 0xAA, 0xF5, 0xC9, 0x03, 0xA4, 0xFE, 0x54, 0x00,
+ 0x09, 0x00, 0xEB, 0xFF, 0x06, 0x00, 0xFD, 0xFF, 0x2D, 0x00, 0x55,
+ 0xFF, 0xB6, 0x01, 0x5F, 0xFC, 0x17, 0x07, 0x87, 0xF1, 0xC2, 0x2E,
+ 0xC0, 0x31, 0x7E, 0xF1, 0xF1, 0x06, 0x86, 0xFC, 0x9B, 0x01, 0x63,
+ 0xFF, 0x28, 0x00, 0xFD, 0xFF, 0x04, 0x00, 0xF7, 0xFF, 0xEA, 0xFF,
+ 0x93, 0x00, 0x36, 0xFE, 0x7D, 0x04, 0x85, 0xF4, 0x1F, 0x40, 0x94,
+ 0x1C, 0x47, 0xF4, 0x7E, 0x06, 0x5A, 0xFC, 0xDF, 0x01, 0x37, 0xFF,
+ 0x36, 0x00, 0xFE, 0xFF, 0x18, 0x00, 0x9C, 0xFF, 0xD4, 0x00, 0xB4,
+ 0xFE, 0x9A, 0x01, 0x95, 0xFE, 0xA8, 0xFF, 0x98, 0x48, 0x1D, 0x08,
+ 0xEE, 0xFA, 0x80, 0x03, 0xB9, 0xFD, 0x4B, 0x01, 0x6E, 0xFF, 0x25,
+ 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x30, 0x00, 0x4A, 0xFF, 0xA9, 0x01,
+ 0xE7, 0xFC, 0x33, 0x05, 0x60, 0xF7, 0xDA, 0x11, 0xB8, 0x45, 0x1C,
+ 0xF9, 0xD8, 0x01, 0xCA, 0xFF, 0xAF, 0xFF, 0x5A, 0x00, 0xCC, 0xFF,
+ 0x0D, 0x00, 0xFD, 0xFF, 0x34, 0x00, 0x3E, 0xFF, 0xDE, 0x01, 0x33,
+ 0xFC, 0x21, 0x07, 0x30, 0xF2, 0x5C, 0x27, 0x5B, 0x38, 0x0F, 0xF2,
+ 0x40, 0x06, 0x0E, 0xFD, 0x43, 0x01, 0x91, 0xFF, 0x18, 0x00, 0xFF,
+ 0xFF, 0x00, 0x00, 0x0F, 0x00, 0xA8, 0xFF, 0x17, 0x01, 0x57, 0xFD,
+ 0xD6, 0x05, 0x90, 0xF2, 0xC8, 0x3A, 0x46, 0x24, 0xAA, 0xF2, 0x06,
+ 0x07, 0x32, 0xFC, 0xE5, 0x01, 0x39, 0xFF, 0x36, 0x00, 0xFD, 0xFF,
+ 0x10, 0x00, 0xBE, 0xFF, 0x7D, 0x00, 0x69, 0xFF, 0x4B, 0x00, 0xF6,
+ 0x00, 0xCB, 0xFA, 0xD3, 0x46, 0xF0, 0x0E, 0x5E, 0xF8, 0xBE, 0x04,
+ 0x1E, 0xFD, 0x91, 0x01, 0x52, 0xFF, 0x2D, 0x00, 0xFF, 0xFF, 0x00,
+ 0x00, 0x28, 0x00, 0x62, 0xFF, 0x69, 0x01, 0x77, 0xFD, 0x04, 0x04,
+ 0xE2, 0xF9, 0xCB, 0x0A, 0x0D, 0x48, 0x94, 0xFD, 0x92, 0xFF, 0x10,
+ 0x01, 0xFE, 0xFE, 0xB1, 0x00, 0xAA, 0xFF, 0x15, 0x00, 0xFD, 0xFF,
+ 0x36, 0x00, 0x36, 0xFF, 0xE5, 0x01, 0x43, 0xFC, 0xC0, 0x06, 0x8F,
+ 0xF3, 0xB1, 0x1F, 0x18, 0x3E, 0x9B, 0xF3, 0x16, 0x05, 0xD5, 0xFD,
+ 0xCC, 0x00, 0xCE, 0xFF, 0x01, 0x00, 0x02, 0x00, 0xFE, 0xFF, 0x22,
+ 0x00, 0x74, 0xFF, 0x7C, 0x01, 0xB5, 0xFC, 0xB8, 0x06, 0x9C, 0xF1,
+ 0x81, 0x34, 0xD1, 0x2B, 0xB3, 0xF1, 0x29, 0x07, 0x46, 0xFC, 0xCA,
+ 0x01, 0x4A, 0xFF, 0x30, 0x00, 0xFD, 0xFF, 0x09, 0x00, 0xDF, 0xFF,
+ 0x29, 0x00, 0x14, 0x00, 0x16, 0xFF, 0x0C, 0x03, 0xEE, 0xF6, 0xB0,
+ 0x43, 0x47, 0x16, 0xFC, 0xF5, 0xCF, 0x05, 0xA1, 0xFC, 0xC6, 0x01,
+ 0x3F, 0xFF, 0x33, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x1F, 0x00, 0x81,
+ 0xFF, 0x1B, 0x01, 0x20, 0xFE, 0xB6, 0x02, 0x7A, 0xFC, 0x5F, 0x04,
+ 0xF4, 0x48, 0xFF, 0x02, 0x13, 0xFD, 0x67, 0x02, 0x49, 0xFE, 0x07,
+ 0x01, 0x88, 0xFF, 0x1D, 0x00, 0xFE, 0xFF, 0x34, 0x00, 0x3C, 0xFF,
+ 0xCF, 0x01, 0x8A, 0xFC, 0x05, 0x06, 0x7B, 0xF5, 0x06, 0x18, 0xC7,
+ 0x42, 0x2F, 0xF6, 0x7A, 0x03, 0xD4, 0xFE, 0x39, 0x00, 0x17, 0x00,
+ 0xE6, 0xFF, 0x07, 0x00, 0xFD, 0xFF, 0x2E, 0x00, 0x50, 0xFF, 0xC0,
+ 0x01, 0x53, 0xFC, 0x21, 0x07, 0x96, 0xF1, 0x82, 0x2D, 0xF2, 0x32,
+ 0x86, 0xF1, 0xDB, 0x06, 0x99, 0xFC, 0x8E, 0x01, 0x6A, 0xFF, 0x25,
+ 0x00, 0xFD, 0xFF, 0x03, 0x00, 0xFB, 0xFF, 0xDE, 0xFF, 0xAC, 0x00,
+ 0x0B, 0xFE, 0xC1, 0x04, 0x1B, 0xF4, 0x47, 0x3F, 0xEA, 0x1D, 0xF5,
+ 0xF3, 0x9C, 0x06, 0x4F, 0xFC, 0xE2, 0x01, 0x36, 0xFF, 0x36, 0x00,
+ 0xFE, 0xFF, 0x16, 0x00, 0xA2, 0xFF, 0xC5, 0x00, 0xD4, 0xFE, 0x5F,
+ 0x01, 0x03, 0xFF, 0xBF, 0xFE, 0x63, 0x48, 0x40, 0x09, 0x7B, 0xFA,
+ 0xB9, 0x03, 0x9D, 0xFD, 0x58, 0x01, 0x69, 0xFF, 0x26, 0x00, 0x00,
+ 0x00, 0xFF, 0xFF, 0x2E, 0x00, 0x4D, 0xFF, 0x9F, 0x01, 0xFE, 0xFC,
+ 0x02, 0x05, 0xCB, 0xF7, 0x98, 0x10, 0x39, 0x46, 0xD0, 0xF9, 0x78,
+ 0x01, 0x00, 0x00, 0x91, 0xFF, 0x69, 0x00, 0xC6, 0xFF, 0x0E, 0x00,
+ 0xFD, 0xFF, 0x35, 0x00, 0x3B, 0xFF, 0xE2, 0x01, 0x31, 0xFC, 0x17,
+ 0x07, 0x61, 0xF2, 0x0A, 0x26, 0x6A, 0x39, 0x41, 0xF2, 0x15, 0x06,
+ 0x2C, 0xFD, 0x31, 0x01, 0x9B, 0xFF, 0x14, 0x00, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0x13, 0x00, 0x9E, 0xFF, 0x2B, 0x01, 0x37, 0xFD, 0x05, 0x06,
+ 0x54, 0xF2, 0xC2, 0x39, 0x99, 0x25, 0x73, 0xF2, 0x14, 0x07, 0x31,
+ 0xFC, 0xE3, 0x01, 0x3B, 0xFF, 0x35, 0x00, 0xFD, 0xFF, 0x0E, 0x00,
+ 0xC4, 0xFF, 0x6E, 0x00, 0x87, 0xFF, 0x13, 0x00, 0x58, 0x01, 0x0D,
+ 0xFA, 0x61, 0x46, 0x2D, 0x10, 0xF0, 0xF7, 0xF1, 0x04, 0x05, 0xFD,
+ 0x9C, 0x01, 0x4E, 0xFF, 0x2E, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x27,
+ 0x00, 0x67, 0xFF, 0x5C, 0x01, 0x93, 0xFD, 0xCC, 0x03, 0x54, 0xFA,
+ 0xA2, 0x09, 0x4F, 0x48, 0x73, 0xFE, 0x27, 0xFF, 0x4B, 0x01, 0xDE,
+ 0xFE, 0xC0, 0x00, 0xA4, 0xFF, 0x16, 0x00, 0xFE, 0xFF, 0x36, 0x00,
+ 0x36, 0xFF, 0xE3, 0x01, 0x4C, 0xFC, 0xA6, 0x06, 0xDB, 0xF3, 0x5B,
+ 0x1E, 0xFC, 0x3E, 0xFA, 0xF3, 0xD7, 0x04, 0xFD, 0xFD, 0xB4, 0x00,
+ 0xD9, 0xFF, 0xFD, 0xFF, 0x03, 0x00, 0xFD, 0xFF, 0x25, 0x00, 0x6D,
+ 0xFF, 0x8A, 0x01, 0x9F, 0xFC, 0xD3, 0x06, 0x8A, 0xF1, 0x57, 0x33,
+ 0x17, 0x2D, 0x9C, 0xF1, 0x24, 0x07, 0x4F, 0xFC, 0xC3, 0x01, 0x4E,
+ 0xFF, 0x2F, 0x00, 0xFD, 0xFF, 0x08, 0x00, 0xE4, 0xFF, 0x1B, 0x00,
+ 0x30, 0x00, 0xE4, 0xFE, 0x5F, 0x03, 0x5E, 0xF6, 0x02, 0x43, 0x96,
+ 0x17, 0x9B, 0xF5, 0xF8, 0x05, 0x8F, 0xFC, 0xCC, 0x01, 0x3D, 0xFF,
+ 0x34, 0x00, 0xFE, 0xFF, 0x1E, 0x00, 0x86, 0xFF, 0x0C, 0x01, 0x3E,
+ 0xFE, 0x7B, 0x02, 0xED, 0xFC, 0x56, 0x03, 0xF5, 0x48, 0x06, 0x04,
+ 0xA1, 0xFC, 0xA3, 0x02, 0x2A, 0xFE, 0x16, 0x01, 0x83, 0xFF, 0x1F,
+ 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x33, 0x00, 0x3E, 0xFF, 0xC8, 0x01,
+ 0x9B, 0xFC, 0xDD, 0x05, 0xDC, 0xF5, 0xB6, 0x16, 0x77, 0x43, 0xBD,
+ 0xF6, 0x28, 0x03, 0x05, 0xFF, 0x1D, 0x00, 0x25, 0x00, 0xE1, 0xFF,
+ 0x08, 0x00, 0xFD, 0xFF, 0x30, 0x00, 0x4B, 0xFF, 0xC8, 0x01, 0x49,
+ 0xFC, 0x27, 0x07, 0xAB, 0xF1, 0x3E, 0x2C, 0x1E, 0x34, 0x95, 0xF1,
+ 0xC1, 0x06, 0xAE, 0xFC, 0x81, 0x01, 0x71, 0xFF, 0x23, 0x00, 0xFE,
+ 0xFF, 0x02, 0x00, 0x00, 0x00, 0xD2, 0xFF, 0xC4, 0x00, 0xE2, 0xFD,
+ 0x01, 0x05, 0xBA, 0xF3, 0x64, 0x3E, 0x3F, 0x1F, 0xA8, 0xF3, 0xB8,
+ 0x06, 0x46, 0xFC, 0xE5, 0x01, 0x36, 0xFF, 0x36, 0x00, 0xFD, 0xFF,
+ 0x15, 0x00, 0xA8, 0xFF, 0xB6, 0x00, 0xF3, 0xFE, 0x24, 0x01, 0x6E,
+ 0xFF, 0xDE, 0xFD, 0x25, 0x48, 0x68, 0x0A, 0x08, 0xFA, 0xF2, 0x03,
+ 0x81, 0xFD, 0x65, 0x01, 0x64, 0xFF, 0x28, 0x00, 0x00, 0x00, 0xFF,
+ 0xFF, 0x2D, 0x00, 0x51, 0xFF, 0x95, 0x01, 0x15, 0xFD, 0xCF, 0x04,
+ 0x39, 0xF8, 0x59, 0x0F, 0xAF, 0x46, 0x8B, 0xFA, 0x17, 0x01, 0x38,
+ 0x00, 0x73, 0xFF, 0x78, 0x00, 0xC0, 0xFF, 0x0F, 0x00, 0xFD, 0xFF,
+ 0x36, 0x00, 0x39, 0xFF, 0xE4, 0x01, 0x32, 0xFC, 0x0B, 0x07, 0x97,
+ 0xF2, 0xB8, 0x24, 0x71, 0x3A, 0x7B, 0xF2, 0xE6, 0x05, 0x4C, 0xFD,
+ 0x1D, 0x01, 0xA4, 0xFF, 0x11, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x16,
+ 0x00, 0x94, 0xFF, 0x3D, 0x01, 0x18, 0xFD, 0x32, 0x06, 0x1F, 0xF2,
+ 0xB5, 0x38, 0xEB, 0x26, 0x40, 0xF2, 0x1E, 0x07, 0x32, 0xFC, 0xDF,
+ 0x01, 0x3D, 0xFF, 0x35, 0x00, 0xFD, 0xFF, 0x0D, 0x00, 0xCA, 0xFF,
+ 0x5F, 0x00, 0xA5, 0xFF, 0xDC, 0xFF, 0xB8, 0x01, 0x57, 0xF9, 0xE5,
+ 0x45, 0x6E, 0x11, 0x83, 0xF7, 0x23, 0x05, 0xEE, 0xFC, 0xA6, 0x01,
+ 0x4B, 0xFF, 0x2F, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x25, 0x00, 0x6C,
+ 0xFF, 0x4F, 0x01, 0xB0, 0xFD, 0x93, 0x03, 0xC7, 0xFA, 0x7D, 0x08,
+ 0x86, 0x48, 0x5A, 0xFF, 0xBA, 0xFE, 0x86, 0x01, 0xBF, 0xFE, 0xCF,
+ 0x00, 0x9E, 0xFF, 0x17, 0x00, 0xFE, 0xFF, 0x36, 0x00, 0x37, 0xFF,
+ 0xE0, 0x01, 0x56, 0xFC, 0x89, 0x06, 0x2B, 0xF4, 0x06, 0x1D, 0xD7,
+ 0x3F, 0x61, 0xF4, 0x94, 0x04, 0x27, 0xFE, 0x9C, 0x00, 0xE6, 0xFF,
+ 0xF8, 0xFF, 0x04, 0x00, 0xFD, 0xFF, 0x27, 0x00, 0x66, 0xFF, 0x97,
+ 0x01, 0x8C, 0xFC, 0xEA, 0x06, 0x80, 0xF1, 0x26, 0x32, 0x58, 0x2E,
+ 0x8B, 0xF1, 0x1B, 0x07, 0x5B, 0xFC, 0xBA, 0x01, 0x53, 0xFF, 0x2D,
+ 0x00, 0xFD, 0xFF, 0x07, 0x00, 0xE9, 0xFF, 0x0E, 0x00, 0x4B, 0x00,
+ 0xB4, 0xFE, 0xAF, 0x03, 0xD5, 0xF5, 0x4D, 0x42, 0xE6, 0x18, 0x3C,
+ 0xF5, 0x1F, 0x06, 0x7F, 0xFC, 0xD3, 0x01, 0x3B, 0xFF, 0x35, 0x00,
+ 0xFE, 0xFF, 0x1C, 0x00, 0x8C, 0xFF, 0xFE, 0x00, 0x5D, 0xFE, 0x3F,
+ 0x02, 0x5E, 0xFD, 0x54, 0x02, 0xEC, 0x48, 0x13, 0x05, 0x2E, 0xFC,
+ 0xDE, 0x02, 0x0C, 0xFE, 0x24, 0x01, 0x7D, 0xFF, 0x20, 0x00, 0x00,
+ 0x00, 0xFF, 0xFF, 0x32, 0x00, 0x41, 0xFF, 0xC1, 0x01, 0xAD, 0xFC,
+ 0xB2, 0x05, 0x3F, 0xF6, 0x69, 0x15, 0x1F, 0x44, 0x53, 0xF7, 0xD3,
+ 0x02, 0x38, 0xFF, 0x01, 0x00, 0x33, 0x00, 0xDB, 0xFF, 0x09, 0x00,
+ 0xFD, 0xFF, 0x31, 0x00, 0x47, 0xFF, 0xCF, 0x01, 0x40, 0xFC, 0x2A,
+ 0x07, 0xC6, 0xF1, 0xF7, 0x2A, 0x46, 0x35, 0xAB, 0xF1, 0xA4, 0x06,
+ 0xC4, 0xFC, 0x72, 0x01, 0x79, 0xFF, 0x20, 0x00, 0xFE, 0xFF, 0x02,
+ 0x00, 0x04, 0x00, 0xC6, 0xFF, 0xDB, 0x00, 0xBB, 0xFD, 0x3E, 0x05,
+ 0x60, 0xF3, 0x7B, 0x3D, 0x94, 0x20, 0x5E, 0xF3, 0xD0, 0x06, 0x3E,
+ 0xFC, 0xE6, 0x01, 0x36, 0xFF, 0x36, 0x00, 0xFD, 0xFF, 0x14, 0x00,
+ 0xAE, 0xFF, 0xA7, 0x00, 0x12, 0xFF, 0xEA, 0x00, 0xD9, 0xFF, 0x03,
+ 0xFD, 0xDC, 0x47, 0x95, 0x0B, 0x96, 0xF9, 0x29, 0x04, 0x65, 0xFD,
+ 0x71, 0x01, 0x5F, 0xFF, 0x29, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x2C,
+ 0x00, 0x55, 0xFF, 0x8A, 0x01, 0x2E, 0xFD, 0x9B, 0x04, 0xA8, 0xF8,
+ 0x1F, 0x0E, 0x1A, 0x47, 0x4E, 0xFB, 0xB3, 0x00, 0x70, 0x00, 0x54,
+ 0xFF, 0x87, 0x00, 0xBB, 0xFF, 0x11, 0x00, 0xFD, 0xFF, 0x36, 0x00,
+ 0x38, 0xFF, 0xE6, 0x01, 0x34, 0xFC, 0xFB, 0x06, 0xD2, 0xF2, 0x64,
+ 0x23, 0x73, 0x3B, 0xBC, 0xF2, 0xB4, 0x05, 0x6E, 0xFD, 0x09, 0x01,
+ 0xAF, 0xFF, 0x0D, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x1A, 0x00, 0x8B,
+ 0xFF, 0x4F, 0x01, 0xFB, 0xFC, 0x5A, 0x06, 0xF2, 0xF1, 0xA0, 0x37,
+ 0x3A, 0x28, 0x13, 0xF2, 0x25, 0x07, 0x35, 0xFC, 0xDB, 0x01, 0x40,
+ 0xFF, 0x34, 0x00, 0xFD, 0xFF, 0x0C, 0x00, 0xD0, 0xFF, 0x51, 0x00,
+ 0xC3, 0xFF, 0xA6, 0xFF, 0x16, 0x02, 0xA9, 0xF8, 0x5C, 0x45, 0xB2,
+ 0x12, 0x19, 0xF7, 0x52, 0x05, 0xD8, 0xFC, 0xAF, 0x01, 0x47, 0xFF,
+ 0x30, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x24, 0x00, 0x71, 0xFF, 0x42,
+ 0x01, 0xCD, 0xFD, 0x59, 0x03, 0x3B, 0xFB, 0x5E, 0x07, 0xB3, 0x48,
+ 0x48, 0x00, 0x4B, 0xFE, 0xC2, 0x01, 0x9F, 0xFE, 0xDE, 0x00, 0x98,
+ 0xFF, 0x19, 0x00, 0xFE, 0xFF, 0x36, 0x00, 0x38, 0xFF, 0xDD, 0x01,
+ 0x62, 0xFC, 0x69, 0x06, 0x7F, 0xF4, 0xB2, 0x1B, 0xAB, 0x40, 0xD0,
+ 0xF4, 0x4E, 0x04, 0x53, 0xFE, 0x83, 0x00, 0xF2, 0xFF, 0xF4, 0xFF,
+ 0x05, 0x00, 0xFD, 0xFF, 0x29, 0x00, 0x5F, 0xFF, 0xA3, 0x01, 0x7A,
+ 0xFC, 0xFD, 0x06, 0x7C, 0xF1, 0xF2, 0x30, 0x96, 0x2F, 0x80, 0xF1,
+ 0x0F, 0x07, 0x69, 0xFC, 0xB0, 0x01, 0x59, 0xFF, 0x2B, 0x00, 0xFD,
+ 0xFF, 0x06, 0x00, 0xEE, 0xFF, 0x01, 0x00, 0x66, 0x00, 0x85, 0xFE,
+ 0xFC, 0x03, 0x55, 0xF5, 0x8C, 0x41, 0x38, 0x1A, 0xE1, 0xF4, 0x43,
+ 0x06, 0x70, 0xFC, 0xD8, 0x01, 0x39, 0xFF, 0x35, 0x00, 0xFE, 0xFF,
+ 0x1B, 0x00, 0x92, 0xFF, 0xEF, 0x00, 0x7D, 0xFE, 0x04, 0x02, 0xCF,
+ 0xFD, 0x58, 0x01, 0xD7, 0x48, 0x26, 0x06, 0xBB, 0xFB, 0x19, 0x03,
+ 0xED, 0xFD, 0x32, 0x01, 0x77, 0xFF, 0x22, 0x00, 0x00, 0x00, 0xFF,
+ 0xFF, 0x32, 0x00, 0x44, 0xFF, 0xB9, 0x01, 0xC1, 0xFC, 0x86, 0x05,
+ 0xA5, 0xF6, 0x1E, 0x14, 0xBA, 0x44, 0xF0, 0xF7, 0x7B, 0x02, 0x6B,
+ 0xFF, 0xE4, 0xFF, 0x41, 0x00, 0xD6, 0xFF, 0x0B, 0x00, 0xFD, 0xFF,
+ 0x33, 0x00, 0x43, 0xFF, 0xD5, 0x01, 0x3A, 0xFC, 0x2A, 0x07, 0xE7,
+ 0xF1, 0xAC, 0x29, 0x66, 0x36, 0xC9, 0xF1, 0x83, 0x06, 0xDD, 0xFC,
+ 0x62, 0x01, 0x81, 0xFF, 0x1D, 0x00, 0xFE, 0xFF, 0x01, 0x00, 0x08,
+ 0x00, 0xBB, 0xFF, 0xF1, 0x00, 0x96, 0xFD, 0x78, 0x05, 0x0E, 0xF3,
+ 0x8A, 0x3C, 0xEA, 0x21, 0x19, 0xF3, 0xE6, 0x06, 0x38, 0xFC, 0xE6,
+ 0x01, 0x37, 0xFF, 0x36, 0x00, 0xFD, 0xFF, 0x12, 0x00, 0xB4, 0xFF,
+ 0x98, 0x00, 0x32, 0xFF, 0xB0, 0x00, 0x41, 0x00, 0x30, 0xFC, 0x86,
+ 0x47, 0xC6, 0x0C, 0x24, 0xF9, 0x60, 0x04, 0x4B, 0xFD, 0x7D, 0x01,
+ 0x5A, 0xFF, 0x2A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2B, 0x00, 0x5A,
+ 0xFF, 0x7E, 0x01, 0x48, 0xFD, 0x66, 0x04, 0x18, 0xF9, 0xE8, 0x0C,
+ 0x7C, 0x47, 0x19, 0xFC, 0x4D, 0x00, 0xA9, 0x00, 0x35, 0xFF, 0x96,
+ 0x00, 0xB5, 0xFF, 0x12, 0x00, 0xFD, 0xFF, 0x36, 0x00, 0x37, 0xFF,
+ 0xE6, 0x01, 0x38, 0xFC, 0xE9, 0x06, 0x12, 0xF3, 0x10, 0x22, 0x6E,
+ 0x3C, 0x05, 0xF3, 0x7E, 0x05, 0x91, 0xFD, 0xF4, 0x00, 0xBA, 0xFF,
+ 0x09, 0x00, 0x01, 0x00, 0xFE, 0xFF, 0x1D, 0x00, 0x82, 0xFF, 0x60,
+ 0x01, 0xE0, 0xFC, 0x7F, 0x06, 0xCC, 0xF1, 0x85, 0x36, 0x87, 0x29,
+ 0xEB, 0xF1, 0x2A, 0x07, 0x39, 0xFC, 0xD6, 0x01, 0x43, 0xFF, 0x33,
+ 0x00, 0xFD, 0xFF, 0x0B, 0x00, 0xD5, 0xFF, 0x42, 0x00, 0xE1, 0xFF,
+ 0x71, 0xFF, 0x71, 0x02, 0x02, 0xF8, 0xCC, 0x44, 0xFA, 0x13, 0xB0,
+ 0xF6, 0x81, 0x05, 0xC3, 0xFC, 0xB8, 0x01, 0x44, 0xFF, 0x31, 0x00,
+ 0xFF, 0xFF, 0x00, 0x00, 0x22, 0x00, 0x77, 0xFF, 0x34, 0x01, 0xEA,
+ 0xFD, 0x1F, 0x03, 0xAE, 0xFB, 0x45, 0x06, 0xD5, 0x48, 0x3C, 0x01,
+ 0xDC, 0xFD, 0xFD, 0x01, 0x80, 0xFE, 0xED, 0x00, 0x93, 0xFF, 0x1B,
+ 0x00, 0xFE, 0xFF, 0x35, 0x00, 0x39, 0xFF, 0xD8, 0x01, 0x6F, 0xFC,
+ 0x47, 0x06, 0xD7, 0xF4, 0x5D, 0x1A, 0x74, 0x41, 0x48, 0xF5, 0x04,
+ 0x04, 0x80, 0xFE, 0x69, 0x00, 0xFF, 0xFF, 0xEF, 0xFF, 0x05, 0x00,
+ 0xFD, 0xFF, 0x2B, 0x00, 0x59, 0xFF, 0xAE, 0x01, 0x6A, 0xFC, 0x0D,
+ 0x07, 0x80, 0xF1, 0xB8, 0x2F, 0xCF, 0x30, 0x7D, 0xF1, 0xFF, 0x06,
+ 0x78, 0xFC, 0xA5, 0x01, 0x5F, 0xFF, 0x29, 0x00, 0xFD, 0xFF, 0x05,
+ 0x00, 0xF3, 0xFF, 0xF4, 0xFF, 0x80, 0x00, 0x58, 0xFE, 0x46, 0x04,
+ 0xDD, 0xF4, 0xC3, 0x40, 0x8C, 0x1B, 0x89, 0xF4, 0x66, 0x06, 0x63,
+ 0xFC, 0xDC, 0x01, 0x38, 0xFF, 0x36, 0x00, 0xFE, 0xFF, 0x19, 0x00,
+ 0x98, 0xFF, 0xE0, 0x00, 0x9C, 0xFE, 0xC8, 0x01, 0x3F, 0xFE, 0x62,
+ 0x00, 0xB8, 0x48, 0x3F, 0x07, 0x47, 0xFB, 0x53, 0x03, 0xD0, 0xFD,
+ 0x40, 0x01, 0x72, 0xFF, 0x23, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x30,
+ 0x00, 0x47, 0xFF, 0xB0, 0x01, 0xD6, 0xFC, 0x58, 0x05, 0x0D, 0xF7,
+ 0xD7, 0x12, 0x4E, 0x45, 0x96, 0xF8, 0x20, 0x02, 0xA0, 0xFF, 0xC7,
+ 0xFF, 0x4F, 0x00, 0xD0, 0xFF, 0x0C, 0x00, 0xFD, 0xFF, 0x34, 0x00,
+ 0x40, 0xFF, 0xDB, 0x01, 0x35, 0xFC, 0x26, 0x07, 0x0E, 0xF2, 0x60,
+ 0x28, 0x82, 0x37, 0xED, 0xF1, 0x5E, 0x06, 0xF8, 0xFC, 0x51, 0x01,
+ 0x8A, 0xFF, 0x1A, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x0C, 0x00, 0xB0,
+ 0xFF, 0x07, 0x01, 0x72, 0xFD, 0xAE, 0x05, 0xC4, 0xF2, 0x90, 0x3B,
+ 0x3F, 0x23, 0xD9, 0xF2, 0xF9, 0x06, 0x34, 0xFC, 0xE6, 0x01, 0x38,
+ 0xFF, 0x36, 0x00, 0xFD, 0xFF, 0x11, 0x00, 0xBA, 0xFF, 0x89, 0x00,
+ 0x51, 0xFF, 0x77, 0x00, 0xA7, 0x00, 0x64, 0xFB, 0x26, 0x47, 0xFC,
+ 0x0D, 0xB4, 0xF8, 0x95, 0x04, 0x31, 0xFD, 0x88, 0x01, 0x56, 0xFF,
+ 0x2C, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x29, 0x00, 0x5E, 0xFF, 0x72,
+ 0x01, 0x62, 0xFD, 0x2F, 0x04, 0x89, 0xF9, 0xB6, 0x0B, 0xD2, 0x47,
+ 0xEB, 0xFC, 0xE4, 0xFF, 0xE3, 0x00, 0x16, 0xFF, 0xA5, 0x00, 0xAF,
+ 0xFF, 0x13, 0x00, 0xFD, 0xFF, 0x36, 0x00, 0x36, 0xFF, 0xE6, 0x01,
+ 0x3E, 0xFC, 0xD3, 0x06, 0x56, 0xF3, 0xBA, 0x20, 0x61, 0x3D, 0x56,
+ 0xF3, 0x45, 0x05, 0xB7, 0xFD, 0xDE, 0x00, 0xC5, 0xFF, 0x05, 0x00,
+ 0x02, 0x00, 0xFE, 0xFF, 0x20, 0x00, 0x7A, 0xFF, 0x70, 0x01, 0xC7,
+ 0xFC, 0xA0, 0x06, 0xAE, 0xF1, 0x65, 0x35, 0xD1, 0x2A, 0xCA, 0xF1,
+ 0x2A, 0x07, 0x40, 0xFC, 0xD0, 0x01, 0x47, 0xFF, 0x32, 0x00, 0xFD,
+ 0xFF, 0x09, 0x00, 0xDB, 0xFF, 0x34, 0x00, 0xFE, 0xFF, 0x3D, 0xFF,
+ 0xC9, 0x02, 0x64, 0xF7, 0x2F, 0x44, 0x44, 0x15, 0x4A, 0xF6, 0xAD,
+ 0x05, 0xAF, 0xFC, 0xC0, 0x01, 0x41, 0xFF, 0x32, 0x00, 0xFF, 0xFF,
+ 0x00, 0x00, 0x21, 0x00, 0x7C, 0xFF, 0x26, 0x01, 0x08, 0xFE, 0xE4,
+ 0x02, 0x21, 0xFC, 0x31, 0x05, 0xEB, 0x48, 0x37, 0x02, 0x6B, 0xFD,
+ 0x39, 0x02, 0x61, 0xFE, 0xFC, 0x00, 0x8D, 0xFF, 0x1C, 0x00, 0xFE,
+ 0xFF, 0x35, 0x00, 0x3A, 0xFF, 0xD3, 0x01, 0x7D, 0xFC, 0x23, 0x06,
+ 0x32, 0xF5, 0x0C, 0x19, 0x38, 0x42, 0xC7, 0xF5, 0xB8, 0x03, 0xAF,
+ 0xFE, 0x4E, 0x00, 0x0C, 0x00, 0xEA, 0xFF, 0x06, 0x00, 0xFD, 0xFF,
+ 0x2D, 0x00, 0x54, 0xFF, 0xB8, 0x01, 0x5D, 0xFC, 0x1A, 0x07, 0x8A,
+ 0xF1, 0x7B, 0x2E, 0x04, 0x32, 0x7F, 0xF1, 0xEC, 0x06, 0x8A, 0xFC,
+ 0x98, 0x01, 0x65, 0xFF, 0x27, 0x00, 0xFD, 0xFF, 0x04, 0x00, 0xF8,
+ 0xFF, 0xE7, 0xFF, 0x99, 0x00, 0x2C, 0xFE, 0x8C, 0x04, 0x6D, 0xF4,
+ 0xF0, 0x3F, 0xE0, 0x1C, 0x34, 0xF4, 0x85, 0x06, 0x57, 0xFC, 0xE0,
+ 0x01, 0x37, 0xFF, 0x36, 0x00, 0xFE, 0xFF, 0x18, 0x00, 0x9E, 0xFF,
+ 0xD1, 0x00, 0xBB, 0xFE, 0x8D, 0x01, 0xAE, 0xFE, 0x74, 0xFF, 0x8D,
+ 0x48, 0x5D, 0x08, 0xD4, 0xFA, 0x8D, 0x03, 0xB3, 0xFD, 0x4E, 0x01,
+ 0x6D, 0xFF, 0x25, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x2F, 0x00, 0x4A,
+ 0xFF, 0xA7, 0x01, 0xEC, 0xFC, 0x28, 0x05, 0x77, 0xF7, 0x92, 0x11,
+ 0xD7, 0x45, 0x43, 0xF9, 0xC3, 0x01, 0xD6, 0xFF, 0xA9, 0xFF, 0x5E,
+ 0x00, 0xCB, 0xFF, 0x0D, 0x00, 0xFD, 0xFF, 0x34, 0x00, 0x3D, 0xFF,
+ 0xDF, 0x01, 0x32, 0xFC, 0x1F, 0x07, 0x3B, 0xF2, 0x11, 0x27, 0x97,
+ 0x38, 0x19, 0xF2, 0x36, 0x06, 0x15, 0xFD, 0x3F, 0x01, 0x93, 0xFF,
+ 0x17, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x10, 0x00, 0xA6, 0xFF, 0x1B,
+ 0x01, 0x50, 0xFD, 0xE1, 0x05, 0x82, 0xF2, 0x8F, 0x3A, 0x92, 0x24,
+ 0x9D, 0xF2, 0x09, 0x07, 0x32, 0xFC, 0xE4, 0x01, 0x39, 0xFF, 0x36,
+ 0x00, 0xFD, 0xFF, 0x0F, 0x00, 0xC0, 0xFF, 0x7A, 0x00, 0x70, 0xFF,
+ 0x3E, 0x00, 0x0C, 0x01, 0xA1, 0xFA, 0xBB, 0x46, 0x36, 0x0F, 0x45,
+ 0xF8, 0xC9, 0x04, 0x18, 0xFD, 0x93, 0x01, 0x52, 0xFF, 0x2D, 0x00,
+ 0xFF, 0xFF, 0x00, 0x00, 0x28, 0x00, 0x63, 0xFF, 0x66, 0x01, 0x7D,
+ 0xFD, 0xF8, 0x03, 0xFB, 0xF9, 0x89, 0x0A, 0x1D, 0x48, 0xC5, 0xFD,
+ 0x7A, 0xFF, 0x1D, 0x01, 0xF7, 0xFE, 0xB4, 0x00, 0xA9, 0xFF, 0x15,
+ 0x00, 0xFD, 0xFF, 0x36, 0x00, 0x36, 0xFF, 0xE5, 0x01, 0x45, 0xFC,
+ 0xBB, 0x06, 0xA0, 0xF3, 0x64, 0x1F, 0x4A, 0x3E, 0xB0, 0xF3, 0x08,
+ 0x05, 0xDE, 0xFD, 0xC7, 0x00, 0xD0, 0xFF, 0x00, 0x00, 0x02, 0x00,
+ 0xFE, 0xFF, 0x23, 0x00, 0x72, 0xFF, 0x7F, 0x01, 0xB0, 0xFC, 0xBE,
+ 0x06, 0x97, 0xF1, 0x3F, 0x34, 0x19, 0x2C, 0xAD, 0xF1, 0x28, 0x07,
+ 0x48, 0xFC, 0xC9, 0x01, 0x4B, 0xFF, 0x30, 0x00, 0xFD, 0xFF, 0x08,
+ 0x00, 0xE0, 0xFF, 0x26, 0x00, 0x1A, 0x00, 0x0B, 0xFF, 0x1E, 0x03,
+ 0xCD, 0xF6, 0x89, 0x43, 0x91, 0x16, 0xE7, 0xF5, 0xD8, 0x05, 0x9D,
+ 0xFC, 0xC7, 0x01, 0x3E, 0xFF, 0x33, 0x00, 0xFF, 0xFF, 0x00, 0x00,
+ 0x1F, 0x00, 0x82, 0xFF, 0x18, 0x01, 0x27, 0xFE, 0xA9, 0x02, 0x94,
+ 0xFC, 0x24, 0x04, 0xF5, 0x48, 0x39, 0x03, 0xF9, 0xFC, 0x74, 0x02,
+ 0x42, 0xFE, 0x0B, 0x01, 0x87, 0xFF, 0x1E, 0x00, 0xFE, 0xFF, 0x34,
+ 0x00, 0x3C, 0xFF, 0xCD, 0x01, 0x8E, 0xFC, 0xFC, 0x05, 0x90, 0xF5,
+ 0xBB, 0x17, 0xEE, 0x42, 0x4E, 0xF6, 0x68, 0x03, 0xDF, 0xFE, 0x33,
+ 0x00, 0x1A, 0x00, 0xE5, 0xFF, 0x07, 0x00, 0xFD, 0xFF, 0x2F, 0x00,
+ 0x4F, 0xFF, 0xC2, 0x01, 0x51, 0xFC, 0x23, 0x07, 0x9A, 0xF1, 0x3A,
+ 0x2D, 0x35, 0x33, 0x89, 0xF1, 0xD5, 0x06, 0x9D, 0xFC, 0x8B, 0x01,
+ 0x6C, 0xFF, 0x25, 0x00, 0xFD, 0xFF, 0x03, 0x00, 0xFC, 0xFF, 0xDB,
+ 0xFF, 0xB2, 0x00, 0x02, 0xFE, 0xCF, 0x04, 0x05, 0xF4, 0x16, 0x3F,
+ 0x36, 0x1E, 0xE4, 0xF3, 0xA3, 0x06, 0x4D, 0xFC, 0xE3, 0x01, 0x36,
+ 0xFF, 0x36, 0x00, 0xFE, 0xFF, 0x16, 0x00, 0xA4, 0xFF, 0xC2, 0x00,
+ 0xDB, 0xFE, 0x52, 0x01, 0x1B, 0xFF, 0x8D, 0xFE, 0x57, 0x48, 0x81,
+ 0x09, 0x61, 0xFA, 0xC6, 0x03, 0x96, 0xFD, 0x5B, 0x01, 0x68, 0xFF,
+ 0x26, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x2E, 0x00, 0x4E, 0xFF, 0x9D,
+ 0x01, 0x03, 0xFD, 0xF7, 0x04, 0xE3, 0xF7, 0x51, 0x10, 0x55, 0x46,
+ 0xF9, 0xF9, 0x63, 0x01, 0x0D, 0x00, 0x8B, 0xFF, 0x6D, 0x00, 0xC5,
+ 0xFF, 0x0E, 0x00, 0xFD, 0xFF, 0x35, 0x00, 0x3B, 0xFF, 0xE2, 0x01,
+ 0x31, 0xFC, 0x15, 0x07, 0x6D, 0xF2, 0xBF, 0x25, 0xA5, 0x39, 0x4D,
+ 0xF2, 0x0B, 0x06, 0x33, 0xFD, 0x2D, 0x01, 0x9D, 0xFF, 0x13, 0x00,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0x14, 0x00, 0x9C, 0xFF, 0x2F, 0x01, 0x30,
+ 0xFD, 0x10, 0x06, 0x47, 0xF2, 0x87, 0x39, 0xE5, 0x25, 0x67, 0xF2,
+ 0x16, 0x07, 0x31, 0xFC, 0xE2, 0x01, 0x3B, 0xFF, 0x35, 0x00, 0xFD,
+ 0xFF, 0x0E, 0x00, 0xC6, 0xFF, 0x6B, 0x00, 0x8E, 0xFF, 0x06, 0x00,
+ 0x6E, 0x01, 0xE4, 0xF9, 0x48, 0x46, 0x75, 0x10, 0xD7, 0xF7, 0xFC,
+ 0x04, 0x00, 0xFD, 0x9E, 0x01, 0x4E, 0xFF, 0x2E, 0x00, 0xFF, 0xFF,
+ 0x00, 0x00, 0x26, 0x00, 0x68, 0xFF, 0x59, 0x01, 0x99, 0xFD, 0xC0,
+ 0x03, 0x6E, 0xFA, 0x61, 0x09, 0x5D, 0x48, 0xA6, 0xFE, 0x0F, 0xFF,
+ 0x58, 0x01, 0xD7, 0xFE, 0xC3, 0x00, 0xA3, 0xFF, 0x16, 0x00, 0xFE,
+ 0xFF, 0x36, 0x00, 0x36, 0xFF, 0xE3, 0x01, 0x4E, 0xFC, 0xA0, 0x06,
+ 0xED, 0xF3, 0x0F, 0x1E, 0x2D, 0x3F, 0x10, 0xF4, 0xC8, 0x04, 0x07,
+ 0xFE, 0xAF, 0x00, 0xDC, 0xFF, 0xFC, 0xFF, 0x03, 0x00, 0xFD, 0xFF,
+ 0x25, 0x00, 0x6B, 0xFF, 0x8D, 0x01, 0x9B, 0xFC, 0xD8, 0x06, 0x87,
+ 0xF1, 0x13, 0x33, 0x5E, 0x2D, 0x98, 0xF1, 0x22, 0x07, 0x52, 0xFC,
+ 0xC1, 0x01, 0x4F, 0xFF, 0x2F, 0x00, 0xFD, 0xFF, 0x07, 0x00, 0xE5,
+ 0xFF, 0x18, 0x00, 0x36, 0x00, 0xD9, 0xFE, 0x71, 0x03, 0x3F, 0xF6,
+ 0xDB, 0x42, 0xE0, 0x17, 0x86, 0xF5, 0x00, 0x06, 0x8C, 0xFC, 0xCE,
+ 0x01, 0x3C, 0xFF, 0x34, 0x00, 0xFE, 0xFF, 0x1D, 0x00, 0x88, 0xFF,
+ 0x09, 0x01, 0x45, 0xFE, 0x6E, 0x02, 0x06, 0xFD, 0x1C, 0x03, 0xF4,
+ 0x48, 0x41, 0x04, 0x87, 0xFC, 0xB0, 0x02, 0x23, 0xFE, 0x19, 0x01,
+ 0x81, 0xFF, 0x1F, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x33, 0x00, 0x3F,
+ 0xFF, 0xC6, 0x01, 0x9F, 0xFC, 0xD3, 0x05, 0xF1, 0xF5, 0x6C, 0x16,
+ 0x9E, 0x43, 0xDD, 0xF6, 0x15, 0x03, 0x10, 0xFF, 0x17, 0x00, 0x28,
+ 0x00, 0xDF, 0xFF, 0x09, 0x00, 0xFD, 0xFF, 0x30, 0x00, 0x4A, 0xFF,
+ 0xCA, 0x01, 0x47, 0xFC, 0x28, 0x07, 0xB0, 0xF1, 0xF5, 0x2B, 0x60,
+ 0x34, 0x9A, 0xF1, 0xBB, 0x06, 0xB3, 0xFC, 0x7D, 0x01, 0x73, 0xFF,
+ 0x22, 0x00, 0xFE, 0xFF, 0x02, 0x00, 0x01, 0x00, 0xCF, 0xFF, 0xC9,
+ 0x00, 0xDA, 0xFD, 0x0F, 0x05, 0xA5, 0xF3, 0x31, 0x3E, 0x8A, 0x1F,
+ 0x97, 0xF3, 0xBD, 0x06, 0x44, 0xFC, 0xE5, 0x01, 0x36, 0xFF, 0x36,
+ 0x00, 0xFD, 0xFF, 0x15, 0x00, 0xAA, 0xFF, 0xB3, 0x00, 0xFA, 0xFE,
+ 0x17, 0x01, 0x86, 0xFF, 0xAC, 0xFD, 0x16, 0x48, 0xAA, 0x0A, 0xEE,
+ 0xF9, 0xFE, 0x03, 0x7A, 0xFD, 0x67, 0x01, 0x63, 0xFF, 0x28, 0x00,
+ 0x00, 0x00, 0xFF, 0xFF, 0x2D, 0x00, 0x52, 0xFF, 0x92, 0x01, 0x1B,
+ 0xFD, 0xC4, 0x04, 0x51, 0xF8, 0x13, 0x0F, 0xC8, 0x46, 0xB6, 0xFA,
+ 0x01, 0x01, 0x44, 0x00, 0x6C, 0xFF, 0x7B, 0x00, 0xBF, 0xFF, 0x10,
+ 0x00, 0xFD, 0xFF, 0x36, 0x00, 0x39, 0xFF, 0xE5, 0x01, 0x32, 0xFC,
+ 0x08, 0x07, 0xA4, 0xF2, 0x6D, 0x24, 0xAD, 0x3A, 0x88, 0xF2, 0xDB,
+ 0x05, 0x53, 0xFD, 0x19, 0x01, 0xA7, 0xFF, 0x10, 0x00, 0x00, 0x00,
+ 0xFF, 0xFF, 0x17, 0x00, 0x92, 0xFF, 0x41, 0x01, 0x11, 0xFD, 0x3B,
+ 0x06, 0x14, 0xF2, 0x78, 0x38, 0x36, 0x27, 0x35, 0xF2, 0x20, 0x07,
+ 0x33, 0xFC, 0xDF, 0x01, 0x3E, 0xFF, 0x34, 0x00, 0xFD, 0xFF, 0x0D,
+ 0x00, 0xCB, 0xFF, 0x5C, 0x00, 0xAC, 0xFF, 0xD0, 0xFF, 0xCD, 0x01,
+ 0x30, 0xF9, 0xC8, 0x45, 0xB6, 0x11, 0x6B, 0xF7, 0x2D, 0x05, 0xE9,
+ 0xFC, 0xA8, 0x01, 0x4A, 0xFF, 0x30, 0x00, 0xFF, 0xFF, 0x00, 0x00,
+ 0x25, 0x00, 0x6D, 0xFF, 0x4C, 0x01, 0xB6, 0xFD, 0x86, 0x03, 0xE1,
+ 0xFA, 0x3D, 0x08, 0x92, 0x48, 0x8E, 0xFF, 0xA1, 0xFE, 0x93, 0x01,
+ 0xB8, 0xFE, 0xD3, 0x00, 0x9D, 0xFF, 0x18, 0x00, 0xFE, 0xFF, 0x36,
+ 0x00, 0x37, 0xFF, 0xE0, 0x01, 0x58, 0xFC, 0x82, 0x06, 0x3E, 0xF4,
+ 0xBA, 0x1C, 0x07, 0x40, 0x79, 0xF4, 0x84, 0x04, 0x31, 0xFE, 0x96,
+ 0x00, 0xE8, 0xFF, 0xF7, 0xFF, 0x04, 0x00, 0xFD, 0xFF, 0x28, 0x00,
+ 0x64, 0xFF, 0x9A, 0x01, 0x88, 0xFC, 0xEE, 0x06, 0x7E, 0xF1, 0xE3,
+ 0x31, 0x9F, 0x2E, 0x88, 0xF1, 0x19, 0x07, 0x5E, 0xFC, 0xB7, 0x01,
+ 0x54, 0xFF, 0x2D, 0x00, 0xFD, 0xFF, 0x06, 0x00, 0xEA, 0xFF, 0x0B,
+ 0x00, 0x51, 0x00, 0xAA, 0xFE, 0xC0, 0x03, 0xB8, 0xF5, 0x21, 0x42,
+ 0x31, 0x19, 0x28, 0xF5, 0x27, 0x06, 0x7C, 0xFC, 0xD4, 0x01, 0x3A,
+ 0xFF, 0x35, 0x00, 0xFE, 0xFF, 0x1C, 0x00, 0x8D, 0xFF, 0xFA, 0x00,
+ 0x64, 0xFE, 0x32, 0x02, 0x78, 0xFD, 0x1B, 0x02, 0xEA, 0x48, 0x50,
+ 0x05, 0x14, 0xFC, 0xEB, 0x02, 0x05, 0xFE, 0x27, 0x01, 0x7C, 0xFF,
+ 0x21, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x32, 0x00, 0x41, 0xFF, 0xBF,
+ 0x01, 0xB2, 0xFC, 0xA9, 0x05, 0x55, 0xF6, 0x20, 0x15, 0x42, 0x44,
+ 0x75, 0xF7, 0xBF, 0x02, 0x43, 0xFF, 0xFA, 0xFF, 0x36, 0x00, 0xDA,
+ 0xFF, 0x0A, 0x00, 0xFD, 0xFF, 0x32, 0x00, 0x46, 0xFF, 0xD1, 0x01,
+ 0x3F, 0xFC, 0x2B, 0x07, 0xCD, 0xF1, 0xAE, 0x2A, 0x86, 0x35, 0xB1,
+ 0xF1, 0x9D, 0x06, 0xCA, 0xFC, 0x6E, 0x01, 0x7B, 0xFF, 0x20, 0x00,
+ 0xFE, 0xFF, 0x02, 0x00, 0x05, 0x00, 0xC3, 0xFF, 0xE0, 0x00, 0xB3,
+ 0xFD, 0x4B, 0x05, 0x4D, 0xF3, 0x45, 0x3D, 0xE0, 0x20, 0x4F, 0xF3,
+ 0xD5, 0x06, 0x3D, 0xFC, 0xE6, 0x01, 0x36, 0xFF, 0x36, 0x00, 0xFD,
+ 0xFF, 0x13, 0x00, 0xAF, 0xFF, 0xA4, 0x00, 0x19, 0xFF, 0xDD, 0x00,
+ 0xF0, 0xFF, 0xD4, 0xFC, 0xC9, 0x47, 0xD8, 0x0B, 0x7C, 0xF9, 0x35,
+ 0x04, 0x5F, 0xFD, 0x74, 0x01, 0x5E, 0xFF, 0x29, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x2C, 0x00, 0x56, 0xFF, 0x87, 0x01, 0x34, 0xFD, 0x8F,
+ 0x04, 0xC0, 0xF8, 0xD9, 0x0D, 0x31, 0x47, 0x7B, 0xFB, 0x9C, 0x00,
+ 0x7D, 0x00, 0x4D, 0xFF, 0x8A, 0x00, 0xB9, 0xFF, 0x11, 0x00, 0xFD,
+ 0xFF, 0x36, 0x00, 0x38, 0xFF, 0xE6, 0x01, 0x35, 0xFC, 0xF7, 0x06,
+ 0xE0, 0xF2, 0x18, 0x23, 0xAB, 0x3B, 0xCC, 0xF2, 0xA8, 0x05, 0x76,
+ 0xFD, 0x04, 0x01, 0xB1, 0xFF, 0x0C, 0x00, 0x00, 0x00, 0xFE, 0xFF,
+ 0x1A, 0x00, 0x89, 0xFF, 0x53, 0x01, 0xF5, 0xFC, 0x63, 0x06, 0xE9,
+ 0xF1, 0x63, 0x37, 0x85, 0x28, 0x09, 0xF2, 0x27, 0x07, 0x35, 0xFC,
+ 0xDA, 0x01, 0x40, 0xFF, 0x34, 0x00, 0xFD, 0xFF, 0x0C, 0x00, 0xD1,
+ 0xFF, 0x4E, 0x00, 0xCA, 0xFF, 0x9A, 0xFF, 0x2A, 0x02, 0x83, 0xF8,
+ 0x3F, 0x45, 0xFB, 0x12, 0x01, 0xF7, 0x5D, 0x05, 0xD3, 0xFC, 0xB1,
+ 0x01, 0x46, 0xFF, 0x31, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x23, 0x00,
+ 0x73, 0xFF, 0x3F, 0x01, 0xD3, 0xFD, 0x4C, 0x03, 0x54, 0xFB, 0x1F,
+ 0x07, 0xBB, 0x48, 0x7D, 0x00, 0x33, 0xFE, 0xCF, 0x01, 0x98, 0xFE,
+ 0xE2, 0x00, 0x97, 0xFF, 0x19, 0x00, 0xFE, 0xFF, 0x36, 0x00, 0x38,
+ 0xFF, 0xDC, 0x01, 0x64, 0xFC, 0x62, 0x06, 0x93, 0xF4, 0x66, 0x1B,
+ 0xD9, 0x40, 0xEA, 0xF4, 0x3E, 0x04, 0x5D, 0xFE, 0x7D, 0x00, 0xF5,
+ 0xFF, 0xF3, 0xFF, 0x05, 0x00, 0xFD, 0xFF, 0x2A, 0x00, 0x5E, 0xFF,
+ 0xA6, 0x01, 0x76, 0xFC, 0x01, 0x07, 0x7D, 0xF1, 0xAD, 0x30, 0xDC,
+ 0x2F, 0x7F, 0xF1, 0x0C, 0x07, 0x6C, 0xFC, 0xAD, 0x01, 0x5A, 0xFF,
+ 0x2B, 0x00, 0xFD, 0xFF, 0x05, 0x00, 0xEF, 0xFF, 0xFE, 0xFF, 0x6C,
+ 0x00, 0x7B, 0xFE, 0x0C, 0x04, 0x3A, 0xF5, 0x5F, 0x41, 0x83, 0x1A,
+ 0xCD, 0xF4, 0x4B, 0x06, 0x6D, 0xFC, 0xD9, 0x01, 0x39, 0xFF, 0x35,
+ 0x00, 0xFE, 0xFF, 0x1A, 0x00, 0x93, 0xFF, 0xEC, 0x00, 0x83, 0xFE,
+ 0xF7, 0x01, 0xE8, 0xFD, 0x21, 0x01, 0xD2, 0x48, 0x64, 0x06, 0xA1,
+ 0xFB, 0x26, 0x03, 0xE7, 0xFD, 0x35, 0x01, 0x76, 0xFF, 0x22, 0x00,
+ 0x00, 0x00, 0xFF, 0xFF, 0x31, 0x00, 0x44, 0xFF, 0xB7, 0x01, 0xC5,
+ 0xFC, 0x7C, 0x05, 0xBC, 0xF6, 0xD5, 0x13, 0xDC, 0x44, 0x14, 0xF8,
+ 0x67, 0x02, 0x77, 0xFF, 0xDD, 0xFF, 0x44, 0x00, 0xD5, 0xFF, 0x0B,
+ 0x00, 0xFD, 0xFF, 0x33, 0x00, 0x42, 0xFF, 0xD7, 0x01, 0x39, 0xFC,
+ 0x29, 0x07, 0xEF, 0xF1, 0x62, 0x29, 0xA5, 0x36, 0xD0, 0xF1, 0x7B,
+ 0x06, 0xE3, 0xFC, 0x5E, 0x01, 0x83, 0xFF, 0x1D, 0x00, 0xFE, 0xFF,
+ 0x01, 0x00, 0x09, 0x00, 0xB8, 0xFF, 0xF6, 0x00, 0x8D, 0xFD, 0x84,
+ 0x05, 0xFD, 0xF2, 0x52, 0x3C, 0x35, 0x22, 0x0B, 0xF3, 0xEB, 0x06,
+ 0x37, 0xFC, 0xE6, 0x01, 0x37, 0xFF, 0x36, 0x00, 0xFD, 0xFF, 0x12,
+ 0x00, 0xB5, 0xFF, 0x94, 0x00, 0x39, 0xFF, 0xA3, 0x00, 0x58, 0x00,
+ 0x02, 0xFC, 0x73, 0x47, 0x0B, 0x0D, 0x0B, 0xF9, 0x6C, 0x04, 0x45,
+ 0xFD, 0x80, 0x01, 0x59, 0xFF, 0x2B, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x2A, 0x00, 0x5B, 0xFF, 0x7C, 0x01, 0x4E, 0xFD, 0x5A, 0x04, 0x31,
+ 0xF9, 0xA4, 0x0C, 0x90, 0x47, 0x47, 0xFC, 0x36, 0x00, 0xB6, 0x00,
+ 0x2E, 0xFF, 0x99, 0x00, 0xB3, 0xFF, 0x12, 0x00, 0xFD, 0xFF, 0x36,
+ 0x00, 0x37, 0xFF, 0xE6, 0x01, 0x39, 0xFC, 0xE4, 0x06, 0x21, 0xF3,
+ 0xC4, 0x21, 0xA5, 0x3C, 0x16, 0xF3, 0x72, 0x05, 0x9A, 0xFD, 0xEF,
+ 0x00, 0xBC, 0xFF, 0x08, 0x00, 0x01, 0x00, 0xFE, 0xFF, 0x1E, 0x00,
+ 0x80, 0xFF, 0x64, 0x01, 0xDA, 0xFC, 0x87, 0x06, 0xC5, 0xF1, 0x46,
+ 0x36, 0xD1, 0x29, 0xE3, 0xF1, 0x2A, 0x07, 0x3A, 0xFC, 0xD5, 0x01,
+ 0x44, 0xFF, 0x32, 0x00, 0xFD, 0xFF, 0x0A, 0x00, 0xD6, 0xFF, 0x3F,
+ 0x00, 0xE7, 0xFF, 0x65, 0xFF, 0x85, 0x02, 0xDE, 0xF7, 0xA9, 0x44,
+ 0x43, 0x14, 0x99, 0xF6, 0x8B, 0x05, 0xBF, 0xFC, 0xBA, 0x01, 0x43,
+ 0xFF, 0x32, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x22, 0x00, 0x78, 0xFF,
+ 0x31, 0x01, 0xF1, 0xFD, 0x12, 0x03, 0xC7, 0xFB, 0x07, 0x06, 0xDB,
+ 0x48, 0x73, 0x01, 0xC3, 0xFD, 0x0A, 0x02, 0x79, 0xFE, 0xF1, 0x00,
+ 0x91, 0xFF, 0x1B, 0x00, 0xFE, 0xFF, 0x35, 0x00, 0x39, 0xFF, 0xD7,
+ 0x01, 0x72, 0xFC, 0x3F, 0x06, 0xEB, 0xF4, 0x12, 0x1A, 0xA1, 0x41,
+ 0x63, 0xF5, 0xF3, 0x03, 0x8A, 0xFE, 0x63, 0x00, 0x02, 0x00, 0xEE,
+ 0xFF, 0x06, 0x00, 0xFD, 0xFF, 0x2C, 0x00, 0x58, 0xFF, 0xB1, 0x01,
+ 0x67, 0xFC, 0x10, 0x07, 0x81, 0xF1, 0x73, 0x2F, 0x15, 0x31, 0x7C,
+ 0xF1, 0xFB, 0x06, 0x7C, 0xFC, 0xA2, 0x01, 0x60, 0xFF, 0x29, 0x00,
+ 0xFD, 0xFF, 0x04, 0x00, 0xF4, 0xFF, 0xF1, 0xFF, 0x85, 0x00, 0x4E,
+ 0xFE, 0x56, 0x04, 0xC3, 0xF4, 0x95, 0x40, 0xD8, 0x1B, 0x76, 0xF4,
+ 0x6D, 0x06, 0x60, 0xFC, 0xDD, 0x01, 0x37, 0xFF, 0x36, 0x00, 0xFE,
+ 0xFF, 0x19, 0x00, 0x99, 0xFF, 0xDD, 0x00, 0xA3, 0xFE, 0xBB, 0x01,
+ 0x58, 0xFE, 0x2D, 0x00, 0xAF, 0x48, 0x7E, 0x07, 0x2E, 0xFB, 0x60,
+ 0x03, 0xC9, 0xFD, 0x43, 0x01, 0x71, 0xFF, 0x24, 0x00, 0x00, 0x00,
+ 0xFF, 0xFF, 0x30, 0x00, 0x48, 0xFF, 0xAE, 0x01, 0xDB, 0xFC, 0x4D,
+ 0x05, 0x24, 0xF7, 0x8E, 0x12, 0x6D, 0x45, 0xBC, 0xF8, 0x0C, 0x02,
+ 0xAC, 0xFF, 0xC0, 0xFF, 0x52, 0x00, 0xCF, 0xFF, 0x0C, 0x00, 0xFD,
+ 0xFF, 0x34, 0x00, 0x3F, 0xFF, 0xDC, 0x01, 0x34, 0xFC, 0x25, 0x07,
+ 0x18, 0xF2, 0x15, 0x28, 0xBF, 0x37, 0xF7, 0xF1, 0x56, 0x06, 0xFE,
+ 0xFC, 0x4D, 0x01, 0x8C, 0xFF, 0x19, 0x00, 0xFF, 0xFF, 0x00, 0x00,
+ 0x0D, 0x00, 0xAE, 0xFF, 0x0B, 0x01, 0x6A, 0xFD, 0xBA, 0x05, 0xB4,
+ 0xF2, 0x58, 0x3B, 0x8A, 0x23, 0xCB, 0xF2, 0xFD, 0x06, 0x34, 0xFC,
+ 0xE6, 0x01, 0x38, 0xFF, 0x36, 0x00, 0xFD, 0xFF, 0x10, 0x00, 0xBB,
+ 0xFF, 0x85, 0x00, 0x58, 0xFF, 0x6A, 0x00, 0xBE, 0x00, 0x38, 0xFB,
+ 0x0F, 0x47, 0x42, 0x0E, 0x9B, 0xF8, 0xA1, 0x04, 0x2B, 0xFD, 0x8B,
+ 0x01, 0x55, 0xFF, 0x2C, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x29, 0x00,
+ 0x5F, 0xFF, 0x70, 0x01, 0x68, 0xFD, 0x23, 0x04, 0xA2, 0xF9, 0x73,
+ 0x0B, 0xE4, 0x47, 0x1B, 0xFD, 0xCD, 0xFF, 0xF0, 0x00, 0x0F, 0xFF,
+ 0xA9, 0x00, 0xAE, 0xFF, 0x14, 0x00, 0xFD, 0xFF, 0x36, 0x00, 0x36,
+ 0xFF, 0xE6, 0x01, 0x3F, 0xFC, 0xCE, 0x06, 0x66, 0xF3, 0x6F, 0x20,
+ 0x96, 0x3D, 0x69, 0xF3, 0x38, 0x05, 0xBF, 0xFD, 0xD9, 0x00, 0xC7,
+ 0xFF, 0x04, 0x00, 0x02, 0x00, 0xFE, 0xFF, 0x20, 0x00, 0x78, 0xFF,
+ 0x74, 0x01, 0xC2, 0xFC, 0xA7, 0x06, 0xA8, 0xF1, 0x25, 0x35, 0x1B,
+ 0x2B, 0xC2, 0xF1, 0x2A, 0x07, 0x41, 0xFC, 0xCE, 0x01, 0x47, 0xFF,
+ 0x31, 0x00, 0xFD, 0xFF, 0x09, 0x00, 0xDC, 0xFF, 0x31, 0x00, 0x04,
+ 0x00, 0x32, 0xFF, 0xDC, 0x02, 0x42, 0xF7, 0x0B, 0x44, 0x8E, 0x15,
+ 0x34, 0xF6, 0xB7, 0x05, 0xAB, 0xFC, 0xC1, 0x01, 0x40, 0xFF, 0x33,
+ 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x20, 0x00, 0x7E, 0xFF, 0x23, 0x01,
+ 0x0F, 0xFE, 0xD7, 0x02, 0x3B, 0xFC, 0xF5, 0x04, 0xED, 0x48, 0x70,
+ 0x02, 0x52, 0xFD, 0x46, 0x02, 0x5A, 0xFE, 0xFF, 0x00, 0x8B, 0xFF,
+ 0x1C, 0x00, 0xFE, 0xFF, 0x35, 0x00, 0x3B, 0xFF, 0xD2, 0x01, 0x81,
+ 0xFC, 0x1A, 0x06, 0x47, 0xF5, 0xC1, 0x18, 0x60, 0x42, 0xE4, 0xF5,
+ 0xA6, 0x03, 0xB9, 0xFE, 0x48, 0x00, 0x0F, 0x00, 0xE9, 0xFF, 0x07,
+ 0x00, 0xFD, 0xFF, 0x2E, 0x00, 0x53, 0xFF, 0xBB, 0x01, 0x5A, 0xFC,
+ 0x1C, 0x07, 0x8D, 0xF1, 0x34, 0x2E, 0x48, 0x32, 0x81, 0xF1, 0xE7,
+ 0x06, 0x8E, 0xFC, 0x96, 0x01, 0x66, 0xFF, 0x27, 0x00, 0xFD, 0xFF,
+ 0x04, 0x00, 0xF9, 0xFF, 0xE4, 0xFF, 0x9F, 0x00, 0x23, 0xFE, 0x9B,
+ 0x04, 0x55, 0xF4, 0xC0, 0x3F, 0x2C, 0x1D, 0x22, 0xF4, 0x8C, 0x06,
+ 0x55, 0xFC, 0xE1, 0x01, 0x37, 0xFF, 0x36, 0x00, 0xFE, 0xFF, 0x17,
+ 0x00, 0x9F, 0xFF, 0xCE, 0x00, 0xC2, 0xFE, 0x80, 0x01, 0xC6, 0xFE,
+ 0x40, 0xFF, 0x81, 0x48, 0x9E, 0x08, 0xBA, 0xFA, 0x9A, 0x03, 0xAC,
+ 0xFD, 0x51, 0x01, 0x6C, 0xFF, 0x25, 0x00, 0x00, 0x00, 0xFF, 0xFF,
+ 0x2F, 0x00, 0x4B, 0xFF, 0xA4, 0x01, 0xF1, 0xFC, 0x1D, 0x05, 0x8F,
+ 0xF7, 0x4A, 0x11, 0xF2, 0x45, 0x6B, 0xF9, 0xAE, 0x01, 0xE2, 0xFF,
+ 0xA2, 0xFF, 0x61, 0x00, 0xC9, 0xFF, 0x0D, 0x00, 0xFD, 0xFF, 0x35,
+ 0x00, 0x3D, 0xFF, 0xE0, 0x01, 0x32, 0xFC, 0x1D, 0x07, 0x45, 0xF2,
+ 0xC6, 0x26, 0xD3, 0x38, 0x24, 0xF2, 0x2D, 0x06, 0x1B, 0xFD, 0x3B,
+ 0x01, 0x95, 0xFF, 0x16, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x11, 0x00,
+ 0xA3, 0xFF, 0x20, 0x01, 0x49, 0xFD, 0xEB, 0x05, 0x74, 0xF2, 0x54,
+ 0x3A, 0xDD, 0x24, 0x91, 0xF2, 0x0C, 0x07, 0x32, 0xFC, 0xE4, 0x01,
+ 0x3A, 0xFF, 0x36, 0x00, 0xFD, 0xFF, 0x0F, 0x00, 0xC1, 0xFF, 0x76,
+ 0x00, 0x76, 0xFF, 0x32, 0x00, 0x22, 0x01, 0x76, 0xFA, 0xA3, 0x46,
+ 0x7D, 0x0F, 0x2C, 0xF8, 0xD5, 0x04, 0x13, 0xFD, 0x96, 0x01, 0x51,
+ 0xFF, 0x2D, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x27, 0x00, 0x64, 0xFF,
+ 0x63, 0x01, 0x84, 0xFD, 0xEB, 0x03, 0x14, 0xFA, 0x47, 0x0A, 0x2C,
+ 0x48, 0xF6, 0xFD, 0x63, 0xFF, 0x2B, 0x01, 0xF0, 0xFE, 0xB8, 0x00,
+ 0xA8, 0xFF, 0x15, 0x00, 0xFD, 0xFF, 0x36, 0x00, 0x36, 0xFF, 0xE4,
+ 0x01, 0x47, 0xFC, 0xB5, 0x06, 0xB0, 0xF3, 0x19, 0x1F, 0x7E, 0x3E,
+ 0xC4, 0xF3, 0xFA, 0x04, 0xE7, 0xFD, 0xC1, 0x00, 0xD3, 0xFF, 0xFF,
+ 0xFF, 0x02, 0x00, 0xFE, 0xFF, 0x23, 0x00, 0x71, 0xFF, 0x82, 0x01,
+ 0xAB, 0xFC, 0xC4, 0x06, 0x93, 0xF1, 0xFD, 0x33, 0x62, 0x2C, 0xA8,
+ 0xF1, 0x27, 0x07, 0x4A, 0xFC, 0xC7, 0x01, 0x4C, 0xFF, 0x30, 0x00,
+ 0xFD, 0xFF, 0x08, 0x00, 0xE1, 0xFF, 0x23, 0x00, 0x20, 0x00, 0x00,
+ 0xFF, 0x31, 0x03, 0xAD, 0xF6, 0x65, 0x43, 0xDC, 0x16, 0xD1, 0xF5,
+ 0xE1, 0x05, 0x99, 0xFC, 0xC9, 0x01, 0x3E, 0xFF, 0x33, 0x00, 0xFF,
+ 0xFF, 0x00, 0x00, 0x1F, 0x00, 0x83, 0xFF, 0x14, 0x01, 0x2D, 0xFE,
+ 0x9C, 0x02, 0xAD, 0xFC, 0xE9, 0x03, 0xF6, 0x48, 0x73, 0x03, 0xE0,
+ 0xFC, 0x82, 0x02, 0x3B, 0xFE, 0x0E, 0x01, 0x86, 0xFF, 0x1E, 0x00,
+ 0xFE, 0xFF, 0x34, 0x00, 0x3D, 0xFF, 0xCC, 0x01, 0x91, 0xFC, 0xF3,
+ 0x05, 0xA6, 0xF5, 0x70, 0x17, 0x17, 0x43, 0x6D, 0xF6, 0x56, 0x03,
+ 0xEA, 0xFE, 0x2D, 0x00, 0x1D, 0x00, 0xE4, 0xFF, 0x08, 0x00, 0xFD,
+ 0xFF, 0x2F, 0x00, 0x4E, 0xFF, 0xC3, 0x01, 0x4E, 0xFC, 0x24, 0x07,
+ 0x9E, 0xF1, 0xF2, 0x2C, 0x78, 0x33, 0x8C, 0xF1, 0xD0, 0x06, 0xA2,
+ 0xFC, 0x88, 0x01, 0x6D, 0xFF, 0x24, 0x00, 0xFD, 0xFF, 0x03, 0x00,
+ 0xFD, 0xFF, 0xD8, 0xFF, 0xB7, 0x00, 0xF9, 0xFD, 0xDE, 0x04, 0xEF,
+ 0xF3, 0xE4, 0x3E, 0x81, 0x1E, 0xD2, 0xF3, 0xA9, 0x06, 0x4B, 0xFC,
+ 0xE3, 0x01, 0x36, 0xFF, 0x36, 0x00, 0xFE, 0xFF, 0x16, 0x00, 0xA5,
+ 0xFF, 0xBE, 0x00, 0xE2, 0xFE, 0x45, 0x01, 0x33, 0xFF, 0x5A, 0xFE,
+ 0x48, 0x48, 0xC3, 0x09, 0x47, 0xFA, 0xD2, 0x03, 0x90, 0xFD, 0x5E,
+ 0x01, 0x66, 0xFF, 0x27, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x2E, 0x00,
+ 0x4F, 0xFF, 0x9A, 0x01, 0x08, 0xFD, 0xEB, 0x04, 0xFC, 0xF7, 0x0A,
+ 0x10, 0x70, 0x46, 0x22, 0xFA, 0x4D, 0x01, 0x19, 0x00, 0x84, 0xFF,
+ 0x70, 0x00, 0xC4, 0xFF, 0x0F, 0x00, 0xFD, 0xFF, 0x35, 0x00, 0x3B,
+ 0xFF, 0xE3, 0x01, 0x31, 0xFC, 0x12, 0x07, 0x79, 0xF2, 0x73, 0x25,
+ 0xDF, 0x39, 0x5A, 0xF2, 0x00, 0x06, 0x3A, 0xFD, 0x28, 0x01, 0x9F,
+ 0xFF, 0x13, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x15, 0x00, 0x99, 0xFF,
+ 0x33, 0x01, 0x29, 0xFD, 0x1A, 0x06, 0x3B, 0xF2, 0x4B, 0x39, 0x30,
+ 0x26, 0x5B, 0xF2, 0x19, 0x07, 0x31, 0xFC, 0xE1, 0x01, 0x3C, 0xFF,
+ 0x35, 0x00, 0xFD, 0xFF, 0x0E, 0x00, 0xC7, 0xFF, 0x68, 0x00, 0x95,
+ 0xFF, 0xFA, 0xFF, 0x83, 0x01, 0xBB, 0xF9, 0x2B, 0x46, 0xBB, 0x10,
+ 0xBF, 0xF7, 0x07, 0x05, 0xFB, 0xFC, 0xA0, 0x01, 0x4D, 0xFF, 0x2F,
+ 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x26, 0x00, 0x69, 0xFF, 0x56, 0x01,
+ 0xA0, 0xFD, 0xB3, 0x03, 0x87, 0xFA, 0x1F, 0x09, 0x6A, 0x48, 0xD9,
+ 0xFE, 0xF6, 0xFE, 0x65, 0x01, 0xD0, 0xFE, 0xC7, 0x00, 0xA2, 0xFF,
+ 0x17, 0x00, 0xFE, 0xFF, 0x36, 0x00, 0x36, 0xFF, 0xE2, 0x01, 0x50,
+ 0xFC, 0x99, 0x06, 0xFE, 0xF3, 0xC3, 0x1D, 0x5E, 0x3F, 0x27, 0xF4,
+ 0xB9, 0x04, 0x10, 0xFE, 0xA9, 0x00, 0xDF, 0xFF, 0xFB, 0xFF, 0x03,
+ 0x00, 0xFD, 0xFF, 0x26, 0x00, 0x69, 0xFF, 0x90, 0x01, 0x96, 0xFC,
+ 0xDD, 0x06, 0x85, 0xF1, 0xD0, 0x32, 0xA6, 0x2D, 0x94, 0xF1, 0x20,
+ 0x07, 0x54, 0xFC, 0xBF, 0x01, 0x50, 0xFF, 0x2E, 0x00, 0xFD, 0xFF,
+ 0x07, 0x00, 0xE6, 0xFF, 0x15, 0x00, 0x3C, 0x00, 0xCF, 0xFE, 0x83,
+ 0x03, 0x20, 0xF6, 0xB2, 0x42, 0x2B, 0x18, 0x71, 0xF5, 0x09, 0x06,
+ 0x88, 0xFC, 0xCF, 0x01, 0x3C, 0xFF, 0x34, 0x00, 0xFE, 0xFF, 0x1D,
+ 0x00, 0x89, 0xFF, 0x06, 0x01, 0x4C, 0xFE, 0x60, 0x02, 0x1F, 0xFD,
+ 0xE2, 0x02, 0xF3, 0x48, 0x7D, 0x04, 0x6E, 0xFC, 0xBD, 0x02, 0x1C,
+ 0xFE, 0x1C, 0x01, 0x80, 0xFF, 0x20, 0x00, 0x00, 0x00, 0xFF, 0xFF,
+ 0x33, 0x00, 0x3F, 0xFF, 0xC5, 0x01, 0xA3, 0xFC, 0xCA, 0x05, 0x07,
+ 0xF6, 0x22, 0x16, 0xC3, 0x43, 0xFE, 0xF6, 0x02, 0x03, 0x1B, 0xFF,
+ 0x11, 0x00, 0x2B, 0x00, 0xDE, 0xFF, 0x09, 0x00, 0xFD, 0xFF, 0x31,
+ 0x00, 0x49, 0xFF, 0xCB, 0x01, 0x45, 0xFC, 0x29, 0x07, 0xB6, 0xF1,
+ 0xAD, 0x2B, 0xA2, 0x34, 0x9E, 0xF1, 0xB4, 0x06, 0xB8, 0xFC, 0x7A,
+ 0x01, 0x75, 0xFF, 0x22, 0x00, 0xFE, 0xFF, 0x02, 0x00, 0x02, 0x00,
+ 0xCC, 0xFF, 0xCE, 0x00, 0xD1, 0xFD, 0x1D, 0x05, 0x91, 0xF3, 0xFE,
+ 0x3D, 0xD7, 0x1F, 0x87, 0xF3, 0xC3, 0x06, 0x42, 0xFC, 0xE5, 0x01,
+ 0x36, 0xFF, 0x36, 0x00, 0xFD, 0xFF, 0x14, 0x00, 0xAB, 0xFF, 0xAF,
+ 0x00, 0x01, 0xFF, 0x0A, 0x01, 0x9E, 0xFF, 0x7C, 0xFD, 0x03, 0x48,
+ 0xED, 0x0A, 0xD5, 0xF9, 0x0A, 0x04, 0x74, 0xFD, 0x6A, 0x01, 0x62,
+ 0xFF, 0x28, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x2D, 0x00, 0x53, 0xFF,
+ 0x90, 0x01, 0x20, 0xFD, 0xB8, 0x04, 0x6A, 0xF8, 0xCD, 0x0E, 0xE1,
+ 0x46, 0xE1, 0xFA, 0xEB, 0x00, 0x51, 0x00, 0x65, 0xFF, 0x7F, 0x00,
+ 0xBE, 0xFF, 0x10, 0x00, 0xFD, 0xFF, 0x36, 0x00, 0x39, 0xFF, 0xE5,
+ 0x01, 0x33, 0xFC, 0x04, 0x07, 0xB1, 0xF2, 0x21, 0x24, 0xE6, 0x3A,
+ 0x97, 0xF2, 0xD0, 0x05, 0x5B, 0xFD, 0x15, 0x01, 0xA9, 0xFF, 0x0F,
+ 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x18, 0x00, 0x90, 0xFF, 0x45, 0x01,
+ 0x0B, 0xFD, 0x44, 0x06, 0x0A, 0xF2, 0x3B, 0x38, 0x80, 0x27, 0x2B,
+ 0xF2, 0x22, 0x07, 0x33, 0xFC, 0xDE, 0x01, 0x3E, 0xFF, 0x34, 0x00,
+ 0xFD, 0xFF, 0x0D, 0x00, 0xCD, 0xFF, 0x59, 0x00, 0xB3, 0xFF, 0xC4,
+ 0xFF, 0xE2, 0x01, 0x09, 0xF9, 0xAA, 0x45, 0xFE, 0x11, 0x54, 0xF7,
+ 0x38, 0x05, 0xE4, 0xFC, 0xAA, 0x01, 0x49, 0xFF, 0x30, 0x00, 0xFF,
+ 0xFF, 0x00, 0x00, 0x24, 0x00, 0x6E, 0xFF, 0x49, 0x01, 0xBC, 0xFD,
+ 0x7A, 0x03, 0xFA, 0xFA, 0xFD, 0x07, 0x9C, 0x48, 0xC3, 0xFF, 0x89,
+ 0xFE, 0xA1, 0x01, 0xB1, 0xFE, 0xD6, 0x00, 0x9C, 0xFF, 0x18, 0x00,
+ 0xFE, 0xFF, 0x36, 0x00, 0x37, 0xFF, 0xDF, 0x01, 0x5B, 0xFC, 0x7B,
+ 0x06, 0x50, 0xF4, 0x6E, 0x1C, 0x36, 0x40, 0x92, 0xF4, 0x75, 0x04,
+ 0x3B, 0xFE, 0x91, 0x00, 0xEB, 0xFF, 0xF6, 0xFF, 0x04, 0x00, 0xFD,
+ 0xFF, 0x28, 0x00, 0x63, 0xFF, 0x9D, 0x01, 0x84, 0xFC, 0xF3, 0x06,
+ 0x7D, 0xF1, 0x9E, 0x31, 0xE6, 0x2E, 0x85, 0xF1, 0x16, 0x07, 0x61,
+ 0xFC, 0xB5, 0x01, 0x55, 0xFF, 0x2D, 0x00, 0xFD, 0xFF, 0x06, 0x00,
+ 0xEC, 0xFF, 0x08, 0x00, 0x57, 0x00, 0x9F, 0xFE, 0xD1, 0x03, 0x9B,
+ 0xF5, 0xF7, 0x41, 0x7C, 0x19, 0x13, 0xF5, 0x2F, 0x06, 0x78, 0xFC,
+ 0xD5, 0x01, 0x3A, 0xFF, 0x35, 0x00, 0xFE, 0xFF, 0x1C, 0x00, 0x8F,
+ 0xFF, 0xF7, 0x00, 0x6B, 0xFE, 0x25, 0x02, 0x91, 0xFD, 0xE3, 0x01,
+ 0xE5, 0x48, 0x8D, 0x05, 0xFB, 0xFB, 0xF8, 0x02, 0xFE, 0xFD, 0x2B,
+ 0x01, 0x7A, 0xFF, 0x21, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x32, 0x00,
+ 0x42, 0xFF, 0xBD, 0x01, 0xB6, 0xFC, 0x9F, 0x05, 0x6C, 0xF6, 0xD6,
+ 0x14, 0x65, 0x44, 0x98, 0xF7, 0xAC, 0x02, 0x4E, 0xFF, 0xF4, 0xFF,
+ 0x39, 0x00, 0xD9, 0xFF, 0x0A, 0x00, 0xFD, 0xFF, 0x32, 0x00, 0x45,
+ 0xFF, 0xD2, 0x01, 0x3D, 0xFC, 0x2B, 0x07, 0xD4, 0xF1, 0x64, 0x2A,
+ 0xC6, 0x35, 0xB7, 0xF1, 0x96, 0x06, 0xCF, 0xFC, 0x6B, 0x01, 0x7D,
+ 0xFF, 0x1F, 0x00, 0xFE, 0xFF, 0x01, 0x00, 0x06, 0x00, 0xC1, 0xFF,
+ 0xE5, 0x00, 0xAA, 0xFD, 0x58, 0x05, 0x3A, 0xF3, 0x11, 0x3D, 0x2C,
+ 0x21, 0x3F, 0xF3, 0xDA, 0x06, 0x3B, 0xFC, 0xE6, 0x01, 0x36, 0xFF,
+ 0x36, 0x00, 0xFD, 0xFF, 0x13, 0x00, 0xB1, 0xFF, 0xA0, 0x00, 0x20,
+ 0xFF, 0xD0, 0x00, 0x07, 0x00, 0xA4, 0xFC, 0xB6, 0x47, 0x1C, 0x0C,
+ 0x63, 0xF9, 0x42, 0x04, 0x59, 0xFD, 0x76, 0x01, 0x5D, 0xFF, 0x2A,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x2B, 0x00, 0x57, 0xFF, 0x85, 0x01,
+ 0x39, 0xFD, 0x84, 0x04, 0xD9, 0xF8, 0x95, 0x0D, 0x48, 0x47, 0xA7,
+ 0xFB, 0x86, 0x00, 0x8A, 0x00, 0x46, 0xFF, 0x8E, 0x00, 0xB8, 0xFF,
+ 0x11, 0x00, 0xFD, 0xFF, 0x36, 0x00, 0x37, 0xFF, 0xE6, 0x01, 0x35,
+ 0xFC, 0xF3, 0x06, 0xEE, 0xF2, 0xCD, 0x22, 0xE4, 0x3B, 0xDC, 0xF2,
+ 0x9C, 0x05, 0x7E, 0xFD, 0x00, 0x01, 0xB4, 0xFF, 0x0B, 0x00, 0x01,
+ 0x00, 0xFE, 0xFF, 0x1B, 0x00, 0x87, 0xFF, 0x57, 0x01, 0xEF, 0xFC,
+ 0x6B, 0x06, 0xE0, 0xF1, 0x23, 0x37, 0xCE, 0x28, 0x01, 0xF2, 0x28,
+ 0x07, 0x36, 0xFC, 0xD9, 0x01, 0x41, 0xFF, 0x33, 0x00, 0xFD, 0xFF,
+ 0x0B, 0x00, 0xD2, 0xFF, 0x4A, 0x00, 0xD0, 0xFF, 0x8E, 0xFF, 0x3F,
+ 0x02, 0x5E, 0xF8, 0x1E, 0x45, 0x44, 0x13, 0xEA, 0xF6, 0x67, 0x05,
+ 0xCF, 0xFC, 0xB3, 0x01, 0x46, 0xFF, 0x31, 0x00, 0xFF, 0xFF, 0x00,
+ 0x00, 0x23, 0x00, 0x74, 0xFF, 0x3C, 0x01, 0xDA, 0xFD, 0x40, 0x03,
+ 0x6E, 0xFB, 0xE1, 0x06, 0xC3, 0x48, 0xB3, 0x00, 0x1A, 0xFE, 0xDC,
+ 0x01, 0x91, 0xFE, 0xE5, 0x00, 0x96, 0xFF, 0x1A, 0x00, 0xFE, 0xFF,
+ 0x36, 0x00, 0x38, 0xFF, 0xDB, 0x01, 0x67, 0xFC, 0x5A, 0x06, 0xA6,
+ 0xF4, 0x1B, 0x1B, 0x07, 0x41, 0x04, 0xF5, 0x2D, 0x04, 0x67, 0xFE,
+ 0x77, 0x00, 0xF8, 0xFF, 0xF2, 0xFF, 0x05, 0x00, 0xFD, 0xFF, 0x2A,
+ 0x00, 0x5C, 0xFF, 0xA8, 0x01, 0x73, 0xFC, 0x05, 0x07, 0x7D, 0xF1,
+ 0x67, 0x30, 0x21, 0x30, 0x7E, 0xF1, 0x08, 0x07, 0x6F, 0xFC, 0xAB,
+ 0x01, 0x5B, 0xFF, 0x2B, 0x00, 0xFD, 0xFF, 0x05, 0x00, 0xF0, 0xFF,
+ 0xFB, 0xFF, 0x71, 0x00, 0x71, 0xFE, 0x1D, 0x04, 0x1F, 0xF5, 0x32,
+ 0x41, 0xCE, 0x1A, 0xBA, 0xF4, 0x53, 0x06, 0x6A, 0xFC, 0xDA, 0x01,
+ 0x38, 0xFF, 0x35, 0x00, 0xFE, 0xFF, 0x1A, 0x00, 0x95, 0xFF, 0xE8,
+ 0x00, 0x8A, 0xFE, 0xE9, 0x01, 0x01, 0xFE, 0xEA, 0x00, 0xCB, 0x48,
+ 0xA2, 0x06, 0x87, 0xFB, 0x33, 0x03, 0xE0, 0xFD, 0x39, 0x01, 0x75,
+ 0xFF, 0x23, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x31, 0x00, 0x45, 0xFF,
+ 0xB5, 0x01, 0xCA, 0xFC, 0x72, 0x05, 0xD3, 0xF6, 0x8D, 0x13, 0xFD,
+ 0x44, 0x39, 0xF8, 0x53, 0x02, 0x82, 0xFF, 0xD7, 0xFF, 0x47, 0x00,
+ 0xD3, 0xFF, 0x0B, 0x00, 0xFD, 0xFF, 0x33, 0x00, 0x42, 0xFF, 0xD8,
+ 0x01, 0x37, 0xFC, 0x29, 0x07, 0xF8, 0xF1, 0x19, 0x29, 0xE5, 0x36,
+ 0xD8, 0xF1, 0x73, 0x06, 0xE9, 0xFC, 0x5B, 0x01, 0x85, 0xFF, 0x1C,
+ 0x00, 0xFE, 0xFF, 0x01, 0x00, 0x0A, 0x00, 0xB6, 0xFF, 0xFB, 0x00,
+ 0x85, 0xFD, 0x90, 0x05, 0xEC, 0xF2, 0x1C, 0x3C, 0x81, 0x22, 0xFC,
+ 0xF2, 0xEF, 0x06, 0x36, 0xFC, 0xE6, 0x01, 0x37, 0xFF, 0x36, 0x00,
+ 0xFD, 0xFF, 0x12, 0x00, 0xB7, 0xFF, 0x91, 0x00, 0x40, 0xFF, 0x96,
+ 0x00, 0x6F, 0x00, 0xD5, 0xFB, 0x5E, 0x47, 0x50, 0x0D, 0xF2, 0xF8,
+ 0x78, 0x04, 0x3F, 0xFD, 0x82, 0x01, 0x58, 0xFF, 0x2B, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x2A, 0x00, 0x5C, 0xFF, 0x79, 0x01, 0x53, 0xFD,
+ 0x4E, 0x04, 0x4A, 0xF9, 0x60, 0x0C, 0xA3, 0x47, 0x76, 0xFC, 0x1F,
+ 0x00, 0xC3, 0x00, 0x27, 0xFF, 0x9D, 0x00, 0xB2, 0xFF, 0x13, 0x00,
+ 0xFD, 0xFF, 0x36, 0x00, 0x37, 0xFF, 0xE6, 0x01, 0x3A, 0xFC, 0xDF,
+ 0x06, 0x30, 0xF3, 0x78, 0x21, 0xDB, 0x3C, 0x28, 0xF3, 0x65, 0x05,
+ 0xA2, 0xFD, 0xEA, 0x00, 0xBE, 0xFF, 0x07, 0x00, 0x01, 0x00, 0xFE,
+ 0xFF, 0x1E, 0x00, 0x7F, 0xFF, 0x67, 0x01, 0xD5, 0xFC, 0x8E, 0x06,
+ 0xBE, 0xF1, 0x06, 0x36, 0x1A, 0x2A, 0xDC, 0xF1, 0x2A, 0x07, 0x3C,
+ 0xFC, 0xD3, 0x01, 0x44, 0xFF, 0x32, 0x00, 0xFD, 0xFF, 0x0A, 0x00,
+ 0xD8, 0xFF, 0x3C, 0x00, 0xEE, 0xFF, 0x5A, 0xFF, 0x98, 0x02, 0xBB,
+ 0xF7, 0x87, 0x44, 0x8C, 0x14, 0x83, 0xF6, 0x95, 0x05, 0xBA, 0xFC,
+ 0xBB, 0x01, 0x43, 0xFF, 0x32, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x21,
+ 0x00, 0x79, 0xFF, 0x2E, 0x01, 0xF7, 0xFD, 0x05, 0x03, 0xE1, 0xFB,
+ 0xCA, 0x05, 0xDF, 0x48, 0xAB, 0x01, 0xAA, 0xFD, 0x18, 0x02, 0x72,
+ 0xFE, 0xF4, 0x00, 0x90, 0xFF, 0x1B, 0x00, 0xFE, 0xFF, 0x35, 0x00,
+ 0x39, 0xFF, 0xD6, 0x01, 0x75, 0xFC, 0x37, 0x06, 0xFF, 0xF4, 0xC7,
+ 0x19, 0xCC, 0x41, 0x7F, 0xF5, 0xE2, 0x03, 0x95, 0xFE, 0x5D, 0x00,
+ 0x05, 0x00, 0xED, 0xFF, 0x06, 0x00, 0xFD, 0xFF, 0x2C, 0x00, 0x57,
+ 0xFF, 0xB3, 0x01, 0x64, 0xFC, 0x13, 0x07, 0x83, 0xF1, 0x2C, 0x2F,
+ 0x5A, 0x31, 0x7D, 0xF1, 0xF7, 0x06, 0x80, 0xFC, 0x9F, 0x01, 0x61,
+ 0xFF, 0x29, 0x00, 0xFD, 0xFF, 0x04, 0x00, 0xF5, 0xFF, 0xEE, 0xFF,
+ 0x8B, 0x00, 0x44, 0xFE, 0x65, 0x04, 0xAA, 0xF4, 0x66, 0x40, 0x23,
+ 0x1C, 0x63, 0xF4, 0x74, 0x06, 0x5D, 0xFC, 0xDE, 0x01, 0x37, 0xFF,
+ 0x36, 0x00, 0xFE, 0xFF, 0x19, 0x00, 0x9A, 0xFF, 0xD9, 0x00, 0xAA,
+ 0xFE, 0xAE, 0x01, 0x70, 0xFE, 0xF8, 0xFF, 0xA6, 0x48, 0xBE, 0x07,
+ 0x14, 0xFB, 0x6D, 0x03, 0xC3, 0xFD, 0x46, 0x01, 0x70, 0xFF, 0x24,
+ 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x30, 0x00, 0x48, 0xFF, 0xAC, 0x01,
+ 0xDF, 0xFC, 0x43, 0x05, 0x3C, 0xF7, 0x46, 0x12, 0x8D, 0x45, 0xE2,
+ 0xF8, 0xF7, 0x01, 0xB8, 0xFF, 0xB9, 0xFF, 0x56, 0x00, 0xCE, 0xFF,
+ 0x0C, 0x00, 0xFD, 0xFF, 0x34, 0x00, 0x3F, 0xFF, 0xDD, 0x01, 0x34,
+ 0xFC, 0x23, 0x07, 0x21, 0xF2, 0xCB, 0x27, 0xFE, 0x37, 0x00, 0xF2,
+ 0x4D, 0x06, 0x04, 0xFD, 0x49, 0x01, 0x8E, 0xFF, 0x19, 0x00, 0xFF,
+ 0xFF, 0x00, 0x00, 0x0E, 0x00, 0xAB, 0xFF, 0x10, 0x01, 0x62, 0xFD,
+ 0xC5, 0x05, 0xA5, 0xF2, 0x1F, 0x3B, 0xD6, 0x23, 0xBE, 0xF2, 0x01,
+ 0x07, 0x33, 0xFC, 0xE5, 0x01, 0x38, 0xFF, 0x36, 0x00, 0xFD, 0xFF,
+ 0x10, 0x00, 0xBD, 0xFF, 0x82, 0x00, 0x5E, 0xFF, 0x5D, 0x00, 0xD4,
+ 0x00, 0x0C, 0xFB, 0xF9, 0x46, 0x87, 0x0E, 0x82, 0xF8, 0xAD, 0x04,
+ 0x26, 0xFD, 0x8D, 0x01, 0x54, 0xFF, 0x2C, 0x00, 0xFF, 0xFF, 0x00,
+ 0x00, 0x29, 0x00, 0x60, 0xFF, 0x6D, 0x01, 0x6E, 0xFD, 0x17, 0x04,
+ 0xBC, 0xF9, 0x30, 0x0B, 0xF4, 0x47, 0x4B, 0xFD, 0xB5, 0xFF, 0xFD,
+ 0x00, 0x08, 0xFF, 0xAC, 0x00, 0xAC, 0xFF, 0x14, 0x00, 0xFD, 0xFF,
+ 0x36, 0x00, 0x36, 0xFF, 0xE6, 0x01, 0x41, 0xFC, 0xC8, 0x06, 0x76,
+ 0xF3, 0x22, 0x20, 0xCA, 0x3D, 0x7D, 0xF3, 0x2A, 0x05, 0xC8, 0xFD,
+ 0xD4, 0x00, 0xCA, 0xFF, 0x03, 0x00, 0x02, 0x00, 0xFE, 0xFF, 0x21,
+ 0x00, 0x77, 0xFF, 0x77, 0x01, 0xBD, 0xFC, 0xAE, 0x06, 0xA3, 0xF1,
+ 0xE3, 0x34, 0x64, 0x2B, 0xBC, 0xF1, 0x2A, 0x07, 0x43, 0xFC, 0xCD,
+ 0x01, 0x48, 0xFF, 0x31, 0x00, 0xFD, 0xFF, 0x09, 0x00, 0xDD, 0xFF,
+ 0x2E, 0x00, 0x0A, 0x00, 0x27, 0xFF, 0xEF, 0x02, 0x20, 0xF7, 0xE7,
+ 0x43, 0xD8, 0x15, 0x1E, 0xF6, 0xC0, 0x05, 0xA7, 0xFC, 0xC3, 0x01,
+ 0x40, 0xFF, 0x33, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x20, 0x00, 0x7F,
+ 0xFF, 0x20, 0x01, 0x16, 0xFE, 0xCA, 0x02, 0x54, 0xFC, 0xB9, 0x04,
+ 0xF2, 0x48, 0xA9, 0x02, 0x39, 0xFD, 0x53, 0x02, 0x53, 0xFE, 0x03,
+ 0x01, 0x8A, 0xFF, 0x1D, 0x00, 0xFE, 0xFF, 0x34, 0x00, 0x3B, 0xFF,
+ 0xD1, 0x01, 0x84, 0xFC, 0x12, 0x06, 0x5C, 0xF5, 0x76, 0x18, 0x89,
+ 0x42, 0x02, 0xF6, 0x94, 0x03, 0xC4, 0xFE, 0x42, 0x00, 0x12, 0x00,
+ 0xE8, 0xFF, 0x07, 0x00, 0xFD, 0xFF, 0x2E, 0x00, 0x51, 0xFF, 0xBD,
+ 0x01, 0x57, 0xFC, 0x1E, 0x07, 0x90, 0xF1, 0xED, 0x2D, 0x8C, 0x32,
+ 0x83, 0xF1, 0xE2, 0x06, 0x92, 0xFC, 0x93, 0x01, 0x68, 0xFF, 0x26,
+ 0x00, 0xFD, 0xFF, 0x03, 0x00, 0xFA, 0xFF, 0xE2, 0xFF, 0xA4, 0x00,
+ 0x19, 0xFE, 0xAA, 0x04, 0x3E, 0xF4, 0x90, 0x3F, 0x78, 0x1D, 0x10,
+ 0xF4, 0x93, 0x06, 0x52, 0xFC, 0xE1, 0x01, 0x36, 0xFF, 0x36, 0x00,
+ 0xFE, 0xFF, 0x17, 0x00, 0xA0, 0xFF, 0xCA, 0x00, 0xC9, 0xFE, 0x73,
+ 0x01, 0xDE, 0xFE, 0x0C, 0xFF, 0x76, 0x48, 0xDE, 0x08, 0xA1, 0xFA,
+ 0xA6, 0x03, 0xA6, 0xFD, 0x53, 0x01, 0x6A, 0xFF, 0x26, 0x00, 0x00,
+ 0x00, 0xFF, 0xFF, 0x2F, 0x00, 0x4C, 0xFF, 0xA2, 0x01, 0xF6, 0xFC,
+ 0x12, 0x05, 0xA7, 0xF7, 0x03, 0x11, 0x10, 0x46, 0x93, 0xF9, 0x98,
+ 0x01, 0xEE, 0xFF, 0x9B, 0xFF, 0x64, 0x00, 0xC8, 0xFF, 0x0E, 0x00,
+ 0xFD, 0xFF, 0x35, 0x00, 0x3C, 0xFF, 0xE1, 0x01, 0x32, 0xFC, 0x1B,
+ 0x07, 0x50, 0xF2, 0x7B, 0x26, 0x11, 0x39, 0x2F, 0xF2, 0x23, 0x06,
+ 0x22, 0xFD, 0x37, 0x01, 0x97, 0xFF, 0x15, 0x00, 0xFF, 0xFF, 0x00,
+ 0x00, 0x12, 0x00, 0xA1, 0xFF, 0x24, 0x01, 0x41, 0xFD, 0xF6, 0x05,
+ 0x67, 0xF2, 0x1A, 0x3A, 0x29, 0x25, 0x84, 0xF2, 0x0F, 0x07, 0x31,
+ 0xFC, 0xE3, 0x01, 0x3A, 0xFF, 0x35, 0x00, 0xFD, 0xFF, 0x0F, 0x00,
+ 0xC2, 0xFF, 0x73, 0x00, 0x7D, 0xFF, 0x25, 0x00, 0x38, 0x01, 0x4C,
+ 0xFA, 0x89, 0x46, 0xC3, 0x0F, 0x14, 0xF8, 0xE0, 0x04, 0x0D, 0xFD,
+ 0x98, 0x01, 0x50, 0xFF, 0x2E, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x27,
+ 0x00, 0x65, 0xFF, 0x60, 0x01, 0x8A, 0xFD, 0xDF, 0x03, 0x2E, 0xFA,
+ 0x04, 0x0A, 0x3A, 0x48, 0x28, 0xFE, 0x4B, 0xFF, 0x38, 0x01, 0xE9,
+ 0xFE, 0xBB, 0x00, 0xA6, 0xFF, 0x16, 0x00, 0xFE, 0xFF, 0x36, 0x00,
+ 0x36, 0xFF, 0xE4, 0x01, 0x49, 0xFC, 0xAF, 0x06, 0xC1, 0xF3, 0xCD,
+ 0x1E, 0xB1, 0x3E, 0xD9, 0xF3, 0xEC, 0x04, 0xF0, 0xFD, 0xBC, 0x00,
+ 0xD5, 0xFF, 0xFE, 0xFF, 0x03, 0x00, 0xFD, 0xFF, 0x24, 0x00, 0x6F,
+ 0xFF, 0x85, 0x01, 0xA6, 0xFC, 0xCA, 0x06, 0x8F, 0xF1, 0xBB, 0x33,
+ 0xAB, 0x2C, 0xA3, 0xF1, 0x26, 0x07, 0x4C, 0xFC, 0xC5, 0x01, 0x4D,
+ 0xFF, 0x30, 0x00, 0xFD, 0xFF, 0x08, 0x00, 0xE2, 0xFF, 0x20, 0x00,
+ 0x26, 0x00, 0xF5, 0xFE, 0x43, 0x03, 0x8D, 0xF6, 0x3C, 0x43, 0x25,
+ 0x17, 0xBB, 0xF5, 0xEA, 0x05, 0x95, 0xFC, 0xCA, 0x01, 0x3D, 0xFF,
+ 0x34, 0x00, 0xFE, 0xFF, 0x00, 0x00, 0x1E, 0x00, 0x84, 0xFF, 0x11,
+ 0x01, 0x34, 0xFE, 0x8F, 0x02, 0xC7, 0xFC, 0xAE, 0x03, 0xF7, 0x48,
+ 0xAE, 0x03, 0xC7, 0xFC, 0x8F, 0x02, 0x34, 0xFE, 0x11, 0x01, 0x84,
+ 0xFF, 0x1E, 0x00, 0xFD, 0xFF, 0x36, 0x00, 0x36, 0xFF, 0xE6, 0x01,
+ 0x3D, 0xFC, 0xD6, 0x06, 0x4C, 0xF3, 0xED, 0x20, 0x3D, 0x3D, 0x4A,
+ 0xF3, 0x4E, 0x05, 0xB1, 0xFD, 0xE1, 0x00, 0xC3, 0xFF, 0x05, 0x00,
+ 0x02, 0x00, 0x02, 0x00, 0x05, 0x00, 0xC3, 0xFF, 0xE1, 0x00, 0xB1,
+ 0xFD, 0x4E, 0x05, 0x4A, 0xF3, 0x3D, 0x3D, 0xED, 0x20, 0x4C, 0xF3,
+ 0xD6, 0x06, 0x3D, 0xFC, 0xE6, 0x01, 0x36, 0xFF, 0x36, 0x00, 0xFD,
+ 0xFF, 0x00, 0x00, 0x1E, 0x00, 0x84, 0xFF, 0x11, 0x01, 0x34, 0xFE,
+ 0x8F, 0x02, 0xC7, 0xFC, 0xAE, 0x03, 0xF7, 0x48, 0xAE, 0x03, 0xC7,
+ 0xFC, 0x8F, 0x02, 0x34, 0xFE, 0x11, 0x01, 0x84, 0xFF, 0x1E, 0x00,
+ 0xFD, 0xFF, 0x30, 0x00, 0x4D, 0xFF, 0xC5, 0x01, 0x4C, 0xFC, 0x26,
+ 0x07, 0xA3, 0xF1, 0xAB, 0x2C, 0xBB, 0x33, 0x8F, 0xF1, 0xCA, 0x06,
+ 0xA6, 0xFC, 0x85, 0x01, 0x6F, 0xFF, 0x24, 0x00, 0xFD, 0xFF, 0x16,
+ 0x00, 0xA6, 0xFF, 0xBB, 0x00, 0xE9, 0xFE, 0x38, 0x01, 0x4B, 0xFF,
+ 0x28, 0xFE, 0x3A, 0x48, 0x04, 0x0A, 0x2E, 0xFA, 0xDF, 0x03, 0x8A,
+ 0xFD, 0x60, 0x01, 0x65, 0xFF, 0x27, 0x00, 0x00, 0x00, 0xFD, 0xFF,
+ 0x35, 0x00, 0x3A, 0xFF, 0xE3, 0x01, 0x31, 0xFC, 0x0F, 0x07, 0x84,
+ 0xF2, 0x29, 0x25, 0x1A, 0x3A, 0x67, 0xF2, 0xF6, 0x05, 0x41, 0xFD,
+ 0x24, 0x01, 0xA1, 0xFF, 0x12, 0x00, 0x00, 0x00, 0x0E, 0x00, 0xC8,
+ 0xFF, 0x64, 0x00, 0x9B, 0xFF, 0xEE, 0xFF, 0x98, 0x01, 0x93, 0xF9,
+ 0x10, 0x46, 0x03, 0x11, 0xA7, 0xF7, 0x12, 0x05, 0xF6, 0xFC, 0xA2,
+ 0x01, 0x4C, 0xFF, 0x2F, 0x00, 0xFF, 0xFF, 0xFE, 0xFF, 0x36, 0x00,
+ 0x36, 0xFF, 0xE1, 0x01, 0x52, 0xFC, 0x93, 0x06, 0x10, 0xF4, 0x78,
+ 0x1D, 0x90, 0x3F, 0x3E, 0xF4, 0xAA, 0x04, 0x19, 0xFE, 0xA4, 0x00,
+ 0xE2, 0xFF, 0xFA, 0xFF, 0x03, 0x00, 0x07, 0x00, 0xE8, 0xFF, 0x12,
+ 0x00, 0x42, 0x00, 0xC4, 0xFE, 0x94, 0x03, 0x02, 0xF6, 0x89, 0x42,
+ 0x76, 0x18, 0x5C, 0xF5, 0x12, 0x06, 0x84, 0xFC, 0xD1, 0x01, 0x3B,
+ 0xFF, 0x34, 0x00, 0xFE, 0xFF, 0xFF, 0xFF, 0x33, 0x00, 0x40, 0xFF,
+ 0xC3, 0x01, 0xA7, 0xFC, 0xC0, 0x05, 0x1E, 0xF6, 0xD8, 0x15, 0xE7,
+ 0x43, 0x20, 0xF7, 0xEF, 0x02, 0x27, 0xFF, 0x0A, 0x00, 0x2E, 0x00,
+ 0xDD, 0xFF, 0x09, 0x00, 0x02, 0x00, 0x03, 0x00, 0xCA, 0xFF, 0xD4,
+ 0x00, 0xC8, 0xFD, 0x2A, 0x05, 0x7D, 0xF3, 0xCA, 0x3D, 0x22, 0x20,
+ 0x76, 0xF3, 0xC8, 0x06, 0x41, 0xFC, 0xE6, 0x01, 0x36, 0xFF, 0x36,
+ 0x00, 0xFD, 0xFF, 0xFF, 0xFF, 0x2C, 0x00, 0x54, 0xFF, 0x8D, 0x01,
+ 0x26, 0xFD, 0xAD, 0x04, 0x82, 0xF8, 0x87, 0x0E, 0xF9, 0x46, 0x0C,
+ 0xFB, 0xD4, 0x00, 0x5D, 0x00, 0x5E, 0xFF, 0x82, 0x00, 0xBD, 0xFF,
+ 0x10, 0x00, 0xFF, 0xFF, 0x19, 0x00, 0x8E, 0xFF, 0x49, 0x01, 0x04,
+ 0xFD, 0x4D, 0x06, 0x00, 0xF2, 0xFE, 0x37, 0xCB, 0x27, 0x21, 0xF2,
+ 0x23, 0x07, 0x34, 0xFC, 0xDD, 0x01, 0x3F, 0xFF, 0x34, 0x00, 0xFD,
+ 0xFF, 0x00, 0x00, 0x24, 0x00, 0x70, 0xFF, 0x46, 0x01, 0xC3, 0xFD,
+ 0x6D, 0x03, 0x14, 0xFB, 0xBE, 0x07, 0xA6, 0x48, 0xF8, 0xFF, 0x70,
+ 0xFE, 0xAE, 0x01, 0xAA, 0xFE, 0xD9, 0x00, 0x9A, 0xFF, 0x19, 0x00,
+ 0xFD, 0xFF, 0x29, 0x00, 0x61, 0xFF, 0x9F, 0x01, 0x80, 0xFC, 0xF7,
+ 0x06, 0x7D, 0xF1, 0x5A, 0x31, 0x2C, 0x2F, 0x83, 0xF1, 0x13, 0x07,
+ 0x64, 0xFC, 0xB3, 0x01, 0x57, 0xFF, 0x2C, 0x00, 0xFD, 0xFF, 0x1B,
+ 0x00, 0x90, 0xFF, 0xF4, 0x00, 0x72, 0xFE, 0x18, 0x02, 0xAA, 0xFD,
+ 0xAB, 0x01, 0xDF, 0x48, 0xCA, 0x05, 0xE1, 0xFB, 0x05, 0x03, 0xF7,
+ 0xFD, 0x2E, 0x01, 0x79, 0xFF, 0x21, 0x00, 0x00, 0x00, 0xFD, 0xFF,
+ 0x32, 0x00, 0x44, 0xFF, 0xD3, 0x01, 0x3C, 0xFC, 0x2A, 0x07, 0xDC,
+ 0xF1, 0x1A, 0x2A, 0x06, 0x36, 0xBE, 0xF1, 0x8E, 0x06, 0xD5, 0xFC,
+ 0x67, 0x01, 0x7F, 0xFF, 0x1E, 0x00, 0xFE, 0xFF, 0x13, 0x00, 0xB2,
+ 0xFF, 0x9D, 0x00, 0x27, 0xFF, 0xC3, 0x00, 0x1F, 0x00, 0x76, 0xFC,
+ 0xA3, 0x47, 0x60, 0x0C, 0x4A, 0xF9, 0x4E, 0x04, 0x53, 0xFD, 0x79,
+ 0x01, 0x5C, 0xFF, 0x2A, 0x00, 0x00, 0x00, 0xFD, 0xFF, 0x36, 0x00,
+ 0x37, 0xFF, 0xE6, 0x01, 0x36, 0xFC, 0xEF, 0x06, 0xFC, 0xF2, 0x81,
+ 0x22, 0x1C, 0x3C, 0xEC, 0xF2, 0x90, 0x05, 0x85, 0xFD, 0xFB, 0x00,
+ 0xB6, 0xFF, 0x0A, 0x00, 0x01, 0x00, 0x0B, 0x00, 0xD3, 0xFF, 0x47,
+ 0x00, 0xD7, 0xFF, 0x82, 0xFF, 0x53, 0x02, 0x39, 0xF8, 0xFD, 0x44,
+ 0x8D, 0x13, 0xD3, 0xF6, 0x72, 0x05, 0xCA, 0xFC, 0xB5, 0x01, 0x45,
+ 0xFF, 0x31, 0x00, 0xFF, 0xFF, 0xFE, 0xFF, 0x35, 0x00, 0x38, 0xFF,
+ 0xDA, 0x01, 0x6A, 0xFC, 0x53, 0x06, 0xBA, 0xF4, 0xCE, 0x1A, 0x32,
+ 0x41, 0x1F, 0xF5, 0x1D, 0x04, 0x71, 0xFE, 0x71, 0x00, 0xFB, 0xFF,
+ 0xF0, 0xFF, 0x05, 0x00, 0x05, 0x00, 0xF2, 0xFF, 0xF8, 0xFF, 0x77,
+ 0x00, 0x67, 0xFE, 0x2D, 0x04, 0x04, 0xF5, 0x07, 0x41, 0x1B, 0x1B,
+ 0xA6, 0xF4, 0x5A, 0x06, 0x67, 0xFC, 0xDB, 0x01, 0x38, 0xFF, 0x36,
+ 0x00, 0xFE, 0xFF, 0xFF, 0xFF, 0x31, 0x00, 0x46, 0xFF, 0xB3, 0x01,
+ 0xCF, 0xFC, 0x67, 0x05, 0xEA, 0xF6, 0x44, 0x13, 0x1E, 0x45, 0x5E,
+ 0xF8, 0x3F, 0x02, 0x8E, 0xFF, 0xD0, 0xFF, 0x4A, 0x00, 0xD2, 0xFF,
+ 0x0B, 0x00, 0x01, 0x00, 0x0B, 0x00, 0xB4, 0xFF, 0x00, 0x01, 0x7E,
+ 0xFD, 0x9C, 0x05, 0xDC, 0xF2, 0xE4, 0x3B, 0xCD, 0x22, 0xEE, 0xF2,
+ 0xF3, 0x06, 0x35, 0xFC, 0xE6, 0x01, 0x37, 0xFF, 0x36, 0x00, 0xFD,
+ 0xFF, 0x00, 0x00, 0x2A, 0x00, 0x5D, 0xFF, 0x76, 0x01, 0x59, 0xFD,
+ 0x42, 0x04, 0x63, 0xF9, 0x1C, 0x0C, 0xB6, 0x47, 0xA4, 0xFC, 0x07,
+ 0x00, 0xD0, 0x00, 0x20, 0xFF, 0xA0, 0x00, 0xB1, 0xFF, 0x13, 0x00,
+ 0xFE, 0xFF, 0x1F, 0x00, 0x7D, 0xFF, 0x6B, 0x01, 0xCF, 0xFC, 0x96,
+ 0x06, 0xB7, 0xF1, 0xC6, 0x35, 0x64, 0x2A, 0xD4, 0xF1, 0x2B, 0x07,
+ 0x3D, 0xFC, 0xD2, 0x01, 0x45, 0xFF, 0x32, 0x00, 0xFD, 0xFF, 0x00,
+ 0x00, 0x21, 0x00, 0x7A, 0xFF, 0x2B, 0x01, 0xFE, 0xFD, 0xF8, 0x02,
+ 0xFB, 0xFB, 0x8D, 0x05, 0xE5, 0x48, 0xE3, 0x01, 0x91, 0xFD, 0x25,
+ 0x02, 0x6B, 0xFE, 0xF7, 0x00, 0x8F, 0xFF, 0x1C, 0x00, 0xFD, 0xFF,
+ 0x2D, 0x00, 0x55, 0xFF, 0xB5, 0x01, 0x61, 0xFC, 0x16, 0x07, 0x85,
+ 0xF1, 0xE6, 0x2E, 0x9E, 0x31, 0x7D, 0xF1, 0xF3, 0x06, 0x84, 0xFC,
+ 0x9D, 0x01, 0x63, 0xFF, 0x28, 0x00, 0xFD, 0xFF, 0x18, 0x00, 0x9C,
+ 0xFF, 0xD6, 0x00, 0xB1, 0xFE, 0xA1, 0x01, 0x89, 0xFE, 0xC3, 0xFF,
+ 0x9C, 0x48, 0xFD, 0x07, 0xFA, 0xFA, 0x7A, 0x03, 0xBC, 0xFD, 0x49,
+ 0x01, 0x6E, 0xFF, 0x24, 0x00, 0x00, 0x00, 0xFD, 0xFF, 0x34, 0x00,
+ 0x3E, 0xFF, 0xDE, 0x01, 0x33, 0xFC, 0x22, 0x07, 0x2B, 0xF2, 0x80,
+ 0x27, 0x3B, 0x38, 0x0A, 0xF2, 0x44, 0x06, 0x0B, 0xFD, 0x45, 0x01,
+ 0x90, 0xFF, 0x18, 0x00, 0xFF, 0xFF, 0x10, 0x00, 0xBE, 0xFF, 0x7F,
+ 0x00, 0x65, 0xFF, 0x51, 0x00, 0xEB, 0x00, 0xE1, 0xFA, 0xE1, 0x46,
+ 0xCD, 0x0E, 0x6A, 0xF8, 0xB8, 0x04, 0x20, 0xFD, 0x90, 0x01, 0x53,
+ 0xFF, 0x2D, 0x00, 0xFF, 0xFF, 0xFD, 0xFF, 0x36, 0x00, 0x36, 0xFF,
+ 0xE5, 0x01, 0x42, 0xFC, 0xC3, 0x06, 0x87, 0xF3, 0xD7, 0x1F, 0xFE,
+ 0x3D, 0x91, 0xF3, 0x1D, 0x05, 0xD1, 0xFD, 0xCE, 0x00, 0xCC, 0xFF,
+ 0x02, 0x00, 0x02, 0x00, 0x09, 0x00, 0xDE, 0xFF, 0x2B, 0x00, 0x11,
+ 0x00, 0x1B, 0xFF, 0x02, 0x03, 0xFE, 0xF6, 0xC3, 0x43, 0x22, 0x16,
+ 0x07, 0xF6, 0xCA, 0x05, 0xA3, 0xFC, 0xC5, 0x01, 0x3F, 0xFF, 0x33,
+ 0x00, 0xFF, 0xFF, 0xFE, 0xFF, 0x34, 0x00, 0x3C, 0xFF, 0xCF, 0x01,
+ 0x88, 0xFC, 0x09, 0x06, 0x71, 0xF5, 0x2B, 0x18, 0xB2, 0x42, 0x20,
+ 0xF6, 0x83, 0x03, 0xCF, 0xFE, 0x3C, 0x00, 0x15, 0x00, 0xE6, 0xFF,
+ 0x07, 0x00, 0x03, 0x00, 0xFB, 0xFF, 0xDF, 0xFF, 0xA9, 0x00, 0x10,
+ 0xFE, 0xB9, 0x04, 0x27, 0xF4, 0x5E, 0x3F, 0xC3, 0x1D, 0xFE, 0xF3,
+ 0x99, 0x06, 0x50, 0xFC, 0xE2, 0x01, 0x36, 0xFF, 0x36, 0x00, 0xFE,
+ 0xFF, 0xFF, 0xFF, 0x2F, 0x00, 0x4D, 0xFF, 0xA0, 0x01, 0xFB, 0xFC,
+ 0x07, 0x05, 0xBF, 0xF7, 0xBB, 0x10, 0x2B, 0x46, 0xBB, 0xF9, 0x83,
+ 0x01, 0xFA, 0xFF, 0x95, 0xFF, 0x68, 0x00, 0xC7, 0xFF, 0x0E, 0x00,
+ 0x00, 0x00, 0x13, 0x00, 0x9F, 0xFF, 0x28, 0x01, 0x3A, 0xFD, 0x00,
+ 0x06, 0x5A, 0xF2, 0xDF, 0x39, 0x73, 0x25, 0x79, 0xF2, 0x12, 0x07,
+ 0x31, 0xFC, 0xE3, 0x01, 0x3B, 0xFF, 0x35, 0x00, 0xFD, 0xFF, 0x00,
+ 0x00, 0x27, 0x00, 0x66, 0xFF, 0x5E, 0x01, 0x90, 0xFD, 0xD2, 0x03,
+ 0x47, 0xFA, 0xC3, 0x09, 0x48, 0x48, 0x5A, 0xFE, 0x33, 0xFF, 0x45,
+ 0x01, 0xE2, 0xFE, 0xBE, 0x00, 0xA5, 0xFF, 0x16, 0x00, 0xFD, 0xFF,
+ 0x24, 0x00, 0x6D, 0xFF, 0x88, 0x01, 0xA2, 0xFC, 0xD0, 0x06, 0x8C,
+ 0xF1, 0x78, 0x33, 0xF2, 0x2C, 0x9E, 0xF1, 0x24, 0x07, 0x4E, 0xFC,
+ 0xC3, 0x01, 0x4E, 0xFF, 0x2F, 0x00, 0xFD, 0xFF, 0x1E, 0x00, 0x86,
+ 0xFF, 0x0E, 0x01, 0x3B, 0xFE, 0x82, 0x02, 0xE0, 0xFC, 0x73, 0x03,
+ 0xF6, 0x48, 0xE9, 0x03, 0xAD, 0xFC, 0x9C, 0x02, 0x2D, 0xFE, 0x14,
+ 0x01, 0x83, 0xFF, 0x1F, 0x00, 0x00, 0x00, 0xFD, 0xFF, 0x30, 0x00,
+ 0x4C, 0xFF, 0xC7, 0x01, 0x4A, 0xFC, 0x27, 0x07, 0xA8, 0xF1, 0x62,
+ 0x2C, 0xFD, 0x33, 0x93, 0xF1, 0xC4, 0x06, 0xAB, 0xFC, 0x82, 0x01,
+ 0x71, 0xFF, 0x23, 0x00, 0xFE, 0xFF, 0x15, 0x00, 0xA8, 0xFF, 0xB8,
+ 0x00, 0xF0, 0xFE, 0x2B, 0x01, 0x63, 0xFF, 0xF6, 0xFD, 0x2C, 0x48,
+ 0x47, 0x0A, 0x14, 0xFA, 0xEB, 0x03, 0x84, 0xFD, 0x63, 0x01, 0x64,
+ 0xFF, 0x27, 0x00, 0x00, 0x00, 0xFD, 0xFF, 0x36, 0x00, 0x3A, 0xFF,
+ 0xE4, 0x01, 0x32, 0xFC, 0x0C, 0x07, 0x91, 0xF2, 0xDD, 0x24, 0x54,
+ 0x3A, 0x74, 0xF2, 0xEB, 0x05, 0x49, 0xFD, 0x20, 0x01, 0xA3, 0xFF,
+ 0x11, 0x00, 0x00, 0x00, 0x0D, 0x00, 0xC9, 0xFF, 0x61, 0x00, 0xA2,
+ 0xFF, 0xE2, 0xFF, 0xAE, 0x01, 0x6B, 0xF9, 0xF2, 0x45, 0x4A, 0x11,
+ 0x8F, 0xF7, 0x1D, 0x05, 0xF1, 0xFC, 0xA4, 0x01, 0x4B, 0xFF, 0x2F,
+ 0x00, 0xFF, 0xFF, 0xFE, 0xFF, 0x36, 0x00, 0x37, 0xFF, 0xE1, 0x01,
+ 0x55, 0xFC, 0x8C, 0x06, 0x22, 0xF4, 0x2C, 0x1D, 0xC0, 0x3F, 0x55,
+ 0xF4, 0x9B, 0x04, 0x23, 0xFE, 0x9F, 0x00, 0xE4, 0xFF, 0xF9, 0xFF,
+ 0x04, 0x00, 0x07, 0x00, 0xE9, 0xFF, 0x0F, 0x00, 0x48, 0x00, 0xB9,
+ 0xFE, 0xA6, 0x03, 0xE4, 0xF5, 0x60, 0x42, 0xC1, 0x18, 0x47, 0xF5,
+ 0x1A, 0x06, 0x81, 0xFC, 0xD2, 0x01, 0x3B, 0xFF, 0x35, 0x00, 0xFE,
+ 0xFF, 0xFF, 0xFF, 0x33, 0x00, 0x40, 0xFF, 0xC1, 0x01, 0xAB, 0xFC,
+ 0xB7, 0x05, 0x34, 0xF6, 0x8E, 0x15, 0x0B, 0x44, 0x42, 0xF7, 0xDC,
+ 0x02, 0x32, 0xFF, 0x04, 0x00, 0x31, 0x00, 0xDC, 0xFF, 0x09, 0x00,
+ 0x02, 0x00, 0x04, 0x00, 0xC7, 0xFF, 0xD9, 0x00, 0xBF, 0xFD, 0x38,
+ 0x05, 0x69, 0xF3, 0x96, 0x3D, 0x6F, 0x20, 0x66, 0xF3, 0xCE, 0x06,
+ 0x3F, 0xFC, 0xE6, 0x01, 0x36, 0xFF, 0x36, 0x00, 0xFD, 0xFF, 0xFF,
+ 0xFF, 0x2C, 0x00, 0x55, 0xFF, 0x8B, 0x01, 0x2B, 0xFD, 0xA1, 0x04,
+ 0x9B, 0xF8, 0x42, 0x0E, 0x0F, 0x47, 0x38, 0xFB, 0xBE, 0x00, 0x6A,
+ 0x00, 0x58, 0xFF, 0x85, 0x00, 0xBB, 0xFF, 0x10, 0x00, 0xFF, 0xFF,
+ 0x19, 0x00, 0x8C, 0xFF, 0x4D, 0x01, 0xFE, 0xFC, 0x56, 0x06, 0xF7,
+ 0xF1, 0xBF, 0x37, 0x15, 0x28, 0x18, 0xF2, 0x25, 0x07, 0x34, 0xFC,
+ 0xDC, 0x01, 0x3F, 0xFF, 0x34, 0x00, 0xFD, 0xFF, 0x00, 0x00, 0x24,
+ 0x00, 0x71, 0xFF, 0x43, 0x01, 0xC9, 0xFD, 0x60, 0x03, 0x2E, 0xFB,
+ 0x7E, 0x07, 0xAF, 0x48, 0x2D, 0x00, 0x58, 0xFE, 0xBB, 0x01, 0xA3,
+ 0xFE, 0xDD, 0x00, 0x99, 0xFF, 0x19, 0x00, 0xFD, 0xFF, 0x29, 0x00,
+ 0x60, 0xFF, 0xA2, 0x01, 0x7C, 0xFC, 0xFB, 0x06, 0x7C, 0xF1, 0x15,
+ 0x31, 0x73, 0x2F, 0x81, 0xF1, 0x10, 0x07, 0x67, 0xFC, 0xB1, 0x01,
+ 0x58, 0xFF, 0x2C, 0x00, 0xFD, 0xFF, 0x1B, 0x00, 0x91, 0xFF, 0xF1,
+ 0x00, 0x79, 0xFE, 0x0A, 0x02, 0xC3, 0xFD, 0x73, 0x01, 0xDB, 0x48,
+ 0x07, 0x06, 0xC7, 0xFB, 0x12, 0x03, 0xF1, 0xFD, 0x31, 0x01, 0x78,
+ 0xFF, 0x22, 0x00, 0x00, 0x00, 0xFD, 0xFF, 0x32, 0x00, 0x44, 0xFF,
+ 0xD5, 0x01, 0x3A, 0xFC, 0x2A, 0x07, 0xE3, 0xF1, 0xD1, 0x29, 0x46,
+ 0x36, 0xC5, 0xF1, 0x87, 0x06, 0xDA, 0xFC, 0x64, 0x01, 0x80, 0xFF,
+ 0x1E, 0x00, 0xFE, 0xFF, 0x12, 0x00, 0xB3, 0xFF, 0x99, 0x00, 0x2E,
+ 0xFF, 0xB6, 0x00, 0x36, 0x00, 0x47, 0xFC, 0x90, 0x47, 0xA4, 0x0C,
+ 0x31, 0xF9, 0x5A, 0x04, 0x4E, 0xFD, 0x7C, 0x01, 0x5B, 0xFF, 0x2A,
+ 0x00, 0x00, 0x00, 0xFD, 0xFF, 0x36, 0x00, 0x37, 0xFF, 0xE6, 0x01,
+ 0x37, 0xFC, 0xEB, 0x06, 0x0B, 0xF3, 0x35, 0x22, 0x52, 0x3C, 0xFD,
+ 0xF2, 0x84, 0x05, 0x8D, 0xFD, 0xF6, 0x00, 0xB8, 0xFF, 0x09, 0x00,
+ 0x01, 0x00, 0x0B, 0x00, 0xD5, 0xFF, 0x44, 0x00, 0xDD, 0xFF, 0x77,
+ 0xFF, 0x67, 0x02, 0x14, 0xF8, 0xDC, 0x44, 0xD5, 0x13, 0xBC, 0xF6,
+ 0x7C, 0x05, 0xC5, 0xFC, 0xB7, 0x01, 0x44, 0xFF, 0x31, 0x00, 0xFF,
+ 0xFF, 0xFE, 0xFF, 0x35, 0x00, 0x39, 0xFF, 0xD9, 0x01, 0x6D, 0xFC,
+ 0x4B, 0x06, 0xCD, 0xF4, 0x83, 0x1A, 0x5F, 0x41, 0x3A, 0xF5, 0x0C,
+ 0x04, 0x7B, 0xFE, 0x6C, 0x00, 0xFE, 0xFF, 0xEF, 0xFF, 0x05, 0x00,
+ 0x05, 0x00, 0xF3, 0xFF, 0xF5, 0xFF, 0x7D, 0x00, 0x5D, 0xFE, 0x3E,
+ 0x04, 0xEA, 0xF4, 0xD9, 0x40, 0x66, 0x1B, 0x93, 0xF4, 0x62, 0x06,
+ 0x64, 0xFC, 0xDC, 0x01, 0x38, 0xFF, 0x36, 0x00, 0xFE, 0xFF, 0xFF,
+ 0xFF, 0x31, 0x00, 0x46, 0xFF, 0xB1, 0x01, 0xD3, 0xFC, 0x5D, 0x05,
+ 0x01, 0xF7, 0xFB, 0x12, 0x3F, 0x45, 0x83, 0xF8, 0x2A, 0x02, 0x9A,
+ 0xFF, 0xCA, 0xFF, 0x4E, 0x00, 0xD1, 0xFF, 0x0C, 0x00, 0x00, 0x00,
+ 0x0C, 0x00, 0xB1, 0xFF, 0x04, 0x01, 0x76, 0xFD, 0xA8, 0x05, 0xCC,
+ 0xF2, 0xAB, 0x3B, 0x18, 0x23, 0xE0, 0xF2, 0xF7, 0x06, 0x35, 0xFC,
+ 0xE6, 0x01, 0x38, 0xFF, 0x36, 0x00, 0xFD, 0xFF, 0x00, 0x00, 0x29,
+ 0x00, 0x5E, 0xFF, 0x74, 0x01, 0x5F, 0xFD, 0x35, 0x04, 0x7C, 0xF9,
+ 0xD8, 0x0B, 0xC9, 0x47, 0xD4, 0xFC, 0xF0, 0xFF, 0xDD, 0x00, 0x19,
+ 0xFF, 0xA4, 0x00, 0xAF, 0xFF, 0x13, 0x00, 0xFE, 0xFF, 0x20, 0x00,
+ 0x7B, 0xFF, 0x6E, 0x01, 0xCA, 0xFC, 0x9D, 0x06, 0xB1, 0xF1, 0x86,
+ 0x35, 0xAE, 0x2A, 0xCD, 0xF1, 0x2B, 0x07, 0x3F, 0xFC, 0xD1, 0x01,
+ 0x46, 0xFF, 0x32, 0x00, 0xFD, 0xFF, 0x00, 0x00, 0x21, 0x00, 0x7C,
+ 0xFF, 0x27, 0x01, 0x05, 0xFE, 0xEB, 0x02, 0x14, 0xFC, 0x50, 0x05,
+ 0xEA, 0x48, 0x1B, 0x02, 0x78, 0xFD, 0x32, 0x02, 0x64, 0xFE, 0xFA,
+ 0x00, 0x8D, 0xFF, 0x1C, 0x00, 0xFD, 0xFF, 0x2D, 0x00, 0x54, 0xFF,
+ 0xB7, 0x01, 0x5E, 0xFC, 0x19, 0x07, 0x88, 0xF1, 0x9F, 0x2E, 0xE3,
+ 0x31, 0x7E, 0xF1, 0xEE, 0x06, 0x88, 0xFC, 0x9A, 0x01, 0x64, 0xFF,
+ 0x28, 0x00, 0xFD, 0xFF, 0x18, 0x00, 0x9D, 0xFF, 0xD3, 0x00, 0xB8,
+ 0xFE, 0x93, 0x01, 0xA1, 0xFE, 0x8E, 0xFF, 0x92, 0x48, 0x3D, 0x08,
+ 0xE1, 0xFA, 0x86, 0x03, 0xB6, 0xFD, 0x4C, 0x01, 0x6D, 0xFF, 0x25,
+ 0x00, 0x00, 0x00, 0xFD, 0xFF, 0x34, 0x00, 0x3E, 0xFF, 0xDF, 0x01,
+ 0x33, 0xFC, 0x20, 0x07, 0x35, 0xF2, 0x36, 0x27, 0x78, 0x38, 0x14,
+ 0xF2, 0x3B, 0x06, 0x11, 0xFD, 0x41, 0x01, 0x92, 0xFF, 0x17, 0x00,
+ 0xFF, 0xFF, 0x10, 0x00, 0xBF, 0xFF, 0x7B, 0x00, 0x6C, 0xFF, 0x44,
+ 0x00, 0x01, 0x01, 0xB6, 0xFA, 0xC8, 0x46, 0x13, 0x0F, 0x51, 0xF8,
+ 0xC4, 0x04, 0x1B, 0xFD, 0x92, 0x01, 0x52, 0xFF, 0x2D, 0x00, 0xFF,
+ 0xFF, 0xFD, 0xFF, 0x36, 0x00, 0x36, 0xFF, 0xE5, 0x01, 0x44, 0xFC,
+ 0xBD, 0x06, 0x97, 0xF3, 0x8A, 0x1F, 0x31, 0x3E, 0xA5, 0xF3, 0x0F,
+ 0x05, 0xDA, 0xFD, 0xC9, 0x00, 0xCF, 0xFF, 0x01, 0x00, 0x02, 0x00,
+ 0x09, 0x00, 0xDF, 0xFF, 0x28, 0x00, 0x17, 0x00, 0x10, 0xFF, 0x15,
+ 0x03, 0xDD, 0xF6, 0x9E, 0x43, 0x6C, 0x16, 0xF1, 0xF5, 0xD3, 0x05,
+ 0x9F, 0xFC, 0xC6, 0x01, 0x3F, 0xFF, 0x33, 0x00, 0xFF, 0xFF, 0xFE,
+ 0xFF, 0x34, 0x00, 0x3C, 0xFF, 0xCE, 0x01, 0x8C, 0xFC, 0x00, 0x06,
+ 0x86, 0xF5, 0xE0, 0x17, 0xDB, 0x42, 0x3F, 0xF6, 0x71, 0x03, 0xD9,
+ 0xFE, 0x36, 0x00, 0x18, 0x00, 0xE5, 0xFF, 0x07, 0x00, 0x03, 0x00,
+ 0xFC, 0xFF, 0xDC, 0xFF, 0xAF, 0x00, 0x07, 0xFE, 0xC8, 0x04, 0x10,
+ 0xF4, 0x2D, 0x3F, 0x0F, 0x1E, 0xED, 0xF3, 0xA0, 0x06, 0x4E, 0xFC,
+ 0xE3, 0x01, 0x36, 0xFF, 0x36, 0x00, 0xFE, 0xFF, 0xFF, 0xFF, 0x2E,
+ 0x00, 0x4E, 0xFF, 0x9E, 0x01, 0x00, 0xFD, 0xFC, 0x04, 0xD7, 0xF7,
+ 0x75, 0x10, 0x48, 0x46, 0xE4, 0xF9, 0x6E, 0x01, 0x06, 0x00, 0x8E,
+ 0xFF, 0x6B, 0x00, 0xC6, 0xFF, 0x0E, 0x00, 0xFF, 0xFF, 0x13, 0x00,
+ 0x9D, 0xFF, 0x2D, 0x01, 0x33, 0xFD, 0x0B, 0x06, 0x4D, 0xF2, 0xA5,
+ 0x39, 0xBF, 0x25, 0x6D, 0xF2, 0x15, 0x07, 0x31, 0xFC, 0xE2, 0x01,
+ 0x3B, 0xFF, 0x35, 0x00, 0xFD, 0xFF, 0x00, 0x00, 0x26, 0x00, 0x68,
+ 0xFF, 0x5B, 0x01, 0x96, 0xFD, 0xC6, 0x03, 0x61, 0xFA, 0x81, 0x09,
+ 0x57, 0x48, 0x8D, 0xFE, 0x1B, 0xFF, 0x52, 0x01, 0xDB, 0xFE, 0xC2,
+ 0x00, 0xA4, 0xFF, 0x16, 0x00, 0xFD, 0xFF, 0x25, 0x00, 0x6C, 0xFF,
+ 0x8B, 0x01, 0x9D, 0xFC, 0xD5, 0x06, 0x89, 0xF1, 0x35, 0x33, 0x3A,
+ 0x2D, 0x9A, 0xF1, 0x23, 0x07, 0x51, 0xFC, 0xC2, 0x01, 0x4F, 0xFF,
+ 0x2F, 0x00, 0xFD, 0xFF, 0x1E, 0x00, 0x87, 0xFF, 0x0B, 0x01, 0x42,
+ 0xFE, 0x74, 0x02, 0xF9, 0xFC, 0x39, 0x03, 0xF5, 0x48, 0x24, 0x04,
+ 0x94, 0xFC, 0xA9, 0x02, 0x27, 0xFE, 0x18, 0x01, 0x82, 0xFF, 0x1F,
+ 0x00, 0x00, 0x00, 0xFD, 0xFF, 0x30, 0x00, 0x4B, 0xFF, 0xC9, 0x01,
+ 0x48, 0xFC, 0x28, 0x07, 0xAD, 0xF1, 0x19, 0x2C, 0x3F, 0x34, 0x97,
+ 0xF1, 0xBE, 0x06, 0xB0, 0xFC, 0x7F, 0x01, 0x72, 0xFF, 0x23, 0x00,
+ 0xFE, 0xFF, 0x15, 0x00, 0xA9, 0xFF, 0xB4, 0x00, 0xF7, 0xFE, 0x1D,
+ 0x01, 0x7A, 0xFF, 0xC5, 0xFD, 0x1D, 0x48, 0x89, 0x0A, 0xFB, 0xF9,
+ 0xF8, 0x03, 0x7D, 0xFD, 0x66, 0x01, 0x63, 0xFF, 0x28, 0x00, 0x00,
+ 0x00, 0xFD, 0xFF, 0x36, 0x00, 0x39, 0xFF, 0xE4, 0x01, 0x32, 0xFC,
+ 0x09, 0x07, 0x9D, 0xF2, 0x92, 0x24, 0x8F, 0x3A, 0x82, 0xF2, 0xE1,
+ 0x05, 0x50, 0xFD, 0x1B, 0x01, 0xA6, 0xFF, 0x10, 0x00, 0x00, 0x00,
+ 0x0D, 0x00, 0xCB, 0xFF, 0x5E, 0x00, 0xA9, 0xFF, 0xD6, 0xFF, 0xC3,
+ 0x01, 0x43, 0xF9, 0xD7, 0x45, 0x92, 0x11, 0x77, 0xF7, 0x28, 0x05,
+ 0xEC, 0xFC, 0xA7, 0x01, 0x4A, 0xFF, 0x2F, 0x00, 0xFF, 0xFF, 0xFE,
+ 0xFF, 0x36, 0x00, 0x37, 0xFF, 0xE0, 0x01, 0x57, 0xFC, 0x85, 0x06,
+ 0x34, 0xF4, 0xE0, 0x1C, 0xF0, 0x3F, 0x6D, 0xF4, 0x8C, 0x04, 0x2C,
+ 0xFE, 0x99, 0x00, 0xE7, 0xFF, 0xF8, 0xFF, 0x04, 0x00, 0x06, 0x00,
+ 0xEA, 0xFF, 0x0C, 0x00, 0x4E, 0x00, 0xAF, 0xFE, 0xB8, 0x03, 0xC7,
+ 0xF5, 0x38, 0x42, 0x0C, 0x19, 0x32, 0xF5, 0x23, 0x06, 0x7D, 0xFC,
+ 0xD3, 0x01, 0x3A, 0xFF, 0x35, 0x00, 0xFE, 0xFF, 0xFF, 0xFF, 0x32,
+ 0x00, 0x41, 0xFF, 0xC0, 0x01, 0xAF, 0xFC, 0xAD, 0x05, 0x4A, 0xF6,
+ 0x44, 0x15, 0x2F, 0x44, 0x64, 0xF7, 0xC9, 0x02, 0x3D, 0xFF, 0xFE,
+ 0xFF, 0x34, 0x00, 0xDB, 0xFF, 0x09, 0x00, 0x02, 0x00, 0x05, 0x00,
+ 0xC5, 0xFF, 0xDE, 0x00, 0xB7, 0xFD, 0x45, 0x05, 0x56, 0xF3, 0x61,
+ 0x3D, 0xBA, 0x20, 0x56, 0xF3, 0xD3, 0x06, 0x3E, 0xFC, 0xE6, 0x01,
+ 0x36, 0xFF, 0x36, 0x00, 0xFD, 0xFF, 0xFF, 0xFF, 0x2C, 0x00, 0x56,
+ 0xFF, 0x88, 0x01, 0x31, 0xFD, 0x95, 0x04, 0xB4, 0xF8, 0xFC, 0x0D,
+ 0x26, 0x47, 0x64, 0xFB, 0xA7, 0x00, 0x77, 0x00, 0x51, 0xFF, 0x89,
+ 0x00, 0xBA, 0xFF, 0x11, 0x00, 0xFF, 0xFF, 0x1A, 0x00, 0x8A, 0xFF,
+ 0x51, 0x01, 0xF8, 0xFC, 0x5E, 0x06, 0xED, 0xF1, 0x82, 0x37, 0x60,
+ 0x28, 0x0E, 0xF2, 0x26, 0x07, 0x35, 0xFC, 0xDB, 0x01, 0x40, 0xFF,
+ 0x34, 0x00, 0xFD, 0xFF, 0x00, 0x00, 0x23, 0x00, 0x72, 0xFF, 0x40,
+ 0x01, 0xD0, 0xFD, 0x53, 0x03, 0x47, 0xFB, 0x3F, 0x07, 0xB8, 0x48,
+ 0x62, 0x00, 0x3F, 0xFE, 0xC8, 0x01, 0x9C, 0xFE, 0xE0, 0x00, 0x98,
+ 0xFF, 0x19, 0x00, 0xFD, 0xFF, 0x29, 0x00, 0x5F, 0xFF, 0xA5, 0x01,
+ 0x78, 0xFC, 0xFF, 0x06, 0x7D, 0xF1, 0xCF, 0x30, 0xB8, 0x2F, 0x80,
+ 0xF1, 0x0D, 0x07, 0x6A, 0xFC, 0xAE, 0x01, 0x59, 0xFF, 0x2B, 0x00,
+ 0xFD, 0xFF, 0x1B, 0x00, 0x93, 0xFF, 0xED, 0x00, 0x80, 0xFE, 0xFD,
+ 0x01, 0xDC, 0xFD, 0x3C, 0x01, 0xD5, 0x48, 0x45, 0x06, 0xAE, 0xFB,
+ 0x1F, 0x03, 0xEA, 0xFD, 0x34, 0x01, 0x77, 0xFF, 0x22, 0x00, 0x00,
+ 0x00, 0xFD, 0xFF, 0x33, 0x00, 0x43, 0xFF, 0xD6, 0x01, 0x39, 0xFC,
+ 0x2A, 0x07, 0xEB, 0xF1, 0x87, 0x29, 0x85, 0x36, 0xCC, 0xF1, 0x7F,
+ 0x06, 0xE0, 0xFC, 0x60, 0x01, 0x82, 0xFF, 0x1D, 0x00, 0xFE, 0xFF,
+ 0x12, 0x00, 0xB5, 0xFF, 0x96, 0x00, 0x35, 0xFF, 0xA9, 0x00, 0x4D,
+ 0x00, 0x19, 0xFC, 0x7C, 0x47, 0xE8, 0x0C, 0x18, 0xF9, 0x66, 0x04,
+ 0x48, 0xFD, 0x7E, 0x01, 0x5A, 0xFF, 0x2B, 0x00, 0x00, 0x00, 0xFD,
+ 0xFF, 0x36, 0x00, 0x37, 0xFF, 0xE6, 0x01, 0x38, 0xFC, 0xE6, 0x06,
+ 0x19, 0xF3, 0xEA, 0x21, 0x8A, 0x3C, 0x0E, 0xF3, 0x78, 0x05, 0x96,
+ 0xFD, 0xF1, 0x00, 0xBB, 0xFF, 0x08, 0x00, 0x01, 0x00, 0x0B, 0x00,
+ 0xD6, 0xFF, 0x41, 0x00, 0xE4, 0xFF, 0x6B, 0xFF, 0x7B, 0x02, 0xF0,
+ 0xF7, 0xBA, 0x44, 0x1E, 0x14, 0xA5, 0xF6, 0x86, 0x05, 0xC1, 0xFC,
+ 0xB9, 0x01, 0x44, 0xFF, 0x32, 0x00, 0xFF, 0xFF, 0xFE, 0xFF, 0x35,
+ 0x00, 0x39, 0xFF, 0xD8, 0x01, 0x70, 0xFC, 0x43, 0x06, 0xE1, 0xF4,
+ 0x38, 0x1A, 0x8C, 0x41, 0x55, 0xF5, 0xFC, 0x03, 0x85, 0xFE, 0x66,
+ 0x00, 0x01, 0x00, 0xEE, 0xFF, 0x06, 0x00, 0x05, 0x00, 0xF4, 0xFF,
+ 0xF2, 0xFF, 0x83, 0x00, 0x53, 0xFE, 0x4E, 0x04, 0xD0, 0xF4, 0xAB,
+ 0x40, 0xB2, 0x1B, 0x7F, 0xF4, 0x69, 0x06, 0x62, 0xFC, 0xDD, 0x01,
+ 0x38, 0xFF, 0x36, 0x00, 0xFE, 0xFF, 0xFF, 0xFF, 0x30, 0x00, 0x47,
+ 0xFF, 0xAF, 0x01, 0xD8, 0xFC, 0x52, 0x05, 0x19, 0xF7, 0xB2, 0x12,
+ 0x5C, 0x45, 0xA9, 0xF8, 0x16, 0x02, 0xA6, 0xFF, 0xC3, 0xFF, 0x51,
+ 0x00, 0xD0, 0xFF, 0x0C, 0x00, 0x00, 0x00, 0x0D, 0x00, 0xAF, 0xFF,
+ 0x09, 0x01, 0x6E, 0xFD, 0xB4, 0x05, 0xBC, 0xF2, 0x73, 0x3B, 0x64,
+ 0x23, 0xD2, 0xF2, 0xFB, 0x06, 0x34, 0xFC, 0xE6, 0x01, 0x38, 0xFF,
+ 0x36, 0x00, 0xFD, 0xFF, 0x00, 0x00, 0x29, 0x00, 0x5F, 0xFF, 0x71,
+ 0x01, 0x65, 0xFD, 0x29, 0x04, 0x96, 0xF9, 0x95, 0x0B, 0xDC, 0x47,
+ 0x03, 0xFD, 0xD9, 0xFF, 0xEA, 0x00, 0x12, 0xFF, 0xA7, 0x00, 0xAE,
+ 0xFF, 0x14, 0x00, 0xFE, 0xFF, 0x20, 0x00, 0x79, 0xFF, 0x72, 0x01,
+ 0xC4, 0xFC, 0xA4, 0x06, 0xAB, 0xF1, 0x46, 0x35, 0xF7, 0x2A, 0xC6,
+ 0xF1, 0x2A, 0x07, 0x40, 0xFC, 0xCF, 0x01, 0x47, 0xFF, 0x31, 0x00,
+ 0xFD, 0xFF, 0x00, 0x00, 0x20, 0x00, 0x7D, 0xFF, 0x24, 0x01, 0x0C,
+ 0xFE, 0xDE, 0x02, 0x2E, 0xFC, 0x13, 0x05, 0xEC, 0x48, 0x54, 0x02,
+ 0x5E, 0xFD, 0x3F, 0x02, 0x5D, 0xFE, 0xFE, 0x00, 0x8C, 0xFF, 0x1C,
+ 0x00, 0xFD, 0xFF, 0x2D, 0x00, 0x53, 0xFF, 0xBA, 0x01, 0x5B, 0xFC,
+ 0x1B, 0x07, 0x8B, 0xF1, 0x58, 0x2E, 0x26, 0x32, 0x80, 0xF1, 0xEA,
+ 0x06, 0x8C, 0xFC, 0x97, 0x01, 0x66, 0xFF, 0x27, 0x00, 0xFD, 0xFF,
+ 0x17, 0x00, 0x9E, 0xFF, 0xCF, 0x00, 0xBF, 0xFE, 0x86, 0x01, 0xBA,
+ 0xFE, 0x5A, 0xFF, 0x86, 0x48, 0x7D, 0x08, 0xC7, 0xFA, 0x93, 0x03,
+ 0xB0, 0xFD, 0x4F, 0x01, 0x6C, 0xFF, 0x25, 0x00, 0x00, 0x00, 0xFD,
+ 0xFF, 0x35, 0x00, 0x3D, 0xFF, 0xDF, 0x01, 0x32, 0xFC, 0x1E, 0x07,
+ 0x40, 0xF2, 0xEB, 0x26, 0xB5, 0x38, 0x1F, 0xF2, 0x32, 0x06, 0x18,
+ 0xFD, 0x3D, 0x01, 0x94, 0xFF, 0x16, 0x00, 0xFF, 0xFF, 0x0F, 0x00,
+ 0xC0, 0xFF, 0x78, 0x00, 0x73, 0xFF, 0x38, 0x00, 0x17, 0x01, 0x8B,
+ 0xFA, 0xAF, 0x46, 0x59, 0x0F, 0x39, 0xF8, 0xCF, 0x04, 0x15, 0xFD,
+ 0x95, 0x01, 0x51, 0xFF, 0x2D, 0x00, 0xFF, 0xFF, 0xFD, 0xFF, 0x36,
+ 0x00, 0x36, 0xFF, 0xE5, 0x01, 0x46, 0xFC, 0xB8, 0x06, 0xA8, 0xF3,
+ 0x3F, 0x1F, 0x64, 0x3E, 0xBA, 0xF3, 0x01, 0x05, 0xE2, 0xFD, 0xC4,
+ 0x00, 0xD2, 0xFF, 0x00, 0x00, 0x02, 0x00, 0x08, 0x00, 0xE1, 0xFF,
+ 0x25, 0x00, 0x1D, 0x00, 0x05, 0xFF, 0x28, 0x03, 0xBD, 0xF6, 0x77,
+ 0x43, 0xB6, 0x16, 0xDC, 0xF5, 0xDD, 0x05, 0x9B, 0xFC, 0xC8, 0x01,
+ 0x3E, 0xFF, 0x33, 0x00, 0xFF, 0xFF, 0xFE, 0xFF, 0x34, 0x00, 0x3D,
+ 0xFF, 0xCC, 0x01, 0x8F, 0xFC, 0xF8, 0x05, 0x9B, 0xF5, 0x96, 0x17,
+ 0x02, 0x43, 0x5E, 0xF6, 0x5F, 0x03, 0xE4, 0xFE, 0x30, 0x00, 0x1B,
+ 0x00, 0xE4, 0xFF, 0x08, 0x00, 0x03, 0x00, 0xFD, 0xFF, 0xD9, 0xFF,
+ 0xB4, 0x00, 0xFD, 0xFD, 0xD7, 0x04, 0xFA, 0xF3, 0xFC, 0x3E, 0x5B,
+ 0x1E, 0xDB, 0xF3, 0xA6, 0x06, 0x4C, 0xFC, 0xE3, 0x01, 0x36, 0xFF,
+ 0x36, 0x00, 0xFE, 0xFF, 0xFF, 0xFF, 0x2E, 0x00, 0x4E, 0xFF, 0x9C,
+ 0x01, 0x05, 0xFD, 0xF1, 0x04, 0xF0, 0xF7, 0x2D, 0x10, 0x61, 0x46,
+ 0x0D, 0xFA, 0x58, 0x01, 0x13, 0x00, 0x87, 0xFF, 0x6E, 0x00, 0xC4,
+ 0xFF, 0x0E, 0x00, 0xFF, 0xFF, 0x14, 0x00, 0x9B, 0xFF, 0x31, 0x01,
+ 0x2C, 0xFD, 0x15, 0x06, 0x41, 0xF2, 0x6A, 0x39, 0x0A, 0x26, 0x61,
+ 0xF2, 0x17, 0x07, 0x31, 0xFC, 0xE2, 0x01, 0x3B, 0xFF, 0x35, 0x00,
+ 0xFD, 0xFF, 0x00, 0x00, 0x26, 0x00, 0x69, 0xFF, 0x58, 0x01, 0x9D,
+ 0xFD, 0xB9, 0x03, 0x7B, 0xFA, 0x40, 0x09, 0x63, 0x48, 0xBF, 0xFE,
+ 0x03, 0xFF, 0x5F, 0x01, 0xD4, 0xFE, 0xC5, 0x00, 0xA2, 0xFF, 0x16,
+ 0x00, 0xFD, 0xFF, 0x25, 0x00, 0x6A, 0xFF, 0x8E, 0x01, 0x99, 0xFC,
+ 0xDB, 0x06, 0x86, 0xF1, 0xF2, 0x32, 0x82, 0x2D, 0x96, 0xF1, 0x21,
+ 0x07, 0x53, 0xFC, 0xC0, 0x01, 0x50, 0xFF, 0x2E, 0x00, 0xFD, 0xFF,
+ 0x1D, 0x00, 0x88, 0xFF, 0x07, 0x01, 0x49, 0xFE, 0x67, 0x02, 0x13,
+ 0xFD, 0xFF, 0x02, 0xF4, 0x48, 0x5F, 0x04, 0x7A, 0xFC, 0xB6, 0x02,
+ 0x20, 0xFE, 0x1B, 0x01, 0x81, 0xFF, 0x1F, 0x00, 0x00, 0x00, 0xFD,
+ 0xFF, 0x30, 0x00, 0x4A, 0xFF, 0xCA, 0x01, 0x46, 0xFC, 0x29, 0x07,
+ 0xB3, 0xF1, 0xD1, 0x2B, 0x81, 0x34, 0x9C, 0xF1, 0xB8, 0x06, 0xB5,
+ 0xFC, 0x7C, 0x01, 0x74, 0xFF, 0x22, 0x00, 0xFE, 0xFF, 0x15, 0x00,
+ 0xAA, 0xFF, 0xB1, 0x00, 0xFE, 0xFE, 0x10, 0x01, 0x92, 0xFF, 0x94,
+ 0xFD, 0x0D, 0x48, 0xCB, 0x0A, 0xE2, 0xF9, 0x04, 0x04, 0x77, 0xFD,
+ 0x69, 0x01, 0x62, 0xFF, 0x28, 0x00, 0x00, 0x00, 0xFD, 0xFF, 0x36,
+ 0x00, 0x39, 0xFF, 0xE5, 0x01, 0x32, 0xFC, 0x06, 0x07, 0xAA, 0xF2,
+ 0x46, 0x24, 0xC8, 0x3A, 0x90, 0xF2, 0xD6, 0x05, 0x57, 0xFD, 0x17,
+ 0x01, 0xA8, 0xFF, 0x0F, 0x00, 0x00, 0x00, 0x0D, 0x00, 0xCC, 0xFF,
+ 0x5A, 0x00, 0xAF, 0xFF, 0xCA, 0xFF, 0xD8, 0x01, 0x1C, 0xF9, 0xB8,
+ 0x45, 0xDA, 0x11, 0x60, 0xF7, 0x33, 0x05, 0xE7, 0xFC, 0xA9, 0x01,
+ 0x4A, 0xFF, 0x30, 0x00, 0xFF, 0xFF, 0xFE, 0xFF, 0x36, 0x00, 0x37,
+ 0xFF, 0xDF, 0x01, 0x5A, 0xFC, 0x7E, 0x06, 0x47, 0xF4, 0x94, 0x1C,
+ 0x1F, 0x40, 0x85, 0xF4, 0x7D, 0x04, 0x36, 0xFE, 0x93, 0x00, 0xEA,
+ 0xFF, 0xF7, 0xFF, 0x04, 0x00, 0x06, 0x00, 0xEB, 0xFF, 0x09, 0x00,
+ 0x54, 0x00, 0xA4, 0xFE, 0xC9, 0x03, 0xAA, 0xF5, 0x0C, 0x42, 0x56,
+ 0x19, 0x1E, 0xF5, 0x2B, 0x06, 0x7A, 0xFC, 0xD4, 0x01, 0x3A, 0xFF,
+ 0x35, 0x00, 0xFE, 0xFF, 0xFF, 0xFF, 0x32, 0x00, 0x42, 0xFF, 0xBE,
+ 0x01, 0xB4, 0xFC, 0xA4, 0x05, 0x61, 0xF6, 0xFB, 0x14, 0x53, 0x44,
+ 0x86, 0xF7, 0xB6, 0x02, 0x49, 0xFF, 0xF7, 0xFF, 0x37, 0x00, 0xD9,
+ 0xFF, 0x0A, 0x00, 0x01, 0x00, 0x06, 0x00, 0xC2, 0xFF, 0xE3, 0x00,
+ 0xAE, 0xFD, 0x52, 0x05, 0x44, 0xF3, 0x2A, 0x3D, 0x06, 0x21, 0x47,
+ 0xF3, 0xD8, 0x06, 0x3C, 0xFC, 0xE6, 0x01, 0x36, 0xFF, 0x36, 0x00,
+ 0xFD, 0xFF, 0x00, 0x00, 0x2B, 0x00, 0x57, 0xFF, 0x86, 0x01, 0x36,
+ 0xFD, 0x89, 0x04, 0xCD, 0xF8, 0xB7, 0x0D, 0x3D, 0x47, 0x91, 0xFB,
+ 0x91, 0x00, 0x83, 0x00, 0x4A, 0xFF, 0x8C, 0x00, 0xB9, 0xFF, 0x11,
+ 0x00, 0xFE, 0xFF, 0x1B, 0x00, 0x88, 0xFF, 0x55, 0x01, 0xF2, 0xFC,
+ 0x67, 0x06, 0xE4, 0xF1, 0x44, 0x37, 0xAA, 0x28, 0x05, 0xF2, 0x27,
+ 0x07, 0x36, 0xFC, 0xDA, 0x01, 0x41, 0xFF, 0x33, 0x00, 0xFD, 0xFF,
+ 0x00, 0x00, 0x23, 0x00, 0x73, 0xFF, 0x3D, 0x01, 0xD6, 0xFD, 0x46,
+ 0x03, 0x61, 0xFB, 0x00, 0x07, 0xBF, 0x48, 0x98, 0x00, 0x26, 0xFE,
+ 0xD5, 0x01, 0x95, 0xFE, 0xE3, 0x00, 0x96, 0xFF, 0x1A, 0x00, 0xFD,
+ 0xFF, 0x2A, 0x00, 0x5D, 0xFF, 0xA7, 0x01, 0x75, 0xFC, 0x03, 0x07,
+ 0x7D, 0xF1, 0x8A, 0x30, 0xFF, 0x2F, 0x7E, 0xF1, 0x0A, 0x07, 0x6E,
+ 0xFC, 0xAC, 0x01, 0x5A, 0xFF, 0x2B, 0x00, 0xFD, 0xFF, 0x1A, 0x00,
+ 0x94, 0xFF, 0xEA, 0x00, 0x87, 0xFE, 0xF0, 0x01, 0xF5, 0xFD, 0x05,
+ 0x01, 0xCE, 0x48, 0x83, 0x06, 0x94, 0xFB, 0x2C, 0x03, 0xE4, 0xFD,
+ 0x37, 0x01, 0x76, 0xFF, 0x22, 0x00, 0x00, 0x00, 0xFD, 0xFF, 0x33,
+ 0x00, 0x42, 0xFF, 0xD7, 0x01, 0x38, 0xFC, 0x29, 0x07, 0xF3, 0xF1,
+ 0x3E, 0x29, 0xC6, 0x36, 0xD4, 0xF1, 0x77, 0x06, 0xE6, 0xFC, 0x5C,
+ 0x01, 0x84, 0xFF, 0x1C, 0x00, 0xFE, 0xFF, 0x12, 0x00, 0xB6, 0xFF,
+ 0x93, 0x00, 0x3C, 0xFF, 0x9D, 0x00, 0x63, 0x00, 0xEB, 0xFB, 0x69,
+ 0x47, 0x2D, 0x0D, 0xFF, 0xF8, 0x72, 0x04, 0x42, 0xFD, 0x81, 0x01,
+ 0x59, 0xFF, 0x2B, 0x00, 0x00, 0x00, 0xFD, 0xFF, 0x36, 0x00, 0x37,
+ 0xFF, 0xE6, 0x01, 0x3A, 0xFC, 0xE2, 0x06, 0x28, 0xF3, 0x9E, 0x21,
+ 0xC0, 0x3C, 0x1F, 0xF3, 0x6C, 0x05, 0x9E, 0xFD, 0xED, 0x00, 0xBD,
+ 0xFF, 0x07, 0x00, 0x01, 0x00, 0x0A, 0x00, 0xD7, 0xFF, 0x3E, 0x00,
+ 0xEA, 0xFF, 0x60, 0xFF, 0x8F, 0x02, 0xCD, 0xF7, 0x99, 0x44, 0x68,
+ 0x14, 0x8E, 0xF6, 0x90, 0x05, 0xBC, 0xFC, 0xBA, 0x01, 0x43, 0xFF,
+ 0x32, 0x00, 0xFF, 0xFF, 0xFE, 0xFF, 0x35, 0x00, 0x39, 0xFF, 0xD7,
+ 0x01, 0x73, 0xFC, 0x3B, 0x06, 0xF5, 0xF4, 0xED, 0x19, 0xB7, 0x41,
+ 0x71, 0xF5, 0xEB, 0x03, 0x90, 0xFE, 0x60, 0x00, 0x04, 0x00, 0xED,
+ 0xFF, 0x06, 0x00, 0x04, 0x00, 0xF5, 0xFF, 0xEF, 0xFF, 0x88, 0x00,
+ 0x49, 0xFE, 0x5D, 0x04, 0xB7, 0xF4, 0x7D, 0x40, 0xFD, 0x1B, 0x6C,
+ 0xF4, 0x70, 0x06, 0x5F, 0xFC, 0xDE, 0x01, 0x37, 0xFF, 0x36, 0x00,
+ 0xFE, 0xFF, 0xFF, 0xFF, 0x30, 0x00, 0x48, 0xFF, 0xAD, 0x01, 0xDD,
+ 0xFC, 0x48, 0x05, 0x30, 0xF7, 0x6B, 0x12, 0x7D, 0x45, 0xCF, 0xF8,
+ 0x01, 0x02, 0xB2, 0xFF, 0xBD, 0xFF, 0x54, 0x00, 0xCE, 0xFF, 0x0C,
+ 0x00, 0x00, 0x00, 0x0E, 0x00, 0xAC, 0xFF, 0x0E, 0x01, 0x66, 0xFD,
+ 0xBF, 0x05, 0xAD, 0xF2, 0x3B, 0x3B, 0xB0, 0x23, 0xC4, 0xF2, 0xFF,
+ 0x06, 0x33, 0xFC, 0xE5, 0x01, 0x38, 0xFF, 0x36, 0x00, 0xFD, 0xFF,
+ 0x00, 0x00, 0x29, 0x00, 0x60, 0xFF, 0x6E, 0x01, 0x6B, 0xFD, 0x1D,
+ 0x04, 0xAF, 0xF9, 0x51, 0x0B, 0xEC, 0x47, 0x33, 0xFD, 0xC1, 0xFF,
+ 0xF7, 0x00, 0x0C, 0xFF, 0xAA, 0x00, 0xAD, 0xFF, 0x14, 0x00, 0xFE,
+ 0xFF, 0x21, 0x00, 0x77, 0xFF, 0x75, 0x01, 0xBF, 0xFC, 0xAB, 0x06,
+ 0xA6, 0xF1, 0x05, 0x35, 0x40, 0x2B, 0xBF, 0xF1, 0x2A, 0x07, 0x42,
+ 0xFC, 0xCE, 0x01, 0x48, 0xFF, 0x31, 0x00, 0xFD, 0xFF, 0x00, 0x00,
+ 0x20, 0x00, 0x7E, 0xFF, 0x21, 0x01, 0x12, 0xFE, 0xD1, 0x02, 0x47,
+ 0xFC, 0xD7, 0x04, 0xF0, 0x48, 0x8D, 0x02, 0x45, 0xFD, 0x4D, 0x02,
+ 0x56, 0xFE, 0x01, 0x01, 0x8B, 0xFF, 0x1D, 0x00, 0xFD, 0xFF, 0x2E,
+ 0x00, 0x52, 0xFF, 0xBC, 0x01, 0x58, 0xFC, 0x1D, 0x07, 0x8E, 0xF1,
+ 0x11, 0x2E, 0x6B, 0x32, 0x81, 0xF1, 0xE5, 0x06, 0x90, 0xFC, 0x94,
+ 0x01, 0x67, 0xFF, 0x26, 0x00, 0xFD, 0xFF, 0x17, 0x00, 0xA0, 0xFF,
+ 0xCC, 0x00, 0xC6, 0xFE, 0x79, 0x01, 0xD2, 0xFE, 0x26, 0xFF, 0x7C,
+ 0x48, 0xBE, 0x08, 0xAE, 0xFA, 0xA0, 0x03, 0xA9, 0xFD, 0x52, 0x01,
+ 0x6B, 0xFF, 0x25, 0x00, 0x00, 0x00, 0xFD, 0xFF, 0x35, 0x00, 0x3C,
+ 0xFF, 0xE0, 0x01, 0x32, 0xFC, 0x1C, 0x07, 0x4B, 0xF2, 0xA0, 0x26,
+ 0xF2, 0x38, 0x2A, 0xF2, 0x28, 0x06, 0x1F, 0xFD, 0x39, 0x01, 0x96,
+ 0xFF, 0x16, 0x00, 0xFF, 0xFF, 0x0F, 0x00, 0xC2, 0xFF, 0x75, 0x00,
+ 0x7A, 0xFF, 0x2B, 0x00, 0x2D, 0x01, 0x61, 0xFA, 0x97, 0x46, 0xA0,
+ 0x0F, 0x20, 0xF8, 0xDA, 0x04, 0x10, 0xFD, 0x97, 0x01, 0x50, 0xFF,
+ 0x2E, 0x00, 0xFF, 0xFF, 0xFE, 0xFF, 0x36, 0x00, 0x36, 0xFF, 0xE4,
+ 0x01, 0x48, 0xFC, 0xB2, 0x06, 0xB9, 0xF3, 0xF3, 0x1E, 0x98, 0x3E,
+ 0xCF, 0xF3, 0xF3, 0x04, 0xEB, 0xFD, 0xBF, 0x00, 0xD4, 0xFF, 0xFF,
+ 0xFF, 0x03, 0x00, 0x08, 0x00, 0xE2, 0xFF, 0x21, 0x00, 0x23, 0x00,
+ 0xFA, 0xFE, 0x3A, 0x03, 0x9D, 0xF6, 0x50, 0x43, 0x00, 0x17, 0xC6,
+ 0xF5, 0xE6, 0x05, 0x97, 0xFC, 0xC9, 0x01, 0x3E, 0xFF, 0x34, 0x00,
+ 0xFE, 0xFF, 0xFE, 0xFF, 0x34, 0x00, 0x3D, 0xFF, 0xCB, 0x01, 0x93,
+ 0xFC, 0xEF, 0x05, 0xB0, 0xF5, 0x4B, 0x17, 0x2A, 0x43, 0x7D, 0xF6,
+ 0x4D, 0x03, 0xEF, 0xFE, 0x2A, 0x00, 0x1E, 0x00, 0xE3, 0xFF, 0x08,
+ 0x00, 0x03, 0x00, 0xFE, 0xFF, 0xD7, 0xFF, 0xBA, 0x00, 0xF4, 0xFD,
+ 0xE5, 0x04, 0xE4, 0xF3, 0xCA, 0x3E, 0xA7, 0x1E, 0xCA, 0xF3, 0xAC,
+ 0x06, 0x4A, 0xFC, 0xE4, 0x01, 0x36, 0xFF, 0x36, 0x00, 0xFE, 0xFF,
+ 0xFF, 0xFF, 0x2E, 0x00, 0x4F, 0xFF, 0x99, 0x01, 0x0B, 0xFD, 0xE6,
+ 0x04, 0x08, 0xF8, 0xE7, 0x0F, 0x7C, 0x46, 0x37, 0xFA, 0x42, 0x01,
+ 0x1F, 0x00, 0x81, 0xFF, 0x71, 0x00, 0xC3, 0xFF, 0x0F, 0x00, 0xFF,
+ 0xFF, 0x15, 0x00, 0x98, 0xFF, 0x35, 0x01, 0x25, 0xFD, 0x1E, 0x06,
+ 0x35, 0xF2, 0x2E, 0x39, 0x55, 0x26, 0x56, 0xF2, 0x1A, 0x07, 0x31,
+ 0xFC, 0xE1, 0x01, 0x3C, 0xFF, 0x35, 0x00, 0xFD, 0xFF, 0x00, 0x00,
+ 0x26, 0x00, 0x6A, 0xFF, 0x55, 0x01, 0xA3, 0xFD, 0xAD, 0x03, 0x94,
+ 0xFA, 0xFF, 0x08, 0x70, 0x48, 0xF3, 0xFE, 0xEA, 0xFE, 0x6C, 0x01,
+ 0xCD, 0xFE, 0xC9, 0x00, 0xA1, 0xFF, 0x17, 0x00, 0xFD, 0xFF, 0x26,
+ 0x00, 0x69, 0xFF, 0x91, 0x01, 0x94, 0xFC, 0xE0, 0x06, 0x84, 0xF1,
+ 0xAF, 0x32, 0xCA, 0x2D, 0x92, 0xF1, 0x1F, 0x07, 0x56, 0xFC, 0xBE,
+ 0x01, 0x51, 0xFF, 0x2E, 0x00, 0xFD, 0xFF, 0x1D, 0x00, 0x8A, 0xFF,
+ 0x04, 0x01, 0x50, 0xFE, 0x5A, 0x02, 0x2C, 0xFD, 0xC6, 0x02, 0xF2,
+ 0x48, 0x9B, 0x04, 0x61, 0xFC, 0xC3, 0x02, 0x19, 0xFE, 0x1E, 0x01,
+ 0x7F, 0xFF, 0x20, 0x00, 0x00, 0x00, 0xFD, 0xFF, 0x31, 0x00, 0x49,
+ 0xFF, 0xCC, 0x01, 0x44, 0xFC, 0x29, 0x07, 0xB9, 0xF1, 0x89, 0x2B,
+ 0xC3, 0x34, 0xA0, 0xF1, 0xB1, 0x06, 0xBA, 0xFC, 0x79, 0x01, 0x76,
+ 0xFF, 0x21, 0x00, 0xFE, 0xFF, 0x14, 0x00, 0xAC, 0xFF, 0xAE, 0x00,
+ 0x05, 0xFF, 0x03, 0x01, 0xAA, 0xFF, 0x63, 0xFD, 0xFD, 0x47, 0x0E,
+ 0x0B, 0xC8, 0xF9, 0x11, 0x04, 0x71, 0xFD, 0x6C, 0x01, 0x61, 0xFF,
+ 0x28, 0x00, 0x00, 0x00, 0xFD, 0xFF, 0x36, 0x00, 0x39, 0xFF, 0xE5,
+ 0x01, 0x33, 0xFC, 0x03, 0x07, 0xB7, 0xF2, 0xFC, 0x23, 0x03, 0x3B,
+ 0x9E, 0xF2, 0xCB, 0x05, 0x5F, 0xFD, 0x12, 0x01, 0xAA, 0xFF, 0x0E,
+ 0x00, 0x00, 0x00, 0x0C, 0x00, 0xCD, 0xFF, 0x57, 0x00, 0xB6, 0xFF,
+ 0xBE, 0xFF, 0xED, 0x01, 0xF5, 0xF8, 0x9B, 0x45, 0x22, 0x12, 0x48,
+ 0xF7, 0x3D, 0x05, 0xE2, 0xFC, 0xAB, 0x01, 0x49, 0xFF, 0x30, 0x00,
+ 0xFF, 0xFF, 0xFE, 0xFF, 0x36, 0x00, 0x37, 0xFF, 0xDF, 0x01, 0x5C,
+ 0xFC, 0x78, 0x06, 0x5A, 0xF4, 0x49, 0x1C, 0x4E, 0x40, 0x9E, 0xF4,
+ 0x6D, 0x04, 0x3F, 0xFE, 0x8E, 0x00, 0xED, 0xFF, 0xF6, 0xFF, 0x04,
+ 0x00, 0x06, 0x00, 0xEC, 0xFF, 0x06, 0x00, 0x5A, 0x00, 0x9A, 0xFE,
+ 0xDA, 0x03, 0x8D, 0xF5, 0xE1, 0x41, 0xA1, 0x19, 0x09, 0xF5, 0x33,
+ 0x06, 0x77, 0xFC, 0xD6, 0x01, 0x3A, 0xFF, 0x35, 0x00, 0xFE, 0xFF,
+ 0xFF, 0xFF, 0x32, 0x00, 0x42, 0xFF, 0xBC, 0x01, 0xB8, 0xFC, 0x9A,
+ 0x05, 0x77, 0xF6, 0xB1, 0x14, 0x77, 0x44, 0xA9, 0xF7, 0xA2, 0x02,
+ 0x54, 0xFF, 0xF1, 0xFF, 0x3A, 0x00, 0xD8, 0xFF, 0x0A, 0x00, 0x01,
+ 0x00, 0x07, 0x00, 0xC0, 0xFF, 0xE8, 0x00, 0xA6, 0xFD, 0x5F, 0x05,
+ 0x31, 0xF3, 0xF6, 0x3C, 0x52, 0x21, 0x37, 0xF3, 0xDD, 0x06, 0x3B,
+ 0xFC, 0xE6, 0x01, 0x36, 0xFF, 0x36, 0x00, 0xFD, 0xFF, 0x00, 0x00,
+ 0x2B, 0x00, 0x58, 0xFF, 0x83, 0x01, 0x3C, 0xFD, 0x7E, 0x04, 0xE6,
+ 0xF8, 0x72, 0x0D, 0x52, 0x47, 0xBE, 0xFB, 0x7A, 0x00, 0x90, 0x00,
+ 0x43, 0xFF, 0x8F, 0x00, 0xB7, 0xFF, 0x11, 0x00, 0xFE, 0xFF, 0x1C,
+ 0x00, 0x86, 0xFF, 0x59, 0x01, 0xEC, 0xFC, 0x6F, 0x06, 0xDC, 0xF1,
+ 0x04, 0x37, 0xF3, 0x28, 0xFC, 0xF1, 0x28, 0x07, 0x37, 0xFC, 0xD8,
+ 0x01, 0x41, 0xFF, 0x33, 0x00, 0xFD, 0xFF, 0x00, 0x00, 0x23, 0x00,
+ 0x74, 0xFF, 0x3A, 0x01, 0xDD, 0xFD, 0x39, 0x03, 0x7B, 0xFB, 0xC1,
+ 0x06, 0xC7, 0x48, 0xCF, 0x00, 0x0D, 0xFE, 0xE3, 0x01, 0x8E, 0xFE,
+ 0xE7, 0x00, 0x95, 0xFF, 0x1A, 0x00, 0xFD, 0xFF, 0x2A, 0x00, 0x5C,
+ 0xFF, 0xAA, 0x01, 0x71, 0xFC, 0x07, 0x07, 0x7E, 0xF1, 0x44, 0x30,
+ 0x44, 0x30, 0x7E, 0xF1, 0x07, 0x07, 0x71, 0xFC, 0xAA, 0x01, 0x5C,
+ 0xFF, 0x2A, 0x00, 0xFD, 0xFF, 0x1A, 0x00, 0x95, 0xFF, 0xE7, 0x00,
+ 0x8E, 0xFE, 0xE3, 0x01, 0x0D, 0xFE, 0xCF, 0x00, 0xC7, 0x48, 0xC1,
+ 0x06, 0x7B, 0xFB, 0x39, 0x03, 0xDD, 0xFD, 0x3A, 0x01, 0x74, 0xFF,
+ 0x23, 0x00, 0x00, 0x00, 0xFD, 0xFF, 0x33, 0x00, 0x41, 0xFF, 0xD8,
+ 0x01, 0x37, 0xFC, 0x28, 0x07, 0xFC, 0xF1, 0xF3, 0x28, 0x04, 0x37,
+ 0xDC, 0xF1, 0x6F, 0x06, 0xEC, 0xFC, 0x59, 0x01, 0x86, 0xFF, 0x1C,
+ 0x00, 0xFE, 0xFF, 0x11, 0x00, 0xB7, 0xFF, 0x8F, 0x00, 0x43, 0xFF,
+ 0x90, 0x00, 0x7A, 0x00, 0xBE, 0xFB, 0x52, 0x47, 0x72, 0x0D, 0xE6,
+ 0xF8, 0x7E, 0x04, 0x3C, 0xFD, 0x83, 0x01, 0x58, 0xFF, 0x2B, 0x00,
+ 0x00, 0x00, 0xFD, 0xFF, 0x36, 0x00, 0x36, 0xFF, 0xE6, 0x01, 0x3B,
+ 0xFC, 0xDD, 0x06, 0x37, 0xF3, 0x52, 0x21, 0xF6, 0x3C, 0x31, 0xF3,
+ 0x5F, 0x05, 0xA6, 0xFD, 0xE8, 0x00, 0xC0, 0xFF, 0x07, 0x00, 0x01,
+ 0x00, 0x0A, 0x00, 0xD8, 0xFF, 0x3A, 0x00, 0xF1, 0xFF, 0x54, 0xFF,
+ 0xA2, 0x02, 0xA9, 0xF7, 0x77, 0x44, 0xB1, 0x14, 0x77, 0xF6, 0x9A,
+ 0x05, 0xB8, 0xFC, 0xBC, 0x01, 0x42, 0xFF, 0x32, 0x00, 0xFF, 0xFF,
+ 0xFE, 0xFF, 0x35, 0x00, 0x3A, 0xFF, 0xD6, 0x01, 0x77, 0xFC, 0x33,
+ 0x06, 0x09, 0xF5, 0xA1, 0x19, 0xE1, 0x41, 0x8D, 0xF5, 0xDA, 0x03,
+ 0x9A, 0xFE, 0x5A, 0x00, 0x06, 0x00, 0xEC, 0xFF, 0x06, 0x00, 0x04,
+ 0x00, 0xF6, 0xFF, 0xED, 0xFF, 0x8E, 0x00, 0x3F, 0xFE, 0x6D, 0x04,
+ 0x9E, 0xF4, 0x4E, 0x40, 0x49, 0x1C, 0x5A, 0xF4, 0x78, 0x06, 0x5C,
+ 0xFC, 0xDF, 0x01, 0x37, 0xFF, 0x36, 0x00, 0xFE, 0xFF, 0xFF, 0xFF,
+ 0x30, 0x00, 0x49, 0xFF, 0xAB, 0x01, 0xE2, 0xFC, 0x3D, 0x05, 0x48,
+ 0xF7, 0x22, 0x12, 0x9B, 0x45, 0xF5, 0xF8, 0xED, 0x01, 0xBE, 0xFF,
+ 0xB6, 0xFF, 0x57, 0x00, 0xCD, 0xFF, 0x0C, 0x00, 0x00, 0x00, 0x0E,
+ 0x00, 0xAA, 0xFF, 0x12, 0x01, 0x5F, 0xFD, 0xCB, 0x05, 0x9E, 0xF2,
+ 0x03, 0x3B, 0xFC, 0x23, 0xB7, 0xF2, 0x03, 0x07, 0x33, 0xFC, 0xE5,
+ 0x01, 0x39, 0xFF, 0x36, 0x00, 0xFD, 0xFF, 0x00, 0x00, 0x28, 0x00,
+ 0x61, 0xFF, 0x6C, 0x01, 0x71, 0xFD, 0x11, 0x04, 0xC8, 0xF9, 0x0E,
+ 0x0B, 0xFD, 0x47, 0x63, 0xFD, 0xAA, 0xFF, 0x03, 0x01, 0x05, 0xFF,
+ 0xAE, 0x00, 0xAC, 0xFF, 0x14, 0x00, 0xFE, 0xFF, 0x21, 0x00, 0x76,
+ 0xFF, 0x79, 0x01, 0xBA, 0xFC, 0xB1, 0x06, 0xA0, 0xF1, 0xC3, 0x34,
+ 0x89, 0x2B, 0xB9, 0xF1, 0x29, 0x07, 0x44, 0xFC, 0xCC, 0x01, 0x49,
+ 0xFF, 0x31, 0x00, 0xFD, 0xFF, 0x00, 0x00, 0x20, 0x00, 0x7F, 0xFF,
+ 0x1E, 0x01, 0x19, 0xFE, 0xC3, 0x02, 0x61, 0xFC, 0x9B, 0x04, 0xF2,
+ 0x48, 0xC6, 0x02, 0x2C, 0xFD, 0x5A, 0x02, 0x50, 0xFE, 0x04, 0x01,
+ 0x8A, 0xFF, 0x1D, 0x00, 0xFD, 0xFF, 0x2E, 0x00, 0x51, 0xFF, 0xBE,
+ 0x01, 0x56, 0xFC, 0x1F, 0x07, 0x92, 0xF1, 0xCA, 0x2D, 0xAF, 0x32,
+ 0x84, 0xF1, 0xE0, 0x06, 0x94, 0xFC, 0x91, 0x01, 0x69, 0xFF, 0x26,
+ 0x00, 0xFD, 0xFF, 0x17, 0x00, 0xA1, 0xFF, 0xC9, 0x00, 0xCD, 0xFE,
+ 0x6C, 0x01, 0xEA, 0xFE, 0xF3, 0xFE, 0x70, 0x48, 0xFF, 0x08, 0x94,
+ 0xFA, 0xAD, 0x03, 0xA3, 0xFD, 0x55, 0x01, 0x6A, 0xFF, 0x26, 0x00,
+ 0x00, 0x00, 0xFD, 0xFF, 0x35, 0x00, 0x3C, 0xFF, 0xE1, 0x01, 0x31,
+ 0xFC, 0x1A, 0x07, 0x56, 0xF2, 0x55, 0x26, 0x2E, 0x39, 0x35, 0xF2,
+ 0x1E, 0x06, 0x25, 0xFD, 0x35, 0x01, 0x98, 0xFF, 0x15, 0x00, 0xFF,
+ 0xFF, 0x0F, 0x00, 0xC3, 0xFF, 0x71, 0x00, 0x81, 0xFF, 0x1F, 0x00,
+ 0x42, 0x01, 0x37, 0xFA, 0x7C, 0x46, 0xE7, 0x0F, 0x08, 0xF8, 0xE6,
+ 0x04, 0x0B, 0xFD, 0x99, 0x01, 0x4F, 0xFF, 0x2E, 0x00, 0xFF, 0xFF,
+ 0xFE, 0xFF, 0x36, 0x00, 0x36, 0xFF, 0xE4, 0x01, 0x4A, 0xFC, 0xAC,
+ 0x06, 0xCA, 0xF3, 0xA7, 0x1E, 0xCA, 0x3E, 0xE4, 0xF3, 0xE5, 0x04,
+ 0xF4, 0xFD, 0xBA, 0x00, 0xD7, 0xFF, 0xFE, 0xFF, 0x03, 0x00, 0x08,
+ 0x00, 0xE3, 0xFF, 0x1E, 0x00, 0x2A, 0x00, 0xEF, 0xFE, 0x4D, 0x03,
+ 0x7D, 0xF6, 0x2A, 0x43, 0x4B, 0x17, 0xB0, 0xF5, 0xEF, 0x05, 0x93,
+ 0xFC, 0xCB, 0x01, 0x3D, 0xFF, 0x34, 0x00, 0xFE, 0xFF, 0xFE, 0xFF,
+ 0x34, 0x00, 0x3E, 0xFF, 0xC9, 0x01, 0x97, 0xFC, 0xE6, 0x05, 0xC6,
+ 0xF5, 0x00, 0x17, 0x50, 0x43, 0x9D, 0xF6, 0x3A, 0x03, 0xFA, 0xFE,
+ 0x23, 0x00, 0x21, 0x00, 0xE2, 0xFF, 0x08, 0x00, 0x03, 0x00, 0xFF,
+ 0xFF, 0xD4, 0xFF, 0xBF, 0x00, 0xEB, 0xFD, 0xF3, 0x04, 0xCF, 0xF3,
+ 0x98, 0x3E, 0xF3, 0x1E, 0xB9, 0xF3, 0xB2, 0x06, 0x48, 0xFC, 0xE4,
+ 0x01, 0x36, 0xFF, 0x36, 0x00, 0xFE, 0xFF, 0xFF, 0xFF, 0x2E, 0x00,
+ 0x50, 0xFF, 0x97, 0x01, 0x10, 0xFD, 0xDA, 0x04, 0x20, 0xF8, 0xA0,
+ 0x0F, 0x97, 0x46, 0x61, 0xFA, 0x2D, 0x01, 0x2B, 0x00, 0x7A, 0xFF,
+ 0x75, 0x00, 0xC2, 0xFF, 0x0F, 0x00, 0xFF, 0xFF, 0x16, 0x00, 0x96,
+ 0xFF, 0x39, 0x01, 0x1F, 0xFD, 0x28, 0x06, 0x2A, 0xF2, 0xF2, 0x38,
+ 0xA0, 0x26, 0x4B, 0xF2, 0x1C, 0x07, 0x32, 0xFC, 0xE0, 0x01, 0x3C,
+ 0xFF, 0x35, 0x00, 0xFD, 0xFF, 0x00, 0x00, 0x25, 0x00, 0x6B, 0xFF,
+ 0x52, 0x01, 0xA9, 0xFD, 0xA0, 0x03, 0xAE, 0xFA, 0xBE, 0x08, 0x7C,
+ 0x48, 0x26, 0xFF, 0xD2, 0xFE, 0x79, 0x01, 0xC6, 0xFE, 0xCC, 0x00,
+ 0xA0, 0xFF, 0x17, 0x00, 0xFD, 0xFF, 0x26, 0x00, 0x67, 0xFF, 0x94,
+ 0x01, 0x90, 0xFC, 0xE5, 0x06, 0x81, 0xF1, 0x6B, 0x32, 0x11, 0x2E,
+ 0x8E, 0xF1, 0x1D, 0x07, 0x58, 0xFC, 0xBC, 0x01, 0x52, 0xFF, 0x2E,
+ 0x00, 0xFD, 0xFF, 0x1D, 0x00, 0x8B, 0xFF, 0x01, 0x01, 0x56, 0xFE,
+ 0x4D, 0x02, 0x45, 0xFD, 0x8D, 0x02, 0xF0, 0x48, 0xD7, 0x04, 0x47,
+ 0xFC, 0xD1, 0x02, 0x12, 0xFE, 0x21, 0x01, 0x7E, 0xFF, 0x20, 0x00,
+ 0x00, 0x00, 0xFD, 0xFF, 0x31, 0x00, 0x48, 0xFF, 0xCE, 0x01, 0x42,
+ 0xFC, 0x2A, 0x07, 0xBF, 0xF1, 0x40, 0x2B, 0x05, 0x35, 0xA6, 0xF1,
+ 0xAB, 0x06, 0xBF, 0xFC, 0x75, 0x01, 0x77, 0xFF, 0x21, 0x00, 0xFE,
+ 0xFF, 0x14, 0x00, 0xAD, 0xFF, 0xAA, 0x00, 0x0C, 0xFF, 0xF7, 0x00,
+ 0xC1, 0xFF, 0x33, 0xFD, 0xEC, 0x47, 0x51, 0x0B, 0xAF, 0xF9, 0x1D,
+ 0x04, 0x6B, 0xFD, 0x6E, 0x01, 0x60, 0xFF, 0x29, 0x00, 0x00, 0x00,
+ 0xFD, 0xFF, 0x36, 0x00, 0x38, 0xFF, 0xE5, 0x01, 0x33, 0xFC, 0xFF,
+ 0x06, 0xC4, 0xF2, 0xB0, 0x23, 0x3B, 0x3B, 0xAD, 0xF2, 0xBF, 0x05,
+ 0x66, 0xFD, 0x0E, 0x01, 0xAC, 0xFF, 0x0E, 0x00, 0x00, 0x00, 0x0C,
+ 0x00, 0xCE, 0xFF, 0x54, 0x00, 0xBD, 0xFF, 0xB2, 0xFF, 0x01, 0x02,
+ 0xCF, 0xF8, 0x7D, 0x45, 0x6B, 0x12, 0x30, 0xF7, 0x48, 0x05, 0xDD,
+ 0xFC, 0xAD, 0x01, 0x48, 0xFF, 0x30, 0x00, 0xFF, 0xFF, 0xFE, 0xFF,
+ 0x36, 0x00, 0x37, 0xFF, 0xDE, 0x01, 0x5F, 0xFC, 0x70, 0x06, 0x6C,
+ 0xF4, 0xFD, 0x1B, 0x7D, 0x40, 0xB7, 0xF4, 0x5D, 0x04, 0x49, 0xFE,
+ 0x88, 0x00, 0xEF, 0xFF, 0xF5, 0xFF, 0x04, 0x00, 0x06, 0x00, 0xED,
+ 0xFF, 0x04, 0x00, 0x60, 0x00, 0x90, 0xFE, 0xEB, 0x03, 0x71, 0xF5,
+ 0xB7, 0x41, 0xED, 0x19, 0xF5, 0xF4, 0x3B, 0x06, 0x73, 0xFC, 0xD7,
+ 0x01, 0x39, 0xFF, 0x35, 0x00, 0xFE, 0xFF, 0xFF, 0xFF, 0x32, 0x00,
+ 0x43, 0xFF, 0xBA, 0x01, 0xBC, 0xFC, 0x90, 0x05, 0x8E, 0xF6, 0x68,
+ 0x14, 0x99, 0x44, 0xCD, 0xF7, 0x8F, 0x02, 0x60, 0xFF, 0xEA, 0xFF,
+ 0x3E, 0x00, 0xD7, 0xFF, 0x0A, 0x00, 0x01, 0x00, 0x07, 0x00, 0xBD,
+ 0xFF, 0xED, 0x00, 0x9E, 0xFD, 0x6C, 0x05, 0x1F, 0xF3, 0xC0, 0x3C,
+ 0x9E, 0x21, 0x28, 0xF3, 0xE2, 0x06, 0x3A, 0xFC, 0xE6, 0x01, 0x37,
+ 0xFF, 0x36, 0x00, 0xFD, 0xFF, 0x00, 0x00, 0x2B, 0x00, 0x59, 0xFF,
+ 0x81, 0x01, 0x42, 0xFD, 0x72, 0x04, 0xFF, 0xF8, 0x2D, 0x0D, 0x69,
+ 0x47, 0xEB, 0xFB, 0x63, 0x00, 0x9D, 0x00, 0x3C, 0xFF, 0x93, 0x00,
+ 0xB6, 0xFF, 0x12, 0x00, 0xFE, 0xFF, 0x1C, 0x00, 0x84, 0xFF, 0x5C,
+ 0x01, 0xE6, 0xFC, 0x77, 0x06, 0xD4, 0xF1, 0xC6, 0x36, 0x3E, 0x29,
+ 0xF3, 0xF1, 0x29, 0x07, 0x38, 0xFC, 0xD7, 0x01, 0x42, 0xFF, 0x33,
+ 0x00, 0xFD, 0xFF, 0x00, 0x00, 0x22, 0x00, 0x76, 0xFF, 0x37, 0x01,
+ 0xE4, 0xFD, 0x2C, 0x03, 0x94, 0xFB, 0x83, 0x06, 0xCE, 0x48, 0x05,
+ 0x01, 0xF5, 0xFD, 0xF0, 0x01, 0x87, 0xFE, 0xEA, 0x00, 0x94, 0xFF,
+ 0x1A, 0x00, 0xFD, 0xFF, 0x2B, 0x00, 0x5A, 0xFF, 0xAC, 0x01, 0x6E,
+ 0xFC, 0x0A, 0x07, 0x7E, 0xF1, 0xFF, 0x2F, 0x8A, 0x30, 0x7D, 0xF1,
+ 0x03, 0x07, 0x75, 0xFC, 0xA7, 0x01, 0x5D, 0xFF, 0x2A, 0x00, 0xFD,
+ 0xFF, 0x1A, 0x00, 0x96, 0xFF, 0xE3, 0x00, 0x95, 0xFE, 0xD5, 0x01,
+ 0x26, 0xFE, 0x98, 0x00, 0xBF, 0x48, 0x00, 0x07, 0x61, 0xFB, 0x46,
+ 0x03, 0xD6, 0xFD, 0x3D, 0x01, 0x73, 0xFF, 0x23, 0x00, 0x00, 0x00,
+ 0xFD, 0xFF, 0x33, 0x00, 0x41, 0xFF, 0xDA, 0x01, 0x36, 0xFC, 0x27,
+ 0x07, 0x05, 0xF2, 0xAA, 0x28, 0x44, 0x37, 0xE4, 0xF1, 0x67, 0x06,
+ 0xF2, 0xFC, 0x55, 0x01, 0x88, 0xFF, 0x1B, 0x00, 0xFE, 0xFF, 0x11,
+ 0x00, 0xB9, 0xFF, 0x8C, 0x00, 0x4A, 0xFF, 0x83, 0x00, 0x91, 0x00,
+ 0x91, 0xFB, 0x3D, 0x47, 0xB7, 0x0D, 0xCD, 0xF8, 0x89, 0x04, 0x36,
+ 0xFD, 0x86, 0x01, 0x57, 0xFF, 0x2B, 0x00, 0x00, 0x00, 0xFD, 0xFF,
+ 0x36, 0x00, 0x36, 0xFF, 0xE6, 0x01, 0x3C, 0xFC, 0xD8, 0x06, 0x47,
+ 0xF3, 0x06, 0x21, 0x2A, 0x3D, 0x44, 0xF3, 0x52, 0x05, 0xAE, 0xFD,
+ 0xE3, 0x00, 0xC2, 0xFF, 0x06, 0x00, 0x01, 0x00, 0x0A, 0x00, 0xD9,
+ 0xFF, 0x37, 0x00, 0xF7, 0xFF, 0x49, 0xFF, 0xB6, 0x02, 0x86, 0xF7,
+ 0x53, 0x44, 0xFB, 0x14, 0x61, 0xF6, 0xA4, 0x05, 0xB4, 0xFC, 0xBE,
+ 0x01, 0x42, 0xFF, 0x32, 0x00, 0xFF, 0xFF, 0xFE, 0xFF, 0x35, 0x00,
+ 0x3A, 0xFF, 0xD4, 0x01, 0x7A, 0xFC, 0x2B, 0x06, 0x1E, 0xF5, 0x56,
+ 0x19, 0x0C, 0x42, 0xAA, 0xF5, 0xC9, 0x03, 0xA4, 0xFE, 0x54, 0x00,
+ 0x09, 0x00, 0xEB, 0xFF, 0x06, 0x00, 0x04, 0x00, 0xF7, 0xFF, 0xEA,
+ 0xFF, 0x93, 0x00, 0x36, 0xFE, 0x7D, 0x04, 0x85, 0xF4, 0x1F, 0x40,
+ 0x94, 0x1C, 0x47, 0xF4, 0x7E, 0x06, 0x5A, 0xFC, 0xDF, 0x01, 0x37,
+ 0xFF, 0x36, 0x00, 0xFE, 0xFF, 0xFF, 0xFF, 0x30, 0x00, 0x4A, 0xFF,
+ 0xA9, 0x01, 0xE7, 0xFC, 0x33, 0x05, 0x60, 0xF7, 0xDA, 0x11, 0xB8,
+ 0x45, 0x1C, 0xF9, 0xD8, 0x01, 0xCA, 0xFF, 0xAF, 0xFF, 0x5A, 0x00,
+ 0xCC, 0xFF, 0x0D, 0x00, 0x00, 0x00, 0x0F, 0x00, 0xA8, 0xFF, 0x17,
+ 0x01, 0x57, 0xFD, 0xD6, 0x05, 0x90, 0xF2, 0xC8, 0x3A, 0x46, 0x24,
+ 0xAA, 0xF2, 0x06, 0x07, 0x32, 0xFC, 0xE5, 0x01, 0x39, 0xFF, 0x36,
+ 0x00, 0xFD, 0xFF, 0x00, 0x00, 0x28, 0x00, 0x62, 0xFF, 0x69, 0x01,
+ 0x77, 0xFD, 0x04, 0x04, 0xE2, 0xF9, 0xCB, 0x0A, 0x0D, 0x48, 0x94,
+ 0xFD, 0x92, 0xFF, 0x10, 0x01, 0xFE, 0xFE, 0xB1, 0x00, 0xAA, 0xFF,
+ 0x15, 0x00, 0xFE, 0xFF, 0x22, 0x00, 0x74, 0xFF, 0x7C, 0x01, 0xB5,
+ 0xFC, 0xB8, 0x06, 0x9C, 0xF1, 0x81, 0x34, 0xD1, 0x2B, 0xB3, 0xF1,
+ 0x29, 0x07, 0x46, 0xFC, 0xCA, 0x01, 0x4A, 0xFF, 0x30, 0x00, 0xFD,
+ 0xFF, 0x00, 0x00, 0x1F, 0x00, 0x81, 0xFF, 0x1B, 0x01, 0x20, 0xFE,
+ 0xB6, 0x02, 0x7A, 0xFC, 0x5F, 0x04, 0xF4, 0x48, 0xFF, 0x02, 0x13,
+ 0xFD, 0x67, 0x02, 0x49, 0xFE, 0x07, 0x01, 0x88, 0xFF, 0x1D, 0x00,
+ 0xFD, 0xFF, 0x2E, 0x00, 0x50, 0xFF, 0xC0, 0x01, 0x53, 0xFC, 0x21,
+ 0x07, 0x96, 0xF1, 0x82, 0x2D, 0xF2, 0x32, 0x86, 0xF1, 0xDB, 0x06,
+ 0x99, 0xFC, 0x8E, 0x01, 0x6A, 0xFF, 0x25, 0x00, 0xFD, 0xFF, 0x16,
+ 0x00, 0xA2, 0xFF, 0xC5, 0x00, 0xD4, 0xFE, 0x5F, 0x01, 0x03, 0xFF,
+ 0xBF, 0xFE, 0x63, 0x48, 0x40, 0x09, 0x7B, 0xFA, 0xB9, 0x03, 0x9D,
+ 0xFD, 0x58, 0x01, 0x69, 0xFF, 0x26, 0x00, 0x00, 0x00, 0xFD, 0xFF,
+ 0x35, 0x00, 0x3B, 0xFF, 0xE2, 0x01, 0x31, 0xFC, 0x17, 0x07, 0x61,
+ 0xF2, 0x0A, 0x26, 0x6A, 0x39, 0x41, 0xF2, 0x15, 0x06, 0x2C, 0xFD,
+ 0x31, 0x01, 0x9B, 0xFF, 0x14, 0x00, 0xFF, 0xFF, 0x0E, 0x00, 0xC4,
+ 0xFF, 0x6E, 0x00, 0x87, 0xFF, 0x13, 0x00, 0x58, 0x01, 0x0D, 0xFA,
+ 0x61, 0x46, 0x2D, 0x10, 0xF0, 0xF7, 0xF1, 0x04, 0x05, 0xFD, 0x9C,
+ 0x01, 0x4E, 0xFF, 0x2E, 0x00, 0xFF, 0xFF, 0xFE, 0xFF, 0x36, 0x00,
+ 0x36, 0xFF, 0xE3, 0x01, 0x4C, 0xFC, 0xA6, 0x06, 0xDB, 0xF3, 0x5B,
+ 0x1E, 0xFC, 0x3E, 0xFA, 0xF3, 0xD7, 0x04, 0xFD, 0xFD, 0xB4, 0x00,
+ 0xD9, 0xFF, 0xFD, 0xFF, 0x03, 0x00, 0x08, 0x00, 0xE4, 0xFF, 0x1B,
+ 0x00, 0x30, 0x00, 0xE4, 0xFE, 0x5F, 0x03, 0x5E, 0xF6, 0x02, 0x43,
+ 0x96, 0x17, 0x9B, 0xF5, 0xF8, 0x05, 0x8F, 0xFC, 0xCC, 0x01, 0x3D,
+ 0xFF, 0x34, 0x00, 0xFE, 0xFF, 0xFF, 0xFF, 0x33, 0x00, 0x3E, 0xFF,
+ 0xC8, 0x01, 0x9B, 0xFC, 0xDD, 0x05, 0xDC, 0xF5, 0xB6, 0x16, 0x77,
+ 0x43, 0xBD, 0xF6, 0x28, 0x03, 0x05, 0xFF, 0x1D, 0x00, 0x25, 0x00,
+ 0xE1, 0xFF, 0x08, 0x00, 0x02, 0x00, 0x00, 0x00, 0xD2, 0xFF, 0xC4,
+ 0x00, 0xE2, 0xFD, 0x01, 0x05, 0xBA, 0xF3, 0x64, 0x3E, 0x3F, 0x1F,
+ 0xA8, 0xF3, 0xB8, 0x06, 0x46, 0xFC, 0xE5, 0x01, 0x36, 0xFF, 0x36,
+ 0x00, 0xFD, 0xFF, 0xFF, 0xFF, 0x2D, 0x00, 0x51, 0xFF, 0x95, 0x01,
+ 0x15, 0xFD, 0xCF, 0x04, 0x39, 0xF8, 0x59, 0x0F, 0xAF, 0x46, 0x8B,
+ 0xFA, 0x17, 0x01, 0x38, 0x00, 0x73, 0xFF, 0x78, 0x00, 0xC0, 0xFF,
+ 0x0F, 0x00, 0xFF, 0xFF, 0x16, 0x00, 0x94, 0xFF, 0x3D, 0x01, 0x18,
+ 0xFD, 0x32, 0x06, 0x1F, 0xF2, 0xB5, 0x38, 0xEB, 0x26, 0x40, 0xF2,
+ 0x1E, 0x07, 0x32, 0xFC, 0xDF, 0x01, 0x3D, 0xFF, 0x35, 0x00, 0xFD,
+ 0xFF, 0x00, 0x00, 0x25, 0x00, 0x6C, 0xFF, 0x4F, 0x01, 0xB0, 0xFD,
+ 0x93, 0x03, 0xC7, 0xFA, 0x7D, 0x08, 0x86, 0x48, 0x5A, 0xFF, 0xBA,
+ 0xFE, 0x86, 0x01, 0xBF, 0xFE, 0xCF, 0x00, 0x9E, 0xFF, 0x17, 0x00,
+ 0xFD, 0xFF, 0x27, 0x00, 0x66, 0xFF, 0x97, 0x01, 0x8C, 0xFC, 0xEA,
+ 0x06, 0x80, 0xF1, 0x26, 0x32, 0x58, 0x2E, 0x8B, 0xF1, 0x1B, 0x07,
+ 0x5B, 0xFC, 0xBA, 0x01, 0x53, 0xFF, 0x2D, 0x00, 0xFD, 0xFF, 0x1C,
+ 0x00, 0x8C, 0xFF, 0xFE, 0x00, 0x5D, 0xFE, 0x3F, 0x02, 0x5E, 0xFD,
+ 0x54, 0x02, 0xEC, 0x48, 0x13, 0x05, 0x2E, 0xFC, 0xDE, 0x02, 0x0C,
+ 0xFE, 0x24, 0x01, 0x7D, 0xFF, 0x20, 0x00, 0x00, 0x00, 0xFD, 0xFF,
+ 0x31, 0x00, 0x47, 0xFF, 0xCF, 0x01, 0x40, 0xFC, 0x2A, 0x07, 0xC6,
+ 0xF1, 0xF7, 0x2A, 0x46, 0x35, 0xAB, 0xF1, 0xA4, 0x06, 0xC4, 0xFC,
+ 0x72, 0x01, 0x79, 0xFF, 0x20, 0x00, 0xFE, 0xFF, 0x14, 0x00, 0xAE,
+ 0xFF, 0xA7, 0x00, 0x12, 0xFF, 0xEA, 0x00, 0xD9, 0xFF, 0x03, 0xFD,
+ 0xDC, 0x47, 0x95, 0x0B, 0x96, 0xF9, 0x29, 0x04, 0x65, 0xFD, 0x71,
+ 0x01, 0x5F, 0xFF, 0x29, 0x00, 0x00, 0x00, 0xFD, 0xFF, 0x36, 0x00,
+ 0x38, 0xFF, 0xE6, 0x01, 0x34, 0xFC, 0xFB, 0x06, 0xD2, 0xF2, 0x64,
+ 0x23, 0x73, 0x3B, 0xBC, 0xF2, 0xB4, 0x05, 0x6E, 0xFD, 0x09, 0x01,
+ 0xAF, 0xFF, 0x0D, 0x00, 0x00, 0x00, 0x0C, 0x00, 0xD0, 0xFF, 0x51,
+ 0x00, 0xC3, 0xFF, 0xA6, 0xFF, 0x16, 0x02, 0xA9, 0xF8, 0x5C, 0x45,
+ 0xB2, 0x12, 0x19, 0xF7, 0x52, 0x05, 0xD8, 0xFC, 0xAF, 0x01, 0x47,
+ 0xFF, 0x30, 0x00, 0xFF, 0xFF, 0xFE, 0xFF, 0x36, 0x00, 0x38, 0xFF,
+ 0xDD, 0x01, 0x62, 0xFC, 0x69, 0x06, 0x7F, 0xF4, 0xB2, 0x1B, 0xAB,
+ 0x40, 0xD0, 0xF4, 0x4E, 0x04, 0x53, 0xFE, 0x83, 0x00, 0xF2, 0xFF,
+ 0xF4, 0xFF, 0x05, 0x00, 0x06, 0x00, 0xEE, 0xFF, 0x01, 0x00, 0x66,
+ 0x00, 0x85, 0xFE, 0xFC, 0x03, 0x55, 0xF5, 0x8C, 0x41, 0x38, 0x1A,
+ 0xE1, 0xF4, 0x43, 0x06, 0x70, 0xFC, 0xD8, 0x01, 0x39, 0xFF, 0x35,
+ 0x00, 0xFE, 0xFF, 0xFF, 0xFF, 0x32, 0x00, 0x44, 0xFF, 0xB9, 0x01,
+ 0xC1, 0xFC, 0x86, 0x05, 0xA5, 0xF6, 0x1E, 0x14, 0xBA, 0x44, 0xF0,
+ 0xF7, 0x7B, 0x02, 0x6B, 0xFF, 0xE4, 0xFF, 0x41, 0x00, 0xD6, 0xFF,
+ 0x0B, 0x00, 0x01, 0x00, 0x08, 0x00, 0xBB, 0xFF, 0xF1, 0x00, 0x96,
+ 0xFD, 0x78, 0x05, 0x0E, 0xF3, 0x8A, 0x3C, 0xEA, 0x21, 0x19, 0xF3,
+ 0xE6, 0x06, 0x38, 0xFC, 0xE6, 0x01, 0x37, 0xFF, 0x36, 0x00, 0xFD,
+ 0xFF, 0x00, 0x00, 0x2B, 0x00, 0x5A, 0xFF, 0x7E, 0x01, 0x48, 0xFD,
+ 0x66, 0x04, 0x18, 0xF9, 0xE8, 0x0C, 0x7C, 0x47, 0x19, 0xFC, 0x4D,
+ 0x00, 0xA9, 0x00, 0x35, 0xFF, 0x96, 0x00, 0xB5, 0xFF, 0x12, 0x00,
+ 0xFE, 0xFF, 0x1D, 0x00, 0x82, 0xFF, 0x60, 0x01, 0xE0, 0xFC, 0x7F,
+ 0x06, 0xCC, 0xF1, 0x85, 0x36, 0x87, 0x29, 0xEB, 0xF1, 0x2A, 0x07,
+ 0x39, 0xFC, 0xD6, 0x01, 0x43, 0xFF, 0x33, 0x00, 0xFD, 0xFF, 0x00,
+ 0x00, 0x22, 0x00, 0x77, 0xFF, 0x34, 0x01, 0xEA, 0xFD, 0x1F, 0x03,
+ 0xAE, 0xFB, 0x45, 0x06, 0xD5, 0x48, 0x3C, 0x01, 0xDC, 0xFD, 0xFD,
+ 0x01, 0x80, 0xFE, 0xED, 0x00, 0x93, 0xFF, 0x1B, 0x00, 0xFD, 0xFF,
+ 0x2B, 0x00, 0x59, 0xFF, 0xAE, 0x01, 0x6A, 0xFC, 0x0D, 0x07, 0x80,
+ 0xF1, 0xB8, 0x2F, 0xCF, 0x30, 0x7D, 0xF1, 0xFF, 0x06, 0x78, 0xFC,
+ 0xA5, 0x01, 0x5F, 0xFF, 0x29, 0x00, 0xFD, 0xFF, 0x19, 0x00, 0x98,
+ 0xFF, 0xE0, 0x00, 0x9C, 0xFE, 0xC8, 0x01, 0x3F, 0xFE, 0x62, 0x00,
+ 0xB8, 0x48, 0x3F, 0x07, 0x47, 0xFB, 0x53, 0x03, 0xD0, 0xFD, 0x40,
+ 0x01, 0x72, 0xFF, 0x23, 0x00, 0x00, 0x00, 0xFD, 0xFF, 0x34, 0x00,
+ 0x40, 0xFF, 0xDB, 0x01, 0x35, 0xFC, 0x26, 0x07, 0x0E, 0xF2, 0x60,
+ 0x28, 0x82, 0x37, 0xED, 0xF1, 0x5E, 0x06, 0xF8, 0xFC, 0x51, 0x01,
+ 0x8A, 0xFF, 0x1A, 0x00, 0xFF, 0xFF, 0x11, 0x00, 0xBA, 0xFF, 0x89,
+ 0x00, 0x51, 0xFF, 0x77, 0x00, 0xA7, 0x00, 0x64, 0xFB, 0x26, 0x47,
+ 0xFC, 0x0D, 0xB4, 0xF8, 0x95, 0x04, 0x31, 0xFD, 0x88, 0x01, 0x56,
+ 0xFF, 0x2C, 0x00, 0xFF, 0xFF, 0xFD, 0xFF, 0x36, 0x00, 0x36, 0xFF,
+ 0xE6, 0x01, 0x3E, 0xFC, 0xD3, 0x06, 0x56, 0xF3, 0xBA, 0x20, 0x61,
+ 0x3D, 0x56, 0xF3, 0x45, 0x05, 0xB7, 0xFD, 0xDE, 0x00, 0xC5, 0xFF,
+ 0x05, 0x00, 0x02, 0x00, 0x09, 0x00, 0xDB, 0xFF, 0x34, 0x00, 0xFE,
+ 0xFF, 0x3D, 0xFF, 0xC9, 0x02, 0x64, 0xF7, 0x2F, 0x44, 0x44, 0x15,
+ 0x4A, 0xF6, 0xAD, 0x05, 0xAF, 0xFC, 0xC0, 0x01, 0x41, 0xFF, 0x32,
+ 0x00, 0xFF, 0xFF, 0xFE, 0xFF, 0x35, 0x00, 0x3A, 0xFF, 0xD3, 0x01,
+ 0x7D, 0xFC, 0x23, 0x06, 0x32, 0xF5, 0x0C, 0x19, 0x38, 0x42, 0xC7,
+ 0xF5, 0xB8, 0x03, 0xAF, 0xFE, 0x4E, 0x00, 0x0C, 0x00, 0xEA, 0xFF,
+ 0x06, 0x00, 0x04, 0x00, 0xF8, 0xFF, 0xE7, 0xFF, 0x99, 0x00, 0x2C,
+ 0xFE, 0x8C, 0x04, 0x6D, 0xF4, 0xF0, 0x3F, 0xE0, 0x1C, 0x34, 0xF4,
+ 0x85, 0x06, 0x57, 0xFC, 0xE0, 0x01, 0x37, 0xFF, 0x36, 0x00, 0xFE,
+ 0xFF, 0xFF, 0xFF, 0x2F, 0x00, 0x4A, 0xFF, 0xA7, 0x01, 0xEC, 0xFC,
+ 0x28, 0x05, 0x77, 0xF7, 0x92, 0x11, 0xD7, 0x45, 0x43, 0xF9, 0xC3,
+ 0x01, 0xD6, 0xFF, 0xA9, 0xFF, 0x5E, 0x00, 0xCB, 0xFF, 0x0D, 0x00,
+ 0x00, 0x00, 0x10, 0x00, 0xA6, 0xFF, 0x1B, 0x01, 0x50, 0xFD, 0xE1,
+ 0x05, 0x82, 0xF2, 0x8F, 0x3A, 0x92, 0x24, 0x9D, 0xF2, 0x09, 0x07,
+ 0x32, 0xFC, 0xE4, 0x01, 0x39, 0xFF, 0x36, 0x00, 0xFD, 0xFF, 0x00,
+ 0x00, 0x28, 0x00, 0x63, 0xFF, 0x66, 0x01, 0x7D, 0xFD, 0xF8, 0x03,
+ 0xFB, 0xF9, 0x89, 0x0A, 0x1D, 0x48, 0xC5, 0xFD, 0x7A, 0xFF, 0x1D,
+ 0x01, 0xF7, 0xFE, 0xB4, 0x00, 0xA9, 0xFF, 0x15, 0x00, 0xFE, 0xFF,
+ 0x23, 0x00, 0x72, 0xFF, 0x7F, 0x01, 0xB0, 0xFC, 0xBE, 0x06, 0x97,
+ 0xF1, 0x3F, 0x34, 0x19, 0x2C, 0xAD, 0xF1, 0x28, 0x07, 0x48, 0xFC,
+ 0xC9, 0x01, 0x4B, 0xFF, 0x30, 0x00, 0xFD, 0xFF, 0x00, 0x00, 0x1F,
+ 0x00, 0x82, 0xFF, 0x18, 0x01, 0x27, 0xFE, 0xA9, 0x02, 0x94, 0xFC,
+ 0x24, 0x04, 0xF5, 0x48, 0x39, 0x03, 0xF9, 0xFC, 0x74, 0x02, 0x42,
+ 0xFE, 0x0B, 0x01, 0x87, 0xFF, 0x1E, 0x00, 0xFD, 0xFF, 0x2F, 0x00,
+ 0x4F, 0xFF, 0xC2, 0x01, 0x51, 0xFC, 0x23, 0x07, 0x9A, 0xF1, 0x3A,
+ 0x2D, 0x35, 0x33, 0x89, 0xF1, 0xD5, 0x06, 0x9D, 0xFC, 0x8B, 0x01,
+ 0x6C, 0xFF, 0x25, 0x00, 0xFD, 0xFF, 0x16, 0x00, 0xA4, 0xFF, 0xC2,
+ 0x00, 0xDB, 0xFE, 0x52, 0x01, 0x1B, 0xFF, 0x8D, 0xFE, 0x57, 0x48,
+ 0x81, 0x09, 0x61, 0xFA, 0xC6, 0x03, 0x96, 0xFD, 0x5B, 0x01, 0x68,
+ 0xFF, 0x26, 0x00, 0x00, 0x00, 0xFD, 0xFF, 0x35, 0x00, 0x3B, 0xFF,
+ 0xE2, 0x01, 0x31, 0xFC, 0x15, 0x07, 0x6D, 0xF2, 0xBF, 0x25, 0xA5,
+ 0x39, 0x4D, 0xF2, 0x0B, 0x06, 0x33, 0xFD, 0x2D, 0x01, 0x9D, 0xFF,
+ 0x13, 0x00, 0xFF, 0xFF, 0x0E, 0x00, 0xC6, 0xFF, 0x6B, 0x00, 0x8E,
+ 0xFF, 0x06, 0x00, 0x6E, 0x01, 0xE4, 0xF9, 0x48, 0x46, 0x75, 0x10,
+ 0xD7, 0xF7, 0xFC, 0x04, 0x00, 0xFD, 0x9E, 0x01, 0x4E, 0xFF, 0x2E,
+ 0x00, 0xFF, 0xFF, 0xFE, 0xFF, 0x36, 0x00, 0x36, 0xFF, 0xE3, 0x01,
+ 0x4E, 0xFC, 0xA0, 0x06, 0xED, 0xF3, 0x0F, 0x1E, 0x2D, 0x3F, 0x10,
+ 0xF4, 0xC8, 0x04, 0x07, 0xFE, 0xAF, 0x00, 0xDC, 0xFF, 0xFC, 0xFF,
+ 0x03, 0x00, 0x07, 0x00, 0xE5, 0xFF, 0x18, 0x00, 0x36, 0x00, 0xD9,
+ 0xFE, 0x71, 0x03, 0x3F, 0xF6, 0xDB, 0x42, 0xE0, 0x17, 0x86, 0xF5,
+ 0x00, 0x06, 0x8C, 0xFC, 0xCE, 0x01, 0x3C, 0xFF, 0x34, 0x00, 0xFE,
+ 0xFF, 0xFF, 0xFF, 0x33, 0x00, 0x3F, 0xFF, 0xC6, 0x01, 0x9F, 0xFC,
+ 0xD3, 0x05, 0xF1, 0xF5, 0x6C, 0x16, 0x9E, 0x43, 0xDD, 0xF6, 0x15,
+ 0x03, 0x10, 0xFF, 0x17, 0x00, 0x28, 0x00, 0xDF, 0xFF, 0x09, 0x00,
+ 0x02, 0x00, 0x01, 0x00, 0xCF, 0xFF, 0xC9, 0x00, 0xDA, 0xFD, 0x0F,
+ 0x05, 0xA5, 0xF3, 0x31, 0x3E, 0x8A, 0x1F, 0x97, 0xF3, 0xBD, 0x06,
+ 0x44, 0xFC, 0xE5, 0x01, 0x36, 0xFF, 0x36, 0x00, 0xFD, 0xFF, 0xFF,
+ 0xFF, 0x2D, 0x00, 0x52, 0xFF, 0x92, 0x01, 0x1B, 0xFD, 0xC4, 0x04,
+ 0x51, 0xF8, 0x13, 0x0F, 0xC8, 0x46, 0xB6, 0xFA, 0x01, 0x01, 0x44,
+ 0x00, 0x6C, 0xFF, 0x7B, 0x00, 0xBF, 0xFF, 0x10, 0x00, 0xFF, 0xFF,
+ 0x17, 0x00, 0x92, 0xFF, 0x41, 0x01, 0x11, 0xFD, 0x3B, 0x06, 0x14,
+ 0xF2, 0x78, 0x38, 0x36, 0x27, 0x35, 0xF2, 0x20, 0x07, 0x33, 0xFC,
+ 0xDF, 0x01, 0x3E, 0xFF, 0x34, 0x00, 0xFD, 0xFF, 0x00, 0x00, 0x25,
+ 0x00, 0x6D, 0xFF, 0x4C, 0x01, 0xB6, 0xFD, 0x86, 0x03, 0xE1, 0xFA,
+ 0x3D, 0x08, 0x92, 0x48, 0x8E, 0xFF, 0xA1, 0xFE, 0x93, 0x01, 0xB8,
+ 0xFE, 0xD3, 0x00, 0x9D, 0xFF, 0x18, 0x00, 0xFD, 0xFF, 0x28, 0x00,
+ 0x64, 0xFF, 0x9A, 0x01, 0x88, 0xFC, 0xEE, 0x06, 0x7E, 0xF1, 0xE3,
+ 0x31, 0x9F, 0x2E, 0x88, 0xF1, 0x19, 0x07, 0x5E, 0xFC, 0xB7, 0x01,
+ 0x54, 0xFF, 0x2D, 0x00, 0xFD, 0xFF, 0x1C, 0x00, 0x8D, 0xFF, 0xFA,
+ 0x00, 0x64, 0xFE, 0x32, 0x02, 0x78, 0xFD, 0x1B, 0x02, 0xEA, 0x48,
+ 0x50, 0x05, 0x14, 0xFC, 0xEB, 0x02, 0x05, 0xFE, 0x27, 0x01, 0x7C,
+ 0xFF, 0x21, 0x00, 0x00, 0x00, 0xFD, 0xFF, 0x32, 0x00, 0x46, 0xFF,
+ 0xD1, 0x01, 0x3F, 0xFC, 0x2B, 0x07, 0xCD, 0xF1, 0xAE, 0x2A, 0x86,
+ 0x35, 0xB1, 0xF1, 0x9D, 0x06, 0xCA, 0xFC, 0x6E, 0x01, 0x7B, 0xFF,
+ 0x20, 0x00, 0xFE, 0xFF, 0x13, 0x00, 0xAF, 0xFF, 0xA4, 0x00, 0x19,
+ 0xFF, 0xDD, 0x00, 0xF0, 0xFF, 0xD4, 0xFC, 0xC9, 0x47, 0xD8, 0x0B,
+ 0x7C, 0xF9, 0x35, 0x04, 0x5F, 0xFD, 0x74, 0x01, 0x5E, 0xFF, 0x29,
+ 0x00, 0x00, 0x00, 0xFD, 0xFF, 0x36, 0x00, 0x38, 0xFF, 0xE6, 0x01,
+ 0x35, 0xFC, 0xF7, 0x06, 0xE0, 0xF2, 0x18, 0x23, 0xAB, 0x3B, 0xCC,
+ 0xF2, 0xA8, 0x05, 0x76, 0xFD, 0x04, 0x01, 0xB1, 0xFF, 0x0C, 0x00,
+ 0x00, 0x00, 0x0C, 0x00, 0xD1, 0xFF, 0x4E, 0x00, 0xCA, 0xFF, 0x9A,
+ 0xFF, 0x2A, 0x02, 0x83, 0xF8, 0x3F, 0x45, 0xFB, 0x12, 0x01, 0xF7,
+ 0x5D, 0x05, 0xD3, 0xFC, 0xB1, 0x01, 0x46, 0xFF, 0x31, 0x00, 0xFF,
+ 0xFF, 0xFE, 0xFF, 0x36, 0x00, 0x38, 0xFF, 0xDC, 0x01, 0x64, 0xFC,
+ 0x62, 0x06, 0x93, 0xF4, 0x66, 0x1B, 0xD9, 0x40, 0xEA, 0xF4, 0x3E,
+ 0x04, 0x5D, 0xFE, 0x7D, 0x00, 0xF5, 0xFF, 0xF3, 0xFF, 0x05, 0x00,
+ 0x05, 0x00, 0xEF, 0xFF, 0xFE, 0xFF, 0x6C, 0x00, 0x7B, 0xFE, 0x0C,
+ 0x04, 0x3A, 0xF5, 0x5F, 0x41, 0x83, 0x1A, 0xCD, 0xF4, 0x4B, 0x06,
+ 0x6D, 0xFC, 0xD9, 0x01, 0x39, 0xFF, 0x35, 0x00, 0xFE, 0xFF, 0xFF,
+ 0xFF, 0x31, 0x00, 0x44, 0xFF, 0xB7, 0x01, 0xC5, 0xFC, 0x7C, 0x05,
+ 0xBC, 0xF6, 0xD5, 0x13, 0xDC, 0x44, 0x14, 0xF8, 0x67, 0x02, 0x77,
+ 0xFF, 0xDD, 0xFF, 0x44, 0x00, 0xD5, 0xFF, 0x0B, 0x00, 0x01, 0x00,
+ 0x09, 0x00, 0xB8, 0xFF, 0xF6, 0x00, 0x8D, 0xFD, 0x84, 0x05, 0xFD,
+ 0xF2, 0x52, 0x3C, 0x35, 0x22, 0x0B, 0xF3, 0xEB, 0x06, 0x37, 0xFC,
+ 0xE6, 0x01, 0x37, 0xFF, 0x36, 0x00, 0xFD, 0xFF, 0x00, 0x00, 0x2A,
+ 0x00, 0x5B, 0xFF, 0x7C, 0x01, 0x4E, 0xFD, 0x5A, 0x04, 0x31, 0xF9,
+ 0xA4, 0x0C, 0x90, 0x47, 0x47, 0xFC, 0x36, 0x00, 0xB6, 0x00, 0x2E,
+ 0xFF, 0x99, 0x00, 0xB3, 0xFF, 0x12, 0x00, 0xFE, 0xFF, 0x1E, 0x00,
+ 0x80, 0xFF, 0x64, 0x01, 0xDA, 0xFC, 0x87, 0x06, 0xC5, 0xF1, 0x46,
+ 0x36, 0xD1, 0x29, 0xE3, 0xF1, 0x2A, 0x07, 0x3A, 0xFC, 0xD5, 0x01,
+ 0x44, 0xFF, 0x32, 0x00, 0xFD, 0xFF, 0x00, 0x00, 0x22, 0x00, 0x78,
+ 0xFF, 0x31, 0x01, 0xF1, 0xFD, 0x12, 0x03, 0xC7, 0xFB, 0x07, 0x06,
+ 0xDB, 0x48, 0x73, 0x01, 0xC3, 0xFD, 0x0A, 0x02, 0x79, 0xFE, 0xF1,
+ 0x00, 0x91, 0xFF, 0x1B, 0x00, 0xFD, 0xFF, 0x2C, 0x00, 0x58, 0xFF,
+ 0xB1, 0x01, 0x67, 0xFC, 0x10, 0x07, 0x81, 0xF1, 0x73, 0x2F, 0x15,
+ 0x31, 0x7C, 0xF1, 0xFB, 0x06, 0x7C, 0xFC, 0xA2, 0x01, 0x60, 0xFF,
+ 0x29, 0x00, 0xFD, 0xFF, 0x19, 0x00, 0x99, 0xFF, 0xDD, 0x00, 0xA3,
+ 0xFE, 0xBB, 0x01, 0x58, 0xFE, 0x2D, 0x00, 0xAF, 0x48, 0x7E, 0x07,
+ 0x2E, 0xFB, 0x60, 0x03, 0xC9, 0xFD, 0x43, 0x01, 0x71, 0xFF, 0x24,
+ 0x00, 0x00, 0x00, 0xFD, 0xFF, 0x34, 0x00, 0x3F, 0xFF, 0xDC, 0x01,
+ 0x34, 0xFC, 0x25, 0x07, 0x18, 0xF2, 0x15, 0x28, 0xBF, 0x37, 0xF7,
+ 0xF1, 0x56, 0x06, 0xFE, 0xFC, 0x4D, 0x01, 0x8C, 0xFF, 0x19, 0x00,
+ 0xFF, 0xFF, 0x10, 0x00, 0xBB, 0xFF, 0x85, 0x00, 0x58, 0xFF, 0x6A,
+ 0x00, 0xBE, 0x00, 0x38, 0xFB, 0x0F, 0x47, 0x42, 0x0E, 0x9B, 0xF8,
+ 0xA1, 0x04, 0x2B, 0xFD, 0x8B, 0x01, 0x55, 0xFF, 0x2C, 0x00, 0xFF,
+ 0xFF, 0xFD, 0xFF, 0x36, 0x00, 0x36, 0xFF, 0xE6, 0x01, 0x3F, 0xFC,
+ 0xCE, 0x06, 0x66, 0xF3, 0x6F, 0x20, 0x96, 0x3D, 0x69, 0xF3, 0x38,
+ 0x05, 0xBF, 0xFD, 0xD9, 0x00, 0xC7, 0xFF, 0x04, 0x00, 0x02, 0x00,
+ 0x09, 0x00, 0xDC, 0xFF, 0x31, 0x00, 0x04, 0x00, 0x32, 0xFF, 0xDC,
+ 0x02, 0x42, 0xF7, 0x0B, 0x44, 0x8E, 0x15, 0x34, 0xF6, 0xB7, 0x05,
+ 0xAB, 0xFC, 0xC1, 0x01, 0x40, 0xFF, 0x33, 0x00, 0xFF, 0xFF, 0xFE,
+ 0xFF, 0x35, 0x00, 0x3B, 0xFF, 0xD2, 0x01, 0x81, 0xFC, 0x1A, 0x06,
+ 0x47, 0xF5, 0xC1, 0x18, 0x60, 0x42, 0xE4, 0xF5, 0xA6, 0x03, 0xB9,
+ 0xFE, 0x48, 0x00, 0x0F, 0x00, 0xE9, 0xFF, 0x07, 0x00, 0x04, 0x00,
+ 0xF9, 0xFF, 0xE4, 0xFF, 0x9F, 0x00, 0x23, 0xFE, 0x9B, 0x04, 0x55,
+ 0xF4, 0xC0, 0x3F, 0x2C, 0x1D, 0x22, 0xF4, 0x8C, 0x06, 0x55, 0xFC,
+ 0xE1, 0x01, 0x37, 0xFF, 0x36, 0x00, 0xFE, 0xFF, 0xFF, 0xFF, 0x2F,
+ 0x00, 0x4B, 0xFF, 0xA4, 0x01, 0xF1, 0xFC, 0x1D, 0x05, 0x8F, 0xF7,
+ 0x4A, 0x11, 0xF2, 0x45, 0x6B, 0xF9, 0xAE, 0x01, 0xE2, 0xFF, 0xA2,
+ 0xFF, 0x61, 0x00, 0xC9, 0xFF, 0x0D, 0x00, 0x00, 0x00, 0x11, 0x00,
+ 0xA3, 0xFF, 0x20, 0x01, 0x49, 0xFD, 0xEB, 0x05, 0x74, 0xF2, 0x54,
+ 0x3A, 0xDD, 0x24, 0x91, 0xF2, 0x0C, 0x07, 0x32, 0xFC, 0xE4, 0x01,
+ 0x3A, 0xFF, 0x36, 0x00, 0xFD, 0xFF, 0x00, 0x00, 0x27, 0x00, 0x64,
+ 0xFF, 0x63, 0x01, 0x84, 0xFD, 0xEB, 0x03, 0x14, 0xFA, 0x47, 0x0A,
+ 0x2C, 0x48, 0xF6, 0xFD, 0x63, 0xFF, 0x2B, 0x01, 0xF0, 0xFE, 0xB8,
+ 0x00, 0xA8, 0xFF, 0x15, 0x00, 0xFE, 0xFF, 0x23, 0x00, 0x71, 0xFF,
+ 0x82, 0x01, 0xAB, 0xFC, 0xC4, 0x06, 0x93, 0xF1, 0xFD, 0x33, 0x62,
+ 0x2C, 0xA8, 0xF1, 0x27, 0x07, 0x4A, 0xFC, 0xC7, 0x01, 0x4C, 0xFF,
+ 0x30, 0x00, 0xFD, 0xFF, 0x00, 0x00, 0x1F, 0x00, 0x83, 0xFF, 0x14,
+ 0x01, 0x2D, 0xFE, 0x9C, 0x02, 0xAD, 0xFC, 0xE9, 0x03, 0xF6, 0x48,
+ 0x73, 0x03, 0xE0, 0xFC, 0x82, 0x02, 0x3B, 0xFE, 0x0E, 0x01, 0x86,
+ 0xFF, 0x1E, 0x00, 0xFD, 0xFF, 0x2F, 0x00, 0x4E, 0xFF, 0xC3, 0x01,
+ 0x4E, 0xFC, 0x24, 0x07, 0x9E, 0xF1, 0xF2, 0x2C, 0x78, 0x33, 0x8C,
+ 0xF1, 0xD0, 0x06, 0xA2, 0xFC, 0x88, 0x01, 0x6D, 0xFF, 0x24, 0x00,
+ 0xFD, 0xFF, 0x16, 0x00, 0xA5, 0xFF, 0xBE, 0x00, 0xE2, 0xFE, 0x45,
+ 0x01, 0x33, 0xFF, 0x5A, 0xFE, 0x48, 0x48, 0xC3, 0x09, 0x47, 0xFA,
+ 0xD2, 0x03, 0x90, 0xFD, 0x5E, 0x01, 0x66, 0xFF, 0x27, 0x00, 0x00,
+ 0x00, 0xFD, 0xFF, 0x35, 0x00, 0x3B, 0xFF, 0xE3, 0x01, 0x31, 0xFC,
+ 0x12, 0x07, 0x79, 0xF2, 0x73, 0x25, 0xDF, 0x39, 0x5A, 0xF2, 0x00,
+ 0x06, 0x3A, 0xFD, 0x28, 0x01, 0x9F, 0xFF, 0x13, 0x00, 0x00, 0x00,
+ 0x0E, 0x00, 0xC7, 0xFF, 0x68, 0x00, 0x95, 0xFF, 0xFA, 0xFF, 0x83,
+ 0x01, 0xBB, 0xF9, 0x2B, 0x46, 0xBB, 0x10, 0xBF, 0xF7, 0x07, 0x05,
+ 0xFB, 0xFC, 0xA0, 0x01, 0x4D, 0xFF, 0x2F, 0x00, 0xFF, 0xFF, 0xFE,
+ 0xFF, 0x36, 0x00, 0x36, 0xFF, 0xE2, 0x01, 0x50, 0xFC, 0x99, 0x06,
+ 0xFE, 0xF3, 0xC3, 0x1D, 0x5E, 0x3F, 0x27, 0xF4, 0xB9, 0x04, 0x10,
+ 0xFE, 0xA9, 0x00, 0xDF, 0xFF, 0xFB, 0xFF, 0x03, 0x00, 0x07, 0x00,
+ 0xE6, 0xFF, 0x15, 0x00, 0x3C, 0x00, 0xCF, 0xFE, 0x83, 0x03, 0x20,
+ 0xF6, 0xB2, 0x42, 0x2B, 0x18, 0x71, 0xF5, 0x09, 0x06, 0x88, 0xFC,
+ 0xCF, 0x01, 0x3C, 0xFF, 0x34, 0x00, 0xFE, 0xFF, 0xFF, 0xFF, 0x33,
+ 0x00, 0x3F, 0xFF, 0xC5, 0x01, 0xA3, 0xFC, 0xCA, 0x05, 0x07, 0xF6,
+ 0x22, 0x16, 0xC3, 0x43, 0xFE, 0xF6, 0x02, 0x03, 0x1B, 0xFF, 0x11,
+ 0x00, 0x2B, 0x00, 0xDE, 0xFF, 0x09, 0x00, 0x02, 0x00, 0x02, 0x00,
+ 0xCC, 0xFF, 0xCE, 0x00, 0xD1, 0xFD, 0x1D, 0x05, 0x91, 0xF3, 0xFE,
+ 0x3D, 0xD7, 0x1F, 0x87, 0xF3, 0xC3, 0x06, 0x42, 0xFC, 0xE5, 0x01,
+ 0x36, 0xFF, 0x36, 0x00, 0xFD, 0xFF, 0xFF, 0xFF, 0x2D, 0x00, 0x53,
+ 0xFF, 0x90, 0x01, 0x20, 0xFD, 0xB8, 0x04, 0x6A, 0xF8, 0xCD, 0x0E,
+ 0xE1, 0x46, 0xE1, 0xFA, 0xEB, 0x00, 0x51, 0x00, 0x65, 0xFF, 0x7F,
+ 0x00, 0xBE, 0xFF, 0x10, 0x00, 0xFF, 0xFF, 0x18, 0x00, 0x90, 0xFF,
+ 0x45, 0x01, 0x0B, 0xFD, 0x44, 0x06, 0x0A, 0xF2, 0x3B, 0x38, 0x80,
+ 0x27, 0x2B, 0xF2, 0x22, 0x07, 0x33, 0xFC, 0xDE, 0x01, 0x3E, 0xFF,
+ 0x34, 0x00, 0xFD, 0xFF, 0x00, 0x00, 0x24, 0x00, 0x6E, 0xFF, 0x49,
+ 0x01, 0xBC, 0xFD, 0x7A, 0x03, 0xFA, 0xFA, 0xFD, 0x07, 0x9C, 0x48,
+ 0xC3, 0xFF, 0x89, 0xFE, 0xA1, 0x01, 0xB1, 0xFE, 0xD6, 0x00, 0x9C,
+ 0xFF, 0x18, 0x00, 0xFD, 0xFF, 0x28, 0x00, 0x63, 0xFF, 0x9D, 0x01,
+ 0x84, 0xFC, 0xF3, 0x06, 0x7D, 0xF1, 0x9E, 0x31, 0xE6, 0x2E, 0x85,
+ 0xF1, 0x16, 0x07, 0x61, 0xFC, 0xB5, 0x01, 0x55, 0xFF, 0x2D, 0x00,
+ 0xFD, 0xFF, 0x1C, 0x00, 0x8F, 0xFF, 0xF7, 0x00, 0x6B, 0xFE, 0x25,
+ 0x02, 0x91, 0xFD, 0xE3, 0x01, 0xE5, 0x48, 0x8D, 0x05, 0xFB, 0xFB,
+ 0xF8, 0x02, 0xFE, 0xFD, 0x2B, 0x01, 0x7A, 0xFF, 0x21, 0x00, 0x00,
+ 0x00, 0xFD, 0xFF, 0x32, 0x00, 0x45, 0xFF, 0xD2, 0x01, 0x3D, 0xFC,
+ 0x2B, 0x07, 0xD4, 0xF1, 0x64, 0x2A, 0xC6, 0x35, 0xB7, 0xF1, 0x96,
+ 0x06, 0xCF, 0xFC, 0x6B, 0x01, 0x7D, 0xFF, 0x1F, 0x00, 0xFE, 0xFF,
+ 0x13, 0x00, 0xB1, 0xFF, 0xA0, 0x00, 0x20, 0xFF, 0xD0, 0x00, 0x07,
+ 0x00, 0xA4, 0xFC, 0xB6, 0x47, 0x1C, 0x0C, 0x63, 0xF9, 0x42, 0x04,
+ 0x59, 0xFD, 0x76, 0x01, 0x5D, 0xFF, 0x2A, 0x00, 0x00, 0x00, 0xFD,
+ 0xFF, 0x36, 0x00, 0x37, 0xFF, 0xE6, 0x01, 0x35, 0xFC, 0xF3, 0x06,
+ 0xEE, 0xF2, 0xCD, 0x22, 0xE4, 0x3B, 0xDC, 0xF2, 0x9C, 0x05, 0x7E,
+ 0xFD, 0x00, 0x01, 0xB4, 0xFF, 0x0B, 0x00, 0x01, 0x00, 0x0B, 0x00,
+ 0xD2, 0xFF, 0x4A, 0x00, 0xD0, 0xFF, 0x8E, 0xFF, 0x3F, 0x02, 0x5E,
+ 0xF8, 0x1E, 0x45, 0x44, 0x13, 0xEA, 0xF6, 0x67, 0x05, 0xCF, 0xFC,
+ 0xB3, 0x01, 0x46, 0xFF, 0x31, 0x00, 0xFF, 0xFF, 0xFE, 0xFF, 0x36,
+ 0x00, 0x38, 0xFF, 0xDB, 0x01, 0x67, 0xFC, 0x5A, 0x06, 0xA6, 0xF4,
+ 0x1B, 0x1B, 0x07, 0x41, 0x04, 0xF5, 0x2D, 0x04, 0x67, 0xFE, 0x77,
+ 0x00, 0xF8, 0xFF, 0xF2, 0xFF, 0x05, 0x00, 0x05, 0x00, 0xF0, 0xFF,
+ 0xFB, 0xFF, 0x71, 0x00, 0x71, 0xFE, 0x1D, 0x04, 0x1F, 0xF5, 0x32,
+ 0x41, 0xCE, 0x1A, 0xBA, 0xF4, 0x53, 0x06, 0x6A, 0xFC, 0xDA, 0x01,
+ 0x38, 0xFF, 0x35, 0x00, 0xFE, 0xFF, 0xFF, 0xFF, 0x31, 0x00, 0x45,
+ 0xFF, 0xB5, 0x01, 0xCA, 0xFC, 0x72, 0x05, 0xD3, 0xF6, 0x8D, 0x13,
+ 0xFD, 0x44, 0x39, 0xF8, 0x53, 0x02, 0x82, 0xFF, 0xD7, 0xFF, 0x47,
+ 0x00, 0xD3, 0xFF, 0x0B, 0x00, 0x01, 0x00, 0x0A, 0x00, 0xB6, 0xFF,
+ 0xFB, 0x00, 0x85, 0xFD, 0x90, 0x05, 0xEC, 0xF2, 0x1C, 0x3C, 0x81,
+ 0x22, 0xFC, 0xF2, 0xEF, 0x06, 0x36, 0xFC, 0xE6, 0x01, 0x37, 0xFF,
+ 0x36, 0x00, 0xFD, 0xFF, 0x00, 0x00, 0x2A, 0x00, 0x5C, 0xFF, 0x79,
+ 0x01, 0x53, 0xFD, 0x4E, 0x04, 0x4A, 0xF9, 0x60, 0x0C, 0xA3, 0x47,
+ 0x76, 0xFC, 0x1F, 0x00, 0xC3, 0x00, 0x27, 0xFF, 0x9D, 0x00, 0xB2,
+ 0xFF, 0x13, 0x00, 0xFE, 0xFF, 0x1E, 0x00, 0x7F, 0xFF, 0x67, 0x01,
+ 0xD5, 0xFC, 0x8E, 0x06, 0xBE, 0xF1, 0x06, 0x36, 0x1A, 0x2A, 0xDC,
+ 0xF1, 0x2A, 0x07, 0x3C, 0xFC, 0xD3, 0x01, 0x44, 0xFF, 0x32, 0x00,
+ 0xFD, 0xFF, 0x00, 0x00, 0x21, 0x00, 0x79, 0xFF, 0x2E, 0x01, 0xF7,
+ 0xFD, 0x05, 0x03, 0xE1, 0xFB, 0xCA, 0x05, 0xDF, 0x48, 0xAB, 0x01,
+ 0xAA, 0xFD, 0x18, 0x02, 0x72, 0xFE, 0xF4, 0x00, 0x90, 0xFF, 0x1B,
+ 0x00, 0xFD, 0xFF, 0x2C, 0x00, 0x57, 0xFF, 0xB3, 0x01, 0x64, 0xFC,
+ 0x13, 0x07, 0x83, 0xF1, 0x2C, 0x2F, 0x5A, 0x31, 0x7D, 0xF1, 0xF7,
+ 0x06, 0x80, 0xFC, 0x9F, 0x01, 0x61, 0xFF, 0x29, 0x00, 0xFD, 0xFF,
+ 0x19, 0x00, 0x9A, 0xFF, 0xD9, 0x00, 0xAA, 0xFE, 0xAE, 0x01, 0x70,
+ 0xFE, 0xF8, 0xFF, 0xA6, 0x48, 0xBE, 0x07, 0x14, 0xFB, 0x6D, 0x03,
+ 0xC3, 0xFD, 0x46, 0x01, 0x70, 0xFF, 0x24, 0x00, 0x00, 0x00, 0xFD,
+ 0xFF, 0x34, 0x00, 0x3F, 0xFF, 0xDD, 0x01, 0x34, 0xFC, 0x23, 0x07,
+ 0x21, 0xF2, 0xCB, 0x27, 0xFE, 0x37, 0x00, 0xF2, 0x4D, 0x06, 0x04,
+ 0xFD, 0x49, 0x01, 0x8E, 0xFF, 0x19, 0x00, 0xFF, 0xFF, 0x10, 0x00,
+ 0xBD, 0xFF, 0x82, 0x00, 0x5E, 0xFF, 0x5D, 0x00, 0xD4, 0x00, 0x0C,
+ 0xFB, 0xF9, 0x46, 0x87, 0x0E, 0x82, 0xF8, 0xAD, 0x04, 0x26, 0xFD,
+ 0x8D, 0x01, 0x54, 0xFF, 0x2C, 0x00, 0xFF, 0xFF, 0xFD, 0xFF, 0x36,
+ 0x00, 0x36, 0xFF, 0xE6, 0x01, 0x41, 0xFC, 0xC8, 0x06, 0x76, 0xF3,
+ 0x22, 0x20, 0xCA, 0x3D, 0x7D, 0xF3, 0x2A, 0x05, 0xC8, 0xFD, 0xD4,
+ 0x00, 0xCA, 0xFF, 0x03, 0x00, 0x02, 0x00, 0x09, 0x00, 0xDD, 0xFF,
+ 0x2E, 0x00, 0x0A, 0x00, 0x27, 0xFF, 0xEF, 0x02, 0x20, 0xF7, 0xE7,
+ 0x43, 0xD8, 0x15, 0x1E, 0xF6, 0xC0, 0x05, 0xA7, 0xFC, 0xC3, 0x01,
+ 0x40, 0xFF, 0x33, 0x00, 0xFF, 0xFF, 0xFE, 0xFF, 0x34, 0x00, 0x3B,
+ 0xFF, 0xD1, 0x01, 0x84, 0xFC, 0x12, 0x06, 0x5C, 0xF5, 0x76, 0x18,
+ 0x89, 0x42, 0x02, 0xF6, 0x94, 0x03, 0xC4, 0xFE, 0x42, 0x00, 0x12,
+ 0x00, 0xE8, 0xFF, 0x07, 0x00, 0x03, 0x00, 0xFA, 0xFF, 0xE2, 0xFF,
+ 0xA4, 0x00, 0x19, 0xFE, 0xAA, 0x04, 0x3E, 0xF4, 0x90, 0x3F, 0x78,
+ 0x1D, 0x10, 0xF4, 0x93, 0x06, 0x52, 0xFC, 0xE1, 0x01, 0x36, 0xFF,
+ 0x36, 0x00, 0xFE, 0xFF, 0xFF, 0xFF, 0x2F, 0x00, 0x4C, 0xFF, 0xA2,
+ 0x01, 0xF6, 0xFC, 0x12, 0x05, 0xA7, 0xF7, 0x03, 0x11, 0x10, 0x46,
+ 0x93, 0xF9, 0x98, 0x01, 0xEE, 0xFF, 0x9B, 0xFF, 0x64, 0x00, 0xC8,
+ 0xFF, 0x0E, 0x00, 0x00, 0x00, 0x12, 0x00, 0xA1, 0xFF, 0x24, 0x01,
+ 0x41, 0xFD, 0xF6, 0x05, 0x67, 0xF2, 0x1A, 0x3A, 0x29, 0x25, 0x84,
+ 0xF2, 0x0F, 0x07, 0x31, 0xFC, 0xE3, 0x01, 0x3A, 0xFF, 0x35, 0x00,
+ 0xFD, 0xFF, 0x00, 0x00, 0x27, 0x00, 0x65, 0xFF, 0x60, 0x01, 0x8A,
+ 0xFD, 0xDF, 0x03, 0x2E, 0xFA, 0x04, 0x0A, 0x3A, 0x48, 0x28, 0xFE,
+ 0x4B, 0xFF, 0x38, 0x01, 0xE9, 0xFE, 0xBB, 0x00, 0xA6, 0xFF, 0x16,
+ 0x00, 0xFD, 0xFF, 0x24, 0x00, 0x6F, 0xFF, 0x85, 0x01, 0xA6, 0xFC,
+ 0xCA, 0x06, 0x8F, 0xF1, 0xBB, 0x33, 0xAB, 0x2C, 0xA3, 0xF1, 0x26,
+ 0x07, 0x4C, 0xFC, 0xC5, 0x01, 0x4D, 0xFF, 0x30, 0x00, 0xFD, 0xFF,
+ 0x00, 0x00, 0x1E, 0x00, 0x84, 0xFF, 0x11, 0x01, 0x34, 0xFE, 0x8F,
+ 0x02, 0xC7, 0xFC, 0xAE, 0x03, 0xF7, 0x48, 0xAE, 0x03, 0xC7, 0xFC,
+ 0x8F, 0x02, 0x34, 0xFE, 0x11, 0x01, 0x84, 0xFF, 0x1E, 0x00, 0xFD,
+ 0xFF, 0x2A, 0x00, 0x5C, 0xFF, 0xAA, 0x01, 0x71, 0xFC, 0x07, 0x07,
+ 0x7E, 0xF1, 0x44, 0x30, 0x44, 0x30, 0x7E, 0xF1, 0x07, 0x07, 0x71,
+ 0xFC, 0xAA, 0x01, 0x5C, 0xFF, 0x2A, 0x00, 0xFD, 0xFF, 0x00, 0x00,
+ 0x1E, 0x00, 0x84, 0xFF, 0x11, 0x01, 0x34, 0xFE, 0x8F, 0x02, 0xC7,
+ 0xFC, 0xAE, 0x03, 0xF7, 0x48, 0xAE, 0x03, 0xC7, 0xFC, 0x8F, 0x02,
+ 0x34, 0xFE, 0x11, 0x01, 0x84, 0xFF, 0x1E, 0x00, 0x02, 0x00, 0x05,
+ 0x00, 0xC3, 0xFF, 0xE1, 0x00, 0xB1, 0xFD, 0x4E, 0x05, 0x4A, 0xF3,
+ 0x3D, 0x3D, 0xED, 0x20, 0x4C, 0xF3, 0xD6, 0x06, 0x3D, 0xFC, 0xE6,
+ 0x01, 0x36, 0xFF, 0x36, 0x00, 0xFD, 0xFF, 0xFD, 0xFF, 0x36, 0x00,
+ 0x36, 0xFF, 0xE6, 0x01, 0x3D, 0xFC, 0xD6, 0x06, 0x4C, 0xF3, 0xED,
+ 0x20, 0x3D, 0x3D, 0x4A, 0xF3, 0x4E, 0x05, 0xB1, 0xFD, 0xE1, 0x00,
+ 0xC3, 0xFF, 0x05, 0x00, 0x02, 0x00, 0x00, 0x00, 0x1E, 0x00, 0x84,
+ 0xFF, 0x11, 0x01, 0x34, 0xFE, 0x8F, 0x02, 0xC7, 0xFC, 0xAE, 0x03,
+ 0xF7, 0x48, 0xAE, 0x03, 0xC7, 0xFC, 0x8F, 0x02, 0x34, 0xFE, 0x11,
+ 0x01, 0x84, 0xFF, 0x1E, 0x00, 0x16, 0x00, 0xA6, 0xFF, 0xBB, 0x00,
+ 0xE9, 0xFE, 0x38, 0x01, 0x4B, 0xFF, 0x28, 0xFE, 0x3A, 0x48, 0x04,
+ 0x0A, 0x2E, 0xFA, 0xDF, 0x03, 0x8A, 0xFD, 0x60, 0x01, 0x65, 0xFF,
+ 0x27, 0x00, 0x00, 0x00, 0x0E, 0x00, 0xC8, 0xFF, 0x64, 0x00, 0x9B,
+ 0xFF, 0xEE, 0xFF, 0x98, 0x01, 0x93, 0xF9, 0x10, 0x46, 0x03, 0x11,
+ 0xA7, 0xF7, 0x12, 0x05, 0xF6, 0xFC, 0xA2, 0x01, 0x4C, 0xFF, 0x2F,
+ 0x00, 0xFF, 0xFF, 0x07, 0x00, 0xE8, 0xFF, 0x12, 0x00, 0x42, 0x00,
+ 0xC4, 0xFE, 0x94, 0x03, 0x02, 0xF6, 0x89, 0x42, 0x76, 0x18, 0x5C,
+ 0xF5, 0x12, 0x06, 0x84, 0xFC, 0xD1, 0x01, 0x3B, 0xFF, 0x34, 0x00,
+ 0xFE, 0xFF, 0x02, 0x00, 0x03, 0x00, 0xCA, 0xFF, 0xD4, 0x00, 0xC8,
+ 0xFD, 0x2A, 0x05, 0x7D, 0xF3, 0xCA, 0x3D, 0x22, 0x20, 0x76, 0xF3,
+ 0xC8, 0x06, 0x41, 0xFC, 0xE6, 0x01, 0x36, 0xFF, 0x36, 0x00, 0xFD,
+ 0xFF, 0xFF, 0xFF, 0x19, 0x00, 0x8E, 0xFF, 0x49, 0x01, 0x04, 0xFD,
+ 0x4D, 0x06, 0x00, 0xF2, 0xFE, 0x37, 0xCB, 0x27, 0x21, 0xF2, 0x23,
+ 0x07, 0x34, 0xFC, 0xDD, 0x01, 0x3F, 0xFF, 0x34, 0x00, 0xFD, 0xFF,
+ 0xFD, 0xFF, 0x29, 0x00, 0x61, 0xFF, 0x9F, 0x01, 0x80, 0xFC, 0xF7,
+ 0x06, 0x7D, 0xF1, 0x5A, 0x31, 0x2C, 0x2F, 0x83, 0xF1, 0x13, 0x07,
+ 0x64, 0xFC, 0xB3, 0x01, 0x57, 0xFF, 0x2C, 0x00, 0xFD, 0xFF, 0xFD,
+ 0xFF, 0x32, 0x00, 0x44, 0xFF, 0xD3, 0x01, 0x3C, 0xFC, 0x2A, 0x07,
+ 0xDC, 0xF1, 0x1A, 0x2A, 0x06, 0x36, 0xBE, 0xF1, 0x8E, 0x06, 0xD5,
+ 0xFC, 0x67, 0x01, 0x7F, 0xFF, 0x1E, 0x00, 0xFE, 0xFF, 0xFD, 0xFF,
+ 0x36, 0x00, 0x37, 0xFF, 0xE6, 0x01, 0x36, 0xFC, 0xEF, 0x06, 0xFC,
+ 0xF2, 0x81, 0x22, 0x1C, 0x3C, 0xEC, 0xF2, 0x90, 0x05, 0x85, 0xFD,
+ 0xFB, 0x00, 0xB6, 0xFF, 0x0A, 0x00, 0x01, 0x00, 0xFE, 0xFF, 0x35,
+ 0x00, 0x38, 0xFF, 0xDA, 0x01, 0x6A, 0xFC, 0x53, 0x06, 0xBA, 0xF4,
+ 0xCE, 0x1A, 0x32, 0x41, 0x1F, 0xF5, 0x1D, 0x04, 0x71, 0xFE, 0x71,
+ 0x00, 0xFB, 0xFF, 0xF0, 0xFF, 0x05, 0x00, 0xFF, 0xFF, 0x31, 0x00,
+ 0x46, 0xFF, 0xB3, 0x01, 0xCF, 0xFC, 0x67, 0x05, 0xEA, 0xF6, 0x44,
+ 0x13, 0x1E, 0x45, 0x5E, 0xF8, 0x3F, 0x02, 0x8E, 0xFF, 0xD0, 0xFF,
+ 0x4A, 0x00, 0xD2, 0xFF, 0x0B, 0x00, 0x00, 0x00, 0x2A, 0x00, 0x5D,
+ 0xFF, 0x76, 0x01, 0x59, 0xFD, 0x42, 0x04, 0x63, 0xF9, 0x1C, 0x0C,
+ 0xB6, 0x47, 0xA4, 0xFC, 0x07, 0x00, 0xD0, 0x00, 0x20, 0xFF, 0xA0,
+ 0x00, 0xB1, 0xFF, 0x13, 0x00, 0x00, 0x00, 0x21, 0x00, 0x7A, 0xFF,
+ 0x2B, 0x01, 0xFE, 0xFD, 0xF8, 0x02, 0xFB, 0xFB, 0x8D, 0x05, 0xE5,
+ 0x48, 0xE3, 0x01, 0x91, 0xFD, 0x25, 0x02, 0x6B, 0xFE, 0xF7, 0x00,
+ 0x8F, 0xFF, 0x1C, 0x00, 0x18, 0x00, 0x9C, 0xFF, 0xD6, 0x00, 0xB1,
+ 0xFE, 0xA1, 0x01, 0x89, 0xFE, 0xC3, 0xFF, 0x9C, 0x48, 0xFD, 0x07,
+ 0xFA, 0xFA, 0x7A, 0x03, 0xBC, 0xFD, 0x49, 0x01, 0x6E, 0xFF, 0x24,
+ 0x00, 0x00, 0x00, 0x10, 0x00, 0xBE, 0xFF, 0x7F, 0x00, 0x65, 0xFF,
+ 0x51, 0x00, 0xEB, 0x00, 0xE1, 0xFA, 0xE1, 0x46, 0xCD, 0x0E, 0x6A,
+ 0xF8, 0xB8, 0x04, 0x20, 0xFD, 0x90, 0x01, 0x53, 0xFF, 0x2D, 0x00,
+ 0xFF, 0xFF, 0x09, 0x00, 0xDE, 0xFF, 0x2B, 0x00, 0x11, 0x00, 0x1B,
+ 0xFF, 0x02, 0x03, 0xFE, 0xF6, 0xC3, 0x43, 0x22, 0x16, 0x07, 0xF6,
+ 0xCA, 0x05, 0xA3, 0xFC, 0xC5, 0x01, 0x3F, 0xFF, 0x33, 0x00, 0xFF,
+ 0xFF, 0x03, 0x00, 0xFB, 0xFF, 0xDF, 0xFF, 0xA9, 0x00, 0x10, 0xFE,
+ 0xB9, 0x04, 0x27, 0xF4, 0x5E, 0x3F, 0xC3, 0x1D, 0xFE, 0xF3, 0x99,
+ 0x06, 0x50, 0xFC, 0xE2, 0x01, 0x36, 0xFF, 0x36, 0x00, 0xFE, 0xFF,
+ 0x00, 0x00, 0x13, 0x00, 0x9F, 0xFF, 0x28, 0x01, 0x3A, 0xFD, 0x00,
+ 0x06, 0x5A, 0xF2, 0xDF, 0x39, 0x73, 0x25, 0x79, 0xF2, 0x12, 0x07,
+ 0x31, 0xFC, 0xE3, 0x01, 0x3B, 0xFF, 0x35, 0x00, 0xFD, 0xFF, 0xFD,
+ 0xFF, 0x24, 0x00, 0x6D, 0xFF, 0x88, 0x01, 0xA2, 0xFC, 0xD0, 0x06,
+ 0x8C, 0xF1, 0x78, 0x33, 0xF2, 0x2C, 0x9E, 0xF1, 0x24, 0x07, 0x4E,
+ 0xFC, 0xC3, 0x01, 0x4E, 0xFF, 0x2F, 0x00, 0xFD, 0xFF, 0xFD, 0xFF,
+ 0x30, 0x00, 0x4C, 0xFF, 0xC7, 0x01, 0x4A, 0xFC, 0x27, 0x07, 0xA8,
+ 0xF1, 0x62, 0x2C, 0xFD, 0x33, 0x93, 0xF1, 0xC4, 0x06, 0xAB, 0xFC,
+ 0x82, 0x01, 0x71, 0xFF, 0x23, 0x00, 0xFE, 0xFF, 0xFD, 0xFF, 0x36,
+ 0x00, 0x3A, 0xFF, 0xE4, 0x01, 0x32, 0xFC, 0x0C, 0x07, 0x91, 0xF2,
+ 0xDD, 0x24, 0x54, 0x3A, 0x74, 0xF2, 0xEB, 0x05, 0x49, 0xFD, 0x20,
+ 0x01, 0xA3, 0xFF, 0x11, 0x00, 0x00, 0x00, 0xFE, 0xFF, 0x36, 0x00,
+ 0x37, 0xFF, 0xE1, 0x01, 0x55, 0xFC, 0x8C, 0x06, 0x22, 0xF4, 0x2C,
+ 0x1D, 0xC0, 0x3F, 0x55, 0xF4, 0x9B, 0x04, 0x23, 0xFE, 0x9F, 0x00,
+ 0xE4, 0xFF, 0xF9, 0xFF, 0x04, 0x00, 0xFF, 0xFF, 0x33, 0x00, 0x40,
+ 0xFF, 0xC1, 0x01, 0xAB, 0xFC, 0xB7, 0x05, 0x34, 0xF6, 0x8E, 0x15,
+ 0x0B, 0x44, 0x42, 0xF7, 0xDC, 0x02, 0x32, 0xFF, 0x04, 0x00, 0x31,
+ 0x00, 0xDC, 0xFF, 0x09, 0x00, 0xFF, 0xFF, 0x2C, 0x00, 0x55, 0xFF,
+ 0x8B, 0x01, 0x2B, 0xFD, 0xA1, 0x04, 0x9B, 0xF8, 0x42, 0x0E, 0x0F,
+ 0x47, 0x38, 0xFB, 0xBE, 0x00, 0x6A, 0x00, 0x58, 0xFF, 0x85, 0x00,
+ 0xBB, 0xFF, 0x10, 0x00, 0x00, 0x00, 0x24, 0x00, 0x71, 0xFF, 0x43,
+ 0x01, 0xC9, 0xFD, 0x60, 0x03, 0x2E, 0xFB, 0x7E, 0x07, 0xAF, 0x48,
+ 0x2D, 0x00, 0x58, 0xFE, 0xBB, 0x01, 0xA3, 0xFE, 0xDD, 0x00, 0x99,
+ 0xFF, 0x19, 0x00, 0x1B, 0x00, 0x91, 0xFF, 0xF1, 0x00, 0x79, 0xFE,
+ 0x0A, 0x02, 0xC3, 0xFD, 0x73, 0x01, 0xDB, 0x48, 0x07, 0x06, 0xC7,
+ 0xFB, 0x12, 0x03, 0xF1, 0xFD, 0x31, 0x01, 0x78, 0xFF, 0x22, 0x00,
+ 0x00, 0x00, 0x12, 0x00, 0xB3, 0xFF, 0x99, 0x00, 0x2E, 0xFF, 0xB6,
+ 0x00, 0x36, 0x00, 0x47, 0xFC, 0x90, 0x47, 0xA4, 0x0C, 0x31, 0xF9,
+ 0x5A, 0x04, 0x4E, 0xFD, 0x7C, 0x01, 0x5B, 0xFF, 0x2A, 0x00, 0x00,
+ 0x00, 0x0B, 0x00, 0xD5, 0xFF, 0x44, 0x00, 0xDD, 0xFF, 0x77, 0xFF,
+ 0x67, 0x02, 0x14, 0xF8, 0xDC, 0x44, 0xD5, 0x13, 0xBC, 0xF6, 0x7C,
+ 0x05, 0xC5, 0xFC, 0xB7, 0x01, 0x44, 0xFF, 0x31, 0x00, 0xFF, 0xFF,
+ 0x05, 0x00, 0xF3, 0xFF, 0xF5, 0xFF, 0x7D, 0x00, 0x5D, 0xFE, 0x3E,
+ 0x04, 0xEA, 0xF4, 0xD9, 0x40, 0x66, 0x1B, 0x93, 0xF4, 0x62, 0x06,
+ 0x64, 0xFC, 0xDC, 0x01, 0x38, 0xFF, 0x36, 0x00, 0xFE, 0xFF, 0x00,
+ 0x00, 0x0C, 0x00, 0xB1, 0xFF, 0x04, 0x01, 0x76, 0xFD, 0xA8, 0x05,
+ 0xCC, 0xF2, 0xAB, 0x3B, 0x18, 0x23, 0xE0, 0xF2, 0xF7, 0x06, 0x35,
+ 0xFC, 0xE6, 0x01, 0x38, 0xFF, 0x36, 0x00, 0xFD, 0xFF, 0xFE, 0xFF,
+ 0x20, 0x00, 0x7B, 0xFF, 0x6E, 0x01, 0xCA, 0xFC, 0x9D, 0x06, 0xB1,
+ 0xF1, 0x86, 0x35, 0xAE, 0x2A, 0xCD, 0xF1, 0x2B, 0x07, 0x3F, 0xFC,
+ 0xD1, 0x01, 0x46, 0xFF, 0x32, 0x00, 0xFD, 0xFF, 0xFD, 0xFF, 0x2D,
+ 0x00, 0x54, 0xFF, 0xB7, 0x01, 0x5E, 0xFC, 0x19, 0x07, 0x88, 0xF1,
+ 0x9F, 0x2E, 0xE3, 0x31, 0x7E, 0xF1, 0xEE, 0x06, 0x88, 0xFC, 0x9A,
+ 0x01, 0x64, 0xFF, 0x28, 0x00, 0xFD, 0xFF, 0xFD, 0xFF, 0x34, 0x00,
+ 0x3E, 0xFF, 0xDF, 0x01, 0x33, 0xFC, 0x20, 0x07, 0x35, 0xF2, 0x36,
+ 0x27, 0x78, 0x38, 0x14, 0xF2, 0x3B, 0x06, 0x11, 0xFD, 0x41, 0x01,
+ 0x92, 0xFF, 0x17, 0x00, 0xFF, 0xFF, 0xFD, 0xFF, 0x36, 0x00, 0x36,
+ 0xFF, 0xE5, 0x01, 0x44, 0xFC, 0xBD, 0x06, 0x97, 0xF3, 0x8A, 0x1F,
+ 0x31, 0x3E, 0xA5, 0xF3, 0x0F, 0x05, 0xDA, 0xFD, 0xC9, 0x00, 0xCF,
+ 0xFF, 0x01, 0x00, 0x02, 0x00, 0xFE, 0xFF, 0x34, 0x00, 0x3C, 0xFF,
+ 0xCE, 0x01, 0x8C, 0xFC, 0x00, 0x06, 0x86, 0xF5, 0xE0, 0x17, 0xDB,
+ 0x42, 0x3F, 0xF6, 0x71, 0x03, 0xD9, 0xFE, 0x36, 0x00, 0x18, 0x00,
+ 0xE5, 0xFF, 0x07, 0x00, 0xFF, 0xFF, 0x2E, 0x00, 0x4E, 0xFF, 0x9E,
+ 0x01, 0x00, 0xFD, 0xFC, 0x04, 0xD7, 0xF7, 0x75, 0x10, 0x48, 0x46,
+ 0xE4, 0xF9, 0x6E, 0x01, 0x06, 0x00, 0x8E, 0xFF, 0x6B, 0x00, 0xC6,
+ 0xFF, 0x0E, 0x00, 0x00, 0x00, 0x26, 0x00, 0x68, 0xFF, 0x5B, 0x01,
+ 0x96, 0xFD, 0xC6, 0x03, 0x61, 0xFA, 0x81, 0x09, 0x57, 0x48, 0x8D,
+ 0xFE, 0x1B, 0xFF, 0x52, 0x01, 0xDB, 0xFE, 0xC2, 0x00, 0xA4, 0xFF,
+ 0x16, 0x00, 0x1E, 0x00, 0x87, 0xFF, 0x0B, 0x01, 0x42, 0xFE, 0x74,
+ 0x02, 0xF9, 0xFC, 0x39, 0x03, 0xF5, 0x48, 0x24, 0x04, 0x94, 0xFC,
+ 0xA9, 0x02, 0x27, 0xFE, 0x18, 0x01, 0x82, 0xFF, 0x1F, 0x00, 0x00,
+ 0x00, 0x15, 0x00, 0xA9, 0xFF, 0xB4, 0x00, 0xF7, 0xFE, 0x1D, 0x01,
+ 0x7A, 0xFF, 0xC5, 0xFD, 0x1D, 0x48, 0x89, 0x0A, 0xFB, 0xF9, 0xF8,
+ 0x03, 0x7D, 0xFD, 0x66, 0x01, 0x63, 0xFF, 0x28, 0x00, 0x00, 0x00,
+ 0x0D, 0x00, 0xCB, 0xFF, 0x5E, 0x00, 0xA9, 0xFF, 0xD6, 0xFF, 0xC3,
+ 0x01, 0x43, 0xF9, 0xD7, 0x45, 0x92, 0x11, 0x77, 0xF7, 0x28, 0x05,
+ 0xEC, 0xFC, 0xA7, 0x01, 0x4A, 0xFF, 0x2F, 0x00, 0xFF, 0xFF, 0x06,
+ 0x00, 0xEA, 0xFF, 0x0C, 0x00, 0x4E, 0x00, 0xAF, 0xFE, 0xB8, 0x03,
+ 0xC7, 0xF5, 0x38, 0x42, 0x0C, 0x19, 0x32, 0xF5, 0x23, 0x06, 0x7D,
+ 0xFC, 0xD3, 0x01, 0x3A, 0xFF, 0x35, 0x00, 0xFE, 0xFF, 0x02, 0x00,
+ 0x05, 0x00, 0xC5, 0xFF, 0xDE, 0x00, 0xB7, 0xFD, 0x45, 0x05, 0x56,
+ 0xF3, 0x61, 0x3D, 0xBA, 0x20, 0x56, 0xF3, 0xD3, 0x06, 0x3E, 0xFC,
+ 0xE6, 0x01, 0x36, 0xFF, 0x36, 0x00, 0xFD, 0xFF, 0xFF, 0xFF, 0x1A,
+ 0x00, 0x8A, 0xFF, 0x51, 0x01, 0xF8, 0xFC, 0x5E, 0x06, 0xED, 0xF1,
+ 0x82, 0x37, 0x60, 0x28, 0x0E, 0xF2, 0x26, 0x07, 0x35, 0xFC, 0xDB,
+ 0x01, 0x40, 0xFF, 0x34, 0x00, 0xFD, 0xFF, 0xFD, 0xFF, 0x29, 0x00,
+ 0x5F, 0xFF, 0xA5, 0x01, 0x78, 0xFC, 0xFF, 0x06, 0x7D, 0xF1, 0xCF,
+ 0x30, 0xB8, 0x2F, 0x80, 0xF1, 0x0D, 0x07, 0x6A, 0xFC, 0xAE, 0x01,
+ 0x59, 0xFF, 0x2B, 0x00, 0xFD, 0xFF, 0xFD, 0xFF, 0x33, 0x00, 0x43,
+ 0xFF, 0xD6, 0x01, 0x39, 0xFC, 0x2A, 0x07, 0xEB, 0xF1, 0x87, 0x29,
+ 0x85, 0x36, 0xCC, 0xF1, 0x7F, 0x06, 0xE0, 0xFC, 0x60, 0x01, 0x82,
+ 0xFF, 0x1D, 0x00, 0xFE, 0xFF, 0xFD, 0xFF, 0x36, 0x00, 0x37, 0xFF,
+ 0xE6, 0x01, 0x38, 0xFC, 0xE6, 0x06, 0x19, 0xF3, 0xEA, 0x21, 0x8A,
+ 0x3C, 0x0E, 0xF3, 0x78, 0x05, 0x96, 0xFD, 0xF1, 0x00, 0xBB, 0xFF,
+ 0x08, 0x00, 0x01, 0x00, 0xFE, 0xFF, 0x35, 0x00, 0x39, 0xFF, 0xD8,
+ 0x01, 0x70, 0xFC, 0x43, 0x06, 0xE1, 0xF4, 0x38, 0x1A, 0x8C, 0x41,
+ 0x55, 0xF5, 0xFC, 0x03, 0x85, 0xFE, 0x66, 0x00, 0x01, 0x00, 0xEE,
+ 0xFF, 0x06, 0x00, 0xFF, 0xFF, 0x30, 0x00, 0x47, 0xFF, 0xAF, 0x01,
+ 0xD8, 0xFC, 0x52, 0x05, 0x19, 0xF7, 0xB2, 0x12, 0x5C, 0x45, 0xA9,
+ 0xF8, 0x16, 0x02, 0xA6, 0xFF, 0xC3, 0xFF, 0x51, 0x00, 0xD0, 0xFF,
+ 0x0C, 0x00, 0x00, 0x00, 0x29, 0x00, 0x5F, 0xFF, 0x71, 0x01, 0x65,
+ 0xFD, 0x29, 0x04, 0x96, 0xF9, 0x95, 0x0B, 0xDC, 0x47, 0x03, 0xFD,
+ 0xD9, 0xFF, 0xEA, 0x00, 0x12, 0xFF, 0xA7, 0x00, 0xAE, 0xFF, 0x14,
+ 0x00, 0x00, 0x00, 0x20, 0x00, 0x7D, 0xFF, 0x24, 0x01, 0x0C, 0xFE,
+ 0xDE, 0x02, 0x2E, 0xFC, 0x13, 0x05, 0xEC, 0x48, 0x54, 0x02, 0x5E,
+ 0xFD, 0x3F, 0x02, 0x5D, 0xFE, 0xFE, 0x00, 0x8C, 0xFF, 0x1C, 0x00,
+ 0x17, 0x00, 0x9E, 0xFF, 0xCF, 0x00, 0xBF, 0xFE, 0x86, 0x01, 0xBA,
+ 0xFE, 0x5A, 0xFF, 0x86, 0x48, 0x7D, 0x08, 0xC7, 0xFA, 0x93, 0x03,
+ 0xB0, 0xFD, 0x4F, 0x01, 0x6C, 0xFF, 0x25, 0x00, 0x00, 0x00, 0x0F,
+ 0x00, 0xC0, 0xFF, 0x78, 0x00, 0x73, 0xFF, 0x38, 0x00, 0x17, 0x01,
+ 0x8B, 0xFA, 0xAF, 0x46, 0x59, 0x0F, 0x39, 0xF8, 0xCF, 0x04, 0x15,
+ 0xFD, 0x95, 0x01, 0x51, 0xFF, 0x2D, 0x00, 0xFF, 0xFF, 0x08, 0x00,
+ 0xE1, 0xFF, 0x25, 0x00, 0x1D, 0x00, 0x05, 0xFF, 0x28, 0x03, 0xBD,
+ 0xF6, 0x77, 0x43, 0xB6, 0x16, 0xDC, 0xF5, 0xDD, 0x05, 0x9B, 0xFC,
+ 0xC8, 0x01, 0x3E, 0xFF, 0x33, 0x00, 0xFF, 0xFF, 0x03, 0x00, 0xFD,
+ 0xFF, 0xD9, 0xFF, 0xB4, 0x00, 0xFD, 0xFD, 0xD7, 0x04, 0xFA, 0xF3,
+ 0xFC, 0x3E, 0x5B, 0x1E, 0xDB, 0xF3, 0xA6, 0x06, 0x4C, 0xFC, 0xE3,
+ 0x01, 0x36, 0xFF, 0x36, 0x00, 0xFE, 0xFF, 0xFF, 0xFF, 0x14, 0x00,
+ 0x9B, 0xFF, 0x31, 0x01, 0x2C, 0xFD, 0x15, 0x06, 0x41, 0xF2, 0x6A,
+ 0x39, 0x0A, 0x26, 0x61, 0xF2, 0x17, 0x07, 0x31, 0xFC, 0xE2, 0x01,
+ 0x3B, 0xFF, 0x35, 0x00, 0xFD, 0xFF, 0xFD, 0xFF, 0x25, 0x00, 0x6A,
+ 0xFF, 0x8E, 0x01, 0x99, 0xFC, 0xDB, 0x06, 0x86, 0xF1, 0xF2, 0x32,
+ 0x82, 0x2D, 0x96, 0xF1, 0x21, 0x07, 0x53, 0xFC, 0xC0, 0x01, 0x50,
+ 0xFF, 0x2E, 0x00, 0xFD, 0xFF, 0xFD, 0xFF, 0x30, 0x00, 0x4A, 0xFF,
+ 0xCA, 0x01, 0x46, 0xFC, 0x29, 0x07, 0xB3, 0xF1, 0xD1, 0x2B, 0x81,
+ 0x34, 0x9C, 0xF1, 0xB8, 0x06, 0xB5, 0xFC, 0x7C, 0x01, 0x74, 0xFF,
+ 0x22, 0x00, 0xFE, 0xFF, 0xFD, 0xFF, 0x36, 0x00, 0x39, 0xFF, 0xE5,
+ 0x01, 0x32, 0xFC, 0x06, 0x07, 0xAA, 0xF2, 0x46, 0x24, 0xC8, 0x3A,
+ 0x90, 0xF2, 0xD6, 0x05, 0x57, 0xFD, 0x17, 0x01, 0xA8, 0xFF, 0x0F,
+ 0x00, 0x00, 0x00, 0xFE, 0xFF, 0x36, 0x00, 0x37, 0xFF, 0xDF, 0x01,
+ 0x5A, 0xFC, 0x7E, 0x06, 0x47, 0xF4, 0x94, 0x1C, 0x1F, 0x40, 0x85,
+ 0xF4, 0x7D, 0x04, 0x36, 0xFE, 0x93, 0x00, 0xEA, 0xFF, 0xF7, 0xFF,
+ 0x04, 0x00, 0xFF, 0xFF, 0x32, 0x00, 0x42, 0xFF, 0xBE, 0x01, 0xB4,
+ 0xFC, 0xA4, 0x05, 0x61, 0xF6, 0xFB, 0x14, 0x53, 0x44, 0x86, 0xF7,
+ 0xB6, 0x02, 0x49, 0xFF, 0xF7, 0xFF, 0x37, 0x00, 0xD9, 0xFF, 0x0A,
+ 0x00, 0x00, 0x00, 0x2B, 0x00, 0x57, 0xFF, 0x86, 0x01, 0x36, 0xFD,
+ 0x89, 0x04, 0xCD, 0xF8, 0xB7, 0x0D, 0x3D, 0x47, 0x91, 0xFB, 0x91,
+ 0x00, 0x83, 0x00, 0x4A, 0xFF, 0x8C, 0x00, 0xB9, 0xFF, 0x11, 0x00,
+ 0x00, 0x00, 0x23, 0x00, 0x73, 0xFF, 0x3D, 0x01, 0xD6, 0xFD, 0x46,
+ 0x03, 0x61, 0xFB, 0x00, 0x07, 0xBF, 0x48, 0x98, 0x00, 0x26, 0xFE,
+ 0xD5, 0x01, 0x95, 0xFE, 0xE3, 0x00, 0x96, 0xFF, 0x1A, 0x00, 0x1A,
+ 0x00, 0x94, 0xFF, 0xEA, 0x00, 0x87, 0xFE, 0xF0, 0x01, 0xF5, 0xFD,
+ 0x05, 0x01, 0xCE, 0x48, 0x83, 0x06, 0x94, 0xFB, 0x2C, 0x03, 0xE4,
+ 0xFD, 0x37, 0x01, 0x76, 0xFF, 0x22, 0x00, 0x00, 0x00, 0x12, 0x00,
+ 0xB6, 0xFF, 0x93, 0x00, 0x3C, 0xFF, 0x9D, 0x00, 0x63, 0x00, 0xEB,
+ 0xFB, 0x69, 0x47, 0x2D, 0x0D, 0xFF, 0xF8, 0x72, 0x04, 0x42, 0xFD,
+ 0x81, 0x01, 0x59, 0xFF, 0x2B, 0x00, 0x00, 0x00, 0x0A, 0x00, 0xD7,
+ 0xFF, 0x3E, 0x00, 0xEA, 0xFF, 0x60, 0xFF, 0x8F, 0x02, 0xCD, 0xF7,
+ 0x99, 0x44, 0x68, 0x14, 0x8E, 0xF6, 0x90, 0x05, 0xBC, 0xFC, 0xBA,
+ 0x01, 0x43, 0xFF, 0x32, 0x00, 0xFF, 0xFF, 0x04, 0x00, 0xF5, 0xFF,
+ 0xEF, 0xFF, 0x88, 0x00, 0x49, 0xFE, 0x5D, 0x04, 0xB7, 0xF4, 0x7D,
+ 0x40, 0xFD, 0x1B, 0x6C, 0xF4, 0x70, 0x06, 0x5F, 0xFC, 0xDE, 0x01,
+ 0x37, 0xFF, 0x36, 0x00, 0xFE, 0xFF, 0x00, 0x00, 0x0E, 0x00, 0xAC,
+ 0xFF, 0x0E, 0x01, 0x66, 0xFD, 0xBF, 0x05, 0xAD, 0xF2, 0x3B, 0x3B,
+ 0xB0, 0x23, 0xC4, 0xF2, 0xFF, 0x06, 0x33, 0xFC, 0xE5, 0x01, 0x38,
+ 0xFF, 0x36, 0x00, 0xFD, 0xFF, 0xFE, 0xFF, 0x21, 0x00, 0x77, 0xFF,
+ 0x75, 0x01, 0xBF, 0xFC, 0xAB, 0x06, 0xA6, 0xF1, 0x05, 0x35, 0x40,
+ 0x2B, 0xBF, 0xF1, 0x2A, 0x07, 0x42, 0xFC, 0xCE, 0x01, 0x48, 0xFF,
+ 0x31, 0x00, 0xFD, 0xFF, 0xFD, 0xFF, 0x2E, 0x00, 0x52, 0xFF, 0xBC,
+ 0x01, 0x58, 0xFC, 0x1D, 0x07, 0x8E, 0xF1, 0x11, 0x2E, 0x6B, 0x32,
+ 0x81, 0xF1, 0xE5, 0x06, 0x90, 0xFC, 0x94, 0x01, 0x67, 0xFF, 0x26,
+ 0x00, 0xFD, 0xFF, 0xFD, 0xFF, 0x35, 0x00, 0x3C, 0xFF, 0xE0, 0x01,
+ 0x32, 0xFC, 0x1C, 0x07, 0x4B, 0xF2, 0xA0, 0x26, 0xF2, 0x38, 0x2A,
+ 0xF2, 0x28, 0x06, 0x1F, 0xFD, 0x39, 0x01, 0x96, 0xFF, 0x16, 0x00,
+ 0xFF, 0xFF, 0xFE, 0xFF, 0x36, 0x00, 0x36, 0xFF, 0xE4, 0x01, 0x48,
+ 0xFC, 0xB2, 0x06, 0xB9, 0xF3, 0xF3, 0x1E, 0x98, 0x3E, 0xCF, 0xF3,
+ 0xF3, 0x04, 0xEB, 0xFD, 0xBF, 0x00, 0xD4, 0xFF, 0xFF, 0xFF, 0x03,
+ 0x00, 0xFE, 0xFF, 0x34, 0x00, 0x3D, 0xFF, 0xCB, 0x01, 0x93, 0xFC,
+ 0xEF, 0x05, 0xB0, 0xF5, 0x4B, 0x17, 0x2A, 0x43, 0x7D, 0xF6, 0x4D,
+ 0x03, 0xEF, 0xFE, 0x2A, 0x00, 0x1E, 0x00, 0xE3, 0xFF, 0x08, 0x00,
+ 0xFF, 0xFF, 0x2E, 0x00, 0x4F, 0xFF, 0x99, 0x01, 0x0B, 0xFD, 0xE6,
+ 0x04, 0x08, 0xF8, 0xE7, 0x0F, 0x7C, 0x46, 0x37, 0xFA, 0x42, 0x01,
+ 0x1F, 0x00, 0x81, 0xFF, 0x71, 0x00, 0xC3, 0xFF, 0x0F, 0x00, 0x00,
+ 0x00, 0x26, 0x00, 0x6A, 0xFF, 0x55, 0x01, 0xA3, 0xFD, 0xAD, 0x03,
+ 0x94, 0xFA, 0xFF, 0x08, 0x70, 0x48, 0xF3, 0xFE, 0xEA, 0xFE, 0x6C,
+ 0x01, 0xCD, 0xFE, 0xC9, 0x00, 0xA1, 0xFF, 0x17, 0x00, 0x1D, 0x00,
+ 0x8A, 0xFF, 0x04, 0x01, 0x50, 0xFE, 0x5A, 0x02, 0x2C, 0xFD, 0xC6,
+ 0x02, 0xF2, 0x48, 0x9B, 0x04, 0x61, 0xFC, 0xC3, 0x02, 0x19, 0xFE,
+ 0x1E, 0x01, 0x7F, 0xFF, 0x20, 0x00, 0x00, 0x00, 0x14, 0x00, 0xAC,
+ 0xFF, 0xAE, 0x00, 0x05, 0xFF, 0x03, 0x01, 0xAA, 0xFF, 0x63, 0xFD,
+ 0xFD, 0x47, 0x0E, 0x0B, 0xC8, 0xF9, 0x11, 0x04, 0x71, 0xFD, 0x6C,
+ 0x01, 0x61, 0xFF, 0x28, 0x00, 0x00, 0x00, 0x0C, 0x00, 0xCD, 0xFF,
+ 0x57, 0x00, 0xB6, 0xFF, 0xBE, 0xFF, 0xED, 0x01, 0xF5, 0xF8, 0x9B,
+ 0x45, 0x22, 0x12, 0x48, 0xF7, 0x3D, 0x05, 0xE2, 0xFC, 0xAB, 0x01,
+ 0x49, 0xFF, 0x30, 0x00, 0xFF, 0xFF, 0x06, 0x00, 0xEC, 0xFF, 0x06,
+ 0x00, 0x5A, 0x00, 0x9A, 0xFE, 0xDA, 0x03, 0x8D, 0xF5, 0xE1, 0x41,
+ 0xA1, 0x19, 0x09, 0xF5, 0x33, 0x06, 0x77, 0xFC, 0xD6, 0x01, 0x3A,
+ 0xFF, 0x35, 0x00, 0xFE, 0xFF, 0x01, 0x00, 0x07, 0x00, 0xC0, 0xFF,
+ 0xE8, 0x00, 0xA6, 0xFD, 0x5F, 0x05, 0x31, 0xF3, 0xF6, 0x3C, 0x52,
+ 0x21, 0x37, 0xF3, 0xDD, 0x06, 0x3B, 0xFC, 0xE6, 0x01, 0x36, 0xFF,
+ 0x36, 0x00, 0xFD, 0xFF, 0xFE, 0xFF, 0x1C, 0x00, 0x86, 0xFF, 0x59,
+ 0x01, 0xEC, 0xFC, 0x6F, 0x06, 0xDC, 0xF1, 0x04, 0x37, 0xF3, 0x28,
+ 0xFC, 0xF1, 0x28, 0x07, 0x37, 0xFC, 0xD8, 0x01, 0x41, 0xFF, 0x33,
+ 0x00, 0xFD, 0xFF, 0xFD, 0xFF, 0x2A, 0x00, 0x5C, 0xFF, 0xAA, 0x01,
+ 0x71, 0xFC, 0x07, 0x07, 0x7E, 0xF1, 0x44, 0x30, 0x44, 0x30, 0x7E,
+ 0xF1, 0x07, 0x07, 0x71, 0xFC, 0xAA, 0x01, 0x5C, 0xFF, 0x2A, 0x00,
+ 0xFD, 0xFF, 0xFD, 0xFF, 0x33, 0x00, 0x41, 0xFF, 0xD8, 0x01, 0x37,
+ 0xFC, 0x28, 0x07, 0xFC, 0xF1, 0xF3, 0x28, 0x04, 0x37, 0xDC, 0xF1,
+ 0x6F, 0x06, 0xEC, 0xFC, 0x59, 0x01, 0x86, 0xFF, 0x1C, 0x00, 0xFE,
+ 0xFF, 0xFD, 0xFF, 0x36, 0x00, 0x36, 0xFF, 0xE6, 0x01, 0x3B, 0xFC,
+ 0xDD, 0x06, 0x37, 0xF3, 0x52, 0x21, 0xF6, 0x3C, 0x31, 0xF3, 0x5F,
+ 0x05, 0xA6, 0xFD, 0xE8, 0x00, 0xC0, 0xFF, 0x07, 0x00, 0x01, 0x00,
+ 0xFE, 0xFF, 0x35, 0x00, 0x3A, 0xFF, 0xD6, 0x01, 0x77, 0xFC, 0x33,
+ 0x06, 0x09, 0xF5, 0xA1, 0x19, 0xE1, 0x41, 0x8D, 0xF5, 0xDA, 0x03,
+ 0x9A, 0xFE, 0x5A, 0x00, 0x06, 0x00, 0xEC, 0xFF, 0x06, 0x00, 0xFF,
+ 0xFF, 0x30, 0x00, 0x49, 0xFF, 0xAB, 0x01, 0xE2, 0xFC, 0x3D, 0x05,
+ 0x48, 0xF7, 0x22, 0x12, 0x9B, 0x45, 0xF5, 0xF8, 0xED, 0x01, 0xBE,
+ 0xFF, 0xB6, 0xFF, 0x57, 0x00, 0xCD, 0xFF, 0x0C, 0x00, 0x00, 0x00,
+ 0x28, 0x00, 0x61, 0xFF, 0x6C, 0x01, 0x71, 0xFD, 0x11, 0x04, 0xC8,
+ 0xF9, 0x0E, 0x0B, 0xFD, 0x47, 0x63, 0xFD, 0xAA, 0xFF, 0x03, 0x01,
+ 0x05, 0xFF, 0xAE, 0x00, 0xAC, 0xFF, 0x14, 0x00, 0x00, 0x00, 0x20,
+ 0x00, 0x7F, 0xFF, 0x1E, 0x01, 0x19, 0xFE, 0xC3, 0x02, 0x61, 0xFC,
+ 0x9B, 0x04, 0xF2, 0x48, 0xC6, 0x02, 0x2C, 0xFD, 0x5A, 0x02, 0x50,
+ 0xFE, 0x04, 0x01, 0x8A, 0xFF, 0x1D, 0x00, 0x17, 0x00, 0xA1, 0xFF,
+ 0xC9, 0x00, 0xCD, 0xFE, 0x6C, 0x01, 0xEA, 0xFE, 0xF3, 0xFE, 0x70,
+ 0x48, 0xFF, 0x08, 0x94, 0xFA, 0xAD, 0x03, 0xA3, 0xFD, 0x55, 0x01,
+ 0x6A, 0xFF, 0x26, 0x00, 0x00, 0x00, 0x0F, 0x00, 0xC3, 0xFF, 0x71,
+ 0x00, 0x81, 0xFF, 0x1F, 0x00, 0x42, 0x01, 0x37, 0xFA, 0x7C, 0x46,
+ 0xE7, 0x0F, 0x08, 0xF8, 0xE6, 0x04, 0x0B, 0xFD, 0x99, 0x01, 0x4F,
+ 0xFF, 0x2E, 0x00, 0xFF, 0xFF, 0x08, 0x00, 0xE3, 0xFF, 0x1E, 0x00,
+ 0x2A, 0x00, 0xEF, 0xFE, 0x4D, 0x03, 0x7D, 0xF6, 0x2A, 0x43, 0x4B,
+ 0x17, 0xB0, 0xF5, 0xEF, 0x05, 0x93, 0xFC, 0xCB, 0x01, 0x3D, 0xFF,
+ 0x34, 0x00, 0xFE, 0xFF, 0x03, 0x00, 0xFF, 0xFF, 0xD4, 0xFF, 0xBF,
+ 0x00, 0xEB, 0xFD, 0xF3, 0x04, 0xCF, 0xF3, 0x98, 0x3E, 0xF3, 0x1E,
+ 0xB9, 0xF3, 0xB2, 0x06, 0x48, 0xFC, 0xE4, 0x01, 0x36, 0xFF, 0x36,
+ 0x00, 0xFE, 0xFF, 0xFF, 0xFF, 0x16, 0x00, 0x96, 0xFF, 0x39, 0x01,
+ 0x1F, 0xFD, 0x28, 0x06, 0x2A, 0xF2, 0xF2, 0x38, 0xA0, 0x26, 0x4B,
+ 0xF2, 0x1C, 0x07, 0x32, 0xFC, 0xE0, 0x01, 0x3C, 0xFF, 0x35, 0x00,
+ 0xFD, 0xFF, 0xFD, 0xFF, 0x26, 0x00, 0x67, 0xFF, 0x94, 0x01, 0x90,
+ 0xFC, 0xE5, 0x06, 0x81, 0xF1, 0x6B, 0x32, 0x11, 0x2E, 0x8E, 0xF1,
+ 0x1D, 0x07, 0x58, 0xFC, 0xBC, 0x01, 0x52, 0xFF, 0x2E, 0x00, 0xFD,
+ 0xFF, 0xFD, 0xFF, 0x31, 0x00, 0x48, 0xFF, 0xCE, 0x01, 0x42, 0xFC,
+ 0x2A, 0x07, 0xBF, 0xF1, 0x40, 0x2B, 0x05, 0x35, 0xA6, 0xF1, 0xAB,
+ 0x06, 0xBF, 0xFC, 0x75, 0x01, 0x77, 0xFF, 0x21, 0x00, 0xFE, 0xFF,
+ 0xFD, 0xFF, 0x36, 0x00, 0x38, 0xFF, 0xE5, 0x01, 0x33, 0xFC, 0xFF,
+ 0x06, 0xC4, 0xF2, 0xB0, 0x23, 0x3B, 0x3B, 0xAD, 0xF2, 0xBF, 0x05,
+ 0x66, 0xFD, 0x0E, 0x01, 0xAC, 0xFF, 0x0E, 0x00, 0x00, 0x00, 0xFE,
+ 0xFF, 0x36, 0x00, 0x37, 0xFF, 0xDE, 0x01, 0x5F, 0xFC, 0x70, 0x06,
+ 0x6C, 0xF4, 0xFD, 0x1B, 0x7D, 0x40, 0xB7, 0xF4, 0x5D, 0x04, 0x49,
+ 0xFE, 0x88, 0x00, 0xEF, 0xFF, 0xF5, 0xFF, 0x04, 0x00, 0xFF, 0xFF,
+ 0x32, 0x00, 0x43, 0xFF, 0xBA, 0x01, 0xBC, 0xFC, 0x90, 0x05, 0x8E,
+ 0xF6, 0x68, 0x14, 0x99, 0x44, 0xCD, 0xF7, 0x8F, 0x02, 0x60, 0xFF,
+ 0xEA, 0xFF, 0x3E, 0x00, 0xD7, 0xFF, 0x0A, 0x00, 0x00, 0x00, 0x2B,
+ 0x00, 0x59, 0xFF, 0x81, 0x01, 0x42, 0xFD, 0x72, 0x04, 0xFF, 0xF8,
+ 0x2D, 0x0D, 0x69, 0x47, 0xEB, 0xFB, 0x63, 0x00, 0x9D, 0x00, 0x3C,
+ 0xFF, 0x93, 0x00, 0xB6, 0xFF, 0x12, 0x00, 0x00, 0x00, 0x22, 0x00,
+ 0x76, 0xFF, 0x37, 0x01, 0xE4, 0xFD, 0x2C, 0x03, 0x94, 0xFB, 0x83,
+ 0x06, 0xCE, 0x48, 0x05, 0x01, 0xF5, 0xFD, 0xF0, 0x01, 0x87, 0xFE,
+ 0xEA, 0x00, 0x94, 0xFF, 0x1A, 0x00, 0x1A, 0x00, 0x96, 0xFF, 0xE3,
+ 0x00, 0x95, 0xFE, 0xD5, 0x01, 0x26, 0xFE, 0x98, 0x00, 0xBF, 0x48,
+ 0x00, 0x07, 0x61, 0xFB, 0x46, 0x03, 0xD6, 0xFD, 0x3D, 0x01, 0x73,
+ 0xFF, 0x23, 0x00, 0x00, 0x00, 0x11, 0x00, 0xB9, 0xFF, 0x8C, 0x00,
+ 0x4A, 0xFF, 0x83, 0x00, 0x91, 0x00, 0x91, 0xFB, 0x3D, 0x47, 0xB7,
+ 0x0D, 0xCD, 0xF8, 0x89, 0x04, 0x36, 0xFD, 0x86, 0x01, 0x57, 0xFF,
+ 0x2B, 0x00, 0x00, 0x00, 0x0A, 0x00, 0xD9, 0xFF, 0x37, 0x00, 0xF7,
+ 0xFF, 0x49, 0xFF, 0xB6, 0x02, 0x86, 0xF7, 0x53, 0x44, 0xFB, 0x14,
+ 0x61, 0xF6, 0xA4, 0x05, 0xB4, 0xFC, 0xBE, 0x01, 0x42, 0xFF, 0x32,
+ 0x00, 0xFF, 0xFF, 0x04, 0x00, 0xF7, 0xFF, 0xEA, 0xFF, 0x93, 0x00,
+ 0x36, 0xFE, 0x7D, 0x04, 0x85, 0xF4, 0x1F, 0x40, 0x94, 0x1C, 0x47,
+ 0xF4, 0x7E, 0x06, 0x5A, 0xFC, 0xDF, 0x01, 0x37, 0xFF, 0x36, 0x00,
+ 0xFE, 0xFF, 0x00, 0x00, 0x0F, 0x00, 0xA8, 0xFF, 0x17, 0x01, 0x57,
+ 0xFD, 0xD6, 0x05, 0x90, 0xF2, 0xC8, 0x3A, 0x46, 0x24, 0xAA, 0xF2,
+ 0x06, 0x07, 0x32, 0xFC, 0xE5, 0x01, 0x39, 0xFF, 0x36, 0x00, 0xFD,
+ 0xFF, 0xFE, 0xFF, 0x22, 0x00, 0x74, 0xFF, 0x7C, 0x01, 0xB5, 0xFC,
+ 0xB8, 0x06, 0x9C, 0xF1, 0x81, 0x34, 0xD1, 0x2B, 0xB3, 0xF1, 0x29,
+ 0x07, 0x46, 0xFC, 0xCA, 0x01, 0x4A, 0xFF, 0x30, 0x00, 0xFD, 0xFF,
+ 0xFD, 0xFF, 0x2E, 0x00, 0x50, 0xFF, 0xC0, 0x01, 0x53, 0xFC, 0x21,
+ 0x07, 0x96, 0xF1, 0x82, 0x2D, 0xF2, 0x32, 0x86, 0xF1, 0xDB, 0x06,
+ 0x99, 0xFC, 0x8E, 0x01, 0x6A, 0xFF, 0x25, 0x00, 0xFD, 0xFF, 0xFD,
+ 0xFF, 0x35, 0x00, 0x3B, 0xFF, 0xE2, 0x01, 0x31, 0xFC, 0x17, 0x07,
+ 0x61, 0xF2, 0x0A, 0x26, 0x6A, 0x39, 0x41, 0xF2, 0x15, 0x06, 0x2C,
+ 0xFD, 0x31, 0x01, 0x9B, 0xFF, 0x14, 0x00, 0xFF, 0xFF, 0xFE, 0xFF,
+ 0x36, 0x00, 0x36, 0xFF, 0xE3, 0x01, 0x4C, 0xFC, 0xA6, 0x06, 0xDB,
+ 0xF3, 0x5B, 0x1E, 0xFC, 0x3E, 0xFA, 0xF3, 0xD7, 0x04, 0xFD, 0xFD,
+ 0xB4, 0x00, 0xD9, 0xFF, 0xFD, 0xFF, 0x03, 0x00, 0xFF, 0xFF, 0x33,
+ 0x00, 0x3E, 0xFF, 0xC8, 0x01, 0x9B, 0xFC, 0xDD, 0x05, 0xDC, 0xF5,
+ 0xB6, 0x16, 0x77, 0x43, 0xBD, 0xF6, 0x28, 0x03, 0x05, 0xFF, 0x1D,
+ 0x00, 0x25, 0x00, 0xE1, 0xFF, 0x08, 0x00, 0xFF, 0xFF, 0x2D, 0x00,
+ 0x51, 0xFF, 0x95, 0x01, 0x15, 0xFD, 0xCF, 0x04, 0x39, 0xF8, 0x59,
+ 0x0F, 0xAF, 0x46, 0x8B, 0xFA, 0x17, 0x01, 0x38, 0x00, 0x73, 0xFF,
+ 0x78, 0x00, 0xC0, 0xFF, 0x0F, 0x00, 0x00, 0x00, 0x25, 0x00, 0x6C,
+ 0xFF, 0x4F, 0x01, 0xB0, 0xFD, 0x93, 0x03, 0xC7, 0xFA, 0x7D, 0x08,
+ 0x86, 0x48, 0x5A, 0xFF, 0xBA, 0xFE, 0x86, 0x01, 0xBF, 0xFE, 0xCF,
+ 0x00, 0x9E, 0xFF, 0x17, 0x00, 0x1C, 0x00, 0x8C, 0xFF, 0xFE, 0x00,
+ 0x5D, 0xFE, 0x3F, 0x02, 0x5E, 0xFD, 0x54, 0x02, 0xEC, 0x48, 0x13,
+ 0x05, 0x2E, 0xFC, 0xDE, 0x02, 0x0C, 0xFE, 0x24, 0x01, 0x7D, 0xFF,
+ 0x20, 0x00, 0x00, 0x00, 0x14, 0x00, 0xAE, 0xFF, 0xA7, 0x00, 0x12,
+ 0xFF, 0xEA, 0x00, 0xD9, 0xFF, 0x03, 0xFD, 0xDC, 0x47, 0x95, 0x0B,
+ 0x96, 0xF9, 0x29, 0x04, 0x65, 0xFD, 0x71, 0x01, 0x5F, 0xFF, 0x29,
+ 0x00, 0x00, 0x00, 0x0C, 0x00, 0xD0, 0xFF, 0x51, 0x00, 0xC3, 0xFF,
+ 0xA6, 0xFF, 0x16, 0x02, 0xA9, 0xF8, 0x5C, 0x45, 0xB2, 0x12, 0x19,
+ 0xF7, 0x52, 0x05, 0xD8, 0xFC, 0xAF, 0x01, 0x47, 0xFF, 0x30, 0x00,
+ 0xFF, 0xFF, 0x06, 0x00, 0xEE, 0xFF, 0x01, 0x00, 0x66, 0x00, 0x85,
+ 0xFE, 0xFC, 0x03, 0x55, 0xF5, 0x8C, 0x41, 0x38, 0x1A, 0xE1, 0xF4,
+ 0x43, 0x06, 0x70, 0xFC, 0xD8, 0x01, 0x39, 0xFF, 0x35, 0x00, 0xFE,
+ 0xFF, 0x01, 0x00, 0x08, 0x00, 0xBB, 0xFF, 0xF1, 0x00, 0x96, 0xFD,
+ 0x78, 0x05, 0x0E, 0xF3, 0x8A, 0x3C, 0xEA, 0x21, 0x19, 0xF3, 0xE6,
+ 0x06, 0x38, 0xFC, 0xE6, 0x01, 0x37, 0xFF, 0x36, 0x00, 0xFD, 0xFF,
+ 0xFE, 0xFF, 0x1D, 0x00, 0x82, 0xFF, 0x60, 0x01, 0xE0, 0xFC, 0x7F,
+ 0x06, 0xCC, 0xF1, 0x85, 0x36, 0x87, 0x29, 0xEB, 0xF1, 0x2A, 0x07,
+ 0x39, 0xFC, 0xD6, 0x01, 0x43, 0xFF, 0x33, 0x00, 0xFD, 0xFF, 0xFD,
+ 0xFF, 0x2B, 0x00, 0x59, 0xFF, 0xAE, 0x01, 0x6A, 0xFC, 0x0D, 0x07,
+ 0x80, 0xF1, 0xB8, 0x2F, 0xCF, 0x30, 0x7D, 0xF1, 0xFF, 0x06, 0x78,
+ 0xFC, 0xA5, 0x01, 0x5F, 0xFF, 0x29, 0x00, 0xFD, 0xFF, 0xFD, 0xFF,
+ 0x34, 0x00, 0x40, 0xFF, 0xDB, 0x01, 0x35, 0xFC, 0x26, 0x07, 0x0E,
+ 0xF2, 0x60, 0x28, 0x82, 0x37, 0xED, 0xF1, 0x5E, 0x06, 0xF8, 0xFC,
+ 0x51, 0x01, 0x8A, 0xFF, 0x1A, 0x00, 0xFF, 0xFF, 0xFD, 0xFF, 0x36,
+ 0x00, 0x36, 0xFF, 0xE6, 0x01, 0x3E, 0xFC, 0xD3, 0x06, 0x56, 0xF3,
+ 0xBA, 0x20, 0x61, 0x3D, 0x56, 0xF3, 0x45, 0x05, 0xB7, 0xFD, 0xDE,
+ 0x00, 0xC5, 0xFF, 0x05, 0x00, 0x02, 0x00, 0xFE, 0xFF, 0x35, 0x00,
+ 0x3A, 0xFF, 0xD3, 0x01, 0x7D, 0xFC, 0x23, 0x06, 0x32, 0xF5, 0x0C,
+ 0x19, 0x38, 0x42, 0xC7, 0xF5, 0xB8, 0x03, 0xAF, 0xFE, 0x4E, 0x00,
+ 0x0C, 0x00, 0xEA, 0xFF, 0x06, 0x00, 0xFF, 0xFF, 0x2F, 0x00, 0x4A,
+ 0xFF, 0xA7, 0x01, 0xEC, 0xFC, 0x28, 0x05, 0x77, 0xF7, 0x92, 0x11,
+ 0xD7, 0x45, 0x43, 0xF9, 0xC3, 0x01, 0xD6, 0xFF, 0xA9, 0xFF, 0x5E,
+ 0x00, 0xCB, 0xFF, 0x0D, 0x00, 0x00, 0x00, 0x28, 0x00, 0x63, 0xFF,
+ 0x66, 0x01, 0x7D, 0xFD, 0xF8, 0x03, 0xFB, 0xF9, 0x89, 0x0A, 0x1D,
+ 0x48, 0xC5, 0xFD, 0x7A, 0xFF, 0x1D, 0x01, 0xF7, 0xFE, 0xB4, 0x00,
+ 0xA9, 0xFF, 0x15, 0x00, 0x00, 0x00, 0x1F, 0x00, 0x82, 0xFF, 0x18,
+ 0x01, 0x27, 0xFE, 0xA9, 0x02, 0x94, 0xFC, 0x24, 0x04, 0xF5, 0x48,
+ 0x39, 0x03, 0xF9, 0xFC, 0x74, 0x02, 0x42, 0xFE, 0x0B, 0x01, 0x87,
+ 0xFF, 0x1E, 0x00, 0x16, 0x00, 0xA4, 0xFF, 0xC2, 0x00, 0xDB, 0xFE,
+ 0x52, 0x01, 0x1B, 0xFF, 0x8D, 0xFE, 0x57, 0x48, 0x81, 0x09, 0x61,
+ 0xFA, 0xC6, 0x03, 0x96, 0xFD, 0x5B, 0x01, 0x68, 0xFF, 0x26, 0x00,
+ 0x00, 0x00, 0x0E, 0x00, 0xC6, 0xFF, 0x6B, 0x00, 0x8E, 0xFF, 0x06,
+ 0x00, 0x6E, 0x01, 0xE4, 0xF9, 0x48, 0x46, 0x75, 0x10, 0xD7, 0xF7,
+ 0xFC, 0x04, 0x00, 0xFD, 0x9E, 0x01, 0x4E, 0xFF, 0x2E, 0x00, 0xFF,
+ 0xFF, 0x07, 0x00, 0xE5, 0xFF, 0x18, 0x00, 0x36, 0x00, 0xD9, 0xFE,
+ 0x71, 0x03, 0x3F, 0xF6, 0xDB, 0x42, 0xE0, 0x17, 0x86, 0xF5, 0x00,
+ 0x06, 0x8C, 0xFC, 0xCE, 0x01, 0x3C, 0xFF, 0x34, 0x00, 0xFE, 0xFF,
+ 0x02, 0x00, 0x01, 0x00, 0xCF, 0xFF, 0xC9, 0x00, 0xDA, 0xFD, 0x0F,
+ 0x05, 0xA5, 0xF3, 0x31, 0x3E, 0x8A, 0x1F, 0x97, 0xF3, 0xBD, 0x06,
+ 0x44, 0xFC, 0xE5, 0x01, 0x36, 0xFF, 0x36, 0x00, 0xFD, 0xFF, 0xFF,
+ 0xFF, 0x17, 0x00, 0x92, 0xFF, 0x41, 0x01, 0x11, 0xFD, 0x3B, 0x06,
+ 0x14, 0xF2, 0x78, 0x38, 0x36, 0x27, 0x35, 0xF2, 0x20, 0x07, 0x33,
+ 0xFC, 0xDF, 0x01, 0x3E, 0xFF, 0x34, 0x00, 0xFD, 0xFF, 0xFD, 0xFF,
+ 0x28, 0x00, 0x64, 0xFF, 0x9A, 0x01, 0x88, 0xFC, 0xEE, 0x06, 0x7E,
+ 0xF1, 0xE3, 0x31, 0x9F, 0x2E, 0x88, 0xF1, 0x19, 0x07, 0x5E, 0xFC,
+ 0xB7, 0x01, 0x54, 0xFF, 0x2D, 0x00, 0xFD, 0xFF, 0xFD, 0xFF, 0x32,
+ 0x00, 0x46, 0xFF, 0xD1, 0x01, 0x3F, 0xFC, 0x2B, 0x07, 0xCD, 0xF1,
+ 0xAE, 0x2A, 0x86, 0x35, 0xB1, 0xF1, 0x9D, 0x06, 0xCA, 0xFC, 0x6E,
+ 0x01, 0x7B, 0xFF, 0x20, 0x00, 0xFE, 0xFF, 0xFD, 0xFF, 0x36, 0x00,
+ 0x38, 0xFF, 0xE6, 0x01, 0x35, 0xFC, 0xF7, 0x06, 0xE0, 0xF2, 0x18,
+ 0x23, 0xAB, 0x3B, 0xCC, 0xF2, 0xA8, 0x05, 0x76, 0xFD, 0x04, 0x01,
+ 0xB1, 0xFF, 0x0C, 0x00, 0x00, 0x00, 0xFE, 0xFF, 0x36, 0x00, 0x38,
+ 0xFF, 0xDC, 0x01, 0x64, 0xFC, 0x62, 0x06, 0x93, 0xF4, 0x66, 0x1B,
+ 0xD9, 0x40, 0xEA, 0xF4, 0x3E, 0x04, 0x5D, 0xFE, 0x7D, 0x00, 0xF5,
+ 0xFF, 0xF3, 0xFF, 0x05, 0x00, 0xFF, 0xFF, 0x31, 0x00, 0x44, 0xFF,
+ 0xB7, 0x01, 0xC5, 0xFC, 0x7C, 0x05, 0xBC, 0xF6, 0xD5, 0x13, 0xDC,
+ 0x44, 0x14, 0xF8, 0x67, 0x02, 0x77, 0xFF, 0xDD, 0xFF, 0x44, 0x00,
+ 0xD5, 0xFF, 0x0B, 0x00, 0x00, 0x00, 0x2A, 0x00, 0x5B, 0xFF, 0x7C,
+ 0x01, 0x4E, 0xFD, 0x5A, 0x04, 0x31, 0xF9, 0xA4, 0x0C, 0x90, 0x47,
+ 0x47, 0xFC, 0x36, 0x00, 0xB6, 0x00, 0x2E, 0xFF, 0x99, 0x00, 0xB3,
+ 0xFF, 0x12, 0x00, 0x00, 0x00, 0x22, 0x00, 0x78, 0xFF, 0x31, 0x01,
+ 0xF1, 0xFD, 0x12, 0x03, 0xC7, 0xFB, 0x07, 0x06, 0xDB, 0x48, 0x73,
+ 0x01, 0xC3, 0xFD, 0x0A, 0x02, 0x79, 0xFE, 0xF1, 0x00, 0x91, 0xFF,
+ 0x1B, 0x00, 0x19, 0x00, 0x99, 0xFF, 0xDD, 0x00, 0xA3, 0xFE, 0xBB,
+ 0x01, 0x58, 0xFE, 0x2D, 0x00, 0xAF, 0x48, 0x7E, 0x07, 0x2E, 0xFB,
+ 0x60, 0x03, 0xC9, 0xFD, 0x43, 0x01, 0x71, 0xFF, 0x24, 0x00, 0x00,
+ 0x00, 0x10, 0x00, 0xBB, 0xFF, 0x85, 0x00, 0x58, 0xFF, 0x6A, 0x00,
+ 0xBE, 0x00, 0x38, 0xFB, 0x0F, 0x47, 0x42, 0x0E, 0x9B, 0xF8, 0xA1,
+ 0x04, 0x2B, 0xFD, 0x8B, 0x01, 0x55, 0xFF, 0x2C, 0x00, 0xFF, 0xFF,
+ 0x09, 0x00, 0xDC, 0xFF, 0x31, 0x00, 0x04, 0x00, 0x32, 0xFF, 0xDC,
+ 0x02, 0x42, 0xF7, 0x0B, 0x44, 0x8E, 0x15, 0x34, 0xF6, 0xB7, 0x05,
+ 0xAB, 0xFC, 0xC1, 0x01, 0x40, 0xFF, 0x33, 0x00, 0xFF, 0xFF, 0x04,
+ 0x00, 0xF9, 0xFF, 0xE4, 0xFF, 0x9F, 0x00, 0x23, 0xFE, 0x9B, 0x04,
+ 0x55, 0xF4, 0xC0, 0x3F, 0x2C, 0x1D, 0x22, 0xF4, 0x8C, 0x06, 0x55,
+ 0xFC, 0xE1, 0x01, 0x37, 0xFF, 0x36, 0x00, 0xFE, 0xFF, 0x00, 0x00,
+ 0x11, 0x00, 0xA3, 0xFF, 0x20, 0x01, 0x49, 0xFD, 0xEB, 0x05, 0x74,
+ 0xF2, 0x54, 0x3A, 0xDD, 0x24, 0x91, 0xF2, 0x0C, 0x07, 0x32, 0xFC,
+ 0xE4, 0x01, 0x3A, 0xFF, 0x36, 0x00, 0xFD, 0xFF, 0xFE, 0xFF, 0x23,
+ 0x00, 0x71, 0xFF, 0x82, 0x01, 0xAB, 0xFC, 0xC4, 0x06, 0x93, 0xF1,
+ 0xFD, 0x33, 0x62, 0x2C, 0xA8, 0xF1, 0x27, 0x07, 0x4A, 0xFC, 0xC7,
+ 0x01, 0x4C, 0xFF, 0x30, 0x00, 0xFD, 0xFF, 0xFD, 0xFF, 0x2F, 0x00,
+ 0x4E, 0xFF, 0xC3, 0x01, 0x4E, 0xFC, 0x24, 0x07, 0x9E, 0xF1, 0xF2,
+ 0x2C, 0x78, 0x33, 0x8C, 0xF1, 0xD0, 0x06, 0xA2, 0xFC, 0x88, 0x01,
+ 0x6D, 0xFF, 0x24, 0x00, 0xFD, 0xFF, 0xFD, 0xFF, 0x35, 0x00, 0x3B,
+ 0xFF, 0xE3, 0x01, 0x31, 0xFC, 0x12, 0x07, 0x79, 0xF2, 0x73, 0x25,
+ 0xDF, 0x39, 0x5A, 0xF2, 0x00, 0x06, 0x3A, 0xFD, 0x28, 0x01, 0x9F,
+ 0xFF, 0x13, 0x00, 0x00, 0x00, 0xFE, 0xFF, 0x36, 0x00, 0x36, 0xFF,
+ 0xE2, 0x01, 0x50, 0xFC, 0x99, 0x06, 0xFE, 0xF3, 0xC3, 0x1D, 0x5E,
+ 0x3F, 0x27, 0xF4, 0xB9, 0x04, 0x10, 0xFE, 0xA9, 0x00, 0xDF, 0xFF,
+ 0xFB, 0xFF, 0x03, 0x00, 0xFF, 0xFF, 0x33, 0x00, 0x3F, 0xFF, 0xC5,
+ 0x01, 0xA3, 0xFC, 0xCA, 0x05, 0x07, 0xF6, 0x22, 0x16, 0xC3, 0x43,
+ 0xFE, 0xF6, 0x02, 0x03, 0x1B, 0xFF, 0x11, 0x00, 0x2B, 0x00, 0xDE,
+ 0xFF, 0x09, 0x00, 0xFF, 0xFF, 0x2D, 0x00, 0x53, 0xFF, 0x90, 0x01,
+ 0x20, 0xFD, 0xB8, 0x04, 0x6A, 0xF8, 0xCD, 0x0E, 0xE1, 0x46, 0xE1,
+ 0xFA, 0xEB, 0x00, 0x51, 0x00, 0x65, 0xFF, 0x7F, 0x00, 0xBE, 0xFF,
+ 0x10, 0x00, 0x00, 0x00, 0x24, 0x00, 0x6E, 0xFF, 0x49, 0x01, 0xBC,
+ 0xFD, 0x7A, 0x03, 0xFA, 0xFA, 0xFD, 0x07, 0x9C, 0x48, 0xC3, 0xFF,
+ 0x89, 0xFE, 0xA1, 0x01, 0xB1, 0xFE, 0xD6, 0x00, 0x9C, 0xFF, 0x18,
+ 0x00, 0x1C, 0x00, 0x8F, 0xFF, 0xF7, 0x00, 0x6B, 0xFE, 0x25, 0x02,
+ 0x91, 0xFD, 0xE3, 0x01, 0xE5, 0x48, 0x8D, 0x05, 0xFB, 0xFB, 0xF8,
+ 0x02, 0xFE, 0xFD, 0x2B, 0x01, 0x7A, 0xFF, 0x21, 0x00, 0x00, 0x00,
+ 0x13, 0x00, 0xB1, 0xFF, 0xA0, 0x00, 0x20, 0xFF, 0xD0, 0x00, 0x07,
+ 0x00, 0xA4, 0xFC, 0xB6, 0x47, 0x1C, 0x0C, 0x63, 0xF9, 0x42, 0x04,
+ 0x59, 0xFD, 0x76, 0x01, 0x5D, 0xFF, 0x2A, 0x00, 0x00, 0x00, 0x0B,
+ 0x00, 0xD2, 0xFF, 0x4A, 0x00, 0xD0, 0xFF, 0x8E, 0xFF, 0x3F, 0x02,
+ 0x5E, 0xF8, 0x1E, 0x45, 0x44, 0x13, 0xEA, 0xF6, 0x67, 0x05, 0xCF,
+ 0xFC, 0xB3, 0x01, 0x46, 0xFF, 0x31, 0x00, 0xFF, 0xFF, 0x05, 0x00,
+ 0xF0, 0xFF, 0xFB, 0xFF, 0x71, 0x00, 0x71, 0xFE, 0x1D, 0x04, 0x1F,
+ 0xF5, 0x32, 0x41, 0xCE, 0x1A, 0xBA, 0xF4, 0x53, 0x06, 0x6A, 0xFC,
+ 0xDA, 0x01, 0x38, 0xFF, 0x35, 0x00, 0xFE, 0xFF, 0x01, 0x00, 0x0A,
+ 0x00, 0xB6, 0xFF, 0xFB, 0x00, 0x85, 0xFD, 0x90, 0x05, 0xEC, 0xF2,
+ 0x1C, 0x3C, 0x81, 0x22, 0xFC, 0xF2, 0xEF, 0x06, 0x36, 0xFC, 0xE6,
+ 0x01, 0x37, 0xFF, 0x36, 0x00, 0xFD, 0xFF, 0xFE, 0xFF, 0x1E, 0x00,
+ 0x7F, 0xFF, 0x67, 0x01, 0xD5, 0xFC, 0x8E, 0x06, 0xBE, 0xF1, 0x06,
+ 0x36, 0x1A, 0x2A, 0xDC, 0xF1, 0x2A, 0x07, 0x3C, 0xFC, 0xD3, 0x01,
+ 0x44, 0xFF, 0x32, 0x00, 0xFD, 0xFF, 0xFD, 0xFF, 0x2C, 0x00, 0x57,
+ 0xFF, 0xB3, 0x01, 0x64, 0xFC, 0x13, 0x07, 0x83, 0xF1, 0x2C, 0x2F,
+ 0x5A, 0x31, 0x7D, 0xF1, 0xF7, 0x06, 0x80, 0xFC, 0x9F, 0x01, 0x61,
+ 0xFF, 0x29, 0x00, 0xFD, 0xFF, 0xFD, 0xFF, 0x34, 0x00, 0x3F, 0xFF,
+ 0xDD, 0x01, 0x34, 0xFC, 0x23, 0x07, 0x21, 0xF2, 0xCB, 0x27, 0xFE,
+ 0x37, 0x00, 0xF2, 0x4D, 0x06, 0x04, 0xFD, 0x49, 0x01, 0x8E, 0xFF,
+ 0x19, 0x00, 0xFF, 0xFF, 0xFD, 0xFF, 0x36, 0x00, 0x36, 0xFF, 0xE6,
+ 0x01, 0x41, 0xFC, 0xC8, 0x06, 0x76, 0xF3, 0x22, 0x20, 0xCA, 0x3D,
+ 0x7D, 0xF3, 0x2A, 0x05, 0xC8, 0xFD, 0xD4, 0x00, 0xCA, 0xFF, 0x03,
+ 0x00, 0x02, 0x00, 0xFE, 0xFF, 0x34, 0x00, 0x3B, 0xFF, 0xD1, 0x01,
+ 0x84, 0xFC, 0x12, 0x06, 0x5C, 0xF5, 0x76, 0x18, 0x89, 0x42, 0x02,
+ 0xF6, 0x94, 0x03, 0xC4, 0xFE, 0x42, 0x00, 0x12, 0x00, 0xE8, 0xFF,
+ 0x07, 0x00, 0xFF, 0xFF, 0x2F, 0x00, 0x4C, 0xFF, 0xA2, 0x01, 0xF6,
+ 0xFC, 0x12, 0x05, 0xA7, 0xF7, 0x03, 0x11, 0x10, 0x46, 0x93, 0xF9,
+ 0x98, 0x01, 0xEE, 0xFF, 0x9B, 0xFF, 0x64, 0x00, 0xC8, 0xFF, 0x0E,
+ 0x00, 0x00, 0x00, 0x27, 0x00, 0x65, 0xFF, 0x60, 0x01, 0x8A, 0xFD,
+ 0xDF, 0x03, 0x2E, 0xFA, 0x04, 0x0A, 0x3A, 0x48, 0x28, 0xFE, 0x4B,
+ 0xFF, 0x38, 0x01, 0xE9, 0xFE, 0xBB, 0x00, 0xA6, 0xFF, 0x16, 0x00,
+ 0x00, 0x00, 0x1E, 0x00, 0x84, 0xFF, 0x11, 0x01, 0x34, 0xFE, 0x8F,
+ 0x02, 0xC7, 0xFC, 0xAE, 0x03, 0xF7, 0x48, 0xAE, 0x03, 0xC7, 0xFC,
+ 0x8F, 0x02, 0x34, 0xFE, 0x11, 0x01, 0x84, 0xFF, 0x1E, 0x00, 0x00,
+ 0x00, 0xF4, 0xFF, 0x1A, 0x00, 0xFF, 0x00, 0x07, 0x03, 0x16, 0x06,
+ 0x7C, 0x09, 0x2A, 0x0C, 0x2E, 0x0D, 0x2A, 0x0C, 0x7C, 0x09, 0x16,
+ 0x06, 0x07, 0x03, 0xFF, 0x00, 0x1A, 0x00, 0xF4, 0xFF, 0xF2, 0xFF,
+ 0xA0, 0xFF, 0x71, 0xFF, 0x71, 0x00, 0x86, 0x03, 0x73, 0x08, 0x88,
+ 0x0D, 0x78, 0x10, 0xC9, 0x0F, 0xD5, 0x0B, 0x8B, 0x06, 0x28, 0x02,
+ 0xDF, 0xFF, 0x6F, 0xFF, 0xC3, 0xFF, 0xFD, 0xFF, 0x00, 0x00, 0xDC,
+ 0xFF, 0x80, 0xFF, 0x9A, 0xFF, 0x46, 0x01, 0x1E, 0x05, 0x5A, 0x0A,
+ 0xED, 0x0E, 0xAA, 0x10, 0xAF, 0x0E, 0xFD, 0x09, 0xCB, 0x04, 0x18,
+ 0x01, 0x8E, 0xFF, 0x85, 0xFF, 0xE1, 0xFF, 0xFC, 0xFF, 0xBD, 0xFF,
+ 0x6D, 0xFF, 0xF6, 0xFF, 0x65, 0x02, 0xE5, 0x06, 0x2B, 0x0C, 0xF3,
+ 0x0F, 0x60, 0x10, 0x3B, 0x0D, 0x16, 0x08, 0x3F, 0x03, 0x50, 0x00,
+ 0x6E, 0xFF, 0xA7, 0xFF, 0xF5, 0xFF, 0xEF, 0xFF, 0x9A, 0xFF, 0x75,
+ 0xFF, 0x91, 0x00, 0xC9, 0x03, 0xC8, 0x08, 0xCC, 0x0D, 0x89, 0x10,
+ 0x9F, 0x0F, 0x85, 0x0B, 0x3B, 0x06, 0xF4, 0x01, 0xCD, 0xFF, 0x72,
+ 0xFF, 0xC9, 0xFF, 0xFE, 0xFF, 0x00, 0x00, 0xD7, 0xFF, 0x7B, 0xFF,
+ 0xA5, 0xFF, 0x73, 0x01, 0x6A, 0x05, 0xAD, 0x0A, 0x21, 0x0F, 0xA6,
+ 0x10, 0x74, 0x0E, 0xA9, 0x09, 0x83, 0x04, 0xF0, 0x00, 0x85, 0xFF,
+ 0x8B, 0xFF, 0xE5, 0xFF, 0xFA, 0xFF, 0xB7, 0xFF, 0x6C, 0xFF, 0x0C,
+ 0x00, 0x9D, 0x02, 0x37, 0x07, 0x78, 0x0C, 0x15, 0x10, 0x47, 0x10,
+ 0xF3, 0x0C, 0xC2, 0x07, 0x01, 0x03, 0x35, 0x00, 0x6D, 0xFF, 0xAD,
+ 0xFF, 0xF7, 0xFF, 0xEB, 0xFF, 0x94, 0xFF, 0x7A, 0xFF, 0xB3, 0x00,
+ 0x0D, 0x04, 0x1C, 0x09, 0x0D, 0x0E, 0x97, 0x10, 0x73, 0x0F, 0x35,
+ 0x0B, 0xEB, 0x05, 0xC1, 0x01, 0xBD, 0xFF, 0x75, 0xFF, 0xCE, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xD2, 0xFF, 0x77, 0xFF, 0xB3, 0xFF, 0xA1,
+ 0x01, 0xB7, 0x05, 0xFF, 0x0A, 0x53, 0x0F, 0x9E, 0x10, 0x37, 0x0E,
+ 0x55, 0x09, 0x3B, 0x04, 0xCB, 0x00, 0x7E, 0xFF, 0x90, 0xFF, 0xE9,
+ 0xFF, 0xF8, 0xFF, 0xB1, 0xFF, 0x6C, 0xFF, 0x24, 0x00, 0xD8, 0x02,
+ 0x8A, 0x07, 0xC2, 0x0C, 0x34, 0x10, 0x2A, 0x10, 0xAA, 0x0C, 0x6F,
+ 0x07, 0xC4, 0x02, 0x1C, 0x00, 0x6C, 0xFF, 0xB3, 0xFF, 0xF9, 0xFF,
+ 0xE8, 0xFF, 0x8E, 0xFF, 0x80, 0xFF, 0xD7, 0x00, 0x53, 0x04, 0x71,
+ 0x09, 0x4C, 0x0E, 0xA1, 0x10, 0x43, 0x0F, 0xE3, 0x0A, 0x9D, 0x05,
+ 0x91, 0x01, 0xAE, 0xFF, 0x79, 0xFF, 0xD4, 0xFF, 0x00, 0x00, 0xFF,
+ 0xFF, 0xCD, 0xFF, 0x74, 0xFF, 0xC2, 0xFF, 0xD2, 0x01, 0x06, 0x06,
+ 0x50, 0x0B, 0x82, 0x0F, 0x93, 0x10, 0xF8, 0x0D, 0x00, 0x09, 0xF6,
+ 0x03, 0xA7, 0x00, 0x78, 0xFF, 0x96, 0xFF, 0xEC, 0xFF, 0xF6, 0xFF,
+ 0xAB, 0xFF, 0x6D, 0xFF, 0x3E, 0x00, 0x15, 0x03, 0xDE, 0x07, 0x0B,
+ 0x0D, 0x50, 0x10, 0x0A, 0x10, 0x5E, 0x0C, 0x1C, 0x07, 0x8A, 0x02,
+ 0x04, 0x00, 0x6C, 0xFF, 0xB9, 0xFF, 0xFB, 0xFF, 0xE4, 0xFF, 0x89,
+ 0xFF, 0x88, 0xFF, 0xFD, 0x00, 0x9B, 0x04, 0xC5, 0x09, 0x88, 0x0E,
+ 0xA8, 0x10, 0x10, 0x0F, 0x91, 0x0A, 0x50, 0x05, 0x64, 0x01, 0xA1,
+ 0xFF, 0x7D, 0xFF, 0xD9, 0xFF, 0x00, 0x00, 0xFE, 0xFF, 0xC7, 0xFF,
+ 0x71, 0xFF, 0xD3, 0xFF, 0x05, 0x02, 0x55, 0x06, 0xA0, 0x0B, 0xAD,
+ 0x0F, 0x84, 0x10, 0xB6, 0x0D, 0xAC, 0x08, 0xB3, 0x03, 0x86, 0x00,
+ 0x74, 0xFF, 0x9C, 0xFF, 0xF0, 0xFF, 0xF4, 0xFF, 0xA5, 0xFF, 0x6F,
+ 0xFF, 0x5A, 0x00, 0x54, 0x03, 0x32, 0x08, 0x52, 0x0D, 0x68, 0x10,
+ 0xE6, 0x0F, 0x11, 0x0C, 0xCA, 0x06, 0x52, 0x02, 0xEF, 0xFF, 0x6E,
+ 0xFF, 0xBF, 0xFF, 0xFC, 0xFF, 0xDF, 0xFF, 0x84, 0xFF, 0x91, 0xFF,
+ 0x25, 0x01, 0xE4, 0x04, 0x19, 0x0A, 0xC2, 0x0E, 0xAA, 0x10, 0xDA,
+ 0x0E, 0x3E, 0x0A, 0x05, 0x05, 0x38, 0x01, 0x96, 0xFF, 0x81, 0xFF,
+ 0xDD, 0xFF, 0x00, 0x00, 0xFD, 0xFF, 0xC1, 0xFF, 0x6E, 0xFF, 0xE6,
+ 0xFF, 0x3A, 0x02, 0xA6, 0x06, 0xEF, 0x0B, 0xD6, 0x0F, 0x71, 0x10,
+ 0x71, 0x0D, 0x57, 0x08, 0x71, 0x03, 0x67, 0x00, 0x70, 0xFF, 0xA2,
+ 0xFF, 0xF3, 0xFF, 0xF1, 0xFF, 0x9F, 0xFF, 0x72, 0xFF, 0x78, 0x00,
+ 0x95, 0x03, 0x86, 0x08, 0x98, 0x0D, 0x7C, 0x10, 0xC0, 0x0F, 0xC3,
+ 0x0B, 0x79, 0x06, 0x1C, 0x02, 0xDB, 0xFF, 0x70, 0xFF, 0xC5, 0xFF,
+ 0xFE, 0xFF, 0x00, 0x00, 0xDB, 0xFF, 0x7F, 0xFF, 0x9C, 0xFF, 0x50,
+ 0x01, 0x2F, 0x05, 0x6C, 0x0A, 0xF9, 0x0E, 0xA9, 0x10, 0xA2, 0x0E,
+ 0xEA, 0x09, 0xBB, 0x04, 0x0F, 0x01, 0x8C, 0xFF, 0x87, 0xFF, 0xE2,
+ 0xFF, 0xFC, 0xFF, 0xBC, 0xFF, 0x6D, 0xFF, 0xFA, 0xFF, 0x71, 0x02,
+ 0xF7, 0x06, 0x3C, 0x0C, 0xFB, 0x0F, 0x5B, 0x10, 0x2B, 0x0D, 0x03,
+ 0x08, 0x31, 0x03, 0x4A, 0x00, 0x6E, 0xFF, 0xA8, 0xFF, 0xF5, 0xFF,
+ 0xEE, 0xFF, 0x99, 0xFF, 0x76, 0xFF, 0x98, 0x00, 0xD8, 0x03, 0xDB,
+ 0x08, 0xDB, 0x0D, 0x8D, 0x10, 0x96, 0x0F, 0x73, 0x0B, 0x29, 0x06,
+ 0xE8, 0x01, 0xC9, 0xFF, 0x72, 0xFF, 0xCA, 0xFF, 0xFE, 0xFF, 0x00,
+ 0x00, 0xD6, 0xFF, 0x7A, 0xFF, 0xA8, 0xFF, 0x7D, 0x01, 0x7B, 0x05,
+ 0xBF, 0x0A, 0x2D, 0x0F, 0xA5, 0x10, 0x67, 0x0E, 0x96, 0x09, 0x73,
+ 0x04, 0xE7, 0x00, 0x84, 0xFF, 0x8C, 0xFF, 0xE6, 0xFF, 0xFA, 0xFF,
+ 0xB6, 0xFF, 0x6C, 0xFF, 0x11, 0x00, 0xAA, 0x02, 0x4A, 0x07, 0x88,
+ 0x0C, 0x1C, 0x10, 0x41, 0x10, 0xE3, 0x0C, 0xAF, 0x07, 0xF3, 0x02,
+ 0x2F, 0x00, 0x6C, 0xFF, 0xAE, 0xFF, 0xF7, 0xFF, 0xEA, 0xFF, 0x93,
+ 0xFF, 0x7B, 0xFF, 0xBB, 0x00, 0x1C, 0x04, 0x2F, 0x09, 0x1B, 0x0E,
+ 0x9A, 0x10, 0x68, 0x0F, 0x23, 0x0B, 0xDA, 0x05, 0xB7, 0x01, 0xB9,
+ 0xFF, 0x76, 0xFF, 0xD0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xD1, 0xFF,
+ 0x76, 0xFF, 0xB6, 0xFF, 0xAC, 0x01, 0xC8, 0x05, 0x11, 0x0B, 0x5E,
+ 0x0F, 0x9C, 0x10, 0x29, 0x0E, 0x42, 0x09, 0x2C, 0x04, 0xC2, 0x00,
+ 0x7D, 0xFF, 0x92, 0xFF, 0xEA, 0xFF, 0xF8, 0xFF, 0xB0, 0xFF, 0x6C,
+ 0xFF, 0x29, 0x00, 0xE6, 0x02, 0x9D, 0x07, 0xD3, 0x0C, 0x3B, 0x10,
+ 0x23, 0x10, 0x99, 0x0C, 0x5C, 0x07, 0xB7, 0x02, 0x16, 0x00, 0x6C,
+ 0xFF, 0xB4, 0xFF, 0xF9, 0xFF, 0xE7, 0xFF, 0x8D, 0xFF, 0x82, 0xFF,
+ 0xDF, 0x00, 0x63, 0x04, 0x84, 0x09, 0x59, 0x0E, 0xA3, 0x10, 0x38,
+ 0x0F, 0xD1, 0x0A, 0x8C, 0x05, 0x87, 0x01, 0xAB, 0xFF, 0x79, 0xFF,
+ 0xD5, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0xCB, 0xFF, 0x73, 0xFF, 0xC6,
+ 0xFF, 0xDD, 0x01, 0x17, 0x06, 0x62, 0x0B, 0x8C, 0x0F, 0x90, 0x10,
+ 0xE9, 0x0D, 0xED, 0x08, 0xE7, 0x03, 0xA0, 0x00, 0x77, 0xFF, 0x97,
+ 0xFF, 0xED, 0xFF, 0xF6, 0xFF, 0xA9, 0xFF, 0x6D, 0xFF, 0x44, 0x00,
+ 0x23, 0x03, 0xF1, 0x07, 0x1B, 0x0D, 0x55, 0x10, 0x02, 0x10, 0x4D,
+ 0x0C, 0x0A, 0x07, 0x7E, 0x02, 0xFF, 0xFF, 0x6D, 0xFF, 0xBA, 0xFF,
+ 0xFB, 0xFF, 0xE3, 0xFF, 0x88, 0xFF, 0x8A, 0xFF, 0x06, 0x01, 0xAB,
+ 0x04, 0xD8, 0x09, 0x95, 0x0E, 0xA9, 0x10, 0x05, 0x0F, 0x7F, 0x0A,
+ 0x40, 0x05, 0x5A, 0x01, 0x9F, 0xFF, 0x7E, 0xFF, 0xDA, 0xFF, 0x00,
+ 0x00, 0xFE, 0xFF, 0xC6, 0xFF, 0x70, 0xFF, 0xD7, 0xFF, 0x10, 0x02,
+ 0x67, 0x06, 0xB1, 0x0B, 0xB7, 0x0F, 0x80, 0x10, 0xA7, 0x0D, 0x99,
+ 0x08, 0xA4, 0x03, 0x7F, 0x00, 0x73, 0xFF, 0x9D, 0xFF, 0xF0, 0xFF,
+ 0xF3, 0xFF, 0xA3, 0xFF, 0x70, 0xFF, 0x60, 0x00, 0x62, 0x03, 0x45,
+ 0x08, 0x62, 0x0D, 0x6C, 0x10, 0xDE, 0x0F, 0x00, 0x0C, 0xB8, 0x06,
+ 0x46, 0x02, 0xEA, 0xFF, 0x6E, 0xFF, 0xC0, 0xFF, 0xFD, 0xFF, 0x00,
+ 0x00, 0xDE, 0xFF, 0x83, 0xFF, 0x94, 0xFF, 0x2F, 0x01, 0xF4, 0x04,
+ 0x2B, 0x0A, 0xCE, 0x0E, 0xAA, 0x10, 0xCE, 0x0E, 0x2B, 0x0A, 0xF4,
+ 0x04, 0x2F, 0x01, 0x94, 0xFF, 0x83, 0xFF, 0xDE, 0xFF, 0xFD, 0xFF,
+ 0xC0, 0xFF, 0x6E, 0xFF, 0xEA, 0xFF, 0x46, 0x02, 0xB8, 0x06, 0x00,
+ 0x0C, 0xDE, 0x0F, 0x6C, 0x10, 0x62, 0x0D, 0x45, 0x08, 0x62, 0x03,
+ 0x60, 0x00, 0x70, 0xFF, 0xA3, 0xFF, 0xF3, 0xFF, 0xF0, 0xFF, 0x9D,
+ 0xFF, 0x73, 0xFF, 0x7F, 0x00, 0xA4, 0x03, 0x99, 0x08, 0xA7, 0x0D,
+ 0x80, 0x10, 0xB7, 0x0F, 0xB1, 0x0B, 0x67, 0x06, 0x10, 0x02, 0xD7,
+ 0xFF, 0x70, 0xFF, 0xC6, 0xFF, 0xFE, 0xFF, 0x00, 0x00, 0xDA, 0xFF,
+ 0x7E, 0xFF, 0x9F, 0xFF, 0x5A, 0x01, 0x40, 0x05, 0x7F, 0x0A, 0x05,
+ 0x0F, 0xA9, 0x10, 0x95, 0x0E, 0xD8, 0x09, 0xAB, 0x04, 0x06, 0x01,
+ 0x8A, 0xFF, 0x88, 0xFF, 0xE3, 0xFF, 0xFB, 0xFF, 0xBA, 0xFF, 0x6D,
+ 0xFF, 0xFF, 0xFF, 0x7E, 0x02, 0x0A, 0x07, 0x4D, 0x0C, 0x02, 0x10,
+ 0x55, 0x10, 0x1B, 0x0D, 0xF1, 0x07, 0x23, 0x03, 0x44, 0x00, 0x6D,
+ 0xFF, 0xA9, 0xFF, 0xF6, 0xFF, 0xED, 0xFF, 0x97, 0xFF, 0x77, 0xFF,
+ 0xA0, 0x00, 0xE7, 0x03, 0xED, 0x08, 0xE9, 0x0D, 0x90, 0x10, 0x8C,
+ 0x0F, 0x62, 0x0B, 0x17, 0x06, 0xDD, 0x01, 0xC6, 0xFF, 0x73, 0xFF,
+ 0xCB, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0xD5, 0xFF, 0x79, 0xFF, 0xAB,
+ 0xFF, 0x87, 0x01, 0x8C, 0x05, 0xD1, 0x0A, 0x38, 0x0F, 0xA3, 0x10,
+ 0x59, 0x0E, 0x84, 0x09, 0x63, 0x04, 0xDF, 0x00, 0x82, 0xFF, 0x8D,
+ 0xFF, 0xE7, 0xFF, 0xF9, 0xFF, 0xB4, 0xFF, 0x6C, 0xFF, 0x16, 0x00,
+ 0xB7, 0x02, 0x5C, 0x07, 0x99, 0x0C, 0x23, 0x10, 0x3B, 0x10, 0xD3,
+ 0x0C, 0x9D, 0x07, 0xE6, 0x02, 0x29, 0x00, 0x6C, 0xFF, 0xB0, 0xFF,
+ 0xF8, 0xFF, 0xEA, 0xFF, 0x92, 0xFF, 0x7D, 0xFF, 0xC2, 0x00, 0x2C,
+ 0x04, 0x42, 0x09, 0x29, 0x0E, 0x9C, 0x10, 0x5E, 0x0F, 0x11, 0x0B,
+ 0xC8, 0x05, 0xAC, 0x01, 0xB6, 0xFF, 0x76, 0xFF, 0xD1, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xD0, 0xFF, 0x76, 0xFF, 0xB9, 0xFF, 0xB7, 0x01,
+ 0xDA, 0x05, 0x23, 0x0B, 0x68, 0x0F, 0x9A, 0x10, 0x1B, 0x0E, 0x2F,
+ 0x09, 0x1C, 0x04, 0xBB, 0x00, 0x7B, 0xFF, 0x93, 0xFF, 0xEA, 0xFF,
+ 0xF7, 0xFF, 0xAE, 0xFF, 0x6C, 0xFF, 0x2F, 0x00, 0xF3, 0x02, 0xAF,
+ 0x07, 0xE3, 0x0C, 0x41, 0x10, 0x1C, 0x10, 0x88, 0x0C, 0x4A, 0x07,
+ 0xAA, 0x02, 0x11, 0x00, 0x6C, 0xFF, 0xB6, 0xFF, 0xFA, 0xFF, 0xE6,
+ 0xFF, 0x8C, 0xFF, 0x84, 0xFF, 0xE7, 0x00, 0x73, 0x04, 0x96, 0x09,
+ 0x67, 0x0E, 0xA5, 0x10, 0x2D, 0x0F, 0xBF, 0x0A, 0x7B, 0x05, 0x7D,
+ 0x01, 0xA8, 0xFF, 0x7A, 0xFF, 0xD6, 0xFF, 0x00, 0x00, 0xFE, 0xFF,
+ 0xCA, 0xFF, 0x72, 0xFF, 0xC9, 0xFF, 0xE8, 0x01, 0x29, 0x06, 0x73,
+ 0x0B, 0x96, 0x0F, 0x8D, 0x10, 0xDB, 0x0D, 0xDB, 0x08, 0xD8, 0x03,
+ 0x98, 0x00, 0x76, 0xFF, 0x99, 0xFF, 0xEE, 0xFF, 0xF5, 0xFF, 0xA8,
+ 0xFF, 0x6E, 0xFF, 0x4A, 0x00, 0x31, 0x03, 0x03, 0x08, 0x2B, 0x0D,
+ 0x5B, 0x10, 0xFB, 0x0F, 0x3C, 0x0C, 0xF7, 0x06, 0x71, 0x02, 0xFA,
+ 0xFF, 0x6D, 0xFF, 0xBC, 0xFF, 0xFC, 0xFF, 0xE2, 0xFF, 0x87, 0xFF,
+ 0x8C, 0xFF, 0x0F, 0x01, 0xBB, 0x04, 0xEA, 0x09, 0xA2, 0x0E, 0xA9,
+ 0x10, 0xF9, 0x0E, 0x6C, 0x0A, 0x2F, 0x05, 0x50, 0x01, 0x9C, 0xFF,
+ 0x7F, 0xFF, 0xDB, 0xFF, 0x00, 0x00, 0xFE, 0xFF, 0xC5, 0xFF, 0x70,
+ 0xFF, 0xDB, 0xFF, 0x1C, 0x02, 0x79, 0x06, 0xC3, 0x0B, 0xC0, 0x0F,
+ 0x7C, 0x10, 0x98, 0x0D, 0x86, 0x08, 0x95, 0x03, 0x78, 0x00, 0x72,
+ 0xFF, 0x9F, 0xFF, 0xF1, 0xFF, 0xF3, 0xFF, 0xA2, 0xFF, 0x70, 0xFF,
+ 0x67, 0x00, 0x71, 0x03, 0x57, 0x08, 0x71, 0x0D, 0x71, 0x10, 0xD6,
+ 0x0F, 0xEF, 0x0B, 0xA6, 0x06, 0x3A, 0x02, 0xE6, 0xFF, 0x6E, 0xFF,
+ 0xC1, 0xFF, 0xFD, 0xFF, 0x00, 0x00, 0xDD, 0xFF, 0x81, 0xFF, 0x96,
+ 0xFF, 0x38, 0x01, 0x05, 0x05, 0x3E, 0x0A, 0xDA, 0x0E, 0xAA, 0x10,
+ 0xC2, 0x0E, 0x19, 0x0A, 0xE4, 0x04, 0x25, 0x01, 0x91, 0xFF, 0x84,
+ 0xFF, 0xDF, 0xFF, 0xFC, 0xFF, 0xBF, 0xFF, 0x6E, 0xFF, 0xEF, 0xFF,
+ 0x52, 0x02, 0xCA, 0x06, 0x11, 0x0C, 0xE6, 0x0F, 0x68, 0x10, 0x52,
+ 0x0D, 0x32, 0x08, 0x54, 0x03, 0x5A, 0x00, 0x6F, 0xFF, 0xA5, 0xFF,
+ 0xF4, 0xFF, 0xF0, 0xFF, 0x9C, 0xFF, 0x74, 0xFF, 0x86, 0x00, 0xB3,
+ 0x03, 0xAC, 0x08, 0xB6, 0x0D, 0x84, 0x10, 0xAD, 0x0F, 0xA0, 0x0B,
+ 0x55, 0x06, 0x05, 0x02, 0xD3, 0xFF, 0x71, 0xFF, 0xC7, 0xFF, 0xFE,
+ 0xFF, 0x00, 0x00, 0xD9, 0xFF, 0x7D, 0xFF, 0xA1, 0xFF, 0x64, 0x01,
+ 0x50, 0x05, 0x91, 0x0A, 0x10, 0x0F, 0xA8, 0x10, 0x88, 0x0E, 0xC5,
+ 0x09, 0x9B, 0x04, 0xFD, 0x00, 0x88, 0xFF, 0x89, 0xFF, 0xE4, 0xFF,
+ 0xFB, 0xFF, 0xB9, 0xFF, 0x6C, 0xFF, 0x04, 0x00, 0x8A, 0x02, 0x1C,
+ 0x07, 0x5E, 0x0C, 0x0A, 0x10, 0x50, 0x10, 0x0B, 0x0D, 0xDE, 0x07,
+ 0x15, 0x03, 0x3E, 0x00, 0x6D, 0xFF, 0xAB, 0xFF, 0xF6, 0xFF, 0xEC,
+ 0xFF, 0x96, 0xFF, 0x78, 0xFF, 0xA7, 0x00, 0xF6, 0x03, 0x00, 0x09,
+ 0xF8, 0x0D, 0x93, 0x10, 0x82, 0x0F, 0x50, 0x0B, 0x06, 0x06, 0xD2,
+ 0x01, 0xC2, 0xFF, 0x74, 0xFF, 0xCD, 0xFF, 0xFF, 0xFF, 0x00, 0x00,
+ 0xD4, 0xFF, 0x79, 0xFF, 0xAE, 0xFF, 0x91, 0x01, 0x9D, 0x05, 0xE3,
+ 0x0A, 0x43, 0x0F, 0xA1, 0x10, 0x4C, 0x0E, 0x71, 0x09, 0x53, 0x04,
+ 0xD7, 0x00, 0x80, 0xFF, 0x8E, 0xFF, 0xE8, 0xFF, 0xF9, 0xFF, 0xB3,
+ 0xFF, 0x6C, 0xFF, 0x1C, 0x00, 0xC4, 0x02, 0x6F, 0x07, 0xAA, 0x0C,
+ 0x2A, 0x10, 0x34, 0x10, 0xC2, 0x0C, 0x8A, 0x07, 0xD8, 0x02, 0x24,
+ 0x00, 0x6C, 0xFF, 0xB1, 0xFF, 0xF8, 0xFF, 0xE9, 0xFF, 0x90, 0xFF,
+ 0x7E, 0xFF, 0xCB, 0x00, 0x3B, 0x04, 0x55, 0x09, 0x37, 0x0E, 0x9E,
+ 0x10, 0x53, 0x0F, 0xFF, 0x0A, 0xB7, 0x05, 0xA1, 0x01, 0xB3, 0xFF,
+ 0x77, 0xFF, 0xD2, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xCE, 0xFF, 0x75,
+ 0xFF, 0xBD, 0xFF, 0xC1, 0x01, 0xEB, 0x05, 0x35, 0x0B, 0x73, 0x0F,
+ 0x97, 0x10, 0x0D, 0x0E, 0x1C, 0x09, 0x0D, 0x04, 0xB3, 0x00, 0x7A,
+ 0xFF, 0x94, 0xFF, 0xEB, 0xFF, 0xF7, 0xFF, 0xAD, 0xFF, 0x6D, 0xFF,
+ 0x35, 0x00, 0x01, 0x03, 0xC2, 0x07, 0xF3, 0x0C, 0x47, 0x10, 0x15,
+ 0x10, 0x78, 0x0C, 0x37, 0x07, 0x9D, 0x02, 0x0C, 0x00, 0x6C, 0xFF,
+ 0xB7, 0xFF, 0xFA, 0xFF, 0xE5, 0xFF, 0x8B, 0xFF, 0x85, 0xFF, 0xF0,
+ 0x00, 0x83, 0x04, 0xA9, 0x09, 0x74, 0x0E, 0xA6, 0x10, 0x21, 0x0F,
+ 0xAD, 0x0A, 0x6A, 0x05, 0x73, 0x01, 0xA5, 0xFF, 0x7B, 0xFF, 0xD7,
+ 0xFF, 0x00, 0x00, 0xFE, 0xFF, 0xC9, 0xFF, 0x72, 0xFF, 0xCD, 0xFF,
+ 0xF4, 0x01, 0x3B, 0x06, 0x85, 0x0B, 0x9F, 0x0F, 0x89, 0x10, 0xCC,
+ 0x0D, 0xC8, 0x08, 0xC9, 0x03, 0x91, 0x00, 0x75, 0xFF, 0x9A, 0xFF,
+ 0xEF, 0xFF, 0xF5, 0xFF, 0xA7, 0xFF, 0x6E, 0xFF, 0x50, 0x00, 0x3F,
+ 0x03, 0x16, 0x08, 0x3B, 0x0D, 0x60, 0x10, 0xF3, 0x0F, 0x2B, 0x0C,
+ 0xE5, 0x06, 0x65, 0x02, 0xF6, 0xFF, 0x6D, 0xFF, 0xBD, 0xFF, 0xFC,
+ 0xFF, 0xE1, 0xFF, 0x85, 0xFF, 0x8E, 0xFF, 0x18, 0x01, 0xCB, 0x04,
+ 0xFD, 0x09, 0xAF, 0x0E, 0xAA, 0x10, 0xED, 0x0E, 0x5A, 0x0A, 0x1E,
+ 0x05, 0x46, 0x01, 0x9A, 0xFF, 0x80, 0xFF, 0xDC, 0xFF, 0x00, 0x00,
+ 0xFD, 0xFF, 0xC3, 0xFF, 0x6F, 0xFF, 0xDF, 0xFF, 0x28, 0x02, 0x8B,
+ 0x06, 0xD5, 0x0B, 0xC9, 0x0F, 0x78, 0x10, 0x88, 0x0D, 0x73, 0x08,
+ 0x86, 0x03, 0x71, 0x00, 0x71, 0xFF, 0xA0, 0xFF, 0xF2, 0xFF, 0xF2,
+ 0xFF, 0xA1, 0xFF, 0x71, 0xFF, 0x6E, 0x00, 0x7F, 0x03, 0x6A, 0x08,
+ 0x81, 0x0D, 0x76, 0x10, 0xCD, 0x0F, 0xDD, 0x0B, 0x94, 0x06, 0x2E,
+ 0x02, 0xE1, 0xFF, 0x6F, 0xFF, 0xC3, 0xFF, 0xFD, 0xFF, 0x00, 0x00,
+ 0xDC, 0xFF, 0x80, 0xFF, 0x98, 0xFF, 0x42, 0x01, 0x16, 0x05, 0x50,
+ 0x0A, 0xE7, 0x0E, 0xAA, 0x10, 0xB5, 0x0E, 0x06, 0x0A, 0xD3, 0x04,
+ 0x1C, 0x01, 0x8F, 0xFF, 0x85, 0xFF, 0xE0, 0xFF, 0xFC, 0xFF, 0xBE,
+ 0xFF, 0x6D, 0xFF, 0xF3, 0xFF, 0x5E, 0x02, 0xDC, 0x06, 0x23, 0x0C,
+ 0xEF, 0x0F, 0x63, 0x10, 0x43, 0x0D, 0x1F, 0x08, 0x46, 0x03, 0x53,
+ 0x00, 0x6E, 0xFF, 0xA6, 0xFF, 0xF4, 0xFF, 0xEF, 0xFF, 0x9B, 0xFF,
+ 0x75, 0xFF, 0x8D, 0x00, 0xC1, 0x03, 0xBE, 0x08, 0xC4, 0x0D, 0x88,
+ 0x10, 0xA4, 0x0F, 0x8E, 0x0B, 0x43, 0x06, 0xF9, 0x01, 0xCF, 0xFF,
+ 0x71, 0xFF, 0xC8, 0xFF, 0xFE, 0xFF, 0x00, 0x00, 0xD8, 0xFF, 0x7C,
+ 0xFF, 0xA4, 0xFF, 0x6E, 0x01, 0x61, 0x05, 0xA3, 0x0A, 0x1C, 0x0F,
+ 0xA7, 0x10, 0x7B, 0x0E, 0xB2, 0x09, 0x8B, 0x04, 0xF4, 0x00, 0x86,
+ 0xFF, 0x8A, 0xFF, 0xE4, 0xFF, 0xFA, 0xFF, 0xB8, 0xFF, 0x6C, 0xFF,
+ 0x09, 0x00, 0x97, 0x02, 0x2E, 0x07, 0x6F, 0x0C, 0x11, 0x10, 0x4A,
+ 0x10, 0xFB, 0x0C, 0xCB, 0x07, 0x07, 0x03, 0x38, 0x00, 0x6D, 0xFF,
+ 0xAC, 0xFF, 0xF7, 0xFF, 0xEC, 0xFF, 0x95, 0xFF, 0x79, 0xFF, 0xAF,
+ 0x00, 0x05, 0x04, 0x13, 0x09, 0x06, 0x0E, 0x96, 0x10, 0x78, 0x0F,
+ 0x3E, 0x0B, 0xF4, 0x05, 0xC7, 0x01, 0xBF, 0xFF, 0x74, 0xFF, 0xCE,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xD2, 0xFF, 0x78, 0xFF, 0xB1, 0xFF,
+ 0x9C, 0x01, 0xAE, 0x05, 0xF6, 0x0A, 0x4E, 0x0F, 0x9F, 0x10, 0x3E,
+ 0x0E, 0x5E, 0x09, 0x43, 0x04, 0xCF, 0x00, 0x7F, 0xFF, 0x90, 0xFF,
+ 0xE8, 0xFF, 0xF9, 0xFF, 0xB2, 0xFF, 0x6C, 0xFF, 0x21, 0x00, 0xD2,
+ 0x02, 0x81, 0x07, 0xBA, 0x0C, 0x31, 0x10, 0x2E, 0x10, 0xB2, 0x0C,
+ 0x78, 0x07, 0xCB, 0x02, 0x1E, 0x00, 0x6C, 0xFF, 0xB2, 0xFF, 0xF9,
+ 0xFF, 0xE8, 0xFF, 0x8F, 0xFF, 0x80, 0xFF, 0xD3, 0x00, 0x4B, 0x04,
+ 0x67, 0x09, 0x45, 0x0E, 0xA0, 0x10, 0x48, 0x0F, 0xEC, 0x0A, 0xA6,
+ 0x05, 0x97, 0x01, 0xB0, 0xFF, 0x78, 0xFF, 0xD3, 0xFF, 0x00, 0x00,
+ 0xFF, 0xFF, 0xCD, 0xFF, 0x74, 0xFF, 0xC0, 0xFF, 0xCC, 0x01, 0xFD,
+ 0x05, 0x47, 0x0B, 0x7D, 0x0F, 0x94, 0x10, 0xFF, 0x0D, 0x0A, 0x09,
+ 0xFE, 0x03, 0xAB, 0x00, 0x79, 0xFF, 0x95, 0xFF, 0xEC, 0xFF, 0xF7,
+ 0xFF, 0xAC, 0xFF, 0x6D, 0xFF, 0x3B, 0x00, 0x0E, 0x03, 0xD5, 0x07,
+ 0x03, 0x0D, 0x4D, 0x10, 0x0E, 0x10, 0x67, 0x0C, 0x25, 0x07, 0x91,
+ 0x02, 0x07, 0x00, 0x6C, 0xFF, 0xB8, 0xFF, 0xFB, 0xFF, 0xE4, 0xFF,
+ 0x89, 0xFF, 0x87, 0xFF, 0xF9, 0x00, 0x93, 0x04, 0xBC, 0x09, 0x82,
+ 0x0E, 0xA7, 0x10, 0x16, 0x0F, 0x9A, 0x0A, 0x59, 0x05, 0x69, 0x01,
+ 0xA3, 0xFF, 0x7C, 0xFF, 0xD8, 0xFF, 0x00, 0x00, 0xFE, 0xFF, 0xC8,
+ 0xFF, 0x71, 0xFF, 0xD1, 0xFF, 0xFF, 0x01, 0x4C, 0x06, 0x97, 0x0B,
+ 0xA9, 0x0F, 0x86, 0x10, 0xBD, 0x0D, 0xB5, 0x08, 0xBA, 0x03, 0x8A,
+ 0x00, 0x74, 0xFF, 0x9B, 0xFF, 0xEF, 0xFF, 0xF4, 0xFF, 0xA5, 0xFF,
+ 0x6F, 0xFF, 0x57, 0x00, 0x4D, 0x03, 0x29, 0x08, 0x4B, 0x0D, 0x65,
+ 0x10, 0xEB, 0x0F, 0x1A, 0x0C, 0xD3, 0x06, 0x58, 0x02, 0xF1, 0xFF,
+ 0x6D, 0xFF, 0xBE, 0xFF, 0xFC, 0xFF, 0xE0, 0xFF, 0x84, 0xFF, 0x90,
+ 0xFF, 0x21, 0x01, 0xDC, 0x04, 0x10, 0x0A, 0xBB, 0x0E, 0xAA, 0x10,
+ 0xE1, 0x0E, 0x47, 0x0A, 0x0D, 0x05, 0x3D, 0x01, 0x97, 0xFF, 0x81,
+ 0xFF, 0xDD, 0xFF, 0x00, 0x00, 0xFD, 0xFF, 0xC2, 0xFF, 0x6F, 0xFF,
+ 0xE4, 0xFF, 0x34, 0x02, 0x9D, 0x06, 0xE6, 0x0B, 0xD1, 0x0F, 0x73,
+ 0x10, 0x79, 0x0D, 0x61, 0x08, 0x78, 0x03, 0x6A, 0x00, 0x70, 0xFF,
+ 0xA1, 0xFF, 0xF2, 0xFF, 0xF1, 0xFF, 0x9F, 0xFF, 0x72, 0xFF, 0x74,
+ 0x00, 0x8E, 0x03, 0x7D, 0x08, 0x90, 0x0D, 0x7A, 0x10, 0xC4, 0x0F,
+ 0xCC, 0x0B, 0x82, 0x06, 0x22, 0x02, 0xDD, 0xFF, 0x6F, 0xFF, 0xC4,
+ 0xFF, 0xFD, 0xFF, 0x00, 0x00, 0xDB, 0xFF, 0x7F, 0xFF, 0x9B, 0xFF,
+ 0x4B, 0x01, 0x26, 0x05, 0x63, 0x0A, 0xF3, 0x0E, 0xAA, 0x10, 0xA8,
+ 0x0E, 0xF4, 0x09, 0xC3, 0x04, 0x13, 0x01, 0x8D, 0xFF, 0x86, 0xFF,
+ 0xE1, 0xFF, 0xFC, 0xFF, 0xBC, 0xFF, 0x6D, 0xFF, 0xF8, 0xFF, 0x6B,
+ 0x02, 0xEE, 0x06, 0x34, 0x0C, 0xF7, 0x0F, 0x5D, 0x10, 0x33, 0x0D,
+ 0x0D, 0x08, 0x38, 0x03, 0x4D, 0x00, 0x6E, 0xFF, 0xA7, 0xFF, 0xF5,
+ 0xFF, 0xEE, 0xFF, 0x99, 0xFF, 0x76, 0xFF, 0x94, 0x00, 0xD0, 0x03,
+ 0xD1, 0x08, 0xD3, 0x0D, 0x8B, 0x10, 0x9A, 0x0F, 0x7C, 0x0B, 0x32,
+ 0x06, 0xEE, 0x01, 0xCB, 0xFF, 0x72, 0xFF, 0xCA, 0xFF, 0xFE, 0xFF,
+ 0x00, 0x00, 0xD6, 0xFF, 0x7B, 0xFF, 0xA7, 0xFF, 0x78, 0x01, 0x72,
+ 0x05, 0xB6, 0x0A, 0x27, 0x0F, 0xA5, 0x10, 0x6E, 0x0E, 0xA0, 0x09,
+ 0x7B, 0x04, 0xEC, 0x00, 0x85, 0xFF, 0x8B, 0xFF, 0xE5, 0xFF, 0xFA,
+ 0xFF, 0xB6, 0xFF, 0x6C, 0xFF, 0x0E, 0x00, 0xA4, 0x02, 0x41, 0x07,
+ 0x80, 0x0C, 0x19, 0x10, 0x44, 0x10, 0xEB, 0x0C, 0xB9, 0x07, 0xFA,
+ 0x02, 0x32, 0x00, 0x6D, 0xFF, 0xAE, 0xFF, 0xF7, 0xFF, 0xEB, 0xFF,
+ 0x93, 0xFF, 0x7B, 0xFF, 0xB7, 0x00, 0x15, 0x04, 0x26, 0x09, 0x14,
+ 0x0E, 0x98, 0x10, 0x6D, 0x0F, 0x2C, 0x0B, 0xE3, 0x05, 0xBC, 0x01,
+ 0xBB, 0xFF, 0x75, 0xFF, 0xCF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xD1,
+ 0xFF, 0x77, 0xFF, 0xB5, 0xFF, 0xA6, 0x01, 0xC0, 0x05, 0x08, 0x0B,
+ 0x58, 0x0F, 0x9D, 0x10, 0x30, 0x0E, 0x4B, 0x09, 0x34, 0x04, 0xC6,
+ 0x00, 0x7D, 0xFF, 0x91, 0xFF, 0xE9, 0xFF, 0xF8, 0xFF, 0xB0, 0xFF,
+ 0x6C, 0xFF, 0x27, 0x00, 0xDF, 0x02, 0x94, 0x07, 0xCA, 0x0C, 0x37,
+ 0x10, 0x27, 0x10, 0xA1, 0x0C, 0x65, 0x07, 0xBE, 0x02, 0x19, 0x00,
+ 0x6C, 0xFF, 0xB4, 0xFF, 0xF9, 0xFF, 0xE7, 0xFF, 0x8E, 0xFF, 0x81,
+ 0xFF, 0xDB, 0x00, 0x5B, 0x04, 0x7A, 0x09, 0x53, 0x0E, 0xA2, 0x10,
+ 0x3D, 0x0F, 0xDA, 0x0A, 0x95, 0x05, 0x8C, 0x01, 0xAD, 0xFF, 0x79,
+ 0xFF, 0xD4, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0xCC, 0xFF, 0x73, 0xFF,
+ 0xC4, 0xFF, 0xD7, 0x01, 0x0E, 0x06, 0x59, 0x0B, 0x87, 0x0F, 0x91,
+ 0x10, 0xF0, 0x0D, 0xF7, 0x08, 0xEF, 0x03, 0xA3, 0x00, 0x78, 0xFF,
+ 0x97, 0xFF, 0xED, 0xFF, 0xF6, 0xFF, 0xAA, 0xFF, 0x6D, 0xFF, 0x41,
+ 0x00, 0x1C, 0x03, 0xE7, 0x07, 0x13, 0x0D, 0x52, 0x10, 0x06, 0x10,
+ 0x56, 0x0C, 0x13, 0x07, 0x84, 0x02, 0x02, 0x00, 0x6D, 0xFF, 0xBA,
+ 0xFF, 0xFB, 0xFF, 0xE3, 0xFF, 0x88, 0xFF, 0x89, 0xFF, 0x01, 0x01,
+ 0xA3, 0x04, 0xCE, 0x09, 0x8F, 0x0E, 0xA8, 0x10, 0x0A, 0x0F, 0x88,
+ 0x0A, 0x48, 0x05, 0x5F, 0x01, 0xA0, 0xFF, 0x7D, 0xFF, 0xD9, 0xFF,
+ 0x00, 0x00, 0xFE, 0xFF, 0xC7, 0xFF, 0x70, 0xFF, 0xD5, 0xFF, 0x0B,
+ 0x02, 0x5E, 0x06, 0xA9, 0x0B, 0xB2, 0x0F, 0x82, 0x10, 0xAE, 0x0D,
+ 0xA2, 0x08, 0xAB, 0x03, 0x82, 0x00, 0x73, 0xFF, 0x9D, 0xFF, 0xF0,
+ 0xFF, 0xF3, 0xFF, 0xA4, 0xFF, 0x6F, 0xFF, 0x5D, 0x00, 0x5B, 0x03,
+ 0x3B, 0x08, 0x5A, 0x0D, 0x6A, 0x10, 0xE2, 0x0F, 0x09, 0x0C, 0xC1,
+ 0x06, 0x4C, 0x02, 0xEC, 0xFF, 0x6E, 0xFF, 0xC0, 0xFF, 0xFC, 0xFF,
+ 0xDF, 0xFF, 0x83, 0xFF, 0x93, 0xFF, 0x2A, 0x01, 0xEC, 0x04, 0x22,
+ 0x0A, 0xC8, 0x0E, 0xAB, 0x10, 0xD4, 0x0E, 0x35, 0x0A, 0xFD, 0x04,
+ 0x33, 0x01, 0x95, 0xFF, 0x82, 0xFF, 0xDE, 0xFF, 0x00, 0x00, 0xFD,
+ 0xFF, 0xC1, 0xFF, 0x6E, 0xFF, 0xE8, 0xFF, 0x40, 0x02, 0xAF, 0x06,
+ 0xF7, 0x0B, 0xDA, 0x0F, 0x6F, 0x10, 0x6A, 0x0D, 0x4E, 0x08, 0x6A,
+ 0x03, 0x64, 0x00, 0x70, 0xFF, 0xA3, 0xFF, 0xF3, 0xFF, 0xF1, 0xFF,
+ 0x9E, 0xFF, 0x72, 0xFF, 0x7B, 0x00, 0x9C, 0x03, 0x90, 0x08, 0x9F,
+ 0x0D, 0x7E, 0x10, 0xBB, 0x0F, 0xBA, 0x0B, 0x70, 0x06, 0x16, 0x02,
+ 0xD9, 0xFF, 0x70, 0xFF, 0xC5, 0xFF, 0xFE, 0xFF, 0x00, 0x00, 0xDA,
+ 0xFF, 0x7E, 0xFF, 0x9D, 0xFF, 0x55, 0x01, 0x37, 0x05, 0x75, 0x0A,
+ 0xFF, 0x0E, 0xA9, 0x10, 0x9C, 0x0E, 0xE1, 0x09, 0xB3, 0x04, 0x0A,
+ 0x01, 0x8B, 0xFF, 0x87, 0xFF, 0xE2, 0xFF, 0xFB, 0xFF, 0xBB, 0xFF,
+ 0x6D, 0xFF, 0xFD, 0xFF, 0x77, 0x02, 0x01, 0x07, 0x45, 0x0C, 0xFF,
+ 0x0F, 0x58, 0x10, 0x23, 0x0D, 0xFA, 0x07, 0x2A, 0x03, 0x47, 0x00,
+ 0x6E, 0xFF, 0xA9, 0xFF, 0xF5, 0xFF, 0xED, 0xFF, 0x98, 0xFF, 0x77,
+ 0xFF, 0x9C, 0x00, 0xDF, 0x03, 0xE4, 0x08, 0xE2, 0x0D, 0x8E, 0x10,
+ 0x91, 0x0F, 0x6B, 0x0B, 0x20, 0x06, 0xE3, 0x01, 0xC8, 0xFF, 0x73,
+ 0xFF, 0xCB, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0xD5, 0xFF, 0x7A, 0xFF,
+ 0xAA, 0xFF, 0x82, 0x01, 0x83, 0x05, 0xC8, 0x0A, 0x32, 0x0F, 0xA4,
+ 0x10, 0x60, 0x0E, 0x8D, 0x09, 0x6B, 0x04, 0xE3, 0x00, 0x83, 0xFF,
+ 0x8D, 0xFF, 0xE6, 0xFF, 0xFA, 0xFF, 0xB5, 0xFF, 0x6C, 0xFF, 0x14,
+ 0x00, 0xB1, 0x02, 0x53, 0x07, 0x91, 0x0C, 0x20, 0x10, 0x3E, 0x10,
+ 0xDB, 0x0C, 0xA6, 0x07, 0xEC, 0x02, 0x2C, 0x00, 0x6C, 0xFF, 0xAF,
+ 0xFF, 0xF8, 0xFF, 0xEA, 0xFF, 0x92, 0xFF, 0x7C, 0xFF, 0xBE, 0x00,
+ 0x24, 0x04, 0x38, 0x09, 0x22, 0x0E, 0x9B, 0x10, 0x63, 0x0F, 0x1A,
+ 0x0B, 0xD1, 0x05, 0xB1, 0x01, 0xB8, 0xFF, 0x76, 0xFF, 0xD0, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xD0, 0xFF, 0x76, 0xFF, 0xB8, 0xFF, 0xB1,
+ 0x01, 0xD1, 0x05, 0x1A, 0x0B, 0x63, 0x0F, 0x9B, 0x10, 0x22, 0x0E,
+ 0x38, 0x09, 0x24, 0x04, 0xBE, 0x00, 0x7C, 0xFF, 0x92, 0xFF, 0xEA,
+ 0xFF, 0xF8, 0xFF, 0xAF, 0xFF, 0x6C, 0xFF, 0x2C, 0x00, 0xEC, 0x02,
+ 0xA6, 0x07, 0xDB, 0x0C, 0x3E, 0x10, 0x20, 0x10, 0x91, 0x0C, 0x53,
+ 0x07, 0xB1, 0x02, 0x14, 0x00, 0x6C, 0xFF, 0xB5, 0xFF, 0xFA, 0xFF,
+ 0xE6, 0xFF, 0x8D, 0xFF, 0x83, 0xFF, 0xE3, 0x00, 0x6B, 0x04, 0x8D,
+ 0x09, 0x60, 0x0E, 0xA4, 0x10, 0x32, 0x0F, 0xC8, 0x0A, 0x83, 0x05,
+ 0x82, 0x01, 0xAA, 0xFF, 0x7A, 0xFF, 0xD5, 0xFF, 0x00, 0x00, 0xFF,
+ 0xFF, 0xCB, 0xFF, 0x73, 0xFF, 0xC8, 0xFF, 0xE3, 0x01, 0x20, 0x06,
+ 0x6B, 0x0B, 0x91, 0x0F, 0x8E, 0x10, 0xE2, 0x0D, 0xE4, 0x08, 0xDF,
+ 0x03, 0x9C, 0x00, 0x77, 0xFF, 0x98, 0xFF, 0xED, 0xFF, 0xF5, 0xFF,
+ 0xA9, 0xFF, 0x6E, 0xFF, 0x47, 0x00, 0x2A, 0x03, 0xFA, 0x07, 0x23,
+ 0x0D, 0x58, 0x10, 0xFF, 0x0F, 0x45, 0x0C, 0x01, 0x07, 0x77, 0x02,
+ 0xFD, 0xFF, 0x6D, 0xFF, 0xBB, 0xFF, 0xFB, 0xFF, 0xE2, 0xFF, 0x87,
+ 0xFF, 0x8B, 0xFF, 0x0A, 0x01, 0xB3, 0x04, 0xE1, 0x09, 0x9C, 0x0E,
+ 0xA9, 0x10, 0xFF, 0x0E, 0x75, 0x0A, 0x37, 0x05, 0x55, 0x01, 0x9D,
+ 0xFF, 0x7E, 0xFF, 0xDA, 0xFF, 0x00, 0x00, 0xFE, 0xFF, 0xC5, 0xFF,
+ 0x70, 0xFF, 0xD9, 0xFF, 0x16, 0x02, 0x70, 0x06, 0xBA, 0x0B, 0xBB,
+ 0x0F, 0x7E, 0x10, 0x9F, 0x0D, 0x90, 0x08, 0x9C, 0x03, 0x7B, 0x00,
+ 0x72, 0xFF, 0x9E, 0xFF, 0xF1, 0xFF, 0xF3, 0xFF, 0xA3, 0xFF, 0x70,
+ 0xFF, 0x64, 0x00, 0x6A, 0x03, 0x4E, 0x08, 0x6A, 0x0D, 0x6F, 0x10,
+ 0xDA, 0x0F, 0xF7, 0x0B, 0xAF, 0x06, 0x40, 0x02, 0xE8, 0xFF, 0x6E,
+ 0xFF, 0xC1, 0xFF, 0xFD, 0xFF, 0x00, 0x00, 0xDE, 0xFF, 0x82, 0xFF,
+ 0x95, 0xFF, 0x33, 0x01, 0xFD, 0x04, 0x35, 0x0A, 0xD4, 0x0E, 0xAB,
+ 0x10, 0xC8, 0x0E, 0x22, 0x0A, 0xEC, 0x04, 0x2A, 0x01, 0x93, 0xFF,
+ 0x83, 0xFF, 0xDF, 0xFF, 0xFC, 0xFF, 0xC0, 0xFF, 0x6E, 0xFF, 0xEC,
+ 0xFF, 0x4C, 0x02, 0xC1, 0x06, 0x09, 0x0C, 0xE2, 0x0F, 0x6A, 0x10,
+ 0x5A, 0x0D, 0x3B, 0x08, 0x5B, 0x03, 0x5D, 0x00, 0x6F, 0xFF, 0xA4,
+ 0xFF, 0xF3, 0xFF, 0xF0, 0xFF, 0x9D, 0xFF, 0x73, 0xFF, 0x82, 0x00,
+ 0xAB, 0x03, 0xA2, 0x08, 0xAE, 0x0D, 0x82, 0x10, 0xB2, 0x0F, 0xA9,
+ 0x0B, 0x5E, 0x06, 0x0B, 0x02, 0xD5, 0xFF, 0x70, 0xFF, 0xC7, 0xFF,
+ 0xFE, 0xFF, 0x00, 0x00, 0xD9, 0xFF, 0x7D, 0xFF, 0xA0, 0xFF, 0x5F,
+ 0x01, 0x48, 0x05, 0x88, 0x0A, 0x0A, 0x0F, 0xA8, 0x10, 0x8F, 0x0E,
+ 0xCE, 0x09, 0xA3, 0x04, 0x01, 0x01, 0x89, 0xFF, 0x88, 0xFF, 0xE3,
+ 0xFF, 0xFB, 0xFF, 0xBA, 0xFF, 0x6D, 0xFF, 0x02, 0x00, 0x84, 0x02,
+ 0x13, 0x07, 0x56, 0x0C, 0x06, 0x10, 0x52, 0x10, 0x13, 0x0D, 0xE7,
+ 0x07, 0x1C, 0x03, 0x41, 0x00, 0x6D, 0xFF, 0xAA, 0xFF, 0xF6, 0xFF,
+ 0xED, 0xFF, 0x97, 0xFF, 0x78, 0xFF, 0xA3, 0x00, 0xEF, 0x03, 0xF7,
+ 0x08, 0xF0, 0x0D, 0x91, 0x10, 0x87, 0x0F, 0x59, 0x0B, 0x0E, 0x06,
+ 0xD7, 0x01, 0xC4, 0xFF, 0x73, 0xFF, 0xCC, 0xFF, 0xFF, 0xFF, 0x00,
+ 0x00, 0xD4, 0xFF, 0x79, 0xFF, 0xAD, 0xFF, 0x8C, 0x01, 0x95, 0x05,
+ 0xDA, 0x0A, 0x3D, 0x0F, 0xA2, 0x10, 0x53, 0x0E, 0x7A, 0x09, 0x5B,
+ 0x04, 0xDB, 0x00, 0x81, 0xFF, 0x8E, 0xFF, 0xE7, 0xFF, 0xF9, 0xFF,
+ 0xB4, 0xFF, 0x6C, 0xFF, 0x19, 0x00, 0xBE, 0x02, 0x65, 0x07, 0xA1,
+ 0x0C, 0x27, 0x10, 0x37, 0x10, 0xCA, 0x0C, 0x94, 0x07, 0xDF, 0x02,
+ 0x27, 0x00, 0x6C, 0xFF, 0xB0, 0xFF, 0xF8, 0xFF, 0xE9, 0xFF, 0x91,
+ 0xFF, 0x7D, 0xFF, 0xC6, 0x00, 0x34, 0x04, 0x4B, 0x09, 0x30, 0x0E,
+ 0x9D, 0x10, 0x58, 0x0F, 0x08, 0x0B, 0xC0, 0x05, 0xA6, 0x01, 0xB5,
+ 0xFF, 0x77, 0xFF, 0xD1, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xCF, 0xFF,
+ 0x75, 0xFF, 0xBB, 0xFF, 0xBC, 0x01, 0xE3, 0x05, 0x2C, 0x0B, 0x6D,
+ 0x0F, 0x98, 0x10, 0x14, 0x0E, 0x26, 0x09, 0x15, 0x04, 0xB7, 0x00,
+ 0x7B, 0xFF, 0x93, 0xFF, 0xEB, 0xFF, 0xF7, 0xFF, 0xAE, 0xFF, 0x6D,
+ 0xFF, 0x32, 0x00, 0xFA, 0x02, 0xB9, 0x07, 0xEB, 0x0C, 0x44, 0x10,
+ 0x19, 0x10, 0x80, 0x0C, 0x41, 0x07, 0xA4, 0x02, 0x0E, 0x00, 0x6C,
+ 0xFF, 0xB6, 0xFF, 0xFA, 0xFF, 0xE5, 0xFF, 0x8B, 0xFF, 0x85, 0xFF,
+ 0xEC, 0x00, 0x7B, 0x04, 0xA0, 0x09, 0x6E, 0x0E, 0xA5, 0x10, 0x27,
+ 0x0F, 0xB6, 0x0A, 0x72, 0x05, 0x78, 0x01, 0xA7, 0xFF, 0x7B, 0xFF,
+ 0xD6, 0xFF, 0x00, 0x00, 0xFE, 0xFF, 0xCA, 0xFF, 0x72, 0xFF, 0xCB,
+ 0xFF, 0xEE, 0x01, 0x32, 0x06, 0x7C, 0x0B, 0x9A, 0x0F, 0x8B, 0x10,
+ 0xD3, 0x0D, 0xD1, 0x08, 0xD0, 0x03, 0x94, 0x00, 0x76, 0xFF, 0x99,
+ 0xFF, 0xEE, 0xFF, 0xF5, 0xFF, 0xA7, 0xFF, 0x6E, 0xFF, 0x4D, 0x00,
+ 0x38, 0x03, 0x0D, 0x08, 0x33, 0x0D, 0x5D, 0x10, 0xF7, 0x0F, 0x34,
+ 0x0C, 0xEE, 0x06, 0x6B, 0x02, 0xF8, 0xFF, 0x6D, 0xFF, 0xBC, 0xFF,
+ 0xFC, 0xFF, 0xE1, 0xFF, 0x86, 0xFF, 0x8D, 0xFF, 0x13, 0x01, 0xC3,
+ 0x04, 0xF4, 0x09, 0xA8, 0x0E, 0xAA, 0x10, 0xF3, 0x0E, 0x63, 0x0A,
+ 0x26, 0x05, 0x4B, 0x01, 0x9B, 0xFF, 0x7F, 0xFF, 0xDB, 0xFF, 0x00,
+ 0x00, 0xFD, 0xFF, 0xC4, 0xFF, 0x6F, 0xFF, 0xDD, 0xFF, 0x22, 0x02,
+ 0x82, 0x06, 0xCC, 0x0B, 0xC4, 0x0F, 0x7A, 0x10, 0x90, 0x0D, 0x7D,
+ 0x08, 0x8E, 0x03, 0x74, 0x00, 0x72, 0xFF, 0x9F, 0xFF, 0xF1, 0xFF,
+ 0xF2, 0xFF, 0xA1, 0xFF, 0x70, 0xFF, 0x6A, 0x00, 0x78, 0x03, 0x61,
+ 0x08, 0x79, 0x0D, 0x73, 0x10, 0xD1, 0x0F, 0xE6, 0x0B, 0x9D, 0x06,
+ 0x34, 0x02, 0xE4, 0xFF, 0x6F, 0xFF, 0xC2, 0xFF, 0xFD, 0xFF, 0x00,
+ 0x00, 0xDD, 0xFF, 0x81, 0xFF, 0x97, 0xFF, 0x3D, 0x01, 0x0D, 0x05,
+ 0x47, 0x0A, 0xE1, 0x0E, 0xAA, 0x10, 0xBB, 0x0E, 0x10, 0x0A, 0xDC,
+ 0x04, 0x21, 0x01, 0x90, 0xFF, 0x84, 0xFF, 0xE0, 0xFF, 0xFC, 0xFF,
+ 0xBE, 0xFF, 0x6D, 0xFF, 0xF1, 0xFF, 0x58, 0x02, 0xD3, 0x06, 0x1A,
+ 0x0C, 0xEB, 0x0F, 0x65, 0x10, 0x4B, 0x0D, 0x29, 0x08, 0x4D, 0x03,
+ 0x57, 0x00, 0x6F, 0xFF, 0xA5, 0xFF, 0xF4, 0xFF, 0xEF, 0xFF, 0x9B,
+ 0xFF, 0x74, 0xFF, 0x8A, 0x00, 0xBA, 0x03, 0xB5, 0x08, 0xBD, 0x0D,
+ 0x86, 0x10, 0xA9, 0x0F, 0x97, 0x0B, 0x4C, 0x06, 0xFF, 0x01, 0xD1,
+ 0xFF, 0x71, 0xFF, 0xC8, 0xFF, 0xFE, 0xFF, 0x00, 0x00, 0xD8, 0xFF,
+ 0x7C, 0xFF, 0xA3, 0xFF, 0x69, 0x01, 0x59, 0x05, 0x9A, 0x0A, 0x16,
+ 0x0F, 0xA7, 0x10, 0x82, 0x0E, 0xBC, 0x09, 0x93, 0x04, 0xF9, 0x00,
+ 0x87, 0xFF, 0x89, 0xFF, 0xE4, 0xFF, 0xFB, 0xFF, 0xB8, 0xFF, 0x6C,
+ 0xFF, 0x07, 0x00, 0x91, 0x02, 0x25, 0x07, 0x67, 0x0C, 0x0E, 0x10,
+ 0x4D, 0x10, 0x03, 0x0D, 0xD5, 0x07, 0x0E, 0x03, 0x3B, 0x00, 0x6D,
+ 0xFF, 0xAC, 0xFF, 0xF7, 0xFF, 0xEC, 0xFF, 0x95, 0xFF, 0x79, 0xFF,
+ 0xAB, 0x00, 0xFE, 0x03, 0x0A, 0x09, 0xFF, 0x0D, 0x94, 0x10, 0x7D,
+ 0x0F, 0x47, 0x0B, 0xFD, 0x05, 0xCC, 0x01, 0xC0, 0xFF, 0x74, 0xFF,
+ 0xCD, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0xD3, 0xFF, 0x78, 0xFF, 0xB0,
+ 0xFF, 0x97, 0x01, 0xA6, 0x05, 0xEC, 0x0A, 0x48, 0x0F, 0xA0, 0x10,
+ 0x45, 0x0E, 0x67, 0x09, 0x4B, 0x04, 0xD3, 0x00, 0x80, 0xFF, 0x8F,
+ 0xFF, 0xE8, 0xFF, 0xF9, 0xFF, 0xB2, 0xFF, 0x6C, 0xFF, 0x1E, 0x00,
+ 0xCB, 0x02, 0x78, 0x07, 0xB2, 0x0C, 0x2E, 0x10, 0x31, 0x10, 0xBA,
+ 0x0C, 0x81, 0x07, 0xD2, 0x02, 0x21, 0x00, 0x6C, 0xFF, 0xB2, 0xFF,
+ 0xF9, 0xFF, 0xE8, 0xFF, 0x90, 0xFF, 0x7F, 0xFF, 0xCF, 0x00, 0x43,
+ 0x04, 0x5E, 0x09, 0x3E, 0x0E, 0x9F, 0x10, 0x4E, 0x0F, 0xF6, 0x0A,
+ 0xAE, 0x05, 0x9C, 0x01, 0xB1, 0xFF, 0x78, 0xFF, 0xD2, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xCE, 0xFF, 0x74, 0xFF, 0xBF, 0xFF, 0xC7, 0x01,
+ 0xF4, 0x05, 0x3E, 0x0B, 0x78, 0x0F, 0x96, 0x10, 0x06, 0x0E, 0x13,
+ 0x09, 0x05, 0x04, 0xAF, 0x00, 0x79, 0xFF, 0x95, 0xFF, 0xEC, 0xFF,
+ 0xF7, 0xFF, 0xAC, 0xFF, 0x6D, 0xFF, 0x38, 0x00, 0x07, 0x03, 0xCB,
+ 0x07, 0xFB, 0x0C, 0x4A, 0x10, 0x11, 0x10, 0x6F, 0x0C, 0x2E, 0x07,
+ 0x97, 0x02, 0x09, 0x00, 0x6C, 0xFF, 0xB8, 0xFF, 0xFA, 0xFF, 0xE4,
+ 0xFF, 0x8A, 0xFF, 0x86, 0xFF, 0xF4, 0x00, 0x8B, 0x04, 0xB2, 0x09,
+ 0x7B, 0x0E, 0xA7, 0x10, 0x1C, 0x0F, 0xA3, 0x0A, 0x61, 0x05, 0x6E,
+ 0x01, 0xA4, 0xFF, 0x7C, 0xFF, 0xD8, 0xFF, 0x00, 0x00, 0xFE, 0xFF,
+ 0xC8, 0xFF, 0x71, 0xFF, 0xCF, 0xFF, 0xF9, 0x01, 0x43, 0x06, 0x8E,
+ 0x0B, 0xA4, 0x0F, 0x88, 0x10, 0xC4, 0x0D, 0xBE, 0x08, 0xC1, 0x03,
+ 0x8D, 0x00, 0x75, 0xFF, 0x9B, 0xFF, 0xEF, 0xFF, 0xF4, 0xFF, 0xA6,
+ 0xFF, 0x6E, 0xFF, 0x53, 0x00, 0x46, 0x03, 0x1F, 0x08, 0x43, 0x0D,
+ 0x63, 0x10, 0xEF, 0x0F, 0x23, 0x0C, 0xDC, 0x06, 0x5E, 0x02, 0xF3,
+ 0xFF, 0x6D, 0xFF, 0xBE, 0xFF, 0xFC, 0xFF, 0xE0, 0xFF, 0x85, 0xFF,
+ 0x8F, 0xFF, 0x1C, 0x01, 0xD3, 0x04, 0x06, 0x0A, 0xB5, 0x0E, 0xAA,
+ 0x10, 0xE7, 0x0E, 0x50, 0x0A, 0x16, 0x05, 0x42, 0x01, 0x98, 0xFF,
+ 0x80, 0xFF, 0xDC, 0xFF, 0x00, 0x00, 0xFD, 0xFF, 0xC3, 0xFF, 0x6F,
+ 0xFF, 0xE1, 0xFF, 0x2E, 0x02, 0x94, 0x06, 0xDD, 0x0B, 0xCD, 0x0F,
+ 0x76, 0x10, 0x81, 0x0D, 0x6A, 0x08, 0x7F, 0x03, 0x6E, 0x00, 0x71,
+ 0xFF, 0xA1, 0xFF, 0xF2, 0xFF, 0x00, 0x00, 0x15, 0x00, 0xD1, 0xFF,
+ 0x8B, 0xFE, 0xBC, 0xFD, 0xE1, 0x00, 0x84, 0x09, 0xB0, 0x13, 0x47,
+ 0x18, 0xB0, 0x13, 0x84, 0x09, 0xE1, 0x00, 0xBC, 0xFD, 0x8B, 0xFE,
+ 0xD1, 0xFF, 0x15, 0x00, 0xFD, 0xFF, 0x13, 0x00, 0xDA, 0x00, 0x30,
+ 0x00, 0x5D, 0xFC, 0xB3, 0xFC, 0x35, 0x0A, 0xC2, 0x1C, 0x24, 0x20,
+ 0x48, 0x10, 0x5D, 0xFF, 0x74, 0xFB, 0x3A, 0xFF, 0xFB, 0x00, 0x42,
+ 0x00, 0xF8, 0xFF, 0xFA, 0xFF, 0x2C, 0x00, 0xF3, 0x00, 0xAD, 0xFF,
+ 0xC5, 0xFB, 0x11, 0xFE, 0xAF, 0x0D, 0xEF, 0x1E, 0x68, 0x1E, 0xBC,
+ 0x0C, 0xA7, 0xFD, 0xEA, 0xFB, 0xD3, 0xFF, 0xEE, 0x00, 0x24, 0x00,
+ 0xFA, 0xFF, 0xF7, 0xFF, 0x4C, 0x00, 0xFB, 0x00, 0x0C, 0xFF, 0x5F,
+ 0xFB, 0xE8, 0xFF, 0x3D, 0x11, 0x7E, 0x20, 0x13, 0x1C, 0x4C, 0x09,
+ 0x6A, 0xFC, 0x8C, 0xFC, 0x4E, 0x00, 0xD1, 0x00, 0x0E, 0x00, 0xFD,
+ 0xFF, 0xF7, 0xFF, 0x72, 0x00, 0xEC, 0x00, 0x55, 0xFE, 0x3D, 0xFB,
+ 0x37, 0x02, 0xBE, 0x14, 0x5D, 0x21, 0x40, 0x19, 0x18, 0x06, 0xA2,
+ 0xFB, 0x47, 0xFD, 0xA7, 0x00, 0xAB, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0xFC, 0xFF, 0x9B, 0x00, 0xC0, 0x00, 0x92, 0xFD, 0x73,
+ 0xFB, 0xF2, 0x04, 0x0E, 0x18, 0x81, 0x21, 0x0C, 0x16, 0x37, 0x03,
+ 0x47, 0xFB, 0x0B, 0xFE, 0xDF, 0x00, 0x82, 0x00, 0xF9, 0xFF, 0xFE,
+ 0xFF, 0x08, 0x00, 0xC3, 0x00, 0x74, 0x00, 0xD2, 0xFC, 0x10, 0xFC,
+ 0x08, 0x08, 0x0A, 0x1B, 0xE9, 0x20, 0x9A, 0x12, 0xBE, 0x00, 0x49,
+ 0xFB, 0xC8, 0xFE, 0xF9, 0x00, 0x5A, 0x00, 0xF7, 0xFF, 0xFC, 0xFF,
+ 0x1B, 0x00, 0xE4, 0x00, 0x06, 0x00, 0x24, 0xFC, 0x1E, 0xFD, 0x65,
+ 0x0B, 0x94, 0x1D, 0x9D, 0x1F, 0x0D, 0x0F, 0xB8, 0xFE, 0x96, 0xFB,
+ 0x72, 0xFF, 0xF9, 0x00, 0x37, 0x00, 0xF8, 0xFF, 0xF9, 0xFF, 0x36,
+ 0x00, 0xF8, 0x00, 0x78, 0xFF, 0x9B, 0xFB, 0xA6, 0xFE, 0xE9, 0x0E,
+ 0x8D, 0x1F, 0xAA, 0x1D, 0x87, 0x0B, 0x2B, 0xFD, 0x1E, 0xFC, 0x02,
+ 0x00, 0xE5, 0x00, 0x1C, 0x00, 0xFB, 0xFF, 0xF7, 0xFF, 0x58, 0x00,
+ 0xF9, 0x00, 0xCF, 0xFE, 0x4A, 0xFB, 0xA7, 0x00, 0x77, 0x12, 0xE0,
+ 0x20, 0x26, 0x1B, 0x28, 0x08, 0x18, 0xFC, 0xCB, 0xFC, 0x71, 0x00,
+ 0xC5, 0x00, 0x08, 0x00, 0xFE, 0xFF, 0xF8, 0xFF, 0x80, 0x00, 0xE1,
+ 0x00, 0x13, 0xFE, 0x45, 0xFB, 0x1D, 0x03, 0xEB, 0x15, 0x7F, 0x21,
+ 0x2D, 0x18, 0x0E, 0x05, 0x77, 0xFB, 0x8B, 0xFD, 0xBE, 0x00, 0x9D,
+ 0x00, 0xFD, 0xFF, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xA9, 0x00,
+ 0xAA, 0x00, 0x4F, 0xFD, 0x9D, 0xFB, 0xFA, 0x05, 0x22, 0x19, 0x62,
+ 0x21, 0xE0, 0x14, 0x50, 0x02, 0x3E, 0xFB, 0x4E, 0xFE, 0xEB, 0x00,
+ 0x73, 0x00, 0xF7, 0xFF, 0xFE, 0xFF, 0x0D, 0x00, 0xD0, 0x00, 0x52,
+ 0x00, 0x93, 0xFC, 0x60, 0xFC, 0x2C, 0x09, 0xFA, 0x1B, 0x8A, 0x20,
+ 0x60, 0x11, 0xFD, 0xFF, 0x5C, 0xFB, 0x06, 0xFF, 0xFB, 0x00, 0x4D,
+ 0x00, 0xF7, 0xFF, 0xFA, 0xFF, 0x23, 0x00, 0xED, 0x00, 0xD9, 0xFF,
+ 0xEF, 0xFB, 0x98, 0xFD, 0x99, 0x0C, 0x54, 0x1E, 0x02, 0x1F, 0xD2,
+ 0x0D, 0x20, 0xFE, 0xC0, 0xFB, 0xA7, 0xFF, 0xF4, 0x00, 0x2D, 0x00,
+ 0xF9, 0xFF, 0xF8, 0xFF, 0x41, 0x00, 0xFB, 0x00, 0x41, 0xFF, 0x78,
+ 0xFB, 0x4A, 0xFF, 0x25, 0x10, 0x16, 0x20, 0xDA, 0x1C, 0x56, 0x0A,
+ 0xBE, 0xFC, 0x56, 0xFC, 0x2C, 0x00, 0xDB, 0x00, 0x14, 0x00, 0xFD,
+ 0xFF, 0xF7, 0xFF, 0x66, 0x00, 0xF4, 0x00, 0x8F, 0xFE, 0x3F, 0xFB,
+ 0x75, 0x01, 0xAE, 0x13, 0x2C, 0x21, 0x2A, 0x1A, 0x0D, 0x07, 0xD4,
+ 0xFB, 0x0C, 0xFD, 0x8F, 0x00, 0xB7, 0x00, 0x03, 0x00, 0xFF, 0xFF,
+ 0x00, 0x00, 0xFA, 0xFF, 0x8E, 0x00, 0xD1, 0x00, 0xCF, 0xFD, 0x58,
+ 0xFB, 0x10, 0x04, 0x10, 0x17, 0x8A, 0x21, 0x10, 0x17, 0x10, 0x04,
+ 0x58, 0xFB, 0xCF, 0xFD, 0xD1, 0x00, 0x8E, 0x00, 0xFA, 0xFF, 0xFF,
+ 0xFF, 0x03, 0x00, 0xB7, 0x00, 0x8F, 0x00, 0x0C, 0xFD, 0xD4, 0xFB,
+ 0x0D, 0x07, 0x2A, 0x1A, 0x2C, 0x21, 0xAE, 0x13, 0x75, 0x01, 0x3F,
+ 0xFB, 0x8F, 0xFE, 0xF4, 0x00, 0x66, 0x00, 0xF7, 0xFF, 0xFD, 0xFF,
+ 0x14, 0x00, 0xDB, 0x00, 0x2C, 0x00, 0x56, 0xFC, 0xBE, 0xFC, 0x56,
+ 0x0A, 0xDA, 0x1C, 0x16, 0x20, 0x25, 0x10, 0x4A, 0xFF, 0x78, 0xFB,
+ 0x41, 0xFF, 0xFB, 0x00, 0x41, 0x00, 0xF8, 0xFF, 0xF9, 0xFF, 0x2D,
+ 0x00, 0xF4, 0x00, 0xA7, 0xFF, 0xC0, 0xFB, 0x20, 0xFE, 0xD2, 0x0D,
+ 0x02, 0x1F, 0x54, 0x1E, 0x99, 0x0C, 0x98, 0xFD, 0xEF, 0xFB, 0xD9,
+ 0xFF, 0xED, 0x00, 0x23, 0x00, 0xFA, 0xFF, 0xF7, 0xFF, 0x4D, 0x00,
+ 0xFB, 0x00, 0x06, 0xFF, 0x5C, 0xFB, 0xFD, 0xFF, 0x60, 0x11, 0x8A,
+ 0x20, 0xFA, 0x1B, 0x2C, 0x09, 0x60, 0xFC, 0x93, 0xFC, 0x52, 0x00,
+ 0xD0, 0x00, 0x0D, 0x00, 0xFE, 0xFF, 0xF7, 0xFF, 0x73, 0x00, 0xEB,
+ 0x00, 0x4E, 0xFE, 0x3E, 0xFB, 0x50, 0x02, 0xE0, 0x14, 0x62, 0x21,
+ 0x22, 0x19, 0xFA, 0x05, 0x9D, 0xFB, 0x4F, 0xFD, 0xAA, 0x00, 0xA9,
+ 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0xFD, 0xFF, 0x9D, 0x00,
+ 0xBE, 0x00, 0x8B, 0xFD, 0x77, 0xFB, 0x0E, 0x05, 0x2D, 0x18, 0x7F,
+ 0x21, 0xEB, 0x15, 0x1D, 0x03, 0x45, 0xFB, 0x13, 0xFE, 0xE1, 0x00,
+ 0x80, 0x00, 0xF8, 0xFF, 0xFE, 0xFF, 0x08, 0x00, 0xC5, 0x00, 0x71,
+ 0x00, 0xCB, 0xFC, 0x18, 0xFC, 0x28, 0x08, 0x26, 0x1B, 0xE0, 0x20,
+ 0x77, 0x12, 0xA7, 0x00, 0x4A, 0xFB, 0xCF, 0xFE, 0xF9, 0x00, 0x58,
+ 0x00, 0xF7, 0xFF, 0xFB, 0xFF, 0x1C, 0x00, 0xE5, 0x00, 0x02, 0x00,
+ 0x1E, 0xFC, 0x2B, 0xFD, 0x87, 0x0B, 0xAA, 0x1D, 0x8D, 0x1F, 0xE9,
+ 0x0E, 0xA6, 0xFE, 0x9B, 0xFB, 0x78, 0xFF, 0xF8, 0x00, 0x36, 0x00,
+ 0xF9, 0xFF, 0xF8, 0xFF, 0x37, 0x00, 0xF9, 0x00, 0x72, 0xFF, 0x96,
+ 0xFB, 0xB8, 0xFE, 0x0D, 0x0F, 0x9D, 0x1F, 0x94, 0x1D, 0x65, 0x0B,
+ 0x1E, 0xFD, 0x24, 0xFC, 0x06, 0x00, 0xE4, 0x00, 0x1B, 0x00, 0xFC,
+ 0xFF, 0xF7, 0xFF, 0x5A, 0x00, 0xF9, 0x00, 0xC8, 0xFE, 0x49, 0xFB,
+ 0xBE, 0x00, 0x9A, 0x12, 0xE9, 0x20, 0x0A, 0x1B, 0x08, 0x08, 0x10,
+ 0xFC, 0xD2, 0xFC, 0x74, 0x00, 0xC3, 0x00, 0x08, 0x00, 0xFE, 0xFF,
+ 0xF9, 0xFF, 0x82, 0x00, 0xDF, 0x00, 0x0B, 0xFE, 0x47, 0xFB, 0x37,
+ 0x03, 0x0C, 0x16, 0x81, 0x21, 0x0E, 0x18, 0xF2, 0x04, 0x73, 0xFB,
+ 0x92, 0xFD, 0xC0, 0x00, 0x9B, 0x00, 0xFC, 0xFF, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0xAB, 0x00, 0xA7, 0x00, 0x47, 0xFD, 0xA2, 0xFB,
+ 0x18, 0x06, 0x40, 0x19, 0x5D, 0x21, 0xBE, 0x14, 0x37, 0x02, 0x3D,
+ 0xFB, 0x55, 0xFE, 0xEC, 0x00, 0x72, 0x00, 0xF7, 0xFF, 0xFD, 0xFF,
+ 0x0E, 0x00, 0xD1, 0x00, 0x4E, 0x00, 0x8C, 0xFC, 0x6A, 0xFC, 0x4C,
+ 0x09, 0x13, 0x1C, 0x7E, 0x20, 0x3D, 0x11, 0xE8, 0xFF, 0x5F, 0xFB,
+ 0x0C, 0xFF, 0xFB, 0x00, 0x4C, 0x00, 0xF7, 0xFF, 0xFA, 0xFF, 0x24,
+ 0x00, 0xEE, 0x00, 0xD3, 0xFF, 0xEA, 0xFB, 0xA7, 0xFD, 0xBC, 0x0C,
+ 0x68, 0x1E, 0xEF, 0x1E, 0xAF, 0x0D, 0x11, 0xFE, 0xC5, 0xFB, 0xAD,
+ 0xFF, 0xF3, 0x00, 0x2C, 0x00, 0xFA, 0xFF, 0xF8, 0xFF, 0x42, 0x00,
+ 0xFB, 0x00, 0x3A, 0xFF, 0x74, 0xFB, 0x5D, 0xFF, 0x48, 0x10, 0x24,
+ 0x20, 0xC2, 0x1C, 0x35, 0x0A, 0xB3, 0xFC, 0x5D, 0xFC, 0x30, 0x00,
+ 0xDA, 0x00, 0x13, 0x00, 0xFD, 0xFF, 0xF7, 0xFF, 0x67, 0x00, 0xF3,
+ 0x00, 0x88, 0xFE, 0x3E, 0xFB, 0x8C, 0x01, 0xD0, 0x13, 0x33, 0x21,
+ 0x0D, 0x1A, 0xEE, 0x06, 0xCD, 0xFB, 0x13, 0xFD, 0x92, 0x00, 0xB6,
+ 0x00, 0x03, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0xFA, 0xFF, 0x90, 0x00,
+ 0xCF, 0x00, 0xC7, 0xFD, 0x5B, 0xFB, 0x2B, 0x04, 0x31, 0x17, 0x8A,
+ 0x21, 0xF0, 0x16, 0xF4, 0x03, 0x56, 0xFB, 0xD6, 0xFD, 0xD3, 0x00,
+ 0x8D, 0x00, 0xFA, 0xFF, 0xFF, 0xFF, 0x04, 0x00, 0xB9, 0x00, 0x8C,
+ 0x00, 0x05, 0xFD, 0xDB, 0xFB, 0x2C, 0x07, 0x47, 0x1A, 0x25, 0x21,
+ 0x8B, 0x13, 0x5D, 0x01, 0x40, 0xFB, 0x97, 0xFE, 0xF5, 0x00, 0x64,
+ 0x00, 0xF7, 0xFF, 0xFC, 0xFF, 0x15, 0x00, 0xDC, 0x00, 0x27, 0x00,
+ 0x50, 0xFC, 0xCA, 0xFC, 0x78, 0x0A, 0xF2, 0x1C, 0x07, 0x20, 0x02,
+ 0x10, 0x37, 0xFF, 0x7B, 0xFB, 0x47, 0xFF, 0xFB, 0x00, 0x40, 0x00,
+ 0xF8, 0xFF, 0xF9, 0xFF, 0x2E, 0x00, 0xF5, 0x00, 0xA2, 0xFF, 0xBB,
+ 0xFB, 0x31, 0xFE, 0xF5, 0x0D, 0x14, 0x1F, 0x3F, 0x1E, 0x77, 0x0C,
+ 0x8A, 0xFD, 0xF5, 0xFB, 0xDE, 0xFF, 0xEC, 0x00, 0x22, 0x00, 0xFB,
+ 0xFF, 0xF7, 0xFF, 0x4E, 0x00, 0xFB, 0x00, 0xFF, 0xFE, 0x59, 0xFB,
+ 0x11, 0x00, 0x83, 0x11, 0x96, 0x20, 0xE0, 0x1B, 0x0B, 0x09, 0x56,
+ 0xFC, 0x99, 0xFC, 0x56, 0x00, 0xCE, 0x00, 0x0D, 0x00, 0xFE, 0xFF,
+ 0xF8, 0xFF, 0x75, 0x00, 0xEA, 0x00, 0x47, 0xFE, 0x3E, 0xFB, 0x69,
+ 0x02, 0x02, 0x15, 0x66, 0x21, 0x04, 0x19, 0xDC, 0x05, 0x98, 0xFB,
+ 0x56, 0xFD, 0xAD, 0x00, 0xA8, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x00,
+ 0x00, 0xFD, 0xFF, 0x9E, 0x00, 0xBC, 0x00, 0x83, 0xFD, 0x7B, 0xFB,
+ 0x2B, 0x05, 0x4C, 0x18, 0x7C, 0x21, 0xCA, 0x15, 0x03, 0x03, 0x44,
+ 0xFB, 0x1A, 0xFE, 0xE2, 0x00, 0x7E, 0x00, 0xF8, 0xFF, 0xFE, 0xFF,
+ 0x09, 0x00, 0xC6, 0x00, 0x6D, 0x00, 0xC3, 0xFC, 0x20, 0xFC, 0x49,
+ 0x08, 0x41, 0x1B, 0xD6, 0x20, 0x54, 0x12, 0x92, 0x00, 0x4C, 0xFB,
+ 0xD6, 0xFE, 0xFA, 0x00, 0x57, 0x00, 0xF7, 0xFF, 0xFB, 0xFF, 0x1D,
+ 0x00, 0xE6, 0x00, 0xFD, 0xFF, 0x18, 0xFC, 0x38, 0xFD, 0xA9, 0x0B,
+ 0xC0, 0x1D, 0x7C, 0x1F, 0xC6, 0x0E, 0x95, 0xFE, 0x9F, 0xFB, 0x7E,
+ 0xFF, 0xF8, 0x00, 0x35, 0x00, 0xF9, 0xFF, 0xF8, 0xFF, 0x38, 0x00,
+ 0xF9, 0x00, 0x6C, 0xFF, 0x92, 0xFB, 0xC9, 0xFE, 0x2F, 0x0F, 0xAD,
+ 0x1F, 0x7D, 0x1D, 0x42, 0x0B, 0x12, 0xFD, 0x2A, 0xFC, 0x0B, 0x00,
+ 0xE3, 0x00, 0x1A, 0x00, 0xFC, 0xFF, 0xF7, 0xFF, 0x5B, 0x00, 0xF8,
+ 0x00, 0xC1, 0xFE, 0x47, 0xFB, 0xD4, 0x00, 0xBC, 0x12, 0xF3, 0x20,
+ 0xEF, 0x1A, 0xE9, 0x07, 0x08, 0xFC, 0xD9, 0xFC, 0x78, 0x00, 0xC2,
+ 0x00, 0x07, 0x00, 0xFF, 0xFF, 0xF9, 0xFF, 0x83, 0x00, 0xDD, 0x00,
+ 0x04, 0xFE, 0x49, 0xFB, 0x52, 0x03, 0x2D, 0x16, 0x83, 0x21, 0xEF,
+ 0x17, 0xD5, 0x04, 0x6F, 0xFB, 0x9A, 0xFD, 0xC3, 0x00, 0x9A, 0x00,
+ 0xFC, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0xAD, 0x00, 0xA4,
+ 0x00, 0x40, 0xFD, 0xA8, 0xFB, 0x36, 0x06, 0x5E, 0x19, 0x58, 0x21,
+ 0x9C, 0x14, 0x1E, 0x02, 0x3D, 0xFB, 0x5D, 0xFE, 0xED, 0x00, 0x70,
+ 0x00, 0xF7, 0xFF, 0xFD, 0xFF, 0x0F, 0x00, 0xD2, 0x00, 0x4A, 0x00,
+ 0x85, 0xFC, 0x74, 0xFC, 0x6D, 0x09, 0x2D, 0x1C, 0x72, 0x20, 0x1A,
+ 0x11, 0xD4, 0xFF, 0x61, 0xFB, 0x13, 0xFF, 0xFC, 0x00, 0x4A, 0x00,
+ 0xF7, 0xFF, 0xFA, 0xFF, 0x25, 0x00, 0xEF, 0x00, 0xCE, 0xFF, 0xE4,
+ 0xFB, 0xB5, 0xFD, 0xDE, 0x0C, 0x7C, 0x1E, 0xDD, 0x1E, 0x8C, 0x0D,
+ 0x01, 0xFE, 0xCA, 0xFB, 0xB3, 0xFF, 0xF3, 0x00, 0x2B, 0x00, 0xFA,
+ 0xFF, 0xF8, 0xFF, 0x44, 0x00, 0xFB, 0x00, 0x34, 0xFF, 0x71, 0xFB,
+ 0x71, 0xFF, 0x6B, 0x10, 0x32, 0x20, 0xA9, 0x1C, 0x13, 0x0A, 0xA8,
+ 0xFC, 0x63, 0xFC, 0x35, 0x00, 0xD9, 0x00, 0x12, 0x00, 0xFD, 0xFF,
+ 0xF7, 0xFF, 0x69, 0x00, 0xF2, 0x00, 0x81, 0xFE, 0x3E, 0xFB, 0xA4,
+ 0x01, 0xF2, 0x13, 0x3A, 0x21, 0xF0, 0x19, 0xCF, 0x06, 0xC7, 0xFB,
+ 0x1B, 0xFD, 0x96, 0x00, 0xB4, 0x00, 0x02, 0x00, 0xFF, 0xFF, 0x00,
+ 0x00, 0xFB, 0xFF, 0x92, 0x00, 0xCD, 0x00, 0xC0, 0xFD, 0x5E, 0xFB,
+ 0x47, 0x04, 0x51, 0x17, 0x8A, 0x21, 0xD0, 0x16, 0xD9, 0x03, 0x53,
+ 0xFB, 0xDE, 0xFD, 0xD5, 0x00, 0x8B, 0x00, 0xFA, 0xFF, 0xFF, 0xFF,
+ 0x04, 0x00, 0xBA, 0x00, 0x89, 0x00, 0xFD, 0xFC, 0xE2, 0xFB, 0x4B,
+ 0x07, 0x63, 0x1A, 0x1D, 0x21, 0x69, 0x13, 0x46, 0x01, 0x41, 0xFB,
+ 0x9E, 0xFE, 0xF5, 0x00, 0x63, 0x00, 0xF7, 0xFF, 0xFC, 0xFF, 0x16,
+ 0x00, 0xDD, 0x00, 0x23, 0x00, 0x49, 0xFC, 0xD5, 0xFC, 0x99, 0x0A,
+ 0x09, 0x1D, 0xF9, 0x1F, 0xDF, 0x0F, 0x24, 0xFF, 0x7F, 0xFB, 0x4D,
+ 0xFF, 0xFB, 0x00, 0x3F, 0x00, 0xF8, 0xFF, 0xF9, 0xFF, 0x2F, 0x00,
+ 0xF5, 0x00, 0x9C, 0xFF, 0xB6, 0xFB, 0x41, 0xFE, 0x17, 0x0E, 0x26,
+ 0x1F, 0x2B, 0x1E, 0x54, 0x0C, 0x7C, 0xFD, 0xFA, 0xFB, 0xE3, 0xFF,
+ 0xEB, 0x00, 0x21, 0x00, 0xFB, 0xFF, 0xF7, 0xFF, 0x50, 0x00, 0xFB,
+ 0x00, 0xF8, 0xFE, 0x57, 0xFB, 0x26, 0x00, 0xA6, 0x11, 0xA1, 0x20,
+ 0xC6, 0x1B, 0xEA, 0x08, 0x4D, 0xFC, 0xA0, 0xFC, 0x5A, 0x00, 0xCD,
+ 0x00, 0x0C, 0x00, 0xFE, 0xFF, 0xF8, 0xFF, 0x77, 0x00, 0xE9, 0x00,
+ 0x3F, 0xFE, 0x3F, 0xFB, 0x82, 0x02, 0x23, 0x15, 0x6B, 0x21, 0xE5,
+ 0x18, 0xBE, 0x05, 0x93, 0xFB, 0x5E, 0xFD, 0xAF, 0x00, 0xA6, 0x00,
+ 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0xFD, 0xFF, 0xA0, 0x00, 0xB9,
+ 0x00, 0x7C, 0xFD, 0x80, 0xFB, 0x48, 0x05, 0x6B, 0x18, 0x79, 0x21,
+ 0xA9, 0x15, 0xE9, 0x02, 0x43, 0xFB, 0x21, 0xFE, 0xE3, 0x00, 0x7D,
+ 0x00, 0xF8, 0xFF, 0xFE, 0xFF, 0x09, 0x00, 0xC7, 0x00, 0x69, 0x00,
+ 0xBC, 0xFC, 0x29, 0xFC, 0x69, 0x08, 0x5C, 0x1B, 0xCC, 0x20, 0x32,
+ 0x12, 0x7C, 0x00, 0x4E, 0xFB, 0xDD, 0xFE, 0xFA, 0x00, 0x56, 0x00,
+ 0xF7, 0xFF, 0xFB, 0xFF, 0x1D, 0x00, 0xE7, 0x00, 0xF8, 0xFF, 0x12,
+ 0xFC, 0x45, 0xFD, 0xCB, 0x0B, 0xD6, 0x1D, 0x6C, 0x1F, 0xA3, 0x0E,
+ 0x84, 0xFE, 0xA4, 0xFB, 0x84, 0xFF, 0xF7, 0x00, 0x34, 0x00, 0xF9,
+ 0xFF, 0xF8, 0xFF, 0x3A, 0x00, 0xFA, 0x00, 0x66, 0xFF, 0x8E, 0xFB,
+ 0xDB, 0xFE, 0x53, 0x0F, 0xBD, 0x1F, 0x66, 0x1D, 0x21, 0x0B, 0x05,
+ 0xFD, 0x30, 0xFC, 0x10, 0x00, 0xE2, 0x00, 0x19, 0x00, 0xFC, 0xFF,
+ 0xF7, 0xFF, 0x5D, 0x00, 0xF8, 0x00, 0xBA, 0xFE, 0x46, 0xFB, 0xEA,
+ 0x00, 0xDF, 0x12, 0xFC, 0x20, 0xD3, 0x1A, 0xC9, 0x07, 0x00, 0xFC,
+ 0xE0, 0xFC, 0x7B, 0x00, 0xC0, 0x00, 0x07, 0x00, 0xFF, 0xFF, 0xF9,
+ 0xFF, 0x85, 0x00, 0xDC, 0x00, 0xFC, 0xFD, 0x4A, 0xFB, 0x6C, 0x03,
+ 0x4E, 0x16, 0x85, 0x21, 0xCF, 0x17, 0xB8, 0x04, 0x6C, 0xFB, 0xA2,
+ 0xFD, 0xC5, 0x00, 0x98, 0x00, 0xFC, 0xFF, 0x00, 0x00, 0xFF, 0xFF,
+ 0x01, 0x00, 0xAE, 0x00, 0xA1, 0x00, 0x38, 0xFD, 0xAE, 0xFB, 0x54,
+ 0x06, 0x7C, 0x19, 0x53, 0x21, 0x7B, 0x14, 0x05, 0x02, 0x3D, 0xFB,
+ 0x64, 0xFE, 0xEE, 0x00, 0x6F, 0x00, 0xF7, 0xFF, 0xFD, 0xFF, 0x0F,
+ 0x00, 0xD4, 0x00, 0x46, 0x00, 0x7E, 0xFC, 0x7E, 0xFC, 0x8E, 0x09,
+ 0x46, 0x1C, 0x66, 0x20, 0xF7, 0x10, 0xC0, 0xFF, 0x64, 0xFB, 0x1A,
+ 0xFF, 0xFC, 0x00, 0x49, 0x00, 0xF7, 0xFF, 0xFA, 0xFF, 0x26, 0x00,
+ 0xF0, 0x00, 0xC9, 0xFF, 0xDF, 0xFB, 0xC4, 0xFD, 0x01, 0x0D, 0x90,
+ 0x1E, 0xCA, 0x1E, 0x69, 0x0D, 0xF1, 0xFD, 0xCF, 0xFB, 0xB8, 0xFF,
+ 0xF2, 0x00, 0x29, 0x00, 0xFA, 0xFF, 0xF7, 0xFF, 0x45, 0x00, 0xFC,
+ 0x00, 0x2D, 0xFF, 0x6D, 0xFB, 0x84, 0xFF, 0x8E, 0x10, 0x3F, 0x20,
+ 0x91, 0x1C, 0xF2, 0x09, 0x9D, 0xFC, 0x6A, 0xFC, 0x39, 0x00, 0xD7,
+ 0x00, 0x12, 0x00, 0xFD, 0xFF, 0xF7, 0xFF, 0x6A, 0x00, 0xF1, 0x00,
+ 0x7A, 0xFE, 0x3D, 0xFB, 0xBC, 0x01, 0x14, 0x14, 0x41, 0x21, 0xD4,
+ 0x19, 0xB0, 0x06, 0xC0, 0xFB, 0x22, 0xFD, 0x99, 0x00, 0xB3, 0x00,
+ 0x02, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0xFB, 0xFF, 0x93, 0x00, 0xCB,
+ 0x00, 0xB8, 0xFD, 0x61, 0xFB, 0x63, 0x04, 0x71, 0x17, 0x89, 0x21,
+ 0xB0, 0x16, 0xBD, 0x03, 0x51, 0xFB, 0xE6, 0xFD, 0xD7, 0x00, 0x8A,
+ 0x00, 0xFA, 0xFF, 0xFF, 0xFF, 0x05, 0x00, 0xBC, 0x00, 0x86, 0x00,
+ 0xF6, 0xFC, 0xE9, 0xFB, 0x6A, 0x07, 0x80, 0x1A, 0x15, 0x21, 0x47,
+ 0x13, 0x2F, 0x01, 0x42, 0xFB, 0xA5, 0xFE, 0xF6, 0x00, 0x61, 0x00,
+ 0xF7, 0xFF, 0xFC, 0xFF, 0x16, 0x00, 0xDF, 0x00, 0x1E, 0x00, 0x43,
+ 0xFC, 0xE1, 0xFC, 0xBB, 0x0A, 0x21, 0x1D, 0xEA, 0x1F, 0xBC, 0x0F,
+ 0x12, 0xFF, 0x82, 0xFB, 0x54, 0xFF, 0xFA, 0x00, 0x3D, 0x00, 0xF8,
+ 0xFF, 0xF9, 0xFF, 0x30, 0x00, 0xF6, 0x00, 0x96, 0xFF, 0xB1, 0xFB,
+ 0x51, 0xFE, 0x3A, 0x0E, 0x38, 0x1F, 0x16, 0x1E, 0x32, 0x0C, 0x6E,
+ 0xFD, 0x00, 0xFC, 0xE8, 0xFF, 0xEA, 0x00, 0x20, 0x00, 0xFB, 0xFF,
+ 0xF7, 0xFF, 0x51, 0x00, 0xFB, 0x00, 0xF1, 0xFE, 0x54, 0xFB, 0x3B,
+ 0x00, 0xC9, 0x11, 0xAD, 0x20, 0xAC, 0x1B, 0xCA, 0x08, 0x44, 0xFC,
+ 0xA7, 0xFC, 0x5E, 0x00, 0xCC, 0x00, 0x0B, 0x00, 0xFE, 0xFF, 0xF8,
+ 0xFF, 0x78, 0x00, 0xE7, 0x00, 0x38, 0xFE, 0x40, 0xFB, 0x9B, 0x02,
+ 0x45, 0x15, 0x6F, 0x21, 0xC7, 0x18, 0xA1, 0x05, 0x8E, 0xFB, 0x65,
+ 0xFD, 0xB2, 0x00, 0xA5, 0x00, 0xFE, 0xFF, 0x00, 0x00, 0x00, 0x00,
+ 0xFE, 0xFF, 0xA2, 0x00, 0xB7, 0x00, 0x74, 0xFD, 0x84, 0xFB, 0x66,
+ 0x05, 0x8A, 0x18, 0x76, 0x21, 0x87, 0x15, 0xCF, 0x02, 0x41, 0xFB,
+ 0x29, 0xFE, 0xE5, 0x00, 0x7B, 0x00, 0xF8, 0xFF, 0xFE, 0xFF, 0x0A,
+ 0x00, 0xC9, 0x00, 0x66, 0x00, 0xB5, 0xFC, 0x32, 0xFC, 0x89, 0x08,
+ 0x77, 0x1B, 0xC2, 0x20, 0x0F, 0x12, 0x66, 0x00, 0x50, 0xFB, 0xE4,
+ 0xFE, 0xFA, 0x00, 0x54, 0x00, 0xF7, 0xFF, 0xFB, 0xFF, 0x1E, 0x00,
+ 0xE8, 0x00, 0xF3, 0xFF, 0x0C, 0xFC, 0x53, 0xFD, 0xED, 0x0B, 0xEB,
+ 0x1D, 0x5A, 0x1F, 0x80, 0x0E, 0x73, 0xFE, 0xA8, 0xFB, 0x8A, 0xFF,
+ 0xF7, 0x00, 0x32, 0x00, 0xF9, 0xFF, 0xF8, 0xFF, 0x3B, 0x00, 0xFA,
+ 0x00, 0x60, 0xFF, 0x8A, 0xFB, 0xED, 0xFE, 0x76, 0x0F, 0xCC, 0x1F,
+ 0x4F, 0x1D, 0xFF, 0x0A, 0xF9, 0xFC, 0x36, 0xFC, 0x15, 0x00, 0xE1,
+ 0x00, 0x18, 0x00, 0xFC, 0xFF, 0xF7, 0xFF, 0x5E, 0x00, 0xF7, 0x00,
+ 0xB3, 0xFE, 0x44, 0xFB, 0x01, 0x01, 0x02, 0x13, 0x04, 0x21, 0xB8,
+ 0x1A, 0xA9, 0x07, 0xF8, 0xFB, 0xE7, 0xFC, 0x7F, 0x00, 0xBF, 0x00,
+ 0x06, 0x00, 0xFF, 0xFF, 0xF9, 0xFF, 0x86, 0x00, 0xDA, 0x00, 0xF5,
+ 0xFD, 0x4C, 0xFB, 0x87, 0x03, 0x6E, 0x16, 0x86, 0x21, 0xB0, 0x17,
+ 0x9C, 0x04, 0x68, 0xFB, 0xA9, 0xFD, 0xC7, 0x00, 0x96, 0x00, 0xFB,
+ 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0x01, 0x00, 0xB0, 0x00, 0x9F, 0x00,
+ 0x31, 0xFD, 0xB4, 0xFB, 0x73, 0x06, 0x99, 0x19, 0x4D, 0x21, 0x59,
+ 0x14, 0xED, 0x01, 0x3D, 0xFB, 0x6B, 0xFE, 0xEF, 0x00, 0x6D, 0x00,
+ 0xF7, 0xFF, 0xFD, 0xFF, 0x10, 0x00, 0xD5, 0x00, 0x42, 0x00, 0x77,
+ 0xFC, 0x88, 0xFC, 0xAF, 0x09, 0x5F, 0x1C, 0x59, 0x20, 0xD4, 0x10,
+ 0xAC, 0xFF, 0x67, 0xFB, 0x20, 0xFF, 0xFC, 0x00, 0x48, 0x00, 0xF7,
+ 0xFF, 0xFA, 0xFF, 0x27, 0x00, 0xF0, 0x00, 0xC3, 0xFF, 0xD9, 0xFB,
+ 0xD3, 0xFD, 0x24, 0x0D, 0xA3, 0x1E, 0xB7, 0x1E, 0x46, 0x0D, 0xE2,
+ 0xFD, 0xD4, 0xFB, 0xBE, 0xFF, 0xF1, 0x00, 0x28, 0x00, 0xFA, 0xFF,
+ 0xF7, 0xFF, 0x46, 0x00, 0xFC, 0x00, 0x27, 0xFF, 0x6A, 0xFB, 0x98,
+ 0xFF, 0xB1, 0x10, 0x4C, 0x20, 0x78, 0x1C, 0xD1, 0x09, 0x93, 0xFC,
+ 0x71, 0xFC, 0x3D, 0x00, 0xD6, 0x00, 0x11, 0x00, 0xFD, 0xFF, 0xF7,
+ 0xFF, 0x6C, 0x00, 0xF0, 0x00, 0x72, 0xFE, 0x3D, 0xFB, 0xD4, 0x01,
+ 0x36, 0x14, 0x47, 0x21, 0xB6, 0x19, 0x91, 0x06, 0xBA, 0xFB, 0x29,
+ 0xFD, 0x9C, 0x00, 0xB1, 0x00, 0x02, 0x00, 0xFF, 0xFF, 0x00, 0x00,
+ 0xFB, 0xFF, 0x95, 0x00, 0xC9, 0x00, 0xB1, 0xFD, 0x65, 0xFB, 0x80,
+ 0x04, 0x90, 0x17, 0x88, 0x21, 0x8F, 0x16, 0xA2, 0x03, 0x4E, 0xFB,
+ 0xED, 0xFD, 0xD9, 0x00, 0x88, 0x00, 0xF9, 0xFF, 0xFF, 0xFF, 0x05,
+ 0x00, 0xBD, 0x00, 0x82, 0x00, 0xEF, 0xFC, 0xF0, 0xFB, 0x8A, 0x07,
+ 0x9C, 0x1A, 0x0D, 0x21, 0x24, 0x13, 0x18, 0x01, 0x43, 0xFB, 0xAC,
+ 0xFE, 0xF7, 0x00, 0x60, 0x00, 0xF7, 0xFF, 0xFC, 0xFF, 0x17, 0x00,
+ 0xE0, 0x00, 0x1A, 0x00, 0x3D, 0xFC, 0xED, 0xFC, 0xDD, 0x0A, 0x38,
+ 0x1D, 0xDB, 0x1F, 0x99, 0x0F, 0xFF, 0xFE, 0x86, 0xFB, 0x5A, 0xFF,
+ 0xFA, 0x00, 0x3C, 0x00, 0xF8, 0xFF, 0xF9, 0xFF, 0x31, 0x00, 0xF6,
+ 0x00, 0x90, 0xFF, 0xAD, 0xFB, 0x62, 0xFE, 0x5D, 0x0E, 0x49, 0x1F,
+ 0x01, 0x1E, 0x10, 0x0C, 0x60, 0xFD, 0x06, 0xFC, 0xEE, 0xFF, 0xE9,
+ 0x00, 0x1F, 0x00, 0xFB, 0xFF, 0xF7, 0xFF, 0x53, 0x00, 0xFB, 0x00,
+ 0xEB, 0xFE, 0x52, 0xFB, 0x51, 0x00, 0xEC, 0x11, 0xB7, 0x20, 0x91,
+ 0x1B, 0xA9, 0x08, 0x3B, 0xFC, 0xAE, 0xFC, 0x62, 0x00, 0xCA, 0x00,
+ 0x0B, 0x00, 0xFE, 0xFF, 0xF8, 0xFF, 0x7A, 0x00, 0xE6, 0x00, 0x30,
+ 0xFE, 0x40, 0xFB, 0xB5, 0x02, 0x66, 0x15, 0x73, 0x21, 0xA9, 0x18,
+ 0x83, 0x05, 0x89, 0xFB, 0x6D, 0xFD, 0xB4, 0x00, 0xA3, 0x00, 0xFE,
+ 0xFF, 0x00, 0x00, 0x00, 0x00, 0xFE, 0xFF, 0xA3, 0x00, 0xB4, 0x00,
+ 0x6D, 0xFD, 0x89, 0xFB, 0x83, 0x05, 0xA9, 0x18, 0x73, 0x21, 0x66,
+ 0x15, 0xB5, 0x02, 0x40, 0xFB, 0x30, 0xFE, 0xE6, 0x00, 0x7A, 0x00,
+ 0xF8, 0xFF, 0xFE, 0xFF, 0x0B, 0x00, 0xCA, 0x00, 0x62, 0x00, 0xAE,
+ 0xFC, 0x3B, 0xFC, 0xA9, 0x08, 0x91, 0x1B, 0xB7, 0x20, 0xEC, 0x11,
+ 0x51, 0x00, 0x52, 0xFB, 0xEB, 0xFE, 0xFB, 0x00, 0x53, 0x00, 0xF7,
+ 0xFF, 0xFB, 0xFF, 0x1F, 0x00, 0xE9, 0x00, 0xEE, 0xFF, 0x06, 0xFC,
+ 0x60, 0xFD, 0x10, 0x0C, 0x01, 0x1E, 0x49, 0x1F, 0x5D, 0x0E, 0x62,
+ 0xFE, 0xAD, 0xFB, 0x90, 0xFF, 0xF6, 0x00, 0x31, 0x00, 0xF9, 0xFF,
+ 0xF8, 0xFF, 0x3C, 0x00, 0xFA, 0x00, 0x5A, 0xFF, 0x86, 0xFB, 0xFF,
+ 0xFE, 0x99, 0x0F, 0xDB, 0x1F, 0x38, 0x1D, 0xDD, 0x0A, 0xED, 0xFC,
+ 0x3D, 0xFC, 0x1A, 0x00, 0xE0, 0x00, 0x17, 0x00, 0xFC, 0xFF, 0xF7,
+ 0xFF, 0x60, 0x00, 0xF7, 0x00, 0xAC, 0xFE, 0x43, 0xFB, 0x18, 0x01,
+ 0x24, 0x13, 0x0D, 0x21, 0x9C, 0x1A, 0x8A, 0x07, 0xF0, 0xFB, 0xEF,
+ 0xFC, 0x82, 0x00, 0xBD, 0x00, 0x05, 0x00, 0xFF, 0xFF, 0xF9, 0xFF,
+ 0x88, 0x00, 0xD9, 0x00, 0xED, 0xFD, 0x4E, 0xFB, 0xA2, 0x03, 0x8F,
+ 0x16, 0x88, 0x21, 0x90, 0x17, 0x80, 0x04, 0x65, 0xFB, 0xB1, 0xFD,
+ 0xC9, 0x00, 0x95, 0x00, 0xFB, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0x02,
+ 0x00, 0xB1, 0x00, 0x9C, 0x00, 0x29, 0xFD, 0xBA, 0xFB, 0x91, 0x06,
+ 0xB6, 0x19, 0x47, 0x21, 0x36, 0x14, 0xD4, 0x01, 0x3D, 0xFB, 0x72,
+ 0xFE, 0xF0, 0x00, 0x6C, 0x00, 0xF7, 0xFF, 0xFD, 0xFF, 0x11, 0x00,
+ 0xD6, 0x00, 0x3D, 0x00, 0x71, 0xFC, 0x93, 0xFC, 0xD1, 0x09, 0x78,
+ 0x1C, 0x4C, 0x20, 0xB1, 0x10, 0x98, 0xFF, 0x6A, 0xFB, 0x27, 0xFF,
+ 0xFC, 0x00, 0x46, 0x00, 0xF7, 0xFF, 0xFA, 0xFF, 0x28, 0x00, 0xF1,
+ 0x00, 0xBE, 0xFF, 0xD4, 0xFB, 0xE2, 0xFD, 0x46, 0x0D, 0xB7, 0x1E,
+ 0xA3, 0x1E, 0x24, 0x0D, 0xD3, 0xFD, 0xD9, 0xFB, 0xC3, 0xFF, 0xF0,
+ 0x00, 0x27, 0x00, 0xFA, 0xFF, 0xF7, 0xFF, 0x48, 0x00, 0xFC, 0x00,
+ 0x20, 0xFF, 0x67, 0xFB, 0xAC, 0xFF, 0xD4, 0x10, 0x59, 0x20, 0x5F,
+ 0x1C, 0xAF, 0x09, 0x88, 0xFC, 0x77, 0xFC, 0x42, 0x00, 0xD5, 0x00,
+ 0x10, 0x00, 0xFD, 0xFF, 0xF7, 0xFF, 0x6D, 0x00, 0xEF, 0x00, 0x6B,
+ 0xFE, 0x3D, 0xFB, 0xED, 0x01, 0x59, 0x14, 0x4D, 0x21, 0x99, 0x19,
+ 0x73, 0x06, 0xB4, 0xFB, 0x31, 0xFD, 0x9F, 0x00, 0xB0, 0x00, 0x01,
+ 0x00, 0xFF, 0xFF, 0x00, 0x00, 0xFB, 0xFF, 0x96, 0x00, 0xC7, 0x00,
+ 0xA9, 0xFD, 0x68, 0xFB, 0x9C, 0x04, 0xB0, 0x17, 0x86, 0x21, 0x6E,
+ 0x16, 0x87, 0x03, 0x4C, 0xFB, 0xF5, 0xFD, 0xDA, 0x00, 0x86, 0x00,
+ 0xF9, 0xFF, 0xFF, 0xFF, 0x06, 0x00, 0xBF, 0x00, 0x7F, 0x00, 0xE7,
+ 0xFC, 0xF8, 0xFB, 0xA9, 0x07, 0xB8, 0x1A, 0x04, 0x21, 0x02, 0x13,
+ 0x01, 0x01, 0x44, 0xFB, 0xB3, 0xFE, 0xF7, 0x00, 0x5E, 0x00, 0xF7,
+ 0xFF, 0xFC, 0xFF, 0x18, 0x00, 0xE1, 0x00, 0x15, 0x00, 0x36, 0xFC,
+ 0xF9, 0xFC, 0xFF, 0x0A, 0x4F, 0x1D, 0xCC, 0x1F, 0x76, 0x0F, 0xED,
+ 0xFE, 0x8A, 0xFB, 0x60, 0xFF, 0xFA, 0x00, 0x3B, 0x00, 0xF8, 0xFF,
+ 0xF9, 0xFF, 0x32, 0x00, 0xF7, 0x00, 0x8A, 0xFF, 0xA8, 0xFB, 0x73,
+ 0xFE, 0x80, 0x0E, 0x5A, 0x1F, 0xEB, 0x1D, 0xED, 0x0B, 0x53, 0xFD,
+ 0x0C, 0xFC, 0xF3, 0xFF, 0xE8, 0x00, 0x1E, 0x00, 0xFB, 0xFF, 0xF7,
+ 0xFF, 0x54, 0x00, 0xFA, 0x00, 0xE4, 0xFE, 0x50, 0xFB, 0x66, 0x00,
+ 0x0F, 0x12, 0xC2, 0x20, 0x77, 0x1B, 0x89, 0x08, 0x32, 0xFC, 0xB5,
+ 0xFC, 0x66, 0x00, 0xC9, 0x00, 0x0A, 0x00, 0xFE, 0xFF, 0xF8, 0xFF,
+ 0x7B, 0x00, 0xE5, 0x00, 0x29, 0xFE, 0x41, 0xFB, 0xCF, 0x02, 0x87,
+ 0x15, 0x76, 0x21, 0x8A, 0x18, 0x66, 0x05, 0x84, 0xFB, 0x74, 0xFD,
+ 0xB7, 0x00, 0xA2, 0x00, 0xFE, 0xFF, 0x00, 0x00, 0x00, 0x00, 0xFE,
+ 0xFF, 0xA5, 0x00, 0xB2, 0x00, 0x65, 0xFD, 0x8E, 0xFB, 0xA1, 0x05,
+ 0xC7, 0x18, 0x6F, 0x21, 0x45, 0x15, 0x9B, 0x02, 0x40, 0xFB, 0x38,
+ 0xFE, 0xE7, 0x00, 0x78, 0x00, 0xF8, 0xFF, 0xFE, 0xFF, 0x0B, 0x00,
+ 0xCC, 0x00, 0x5E, 0x00, 0xA7, 0xFC, 0x44, 0xFC, 0xCA, 0x08, 0xAC,
+ 0x1B, 0xAD, 0x20, 0xC9, 0x11, 0x3B, 0x00, 0x54, 0xFB, 0xF1, 0xFE,
+ 0xFB, 0x00, 0x51, 0x00, 0xF7, 0xFF, 0xFB, 0xFF, 0x20, 0x00, 0xEA,
+ 0x00, 0xE8, 0xFF, 0x00, 0xFC, 0x6E, 0xFD, 0x32, 0x0C, 0x16, 0x1E,
+ 0x38, 0x1F, 0x3A, 0x0E, 0x51, 0xFE, 0xB1, 0xFB, 0x96, 0xFF, 0xF6,
+ 0x00, 0x30, 0x00, 0xF9, 0xFF, 0xF8, 0xFF, 0x3D, 0x00, 0xFA, 0x00,
+ 0x54, 0xFF, 0x82, 0xFB, 0x12, 0xFF, 0xBC, 0x0F, 0xEA, 0x1F, 0x21,
+ 0x1D, 0xBB, 0x0A, 0xE1, 0xFC, 0x43, 0xFC, 0x1E, 0x00, 0xDF, 0x00,
+ 0x16, 0x00, 0xFC, 0xFF, 0xF7, 0xFF, 0x61, 0x00, 0xF6, 0x00, 0xA5,
+ 0xFE, 0x42, 0xFB, 0x2F, 0x01, 0x47, 0x13, 0x15, 0x21, 0x80, 0x1A,
+ 0x6A, 0x07, 0xE9, 0xFB, 0xF6, 0xFC, 0x86, 0x00, 0xBC, 0x00, 0x05,
+ 0x00, 0xFF, 0xFF, 0xFA, 0xFF, 0x8A, 0x00, 0xD7, 0x00, 0xE6, 0xFD,
+ 0x51, 0xFB, 0xBD, 0x03, 0xB0, 0x16, 0x89, 0x21, 0x71, 0x17, 0x63,
+ 0x04, 0x61, 0xFB, 0xB8, 0xFD, 0xCB, 0x00, 0x93, 0x00, 0xFB, 0xFF,
+ 0x00, 0x00, 0xFF, 0xFF, 0x02, 0x00, 0xB3, 0x00, 0x99, 0x00, 0x22,
+ 0xFD, 0xC0, 0xFB, 0xB0, 0x06, 0xD4, 0x19, 0x41, 0x21, 0x14, 0x14,
+ 0xBC, 0x01, 0x3D, 0xFB, 0x7A, 0xFE, 0xF1, 0x00, 0x6A, 0x00, 0xF7,
+ 0xFF, 0xFD, 0xFF, 0x12, 0x00, 0xD7, 0x00, 0x39, 0x00, 0x6A, 0xFC,
+ 0x9D, 0xFC, 0xF2, 0x09, 0x91, 0x1C, 0x3F, 0x20, 0x8E, 0x10, 0x84,
+ 0xFF, 0x6D, 0xFB, 0x2D, 0xFF, 0xFC, 0x00, 0x45, 0x00, 0xF7, 0xFF,
+ 0xFA, 0xFF, 0x29, 0x00, 0xF2, 0x00, 0xB8, 0xFF, 0xCF, 0xFB, 0xF1,
+ 0xFD, 0x69, 0x0D, 0xCA, 0x1E, 0x90, 0x1E, 0x01, 0x0D, 0xC4, 0xFD,
+ 0xDF, 0xFB, 0xC9, 0xFF, 0xF0, 0x00, 0x26, 0x00, 0xFA, 0xFF, 0xF7,
+ 0xFF, 0x49, 0x00, 0xFC, 0x00, 0x1A, 0xFF, 0x64, 0xFB, 0xC0, 0xFF,
+ 0xF7, 0x10, 0x66, 0x20, 0x46, 0x1C, 0x8E, 0x09, 0x7E, 0xFC, 0x7E,
+ 0xFC, 0x46, 0x00, 0xD4, 0x00, 0x0F, 0x00, 0xFD, 0xFF, 0xF7, 0xFF,
+ 0x6F, 0x00, 0xEE, 0x00, 0x64, 0xFE, 0x3D, 0xFB, 0x05, 0x02, 0x7B,
+ 0x14, 0x53, 0x21, 0x7C, 0x19, 0x54, 0x06, 0xAE, 0xFB, 0x38, 0xFD,
+ 0xA1, 0x00, 0xAE, 0x00, 0x01, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0xFC,
+ 0xFF, 0x98, 0x00, 0xC5, 0x00, 0xA2, 0xFD, 0x6C, 0xFB, 0xB8, 0x04,
+ 0xCF, 0x17, 0x85, 0x21, 0x4E, 0x16, 0x6C, 0x03, 0x4A, 0xFB, 0xFC,
+ 0xFD, 0xDC, 0x00, 0x85, 0x00, 0xF9, 0xFF, 0xFF, 0xFF, 0x07, 0x00,
+ 0xC0, 0x00, 0x7B, 0x00, 0xE0, 0xFC, 0x00, 0xFC, 0xC9, 0x07, 0xD3,
+ 0x1A, 0xFC, 0x20, 0xDF, 0x12, 0xEA, 0x00, 0x46, 0xFB, 0xBA, 0xFE,
+ 0xF8, 0x00, 0x5D, 0x00, 0xF7, 0xFF, 0xFC, 0xFF, 0x19, 0x00, 0xE2,
+ 0x00, 0x10, 0x00, 0x30, 0xFC, 0x05, 0xFD, 0x21, 0x0B, 0x66, 0x1D,
+ 0xBD, 0x1F, 0x53, 0x0F, 0xDB, 0xFE, 0x8E, 0xFB, 0x66, 0xFF, 0xFA,
+ 0x00, 0x3A, 0x00, 0xF8, 0xFF, 0xF9, 0xFF, 0x34, 0x00, 0xF7, 0x00,
+ 0x84, 0xFF, 0xA4, 0xFB, 0x84, 0xFE, 0xA3, 0x0E, 0x6C, 0x1F, 0xD6,
+ 0x1D, 0xCB, 0x0B, 0x45, 0xFD, 0x12, 0xFC, 0xF8, 0xFF, 0xE7, 0x00,
+ 0x1D, 0x00, 0xFB, 0xFF, 0xF7, 0xFF, 0x56, 0x00, 0xFA, 0x00, 0xDD,
+ 0xFE, 0x4E, 0xFB, 0x7C, 0x00, 0x32, 0x12, 0xCC, 0x20, 0x5C, 0x1B,
+ 0x69, 0x08, 0x29, 0xFC, 0xBC, 0xFC, 0x69, 0x00, 0xC7, 0x00, 0x09,
+ 0x00, 0xFE, 0xFF, 0xF8, 0xFF, 0x7D, 0x00, 0xE3, 0x00, 0x21, 0xFE,
+ 0x43, 0xFB, 0xE9, 0x02, 0xA9, 0x15, 0x79, 0x21, 0x6B, 0x18, 0x48,
+ 0x05, 0x80, 0xFB, 0x7C, 0xFD, 0xB9, 0x00, 0xA0, 0x00, 0xFD, 0xFF,
+ 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xA6, 0x00, 0xAF, 0x00, 0x5E,
+ 0xFD, 0x93, 0xFB, 0xBE, 0x05, 0xE5, 0x18, 0x6B, 0x21, 0x23, 0x15,
+ 0x82, 0x02, 0x3F, 0xFB, 0x3F, 0xFE, 0xE9, 0x00, 0x77, 0x00, 0xF8,
+ 0xFF, 0xFE, 0xFF, 0x0C, 0x00, 0xCD, 0x00, 0x5A, 0x00, 0xA0, 0xFC,
+ 0x4D, 0xFC, 0xEA, 0x08, 0xC6, 0x1B, 0xA1, 0x20, 0xA6, 0x11, 0x26,
+ 0x00, 0x57, 0xFB, 0xF8, 0xFE, 0xFB, 0x00, 0x50, 0x00, 0xF7, 0xFF,
+ 0xFB, 0xFF, 0x21, 0x00, 0xEB, 0x00, 0xE3, 0xFF, 0xFA, 0xFB, 0x7C,
+ 0xFD, 0x54, 0x0C, 0x2B, 0x1E, 0x26, 0x1F, 0x17, 0x0E, 0x41, 0xFE,
+ 0xB6, 0xFB, 0x9C, 0xFF, 0xF5, 0x00, 0x2F, 0x00, 0xF9, 0xFF, 0xF8,
+ 0xFF, 0x3F, 0x00, 0xFB, 0x00, 0x4D, 0xFF, 0x7F, 0xFB, 0x24, 0xFF,
+ 0xDF, 0x0F, 0xF9, 0x1F, 0x09, 0x1D, 0x99, 0x0A, 0xD5, 0xFC, 0x49,
+ 0xFC, 0x23, 0x00, 0xDD, 0x00, 0x16, 0x00, 0xFC, 0xFF, 0xF7, 0xFF,
+ 0x63, 0x00, 0xF5, 0x00, 0x9E, 0xFE, 0x41, 0xFB, 0x46, 0x01, 0x69,
+ 0x13, 0x1D, 0x21, 0x63, 0x1A, 0x4B, 0x07, 0xE2, 0xFB, 0xFD, 0xFC,
+ 0x89, 0x00, 0xBA, 0x00, 0x04, 0x00, 0xFF, 0xFF, 0xFA, 0xFF, 0x8B,
+ 0x00, 0xD5, 0x00, 0xDE, 0xFD, 0x53, 0xFB, 0xD9, 0x03, 0xD0, 0x16,
+ 0x8A, 0x21, 0x51, 0x17, 0x47, 0x04, 0x5E, 0xFB, 0xC0, 0xFD, 0xCD,
+ 0x00, 0x92, 0x00, 0xFB, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0x02, 0x00,
+ 0xB4, 0x00, 0x96, 0x00, 0x1B, 0xFD, 0xC7, 0xFB, 0xCF, 0x06, 0xF0,
+ 0x19, 0x3A, 0x21, 0xF2, 0x13, 0xA4, 0x01, 0x3E, 0xFB, 0x81, 0xFE,
+ 0xF2, 0x00, 0x69, 0x00, 0xF7, 0xFF, 0xFD, 0xFF, 0x12, 0x00, 0xD9,
+ 0x00, 0x35, 0x00, 0x63, 0xFC, 0xA8, 0xFC, 0x13, 0x0A, 0xA9, 0x1C,
+ 0x32, 0x20, 0x6B, 0x10, 0x71, 0xFF, 0x71, 0xFB, 0x34, 0xFF, 0xFB,
+ 0x00, 0x44, 0x00, 0xF8, 0xFF, 0xFA, 0xFF, 0x2B, 0x00, 0xF3, 0x00,
+ 0xB3, 0xFF, 0xCA, 0xFB, 0x01, 0xFE, 0x8C, 0x0D, 0xDD, 0x1E, 0x7C,
+ 0x1E, 0xDE, 0x0C, 0xB5, 0xFD, 0xE4, 0xFB, 0xCE, 0xFF, 0xEF, 0x00,
+ 0x25, 0x00, 0xFA, 0xFF, 0xF7, 0xFF, 0x4A, 0x00, 0xFC, 0x00, 0x13,
+ 0xFF, 0x61, 0xFB, 0xD4, 0xFF, 0x1A, 0x11, 0x72, 0x20, 0x2D, 0x1C,
+ 0x6D, 0x09, 0x74, 0xFC, 0x85, 0xFC, 0x4A, 0x00, 0xD2, 0x00, 0x0F,
+ 0x00, 0xFD, 0xFF, 0xF7, 0xFF, 0x70, 0x00, 0xED, 0x00, 0x5D, 0xFE,
+ 0x3D, 0xFB, 0x1E, 0x02, 0x9C, 0x14, 0x58, 0x21, 0x5E, 0x19, 0x36,
+ 0x06, 0xA8, 0xFB, 0x40, 0xFD, 0xA4, 0x00, 0xAD, 0x00, 0x00, 0x00,
+ 0xFF, 0xFF, 0x00, 0x00, 0xFC, 0xFF, 0x9A, 0x00, 0xC3, 0x00, 0x9A,
+ 0xFD, 0x6F, 0xFB, 0xD5, 0x04, 0xEF, 0x17, 0x83, 0x21, 0x2D, 0x16,
+ 0x52, 0x03, 0x49, 0xFB, 0x04, 0xFE, 0xDD, 0x00, 0x83, 0x00, 0xF9,
+ 0xFF, 0xFF, 0xFF, 0x07, 0x00, 0xC2, 0x00, 0x78, 0x00, 0xD9, 0xFC,
+ 0x08, 0xFC, 0xE9, 0x07, 0xEF, 0x1A, 0xF3, 0x20, 0xBC, 0x12, 0xD4,
+ 0x00, 0x47, 0xFB, 0xC1, 0xFE, 0xF8, 0x00, 0x5B, 0x00, 0xF7, 0xFF,
+ 0xFC, 0xFF, 0x1A, 0x00, 0xE3, 0x00, 0x0B, 0x00, 0x2A, 0xFC, 0x12,
+ 0xFD, 0x42, 0x0B, 0x7D, 0x1D, 0xAD, 0x1F, 0x2F, 0x0F, 0xC9, 0xFE,
+ 0x92, 0xFB, 0x6C, 0xFF, 0xF9, 0x00, 0x38, 0x00, 0xF8, 0xFF, 0xF9,
+ 0xFF, 0x35, 0x00, 0xF8, 0x00, 0x7E, 0xFF, 0x9F, 0xFB, 0x95, 0xFE,
+ 0xC6, 0x0E, 0x7C, 0x1F, 0xC0, 0x1D, 0xA9, 0x0B, 0x38, 0xFD, 0x18,
+ 0xFC, 0xFD, 0xFF, 0xE6, 0x00, 0x1D, 0x00, 0xFB, 0xFF, 0xF7, 0xFF,
+ 0x57, 0x00, 0xFA, 0x00, 0xD6, 0xFE, 0x4C, 0xFB, 0x92, 0x00, 0x54,
+ 0x12, 0xD6, 0x20, 0x41, 0x1B, 0x49, 0x08, 0x20, 0xFC, 0xC3, 0xFC,
+ 0x6D, 0x00, 0xC6, 0x00, 0x09, 0x00, 0xFE, 0xFF, 0xF8, 0xFF, 0x7E,
+ 0x00, 0xE2, 0x00, 0x1A, 0xFE, 0x44, 0xFB, 0x03, 0x03, 0xCA, 0x15,
+ 0x7C, 0x21, 0x4C, 0x18, 0x2B, 0x05, 0x7B, 0xFB, 0x83, 0xFD, 0xBC,
+ 0x00, 0x9E, 0x00, 0xFD, 0xFF, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF,
+ 0xA8, 0x00, 0xAD, 0x00, 0x56, 0xFD, 0x98, 0xFB, 0xDC, 0x05, 0x04,
+ 0x19, 0x66, 0x21, 0x02, 0x15, 0x69, 0x02, 0x3E, 0xFB, 0x47, 0xFE,
+ 0xEA, 0x00, 0x75, 0x00, 0xF8, 0xFF, 0xFE, 0xFF, 0x0D, 0x00, 0xCE,
+ 0x00, 0x56, 0x00, 0x99, 0xFC, 0x56, 0xFC, 0x0B, 0x09, 0xE0, 0x1B,
+ 0x96, 0x20, 0x83, 0x11, 0x11, 0x00, 0x59, 0xFB, 0xFF, 0xFE, 0xFB,
+ 0x00, 0x4E, 0x00, 0xF7, 0xFF, 0xFB, 0xFF, 0x22, 0x00, 0xEC, 0x00,
+ 0xDE, 0xFF, 0xF5, 0xFB, 0x8A, 0xFD, 0x77, 0x0C, 0x3F, 0x1E, 0x14,
+ 0x1F, 0xF5, 0x0D, 0x31, 0xFE, 0xBB, 0xFB, 0xA2, 0xFF, 0xF5, 0x00,
+ 0x2E, 0x00, 0xF9, 0xFF, 0xF8, 0xFF, 0x40, 0x00, 0xFB, 0x00, 0x47,
+ 0xFF, 0x7B, 0xFB, 0x37, 0xFF, 0x02, 0x10, 0x07, 0x20, 0xF2, 0x1C,
+ 0x78, 0x0A, 0xCA, 0xFC, 0x50, 0xFC, 0x27, 0x00, 0xDC, 0x00, 0x15,
+ 0x00, 0xFC, 0xFF, 0xF7, 0xFF, 0x64, 0x00, 0xF5, 0x00, 0x97, 0xFE,
+ 0x40, 0xFB, 0x5D, 0x01, 0x8B, 0x13, 0x25, 0x21, 0x47, 0x1A, 0x2C,
+ 0x07, 0xDB, 0xFB, 0x05, 0xFD, 0x8C, 0x00, 0xB9, 0x00, 0x04, 0x00,
+ 0xFF, 0xFF, 0xFA, 0xFF, 0x8D, 0x00, 0xD3, 0x00, 0xD6, 0xFD, 0x56,
+ 0xFB, 0xF4, 0x03, 0xF0, 0x16, 0x8A, 0x21, 0x31, 0x17, 0x2B, 0x04,
+ 0x5B, 0xFB, 0xC7, 0xFD, 0xCF, 0x00, 0x90, 0x00, 0xFA, 0xFF, 0x00,
+ 0x00, 0xFF, 0xFF, 0x03, 0x00, 0xB6, 0x00, 0x92, 0x00, 0x13, 0xFD,
+ 0xCD, 0xFB, 0xEE, 0x06, 0x0D, 0x1A, 0x33, 0x21, 0xD0, 0x13, 0x8C,
+ 0x01, 0x3E, 0xFB, 0x88, 0xFE, 0xF3, 0x00, 0x67, 0x00, 0xF7, 0xFF,
+ 0x06, 0x00, 0x1D, 0x00, 0x03, 0xFF, 0xFE, 0x00, 0xA1, 0x02, 0xA6,
+ 0xF8, 0x56, 0x02, 0xA5, 0x28, 0xA5, 0x28, 0x56, 0x02, 0xA6, 0xF8,
+ 0xA1, 0x02, 0xFE, 0x00, 0x03, 0xFF, 0x1D, 0x00, 0x06, 0x00, 0x00,
+ 0x00, 0x21, 0x00, 0xA6, 0xFF, 0x3F, 0xFF, 0x0B, 0x03, 0x42, 0xFE,
+ 0x3E, 0xF8, 0x7F, 0x15, 0xAC, 0x30, 0x7F, 0x15, 0x3E, 0xF8, 0x42,
+ 0xFE, 0x0B, 0x03, 0x3F, 0xFF, 0xA6, 0xFF, 0x21, 0x00, 0x00, 0x00,
+ 0xFA, 0xFF, 0xCE, 0xFF, 0x14, 0x01, 0x00, 0xFD, 0x35, 0x06, 0xD5,
+ 0xF4, 0xDA, 0x15, 0x92, 0x40, 0xAE, 0xFE, 0xF3, 0xFC, 0x68, 0x03,
+ 0x86, 0xFD, 0x51, 0x01, 0x8B, 0xFF, 0x11, 0x00, 0x01, 0x00, 0xEC,
+ 0xFF, 0xF9, 0xFF, 0xC6, 0x00, 0x55, 0xFD, 0x35, 0x06, 0x90, 0xF3,
+ 0xE5, 0x1C, 0x6B, 0x3D, 0x71, 0xFA, 0x34, 0xFF, 0x46, 0x02, 0xFF,
+ 0xFD, 0x2D, 0x01, 0x90, 0xFF, 0x10, 0x00, 0x03, 0x00, 0xDB, 0xFF,
+ 0x2D, 0x00, 0x60, 0x00, 0xE1, 0xFD, 0xCE, 0x05, 0xED, 0xF2, 0xF3,
+ 0x23, 0x20, 0x39, 0x22, 0xF7, 0x44, 0x01, 0x1F, 0x01, 0x89, 0xFE,
+ 0xFB, 0x00, 0x9C, 0xFF, 0x0D, 0x00, 0x06, 0x00, 0xC9, 0xFF, 0x68,
+ 0x00, 0xE5, 0xFF, 0xA0, 0xFE, 0xFB, 0x04, 0x0C, 0xF3, 0xC5, 0x2A,
+ 0xD8, 0x33, 0xC9, 0xF4, 0x0B, 0x03, 0x05, 0x00, 0x1A, 0xFF, 0xC1,
+ 0x00, 0xAD, 0xFF, 0x0A, 0x00, 0x09, 0x00, 0xB5, 0xFF, 0xA5, 0x00,
+ 0x5C, 0xFF, 0x8C, 0xFF, 0xBF, 0x03, 0x06, 0xF4, 0x22, 0x31, 0xC8,
+ 0x2D, 0x63, 0xF3, 0x76, 0x04, 0x08, 0xFF, 0xA7, 0xFF, 0x84, 0x00,
+ 0xC0, 0xFF, 0x07, 0x00, 0x0C, 0x00, 0xA4, 0xFF, 0xE1, 0x00, 0xCB,
+ 0xFE, 0x9B, 0x00, 0x21, 0x02, 0xEE, 0xF5, 0xCD, 0x36, 0x24, 0x27,
+ 0xE1, 0xF2, 0x7A, 0x05, 0x33, 0xFE, 0x2A, 0x00, 0x47, 0x00, 0xD3,
+ 0xFF, 0x04, 0x00, 0x0F, 0x00, 0x95, 0xFF, 0x17, 0x01, 0x3D, 0xFE,
+ 0xBD, 0x01, 0x30, 0x00, 0xCC, 0xF8, 0x92, 0x3B, 0x2A, 0x20, 0x2E,
+ 0xF3, 0x12, 0x06, 0x8F, 0xFD, 0x9A, 0x00, 0x10, 0x00, 0xE5, 0xFF,
+ 0x02, 0x00, 0x10, 0x00, 0x8C, 0xFF, 0x42, 0x01, 0xBB, 0xFD, 0xE4,
+ 0x02, 0x01, 0xFE, 0x9C, 0xFC, 0x45, 0x3F, 0x16, 0x19, 0x2D, 0xF4,
+ 0x41, 0x06, 0x21, 0xFD, 0xF3, 0x00, 0xE0, 0xFF, 0xF4, 0xFF, 0x01,
+ 0x00, 0x10, 0x00, 0x8B, 0xFF, 0x5D, 0x01, 0x4F, 0xFD, 0xFB, 0x03,
+ 0xB2, 0xFB, 0x53, 0x01, 0xC2, 0x41, 0x24, 0x12, 0xBA, 0xF5, 0x0F,
+ 0x06, 0xE9, 0xFC, 0x33, 0x01, 0xBB, 0xFF, 0x00, 0x00, 0x00, 0x00,
+ 0x0D, 0x00, 0x93, 0xFF, 0x63, 0x01, 0x04, 0xFD, 0xEF, 0x04, 0x62,
+ 0xF9, 0xD7, 0x06, 0xF2, 0x42, 0x8D, 0x0B, 0xB0, 0xF7, 0x87, 0x05,
+ 0xE6, 0xFC, 0x58, 0x01, 0xA0, 0xFF, 0x09, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x07, 0x00, 0xA5, 0xFF, 0x52, 0x01, 0xE2, 0xFC, 0xAD, 0x05,
+ 0x35, 0xF7, 0x08, 0x0D, 0xCB, 0x42, 0x81, 0x05, 0xE8, 0xF9, 0xBB,
+ 0x04, 0x12, 0xFD, 0x64, 0x01, 0x90, 0xFF, 0x0E, 0x00, 0x00, 0x00,
+ 0xFE, 0xFF, 0xC2, 0xFF, 0x27, 0x01, 0xF1, 0xFC, 0x22, 0x06, 0x54,
+ 0xF5, 0xB8, 0x13, 0x4A, 0x41, 0x29, 0x00, 0x3C, 0xFC, 0xBD, 0x03,
+ 0x66, 0xFD, 0x58, 0x01, 0x8A, 0xFF, 0x11, 0x00, 0x01, 0x00, 0xF1,
+ 0xFF, 0xEB, 0xFF, 0xE1, 0x00, 0x35, 0xFD, 0x40, 0x06, 0xE4, 0xF3,
+ 0xB7, 0x1A, 0x85, 0x3E, 0xA6, 0xFB, 0x86, 0xFE, 0xA0, 0x02, 0xD7,
+ 0xFD, 0x39, 0x01, 0x8E, 0xFF, 0x10, 0x00, 0x03, 0x00, 0xE1, 0xFF,
+ 0x1C, 0x00, 0x82, 0x00, 0xB0, 0xFD, 0xF9, 0x05, 0x0C, 0xF3, 0xCB,
+ 0x21, 0x8F, 0x3A, 0x0D, 0xF8, 0xA9, 0x00, 0x79, 0x01, 0x5D, 0xFE,
+ 0x0B, 0x01, 0x98, 0xFF, 0x0E, 0x00, 0x05, 0x00, 0xCE, 0xFF, 0x55,
+ 0x00, 0x0D, 0x00, 0x60, 0xFE, 0x48, 0x05, 0xEC, 0xF2, 0xB6, 0x28,
+ 0x91, 0x35, 0x68, 0xF5, 0x88, 0x02, 0x5A, 0x00, 0xED, 0xFE, 0xD4,
+ 0x00, 0xA8, 0xFF, 0x0B, 0x00, 0x08, 0x00, 0xBB, 0xFF, 0x92, 0x00,
+ 0x87, 0xFF, 0x3F, 0xFF, 0x2B, 0x04, 0xA1, 0xF3, 0x3D, 0x2F, 0xB8,
+ 0x2F, 0xB8, 0xF3, 0x11, 0x04, 0x52, 0xFF, 0x7C, 0xFF, 0x97, 0x00,
+ 0xBA, 0xFF, 0x08, 0x00, 0x0B, 0x00, 0xA9, 0xFF, 0xCF, 0x00, 0xF8,
+ 0xFE, 0x44, 0x00, 0xAA, 0x02, 0x3E, 0xF5, 0x24, 0x35, 0x3B, 0x29,
+ 0xF2, 0xF2, 0x35, 0x05, 0x70, 0xFE, 0x03, 0x00, 0x5A, 0x00, 0xCD,
+ 0xFF, 0x05, 0x00, 0x0E, 0x00, 0x99, 0xFF, 0x07, 0x01, 0x68, 0xFE,
+ 0x63, 0x01, 0xD0, 0x00, 0xD0, 0xF7, 0x35, 0x3A, 0x55, 0x22, 0x02,
+ 0xF3, 0xEF, 0x05, 0xBC, 0xFD, 0x7A, 0x00, 0x20, 0x00, 0xDF, 0xFF,
+ 0x03, 0x00, 0x10, 0x00, 0x8E, 0xFF, 0x36, 0x01, 0xE1, 0xFD, 0x8A,
+ 0x02, 0xB2, 0xFE, 0x56, 0xFB, 0x40, 0x3E, 0x42, 0x1B, 0xCE, 0xF3,
+ 0x3E, 0x06, 0x3D, 0xFD, 0xDB, 0x00, 0xEE, 0xFF, 0xF0, 0xFF, 0x01,
+ 0x00, 0x11, 0x00, 0x8A, 0xFF, 0x57, 0x01, 0x6D, 0xFD, 0xA8, 0x03,
+ 0x69, 0xFC, 0xC8, 0xFF, 0x20, 0x41, 0x40, 0x14, 0x33, 0xF5, 0x28,
+ 0x06, 0xF5, 0xFC, 0x22, 0x01, 0xC5, 0xFF, 0xFD, 0xFF, 0x00, 0x00,
+ 0x0F, 0x00, 0x8F, 0xFF, 0x64, 0x01, 0x17, 0xFD, 0xA9, 0x04, 0x16,
+ 0xFA, 0x10, 0x05, 0xB8, 0x42, 0x87, 0x0D, 0x0D, 0xF7, 0xB9, 0x05,
+ 0xE2, 0xFC, 0x50, 0x01, 0xA7, 0xFF, 0x07, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x0A, 0x00, 0x9E, 0xFF, 0x5A, 0x01, 0xE8, 0xFC, 0x7A, 0x05,
+ 0xDA, 0xF7, 0x10, 0x0B, 0xFB, 0x42, 0x4B, 0x07, 0x35, 0xF9, 0x00,
+ 0x05, 0x00, 0xFD, 0x63, 0x01, 0x94, 0xFF, 0x0D, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0xB8, 0xFF, 0x37, 0x01, 0xE7, 0xFC, 0x07, 0x06, 0xDE,
+ 0xF5, 0x9F, 0x11, 0xE4, 0x41, 0xB8, 0x01, 0x84, 0xFB, 0x0F, 0x04,
+ 0x48, 0xFD, 0x5E, 0x01, 0x8B, 0xFF, 0x10, 0x00, 0x01, 0x00, 0xF5,
+ 0xFF, 0xDD, 0xFF, 0xF9, 0x00, 0x1B, 0xFD, 0x41, 0x06, 0x47, 0xF4,
+ 0x8B, 0x18, 0x81, 0x3F, 0xF1, 0xFC, 0xD5, 0xFD, 0xFA, 0x02, 0xB2,
+ 0xFD, 0x45, 0x01, 0x8C, 0xFF, 0x11, 0x00, 0x02, 0x00, 0xE6, 0xFF,
+ 0x0C, 0x00, 0xA2, 0x00, 0x85, 0xFD, 0x1A, 0x06, 0x3C, 0xF3, 0x9F,
+ 0x1F, 0xE6, 0x3B, 0x0E, 0xF9, 0x07, 0x00, 0xD4, 0x01, 0x33, 0xFE,
+ 0x1B, 0x01, 0x94, 0xFF, 0x0F, 0x00, 0x04, 0x00, 0xD4, 0xFF, 0x43,
+ 0x00, 0x33, 0x00, 0x25, 0xFE, 0x89, 0x05, 0xE0, 0xF2, 0x9C, 0x26,
+ 0x33, 0x37, 0x1E, 0xF6, 0xFD, 0x01, 0xB0, 0x00, 0xC0, 0xFE, 0xE6,
+ 0x00, 0xA2, 0xFF, 0x0C, 0x00, 0x07, 0x00, 0xC1, 0xFF, 0x7F, 0x00,
+ 0xB2, 0xFF, 0xF6, 0xFE, 0x8E, 0x04, 0x51, 0xF3, 0x49, 0x2D, 0x98,
+ 0x31, 0x23, 0xF4, 0xA2, 0x03, 0xA0, 0xFF, 0x51, 0xFF, 0xAA, 0x00,
+ 0xB4, 0xFF, 0x09, 0x00, 0x0A, 0x00, 0xAE, 0xFF, 0xBD, 0x00, 0x25,
+ 0xFF, 0xF1, 0xFF, 0x2B, 0x03, 0xA5, 0xF4, 0x68, 0x33, 0x48, 0x2B,
+ 0x17, 0xF3, 0xE7, 0x04, 0xB1, 0xFE, 0xDB, 0xFF, 0x6C, 0x00, 0xC7,
+ 0xFF, 0x06, 0x00, 0x0D, 0x00, 0x9E, 0xFF, 0xF7, 0x00, 0x94, 0xFE,
+ 0x09, 0x01, 0x6A, 0x01, 0xEB, 0xF6, 0xC1, 0x38, 0x7D, 0x24, 0xE8,
+ 0xF2, 0xC1, 0x05, 0xEE, 0xFD, 0x57, 0x00, 0x31, 0x00, 0xDA, 0xFF,
+ 0x03, 0x00, 0x10, 0x00, 0x91, 0xFF, 0x29, 0x01, 0x09, 0xFE, 0x2F,
+ 0x02, 0x5F, 0xFF, 0x27, 0xFA, 0x20, 0x3D, 0x70, 0x1D, 0x7D, 0xF3,
+ 0x31, 0x06, 0x5E, 0xFD, 0xBF, 0x00, 0xFD, 0xFF, 0xEB, 0xFF, 0x02,
+ 0x00, 0x11, 0x00, 0x8B, 0xFF, 0x4E, 0x01, 0x8E, 0xFD, 0x52, 0x03,
+ 0x20, 0xFD, 0x52, 0xFE, 0x60, 0x40, 0x63, 0x16, 0xB7, 0xF4, 0x39,
+ 0x06, 0x05, 0xFD, 0x0F, 0x01, 0xD1, 0xFF, 0xF9, 0xFF, 0x00, 0x00,
+ 0x10, 0x00, 0x8D, 0xFF, 0x62, 0x01, 0x2E, 0xFD, 0x5E, 0x04, 0xCC,
+ 0xFA, 0x5B, 0x03, 0x5E, 0x42, 0x8E, 0x0F, 0x71, 0xF6, 0xE4, 0x05,
+ 0xE2, 0xFC, 0x45, 0x01, 0xAF, 0xFF, 0x04, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x0B, 0x00, 0x99, 0xFF, 0x60, 0x01, 0xF2, 0xFC, 0x40, 0x05,
+ 0x85, 0xF8, 0x26, 0x09, 0x0C, 0x43, 0x26, 0x09, 0x85, 0xF8, 0x40,
+ 0x05, 0xF2, 0xFC, 0x60, 0x01, 0x99, 0xFF, 0x0B, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0xAF, 0xFF, 0x45, 0x01, 0xE2, 0xFC, 0xE4, 0x05, 0x71,
+ 0xF6, 0x8E, 0x0F, 0x5E, 0x42, 0x5B, 0x03, 0xCC, 0xFA, 0x5E, 0x04,
+ 0x2E, 0xFD, 0x62, 0x01, 0x8D, 0xFF, 0x10, 0x00, 0x00, 0x00, 0xF9,
+ 0xFF, 0xD1, 0xFF, 0x0F, 0x01, 0x05, 0xFD, 0x39, 0x06, 0xB7, 0xF4,
+ 0x63, 0x16, 0x60, 0x40, 0x52, 0xFE, 0x20, 0xFD, 0x52, 0x03, 0x8E,
+ 0xFD, 0x4E, 0x01, 0x8B, 0xFF, 0x11, 0x00, 0x02, 0x00, 0xEB, 0xFF,
+ 0xFD, 0xFF, 0xBF, 0x00, 0x5E, 0xFD, 0x31, 0x06, 0x7D, 0xF3, 0x70,
+ 0x1D, 0x20, 0x3D, 0x27, 0xFA, 0x5F, 0xFF, 0x2F, 0x02, 0x09, 0xFE,
+ 0x29, 0x01, 0x91, 0xFF, 0x10, 0x00, 0x03, 0x00, 0xDA, 0xFF, 0x31,
+ 0x00, 0x57, 0x00, 0xEE, 0xFD, 0xC1, 0x05, 0xE8, 0xF2, 0x7D, 0x24,
+ 0xC1, 0x38, 0xEB, 0xF6, 0x6A, 0x01, 0x09, 0x01, 0x94, 0xFE, 0xF7,
+ 0x00, 0x9E, 0xFF, 0x0D, 0x00, 0x06, 0x00, 0xC7, 0xFF, 0x6C, 0x00,
+ 0xDB, 0xFF, 0xB1, 0xFE, 0xE7, 0x04, 0x17, 0xF3, 0x48, 0x2B, 0x68,
+ 0x33, 0xA5, 0xF4, 0x2B, 0x03, 0xF1, 0xFF, 0x25, 0xFF, 0xBD, 0x00,
+ 0xAE, 0xFF, 0x0A, 0x00, 0x09, 0x00, 0xB4, 0xFF, 0xAA, 0x00, 0x51,
+ 0xFF, 0xA0, 0xFF, 0xA2, 0x03, 0x23, 0xF4, 0x98, 0x31, 0x49, 0x2D,
+ 0x51, 0xF3, 0x8E, 0x04, 0xF6, 0xFE, 0xB2, 0xFF, 0x7F, 0x00, 0xC1,
+ 0xFF, 0x07, 0x00, 0x0C, 0x00, 0xA2, 0xFF, 0xE6, 0x00, 0xC0, 0xFE,
+ 0xB0, 0x00, 0xFD, 0x01, 0x1E, 0xF6, 0x33, 0x37, 0x9C, 0x26, 0xE0,
+ 0xF2, 0x89, 0x05, 0x25, 0xFE, 0x33, 0x00, 0x43, 0x00, 0xD4, 0xFF,
+ 0x04, 0x00, 0x0F, 0x00, 0x94, 0xFF, 0x1B, 0x01, 0x33, 0xFE, 0xD4,
+ 0x01, 0x07, 0x00, 0x0E, 0xF9, 0xE6, 0x3B, 0x9F, 0x1F, 0x3C, 0xF3,
+ 0x1A, 0x06, 0x85, 0xFD, 0xA2, 0x00, 0x0C, 0x00, 0xE6, 0xFF, 0x02,
+ 0x00, 0x11, 0x00, 0x8C, 0xFF, 0x45, 0x01, 0xB2, 0xFD, 0xFA, 0x02,
+ 0xD5, 0xFD, 0xF1, 0xFC, 0x81, 0x3F, 0x8B, 0x18, 0x47, 0xF4, 0x41,
+ 0x06, 0x1B, 0xFD, 0xF9, 0x00, 0xDD, 0xFF, 0xF5, 0xFF, 0x01, 0x00,
+ 0x10, 0x00, 0x8B, 0xFF, 0x5E, 0x01, 0x48, 0xFD, 0x0F, 0x04, 0x84,
+ 0xFB, 0xB8, 0x01, 0xE4, 0x41, 0x9F, 0x11, 0xDE, 0xF5, 0x07, 0x06,
+ 0xE7, 0xFC, 0x37, 0x01, 0xB8, 0xFF, 0x01, 0x00, 0x00, 0x00, 0x0D,
+ 0x00, 0x94, 0xFF, 0x63, 0x01, 0x00, 0xFD, 0x00, 0x05, 0x35, 0xF9,
+ 0x4B, 0x07, 0xFB, 0x42, 0x10, 0x0B, 0xDA, 0xF7, 0x7A, 0x05, 0xE8,
+ 0xFC, 0x5A, 0x01, 0x9E, 0xFF, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x07, 0x00, 0xA7, 0xFF, 0x50, 0x01, 0xE2, 0xFC, 0xB9, 0x05, 0x0D,
+ 0xF7, 0x87, 0x0D, 0xB8, 0x42, 0x10, 0x05, 0x16, 0xFA, 0xA9, 0x04,
+ 0x17, 0xFD, 0x64, 0x01, 0x8F, 0xFF, 0x0F, 0x00, 0x00, 0x00, 0xFD,
+ 0xFF, 0xC5, 0xFF, 0x22, 0x01, 0xF5, 0xFC, 0x28, 0x06, 0x33, 0xF5,
+ 0x40, 0x14, 0x20, 0x41, 0xC8, 0xFF, 0x69, 0xFC, 0xA8, 0x03, 0x6D,
+ 0xFD, 0x57, 0x01, 0x8A, 0xFF, 0x11, 0x00, 0x01, 0x00, 0xF0, 0xFF,
+ 0xEE, 0xFF, 0xDB, 0x00, 0x3D, 0xFD, 0x3E, 0x06, 0xCE, 0xF3, 0x42,
+ 0x1B, 0x40, 0x3E, 0x56, 0xFB, 0xB2, 0xFE, 0x8A, 0x02, 0xE1, 0xFD,
+ 0x36, 0x01, 0x8E, 0xFF, 0x10, 0x00, 0x03, 0x00, 0xDF, 0xFF, 0x20,
+ 0x00, 0x7A, 0x00, 0xBC, 0xFD, 0xEF, 0x05, 0x02, 0xF3, 0x55, 0x22,
+ 0x35, 0x3A, 0xD0, 0xF7, 0xD0, 0x00, 0x63, 0x01, 0x68, 0xFE, 0x07,
+ 0x01, 0x99, 0xFF, 0x0E, 0x00, 0x05, 0x00, 0xCD, 0xFF, 0x5A, 0x00,
+ 0x03, 0x00, 0x70, 0xFE, 0x35, 0x05, 0xF2, 0xF2, 0x3B, 0x29, 0x24,
+ 0x35, 0x3E, 0xF5, 0xAA, 0x02, 0x44, 0x00, 0xF8, 0xFE, 0xCF, 0x00,
+ 0xA9, 0xFF, 0x0B, 0x00, 0x08, 0x00, 0xBA, 0xFF, 0x97, 0x00, 0x7C,
+ 0xFF, 0x52, 0xFF, 0x11, 0x04, 0xB8, 0xF3, 0xB8, 0x2F, 0x3D, 0x2F,
+ 0xA1, 0xF3, 0x2B, 0x04, 0x3F, 0xFF, 0x87, 0xFF, 0x92, 0x00, 0xBB,
+ 0xFF, 0x08, 0x00, 0x0B, 0x00, 0xA8, 0xFF, 0xD4, 0x00, 0xED, 0xFE,
+ 0x5A, 0x00, 0x88, 0x02, 0x68, 0xF5, 0x91, 0x35, 0xB6, 0x28, 0xEC,
+ 0xF2, 0x48, 0x05, 0x60, 0xFE, 0x0D, 0x00, 0x55, 0x00, 0xCE, 0xFF,
+ 0x05, 0x00, 0x0E, 0x00, 0x98, 0xFF, 0x0B, 0x01, 0x5D, 0xFE, 0x79,
+ 0x01, 0xA9, 0x00, 0x0D, 0xF8, 0x8F, 0x3A, 0xCB, 0x21, 0x0C, 0xF3,
+ 0xF9, 0x05, 0xB0, 0xFD, 0x82, 0x00, 0x1C, 0x00, 0xE1, 0xFF, 0x03,
+ 0x00, 0x10, 0x00, 0x8E, 0xFF, 0x39, 0x01, 0xD7, 0xFD, 0xA0, 0x02,
+ 0x86, 0xFE, 0xA6, 0xFB, 0x85, 0x3E, 0xB7, 0x1A, 0xE4, 0xF3, 0x40,
+ 0x06, 0x35, 0xFD, 0xE1, 0x00, 0xEB, 0xFF, 0xF1, 0xFF, 0x01, 0x00,
+ 0x11, 0x00, 0x8A, 0xFF, 0x58, 0x01, 0x66, 0xFD, 0xBD, 0x03, 0x3C,
+ 0xFC, 0x29, 0x00, 0x4A, 0x41, 0xB8, 0x13, 0x54, 0xF5, 0x22, 0x06,
+ 0xF1, 0xFC, 0x27, 0x01, 0xC2, 0xFF, 0xFE, 0xFF, 0x00, 0x00, 0x0E,
+ 0x00, 0x90, 0xFF, 0x64, 0x01, 0x12, 0xFD, 0xBB, 0x04, 0xE8, 0xF9,
+ 0x81, 0x05, 0xCB, 0x42, 0x08, 0x0D, 0x35, 0xF7, 0xAD, 0x05, 0xE2,
+ 0xFC, 0x52, 0x01, 0xA5, 0xFF, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x09, 0x00, 0xA0, 0xFF, 0x58, 0x01, 0xE6, 0xFC, 0x87, 0x05, 0xB0,
+ 0xF7, 0x8D, 0x0B, 0xF2, 0x42, 0xD7, 0x06, 0x62, 0xF9, 0xEF, 0x04,
+ 0x04, 0xFD, 0x63, 0x01, 0x93, 0xFF, 0x0D, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0xBB, 0xFF, 0x33, 0x01, 0xE9, 0xFC, 0x0F, 0x06, 0xBA, 0xF5,
+ 0x24, 0x12, 0xC2, 0x41, 0x53, 0x01, 0xB2, 0xFB, 0xFB, 0x03, 0x4F,
+ 0xFD, 0x5D, 0x01, 0x8B, 0xFF, 0x10, 0x00, 0x01, 0x00, 0xF4, 0xFF,
+ 0xE0, 0xFF, 0xF3, 0x00, 0x21, 0xFD, 0x41, 0x06, 0x2D, 0xF4, 0x16,
+ 0x19, 0x45, 0x3F, 0x9C, 0xFC, 0x01, 0xFE, 0xE4, 0x02, 0xBB, 0xFD,
+ 0x42, 0x01, 0x8C, 0xFF, 0x10, 0x00, 0x02, 0x00, 0xE5, 0xFF, 0x10,
+ 0x00, 0x9A, 0x00, 0x8F, 0xFD, 0x12, 0x06, 0x2E, 0xF3, 0x2A, 0x20,
+ 0x92, 0x3B, 0xCC, 0xF8, 0x30, 0x00, 0xBD, 0x01, 0x3D, 0xFE, 0x17,
+ 0x01, 0x95, 0xFF, 0x0F, 0x00, 0x04, 0x00, 0xD3, 0xFF, 0x47, 0x00,
+ 0x2A, 0x00, 0x33, 0xFE, 0x7A, 0x05, 0xE1, 0xF2, 0x24, 0x27, 0xCD,
+ 0x36, 0xEE, 0xF5, 0x21, 0x02, 0x9B, 0x00, 0xCB, 0xFE, 0xE1, 0x00,
+ 0xA4, 0xFF, 0x0C, 0x00, 0x07, 0x00, 0xC0, 0xFF, 0x84, 0x00, 0xA7,
+ 0xFF, 0x08, 0xFF, 0x76, 0x04, 0x63, 0xF3, 0xC8, 0x2D, 0x22, 0x31,
+ 0x06, 0xF4, 0xBF, 0x03, 0x8C, 0xFF, 0x5C, 0xFF, 0xA5, 0x00, 0xB5,
+ 0xFF, 0x09, 0x00, 0x0A, 0x00, 0xAD, 0xFF, 0xC1, 0x00, 0x1A, 0xFF,
+ 0x05, 0x00, 0x0B, 0x03, 0xC9, 0xF4, 0xD8, 0x33, 0xC5, 0x2A, 0x0C,
+ 0xF3, 0xFB, 0x04, 0xA0, 0xFE, 0xE5, 0xFF, 0x68, 0x00, 0xC9, 0xFF,
+ 0x06, 0x00, 0x0D, 0x00, 0x9C, 0xFF, 0xFB, 0x00, 0x89, 0xFE, 0x1F,
+ 0x01, 0x44, 0x01, 0x22, 0xF7, 0x20, 0x39, 0xF3, 0x23, 0xED, 0xF2,
+ 0xCE, 0x05, 0xE1, 0xFD, 0x60, 0x00, 0x2D, 0x00, 0xDB, 0xFF, 0x03,
+ 0x00, 0x10, 0x00, 0x90, 0xFF, 0x2D, 0x01, 0xFF, 0xFD, 0x46, 0x02,
+ 0x34, 0xFF, 0x71, 0xFA, 0x6B, 0x3D, 0xE5, 0x1C, 0x90, 0xF3, 0x35,
+ 0x06, 0x55, 0xFD, 0xC6, 0x00, 0xF9, 0xFF, 0xEC, 0xFF, 0x01, 0x00,
+ 0x11, 0x00, 0x8B, 0xFF, 0x51, 0x01, 0x86, 0xFD, 0x68, 0x03, 0xF3,
+ 0xFC, 0xAE, 0xFE, 0x92, 0x40, 0xDA, 0x15, 0xD5, 0xF4, 0x35, 0x06,
+ 0x00, 0xFD, 0x14, 0x01, 0xCE, 0xFF, 0xFA, 0xFF, 0x00, 0x00, 0x0F,
+ 0x00, 0x8D, 0xFF, 0x63, 0x01, 0x28, 0xFD, 0x71, 0x04, 0x9E, 0xFA,
+ 0xC7, 0x03, 0x79, 0x42, 0x0B, 0x0F, 0x97, 0xF6, 0xDA, 0x05, 0xE2,
+ 0xFC, 0x48, 0x01, 0xAD, 0xFF, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x0B, 0x00, 0x9A, 0xFF, 0x5F, 0x01, 0xEF, 0xFC, 0x4F, 0x05, 0x5A,
+ 0xF8, 0x9F, 0x09, 0x0A, 0x43, 0xAE, 0x08, 0xB1, 0xF8, 0x30, 0x05,
+ 0xF5, 0xFC, 0x61, 0x01, 0x97, 0xFF, 0x0C, 0x00, 0x00, 0x00, 0x03,
+ 0x00, 0xB1, 0xFF, 0x41, 0x01, 0xE3, 0xFC, 0xED, 0x05, 0x4C, 0xF6,
+ 0x11, 0x10, 0x42, 0x42, 0xF1, 0x02, 0xFA, 0xFA, 0x4B, 0x04, 0x34,
+ 0xFD, 0x61, 0x01, 0x8C, 0xFF, 0x10, 0x00, 0x01, 0x00, 0xF8, 0xFF,
+ 0xD4, 0xFF, 0x0A, 0x01, 0x0A, 0xFD, 0x3C, 0x06, 0x9A, 0xF4, 0xED,
+ 0x16, 0x2A, 0x40, 0xF8, 0xFD, 0x4D, 0xFD, 0x3C, 0x03, 0x97, 0xFD,
+ 0x4C, 0x01, 0x8B, 0xFF, 0x11, 0x00, 0x02, 0x00, 0xEA, 0xFF, 0x00,
+ 0x00, 0xB8, 0x00, 0x67, 0xFD, 0x2C, 0x06, 0x6B, 0xF3, 0xFC, 0x1D,
+ 0xD3, 0x3C, 0xDF, 0xF9, 0x89, 0xFF, 0x18, 0x02, 0x13, 0xFE, 0x26,
+ 0x01, 0x92, 0xFF, 0x0F, 0x00, 0x04, 0x00, 0xD9, 0xFF, 0x36, 0x00,
+ 0x4E, 0x00, 0xFB, 0xFD, 0xB4, 0x05, 0xE4, 0xF2, 0x04, 0x25, 0x5F,
+ 0x38, 0xB6, 0xF6, 0x90, 0x01, 0xF3, 0x00, 0x9F, 0xFE, 0xF3, 0x00,
+ 0x9F, 0xFF, 0x0D, 0x00, 0x06, 0x00, 0xC6, 0xFF, 0x71, 0x00, 0xD1,
+ 0xFF, 0xC2, 0xFE, 0xD1, 0x04, 0x23, 0xF3, 0xC9, 0x2B, 0xF5, 0x32,
+ 0x83, 0xF4, 0x49, 0x03, 0xDC, 0xFF, 0x30, 0xFF, 0xB8, 0x00, 0xB0,
+ 0xFF, 0x0A, 0x00, 0x09, 0x00, 0xB3, 0xFF, 0xAE, 0x00, 0x46, 0xFF,
+ 0xB4, 0xFF, 0x85, 0x03, 0x42, 0xF4, 0x0E, 0x32, 0xCA, 0x2C, 0x41,
+ 0xF3, 0xA5, 0x04, 0xE4, 0xFE, 0xBC, 0xFF, 0x7A, 0x00, 0xC3, 0xFF,
+ 0x07, 0x00, 0x0D, 0x00, 0xA1, 0xFF, 0xEA, 0x00, 0xB5, 0xFE, 0xC6,
+ 0x00, 0xD9, 0x01, 0x4F, 0xF6, 0x99, 0x37, 0x16, 0x26, 0xE0, 0xF2,
+ 0x98, 0x05, 0x16, 0xFE, 0x3C, 0x00, 0x3F, 0x00, 0xD6, 0xFF, 0x04,
+ 0x00, 0x0F, 0x00, 0x93, 0xFF, 0x1F, 0x01, 0x28, 0xFE, 0xEB, 0x01,
+ 0xDD, 0xFF, 0x52, 0xF9, 0x36, 0x3C, 0x13, 0x1F, 0x4B, 0xF3, 0x20,
+ 0x06, 0x7B, 0xFD, 0xA9, 0x00, 0x08, 0x00, 0xE7, 0xFF, 0x02, 0x00,
+ 0x11, 0x00, 0x8C, 0xFF, 0x47, 0x01, 0xA9, 0xFD, 0x10, 0x03, 0xA8,
+ 0xFD, 0x47, 0xFD, 0xBB, 0x3F, 0x01, 0x18, 0x62, 0xF4, 0x40, 0x06,
+ 0x15, 0xFD, 0xFF, 0x00, 0xDA, 0xFF, 0xF6, 0xFF, 0x01, 0x00, 0x10,
+ 0x00, 0x8B, 0xFF, 0x5F, 0x01, 0x41, 0xFD, 0x23, 0x04, 0x56, 0xFB,
+ 0x1F, 0x02, 0x06, 0x42, 0x19, 0x11, 0x02, 0xF6, 0xFF, 0x05, 0xE5,
+ 0xFC, 0x3B, 0x01, 0xB6, 0xFF, 0x02, 0x00, 0x00, 0x00, 0x0D, 0x00,
+ 0x95, 0xFF, 0x62, 0x01, 0xFC, 0xFC, 0x10, 0x05, 0x09, 0xF9, 0xC1,
+ 0x07, 0x03, 0x43, 0x94, 0x0A, 0x05, 0xF8, 0x6C, 0x05, 0xEA, 0xFC,
+ 0x5C, 0x01, 0x9D, 0xFF, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06,
+ 0x00, 0xA9, 0xFF, 0x4D, 0x01, 0xE1, 0xFC, 0xC4, 0x05, 0xE6, 0xF6,
+ 0x08, 0x0E, 0xA5, 0x42, 0xA1, 0x04, 0x43, 0xFA, 0x97, 0x04, 0x1D,
+ 0xFD, 0x64, 0x01, 0x8F, 0xFF, 0x0F, 0x00, 0x00, 0x00, 0xFC, 0xFF,
+ 0xC8, 0xFF, 0x1E, 0x01, 0xF8, 0xFC, 0x2D, 0x06, 0x13, 0xF5, 0xC8,
+ 0x14, 0xF2, 0x40, 0x69, 0xFF, 0x97, 0xFC, 0x92, 0x03, 0x75, 0xFD,
+ 0x55, 0x01, 0x8A, 0xFF, 0x11, 0x00, 0x01, 0x00, 0xEF, 0xFF, 0xF2,
+ 0xFF, 0xD4, 0x00, 0x45, 0xFD, 0x3B, 0x06, 0xB8, 0xF3, 0xCE, 0x1B,
+ 0xFB, 0x3D, 0x08, 0xFB, 0xDE, 0xFE, 0x73, 0x02, 0xEB, 0xFD, 0x33,
+ 0x01, 0x8F, 0xFF, 0x10, 0x00, 0x03, 0x00, 0xDE, 0xFF, 0x25, 0x00,
+ 0x71, 0x00, 0xC8, 0xFD, 0xE5, 0x05, 0xFA, 0xF2, 0xDF, 0x22, 0xDB,
+ 0x39, 0x94, 0xF7, 0xF7, 0x00, 0x4C, 0x01, 0x73, 0xFE, 0x03, 0x01,
+ 0x9A, 0xFF, 0x0E, 0x00, 0x05, 0x00, 0xCC, 0xFF, 0x5E, 0x00, 0xF9,
+ 0xFF, 0x80, 0xFE, 0x23, 0x05, 0xF9, 0xF2, 0xC0, 0x29, 0xB8, 0x34,
+ 0x16, 0xF5, 0xCB, 0x02, 0x2F, 0x00, 0x03, 0xFF, 0xCA, 0x00, 0xAA,
+ 0xFF, 0x0B, 0x00, 0x08, 0x00, 0xB8, 0xFF, 0x9B, 0x00, 0x72, 0xFF,
+ 0x65, 0xFF, 0xF6, 0x03, 0xD1, 0xF3, 0x31, 0x30, 0xC1, 0x2E, 0x8B,
+ 0xF3, 0x45, 0x04, 0x2D, 0xFF, 0x92, 0xFF, 0x8D, 0x00, 0xBD, 0xFF,
+ 0x08, 0x00, 0x0C, 0x00, 0xA6, 0xFF, 0xD8, 0x00, 0xE2, 0xFE, 0x6F,
+ 0x00, 0x66, 0x02, 0x93, 0xF5, 0xFB, 0x35, 0x31, 0x28, 0xE7, 0xF2,
+ 0x59, 0x05, 0x51, 0xFE, 0x17, 0x00, 0x50, 0x00, 0xD0, 0xFF, 0x05,
+ 0x00, 0x0E, 0x00, 0x97, 0xFF, 0x0F, 0x01, 0x53, 0xFE, 0x90, 0x01,
+ 0x81, 0x00, 0x4B, 0xF8, 0xE6, 0x3A, 0x3F, 0x21, 0x16, 0xF3, 0x02,
+ 0x06, 0xA5, 0xFD, 0x8A, 0x00, 0x18, 0x00, 0xE2, 0xFF, 0x02, 0x00,
+ 0x10, 0x00, 0x8D, 0xFF, 0x3C, 0x01, 0xCE, 0xFD, 0xB7, 0x02, 0x5A,
+ 0xFE, 0xF7, 0xFB, 0xC6, 0x3E, 0x2C, 0x1A, 0xFC, 0xF3, 0x41, 0x06,
+ 0x2E, 0xFD, 0xE7, 0x00, 0xE7, 0xFF, 0xF2, 0xFF, 0x01, 0x00, 0x10,
+ 0x00, 0x8B, 0xFF, 0x5A, 0x01, 0x5E, 0xFD, 0xD2, 0x03, 0x0E, 0xFC,
+ 0x8B, 0x00, 0x75, 0x41, 0x32, 0x13, 0x75, 0xF5, 0x1C, 0x06, 0xEE,
+ 0xFC, 0x2B, 0x01, 0xC0, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x0E, 0x00,
+ 0x91, 0xFF, 0x64, 0x01, 0x0D, 0xFD, 0xCD, 0x04, 0xBB, 0xF9, 0xF2,
+ 0x05, 0xD9, 0x42, 0x88, 0x0C, 0x5E, 0xF7, 0xA1, 0x05, 0xE3, 0xFC,
+ 0x54, 0x01, 0xA3, 0xFF, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09,
+ 0x00, 0xA2, 0xFF, 0x56, 0x01, 0xE5, 0xFC, 0x94, 0x05, 0x87, 0xF7,
+ 0x0A, 0x0C, 0xE6, 0x42, 0x64, 0x06, 0x8E, 0xF9, 0xDE, 0x04, 0x09,
+ 0xFD, 0x64, 0x01, 0x92, 0xFF, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xBD, 0xFF, 0x2F, 0x01, 0xEC, 0xFC, 0x16, 0x06, 0x98, 0xF5, 0xAB,
+ 0x12, 0x9C, 0x41, 0xEE, 0x00, 0xE0, 0xFB, 0xE6, 0x03, 0x57, 0xFD,
+ 0x5B, 0x01, 0x8B, 0xFF, 0x10, 0x00, 0x01, 0x00, 0xF3, 0xFF, 0xE4,
+ 0xFF, 0xED, 0x00, 0x27, 0xFD, 0x41, 0x06, 0x14, 0xF4, 0xA1, 0x19,
+ 0x06, 0x3F, 0x49, 0xFC, 0x2E, 0xFE, 0xCD, 0x02, 0xC4, 0xFD, 0x3F,
+ 0x01, 0x8D, 0xFF, 0x10, 0x00, 0x02, 0x00, 0xE3, 0xFF, 0x14, 0x00,
+ 0x92, 0x00, 0x9A, 0xFD, 0x0A, 0x06, 0x22, 0xF3, 0xB4, 0x20, 0x3C,
+ 0x3B, 0x8B, 0xF8, 0x58, 0x00, 0xA7, 0x01, 0x48, 0xFE, 0x13, 0x01,
+ 0x96, 0xFF, 0x0F, 0x00, 0x04, 0x00, 0xD1, 0xFF, 0x4C, 0x00, 0x20,
+ 0x00, 0x42, 0xFE, 0x6A, 0x05, 0xE3, 0xF2, 0xAB, 0x27, 0x66, 0x36,
+ 0xC0, 0xF5, 0x44, 0x02, 0x85, 0x00, 0xD7, 0xFE, 0xDD, 0x00, 0xA5,
+ 0xFF, 0x0C, 0x00, 0x07, 0x00, 0xBE, 0xFF, 0x89, 0x00, 0x9D, 0xFF,
+ 0x1A, 0xFF, 0x5E, 0x04, 0x76, 0xF3, 0x45, 0x2E, 0xAA, 0x30, 0xEB,
+ 0xF3, 0xDB, 0x03, 0x79, 0xFF, 0x67, 0xFF, 0xA0, 0x00, 0xB7, 0xFF,
+ 0x09, 0x00, 0x0B, 0x00, 0xAC, 0xFF, 0xC6, 0x00, 0x0E, 0xFF, 0x1A,
+ 0x00, 0xEB, 0x02, 0xEF, 0xF4, 0x49, 0x34, 0x43, 0x2A, 0x02, 0xF3,
+ 0x0F, 0x05, 0x90, 0xFE, 0xEF, 0xFF, 0x63, 0x00, 0xCA, 0xFF, 0x06,
+ 0x00, 0x0E, 0x00, 0x9B, 0xFF, 0xFF, 0x00, 0x7E, 0xFE, 0x36, 0x01,
+ 0x1E, 0x01, 0x5B, 0xF7, 0x7E, 0x39, 0x69, 0x23, 0xF3, 0xF2, 0xD9,
+ 0x05, 0xD4, 0xFD, 0x69, 0x00, 0x29, 0x00, 0xDD, 0xFF, 0x03, 0x00,
+ 0x10, 0x00, 0x90, 0xFF, 0x30, 0x01, 0xF5, 0xFD, 0x5C, 0x02, 0x09,
+ 0xFF, 0xBC, 0xFA, 0xB5, 0x3D, 0x5A, 0x1C, 0xA3, 0xF3, 0x38, 0x06,
+ 0x4D, 0xFD, 0xCD, 0x00, 0xF5, 0xFF, 0xED, 0xFF, 0x01, 0x00, 0x11,
+ 0x00, 0x8B, 0xFF, 0x53, 0x01, 0x7E, 0xFD, 0x7D, 0x03, 0xC5, 0xFC,
+ 0x0B, 0xFF, 0xC3, 0x40, 0x51, 0x15, 0xF4, 0xF4, 0x31, 0x06, 0xFC,
+ 0xFC, 0x19, 0x01, 0xCB, 0xFF, 0xFB, 0xFF, 0x00, 0x00, 0x0F, 0x00,
+ 0x8E, 0xFF, 0x63, 0x01, 0x22, 0xFD, 0x84, 0x04, 0x71, 0xFA, 0x34,
+ 0x04, 0x90, 0x42, 0x89, 0x0E, 0xBE, 0xF6, 0xCF, 0x05, 0xE1, 0xFC,
+ 0x4A, 0x01, 0xAB, 0xFF, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0B,
+ 0x00, 0x9B, 0xFF, 0x5D, 0x01, 0xEC, 0xFC, 0x5D, 0x05, 0x2F, 0xF8,
+ 0x19, 0x0A, 0x07, 0x43, 0x37, 0x08, 0xDD, 0xF8, 0x21, 0x05, 0xF8,
+ 0xFC, 0x62, 0x01, 0x96, 0xFF, 0x0C, 0x00, 0x00, 0x00, 0x03, 0x00,
+ 0xB4, 0xFF, 0x3E, 0x01, 0xE4, 0xFC, 0xF6, 0x05, 0x26, 0xF6, 0x95,
+ 0x10, 0x26, 0x42, 0x87, 0x02, 0x28, 0xFB, 0x37, 0x04, 0x3B, 0xFD,
+ 0x60, 0x01, 0x8C, 0xFF, 0x10, 0x00, 0x01, 0x00, 0xF7, 0xFF, 0xD7,
+ 0xFF, 0x04, 0x01, 0x0F, 0xFD, 0x3E, 0x06, 0x7D, 0xF4, 0x76, 0x17,
+ 0xF4, 0x3F, 0x9F, 0xFD, 0x7B, 0xFD, 0x26, 0x03, 0xA0, 0xFD, 0x4A,
+ 0x01, 0x8B, 0xFF, 0x11, 0x00, 0x02, 0x00, 0xE9, 0xFF, 0x04, 0x00,
+ 0xB1, 0x00, 0x71, 0xFD, 0x26, 0x06, 0x5A, 0xF3, 0x88, 0x1E, 0x87,
+ 0x3C, 0x98, 0xF9, 0xB3, 0xFF, 0x02, 0x02, 0x1E, 0xFE, 0x22, 0x01,
+ 0x93, 0xFF, 0x0F, 0x00, 0x04, 0x00, 0xD7, 0xFF, 0x3A, 0x00, 0x45,
+ 0x00, 0x09, 0xFE, 0xA7, 0x05, 0xE1, 0xF2, 0x8D, 0x25, 0xFD, 0x37,
+ 0x82, 0xF6, 0xB5, 0x01, 0xDC, 0x00, 0xAA, 0xFE, 0xEE, 0x00, 0xA0,
+ 0xFF, 0x0D, 0x00, 0x06, 0x00, 0xC4, 0xFF, 0x76, 0x00, 0xC7, 0xFF,
+ 0xD3, 0xFE, 0xBC, 0x04, 0x31, 0xF3, 0x4A, 0x2C, 0x83, 0x32, 0x61,
+ 0xF4, 0x68, 0x03, 0xC8, 0xFF, 0x3B, 0xFF, 0xB3, 0x00, 0xB1, 0xFF,
+ 0x0A, 0x00, 0x0A, 0x00, 0xB1, 0xFF, 0xB3, 0x00, 0x3B, 0xFF, 0xC8,
+ 0xFF, 0x68, 0x03, 0x61, 0xF4, 0x83, 0x32, 0x4A, 0x2C, 0x31, 0xF3,
+ 0xBC, 0x04, 0xD3, 0xFE, 0xC7, 0xFF, 0x76, 0x00, 0xC4, 0xFF, 0x06,
+ 0x00, 0x0D, 0x00, 0xA0, 0xFF, 0xEE, 0x00, 0xAA, 0xFE, 0xDC, 0x00,
+ 0xB5, 0x01, 0x82, 0xF6, 0xFD, 0x37, 0x8D, 0x25, 0xE1, 0xF2, 0xA7,
+ 0x05, 0x09, 0xFE, 0x45, 0x00, 0x3A, 0x00, 0xD7, 0xFF, 0x04, 0x00,
+ 0x0F, 0x00, 0x93, 0xFF, 0x22, 0x01, 0x1E, 0xFE, 0x02, 0x02, 0xB3,
+ 0xFF, 0x98, 0xF9, 0x87, 0x3C, 0x88, 0x1E, 0x5A, 0xF3, 0x26, 0x06,
+ 0x71, 0xFD, 0xB1, 0x00, 0x04, 0x00, 0xE9, 0xFF, 0x02, 0x00, 0x11,
+ 0x00, 0x8B, 0xFF, 0x4A, 0x01, 0xA0, 0xFD, 0x26, 0x03, 0x7B, 0xFD,
+ 0x9F, 0xFD, 0xF4, 0x3F, 0x76, 0x17, 0x7D, 0xF4, 0x3E, 0x06, 0x0F,
+ 0xFD, 0x04, 0x01, 0xD7, 0xFF, 0xF7, 0xFF, 0x01, 0x00, 0x10, 0x00,
+ 0x8C, 0xFF, 0x60, 0x01, 0x3B, 0xFD, 0x37, 0x04, 0x28, 0xFB, 0x87,
+ 0x02, 0x26, 0x42, 0x95, 0x10, 0x26, 0xF6, 0xF6, 0x05, 0xE4, 0xFC,
+ 0x3E, 0x01, 0xB4, 0xFF, 0x03, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x96,
+ 0xFF, 0x62, 0x01, 0xF8, 0xFC, 0x21, 0x05, 0xDD, 0xF8, 0x37, 0x08,
+ 0x07, 0x43, 0x19, 0x0A, 0x2F, 0xF8, 0x5D, 0x05, 0xEC, 0xFC, 0x5D,
+ 0x01, 0x9B, 0xFF, 0x0B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00,
+ 0xAB, 0xFF, 0x4A, 0x01, 0xE1, 0xFC, 0xCF, 0x05, 0xBE, 0xF6, 0x89,
+ 0x0E, 0x90, 0x42, 0x34, 0x04, 0x71, 0xFA, 0x84, 0x04, 0x22, 0xFD,
+ 0x63, 0x01, 0x8E, 0xFF, 0x0F, 0x00, 0x00, 0x00, 0xFB, 0xFF, 0xCB,
+ 0xFF, 0x19, 0x01, 0xFC, 0xFC, 0x31, 0x06, 0xF4, 0xF4, 0x51, 0x15,
+ 0xC3, 0x40, 0x0B, 0xFF, 0xC5, 0xFC, 0x7D, 0x03, 0x7E, 0xFD, 0x53,
+ 0x01, 0x8B, 0xFF, 0x11, 0x00, 0x01, 0x00, 0xED, 0xFF, 0xF5, 0xFF,
+ 0xCD, 0x00, 0x4D, 0xFD, 0x38, 0x06, 0xA3, 0xF3, 0x5A, 0x1C, 0xB5,
+ 0x3D, 0xBC, 0xFA, 0x09, 0xFF, 0x5C, 0x02, 0xF5, 0xFD, 0x30, 0x01,
+ 0x90, 0xFF, 0x10, 0x00, 0x03, 0x00, 0xDD, 0xFF, 0x29, 0x00, 0x69,
+ 0x00, 0xD4, 0xFD, 0xD9, 0x05, 0xF3, 0xF2, 0x69, 0x23, 0x7E, 0x39,
+ 0x5B, 0xF7, 0x1E, 0x01, 0x36, 0x01, 0x7E, 0xFE, 0xFF, 0x00, 0x9B,
+ 0xFF, 0x0E, 0x00, 0x06, 0x00, 0xCA, 0xFF, 0x63, 0x00, 0xEF, 0xFF,
+ 0x90, 0xFE, 0x0F, 0x05, 0x02, 0xF3, 0x43, 0x2A, 0x49, 0x34, 0xEF,
+ 0xF4, 0xEB, 0x02, 0x1A, 0x00, 0x0E, 0xFF, 0xC6, 0x00, 0xAC, 0xFF,
+ 0x0B, 0x00, 0x09, 0x00, 0xB7, 0xFF, 0xA0, 0x00, 0x67, 0xFF, 0x79,
+ 0xFF, 0xDB, 0x03, 0xEB, 0xF3, 0xAA, 0x30, 0x45, 0x2E, 0x76, 0xF3,
+ 0x5E, 0x04, 0x1A, 0xFF, 0x9D, 0xFF, 0x89, 0x00, 0xBE, 0xFF, 0x07,
+ 0x00, 0x0C, 0x00, 0xA5, 0xFF, 0xDD, 0x00, 0xD7, 0xFE, 0x85, 0x00,
+ 0x44, 0x02, 0xC0, 0xF5, 0x66, 0x36, 0xAB, 0x27, 0xE3, 0xF2, 0x6A,
+ 0x05, 0x42, 0xFE, 0x20, 0x00, 0x4C, 0x00, 0xD1, 0xFF, 0x04, 0x00,
+ 0x0F, 0x00, 0x96, 0xFF, 0x13, 0x01, 0x48, 0xFE, 0xA7, 0x01, 0x58,
+ 0x00, 0x8B, 0xF8, 0x3C, 0x3B, 0xB4, 0x20, 0x22, 0xF3, 0x0A, 0x06,
+ 0x9A, 0xFD, 0x92, 0x00, 0x14, 0x00, 0xE3, 0xFF, 0x02, 0x00, 0x10,
+ 0x00, 0x8D, 0xFF, 0x3F, 0x01, 0xC4, 0xFD, 0xCD, 0x02, 0x2E, 0xFE,
+ 0x49, 0xFC, 0x06, 0x3F, 0xA1, 0x19, 0x14, 0xF4, 0x41, 0x06, 0x27,
+ 0xFD, 0xED, 0x00, 0xE4, 0xFF, 0xF3, 0xFF, 0x01, 0x00, 0x10, 0x00,
+ 0x8B, 0xFF, 0x5B, 0x01, 0x57, 0xFD, 0xE6, 0x03, 0xE0, 0xFB, 0xEE,
+ 0x00, 0x9C, 0x41, 0xAB, 0x12, 0x98, 0xF5, 0x16, 0x06, 0xEC, 0xFC,
+ 0x2F, 0x01, 0xBD, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x92,
+ 0xFF, 0x64, 0x01, 0x09, 0xFD, 0xDE, 0x04, 0x8E, 0xF9, 0x64, 0x06,
+ 0xE6, 0x42, 0x0A, 0x0C, 0x87, 0xF7, 0x94, 0x05, 0xE5, 0xFC, 0x56,
+ 0x01, 0xA2, 0xFF, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00,
+ 0xA3, 0xFF, 0x54, 0x01, 0xE3, 0xFC, 0xA1, 0x05, 0x5E, 0xF7, 0x88,
+ 0x0C, 0xD9, 0x42, 0xF2, 0x05, 0xBB, 0xF9, 0xCD, 0x04, 0x0D, 0xFD,
+ 0x64, 0x01, 0x91, 0xFF, 0x0E, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xC0,
+ 0xFF, 0x2B, 0x01, 0xEE, 0xFC, 0x1C, 0x06, 0x75, 0xF5, 0x32, 0x13,
+ 0x75, 0x41, 0x8B, 0x00, 0x0E, 0xFC, 0xD2, 0x03, 0x5E, 0xFD, 0x5A,
+ 0x01, 0x8B, 0xFF, 0x10, 0x00, 0x01, 0x00, 0xF2, 0xFF, 0xE7, 0xFF,
+ 0xE7, 0x00, 0x2E, 0xFD, 0x41, 0x06, 0xFC, 0xF3, 0x2C, 0x1A, 0xC6,
+ 0x3E, 0xF7, 0xFB, 0x5A, 0xFE, 0xB7, 0x02, 0xCE, 0xFD, 0x3C, 0x01,
+ 0x8D, 0xFF, 0x10, 0x00, 0x02, 0x00, 0xE2, 0xFF, 0x18, 0x00, 0x8A,
+ 0x00, 0xA5, 0xFD, 0x02, 0x06, 0x16, 0xF3, 0x3F, 0x21, 0xE6, 0x3A,
+ 0x4B, 0xF8, 0x81, 0x00, 0x90, 0x01, 0x53, 0xFE, 0x0F, 0x01, 0x97,
+ 0xFF, 0x0E, 0x00, 0x05, 0x00, 0xD0, 0xFF, 0x50, 0x00, 0x17, 0x00,
+ 0x51, 0xFE, 0x59, 0x05, 0xE7, 0xF2, 0x31, 0x28, 0xFB, 0x35, 0x93,
+ 0xF5, 0x66, 0x02, 0x6F, 0x00, 0xE2, 0xFE, 0xD8, 0x00, 0xA6, 0xFF,
+ 0x0C, 0x00, 0x08, 0x00, 0xBD, 0xFF, 0x8D, 0x00, 0x92, 0xFF, 0x2D,
+ 0xFF, 0x45, 0x04, 0x8B, 0xF3, 0xC1, 0x2E, 0x31, 0x30, 0xD1, 0xF3,
+ 0xF6, 0x03, 0x65, 0xFF, 0x72, 0xFF, 0x9B, 0x00, 0xB8, 0xFF, 0x08,
+ 0x00, 0x0B, 0x00, 0xAA, 0xFF, 0xCA, 0x00, 0x03, 0xFF, 0x2F, 0x00,
+ 0xCB, 0x02, 0x16, 0xF5, 0xB8, 0x34, 0xC0, 0x29, 0xF9, 0xF2, 0x23,
+ 0x05, 0x80, 0xFE, 0xF9, 0xFF, 0x5E, 0x00, 0xCC, 0xFF, 0x05, 0x00,
+ 0x0E, 0x00, 0x9A, 0xFF, 0x03, 0x01, 0x73, 0xFE, 0x4C, 0x01, 0xF7,
+ 0x00, 0x94, 0xF7, 0xDB, 0x39, 0xDF, 0x22, 0xFA, 0xF2, 0xE5, 0x05,
+ 0xC8, 0xFD, 0x71, 0x00, 0x25, 0x00, 0xDE, 0xFF, 0x03, 0x00, 0x10,
+ 0x00, 0x8F, 0xFF, 0x33, 0x01, 0xEB, 0xFD, 0x73, 0x02, 0xDE, 0xFE,
+ 0x08, 0xFB, 0xFB, 0x3D, 0xCE, 0x1B, 0xB8, 0xF3, 0x3B, 0x06, 0x45,
+ 0xFD, 0xD4, 0x00, 0xF2, 0xFF, 0xEF, 0xFF, 0x01, 0x00, 0x11, 0x00,
+ 0x8A, 0xFF, 0x55, 0x01, 0x75, 0xFD, 0x92, 0x03, 0x97, 0xFC, 0x69,
+ 0xFF, 0xF2, 0x40, 0xC8, 0x14, 0x13, 0xF5, 0x2D, 0x06, 0xF8, 0xFC,
+ 0x1E, 0x01, 0xC8, 0xFF, 0xFC, 0xFF, 0x00, 0x00, 0x0F, 0x00, 0x8F,
+ 0xFF, 0x64, 0x01, 0x1D, 0xFD, 0x97, 0x04, 0x43, 0xFA, 0xA1, 0x04,
+ 0xA5, 0x42, 0x08, 0x0E, 0xE6, 0xF6, 0xC4, 0x05, 0xE1, 0xFC, 0x4D,
+ 0x01, 0xA9, 0xFF, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x00,
+ 0x9D, 0xFF, 0x5C, 0x01, 0xEA, 0xFC, 0x6C, 0x05, 0x05, 0xF8, 0x94,
+ 0x0A, 0x03, 0x43, 0xC1, 0x07, 0x09, 0xF9, 0x10, 0x05, 0xFC, 0xFC,
+ 0x62, 0x01, 0x95, 0xFF, 0x0D, 0x00, 0x00, 0x00, 0x02, 0x00, 0xB6,
+ 0xFF, 0x3B, 0x01, 0xE5, 0xFC, 0xFF, 0x05, 0x02, 0xF6, 0x19, 0x11,
+ 0x06, 0x42, 0x1F, 0x02, 0x56, 0xFB, 0x23, 0x04, 0x41, 0xFD, 0x5F,
+ 0x01, 0x8B, 0xFF, 0x10, 0x00, 0x01, 0x00, 0xF6, 0xFF, 0xDA, 0xFF,
+ 0xFF, 0x00, 0x15, 0xFD, 0x40, 0x06, 0x62, 0xF4, 0x01, 0x18, 0xBB,
+ 0x3F, 0x47, 0xFD, 0xA8, 0xFD, 0x10, 0x03, 0xA9, 0xFD, 0x47, 0x01,
+ 0x8C, 0xFF, 0x11, 0x00, 0x02, 0x00, 0xE7, 0xFF, 0x08, 0x00, 0xA9,
+ 0x00, 0x7B, 0xFD, 0x20, 0x06, 0x4B, 0xF3, 0x13, 0x1F, 0x36, 0x3C,
+ 0x52, 0xF9, 0xDD, 0xFF, 0xEB, 0x01, 0x28, 0xFE, 0x1F, 0x01, 0x93,
+ 0xFF, 0x0F, 0x00, 0x04, 0x00, 0xD6, 0xFF, 0x3F, 0x00, 0x3C, 0x00,
+ 0x16, 0xFE, 0x98, 0x05, 0xE0, 0xF2, 0x16, 0x26, 0x99, 0x37, 0x4F,
+ 0xF6, 0xD9, 0x01, 0xC6, 0x00, 0xB5, 0xFE, 0xEA, 0x00, 0xA1, 0xFF,
+ 0x0D, 0x00, 0x07, 0x00, 0xC3, 0xFF, 0x7A, 0x00, 0xBC, 0xFF, 0xE4,
+ 0xFE, 0xA5, 0x04, 0x41, 0xF3, 0xCA, 0x2C, 0x0E, 0x32, 0x42, 0xF4,
+ 0x85, 0x03, 0xB4, 0xFF, 0x46, 0xFF, 0xAE, 0x00, 0xB3, 0xFF, 0x09,
+ 0x00, 0x0A, 0x00, 0xB0, 0xFF, 0xB8, 0x00, 0x30, 0xFF, 0xDC, 0xFF,
+ 0x49, 0x03, 0x83, 0xF4, 0xF5, 0x32, 0xC9, 0x2B, 0x23, 0xF3, 0xD1,
+ 0x04, 0xC2, 0xFE, 0xD1, 0xFF, 0x71, 0x00, 0xC6, 0xFF, 0x06, 0x00,
+ 0x0D, 0x00, 0x9F, 0xFF, 0xF3, 0x00, 0x9F, 0xFE, 0xF3, 0x00, 0x90,
+ 0x01, 0xB6, 0xF6, 0x5F, 0x38, 0x04, 0x25, 0xE4, 0xF2, 0xB4, 0x05,
+ 0xFB, 0xFD, 0x4E, 0x00, 0x36, 0x00, 0xD9, 0xFF, 0x04, 0x00, 0x0F,
+ 0x00, 0x92, 0xFF, 0x26, 0x01, 0x13, 0xFE, 0x18, 0x02, 0x89, 0xFF,
+ 0xDF, 0xF9, 0xD3, 0x3C, 0xFC, 0x1D, 0x6B, 0xF3, 0x2C, 0x06, 0x67,
+ 0xFD, 0xB8, 0x00, 0x00, 0x00, 0xEA, 0xFF, 0x02, 0x00, 0x11, 0x00,
+ 0x8B, 0xFF, 0x4C, 0x01, 0x97, 0xFD, 0x3C, 0x03, 0x4D, 0xFD, 0xF8,
+ 0xFD, 0x2A, 0x40, 0xED, 0x16, 0x9A, 0xF4, 0x3C, 0x06, 0x0A, 0xFD,
+ 0x0A, 0x01, 0xD4, 0xFF, 0xF8, 0xFF, 0x01, 0x00, 0x10, 0x00, 0x8C,
+ 0xFF, 0x61, 0x01, 0x34, 0xFD, 0x4B, 0x04, 0xFA, 0xFA, 0xF1, 0x02,
+ 0x42, 0x42, 0x11, 0x10, 0x4C, 0xF6, 0xED, 0x05, 0xE3, 0xFC, 0x41,
+ 0x01, 0xB1, 0xFF, 0x03, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x97, 0xFF,
+ 0x61, 0x01, 0xF5, 0xFC, 0x30, 0x05, 0xB1, 0xF8, 0xAE, 0x08, 0x0A,
+ 0x43, 0x9F, 0x09, 0x5A, 0xF8, 0x4F, 0x05, 0xEF, 0xFC, 0x5F, 0x01,
+ 0x9A, 0xFF, 0x0B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0xAD,
+ 0xFF, 0x48, 0x01, 0xE2, 0xFC, 0xDA, 0x05, 0x97, 0xF6, 0x0B, 0x0F,
+ 0x79, 0x42, 0xC7, 0x03, 0x9E, 0xFA, 0x71, 0x04, 0x28, 0xFD, 0x63,
+ 0x01, 0x8D, 0xFF, 0x0F, 0x00
};
static u_int16_t
coefficientSizes[] = {
-/* Playback */
-0x00C0, 0x5000, 0x0060, 0x2800, 0x0040, 0x0060, 0x1400, 0x0000,
-/* Record */
-0x0020, 0x1260, 0x0020, 0x1260, 0x0000, 0x0040, 0x1260, 0x0000,
+ /* Playback */
+ 0x00C0, 0x5000, 0x0060, 0x2800, 0x0040, 0x0060, 0x1400, 0x0000,
+ /* Record */
+ 0x0020, 0x1260, 0x0020, 0x1260, 0x0000, 0x0040, 0x1260, 0x0000,
};
Index: aureal.c
===================================================================
RCS file: /home/cvs/src/sys/dev/sound/pci/aureal.c,v
retrieving revision 1.2
retrieving revision 1.3
diff -L sys/dev/sound/pci/aureal.c -L sys/dev/sound/pci/aureal.c -u -r1.2 -r1.3
--- sys/dev/sound/pci/aureal.c
+++ sys/dev/sound/pci/aureal.c
@@ -1,28 +1,28 @@
/*-
-* Copyright (c) 1999 Cameron Grant <cg at freebsd.org>
-* All rights reserved.
-*
-* Redistribution and use in source and binary forms, with or without
-* modification, are permitted provided that the following conditions
-* are met:
-* 1. Redistributions of source code must retain the above copyright
-* notice, this list of conditions and the following disclaimer.
-* 2. Redistributions in binary form must reproduce the above copyright
-* notice, this list of conditions and the following disclaimer in the
-* documentation and/or other materials provided with the distribution.
-*
-* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
-* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
-* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
-* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
-* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
-* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
-* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
-* SUCH DAMAGE.
-*/
+ * Copyright (c) 1999 Cameron Grant <cg at freebsd.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
#include <dev/sound/pcm/sound.h>
#include <dev/sound/pcm/ac97.h>
@@ -31,27 +31,27 @@
#include <dev/pci/pcireg.h>
#include <dev/pci/pcivar.h>
-SND_DECLARE_FILE("$MidnightBSD$");
+SND_DECLARE_FILE("$FreeBSD: src/sys/dev/sound/pci/aureal.c,v 1.36 2007/06/17 06:10:41 ariff Exp $");
/* PCI IDs of supported chips */
#define AU8820_PCI_ID 0x000112eb
/* channel interface */
static u_int32_t au_playfmt[] = {
-AFMT_U8,
-AFMT_STEREO | AFMT_U8,
-AFMT_S16_LE,
-AFMT_STEREO | AFMT_S16_LE,
-0
+ AFMT_U8,
+ AFMT_STEREO | AFMT_U8,
+ AFMT_S16_LE,
+ AFMT_STEREO | AFMT_S16_LE,
+ 0
};
static struct pcmchan_caps au_playcaps = {4000, 48000, au_playfmt, 0};
static u_int32_t au_recfmt[] = {
-AFMT_U8,
-AFMT_STEREO | AFMT_U8,
-AFMT_S16_LE,
-AFMT_STEREO | AFMT_S16_LE,
-0
+ AFMT_U8,
+ AFMT_STEREO | AFMT_U8,
+ AFMT_S16_LE,
+ AFMT_STEREO | AFMT_S16_LE,
+ 0
};
static struct pcmchan_caps au_reccaps = {4000, 48000, au_recfmt, 0};
@@ -60,25 +60,25 @@
struct au_info;
struct au_chinfo {
-struct au_info *parent;
-struct pcm_channel *channel;
-struct snd_dbuf *buffer;
-int dir;
+ struct au_info *parent;
+ struct pcm_channel *channel;
+ struct snd_dbuf *buffer;
+ int dir;
};
struct au_info {
-int unit;
+ int unit;
-bus_space_tag_t st[3];
-bus_space_handle_t sh[3];
+ bus_space_tag_t st[3];
+ bus_space_handle_t sh[3];
-bus_dma_tag_t parent_dmat;
-struct mtx *lock;
+ bus_dma_tag_t parent_dmat;
+ struct mtx *lock;
-u_int32_t x[32], y[128];
-char z[128];
-u_int32_t routes[4], interrupts;
-struct au_chinfo pch;
+ u_int32_t x[32], y[128];
+ char z[128];
+ u_int32_t routes[4], interrupts;
+ struct au_chinfo pch;
};
static int au_init(device_t dev, struct au_info *au);
@@ -89,32 +89,32 @@
static u_int32_t
au_rd(struct au_info *au, int mapno, int regno, int size)
{
-switch(size) {
-case 1:
-return bus_space_read_1(au->st[mapno], au->sh[mapno], regno);
-case 2:
-return bus_space_read_2(au->st[mapno], au->sh[mapno], regno);
-case 4:
-return bus_space_read_4(au->st[mapno], au->sh[mapno], regno);
-default:
-return 0xffffffff;
-}
+ switch(size) {
+ case 1:
+ return bus_space_read_1(au->st[mapno], au->sh[mapno], regno);
+ case 2:
+ return bus_space_read_2(au->st[mapno], au->sh[mapno], regno);
+ case 4:
+ return bus_space_read_4(au->st[mapno], au->sh[mapno], regno);
+ default:
+ return 0xffffffff;
+ }
}
static void
au_wr(struct au_info *au, int mapno, int regno, u_int32_t data, int size)
{
-switch(size) {
-case 1:
-bus_space_write_1(au->st[mapno], au->sh[mapno], regno, data);
-break;
-case 2:
-bus_space_write_2(au->st[mapno], au->sh[mapno], regno, data);
-break;
-case 4:
-bus_space_write_4(au->st[mapno], au->sh[mapno], regno, data);
-break;
-}
+ switch(size) {
+ case 1:
+ bus_space_write_1(au->st[mapno], au->sh[mapno], regno, data);
+ break;
+ case 2:
+ bus_space_write_2(au->st[mapno], au->sh[mapno], regno, data);
+ break;
+ case 4:
+ bus_space_write_4(au->st[mapno], au->sh[mapno], regno, data);
+ break;
+ }
}
/* -------------------------------------------------------------------- */
@@ -122,52 +122,52 @@
static int
au_rdcd(kobj_t obj, void *arg, int regno)
{
-struct au_info *au = (struct au_info *)arg;
-int i=0, j=0;
+ struct au_info *au = (struct au_info *)arg;
+ int i=0, j=0;
-regno<<=16;
-au_wr(au, 0, AU_REG_CODECIO, regno, 4);
-while (j<50) {
-i=au_rd(au, 0, AU_REG_CODECIO, 4);
-if ((i & 0x00ff0000) == (regno | 0x00800000)) break;
-DELAY(j * 200 + 2000);
-j++;
-}
-if (j==50) printf("pcm%d: codec timeout reading register %x (%x)n",
-au->unit, (regno & AU_CDC_REGMASK)>>16, i);
-return i & AU_CDC_DATAMASK;
+ regno<<=16;
+ au_wr(au, 0, AU_REG_CODECIO, regno, 4);
+ while (j<50) {
+ i=au_rd(au, 0, AU_REG_CODECIO, 4);
+ if ((i & 0x00ff0000) == (regno | 0x00800000)) break;
+ DELAY(j * 200 + 2000);
+ j++;
+ }
+ if (j==50) printf("pcm%d: codec timeout reading register %x (%x)\n",
+ au->unit, (regno & AU_CDC_REGMASK)>>16, i);
+ return i & AU_CDC_DATAMASK;
}
static int
au_wrcd(kobj_t obj, void *arg, int regno, u_int32_t data)
{
-struct au_info *au = (struct au_info *)arg;
-int i, j, tries;
-i=j=tries=0;
-do {
-while (j<50 && (i & AU_CDC_WROK) == 0) {
-i=au_rd(au, 0, AU_REG_CODECST, 4);
-DELAY(2000);
-j++;
-}
-if (j==50) printf("codec timeout during write of register %x, data %xn",
-regno, data);
-au_wr(au, 0, AU_REG_CODECIO, (regno<<16) | AU_CDC_REGSET | data, 4);
+ struct au_info *au = (struct au_info *)arg;
+ int i, j, tries;
+ i=j=tries=0;
+ do {
+ while (j<50 && (i & AU_CDC_WROK) == 0) {
+ i=au_rd(au, 0, AU_REG_CODECST, 4);
+ DELAY(2000);
+ j++;
+ }
+ if (j==50) printf("codec timeout during write of register %x, data %x\n",
+ regno, data);
+ au_wr(au, 0, AU_REG_CODECIO, (regno<<16) | AU_CDC_REGSET | data, 4);
/* DELAY(20000);
-i=au_rdcd(au, regno);
+ i=au_rdcd(au, regno);
*/ tries++;
-} while (0); /* (i != data && tries < 3); */
-/*
-if (tries == 3) printf("giving up writing 0x%4x to codec reg %2xn", data, regno);
-*/
+ } while (0); /* (i != data && tries < 3); */
+ /*
+ if (tries == 3) printf("giving up writing 0x%4x to codec reg %2x\n", data, regno);
+ */
-return 0;
+ return 0;
}
static kobj_method_t au_ac97_methods[] = {
-KOBJMETHOD(ac97_read, au_rdcd),
-KOBJMETHOD(ac97_write, au_wrcd),
-{ 0, 0 }
+ KOBJMETHOD(ac97_read, au_rdcd),
+ KOBJMETHOD(ac97_write, au_wrcd),
+ { 0, 0 }
};
AC97_DECLARE(au_ac97);
@@ -176,119 +176,119 @@
static void
au_setbit(u_int32_t *p, char bit, u_int32_t value)
{
-p += bit >> 5;
-bit &= 0x1f;
-*p &= ~ (1 << bit);
-*p |= (value << bit);
+ p += bit >> 5;
+ bit &= 0x1f;
+ *p &= ~ (1 << bit);
+ *p |= (value << bit);
}
static void
au_addroute(struct au_info *au, int a, int b, int route)
{
-int j = 0x1099c+(a<<2);
-if (au->x[a] != a+0x67) j = AU_REG_RTBASE+(au->x[a]<<2);
+ int j = 0x1099c+(a<<2);
+ if (au->x[a] != a+0x67) j = AU_REG_RTBASE+(au->x[a]<<2);
-au_wr(au, 0, AU_REG_RTBASE+(route<<2), 0xffffffff, 4);
-au_wr(au, 0, j, route | (b<<7), 4);
-au->y[route]=au->x[a];
-au->x[a]=route;
-au->z[route]=a & 0x000000ff;
-au_setbit(au->routes, route, 1);
+ au_wr(au, 0, AU_REG_RTBASE+(route<<2), 0xffffffff, 4);
+ au_wr(au, 0, j, route | (b<<7), 4);
+ au->y[route]=au->x[a];
+ au->x[a]=route;
+ au->z[route]=a & 0x000000ff;
+ au_setbit(au->routes, route, 1);
}
static void
au_delroute(struct au_info *au, int route)
{
-int i;
-int j=au->z[route];
+ int i;
+ int j=au->z[route];
-au_setbit(au->routes, route, 0);
-au->z[route]=0x1f;
-i=au_rd(au, 0, AU_REG_RTBASE+(route<<2), 4);
-au_wr(au, 0, AU_REG_RTBASE+(au->y[route]<<2), i, 4);
-au->y[i & 0x7f]=au->y[route];
-au_wr(au, 0, AU_REG_RTBASE+(route<<2), 0xfffffffe, 4);
-if (au->x[j] == route) au->x[j]=au->y[route];
-au->y[route]=0x7f;
+ au_setbit(au->routes, route, 0);
+ au->z[route]=0x1f;
+ i=au_rd(au, 0, AU_REG_RTBASE+(route<<2), 4);
+ au_wr(au, 0, AU_REG_RTBASE+(au->y[route]<<2), i, 4);
+ au->y[i & 0x7f]=au->y[route];
+ au_wr(au, 0, AU_REG_RTBASE+(route<<2), 0xfffffffe, 4);
+ if (au->x[j] == route) au->x[j]=au->y[route];
+ au->y[route]=0x7f;
}
static void
au_encodec(struct au_info *au, char channel)
{
-au_wr(au, 0, AU_REG_CODECEN,
-au_rd(au, 0, AU_REG_CODECEN, 4) | (1 << (channel + 8)), 4);
+ au_wr(au, 0, AU_REG_CODECEN,
+ au_rd(au, 0, AU_REG_CODECEN, 4) | (1 << (channel + 8)), 4);
}
static void
au_clrfifo(struct au_info *au, u_int32_t c)
{
-u_int32_t i;
+ u_int32_t i;
-for (i=0; i<32; i++) au_wr(au, 0, AU_REG_FIFOBASE+(c<<7)+(i<<2), 0, 4);
+ for (i=0; i<32; i++) au_wr(au, 0, AU_REG_FIFOBASE+(c<<7)+(i<<2), 0, 4);
}
static void
au_setadb(struct au_info *au, u_int32_t c, u_int32_t enable)
{
-int x;
+ int x;
-x = au_rd(au, 0, AU_REG_ADB, 4);
-x &= ~(1 << c);
-x |= (enable << c);
-au_wr(au, 0, AU_REG_ADB, x, 4);
+ x = au_rd(au, 0, AU_REG_ADB, 4);
+ x &= ~(1 << c);
+ x |= (enable << c);
+ au_wr(au, 0, AU_REG_ADB, x, 4);
}
static void
au_prepareoutput(struct au_chinfo *ch, u_int32_t format)
{
-struct au_info *au = ch->parent;
-int i, stereo = (format & AFMT_STEREO)? 1 : 0;
-u_int32_t baseaddr = sndbuf_getbufaddr(ch->buffer);
-
-au_wr(au, 0, 0x1061c, 0, 4);
-au_wr(au, 0, 0x10620, 0, 4);
-au_wr(au, 0, 0x10624, 0, 4);
-switch(format & ~AFMT_STEREO) {
-case 1:
-i=0xb000;
-break;
-case 2:
-i=0xf000;
-break;
-case 8:
-i=0x7000;
-break;
-case 16:
-i=0x23000;
-break;
-default:
-i=0x3000;
-}
-au_wr(au, 0, 0x10200, baseaddr, 4);
-au_wr(au, 0, 0x10204, baseaddr+0x1000, 4);
-au_wr(au, 0, 0x10208, baseaddr+0x2000, 4);
-au_wr(au, 0, 0x1020c, baseaddr+0x3000, 4);
-
-au_wr(au, 0, 0x10400, 0xdeffffff, 4);
-au_wr(au, 0, 0x10404, 0xfcffffff, 4);
-
-au_wr(au, 0, 0x10580, i, 4);
-
-au_wr(au, 0, 0x10210, baseaddr, 4);
-au_wr(au, 0, 0x10214, baseaddr+0x1000, 4);
-au_wr(au, 0, 0x10218, baseaddr+0x2000, 4);
-au_wr(au, 0, 0x1021c, baseaddr+0x3000, 4);
-
-au_wr(au, 0, 0x10408, 0x00fff000 | 0x56000000 | 0x00000fff, 4);
-au_wr(au, 0, 0x1040c, 0x00fff000 | 0x74000000 | 0x00000fff, 4);
+ struct au_info *au = ch->parent;
+ int i, stereo = (format & AFMT_STEREO)? 1 : 0;
+ u_int32_t baseaddr = sndbuf_getbufaddr(ch->buffer);
+
+ au_wr(au, 0, 0x1061c, 0, 4);
+ au_wr(au, 0, 0x10620, 0, 4);
+ au_wr(au, 0, 0x10624, 0, 4);
+ switch(format & ~AFMT_STEREO) {
+ case 1:
+ i=0xb000;
+ break;
+ case 2:
+ i=0xf000;
+ break;
+ case 8:
+ i=0x7000;
+ break;
+ case 16:
+ i=0x23000;
+ break;
+ default:
+ i=0x3000;
+ }
+ au_wr(au, 0, 0x10200, baseaddr, 4);
+ au_wr(au, 0, 0x10204, baseaddr+0x1000, 4);
+ au_wr(au, 0, 0x10208, baseaddr+0x2000, 4);
+ au_wr(au, 0, 0x1020c, baseaddr+0x3000, 4);
+
+ au_wr(au, 0, 0x10400, 0xdeffffff, 4);
+ au_wr(au, 0, 0x10404, 0xfcffffff, 4);
+
+ au_wr(au, 0, 0x10580, i, 4);
+
+ au_wr(au, 0, 0x10210, baseaddr, 4);
+ au_wr(au, 0, 0x10214, baseaddr+0x1000, 4);
+ au_wr(au, 0, 0x10218, baseaddr+0x2000, 4);
+ au_wr(au, 0, 0x1021c, baseaddr+0x3000, 4);
+
+ au_wr(au, 0, 0x10408, 0x00fff000 | 0x56000000 | 0x00000fff, 4);
+ au_wr(au, 0, 0x1040c, 0x00fff000 | 0x74000000 | 0x00000fff, 4);
-au_wr(au, 0, 0x10584, i, 4);
+ au_wr(au, 0, 0x10584, i, 4);
-au_wr(au, 0, 0x0f800, stereo? 0x00030032 : 0x00030030, 4);
-au_wr(au, 0, 0x0f804, stereo? 0x00030032 : 0x00030030, 4);
+ au_wr(au, 0, 0x0f800, stereo? 0x00030032 : 0x00030030, 4);
+ au_wr(au, 0, 0x0f804, stereo? 0x00030032 : 0x00030030, 4);
-au_addroute(au, 0x11, 0, 0x58);
-au_addroute(au, 0x11, stereo? 0 : 1, 0x59);
+ au_addroute(au, 0x11, 0, 0x58);
+ au_addroute(au, 0x11, stereo? 0 : 1, 0x59);
}
/* -------------------------------------------------------------------- */
@@ -296,93 +296,93 @@
static void *
auchan_init(kobj_t obj, void *devinfo, struct snd_dbuf *b, struct pcm_channel *c, int dir)
{
-struct au_info *au = devinfo;
-struct au_chinfo *ch = (dir == PCMDIR_PLAY)? &au->pch : NULL;
+ struct au_info *au = devinfo;
+ struct au_chinfo *ch = (dir == PCMDIR_PLAY)? &au->pch : NULL;
-ch->parent = au;
-ch->channel = c;
-ch->buffer = b;
-ch->dir = dir;
-if (sndbuf_alloc(ch->buffer, au->parent_dmat, AU_BUFFSIZE) != 0)
-return NULL;
-return ch;
+ ch->parent = au;
+ ch->channel = c;
+ ch->buffer = b;
+ ch->dir = dir;
+ if (sndbuf_alloc(ch->buffer, au->parent_dmat, 0, AU_BUFFSIZE) != 0)
+ return NULL;
+ return ch;
}
static int
auchan_setformat(kobj_t obj, void *data, u_int32_t format)
{
-struct au_chinfo *ch = data;
+ struct au_chinfo *ch = data;
-if (ch->dir == PCMDIR_PLAY) au_prepareoutput(ch, format);
-return 0;
+ if (ch->dir == PCMDIR_PLAY) au_prepareoutput(ch, format);
+ return 0;
}
static int
auchan_setspeed(kobj_t obj, void *data, u_int32_t speed)
{
-struct au_chinfo *ch = data;
-if (ch->dir == PCMDIR_PLAY) {
-} else {
-}
-return speed;
+ struct au_chinfo *ch = data;
+ if (ch->dir == PCMDIR_PLAY) {
+ } else {
+ }
+ return speed;
}
static int
auchan_setblocksize(kobj_t obj, void *data, u_int32_t blocksize)
{
-return blocksize;
+ return blocksize;
}
static int
auchan_trigger(kobj_t obj, void *data, int go)
{
-struct au_chinfo *ch = data;
-struct au_info *au = ch->parent;
+ struct au_chinfo *ch = data;
+ struct au_info *au = ch->parent;
-if (go == PCMTRIG_EMLDMAWR || go == PCMTRIG_EMLDMARD)
-return 0;
+ if (!PCMTRIG_COMMON(go))
+ return 0;
-if (ch->dir == PCMDIR_PLAY) {
-au_setadb(au, 0x11, (go)? 1 : 0);
-if (!go) {
-au_wr(au, 0, 0xf800, 0, 4);
-au_wr(au, 0, 0xf804, 0, 4);
-au_delroute(au, 0x58);
-au_delroute(au, 0x59);
-}
-} else {
-}
-return 0;
+ if (ch->dir == PCMDIR_PLAY) {
+ au_setadb(au, 0x11, (go)? 1 : 0);
+ if (go != PCMTRIG_START) {
+ au_wr(au, 0, 0xf800, 0, 4);
+ au_wr(au, 0, 0xf804, 0, 4);
+ au_delroute(au, 0x58);
+ au_delroute(au, 0x59);
+ }
+ } else {
+ }
+ return 0;
}
static int
auchan_getptr(kobj_t obj, void *data)
{
-struct au_chinfo *ch = data;
-struct au_info *au = ch->parent;
-if (ch->dir == PCMDIR_PLAY) {
-return au_rd(au, 0, AU_REG_UNK2, 4) & (AU_BUFFSIZE-1);
-} else {
-return 0;
-}
+ struct au_chinfo *ch = data;
+ struct au_info *au = ch->parent;
+ if (ch->dir == PCMDIR_PLAY) {
+ return au_rd(au, 0, AU_REG_UNK2, 4) & (AU_BUFFSIZE-1);
+ } else {
+ return 0;
+ }
}
static struct pcmchan_caps *
auchan_getcaps(kobj_t obj, void *data)
{
-struct au_chinfo *ch = data;
-return (ch->dir == PCMDIR_PLAY)? &au_playcaps : &au_reccaps;
+ struct au_chinfo *ch = data;
+ return (ch->dir == PCMDIR_PLAY)? &au_playcaps : &au_reccaps;
}
static kobj_method_t auchan_methods[] = {
-KOBJMETHOD(channel_init, auchan_init),
-KOBJMETHOD(channel_setformat, auchan_setformat),
-KOBJMETHOD(channel_setspeed, auchan_setspeed),
-KOBJMETHOD(channel_setblocksize, auchan_setblocksize),
-KOBJMETHOD(channel_trigger, auchan_trigger),
-KOBJMETHOD(channel_getptr, auchan_getptr),
-KOBJMETHOD(channel_getcaps, auchan_getcaps),
-{ 0, 0 }
+ KOBJMETHOD(channel_init, auchan_init),
+ KOBJMETHOD(channel_setformat, auchan_setformat),
+ KOBJMETHOD(channel_setspeed, auchan_setspeed),
+ KOBJMETHOD(channel_setblocksize, auchan_setblocksize),
+ KOBJMETHOD(channel_trigger, auchan_trigger),
+ KOBJMETHOD(channel_getptr, auchan_getptr),
+ KOBJMETHOD(channel_getcaps, auchan_getcaps),
+ { 0, 0 }
};
CHANNEL_DECLARE(auchan);
@@ -391,41 +391,41 @@
static void
au_intr (void *p)
{
-struct au_info *au = p;
-u_int32_t intsrc, i;
+ struct au_info *au = p;
+ u_int32_t intsrc, i;
-au->interrupts++;
-intsrc=au_rd(au, 0, AU_REG_IRQSRC, 4);
-printf("pcm%d: interrupt with src %xn", au->unit, intsrc);
-if (intsrc & AU_IRQ_FATAL) printf("pcm%d: fatal error irqn", au->unit);
-if (intsrc & AU_IRQ_PARITY) printf("pcm%d: parity error irqn", au->unit);
-if (intsrc & AU_IRQ_UNKNOWN) {
-(void)au_rd(au, 0, AU_REG_UNK1, 4);
-au_wr(au, 0, AU_REG_UNK1, 0, 4);
-au_wr(au, 0, AU_REG_UNK1, 0x10000, 4);
-}
-if (intsrc & AU_IRQ_PCMOUT) {
-i=au_rd(au, 0, AU_REG_UNK2, 4) & (AU_BUFFSIZE-1);
-chn_intr(au->pch.channel);
-(void)au_rd(au, 0, AU_REG_UNK3, 4);
-(void)au_rd(au, 0, AU_REG_UNK4, 4);
-(void)au_rd(au, 0, AU_REG_UNK5, 4);
-}
+ au->interrupts++;
+ intsrc=au_rd(au, 0, AU_REG_IRQSRC, 4);
+ printf("pcm%d: interrupt with src %x\n", au->unit, intsrc);
+ if (intsrc & AU_IRQ_FATAL) printf("pcm%d: fatal error irq\n", au->unit);
+ if (intsrc & AU_IRQ_PARITY) printf("pcm%d: parity error irq\n", au->unit);
+ if (intsrc & AU_IRQ_UNKNOWN) {
+ (void)au_rd(au, 0, AU_REG_UNK1, 4);
+ au_wr(au, 0, AU_REG_UNK1, 0, 4);
+ au_wr(au, 0, AU_REG_UNK1, 0x10000, 4);
+ }
+ if (intsrc & AU_IRQ_PCMOUT) {
+ i=au_rd(au, 0, AU_REG_UNK2, 4) & (AU_BUFFSIZE-1);
+ chn_intr(au->pch.channel);
+ (void)au_rd(au, 0, AU_REG_UNK3, 4);
+ (void)au_rd(au, 0, AU_REG_UNK4, 4);
+ (void)au_rd(au, 0, AU_REG_UNK5, 4);
+ }
/* don't support midi
-if (intsrc & AU_IRQ_MIDI) {
-i=au_rd(au, 0, 0x11004, 4);
-j=10;
-while (i & 0xff) {
-if (j-- <= 0) break;
-i=au_rd(au, 0, 0x11000, 4);
-if ((au->midi_stat & 1) && (au->midi_out))
-au->midi_out(au->midi_devno, i);
-i=au_rd(au, 0, 0x11004);
-}
-}
+ if (intsrc & AU_IRQ_MIDI) {
+ i=au_rd(au, 0, 0x11004, 4);
+ j=10;
+ while (i & 0xff) {
+ if (j-- <= 0) break;
+ i=au_rd(au, 0, 0x11000, 4);
+ if ((au->midi_stat & 1) && (au->midi_out))
+ au->midi_out(au->midi_devno, i);
+ i=au_rd(au, 0, 0x11004);
+ }
+ }
*/
-au_wr(au, 0, AU_REG_IRQSRC, intsrc & 0x7ff, 4);
-au_rd(au, 0, AU_REG_IRQSRC, 4);
+ au_wr(au, 0, AU_REG_IRQSRC, intsrc & 0x7ff, 4);
+ au_rd(au, 0, AU_REG_IRQSRC, 4);
}
@@ -436,250 +436,247 @@
static int
au_init(device_t dev, struct au_info *au)
{
-u_int32_t i, j;
-
-au_wr(au, 0, AU_REG_IRQGLOB, 0xffffffff, 4);
-DELAY(100000);
+ u_int32_t i, j;
-/* init codec */
-/* cold reset */
-for (i=0; i<32; i++) {
-au_wr(au, 0, AU_REG_CODECCHN+(i<<2), 0, 4);
-DELAY(10000);
-}
-if (1) {
-au_wr(au, 0, AU_REG_CODECST, 0x8068, 4);
-DELAY(10000);
-au_wr(au, 0, AU_REG_CODECST, 0x00e8, 4);
-DELAY(10000);
-} else {
-au_wr(au, 0, AU_REG_CODECST, 0x00a8, 4);
-DELAY(100000);
-au_wr(au, 0, AU_REG_CODECST, 0x80a8, 4);
-DELAY(100000);
-au_wr(au, 0, AU_REG_CODECST, 0x80e8, 4);
-DELAY(100000);
-au_wr(au, 0, AU_REG_CODECST, 0x80a8, 4);
-DELAY(100000);
-au_wr(au, 0, AU_REG_CODECST, 0x00a8, 4);
-DELAY(100000);
-au_wr(au, 0, AU_REG_CODECST, 0x00e8, 4);
-DELAY(100000);
-}
-
-/* init */
-for (i=0; i<32; i++) {
-au_wr(au, 0, AU_REG_CODECCHN+(i<<2), 0, 4);
-DELAY(10000);
-}
-au_wr(au, 0, AU_REG_CODECST, 0xe8, 4);
-DELAY(10000);
-au_wr(au, 0, AU_REG_CODECEN, 0, 4);
-
-/* setup codec */
-i=j=0;
-while (j<100 && (i & AU_CDC_READY)==0) {
-i=au_rd(au, 0, AU_REG_CODECST, 4);
-DELAY(1000);
-j++;
-}
-if (j==100) device_printf(dev, "codec not ready, status 0x%xn", i);
-
-/* init adb */
-/*au->x5c=0;*/
-for (i=0; i<32; i++) au->x[i]=i+0x67;
-for (i=0; i<128; i++) au->y[i]=0x7f;
-for (i=0; i<128; i++) au->z[i]=0x1f;
-au_wr(au, 0, AU_REG_ADB, 0, 4);
-for (i=0; i<124; i++) au_wr(au, 0, AU_REG_RTBASE+(i<<2), 0xffffffff, 4);
-
-/* test */
-i=au_rd(au, 0, 0x107c0, 4);
-if (i!=0xdeadbeef) device_printf(dev, "dma check failed: 0x%xn", i);
-
-/* install mixer */
-au_wr(au, 0, AU_REG_IRQGLOB,
-au_rd(au, 0, AU_REG_IRQGLOB, 4) | AU_IRQ_ENABLE, 4);
-/* braindead but it's what the oss/linux driver does
-* for (i=0; i<0x80000000; i++) au_wr(au, 0, i<<2, 0, 4);
-*/
-au->routes[0]=au->routes[1]=au->routes[2]=au->routes[3]=0;
-/*au->x1e4=0;*/
+ au_wr(au, 0, AU_REG_IRQGLOB, 0xffffffff, 4);
+ DELAY(100000);
-/* attach channel */
-au_addroute(au, 0x11, 0x48, 0x02);
-au_addroute(au, 0x11, 0x49, 0x03);
-au_encodec(au, 0);
-au_encodec(au, 1);
-
-for (i=0; i<48; i++) au_wr(au, 0, 0xf800+(i<<2), 0x20, 4);
-for (i=2; i<6; i++) au_wr(au, 0, 0xf800+(i<<2), 0, 4);
-au_wr(au, 0, 0xf8c0, 0x0843, 4);
-for (i=0; i<4; i++) au_clrfifo(au, i);
+ /* init codec */
+ /* cold reset */
+ for (i=0; i<32; i++) {
+ au_wr(au, 0, AU_REG_CODECCHN+(i<<2), 0, 4);
+ DELAY(10000);
+ }
+ if (1) {
+ au_wr(au, 0, AU_REG_CODECST, 0x8068, 4);
+ DELAY(10000);
+ au_wr(au, 0, AU_REG_CODECST, 0x00e8, 4);
+ DELAY(10000);
+ } else {
+ au_wr(au, 0, AU_REG_CODECST, 0x00a8, 4);
+ DELAY(100000);
+ au_wr(au, 0, AU_REG_CODECST, 0x80a8, 4);
+ DELAY(100000);
+ au_wr(au, 0, AU_REG_CODECST, 0x80e8, 4);
+ DELAY(100000);
+ au_wr(au, 0, AU_REG_CODECST, 0x80a8, 4);
+ DELAY(100000);
+ au_wr(au, 0, AU_REG_CODECST, 0x00a8, 4);
+ DELAY(100000);
+ au_wr(au, 0, AU_REG_CODECST, 0x00e8, 4);
+ DELAY(100000);
+ }
+
+ /* init */
+ for (i=0; i<32; i++) {
+ au_wr(au, 0, AU_REG_CODECCHN+(i<<2), 0, 4);
+ DELAY(10000);
+ }
+ au_wr(au, 0, AU_REG_CODECST, 0xe8, 4);
+ DELAY(10000);
+ au_wr(au, 0, AU_REG_CODECEN, 0, 4);
+
+ /* setup codec */
+ i=j=0;
+ while (j<100 && (i & AU_CDC_READY)==0) {
+ i=au_rd(au, 0, AU_REG_CODECST, 4);
+ DELAY(1000);
+ j++;
+ }
+ if (j==100) device_printf(dev, "codec not ready, status 0x%x\n", i);
+
+ /* init adb */
+ /*au->x5c=0;*/
+ for (i=0; i<32; i++) au->x[i]=i+0x67;
+ for (i=0; i<128; i++) au->y[i]=0x7f;
+ for (i=0; i<128; i++) au->z[i]=0x1f;
+ au_wr(au, 0, AU_REG_ADB, 0, 4);
+ for (i=0; i<124; i++) au_wr(au, 0, AU_REG_RTBASE+(i<<2), 0xffffffff, 4);
+
+ /* test */
+ i=au_rd(au, 0, 0x107c0, 4);
+ if (i!=0xdeadbeef) device_printf(dev, "dma check failed: 0x%x\n", i);
+
+ /* install mixer */
+ au_wr(au, 0, AU_REG_IRQGLOB,
+ au_rd(au, 0, AU_REG_IRQGLOB, 4) | AU_IRQ_ENABLE, 4);
+ /* braindead but it's what the oss/linux driver does
+ * for (i=0; i<0x80000000; i++) au_wr(au, 0, i<<2, 0, 4);
+ */
+ au->routes[0]=au->routes[1]=au->routes[2]=au->routes[3]=0;
+ /*au->x1e4=0;*/
+
+ /* attach channel */
+ au_addroute(au, 0x11, 0x48, 0x02);
+ au_addroute(au, 0x11, 0x49, 0x03);
+ au_encodec(au, 0);
+ au_encodec(au, 1);
+
+ for (i=0; i<48; i++) au_wr(au, 0, 0xf800+(i<<2), 0x20, 4);
+ for (i=2; i<6; i++) au_wr(au, 0, 0xf800+(i<<2), 0, 4);
+ au_wr(au, 0, 0xf8c0, 0x0843, 4);
+ for (i=0; i<4; i++) au_clrfifo(au, i);
-return (0);
+ return (0);
}
static int
au_testirq(struct au_info *au)
{
-au_wr(au, 0, AU_REG_UNK1, 0x80001000, 4);
-au_wr(au, 0, AU_REG_IRQEN, 0x00001030, 4);
-au_wr(au, 0, AU_REG_IRQSRC, 0x000007ff, 4);
-DELAY(1000000);
-if (au->interrupts==0) printf("pcm%d: irq test failedn", au->unit);
-/* this apparently generates an irq */
-return 0;
+ au_wr(au, 0, AU_REG_UNK1, 0x80001000, 4);
+ au_wr(au, 0, AU_REG_IRQEN, 0x00001030, 4);
+ au_wr(au, 0, AU_REG_IRQSRC, 0x000007ff, 4);
+ DELAY(1000000);
+ if (au->interrupts==0) printf("pcm%d: irq test failed\n", au->unit);
+ /* this apparently generates an irq */
+ return 0;
}
static int
au_pci_probe(device_t dev)
{
-if (pci_get_devid(dev) == AU8820_PCI_ID) {
-device_set_desc(dev, "Aureal Vortex 8820");
-return BUS_PROBE_DEFAULT;
-}
+ if (pci_get_devid(dev) == AU8820_PCI_ID) {
+ device_set_desc(dev, "Aureal Vortex 8820");
+ return BUS_PROBE_DEFAULT;
+ }
-return ENXIO;
+ return ENXIO;
}
static int
au_pci_attach(device_t dev)
{
-u_int32_t data;
-struct au_info *au;
-int type[10];
-int regid[10];
-struct resource *reg[10];
-int i, j, mapped = 0;
-int irqid;
-struct resource *irq = 0;
-void *ih = 0;
-struct ac97_info *codec;
-char status[SND_STATUSLEN];
-
-if ((au = malloc(sizeof(*au), M_DEVBUF, M_NOWAIT | M_ZERO)) == NULL) {
-device_printf(dev, "cannot allocate softcn");
-return ENXIO;
-}
-
-au->unit = device_get_unit(dev);
-
-data = pci_read_config(dev, PCIR_COMMAND, 2);
-data |= (PCIM_CMD_PORTEN|PCIM_CMD_MEMEN|PCIM_CMD_BUSMASTEREN);
-pci_write_config(dev, PCIR_COMMAND, data, 2);
-data = pci_read_config(dev, PCIR_COMMAND, 2);
-
-j=0;
-/* XXX dfr: is this strictly necessary? */
-for (i=0; i<PCI_MAXMAPS_0; i++) {
+ u_int32_t data;
+ struct au_info *au;
+ int type[10];
+ int regid[10];
+ struct resource *reg[10];
+ int i, j, mapped = 0;
+ int irqid;
+ struct resource *irq = 0;
+ void *ih = 0;
+ struct ac97_info *codec;
+ char status[SND_STATUSLEN];
+
+ au = malloc(sizeof(*au), M_DEVBUF, M_WAITOK | M_ZERO);
+ au->unit = device_get_unit(dev);
+
+ data = pci_read_config(dev, PCIR_COMMAND, 2);
+ data |= (PCIM_CMD_PORTEN|PCIM_CMD_MEMEN|PCIM_CMD_BUSMASTEREN);
+ pci_write_config(dev, PCIR_COMMAND, data, 2);
+ data = pci_read_config(dev, PCIR_COMMAND, 2);
+
+ j=0;
+ /* XXX dfr: is this strictly necessary? */
+ for (i=0; i<PCI_MAXMAPS_0; i++) {
#if 0
-/* Slapped wrist: config_id and map are private structures */
-if (bootverbose) {
-printf("pcm%d: map %d - allocating ", unit, i+1);
-printf("0x%x bytes of ", 1<<config_id->map[i].ln2size);
-printf("%s space ", (config_id->map[i].type & PCI_MAPPORT)?
-"io" : "memory");
-printf("at 0x%x...", config_id->map[i].base);
-}
+ /* Slapped wrist: config_id and map are private structures */
+ if (bootverbose) {
+ printf("pcm%d: map %d - allocating ", unit, i+1);
+ printf("0x%x bytes of ", 1<<config_id->map[i].ln2size);
+ printf("%s space ", (config_id->map[i].type & PCI_MAPPORT)?
+ "io" : "memory");
+ printf("at 0x%x...", config_id->map[i].base);
+ }
#endif
-regid[j] = PCIR_BAR(i);
-type[j] = SYS_RES_MEMORY;
-reg[j] = bus_alloc_resource_any(dev, type[j], ®id[j],
-RF_ACTIVE);
-if (!reg[j]) {
-type[j] = SYS_RES_IOPORT;
-reg[j] = bus_alloc_resource_any(dev, type[j],
-®id[j], RF_ACTIVE);
-}
-if (reg[j]) {
-au->st[i] = rman_get_bustag(reg[j]);
-au->sh[i] = rman_get_bushandle(reg[j]);
-mapped++;
-}
+ regid[j] = PCIR_BAR(i);
+ type[j] = SYS_RES_MEMORY;
+ reg[j] = bus_alloc_resource_any(dev, type[j], ®id[j],
+ RF_ACTIVE);
+ if (!reg[j]) {
+ type[j] = SYS_RES_IOPORT;
+ reg[j] = bus_alloc_resource_any(dev, type[j],
+ ®id[j], RF_ACTIVE);
+ }
+ if (reg[j]) {
+ au->st[i] = rman_get_bustag(reg[j]);
+ au->sh[i] = rman_get_bushandle(reg[j]);
+ mapped++;
+ }
#if 0
-if (bootverbose) printf("%sn", mapped? "ok" : "failed");
+ if (bootverbose) printf("%s\n", mapped? "ok" : "failed");
#endif
-if (mapped) j++;
-if (j == 10) {
-/* XXX */
-device_printf(dev, "too many resources");
-goto bad;
-}
-}
+ if (mapped) j++;
+ if (j == 10) {
+ /* XXX */
+ device_printf(dev, "too many resources");
+ goto bad;
+ }
+ }
#if 0
-if (j < config_id->nummaps) {
-printf("pcm%d: unable to map a required resourcen", unit);
-free(au, M_DEVBUF);
-return;
-}
+ if (j < config_id->nummaps) {
+ printf("pcm%d: unable to map a required resource\n", unit);
+ free(au, M_DEVBUF);
+ return;
+ }
#endif
-au_wr(au, 0, AU_REG_IRQEN, 0, 4);
+ au_wr(au, 0, AU_REG_IRQEN, 0, 4);
-irqid = 0;
-irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &irqid,
-RF_ACTIVE | RF_SHAREABLE);
-if (!irq || snd_setup_intr(dev, irq, 0, au_intr, au, &ih)) {
-device_printf(dev, "unable to map interruptn");
-goto bad;
-}
-
-if (au_testirq(au)) device_printf(dev, "irq test failedn");
-
-if (au_init(dev, au) == -1) {
-device_printf(dev, "unable to initialize the cardn");
-goto bad;
-}
-
-codec = AC97_CREATE(dev, au, au_ac97);
-if (codec == NULL) goto bad;
-if (mixer_init(dev, ac97_getmixerclass(), codec) == -1) goto bad;
-
-if (bus_dma_tag_create(/*parent*/NULL, /*alignment*/2, /*boundary*/0,
-/*lowaddr*/BUS_SPACE_MAXADDR_32BIT,
-/*highaddr*/BUS_SPACE_MAXADDR,
-/*filter*/NULL, /*filterarg*/NULL,
-/*maxsize*/AU_BUFFSIZE, /*nsegments*/1, /*maxsegz*/0x3ffff,
-/*flags*/0, /*lockfunc*/busdma_lock_mutex,
-/*lockarg*/&Giant, &au->parent_dmat) != 0) {
-device_printf(dev, "unable to create dma tagn");
-goto bad;
-}
-
-snprintf(status, SND_STATUSLEN, "at %s 0x%lx irq %ld %s",
-(type[0] == SYS_RES_IOPORT)? "io" : "memory",
-rman_get_start(reg[0]), rman_get_start(irq),PCM_KLDSTRING(snd_aureal));
-
-if (pcm_register(dev, au, 1, 1)) goto bad;
-/* pcm_addchan(dev, PCMDIR_REC, &au_chantemplate, au); */
-pcm_addchan(dev, PCMDIR_PLAY, &auchan_class, au);
-pcm_setstatus(dev, status);
-
-return 0;
-
-bad:
-if (au) free(au, M_DEVBUF);
-for (i = 0; i < j; i++)
-bus_release_resource(dev, type[i], regid[i], reg[i]);
-if (ih) bus_teardown_intr(dev, irq, ih);
-if (irq) bus_release_resource(dev, SYS_RES_IRQ, irqid, irq);
-return ENXIO;
+ irqid = 0;
+ irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &irqid,
+ RF_ACTIVE | RF_SHAREABLE);
+ if (!irq || snd_setup_intr(dev, irq, 0, au_intr, au, &ih)) {
+ device_printf(dev, "unable to map interrupt\n");
+ goto bad;
+ }
+
+ if (au_testirq(au)) device_printf(dev, "irq test failed\n");
+
+ if (au_init(dev, au) == -1) {
+ device_printf(dev, "unable to initialize the card\n");
+ goto bad;
+ }
+
+ codec = AC97_CREATE(dev, au, au_ac97);
+ if (codec == NULL) goto bad;
+ if (mixer_init(dev, ac97_getmixerclass(), codec) == -1) goto bad;
+
+ if (bus_dma_tag_create(/*parent*/bus_get_dma_tag(dev), /*alignment*/2,
+ /*boundary*/0,
+ /*lowaddr*/BUS_SPACE_MAXADDR_32BIT,
+ /*highaddr*/BUS_SPACE_MAXADDR,
+ /*filter*/NULL, /*filterarg*/NULL,
+ /*maxsize*/AU_BUFFSIZE, /*nsegments*/1, /*maxsegz*/0x3ffff,
+ /*flags*/0, /*lockfunc*/busdma_lock_mutex,
+ /*lockarg*/&Giant, &au->parent_dmat) != 0) {
+ device_printf(dev, "unable to create dma tag\n");
+ goto bad;
+ }
+
+ snprintf(status, SND_STATUSLEN, "at %s 0x%lx irq %ld %s",
+ (type[0] == SYS_RES_IOPORT)? "io" : "memory",
+ rman_get_start(reg[0]), rman_get_start(irq),PCM_KLDSTRING(snd_aureal));
+
+ if (pcm_register(dev, au, 1, 1)) goto bad;
+ /* pcm_addchan(dev, PCMDIR_REC, &au_chantemplate, au); */
+ pcm_addchan(dev, PCMDIR_PLAY, &auchan_class, au);
+ pcm_setstatus(dev, status);
+
+ return 0;
+
+ bad:
+ if (au) free(au, M_DEVBUF);
+ for (i = 0; i < j; i++)
+ bus_release_resource(dev, type[i], regid[i], reg[i]);
+ if (ih) bus_teardown_intr(dev, irq, ih);
+ if (irq) bus_release_resource(dev, SYS_RES_IRQ, irqid, irq);
+ return ENXIO;
}
static device_method_t au_methods[] = {
-/* Device interface */
-DEVMETHOD(device_probe, au_pci_probe),
-DEVMETHOD(device_attach, au_pci_attach),
+ /* Device interface */
+ DEVMETHOD(device_probe, au_pci_probe),
+ DEVMETHOD(device_attach, au_pci_attach),
-{ 0, 0 }
+ { 0, 0 }
};
static driver_t au_driver = {
-"pcm",
-au_methods,
-PCM_SOFTC_SIZE,
+ "pcm",
+ au_methods,
+ PCM_SOFTC_SIZE,
};
DRIVER_MODULE(snd_aureal, pci, au_driver, pcm_devclass, 0, 0);
Index: neomagic.c
===================================================================
RCS file: /home/cvs/src/sys/dev/sound/pci/neomagic.c,v
retrieving revision 1.2
retrieving revision 1.3
diff -L sys/dev/sound/pci/neomagic.c -L sys/dev/sound/pci/neomagic.c -u -r1.2 -r1.3
--- sys/dev/sound/pci/neomagic.c
+++ sys/dev/sound/pci/neomagic.c
@@ -1,30 +1,30 @@
/*-
-* Copyright (c) 1999 Cameron Grant <cg at freebsd.org>
-* All rights reserved.
-*
-* Derived from the public domain Linux driver
-*
-* Redistribution and use in source and binary forms, with or without
-* modification, are permitted provided that the following conditions
-* are met:
-* 1. Redistributions of source code must retain the above copyright
-* notice, this list of conditions and the following disclaimer.
-* 2. Redistributions in binary form must reproduce the above copyright
-* notice, this list of conditions and the following disclaimer in the
-* documentation and/or other materials provided with the distribution.
-*
-* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
-* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
-* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
-* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
-* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHERIN CONTRACT, STRICT
-* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
-* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THEPOSSIBILITY OF
-* SUCH DAMAGE.
-*/
+ * Copyright (c) 1999 Cameron Grant <cg at freebsd.org>
+ * All rights reserved.
+ *
+ * Derived from the public domain Linux driver
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHERIN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THEPOSSIBILITY OF
+ * SUCH DAMAGE.
+ */
#include <dev/sound/pcm/sound.h>
#include <dev/sound/pcm/ac97.h>
@@ -34,7 +34,7 @@
#include <dev/pci/pcireg.h>
#include <dev/pci/pcivar.h>
-SND_DECLARE_FILE("$MidnightBSD$");
+SND_DECLARE_FILE("$FreeBSD: src/sys/dev/sound/pci/neomagic.c,v 1.37 2007/06/17 06:10:42 ariff Exp $");
/* -------------------------------------------------------------------- */
@@ -47,35 +47,35 @@
/* channel registers */
struct sc_chinfo {
-int active, spd, dir, fmt;
-u_int32_t blksize, wmark;
-struct snd_dbuf *buffer;
-struct pcm_channel *channel;
-struct sc_info *parent;
+ int active, spd, dir, fmt;
+ u_int32_t blksize, wmark;
+ struct snd_dbuf *buffer;
+ struct pcm_channel *channel;
+ struct sc_info *parent;
};
/* device private data */
struct sc_info {
-device_t dev;
-u_int32_t type;
+ device_t dev;
+ u_int32_t type;
-struct resource *reg, *irq, *buf;
-int regid, irqid, bufid;
-void *ih;
-
-u_int32_t ac97_base, ac97_status, ac97_busy;
-u_int32_t buftop, pbuf, rbuf, cbuf, acbuf;
-u_int32_t playint, recint, misc1int, misc2int;
-u_int32_t irsz, badintr;
+ struct resource *reg, *irq, *buf;
+ int regid, irqid, bufid;
+ void *ih;
+
+ u_int32_t ac97_base, ac97_status, ac97_busy;
+ u_int32_t buftop, pbuf, rbuf, cbuf, acbuf;
+ u_int32_t playint, recint, misc1int, misc2int;
+ u_int32_t irsz, badintr;
-struct sc_chinfo pch, rch;
+ struct sc_chinfo pch, rch;
};
/* -------------------------------------------------------------------- */
/*
-* prototypes
-*/
+ * prototypes
+ */
/* stuff */
static int nm_loadcoeff(struct sc_info *sc, int dir, int num);
@@ -90,34 +90,34 @@
static void nm_wrbuf(struct sc_info *, int, u_int32_t, int);
static u_int32_t badcards[] = {
-0x0007103c,
-0x008f1028,
-0x00dd1014,
-0x8005110a,
+ 0x0007103c,
+ 0x008f1028,
+ 0x00dd1014,
+ 0x8005110a,
};
#define NUM_BADCARDS (sizeof(badcards) / sizeof(u_int32_t))
/* The actual rates supported by the card. */
static int samplerates[9] = {
-8000,
-11025,
-16000,
-22050,
-24000,
-32000,
-44100,
-48000,
-99999999
+ 8000,
+ 11025,
+ 16000,
+ 22050,
+ 24000,
+ 32000,
+ 44100,
+ 48000,
+ 99999999
};
/* -------------------------------------------------------------------- */
static u_int32_t nm_fmt[] = {
-AFMT_U8,
-AFMT_STEREO | AFMT_U8,
-AFMT_S16_LE,
-AFMT_STEREO | AFMT_S16_LE,
-0
+ AFMT_U8,
+ AFMT_STEREO | AFMT_U8,
+ AFMT_S16_LE,
+ AFMT_STEREO | AFMT_S16_LE,
+ 0
};
static struct pcmchan_caps nm_caps = {4000, 48000, nm_fmt, 0};
@@ -127,75 +127,75 @@
static u_int32_t
nm_rd(struct sc_info *sc, int regno, int size)
{
-bus_space_tag_t st = rman_get_bustag(sc->reg);
-bus_space_handle_t sh = rman_get_bushandle(sc->reg);
+ bus_space_tag_t st = rman_get_bustag(sc->reg);
+ bus_space_handle_t sh = rman_get_bushandle(sc->reg);
-switch (size) {
-case 1:
-return bus_space_read_1(st, sh, regno);
-case 2:
-return bus_space_read_2(st, sh, regno);
-case 4:
-return bus_space_read_4(st, sh, regno);
-default:
-return 0xffffffff;
-}
+ switch (size) {
+ case 1:
+ return bus_space_read_1(st, sh, regno);
+ case 2:
+ return bus_space_read_2(st, sh, regno);
+ case 4:
+ return bus_space_read_4(st, sh, regno);
+ default:
+ return 0xffffffff;
+ }
}
static void
nm_wr(struct sc_info *sc, int regno, u_int32_t data, int size)
{
-bus_space_tag_t st = rman_get_bustag(sc->reg);
-bus_space_handle_t sh = rman_get_bushandle(sc->reg);
+ bus_space_tag_t st = rman_get_bustag(sc->reg);
+ bus_space_handle_t sh = rman_get_bushandle(sc->reg);
-switch (size) {
-case 1:
-bus_space_write_1(st, sh, regno, data);
-break;
-case 2:
-bus_space_write_2(st, sh, regno, data);
-break;
-case 4:
-bus_space_write_4(st, sh, regno, data);
-break;
-}
+ switch (size) {
+ case 1:
+ bus_space_write_1(st, sh, regno, data);
+ break;
+ case 2:
+ bus_space_write_2(st, sh, regno, data);
+ break;
+ case 4:
+ bus_space_write_4(st, sh, regno, data);
+ break;
+ }
}
static u_int32_t
nm_rdbuf(struct sc_info *sc, int regno, int size)
{
-bus_space_tag_t st = rman_get_bustag(sc->buf);
-bus_space_handle_t sh = rman_get_bushandle(sc->buf);
+ bus_space_tag_t st = rman_get_bustag(sc->buf);
+ bus_space_handle_t sh = rman_get_bushandle(sc->buf);
-switch (size) {
-case 1:
-return bus_space_read_1(st, sh, regno);
-case 2:
-return bus_space_read_2(st, sh, regno);
-case 4:
-return bus_space_read_4(st, sh, regno);
-default:
-return 0xffffffff;
-}
+ switch (size) {
+ case 1:
+ return bus_space_read_1(st, sh, regno);
+ case 2:
+ return bus_space_read_2(st, sh, regno);
+ case 4:
+ return bus_space_read_4(st, sh, regno);
+ default:
+ return 0xffffffff;
+ }
}
static void
nm_wrbuf(struct sc_info *sc, int regno, u_int32_t data, int size)
{
-bus_space_tag_t st = rman_get_bustag(sc->buf);
-bus_space_handle_t sh = rman_get_bushandle(sc->buf);
+ bus_space_tag_t st = rman_get_bustag(sc->buf);
+ bus_space_handle_t sh = rman_get_bushandle(sc->buf);
-switch (size) {
-case 1:
-bus_space_write_1(st, sh, regno, data);
-break;
-case 2:
-bus_space_write_2(st, sh, regno, data);
-break;
-case 4:
-bus_space_write_4(st, sh, regno, data);
-break;
-}
+ switch (size) {
+ case 1:
+ bus_space_write_1(st, sh, regno, data);
+ break;
+ case 2:
+ bus_space_write_2(st, sh, regno, data);
+ break;
+ case 4:
+ bus_space_write_4(st, sh, regno, data);
+ break;
+ }
}
/* -------------------------------------------------------------------- */
@@ -203,81 +203,81 @@
static int
nm_waitcd(struct sc_info *sc)
{
-int cnt = 10;
-int fail = 1;
+ int cnt = 10;
+ int fail = 1;
-while (cnt-- > 0) {
-if (nm_rd(sc, sc->ac97_status, 2) & sc->ac97_busy) {
-DELAY(100);
-} else {
-fail = 0;
-break;
-}
-}
-return (fail);
+ while (cnt-- > 0) {
+ if (nm_rd(sc, sc->ac97_status, 2) & sc->ac97_busy) {
+ DELAY(100);
+ } else {
+ fail = 0;
+ break;
+ }
+ }
+ return (fail);
}
static u_int32_t
nm_initcd(kobj_t obj, void *devinfo)
{
-struct sc_info *sc = (struct sc_info *)devinfo;
+ struct sc_info *sc = (struct sc_info *)devinfo;
-nm_wr(sc, 0x6c0, 0x01, 1);
+ nm_wr(sc, 0x6c0, 0x01, 1);
#if 0
-/*
-* The following code-line may cause a hang for some chipsets, see
-* PR 56617.
-* In case of a bugreport without this line have a look at the PR and
-* conditionize the code-line based upon the specific version of
-* the chip.
-*/
-nm_wr(sc, 0x6cc, 0x87, 1);
+ /*
+ * The following code-line may cause a hang for some chipsets, see
+ * PR 56617.
+ * In case of a bugreport without this line have a look at the PR and
+ * conditionize the code-line based upon the specific version of
+ * the chip.
+ */
+ nm_wr(sc, 0x6cc, 0x87, 1);
#endif
-nm_wr(sc, 0x6cc, 0x80, 1);
-nm_wr(sc, 0x6cc, 0x00, 1);
-return 1;
+ nm_wr(sc, 0x6cc, 0x80, 1);
+ nm_wr(sc, 0x6cc, 0x00, 1);
+ return 1;
}
static int
nm_rdcd(kobj_t obj, void *devinfo, int regno)
{
-struct sc_info *sc = (struct sc_info *)devinfo;
-u_int32_t x;
+ struct sc_info *sc = (struct sc_info *)devinfo;
+ u_int32_t x;
-if (!nm_waitcd(sc)) {
-x = nm_rd(sc, sc->ac97_base + regno, 2);
-DELAY(1000);
-return x;
-} else {
-device_printf(sc->dev, "ac97 codec not readyn");
-return -1;
-}
+ if (!nm_waitcd(sc)) {
+ x = nm_rd(sc, sc->ac97_base + regno, 2);
+ DELAY(1000);
+ return x;
+ } else {
+ device_printf(sc->dev, "ac97 codec not ready\n");
+ return -1;
+ }
}
static int
nm_wrcd(kobj_t obj, void *devinfo, int regno, u_int32_t data)
{
-struct sc_info *sc = (struct sc_info *)devinfo;
-int cnt = 3;
+ struct sc_info *sc = (struct sc_info *)devinfo;
+ int cnt = 3;
-if (!nm_waitcd(sc)) {
-while (cnt-- > 0) {
-nm_wr(sc, sc->ac97_base + regno, data, 2);
-if (!nm_waitcd(sc)) {
-DELAY(1000);
-return 0;
-}
-}
-}
-device_printf(sc->dev, "ac97 codec not readyn");
-return -1;
+ if (!nm_waitcd(sc)) {
+ while (cnt-- > 0) {
+ nm_wr(sc, sc->ac97_base + regno, data, 2);
+ if (!nm_waitcd(sc)) {
+ DELAY(1000);
+ return 0;
+ }
+ }
+ }
+ device_printf(sc->dev, "ac97 codec not ready\n");
+ return -1;
}
static kobj_method_t nm_ac97_methods[] = {
-KOBJMETHOD(ac97_init, nm_initcd),
-KOBJMETHOD(ac97_read, nm_rdcd),
-KOBJMETHOD(ac97_write, nm_wrcd),
-{ 0, 0 }
+ KOBJMETHOD(ac97_init, nm_initcd),
+ KOBJMETHOD(ac97_read, nm_rdcd),
+ KOBJMETHOD(ac97_write, nm_wrcd),
+ { 0, 0 }
};
AC97_DECLARE(nm_ac97);
@@ -286,195 +286,195 @@
static void
nm_ackint(struct sc_info *sc, u_int32_t num)
{
-if (sc->type == NM256AV_PCI_ID) {
-nm_wr(sc, NM_INT_REG, num << 1, 2);
-} else if (sc->type == NM256ZX_PCI_ID) {
-nm_wr(sc, NM_INT_REG, num, 4);
-}
+ if (sc->type == NM256AV_PCI_ID) {
+ nm_wr(sc, NM_INT_REG, num << 1, 2);
+ } else if (sc->type == NM256ZX_PCI_ID) {
+ nm_wr(sc, NM_INT_REG, num, 4);
+ }
}
static int
nm_loadcoeff(struct sc_info *sc, int dir, int num)
{
-int ofs, sz, i;
-u_int32_t addr;
+ int ofs, sz, i;
+ u_int32_t addr;
-addr = (dir == PCMDIR_PLAY)? 0x01c : 0x21c;
-if (dir == PCMDIR_REC)
-num += 8;
-sz = coefficientSizes[num];
-ofs = 0;
-while (num-- > 0)
-ofs+= coefficientSizes[num];
-for (i = 0; i < sz; i++)
-nm_wrbuf(sc, sc->cbuf + i, coefficients[ofs + i], 1);
-nm_wr(sc, addr, sc->cbuf, 4);
-if (dir == PCMDIR_PLAY)
-sz--;
-nm_wr(sc, addr + 4, sc->cbuf + sz, 4);
-return 0;
+ addr = (dir == PCMDIR_PLAY)? 0x01c : 0x21c;
+ if (dir == PCMDIR_REC)
+ num += 8;
+ sz = coefficientSizes[num];
+ ofs = 0;
+ while (num-- > 0)
+ ofs+= coefficientSizes[num];
+ for (i = 0; i < sz; i++)
+ nm_wrbuf(sc, sc->cbuf + i, coefficients[ofs + i], 1);
+ nm_wr(sc, addr, sc->cbuf, 4);
+ if (dir == PCMDIR_PLAY)
+ sz--;
+ nm_wr(sc, addr + 4, sc->cbuf + sz, 4);
+ return 0;
}
static int
nm_setch(struct sc_chinfo *ch)
{
-struct sc_info *sc = ch->parent;
-u_int32_t base;
-u_int8_t x;
-
-for (x = 0; x < 8; x++)
-if (ch->spd < (samplerates[x] + samplerates[x + 1]) / 2)
-break;
-
-if (x == 8) return 1;
-
-ch->spd = samplerates[x];
-nm_loadcoeff(sc, ch->dir, x);
-
-x <<= 4;
-x &= NM_RATE_MASK;
-if (ch->fmt & AFMT_16BIT) x |= NM_RATE_BITS_16;
-if (ch->fmt & AFMT_STEREO) x |= NM_RATE_STEREO;
-
-base = (ch->dir == PCMDIR_PLAY)? NM_PLAYBACK_REG_OFFSET : NM_RECORD_REG_OFFSET;
-nm_wr(sc, base + NM_RATE_REG_OFFSET, x, 1);
-return 0;
+ struct sc_info *sc = ch->parent;
+ u_int32_t base;
+ u_int8_t x;
+
+ for (x = 0; x < 8; x++)
+ if (ch->spd < (samplerates[x] + samplerates[x + 1]) / 2)
+ break;
+
+ if (x == 8) return 1;
+
+ ch->spd = samplerates[x];
+ nm_loadcoeff(sc, ch->dir, x);
+
+ x <<= 4;
+ x &= NM_RATE_MASK;
+ if (ch->fmt & AFMT_16BIT) x |= NM_RATE_BITS_16;
+ if (ch->fmt & AFMT_STEREO) x |= NM_RATE_STEREO;
+
+ base = (ch->dir == PCMDIR_PLAY)? NM_PLAYBACK_REG_OFFSET : NM_RECORD_REG_OFFSET;
+ nm_wr(sc, base + NM_RATE_REG_OFFSET, x, 1);
+ return 0;
}
/* channel interface */
static void *
nmchan_init(kobj_t obj, void *devinfo, struct snd_dbuf *b, struct pcm_channel *c, int dir)
{
-struct sc_info *sc = devinfo;
-struct sc_chinfo *ch;
-u_int32_t chnbuf;
-
-chnbuf = (dir == PCMDIR_PLAY)? sc->pbuf : sc->rbuf;
-ch = (dir == PCMDIR_PLAY)? &sc->pch : &sc->rch;
-ch->active = 0;
-ch->blksize = 0;
-ch->wmark = 0;
-ch->buffer = b;
-sndbuf_setup(ch->buffer, (u_int8_t *)rman_get_virtual(sc->buf) + chnbuf, NM_BUFFSIZE);
-if (bootverbose)
-device_printf(sc->dev, "%s buf %pn", (dir == PCMDIR_PLAY)?
-"play" : "rec", sndbuf_getbuf(ch->buffer));
-ch->parent = sc;
-ch->channel = c;
-ch->dir = dir;
-return ch;
+ struct sc_info *sc = devinfo;
+ struct sc_chinfo *ch;
+ u_int32_t chnbuf;
+
+ chnbuf = (dir == PCMDIR_PLAY)? sc->pbuf : sc->rbuf;
+ ch = (dir == PCMDIR_PLAY)? &sc->pch : &sc->rch;
+ ch->active = 0;
+ ch->blksize = 0;
+ ch->wmark = 0;
+ ch->buffer = b;
+ sndbuf_setup(ch->buffer, (u_int8_t *)rman_get_virtual(sc->buf) + chnbuf, NM_BUFFSIZE);
+ if (bootverbose)
+ device_printf(sc->dev, "%s buf %p\n", (dir == PCMDIR_PLAY)?
+ "play" : "rec", sndbuf_getbuf(ch->buffer));
+ ch->parent = sc;
+ ch->channel = c;
+ ch->dir = dir;
+ return ch;
}
static int
nmchan_free(kobj_t obj, void *data)
{
-return 0;
+ return 0;
}
static int
nmchan_setformat(kobj_t obj, void *data, u_int32_t format)
{
-struct sc_chinfo *ch = data;
+ struct sc_chinfo *ch = data;
-ch->fmt = format;
-return nm_setch(ch);
+ ch->fmt = format;
+ return nm_setch(ch);
}
static int
nmchan_setspeed(kobj_t obj, void *data, u_int32_t speed)
{
-struct sc_chinfo *ch = data;
+ struct sc_chinfo *ch = data;
-ch->spd = speed;
-return nm_setch(ch)? 0 : ch->spd;
+ ch->spd = speed;
+ return nm_setch(ch)? 0 : ch->spd;
}
static int
nmchan_setblocksize(kobj_t obj, void *data, u_int32_t blocksize)
{
-struct sc_chinfo *ch = data;
+ struct sc_chinfo *ch = data;
-ch->blksize = blocksize;
+ ch->blksize = blocksize;
-return blocksize;
+ return blocksize;
}
static int
nmchan_trigger(kobj_t obj, void *data, int go)
{
-struct sc_chinfo *ch = data;
-struct sc_info *sc = ch->parent;
-int ssz;
-
-if (go == PCMTRIG_EMLDMAWR || go == PCMTRIG_EMLDMARD)
-return 0;
-
-ssz = (ch->fmt & AFMT_16BIT)? 2 : 1;
-if (ch->fmt & AFMT_STEREO)
-ssz <<= 1;
-
-if (ch->dir == PCMDIR_PLAY) {
-if (go == PCMTRIG_START) {
-ch->active = 1;
-ch->wmark = ch->blksize;
-nm_wr(sc, NM_PBUFFER_START, sc->pbuf, 4);
-nm_wr(sc, NM_PBUFFER_END, sc->pbuf + NM_BUFFSIZE - ssz, 4);
-nm_wr(sc, NM_PBUFFER_CURRP, sc->pbuf, 4);
-nm_wr(sc, NM_PBUFFER_WMARK, sc->pbuf + ch->wmark, 4);
-nm_wr(sc, NM_PLAYBACK_ENABLE_REG, NM_PLAYBACK_FREERUN |
-NM_PLAYBACK_ENABLE_FLAG, 1);
-nm_wr(sc, NM_AUDIO_MUTE_REG, 0, 2);
-} else {
-ch->active = 0;
-nm_wr(sc, NM_PLAYBACK_ENABLE_REG, 0, 1);
-nm_wr(sc, NM_AUDIO_MUTE_REG, NM_AUDIO_MUTE_BOTH, 2);
-}
-} else {
-if (go == PCMTRIG_START) {
-ch->active = 1;
-ch->wmark = ch->blksize;
-nm_wr(sc, NM_RECORD_ENABLE_REG, NM_RECORD_FREERUN |
-NM_RECORD_ENABLE_FLAG, 1);
-nm_wr(sc, NM_RBUFFER_START, sc->rbuf, 4);
-nm_wr(sc, NM_RBUFFER_END, sc->rbuf + NM_BUFFSIZE, 4);
-nm_wr(sc, NM_RBUFFER_CURRP, sc->rbuf, 4);
-nm_wr(sc, NM_RBUFFER_WMARK, sc->rbuf + ch->wmark, 4);
-} else {
-ch->active = 0;
-nm_wr(sc, NM_RECORD_ENABLE_REG, 0, 1);
-}
-}
-return 0;
+ struct sc_chinfo *ch = data;
+ struct sc_info *sc = ch->parent;
+ int ssz;
+
+ if (!PCMTRIG_COMMON(go))
+ return 0;
+
+ ssz = (ch->fmt & AFMT_16BIT)? 2 : 1;
+ if (ch->fmt & AFMT_STEREO)
+ ssz <<= 1;
+
+ if (ch->dir == PCMDIR_PLAY) {
+ if (go == PCMTRIG_START) {
+ ch->active = 1;
+ ch->wmark = ch->blksize;
+ nm_wr(sc, NM_PBUFFER_START, sc->pbuf, 4);
+ nm_wr(sc, NM_PBUFFER_END, sc->pbuf + NM_BUFFSIZE - ssz, 4);
+ nm_wr(sc, NM_PBUFFER_CURRP, sc->pbuf, 4);
+ nm_wr(sc, NM_PBUFFER_WMARK, sc->pbuf + ch->wmark, 4);
+ nm_wr(sc, NM_PLAYBACK_ENABLE_REG, NM_PLAYBACK_FREERUN |
+ NM_PLAYBACK_ENABLE_FLAG, 1);
+ nm_wr(sc, NM_AUDIO_MUTE_REG, 0, 2);
+ } else {
+ ch->active = 0;
+ nm_wr(sc, NM_PLAYBACK_ENABLE_REG, 0, 1);
+ nm_wr(sc, NM_AUDIO_MUTE_REG, NM_AUDIO_MUTE_BOTH, 2);
+ }
+ } else {
+ if (go == PCMTRIG_START) {
+ ch->active = 1;
+ ch->wmark = ch->blksize;
+ nm_wr(sc, NM_RECORD_ENABLE_REG, NM_RECORD_FREERUN |
+ NM_RECORD_ENABLE_FLAG, 1);
+ nm_wr(sc, NM_RBUFFER_START, sc->rbuf, 4);
+ nm_wr(sc, NM_RBUFFER_END, sc->rbuf + NM_BUFFSIZE, 4);
+ nm_wr(sc, NM_RBUFFER_CURRP, sc->rbuf, 4);
+ nm_wr(sc, NM_RBUFFER_WMARK, sc->rbuf + ch->wmark, 4);
+ } else {
+ ch->active = 0;
+ nm_wr(sc, NM_RECORD_ENABLE_REG, 0, 1);
+ }
+ }
+ return 0;
}
static int
nmchan_getptr(kobj_t obj, void *data)
{
-struct sc_chinfo *ch = data;
-struct sc_info *sc = ch->parent;
+ struct sc_chinfo *ch = data;
+ struct sc_info *sc = ch->parent;
-if (ch->dir == PCMDIR_PLAY)
-return nm_rd(sc, NM_PBUFFER_CURRP, 4) - sc->pbuf;
-else
-return nm_rd(sc, NM_RBUFFER_CURRP, 4) - sc->rbuf;
+ if (ch->dir == PCMDIR_PLAY)
+ return nm_rd(sc, NM_PBUFFER_CURRP, 4) - sc->pbuf;
+ else
+ return nm_rd(sc, NM_RBUFFER_CURRP, 4) - sc->rbuf;
}
static struct pcmchan_caps *
nmchan_getcaps(kobj_t obj, void *data)
{
-return &nm_caps;
+ return &nm_caps;
}
static kobj_method_t nmchan_methods[] = {
-KOBJMETHOD(channel_init, nmchan_init),
-KOBJMETHOD(channel_free, nmchan_free),
-KOBJMETHOD(channel_setformat, nmchan_setformat),
-KOBJMETHOD(channel_setspeed, nmchan_setspeed),
-KOBJMETHOD(channel_setblocksize, nmchan_setblocksize),
-KOBJMETHOD(channel_trigger, nmchan_trigger),
-KOBJMETHOD(channel_getptr, nmchan_getptr),
-KOBJMETHOD(channel_getcaps, nmchan_getcaps),
-{ 0, 0 }
+ KOBJMETHOD(channel_init, nmchan_init),
+ KOBJMETHOD(channel_free, nmchan_free),
+ KOBJMETHOD(channel_setformat, nmchan_setformat),
+ KOBJMETHOD(channel_setspeed, nmchan_setspeed),
+ KOBJMETHOD(channel_setblocksize, nmchan_setblocksize),
+ KOBJMETHOD(channel_trigger, nmchan_trigger),
+ KOBJMETHOD(channel_getptr, nmchan_getptr),
+ KOBJMETHOD(channel_getcaps, nmchan_getcaps),
+ { 0, 0 }
};
CHANNEL_DECLARE(nmchan);
@@ -482,348 +482,344 @@
static void
nm_intr(void *p)
{
-struct sc_info *sc = (struct sc_info *)p;
-int status, x;
+ struct sc_info *sc = (struct sc_info *)p;
+ int status, x;
-status = nm_rd(sc, NM_INT_REG, sc->irsz);
-if (status == 0)
-return;
-
-if (status & sc->playint) {
-status &= ~sc->playint;
-sc->pch.wmark += sc->pch.blksize;
-sc->pch.wmark %= NM_BUFFSIZE;
-nm_wr(sc, NM_PBUFFER_WMARK, sc->pbuf + sc->pch.wmark, 4);
-
-nm_ackint(sc, sc->playint);
-chn_intr(sc->pch.channel);
-}
-if (status & sc->recint) {
-status &= ~sc->recint;
-sc->rch.wmark += sc->rch.blksize;
-sc->rch.wmark %= NM_BUFFSIZE;
-nm_wr(sc, NM_RBUFFER_WMARK, sc->rbuf + sc->rch.wmark, 4);
-
-nm_ackint(sc, sc->recint);
-chn_intr(sc->rch.channel);
-}
-if (status & sc->misc1int) {
-status &= ~sc->misc1int;
-nm_ackint(sc, sc->misc1int);
-x = nm_rd(sc, 0x400, 1);
-nm_wr(sc, 0x400, x | 2, 1);
-device_printf(sc->dev, "misc int 1n");
-}
-if (status & sc->misc2int) {
-status &= ~sc->misc2int;
-nm_ackint(sc, sc->misc2int);
-x = nm_rd(sc, 0x400, 1);
-nm_wr(sc, 0x400, x & ~2, 1);
-device_printf(sc->dev, "misc int 2n");
-}
-if (status) {
-nm_ackint(sc, status);
-device_printf(sc->dev, "unknown intn");
-}
+ status = nm_rd(sc, NM_INT_REG, sc->irsz);
+ if (status == 0)
+ return;
+
+ if (status & sc->playint) {
+ status &= ~sc->playint;
+ sc->pch.wmark += sc->pch.blksize;
+ sc->pch.wmark %= NM_BUFFSIZE;
+ nm_wr(sc, NM_PBUFFER_WMARK, sc->pbuf + sc->pch.wmark, 4);
+
+ nm_ackint(sc, sc->playint);
+ chn_intr(sc->pch.channel);
+ }
+ if (status & sc->recint) {
+ status &= ~sc->recint;
+ sc->rch.wmark += sc->rch.blksize;
+ sc->rch.wmark %= NM_BUFFSIZE;
+ nm_wr(sc, NM_RBUFFER_WMARK, sc->rbuf + sc->rch.wmark, 4);
+
+ nm_ackint(sc, sc->recint);
+ chn_intr(sc->rch.channel);
+ }
+ if (status & sc->misc1int) {
+ status &= ~sc->misc1int;
+ nm_ackint(sc, sc->misc1int);
+ x = nm_rd(sc, 0x400, 1);
+ nm_wr(sc, 0x400, x | 2, 1);
+ device_printf(sc->dev, "misc int 1\n");
+ }
+ if (status & sc->misc2int) {
+ status &= ~sc->misc2int;
+ nm_ackint(sc, sc->misc2int);
+ x = nm_rd(sc, 0x400, 1);
+ nm_wr(sc, 0x400, x & ~2, 1);
+ device_printf(sc->dev, "misc int 2\n");
+ }
+ if (status) {
+ nm_ackint(sc, status);
+ device_printf(sc->dev, "unknown int\n");
+ }
}
/* -------------------------------------------------------------------- */
/*
-* Probe and attach the card
-*/
+ * Probe and attach the card
+ */
static int
nm_init(struct sc_info *sc)
{
-u_int32_t ofs, i;
+ u_int32_t ofs, i;
-if (sc->type == NM256AV_PCI_ID) {
-sc->ac97_base = NM_MIXER_OFFSET;
-sc->ac97_status = NM_MIXER_STATUS_OFFSET;
-sc->ac97_busy = NM_MIXER_READY_MASK;
-
-sc->buftop = 2560 * 1024;
-
-sc->irsz = 2;
-sc->playint = NM_PLAYBACK_INT;
-sc->recint = NM_RECORD_INT;
-sc->misc1int = NM_MISC_INT_1;
-sc->misc2int = NM_MISC_INT_2;
-} else if (sc->type == NM256ZX_PCI_ID) {
-sc->ac97_base = NM_MIXER_OFFSET;
-sc->ac97_status = NM2_MIXER_STATUS_OFFSET;
-sc->ac97_busy = NM2_MIXER_READY_MASK;
-
-sc->buftop = (nm_rd(sc, 0xa0b, 2)? 6144 : 4096) * 1024;
-
-sc->irsz = 4;
-sc->playint = NM2_PLAYBACK_INT;
-sc->recint = NM2_RECORD_INT;
-sc->misc1int = NM2_MISC_INT_1;
-sc->misc2int = NM2_MISC_INT_2;
-} else return -1;
-sc->badintr = 0;
-ofs = sc->buftop - 0x0400;
-sc->buftop -= 0x1400;
-
-if (bootverbose)
-device_printf(sc->dev, "buftop is 0x%08xn", sc->buftop);
-if ((nm_rdbuf(sc, ofs, 4) & NM_SIG_MASK) == NM_SIGNATURE) {
-i = nm_rdbuf(sc, ofs + 4, 4);
-if (i != 0 && i != 0xffffffff) {
-if (bootverbose)
-device_printf(sc->dev, "buftop is changed to 0x%08xn", i);
-sc->buftop = i;
-}
-}
-
-sc->cbuf = sc->buftop - NM_MAX_COEFFICIENT;
-sc->rbuf = sc->cbuf - NM_BUFFSIZE;
-sc->pbuf = sc->rbuf - NM_BUFFSIZE;
-sc->acbuf = sc->pbuf - (NM_TOTAL_COEFF_COUNT * 4);
-
-nm_wr(sc, 0, 0x11, 1);
-nm_wr(sc, NM_RECORD_ENABLE_REG, 0, 1);
-nm_wr(sc, 0x214, 0, 2);
+ if (sc->type == NM256AV_PCI_ID) {
+ sc->ac97_base = NM_MIXER_OFFSET;
+ sc->ac97_status = NM_MIXER_STATUS_OFFSET;
+ sc->ac97_busy = NM_MIXER_READY_MASK;
+
+ sc->buftop = 2560 * 1024;
+
+ sc->irsz = 2;
+ sc->playint = NM_PLAYBACK_INT;
+ sc->recint = NM_RECORD_INT;
+ sc->misc1int = NM_MISC_INT_1;
+ sc->misc2int = NM_MISC_INT_2;
+ } else if (sc->type == NM256ZX_PCI_ID) {
+ sc->ac97_base = NM_MIXER_OFFSET;
+ sc->ac97_status = NM2_MIXER_STATUS_OFFSET;
+ sc->ac97_busy = NM2_MIXER_READY_MASK;
+
+ sc->buftop = (nm_rd(sc, 0xa0b, 2)? 6144 : 4096) * 1024;
+
+ sc->irsz = 4;
+ sc->playint = NM2_PLAYBACK_INT;
+ sc->recint = NM2_RECORD_INT;
+ sc->misc1int = NM2_MISC_INT_1;
+ sc->misc2int = NM2_MISC_INT_2;
+ } else return -1;
+ sc->badintr = 0;
+ ofs = sc->buftop - 0x0400;
+ sc->buftop -= 0x1400;
+
+ if (bootverbose)
+ device_printf(sc->dev, "buftop is 0x%08x\n", sc->buftop);
+ if ((nm_rdbuf(sc, ofs, 4) & NM_SIG_MASK) == NM_SIGNATURE) {
+ i = nm_rdbuf(sc, ofs + 4, 4);
+ if (i != 0 && i != 0xffffffff) {
+ if (bootverbose)
+ device_printf(sc->dev, "buftop is changed to 0x%08x\n", i);
+ sc->buftop = i;
+ }
+ }
+
+ sc->cbuf = sc->buftop - NM_MAX_COEFFICIENT;
+ sc->rbuf = sc->cbuf - NM_BUFFSIZE;
+ sc->pbuf = sc->rbuf - NM_BUFFSIZE;
+ sc->acbuf = sc->pbuf - (NM_TOTAL_COEFF_COUNT * 4);
+
+ nm_wr(sc, 0, 0x11, 1);
+ nm_wr(sc, NM_RECORD_ENABLE_REG, 0, 1);
+ nm_wr(sc, 0x214, 0, 2);
-return 0;
+ return 0;
}
static int
nm_pci_probe(device_t dev)
{
-struct sc_info *sc = NULL;
-char *s = NULL;
-u_int32_t subdev, i, data;
-
-subdev = (pci_get_subdevice(dev) << 16) | pci_get_subvendor(dev);
-switch (pci_get_devid(dev)) {
-case NM256AV_PCI_ID:
-i = 0;
-while ((i < NUM_BADCARDS) && (badcards[i] != subdev))
-i++;
-
-/* Try to catch other non-ac97 cards */
-
-if (i == NUM_BADCARDS) {
-if (!(sc = malloc(sizeof(*sc), M_DEVBUF, M_NOWAIT | M_ZERO))) {
-device_printf(dev, "cannot allocate softcn");
-return ENXIO;
-}
-
-data = pci_read_config(dev, PCIR_COMMAND, 2);
-pci_write_config(dev, PCIR_COMMAND, data |
-PCIM_CMD_PORTEN | PCIM_CMD_MEMEN |
-PCIM_CMD_BUSMASTEREN, 2);
-
-sc->regid = PCIR_BAR(1);
-sc->reg = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
-&sc->regid,
-RF_ACTIVE);
-
-if (!sc->reg) {
-device_printf(dev, "unable to map register spacen");
-pci_write_config(dev, PCIR_COMMAND, data, 2);
-free(sc, M_DEVBUF);
-return ENXIO;
-}
-
-/*
-* My Panasonic CF-M2EV needs resetting device
-* before checking mixer is present or not.
-* t.ichinoseki at nifty.com.
-*/
-nm_wr(sc, 0, 0x11, 1); /* reset device */
-if ((nm_rd(sc, NM_MIXER_PRESENCE, 2) &
-NM_PRESENCE_MASK) != NM_PRESENCE_VALUE) {
-i = 0; /* non-ac97 card, but not listed */
-DEB(device_printf(dev, "subdev = 0x%x - badcard?n",
-subdev));
-}
-pci_write_config(dev, PCIR_COMMAND, data, 2);
-bus_release_resource(dev, SYS_RES_MEMORY, sc->regid,
-sc->reg);
-free(sc, M_DEVBUF);
-}
-
-if (i == NUM_BADCARDS)
-s = "NeoMagic 256AV";
-DEB(else)
-DEB(device_printf(dev, "this is a non-ac97 NM256AV, not attachingn"));
-
-break;
-
-case NM256ZX_PCI_ID:
-s = "NeoMagic 256ZX";
-break;
-}
+ struct sc_info *sc = NULL;
+ char *s = NULL;
+ u_int32_t subdev, i, data;
+
+ subdev = (pci_get_subdevice(dev) << 16) | pci_get_subvendor(dev);
+ switch (pci_get_devid(dev)) {
+ case NM256AV_PCI_ID:
+ i = 0;
+ while ((i < NUM_BADCARDS) && (badcards[i] != subdev))
+ i++;
+
+ /* Try to catch other non-ac97 cards */
+
+ if (i == NUM_BADCARDS) {
+ if (!(sc = malloc(sizeof(*sc), M_DEVBUF, M_NOWAIT | M_ZERO))) {
+ device_printf(dev, "cannot allocate softc\n");
+ return ENXIO;
+ }
+
+ data = pci_read_config(dev, PCIR_COMMAND, 2);
+ pci_write_config(dev, PCIR_COMMAND, data |
+ PCIM_CMD_PORTEN | PCIM_CMD_MEMEN |
+ PCIM_CMD_BUSMASTEREN, 2);
+
+ sc->regid = PCIR_BAR(1);
+ sc->reg = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
+ &sc->regid,
+ RF_ACTIVE);
+
+ if (!sc->reg) {
+ device_printf(dev, "unable to map register space\n");
+ pci_write_config(dev, PCIR_COMMAND, data, 2);
+ free(sc, M_DEVBUF);
+ return ENXIO;
+ }
+
+ /*
+ * My Panasonic CF-M2EV needs resetting device
+ * before checking mixer is present or not.
+ * t.ichinoseki at nifty.com.
+ */
+ nm_wr(sc, 0, 0x11, 1); /* reset device */
+ if ((nm_rd(sc, NM_MIXER_PRESENCE, 2) &
+ NM_PRESENCE_MASK) != NM_PRESENCE_VALUE) {
+ i = 0; /* non-ac97 card, but not listed */
+ DEB(device_printf(dev, "subdev = 0x%x - badcard?\n",
+ subdev));
+ }
+ pci_write_config(dev, PCIR_COMMAND, data, 2);
+ bus_release_resource(dev, SYS_RES_MEMORY, sc->regid,
+ sc->reg);
+ free(sc, M_DEVBUF);
+ }
+
+ if (i == NUM_BADCARDS)
+ s = "NeoMagic 256AV";
+ DEB(else)
+ DEB(device_printf(dev, "this is a non-ac97 NM256AV, not attaching\n"));
+
+ break;
+
+ case NM256ZX_PCI_ID:
+ s = "NeoMagic 256ZX";
+ break;
+ }
-if (s) device_set_desc(dev, s);
-return s? 0 : ENXIO;
+ if (s) device_set_desc(dev, s);
+ return s? 0 : ENXIO;
}
static int
nm_pci_attach(device_t dev)
{
-u_int32_t data;
-struct sc_info *sc;
-struct ac97_info *codec = 0;
-char status[SND_STATUSLEN];
-
-if ((sc = malloc(sizeof(*sc), M_DEVBUF, M_NOWAIT | M_ZERO)) == NULL) {
-device_printf(dev, "cannot allocate softcn");
-return ENXIO;
-}
-
-sc->dev = dev;
-sc->type = pci_get_devid(dev);
-
-data = pci_read_config(dev, PCIR_COMMAND, 2);
-data |= (PCIM_CMD_PORTEN|PCIM_CMD_MEMEN|PCIM_CMD_BUSMASTEREN);
-pci_write_config(dev, PCIR_COMMAND, data, 2);
-data = pci_read_config(dev, PCIR_COMMAND, 2);
-
-sc->bufid = PCIR_BAR(0);
-sc->buf = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &sc->bufid,
-RF_ACTIVE);
-sc->regid = PCIR_BAR(1);
-sc->reg = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &sc->regid,
-RF_ACTIVE);
-
-if (!sc->buf || !sc->reg) {
-device_printf(dev, "unable to map register spacen");
-goto bad;
-}
-
-if (nm_init(sc) == -1) {
-device_printf(dev, "unable to initialize the cardn");
-goto bad;
-}
-
-codec = AC97_CREATE(dev, sc, nm_ac97);
-if (codec == NULL) goto bad;
-if (mixer_init(dev, ac97_getmixerclass(), codec) == -1) goto bad;
-
-sc->irqid = 0;
-sc->irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &sc->irqid,
-RF_ACTIVE | RF_SHAREABLE);
-if (!sc->irq || snd_setup_intr(dev, sc->irq, 0, nm_intr, sc, &sc->ih)) {
-device_printf(dev, "unable to map interruptn");
-goto bad;
-}
-
-snprintf(status, SND_STATUSLEN, "at memory 0x%lx, 0x%lx irq %ld %s",
-rman_get_start(sc->buf), rman_get_start(sc->reg),
-rman_get_start(sc->irq),PCM_KLDSTRING(snd_neomagic));
+ u_int32_t data;
+ struct sc_info *sc;
+ struct ac97_info *codec = 0;
+ char status[SND_STATUSLEN];
+
+ sc = malloc(sizeof(*sc), M_DEVBUF, M_WAITOK | M_ZERO);
+ sc->dev = dev;
+ sc->type = pci_get_devid(dev);
+
+ data = pci_read_config(dev, PCIR_COMMAND, 2);
+ data |= (PCIM_CMD_PORTEN|PCIM_CMD_MEMEN|PCIM_CMD_BUSMASTEREN);
+ pci_write_config(dev, PCIR_COMMAND, data, 2);
+ data = pci_read_config(dev, PCIR_COMMAND, 2);
+
+ sc->bufid = PCIR_BAR(0);
+ sc->buf = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &sc->bufid,
+ RF_ACTIVE);
+ sc->regid = PCIR_BAR(1);
+ sc->reg = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &sc->regid,
+ RF_ACTIVE);
+
+ if (!sc->buf || !sc->reg) {
+ device_printf(dev, "unable to map register space\n");
+ goto bad;
+ }
+
+ if (nm_init(sc) == -1) {
+ device_printf(dev, "unable to initialize the card\n");
+ goto bad;
+ }
+
+ codec = AC97_CREATE(dev, sc, nm_ac97);
+ if (codec == NULL) goto bad;
+ if (mixer_init(dev, ac97_getmixerclass(), codec) == -1) goto bad;
+
+ sc->irqid = 0;
+ sc->irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &sc->irqid,
+ RF_ACTIVE | RF_SHAREABLE);
+ if (!sc->irq || snd_setup_intr(dev, sc->irq, 0, nm_intr, sc, &sc->ih)) {
+ device_printf(dev, "unable to map interrupt\n");
+ goto bad;
+ }
+
+ snprintf(status, SND_STATUSLEN, "at memory 0x%lx, 0x%lx irq %ld %s",
+ rman_get_start(sc->buf), rman_get_start(sc->reg),
+ rman_get_start(sc->irq),PCM_KLDSTRING(snd_neomagic));
+
+ if (pcm_register(dev, sc, 1, 1)) goto bad;
+ pcm_addchan(dev, PCMDIR_REC, &nmchan_class, sc);
+ pcm_addchan(dev, PCMDIR_PLAY, &nmchan_class, sc);
+ pcm_setstatus(dev, status);
-if (pcm_register(dev, sc, 1, 1)) goto bad;
-pcm_addchan(dev, PCMDIR_REC, &nmchan_class, sc);
-pcm_addchan(dev, PCMDIR_PLAY, &nmchan_class, sc);
-pcm_setstatus(dev, status);
-
-return 0;
+ return 0;
bad:
-if (codec) ac97_destroy(codec);
-if (sc->buf) bus_release_resource(dev, SYS_RES_MEMORY, sc->bufid, sc->buf);
-if (sc->reg) bus_release_resource(dev, SYS_RES_MEMORY, sc->regid, sc->reg);
-if (sc->ih) bus_teardown_intr(dev, sc->irq, sc->ih);
-if (sc->irq) bus_release_resource(dev, SYS_RES_IRQ, sc->irqid, sc->irq);
-free(sc, M_DEVBUF);
-return ENXIO;
+ if (codec) ac97_destroy(codec);
+ if (sc->buf) bus_release_resource(dev, SYS_RES_MEMORY, sc->bufid, sc->buf);
+ if (sc->reg) bus_release_resource(dev, SYS_RES_MEMORY, sc->regid, sc->reg);
+ if (sc->ih) bus_teardown_intr(dev, sc->irq, sc->ih);
+ if (sc->irq) bus_release_resource(dev, SYS_RES_IRQ, sc->irqid, sc->irq);
+ free(sc, M_DEVBUF);
+ return ENXIO;
}
static int
nm_pci_detach(device_t dev)
{
-int r;
-struct sc_info *sc;
+ int r;
+ struct sc_info *sc;
-r = pcm_unregister(dev);
-if (r)
-return r;
-
-sc = pcm_getdevinfo(dev);
-bus_release_resource(dev, SYS_RES_MEMORY, sc->bufid, sc->buf);
-bus_release_resource(dev, SYS_RES_MEMORY, sc->regid, sc->reg);
-bus_teardown_intr(dev, sc->irq, sc->ih);
-bus_release_resource(dev, SYS_RES_IRQ, sc->irqid, sc->irq);
-free(sc, M_DEVBUF);
+ r = pcm_unregister(dev);
+ if (r)
+ return r;
+
+ sc = pcm_getdevinfo(dev);
+ bus_release_resource(dev, SYS_RES_MEMORY, sc->bufid, sc->buf);
+ bus_release_resource(dev, SYS_RES_MEMORY, sc->regid, sc->reg);
+ bus_teardown_intr(dev, sc->irq, sc->ih);
+ bus_release_resource(dev, SYS_RES_IRQ, sc->irqid, sc->irq);
+ free(sc, M_DEVBUF);
-return 0;
+ return 0;
}
static int
nm_pci_suspend(device_t dev)
{
-struct sc_info *sc;
+ struct sc_info *sc;
-sc = pcm_getdevinfo(dev);
+ sc = pcm_getdevinfo(dev);
-/* stop playing */
-if (sc->pch.active) {
-nm_wr(sc, NM_PLAYBACK_ENABLE_REG, 0, 1);
-nm_wr(sc, NM_AUDIO_MUTE_REG, NM_AUDIO_MUTE_BOTH, 2);
-}
-/* stop recording */
-if (sc->rch.active) {
-nm_wr(sc, NM_RECORD_ENABLE_REG, 0, 1);
-}
-return 0;
+ /* stop playing */
+ if (sc->pch.active) {
+ nm_wr(sc, NM_PLAYBACK_ENABLE_REG, 0, 1);
+ nm_wr(sc, NM_AUDIO_MUTE_REG, NM_AUDIO_MUTE_BOTH, 2);
+ }
+ /* stop recording */
+ if (sc->rch.active) {
+ nm_wr(sc, NM_RECORD_ENABLE_REG, 0, 1);
+ }
+ return 0;
}
static int
nm_pci_resume(device_t dev)
{
-struct sc_info *sc;
+ struct sc_info *sc;
-sc = pcm_getdevinfo(dev);
+ sc = pcm_getdevinfo(dev);
-/*
-* Reinit audio device.
-* Don't call nm_init(). It would change buftop if X ran or
-* is running. This makes playing and recording buffer address
-* shift but these buffers of channel layer are not changed.
-* As a result of this inconsistency, periodic noise will be
-* generated while playing.
-*/
-nm_wr(sc, 0, 0x11, 1);
-nm_wr(sc, 0x214, 0, 2);
-
-/* Reinit mixer */
-if (mixer_reinit(dev) == -1) {
-device_printf(dev, "unable to reinitialize the mixern");
-return ENXIO;
-}
-/* restart playing */
-if (sc->pch.active) {
-nm_wr(sc, NM_PLAYBACK_ENABLE_REG, NM_PLAYBACK_FREERUN |
-NM_PLAYBACK_ENABLE_FLAG, 1);
-nm_wr(sc, NM_AUDIO_MUTE_REG, 0, 2);
-}
-/* restart recording */
-if (sc->rch.active) {
-nm_wr(sc, NM_RECORD_ENABLE_REG, NM_RECORD_FREERUN |
-NM_RECORD_ENABLE_FLAG, 1);
-}
-return 0;
+ /*
+ * Reinit audio device.
+ * Don't call nm_init(). It would change buftop if X ran or
+ * is running. This makes playing and recording buffer address
+ * shift but these buffers of channel layer are not changed.
+ * As a result of this inconsistency, periodic noise will be
+ * generated while playing.
+ */
+ nm_wr(sc, 0, 0x11, 1);
+ nm_wr(sc, 0x214, 0, 2);
+
+ /* Reinit mixer */
+ if (mixer_reinit(dev) == -1) {
+ device_printf(dev, "unable to reinitialize the mixer\n");
+ return ENXIO;
+ }
+ /* restart playing */
+ if (sc->pch.active) {
+ nm_wr(sc, NM_PLAYBACK_ENABLE_REG, NM_PLAYBACK_FREERUN |
+ NM_PLAYBACK_ENABLE_FLAG, 1);
+ nm_wr(sc, NM_AUDIO_MUTE_REG, 0, 2);
+ }
+ /* restart recording */
+ if (sc->rch.active) {
+ nm_wr(sc, NM_RECORD_ENABLE_REG, NM_RECORD_FREERUN |
+ NM_RECORD_ENABLE_FLAG, 1);
+ }
+ return 0;
}
static device_method_t nm_methods[] = {
-/* Device interface */
-DEVMETHOD(device_probe, nm_pci_probe),
-DEVMETHOD(device_attach, nm_pci_attach),
-DEVMETHOD(device_detach, nm_pci_detach),
-DEVMETHOD(device_suspend, nm_pci_suspend),
-DEVMETHOD(device_resume, nm_pci_resume),
-{ 0, 0 }
+ /* Device interface */
+ DEVMETHOD(device_probe, nm_pci_probe),
+ DEVMETHOD(device_attach, nm_pci_attach),
+ DEVMETHOD(device_detach, nm_pci_detach),
+ DEVMETHOD(device_suspend, nm_pci_suspend),
+ DEVMETHOD(device_resume, nm_pci_resume),
+ { 0, 0 }
};
static driver_t nm_driver = {
-"pcm",
-nm_methods,
-PCM_SOFTC_SIZE,
+ "pcm",
+ nm_methods,
+ PCM_SOFTC_SIZE,
};
DRIVER_MODULE(snd_neomagic, pci, nm_driver, pcm_devclass, 0, 0);
Index: maestro3.c
===================================================================
RCS file: /home/cvs/src/sys/dev/sound/pci/maestro3.c,v
retrieving revision 1.2
retrieving revision 1.3
diff -L sys/dev/sound/pci/maestro3.c -L sys/dev/sound/pci/maestro3.c -u -r1.2 -r1.3
--- sys/dev/sound/pci/maestro3.c
+++ sys/dev/sound/pci/maestro3.c
@@ -1,56 +1,56 @@
/*-
-* Copyright (c) 2001 Scott Long <scottl at freebsd.org>
-* Copyright (c) 2001 Darrell Anderson <anderson at cs.duke.edu>
-* All rights reserved.
-*
-* Redistribution and use in source and binary forms, with or without
-* modification, are permitted provided that the following conditions
-* are met:
-* 1. Redistributions of source code must retain the above copyright
-* notice, this list of conditions and the following disclaimer.
-* 2. Redistributions in binary form must reproduce the above copyright
-* notice, this list of conditions and the following disclaimer in the
-* documentation and/or other materials provided with the distribution.
-*
-* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
-* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
-* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
-* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
-* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
-* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
-* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
-* SUCH DAMAGE.
-*/
+ * Copyright (c) 2001 Scott Long <scottl at freebsd.org>
+ * Copyright (c) 2001 Darrell Anderson <anderson at cs.duke.edu>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
/*
-* Maestro-3/Allegro FreeBSD pcm sound driver
-*
-* executive status summary:
-* (+) /dev/dsp multiple concurrent play channels.
-* (+) /dev/dsp config (speed, mono/stereo, 8/16 bit).
-* (+) /dev/mixer sets left/right volumes.
-* (+) /dev/dsp recording works. Tested successfully with the cdrom channel
-* (+) apm suspend/resume works, and works properly!.
-* (-) hardware volme controls don't work =-(
-* (-) setblocksize() does nothing.
-*
-* The real credit goes to:
-*
-* Zach Brown for his Linux driver core and helpful technical comments.
-* <zab at zabbo.net>, http://www.zabbo.net/maestro3
-*
-* Cameron Grant created the pcm framework used here nearly verbatim.
-* <cg at freebsd.org>, http://people.freebsd.org/~cg/template.c
-*
-* Taku YAMAMOTO for his Maestro-1/2 FreeBSD driver and sanity reference.
-* <taku at cent.saitama-u.ac.jp>
-*
-* ESS docs explained a few magic registers and numbers.
-* http://virgo.caltech.edu/~dmoore/maestro3.pdf.gz
-*/
+ * Maestro-3/Allegro FreeBSD pcm sound driver
+ *
+ * executive status summary:
+ * (+) /dev/dsp multiple concurrent play channels.
+ * (+) /dev/dsp config (speed, mono/stereo, 8/16 bit).
+ * (+) /dev/mixer sets left/right volumes.
+ * (+) /dev/dsp recording works. Tested successfully with the cdrom channel
+ * (+) apm suspend/resume works, and works properly!.
+ * (-) hardware volme controls don't work =-(
+ * (-) setblocksize() does nothing.
+ *
+ * The real credit goes to:
+ *
+ * Zach Brown for his Linux driver core and helpful technical comments.
+ * <zab at zabbo.net>, http://www.zabbo.net/maestro3
+ *
+ * Cameron Grant created the pcm framework used here nearly verbatim.
+ * <cg at freebsd.org>, http://people.freebsd.org/~cg/template.c
+ *
+ * Taku YAMAMOTO for his Maestro-1/2 FreeBSD driver and sanity reference.
+ * <taku at cent.saitama-u.ac.jp>
+ *
+ * ESS docs explained a few magic registers and numbers.
+ * http://virgo.caltech.edu/~dmoore/maestro3.pdf.gz
+ */
#include <dev/sound/pcm/sound.h>
#include <dev/sound/pcm/ac97.h>
@@ -61,7 +61,7 @@
#include <gnu/dev/sound/pci/maestro3_reg.h>
#include <gnu/dev/sound/pci/maestro3_dsp.h>
-SND_DECLARE_FILE("$MidnightBSD$");
+SND_DECLARE_FILE("$FreeBSD: src/sys/dev/sound/pci/maestro3.c,v 1.35 2007/06/17 06:10:42 ariff Exp $");
/* -------------------------------------------------------------------- */
@@ -73,17 +73,17 @@
/* -------------------------------------------------------------------- */
enum {
-ESS_ALLEGRO_1,
-ESS_MAESTRO3
+ ESS_ALLEGRO_1,
+ ESS_MAESTRO3
};
static struct m3_card_type {
-u_int32_t pci_id; int which; int delay1; int delay2; char *name;
+ u_int32_t pci_id; int which; int delay1; int delay2; char *name;
} m3_card_types[] = {
-{ 0x1988125d, ESS_ALLEGRO_1, 50, 800, "ESS Technology Allegro-1" },
-{ 0x1998125d, ESS_MAESTRO3, 20, 500, "ESS Technology Maestro3" },
-{ 0x199a125d, ESS_MAESTRO3, 20, 500, "ESS Technology Maestro3" },
-{ 0, 0, 0, 0, NULL }
+ { 0x1988125d, ESS_ALLEGRO_1, 50, 800, "ESS Technology Allegro-1" },
+ { 0x1998125d, ESS_MAESTRO3, 20, 500, "ESS Technology Maestro3" },
+ { 0x199a125d, ESS_MAESTRO3, 20, 500, "ESS Technology Maestro3" },
+ { 0, 0, 0, 0, NULL }
};
#define M3_BUFSIZE_MIN 4096
@@ -96,60 +96,60 @@
struct sc_info;
struct sc_pchinfo {
-u_int32_t spd;
-u_int32_t fmt;
-struct snd_dbuf *buffer;
-struct pcm_channel *channel;
-struct sc_info *parent;
-u_int32_t bufsize;
-u_int32_t dac_data;
-u_int32_t dac_idx;
-u_int32_t active;
-u_int32_t ptr;
-u_int32_t prevptr;
+ u_int32_t spd;
+ u_int32_t fmt;
+ struct snd_dbuf *buffer;
+ struct pcm_channel *channel;
+ struct sc_info *parent;
+ u_int32_t bufsize;
+ u_int32_t dac_data;
+ u_int32_t dac_idx;
+ u_int32_t active;
+ u_int32_t ptr;
+ u_int32_t prevptr;
};
struct sc_rchinfo {
-u_int32_t spd;
-u_int32_t fmt;
-struct snd_dbuf *buffer;
-struct pcm_channel *channel;
-struct sc_info *parent;
-u_int32_t bufsize;
-u_int32_t adc_data;
-u_int32_t adc_idx;
-u_int32_t active;
-u_int32_t ptr;
-u_int32_t prevptr;
+ u_int32_t spd;
+ u_int32_t fmt;
+ struct snd_dbuf *buffer;
+ struct pcm_channel *channel;
+ struct sc_info *parent;
+ u_int32_t bufsize;
+ u_int32_t adc_data;
+ u_int32_t adc_idx;
+ u_int32_t active;
+ u_int32_t ptr;
+ u_int32_t prevptr;
};
struct sc_info {
-device_t dev;
-u_int32_t type;
-int which;
-int delay1;
-int delay2;
-
-bus_space_tag_t st;
-bus_space_handle_t sh;
-bus_dma_tag_t parent_dmat;
-
-struct resource *reg;
-struct resource *irq;
-int regtype;
-int regid;
-int irqid;
-void *ih;
-
-struct sc_pchinfo pch[M3_PCHANS];
-struct sc_rchinfo rch[M3_RCHANS];
-int pch_cnt;
-int rch_cnt;
-int pch_active_cnt;
-unsigned int bufsz;
-u_int16_t *savemem;
+ device_t dev;
+ u_int32_t type;
+ int which;
+ int delay1;
+ int delay2;
+
+ bus_space_tag_t st;
+ bus_space_handle_t sh;
+ bus_dma_tag_t parent_dmat;
+
+ struct resource *reg;
+ struct resource *irq;
+ int regtype;
+ int regid;
+ int irqid;
+ void *ih;
+
+ struct sc_pchinfo pch[M3_PCHANS];
+ struct sc_rchinfo rch[M3_RCHANS];
+ int pch_cnt;
+ int rch_cnt;
+ int pch_active_cnt;
+ unsigned int bufsz;
+ u_int16_t *savemem;
-struct mtx *sc_lock;
+ struct mtx *sc_lock;
};
#define M3_LOCK(_sc) snd_mtxlock((_sc)->sc_lock)
@@ -203,10 +203,10 @@
/* -------------------------------------------------------------------- */
/* Codec descriptor */
static kobj_method_t m3_codec_methods[] = {
-KOBJMETHOD(ac97_init, m3_initcd),
-KOBJMETHOD(ac97_read, m3_rdcd),
-KOBJMETHOD(ac97_write, m3_wrcd),
-{ 0, 0 }
+ KOBJMETHOD(ac97_init, m3_initcd),
+ KOBJMETHOD(ac97_read, m3_rdcd),
+ KOBJMETHOD(ac97_write, m3_wrcd),
+ { 0, 0 }
};
AC97_DECLARE(m3_codec);
@@ -214,46 +214,46 @@
/* channel descriptors */
static u_int32_t m3_playfmt[] = {
-AFMT_U8,
-AFMT_STEREO | AFMT_U8,
-AFMT_S16_LE,
-AFMT_STEREO | AFMT_S16_LE,
-0
+ AFMT_U8,
+ AFMT_STEREO | AFMT_U8,
+ AFMT_S16_LE,
+ AFMT_STEREO | AFMT_S16_LE,
+ 0
};
static struct pcmchan_caps m3_playcaps = {8000, 48000, m3_playfmt, 0};
static kobj_method_t m3_pch_methods[] = {
-KOBJMETHOD(channel_init, m3_pchan_init),
-KOBJMETHOD(channel_setformat, m3_pchan_setformat),
-KOBJMETHOD(channel_setspeed, m3_pchan_setspeed),
-KOBJMETHOD(channel_setblocksize, m3_pchan_setblocksize),
-KOBJMETHOD(channel_trigger, m3_pchan_trigger),
-KOBJMETHOD(channel_getptr, m3_pchan_getptr),
-KOBJMETHOD(channel_getcaps, m3_pchan_getcaps),
-KOBJMETHOD(channel_free, m3_pchan_free),
-{ 0, 0 }
+ KOBJMETHOD(channel_init, m3_pchan_init),
+ KOBJMETHOD(channel_setformat, m3_pchan_setformat),
+ KOBJMETHOD(channel_setspeed, m3_pchan_setspeed),
+ KOBJMETHOD(channel_setblocksize, m3_pchan_setblocksize),
+ KOBJMETHOD(channel_trigger, m3_pchan_trigger),
+ KOBJMETHOD(channel_getptr, m3_pchan_getptr),
+ KOBJMETHOD(channel_getcaps, m3_pchan_getcaps),
+ KOBJMETHOD(channel_free, m3_pchan_free),
+ { 0, 0 }
};
CHANNEL_DECLARE(m3_pch);
static u_int32_t m3_recfmt[] = {
-AFMT_U8,
-AFMT_STEREO | AFMT_U8,
-AFMT_S16_LE,
-AFMT_STEREO | AFMT_S16_LE,
-0
+ AFMT_U8,
+ AFMT_STEREO | AFMT_U8,
+ AFMT_S16_LE,
+ AFMT_STEREO | AFMT_S16_LE,
+ 0
};
static struct pcmchan_caps m3_reccaps = {8000, 48000, m3_recfmt, 0};
static kobj_method_t m3_rch_methods[] = {
-KOBJMETHOD(channel_init, m3_rchan_init),
-KOBJMETHOD(channel_setformat, m3_rchan_setformat),
-KOBJMETHOD(channel_setspeed, m3_rchan_setspeed),
-KOBJMETHOD(channel_setblocksize, m3_rchan_setblocksize),
-KOBJMETHOD(channel_trigger, m3_rchan_trigger),
-KOBJMETHOD(channel_getptr, m3_rchan_getptr),
-KOBJMETHOD(channel_getcaps, m3_rchan_getcaps),
-KOBJMETHOD(channel_free, m3_rchan_free),
-{ 0, 0 }
+ KOBJMETHOD(channel_init, m3_rchan_init),
+ KOBJMETHOD(channel_setformat, m3_rchan_setformat),
+ KOBJMETHOD(channel_setspeed, m3_rchan_setspeed),
+ KOBJMETHOD(channel_setblocksize, m3_rchan_setblocksize),
+ KOBJMETHOD(channel_trigger, m3_rchan_trigger),
+ KOBJMETHOD(channel_getptr, m3_rchan_getptr),
+ KOBJMETHOD(channel_getcaps, m3_rchan_getcaps),
+ KOBJMETHOD(channel_free, m3_rchan_free),
+ { 0, 0 }
};
CHANNEL_DECLARE(m3_rch);
@@ -266,40 +266,44 @@
#define m3_wr_1(sc, regno, data) bus_space_write_1(sc->st, sc->sh, regno, data)
#define m3_wr_2(sc, regno, data) bus_space_write_2(sc->st, sc->sh, regno, data)
#define m3_wr_4(sc, regno, data) bus_space_write_4(sc->st, sc->sh, regno, data)
-#define m3_rd_assp_code(sc, index) m3_rd_assp(sc, MEMTYPE_INTERNAL_CODE, index)
-#define m3_wr_assp_code(sc, index, data) m3_wr_assp(sc, MEMTYPE_INTERNAL_CODE, index, data)
-#define m3_rd_assp_data(sc, index) m3_rd_assp(sc, MEMTYPE_INTERNAL_DATA, index)
-#define m3_wr_assp_data(sc, index, data) m3_wr_assp(sc, MEMTYPE_INTERNAL_DATA, index, data)
+#define m3_rd_assp_code(sc, index) \
+ m3_rd_assp(sc, MEMTYPE_INTERNAL_CODE, index)
+#define m3_wr_assp_code(sc, index, data) \
+ m3_wr_assp(sc, MEMTYPE_INTERNAL_CODE, index, data)
+#define m3_rd_assp_data(sc, index) \
+ m3_rd_assp(sc, MEMTYPE_INTERNAL_DATA, index)
+#define m3_wr_assp_data(sc, index, data) \
+ m3_wr_assp(sc, MEMTYPE_INTERNAL_DATA, index, data)
static __inline u_int16_t
m3_rd_assp(struct sc_info *sc, u_int16_t region, u_int16_t index)
{
-m3_wr_2(sc, DSP_PORT_MEMORY_TYPE, region & MEMTYPE_MASK);
-m3_wr_2(sc, DSP_PORT_MEMORY_INDEX, index);
-return m3_rd_2(sc, DSP_PORT_MEMORY_DATA);
+ m3_wr_2(sc, DSP_PORT_MEMORY_TYPE, region & MEMTYPE_MASK);
+ m3_wr_2(sc, DSP_PORT_MEMORY_INDEX, index);
+ return m3_rd_2(sc, DSP_PORT_MEMORY_DATA);
}
static __inline void
m3_wr_assp(struct sc_info *sc, u_int16_t region, u_int16_t index,
-u_int16_t data)
+ u_int16_t data)
{
-m3_wr_2(sc, DSP_PORT_MEMORY_TYPE, region & MEMTYPE_MASK);
-m3_wr_2(sc, DSP_PORT_MEMORY_INDEX, index);
-m3_wr_2(sc, DSP_PORT_MEMORY_DATA, data);
+ m3_wr_2(sc, DSP_PORT_MEMORY_TYPE, region & MEMTYPE_MASK);
+ m3_wr_2(sc, DSP_PORT_MEMORY_INDEX, index);
+ m3_wr_2(sc, DSP_PORT_MEMORY_DATA, data);
}
static __inline int
m3_wait(struct sc_info *sc)
{
-int i;
+ int i;
-for (i=0 ; i<20 ; i++) {
-if ((m3_rd_1(sc, CODEC_STATUS) & 1) == 0) {
-return 0;
-}
-DELAY(2);
-}
-return -1;
+ for (i=0 ; i<20 ; i++) {
+ if ((m3_rd_1(sc, CODEC_STATUS) & 1) == 0) {
+ return 0;
+ }
+ DELAY(2);
+ }
+ return -1;
}
/* -------------------------------------------------------------------- */
@@ -308,49 +312,49 @@
static int
m3_initcd(kobj_t kobj, void *devinfo)
{
-struct sc_info *sc = (struct sc_info *)devinfo;
-u_int32_t data;
+ struct sc_info *sc = (struct sc_info *)devinfo;
+ u_int32_t data;
-M3_DEBUG(CALL, ("m3_initcdn"));
+ M3_DEBUG(CALL, ("m3_initcd\n"));
-/* init ac-link */
+ /* init ac-link */
-data = m3_rd_1(sc, CODEC_COMMAND);
-return ((data & 0x1) ? 0 : 1);
+ data = m3_rd_1(sc, CODEC_COMMAND);
+ return ((data & 0x1) ? 0 : 1);
}
static int
m3_rdcd(kobj_t kobj, void *devinfo, int regno)
{
-struct sc_info *sc = (struct sc_info *)devinfo;
-u_int32_t data;
+ struct sc_info *sc = (struct sc_info *)devinfo;
+ u_int32_t data;
-if (m3_wait(sc)) {
-device_printf(sc->dev, "m3_rdcd timed out.n");
-return -1;
-}
-m3_wr_1(sc, CODEC_COMMAND, (regno & 0x7f) | 0x80);
-DELAY(50); /* ac97 cycle = 20.8 usec */
-if (m3_wait(sc)) {
-device_printf(sc->dev, "m3_rdcd timed out.n");
-return -1;
-}
-data = m3_rd_2(sc, CODEC_DATA);
-return data;
+ if (m3_wait(sc)) {
+ device_printf(sc->dev, "m3_rdcd timed out.\n");
+ return -1;
+ }
+ m3_wr_1(sc, CODEC_COMMAND, (regno & 0x7f) | 0x80);
+ DELAY(50); /* ac97 cycle = 20.8 usec */
+ if (m3_wait(sc)) {
+ device_printf(sc->dev, "m3_rdcd timed out.\n");
+ return -1;
+ }
+ data = m3_rd_2(sc, CODEC_DATA);
+ return data;
}
static int
m3_wrcd(kobj_t kobj, void *devinfo, int regno, u_int32_t data)
{
-struct sc_info *sc = (struct sc_info *)devinfo;
-if (m3_wait(sc)) {
-device_printf(sc->dev, "m3_wrcd timed out.n");
-return -1;;
-}
-m3_wr_2(sc, CODEC_DATA, data);
-m3_wr_1(sc, CODEC_COMMAND, regno & 0x7f);
-DELAY(50); /* ac97 cycle = 20.8 usec */
-return 0;
+ struct sc_info *sc = (struct sc_info *)devinfo;
+ if (m3_wait(sc)) {
+ device_printf(sc->dev, "m3_wrcd timed out.\n");
+ return -1;;
+ }
+ m3_wr_2(sc, CODEC_DATA, data);
+ m3_wr_1(sc, CODEC_COMMAND, regno & 0x7f);
+ DELAY(50); /* ac97 cycle = 20.8 usec */
+ return 0;
}
/* -------------------------------------------------------------------- */
@@ -362,347 +366,350 @@
static void *
m3_pchan_init(kobj_t kobj, void *devinfo, struct snd_dbuf *b, struct pcm_channel *c, int dir)
{
-struct sc_info *sc = devinfo;
-struct sc_pchinfo *ch;
-u_int32_t bus_addr, i;
-int idx, data_bytes, dac_data;
-int dsp_in_size, dsp_out_size, dsp_in_buf, dsp_out_buf;
-
-M3_LOCK(sc);
-idx = sc->pch_cnt; /* dac instance number, no active reuse! */
-M3_DEBUG(CHANGE, ("m3_pchan_init(dac=%d)n", idx));
-
-if (dir != PCMDIR_PLAY) {
-M3_UNLOCK(sc);
-device_printf(sc->dev, "m3_pchan_init not PCMDIR_PLAYn");
-return (NULL);
-}
-
-data_bytes = (((MINISRC_TMP_BUFFER_SIZE & ~1) +
-(MINISRC_IN_BUFFER_SIZE & ~1) +
-(MINISRC_OUT_BUFFER_SIZE & ~1) + 4) + 255) &~ 255;
-dac_data = 0x1100 + (data_bytes * idx);
-
-dsp_in_size = MINISRC_IN_BUFFER_SIZE - (0x20 * 2);
-dsp_out_size = MINISRC_OUT_BUFFER_SIZE - (0x20 * 2);
-dsp_in_buf = dac_data + (MINISRC_TMP_BUFFER_SIZE/2);
-dsp_out_buf = dsp_in_buf + (dsp_in_size/2) + 1;
-
-ch = &sc->pch[idx];
-ch->dac_idx = idx;
-ch->dac_data = dac_data;
-if (ch->dac_data + data_bytes/2 >= 0x1c00) {
-M3_UNLOCK(sc);
-device_printf(sc->dev, "m3_pchan_init: revb mem exhaustedn");
-return (NULL);
-}
-
-ch->buffer = b;
-ch->parent = sc;
-ch->channel = c;
-ch->fmt = AFMT_U8;
-ch->spd = DSP_DEFAULT_SPEED;
-M3_UNLOCK(sc); /* XXX */
-if (sndbuf_alloc(ch->buffer, sc->parent_dmat, sc->bufsz) != 0) {
-device_printf(sc->dev, "m3_pchan_init chn_allocbuf failedn");
-return (NULL);
-}
-M3_LOCK(sc);
-ch->bufsize = sndbuf_getsize(ch->buffer);
-
-/* host dma buffer pointers */
-bus_addr = sndbuf_getbufaddr(ch->buffer);
-if (bus_addr & 3) {
-device_printf(sc->dev, "m3_pchan_init unaligned bus_addrn");
-bus_addr = (bus_addr + 4) & ~3;
-}
-m3_wr_assp_data(sc, ch->dac_data + CDATA_HOST_SRC_ADDRL, LO(bus_addr));
-m3_wr_assp_data(sc, ch->dac_data + CDATA_HOST_SRC_ADDRH, HI(bus_addr));
-m3_wr_assp_data(sc, ch->dac_data + CDATA_HOST_SRC_END_PLUS_1L,
-LO(bus_addr + ch->bufsize));
-m3_wr_assp_data(sc, ch->dac_data + CDATA_HOST_SRC_END_PLUS_1H,
-HI(bus_addr + ch->bufsize));
-m3_wr_assp_data(sc, ch->dac_data + CDATA_HOST_SRC_CURRENTL,
-LO(bus_addr));
-m3_wr_assp_data(sc, ch->dac_data + CDATA_HOST_SRC_CURRENTH,
-HI(bus_addr));
-
-/* dsp buffers */
-m3_wr_assp_data(sc, ch->dac_data + CDATA_IN_BUF_BEGIN, dsp_in_buf);
-m3_wr_assp_data(sc, ch->dac_data + CDATA_IN_BUF_END_PLUS_1,
-dsp_in_buf + dsp_in_size/2);
-m3_wr_assp_data(sc, ch->dac_data + CDATA_IN_BUF_HEAD, dsp_in_buf);
-m3_wr_assp_data(sc, ch->dac_data + CDATA_IN_BUF_TAIL, dsp_in_buf);
-m3_wr_assp_data(sc, ch->dac_data + CDATA_OUT_BUF_BEGIN, dsp_out_buf);
-m3_wr_assp_data(sc, ch->dac_data + CDATA_OUT_BUF_END_PLUS_1,
-dsp_out_buf + dsp_out_size/2);
-m3_wr_assp_data(sc, ch->dac_data + CDATA_OUT_BUF_HEAD, dsp_out_buf);
-m3_wr_assp_data(sc, ch->dac_data + CDATA_OUT_BUF_TAIL, dsp_out_buf);
-
-/* some per client initializers */
-m3_wr_assp_data(sc, ch->dac_data + SRC3_DIRECTION_OFFSET + 12,
-ch->dac_data + 40 + 8);
-m3_wr_assp_data(sc, ch->dac_data + SRC3_DIRECTION_OFFSET + 19,
-0x400 + MINISRC_COEF_LOC);
-/* enable or disable low pass filter? (0xff if rate> 45000) */
-m3_wr_assp_data(sc, ch->dac_data + SRC3_DIRECTION_OFFSET + 22, 0);
-/* tell it which way dma is going? */
-m3_wr_assp_data(sc, ch->dac_data + CDATA_DMA_CONTROL,
-DMACONTROL_AUTOREPEAT + DMAC_PAGE3_SELECTOR +
-DMAC_BLOCKF_SELECTOR);
-
-/* set an armload of static initializers */
-for(i = 0 ; i < (sizeof(pv) / sizeof(pv[0])) ; i++) {
-m3_wr_assp_data(sc, ch->dac_data + pv[i].addr, pv[i].val);
-}
-
-/* put us in the packed task lists */
-m3_wr_assp_data(sc, KDATA_INSTANCE0_MINISRC +
-(sc->pch_cnt + sc->rch_cnt),
-ch->dac_data >> DP_SHIFT_COUNT);
-m3_wr_assp_data(sc, KDATA_DMA_XFER0 + (sc->pch_cnt + sc->rch_cnt),
-ch->dac_data >> DP_SHIFT_COUNT);
-m3_wr_assp_data(sc, KDATA_MIXER_XFER0 + sc->pch_cnt,
-ch->dac_data >> DP_SHIFT_COUNT);
-
-/* gotta start before stop */
-m3_pchan_trigger_locked(NULL, ch, PCMTRIG_START);
-/* silence noise on load */
-m3_pchan_trigger_locked(NULL, ch, PCMTRIG_STOP);
+ struct sc_info *sc = devinfo;
+ struct sc_pchinfo *ch;
+ u_int32_t bus_addr, i;
+ int idx, data_bytes, dac_data;
+ int dsp_in_size, dsp_out_size, dsp_in_buf, dsp_out_buf;
+
+ M3_LOCK(sc);
+ idx = sc->pch_cnt; /* dac instance number, no active reuse! */
+ M3_DEBUG(CHANGE, ("m3_pchan_init(dac=%d)\n", idx));
+
+ if (dir != PCMDIR_PLAY) {
+ M3_UNLOCK(sc);
+ device_printf(sc->dev, "m3_pchan_init not PCMDIR_PLAY\n");
+ return (NULL);
+ }
+
+ data_bytes = (((MINISRC_TMP_BUFFER_SIZE & ~1) +
+ (MINISRC_IN_BUFFER_SIZE & ~1) +
+ (MINISRC_OUT_BUFFER_SIZE & ~1) + 4) + 255) &~ 255;
+ dac_data = 0x1100 + (data_bytes * idx);
+
+ dsp_in_size = MINISRC_IN_BUFFER_SIZE - (0x20 * 2);
+ dsp_out_size = MINISRC_OUT_BUFFER_SIZE - (0x20 * 2);
+ dsp_in_buf = dac_data + (MINISRC_TMP_BUFFER_SIZE/2);
+ dsp_out_buf = dsp_in_buf + (dsp_in_size/2) + 1;
+
+ ch = &sc->pch[idx];
+ ch->dac_idx = idx;
+ ch->dac_data = dac_data;
+ if (ch->dac_data + data_bytes/2 >= 0x1c00) {
+ M3_UNLOCK(sc);
+ device_printf(sc->dev, "m3_pchan_init: revb mem exhausted\n");
+ return (NULL);
+ }
+
+ ch->buffer = b;
+ ch->parent = sc;
+ ch->channel = c;
+ ch->fmt = AFMT_U8;
+ ch->spd = DSP_DEFAULT_SPEED;
+ M3_UNLOCK(sc); /* XXX */
+ if (sndbuf_alloc(ch->buffer, sc->parent_dmat, 0, sc->bufsz) != 0) {
+ device_printf(sc->dev, "m3_pchan_init chn_allocbuf failed\n");
+ return (NULL);
+ }
+ M3_LOCK(sc);
+ ch->bufsize = sndbuf_getsize(ch->buffer);
+
+ /* host dma buffer pointers */
+ bus_addr = sndbuf_getbufaddr(ch->buffer);
+ if (bus_addr & 3) {
+ device_printf(sc->dev, "m3_pchan_init unaligned bus_addr\n");
+ bus_addr = (bus_addr + 4) & ~3;
+ }
+ m3_wr_assp_data(sc, ch->dac_data + CDATA_HOST_SRC_ADDRL, LO(bus_addr));
+ m3_wr_assp_data(sc, ch->dac_data + CDATA_HOST_SRC_ADDRH, HI(bus_addr));
+ m3_wr_assp_data(sc, ch->dac_data + CDATA_HOST_SRC_END_PLUS_1L,
+ LO(bus_addr + ch->bufsize));
+ m3_wr_assp_data(sc, ch->dac_data + CDATA_HOST_SRC_END_PLUS_1H,
+ HI(bus_addr + ch->bufsize));
+ m3_wr_assp_data(sc, ch->dac_data + CDATA_HOST_SRC_CURRENTL,
+ LO(bus_addr));
+ m3_wr_assp_data(sc, ch->dac_data + CDATA_HOST_SRC_CURRENTH,
+ HI(bus_addr));
+
+ /* dsp buffers */
+ m3_wr_assp_data(sc, ch->dac_data + CDATA_IN_BUF_BEGIN, dsp_in_buf);
+ m3_wr_assp_data(sc, ch->dac_data + CDATA_IN_BUF_END_PLUS_1,
+ dsp_in_buf + dsp_in_size/2);
+ m3_wr_assp_data(sc, ch->dac_data + CDATA_IN_BUF_HEAD, dsp_in_buf);
+ m3_wr_assp_data(sc, ch->dac_data + CDATA_IN_BUF_TAIL, dsp_in_buf);
+ m3_wr_assp_data(sc, ch->dac_data + CDATA_OUT_BUF_BEGIN, dsp_out_buf);
+ m3_wr_assp_data(sc, ch->dac_data + CDATA_OUT_BUF_END_PLUS_1,
+ dsp_out_buf + dsp_out_size/2);
+ m3_wr_assp_data(sc, ch->dac_data + CDATA_OUT_BUF_HEAD, dsp_out_buf);
+ m3_wr_assp_data(sc, ch->dac_data + CDATA_OUT_BUF_TAIL, dsp_out_buf);
+
+ /* some per client initializers */
+ m3_wr_assp_data(sc, ch->dac_data + SRC3_DIRECTION_OFFSET + 12,
+ ch->dac_data + 40 + 8);
+ m3_wr_assp_data(sc, ch->dac_data + SRC3_DIRECTION_OFFSET + 19,
+ 0x400 + MINISRC_COEF_LOC);
+ /* enable or disable low pass filter? (0xff if rate> 45000) */
+ m3_wr_assp_data(sc, ch->dac_data + SRC3_DIRECTION_OFFSET + 22, 0);
+ /* tell it which way dma is going? */
+ m3_wr_assp_data(sc, ch->dac_data + CDATA_DMA_CONTROL,
+ DMACONTROL_AUTOREPEAT + DMAC_PAGE3_SELECTOR +
+ DMAC_BLOCKF_SELECTOR);
+
+ /* set an armload of static initializers */
+ for(i = 0 ; i < (sizeof(pv) / sizeof(pv[0])) ; i++) {
+ m3_wr_assp_data(sc, ch->dac_data + pv[i].addr, pv[i].val);
+ }
+
+ /* put us in the packed task lists */
+ m3_wr_assp_data(sc, KDATA_INSTANCE0_MINISRC +
+ (sc->pch_cnt + sc->rch_cnt),
+ ch->dac_data >> DP_SHIFT_COUNT);
+ m3_wr_assp_data(sc, KDATA_DMA_XFER0 + (sc->pch_cnt + sc->rch_cnt),
+ ch->dac_data >> DP_SHIFT_COUNT);
+ m3_wr_assp_data(sc, KDATA_MIXER_XFER0 + sc->pch_cnt,
+ ch->dac_data >> DP_SHIFT_COUNT);
+
+ /* gotta start before stop */
+ m3_pchan_trigger_locked(NULL, ch, PCMTRIG_START);
+ /* silence noise on load */
+ m3_pchan_trigger_locked(NULL, ch, PCMTRIG_STOP);
-sc->pch_cnt++;
-M3_UNLOCK(sc);
+ sc->pch_cnt++;
+ M3_UNLOCK(sc);
-return (ch);
+ return (ch);
}
static int
m3_pchan_free(kobj_t kobj, void *chdata)
{
-struct sc_pchinfo *ch = chdata;
-struct sc_info *sc = ch->parent;
+ struct sc_pchinfo *ch = chdata;
+ struct sc_info *sc = ch->parent;
-M3_LOCK(sc);
-M3_DEBUG(CHANGE, ("m3_pchan_free(dac=%d)n", ch->dac_idx));
+ M3_LOCK(sc);
+ M3_DEBUG(CHANGE, ("m3_pchan_free(dac=%d)\n", ch->dac_idx));
-/*
-* should remove this exact instance from the packed lists, but all
-* are released at once (and in a stopped state) so this is ok.
-*/
-m3_wr_assp_data(sc, KDATA_INSTANCE0_MINISRC +
-(sc->pch_cnt - 1) + sc->rch_cnt, 0);
-m3_wr_assp_data(sc, KDATA_DMA_XFER0 +
-(sc->pch_cnt - 1) + sc->rch_cnt, 0);
-m3_wr_assp_data(sc, KDATA_MIXER_XFER0 + (sc->pch_cnt-1), 0);
-sc->pch_cnt--;
-M3_UNLOCK(sc);
+ /*
+ * should remove this exact instance from the packed lists, but all
+ * are released at once (and in a stopped state) so this is ok.
+ */
+ m3_wr_assp_data(sc, KDATA_INSTANCE0_MINISRC +
+ (sc->pch_cnt - 1) + sc->rch_cnt, 0);
+ m3_wr_assp_data(sc, KDATA_DMA_XFER0 +
+ (sc->pch_cnt - 1) + sc->rch_cnt, 0);
+ m3_wr_assp_data(sc, KDATA_MIXER_XFER0 + (sc->pch_cnt-1), 0);
+ sc->pch_cnt--;
+ M3_UNLOCK(sc);
-return (0);
+ return (0);
}
static int
m3_pchan_setformat(kobj_t kobj, void *chdata, u_int32_t format)
{
-struct sc_pchinfo *ch = chdata;
-struct sc_info *sc = ch->parent;
-u_int32_t data;
-
-M3_LOCK(sc);
-M3_DEBUG(CHANGE,
-("m3_pchan_setformat(dac=%d, format=0x%x{%s-%s})n",
-ch->dac_idx, format,
-format & (AFMT_U8|AFMT_S8) ? "8bit":"16bit",
-format & AFMT_STEREO ? "STEREO":"MONO"));
-
-/* mono word */
-data = (format & AFMT_STEREO) ? 0 : 1;
-m3_wr_assp_data(sc, ch->dac_data + SRC3_MODE_OFFSET, data);
-
-/* 8bit word */
-data = ((format & AFMT_U8) || (format & AFMT_S8)) ? 1 : 0;
-m3_wr_assp_data(sc, ch->dac_data + SRC3_WORD_LENGTH_OFFSET, data);
+ struct sc_pchinfo *ch = chdata;
+ struct sc_info *sc = ch->parent;
+ u_int32_t data;
+
+ M3_LOCK(sc);
+ M3_DEBUG(CHANGE,
+ ("m3_pchan_setformat(dac=%d, format=0x%x{%s-%s})\n",
+ ch->dac_idx, format,
+ format & (AFMT_U8|AFMT_S8) ? "8bit":"16bit",
+ format & AFMT_STEREO ? "STEREO":"MONO"));
+
+ /* mono word */
+ data = (format & AFMT_STEREO) ? 0 : 1;
+ m3_wr_assp_data(sc, ch->dac_data + SRC3_MODE_OFFSET, data);
+
+ /* 8bit word */
+ data = ((format & AFMT_U8) || (format & AFMT_S8)) ? 1 : 0;
+ m3_wr_assp_data(sc, ch->dac_data + SRC3_WORD_LENGTH_OFFSET, data);
-ch->fmt = format;
-M3_UNLOCK(sc);
+ ch->fmt = format;
+ M3_UNLOCK(sc);
-return (0);
+ return (0);
}
static int
m3_pchan_setspeed(kobj_t kobj, void *chdata, u_int32_t speed)
{
-struct sc_pchinfo *ch = chdata;
-struct sc_info *sc = ch->parent;
-u_int32_t freq;
-
-M3_LOCK(sc);
-M3_DEBUG(CHANGE, ("m3_pchan_setspeed(dac=%d, speed=%d)n",
-ch->dac_idx, speed));
+ struct sc_pchinfo *ch = chdata;
+ struct sc_info *sc = ch->parent;
+ u_int32_t freq;
+
+ M3_LOCK(sc);
+ M3_DEBUG(CHANGE, ("m3_pchan_setspeed(dac=%d, speed=%d)\n",
+ ch->dac_idx, speed));
+
+ if ((freq = ((speed << 15) + 24000) / 48000) != 0) {
+ freq--;
+ }
+
+ m3_wr_assp_data(sc, ch->dac_data + CDATA_FREQUENCY, freq);
+ ch->spd = speed;
+ M3_UNLOCK(sc);
-if ((freq = ((speed << 15) + 24000) / 48000) != 0) {
-freq--;
-}
-
-m3_wr_assp_data(sc, ch->dac_data + CDATA_FREQUENCY, freq);
-ch->spd = speed;
-M3_UNLOCK(sc);
-
-/* return closest possible speed */
-return (speed);
+ /* return closest possible speed */
+ return (speed);
}
static int
m3_pchan_setblocksize(kobj_t kobj, void *chdata, u_int32_t blocksize)
{
-struct sc_pchinfo *ch = chdata;
+ struct sc_pchinfo *ch = chdata;
-M3_DEBUG(CHANGE, ("m3_pchan_setblocksize(dac=%d, blocksize=%d)n",
-ch->dac_idx, blocksize));
+ M3_DEBUG(CHANGE, ("m3_pchan_setblocksize(dac=%d, blocksize=%d)\n",
+ ch->dac_idx, blocksize));
-return (sndbuf_getblksz(ch->buffer));
+ return (sndbuf_getblksz(ch->buffer));
}
static int
m3_pchan_trigger(kobj_t kobj, void *chdata, int go)
{
-struct sc_pchinfo *ch = chdata;
-struct sc_info *sc = ch->parent;
-int ret;
-
-M3_LOCK(sc);
-ret = m3_pchan_trigger_locked(kobj, chdata, go);
-M3_UNLOCK(sc);
+ struct sc_pchinfo *ch = chdata;
+ struct sc_info *sc = ch->parent;
+ int ret;
+
+ if (!PCMTRIG_COMMON(go))
+ return (0);
+
+ M3_LOCK(sc);
+ ret = m3_pchan_trigger_locked(kobj, chdata, go);
+ M3_UNLOCK(sc);
-return (ret);
+ return (ret);
}
static int
m3_chan_active(struct sc_info *sc)
{
-int i, ret;
+ int i, ret;
-ret = 0;
+ ret = 0;
-for (i = 0; i < sc->pch_cnt; i++)
-ret += sc->pch[i].active;
+ for (i = 0; i < sc->pch_cnt; i++)
+ ret += sc->pch[i].active;
-for (i = 0; i < sc->rch_cnt; i++)
-ret += sc->rch[i].active;
+ for (i = 0; i < sc->rch_cnt; i++)
+ ret += sc->rch[i].active;
-return (ret);
+ return (ret);
}
static int
m3_pchan_trigger_locked(kobj_t kobj, void *chdata, int go)
{
-struct sc_pchinfo *ch = chdata;
-struct sc_info *sc = ch->parent;
-u_int32_t data;
-
-M3_LOCK_ASSERT(sc);
-M3_DEBUG(go == PCMTRIG_START ? CHANGE :
-go == PCMTRIG_STOP ? CHANGE :
-go == PCMTRIG_ABORT ? CHANGE :
-CALL,
-("m3_pchan_trigger(dac=%d, go=0x%x{%s})n", ch->dac_idx, go,
-go == PCMTRIG_START ? "PCMTRIG_START" :
-go == PCMTRIG_STOP ? "PCMTRIG_STOP" :
-go == PCMTRIG_ABORT ? "PCMTRIG_ABORT" : "ignore"));
-
-switch(go) {
-case PCMTRIG_START:
-if (ch->active) {
-return 0;
-}
-ch->active = 1;
-ch->ptr = 0;
-ch->prevptr = 0;
-sc->pch_active_cnt++;
-
-/*[[inc_timer_users]]*/
-if (m3_chan_active(sc) == 1) {
-m3_wr_assp_data(sc, KDATA_TIMER_COUNT_RELOAD, 240);
-m3_wr_assp_data(sc, KDATA_TIMER_COUNT_CURRENT, 240);
-data = m3_rd_2(sc, HOST_INT_CTRL);
-m3_wr_2(sc, HOST_INT_CTRL, data | CLKRUN_GEN_ENABLE);
-}
-
-m3_wr_assp_data(sc, ch->dac_data + CDATA_INSTANCE_READY, 1);
-m3_wr_assp_data(sc, KDATA_MIXER_TASK_NUMBER,
-sc->pch_active_cnt);
-break;
-
-case PCMTRIG_STOP:
-case PCMTRIG_ABORT:
-if (ch->active == 0) {
-return 0;
-}
-ch->active = 0;
-sc->pch_active_cnt--;
-
-/* XXX should the channel be drained? */
-/*[[dec_timer_users]]*/
-if (m3_chan_active(sc) == 0) {
-m3_wr_assp_data(sc, KDATA_TIMER_COUNT_RELOAD, 0);
-m3_wr_assp_data(sc, KDATA_TIMER_COUNT_CURRENT, 0);
-data = m3_rd_2(sc, HOST_INT_CTRL);
-m3_wr_2(sc, HOST_INT_CTRL, data & ~CLKRUN_GEN_ENABLE);
-}
-
-m3_wr_assp_data(sc, ch->dac_data + CDATA_INSTANCE_READY, 0);
-m3_wr_assp_data(sc, KDATA_MIXER_TASK_NUMBER,
-sc->pch_active_cnt);
-break;
-
-case PCMTRIG_EMLDMAWR:
-/* got play irq, transfer next buffer - ignore if using dma */
-case PCMTRIG_EMLDMARD:
-/* got rec irq, transfer next buffer - ignore if using dma */
-default:
-break;
-}
-return 0;
+ struct sc_pchinfo *ch = chdata;
+ struct sc_info *sc = ch->parent;
+ u_int32_t data;
+
+ M3_LOCK_ASSERT(sc);
+ M3_DEBUG(go == PCMTRIG_START ? CHANGE :
+ go == PCMTRIG_STOP ? CHANGE :
+ go == PCMTRIG_ABORT ? CHANGE :
+ CALL,
+ ("m3_pchan_trigger(dac=%d, go=0x%x{%s})\n", ch->dac_idx, go,
+ go == PCMTRIG_START ? "PCMTRIG_START" :
+ go == PCMTRIG_STOP ? "PCMTRIG_STOP" :
+ go == PCMTRIG_ABORT ? "PCMTRIG_ABORT" : "ignore"));
+
+ switch(go) {
+ case PCMTRIG_START:
+ if (ch->active) {
+ return 0;
+ }
+ ch->active = 1;
+ ch->ptr = 0;
+ ch->prevptr = 0;
+ sc->pch_active_cnt++;
+
+ /*[[inc_timer_users]]*/
+ if (m3_chan_active(sc) == 1) {
+ m3_wr_assp_data(sc, KDATA_TIMER_COUNT_RELOAD, 240);
+ m3_wr_assp_data(sc, KDATA_TIMER_COUNT_CURRENT, 240);
+ data = m3_rd_2(sc, HOST_INT_CTRL);
+ m3_wr_2(sc, HOST_INT_CTRL, data | CLKRUN_GEN_ENABLE);
+ }
+
+ m3_wr_assp_data(sc, ch->dac_data + CDATA_INSTANCE_READY, 1);
+ m3_wr_assp_data(sc, KDATA_MIXER_TASK_NUMBER,
+ sc->pch_active_cnt);
+ break;
+
+ case PCMTRIG_STOP:
+ case PCMTRIG_ABORT:
+ if (ch->active == 0) {
+ return 0;
+ }
+ ch->active = 0;
+ sc->pch_active_cnt--;
+
+ /* XXX should the channel be drained? */
+ /*[[dec_timer_users]]*/
+ if (m3_chan_active(sc) == 0) {
+ m3_wr_assp_data(sc, KDATA_TIMER_COUNT_RELOAD, 0);
+ m3_wr_assp_data(sc, KDATA_TIMER_COUNT_CURRENT, 0);
+ data = m3_rd_2(sc, HOST_INT_CTRL);
+ m3_wr_2(sc, HOST_INT_CTRL, data & ~CLKRUN_GEN_ENABLE);
+ }
+
+ m3_wr_assp_data(sc, ch->dac_data + CDATA_INSTANCE_READY, 0);
+ m3_wr_assp_data(sc, KDATA_MIXER_TASK_NUMBER,
+ sc->pch_active_cnt);
+ break;
+
+ case PCMTRIG_EMLDMAWR:
+ /* got play irq, transfer next buffer - ignore if using dma */
+ case PCMTRIG_EMLDMARD:
+ /* got rec irq, transfer next buffer - ignore if using dma */
+ default:
+ break;
+ }
+ return 0;
}
static u_int32_t
m3_pchan_getptr_internal(struct sc_pchinfo *ch)
{
-struct sc_info *sc = ch->parent;
-u_int32_t hi, lo, bus_base, bus_crnt;
+ struct sc_info *sc = ch->parent;
+ u_int32_t hi, lo, bus_base, bus_crnt;
-bus_base = sndbuf_getbufaddr(ch->buffer);
-hi = m3_rd_assp_data(sc, ch->dac_data + CDATA_HOST_SRC_CURRENTH);
-lo = m3_rd_assp_data(sc, ch->dac_data + CDATA_HOST_SRC_CURRENTL);
-bus_crnt = lo | (hi << 16);
+ bus_base = sndbuf_getbufaddr(ch->buffer);
+ hi = m3_rd_assp_data(sc, ch->dac_data + CDATA_HOST_SRC_CURRENTH);
+ lo = m3_rd_assp_data(sc, ch->dac_data + CDATA_HOST_SRC_CURRENTL);
+ bus_crnt = lo | (hi << 16);
-M3_DEBUG(CALL, ("m3_pchan_getptr(dac=%d) result=%dn",
-ch->dac_idx, bus_crnt - bus_base));
+ M3_DEBUG(CALL, ("m3_pchan_getptr(dac=%d) result=%d\n",
+ ch->dac_idx, bus_crnt - bus_base));
-return (bus_crnt - bus_base); /* current byte offset of channel */
+ return (bus_crnt - bus_base); /* current byte offset of channel */
}
static u_int32_t
m3_pchan_getptr(kobj_t kobj, void *chdata)
{
-struct sc_pchinfo *ch = chdata;
-struct sc_info *sc = ch->parent;
-u_int32_t ptr;
-
-M3_LOCK(sc);
-ptr = ch->ptr;
-M3_UNLOCK(sc);
+ struct sc_pchinfo *ch = chdata;
+ struct sc_info *sc = ch->parent;
+ u_int32_t ptr;
+
+ M3_LOCK(sc);
+ ptr = ch->ptr;
+ M3_UNLOCK(sc);
-return (ptr);
+ return (ptr);
}
static struct pcmchan_caps *
m3_pchan_getcaps(kobj_t kobj, void *chdata)
{
-struct sc_pchinfo *ch = chdata;
+ struct sc_pchinfo *ch = chdata;
-M3_DEBUG(CALL, ("m3_pchan_getcaps(dac=%d)n", ch->dac_idx));
+ M3_DEBUG(CALL, ("m3_pchan_getcaps(dac=%d)\n", ch->dac_idx));
-return &m3_playcaps;
+ return &m3_playcaps;
}
/* -------------------------------------------------------------------- */
@@ -711,320 +718,323 @@
static void *
m3_rchan_init(kobj_t kobj, void *devinfo, struct snd_dbuf *b, struct pcm_channel *c, int dir)
{
-struct sc_info *sc = devinfo;
-struct sc_rchinfo *ch;
-u_int32_t bus_addr, i;
-
-int idx, data_bytes, adc_data;
-int dsp_in_size, dsp_out_size, dsp_in_buf, dsp_out_buf;
-
-M3_LOCK(sc);
-idx = sc->rch_cnt; /* adc instance number, no active reuse! */
-M3_DEBUG(CHANGE, ("m3_rchan_init(adc=%d)n", idx));
-
-if (dir != PCMDIR_REC) {
-M3_UNLOCK(sc);
-device_printf(sc->dev, "m3_pchan_init not PCMDIR_RECn");
-return (NULL);
-}
-
-data_bytes = (((MINISRC_TMP_BUFFER_SIZE & ~1) +
-(MINISRC_IN_BUFFER_SIZE & ~1) +
-(MINISRC_OUT_BUFFER_SIZE & ~1) + 4) + 255) &~ 255;
-adc_data = 0x1100 + (data_bytes * idx) + data_bytes/2;
-dsp_in_size = MINISRC_IN_BUFFER_SIZE + (0x10 * 2);
-dsp_out_size = MINISRC_OUT_BUFFER_SIZE - (0x10 * 2);
-dsp_in_buf = adc_data + (MINISRC_TMP_BUFFER_SIZE / 2);
-dsp_out_buf = dsp_in_buf + (dsp_in_size / 2) + 1;
-
-ch = &sc->rch[idx];
-ch->adc_idx = idx;
-ch->adc_data = adc_data;
-if (ch->adc_data + data_bytes/2 >= 0x1c00) {
-M3_UNLOCK(sc);
-device_printf(sc->dev, "m3_rchan_init: revb mem exhaustedn");
-return (NULL);
-}
-
-ch->buffer = b;
-ch->parent = sc;
-ch->channel = c;
-ch->fmt = AFMT_U8;
-ch->spd = DSP_DEFAULT_SPEED;
-M3_UNLOCK(sc); /* XXX */
-if (sndbuf_alloc(ch->buffer, sc->parent_dmat, sc->bufsz) != 0) {
-device_printf(sc->dev, "m3_rchan_init chn_allocbuf failedn");
-return (NULL);
-}
-M3_LOCK(sc);
-ch->bufsize = sndbuf_getsize(ch->buffer);
-
-/* host dma buffer pointers */
-bus_addr = sndbuf_getbufaddr(ch->buffer);
-if (bus_addr & 3) {
-device_printf(sc->dev, "m3_rchan_init unaligned bus_addrn");
-bus_addr = (bus_addr + 4) & ~3;
-}
-m3_wr_assp_data(sc, ch->adc_data + CDATA_HOST_SRC_ADDRL, LO(bus_addr));
-m3_wr_assp_data(sc, ch->adc_data + CDATA_HOST_SRC_ADDRH, HI(bus_addr));
-m3_wr_assp_data(sc, ch->adc_data + CDATA_HOST_SRC_END_PLUS_1L,
-LO(bus_addr + ch->bufsize));
-m3_wr_assp_data(sc, ch->adc_data + CDATA_HOST_SRC_END_PLUS_1H,
-HI(bus_addr + ch->bufsize));
-m3_wr_assp_data(sc, ch->adc_data + CDATA_HOST_SRC_CURRENTL,
-LO(bus_addr));
-m3_wr_assp_data(sc, ch->adc_data + CDATA_HOST_SRC_CURRENTH,
-HI(bus_addr));
-
-/* dsp buffers */
-m3_wr_assp_data(sc, ch->adc_data + CDATA_IN_BUF_BEGIN, dsp_in_buf);
-m3_wr_assp_data(sc, ch->adc_data + CDATA_IN_BUF_END_PLUS_1,
-dsp_in_buf + dsp_in_size/2);
-m3_wr_assp_data(sc, ch->adc_data + CDATA_IN_BUF_HEAD, dsp_in_buf);
-m3_wr_assp_data(sc, ch->adc_data + CDATA_IN_BUF_TAIL, dsp_in_buf);
-m3_wr_assp_data(sc, ch->adc_data + CDATA_OUT_BUF_BEGIN, dsp_out_buf);
-m3_wr_assp_data(sc, ch->adc_data + CDATA_OUT_BUF_END_PLUS_1,
-dsp_out_buf + dsp_out_size/2);
-m3_wr_assp_data(sc, ch->adc_data + CDATA_OUT_BUF_HEAD, dsp_out_buf);
-m3_wr_assp_data(sc, ch->adc_data + CDATA_OUT_BUF_TAIL, dsp_out_buf);
-
-/* some per client initializers */
-m3_wr_assp_data(sc, ch->adc_data + SRC3_DIRECTION_OFFSET + 12,
-ch->adc_data + 40 + 8);
-m3_wr_assp_data(sc, ch->adc_data + CDATA_DMA_CONTROL,
-DMACONTROL_DIRECTION + DMACONTROL_AUTOREPEAT +
-DMAC_PAGE3_SELECTOR + DMAC_BLOCKF_SELECTOR);
-
-/* set an armload of static initializers */
-for(i = 0 ; i < (sizeof(rv) / sizeof(rv[0])) ; i++) {
-m3_wr_assp_data(sc, ch->adc_data + rv[i].addr, rv[i].val);
-}
-
-/* put us in the packed task lists */
-m3_wr_assp_data(sc, KDATA_INSTANCE0_MINISRC +
-(sc->pch_cnt + sc->rch_cnt),
-ch->adc_data >> DP_SHIFT_COUNT);
-m3_wr_assp_data(sc, KDATA_DMA_XFER0 + (sc->pch_cnt + sc->rch_cnt),
-ch->adc_data >> DP_SHIFT_COUNT);
-m3_wr_assp_data(sc, KDATA_ADC1_XFER0 + sc->rch_cnt,
-ch->adc_data >> DP_SHIFT_COUNT);
-
-/* gotta start before stop */
-m3_rchan_trigger_locked(NULL, ch, PCMTRIG_START);
-/* stop on init */
-m3_rchan_trigger_locked(NULL, ch, PCMTRIG_STOP);
+ struct sc_info *sc = devinfo;
+ struct sc_rchinfo *ch;
+ u_int32_t bus_addr, i;
+
+ int idx, data_bytes, adc_data;
+ int dsp_in_size, dsp_out_size, dsp_in_buf, dsp_out_buf;
+
+ M3_LOCK(sc);
+ idx = sc->rch_cnt; /* adc instance number, no active reuse! */
+ M3_DEBUG(CHANGE, ("m3_rchan_init(adc=%d)\n", idx));
+
+ if (dir != PCMDIR_REC) {
+ M3_UNLOCK(sc);
+ device_printf(sc->dev, "m3_pchan_init not PCMDIR_REC\n");
+ return (NULL);
+ }
+
+ data_bytes = (((MINISRC_TMP_BUFFER_SIZE & ~1) +
+ (MINISRC_IN_BUFFER_SIZE & ~1) +
+ (MINISRC_OUT_BUFFER_SIZE & ~1) + 4) + 255) &~ 255;
+ adc_data = 0x1100 + (data_bytes * idx) + data_bytes/2;
+ dsp_in_size = MINISRC_IN_BUFFER_SIZE + (0x10 * 2);
+ dsp_out_size = MINISRC_OUT_BUFFER_SIZE - (0x10 * 2);
+ dsp_in_buf = adc_data + (MINISRC_TMP_BUFFER_SIZE / 2);
+ dsp_out_buf = dsp_in_buf + (dsp_in_size / 2) + 1;
+
+ ch = &sc->rch[idx];
+ ch->adc_idx = idx;
+ ch->adc_data = adc_data;
+ if (ch->adc_data + data_bytes/2 >= 0x1c00) {
+ M3_UNLOCK(sc);
+ device_printf(sc->dev, "m3_rchan_init: revb mem exhausted\n");
+ return (NULL);
+ }
+
+ ch->buffer = b;
+ ch->parent = sc;
+ ch->channel = c;
+ ch->fmt = AFMT_U8;
+ ch->spd = DSP_DEFAULT_SPEED;
+ M3_UNLOCK(sc); /* XXX */
+ if (sndbuf_alloc(ch->buffer, sc->parent_dmat, 0, sc->bufsz) != 0) {
+ device_printf(sc->dev, "m3_rchan_init chn_allocbuf failed\n");
+ return (NULL);
+ }
+ M3_LOCK(sc);
+ ch->bufsize = sndbuf_getsize(ch->buffer);
+
+ /* host dma buffer pointers */
+ bus_addr = sndbuf_getbufaddr(ch->buffer);
+ if (bus_addr & 3) {
+ device_printf(sc->dev, "m3_rchan_init unaligned bus_addr\n");
+ bus_addr = (bus_addr + 4) & ~3;
+ }
+ m3_wr_assp_data(sc, ch->adc_data + CDATA_HOST_SRC_ADDRL, LO(bus_addr));
+ m3_wr_assp_data(sc, ch->adc_data + CDATA_HOST_SRC_ADDRH, HI(bus_addr));
+ m3_wr_assp_data(sc, ch->adc_data + CDATA_HOST_SRC_END_PLUS_1L,
+ LO(bus_addr + ch->bufsize));
+ m3_wr_assp_data(sc, ch->adc_data + CDATA_HOST_SRC_END_PLUS_1H,
+ HI(bus_addr + ch->bufsize));
+ m3_wr_assp_data(sc, ch->adc_data + CDATA_HOST_SRC_CURRENTL,
+ LO(bus_addr));
+ m3_wr_assp_data(sc, ch->adc_data + CDATA_HOST_SRC_CURRENTH,
+ HI(bus_addr));
+
+ /* dsp buffers */
+ m3_wr_assp_data(sc, ch->adc_data + CDATA_IN_BUF_BEGIN, dsp_in_buf);
+ m3_wr_assp_data(sc, ch->adc_data + CDATA_IN_BUF_END_PLUS_1,
+ dsp_in_buf + dsp_in_size/2);
+ m3_wr_assp_data(sc, ch->adc_data + CDATA_IN_BUF_HEAD, dsp_in_buf);
+ m3_wr_assp_data(sc, ch->adc_data + CDATA_IN_BUF_TAIL, dsp_in_buf);
+ m3_wr_assp_data(sc, ch->adc_data + CDATA_OUT_BUF_BEGIN, dsp_out_buf);
+ m3_wr_assp_data(sc, ch->adc_data + CDATA_OUT_BUF_END_PLUS_1,
+ dsp_out_buf + dsp_out_size/2);
+ m3_wr_assp_data(sc, ch->adc_data + CDATA_OUT_BUF_HEAD, dsp_out_buf);
+ m3_wr_assp_data(sc, ch->adc_data + CDATA_OUT_BUF_TAIL, dsp_out_buf);
+
+ /* some per client initializers */
+ m3_wr_assp_data(sc, ch->adc_data + SRC3_DIRECTION_OFFSET + 12,
+ ch->adc_data + 40 + 8);
+ m3_wr_assp_data(sc, ch->adc_data + CDATA_DMA_CONTROL,
+ DMACONTROL_DIRECTION + DMACONTROL_AUTOREPEAT +
+ DMAC_PAGE3_SELECTOR + DMAC_BLOCKF_SELECTOR);
+
+ /* set an armload of static initializers */
+ for(i = 0 ; i < (sizeof(rv) / sizeof(rv[0])) ; i++) {
+ m3_wr_assp_data(sc, ch->adc_data + rv[i].addr, rv[i].val);
+ }
+
+ /* put us in the packed task lists */
+ m3_wr_assp_data(sc, KDATA_INSTANCE0_MINISRC +
+ (sc->pch_cnt + sc->rch_cnt),
+ ch->adc_data >> DP_SHIFT_COUNT);
+ m3_wr_assp_data(sc, KDATA_DMA_XFER0 + (sc->pch_cnt + sc->rch_cnt),
+ ch->adc_data >> DP_SHIFT_COUNT);
+ m3_wr_assp_data(sc, KDATA_ADC1_XFER0 + sc->rch_cnt,
+ ch->adc_data >> DP_SHIFT_COUNT);
+
+ /* gotta start before stop */
+ m3_rchan_trigger_locked(NULL, ch, PCMTRIG_START);
+ /* stop on init */
+ m3_rchan_trigger_locked(NULL, ch, PCMTRIG_STOP);
-sc->rch_cnt++;
-M3_UNLOCK(sc);
+ sc->rch_cnt++;
+ M3_UNLOCK(sc);
-return (ch);
+ return (ch);
}
static int
m3_rchan_free(kobj_t kobj, void *chdata)
{
-struct sc_rchinfo *ch = chdata;
-struct sc_info *sc = ch->parent;
+ struct sc_rchinfo *ch = chdata;
+ struct sc_info *sc = ch->parent;
-M3_LOCK(sc);
-M3_DEBUG(CHANGE, ("m3_rchan_free(adc=%d)n", ch->adc_idx));
+ M3_LOCK(sc);
+ M3_DEBUG(CHANGE, ("m3_rchan_free(adc=%d)\n", ch->adc_idx));
-/*
-* should remove this exact instance from the packed lists, but all
-* are released at once (and in a stopped state) so this is ok.
-*/
-m3_wr_assp_data(sc, KDATA_INSTANCE0_MINISRC +
-(sc->rch_cnt - 1) + sc->pch_cnt, 0);
-m3_wr_assp_data(sc, KDATA_DMA_XFER0 +
-(sc->rch_cnt - 1) + sc->pch_cnt, 0);
-m3_wr_assp_data(sc, KDATA_ADC1_XFER0 + (sc->rch_cnt - 1), 0);
-sc->rch_cnt--;
-M3_UNLOCK(sc);
+ /*
+ * should remove this exact instance from the packed lists, but all
+ * are released at once (and in a stopped state) so this is ok.
+ */
+ m3_wr_assp_data(sc, KDATA_INSTANCE0_MINISRC +
+ (sc->rch_cnt - 1) + sc->pch_cnt, 0);
+ m3_wr_assp_data(sc, KDATA_DMA_XFER0 +
+ (sc->rch_cnt - 1) + sc->pch_cnt, 0);
+ m3_wr_assp_data(sc, KDATA_ADC1_XFER0 + (sc->rch_cnt - 1), 0);
+ sc->rch_cnt--;
+ M3_UNLOCK(sc);
-return (0);
+ return (0);
}
static int
m3_rchan_setformat(kobj_t kobj, void *chdata, u_int32_t format)
{
-struct sc_rchinfo *ch = chdata;
-struct sc_info *sc = ch->parent;
-u_int32_t data;
-
-M3_LOCK(sc);
-M3_DEBUG(CHANGE,
-("m3_rchan_setformat(dac=%d, format=0x%x{%s-%s})n",
-ch->adc_idx, format,
-format & (AFMT_U8|AFMT_S8) ? "8bit":"16bit",
-format & AFMT_STEREO ? "STEREO":"MONO"));
-
-/* mono word */
-data = (format & AFMT_STEREO) ? 0 : 1;
-m3_wr_assp_data(sc, ch->adc_data + SRC3_MODE_OFFSET, data);
-
-/* 8bit word */
-data = ((format & AFMT_U8) || (format & AFMT_S8)) ? 1 : 0;
-m3_wr_assp_data(sc, ch->adc_data + SRC3_WORD_LENGTH_OFFSET, data);
-ch->fmt = format;
-M3_UNLOCK(sc);
+ struct sc_rchinfo *ch = chdata;
+ struct sc_info *sc = ch->parent;
+ u_int32_t data;
+
+ M3_LOCK(sc);
+ M3_DEBUG(CHANGE,
+ ("m3_rchan_setformat(dac=%d, format=0x%x{%s-%s})\n",
+ ch->adc_idx, format,
+ format & (AFMT_U8|AFMT_S8) ? "8bit":"16bit",
+ format & AFMT_STEREO ? "STEREO":"MONO"));
+
+ /* mono word */
+ data = (format & AFMT_STEREO) ? 0 : 1;
+ m3_wr_assp_data(sc, ch->adc_data + SRC3_MODE_OFFSET, data);
+
+ /* 8bit word */
+ data = ((format & AFMT_U8) || (format & AFMT_S8)) ? 1 : 0;
+ m3_wr_assp_data(sc, ch->adc_data + SRC3_WORD_LENGTH_OFFSET, data);
+ ch->fmt = format;
+ M3_UNLOCK(sc);
-return (0);
+ return (0);
}
static int
m3_rchan_setspeed(kobj_t kobj, void *chdata, u_int32_t speed)
{
-struct sc_rchinfo *ch = chdata;
-struct sc_info *sc = ch->parent;
-u_int32_t freq;
-
-M3_LOCK(sc);
-M3_DEBUG(CHANGE, ("m3_rchan_setspeed(adc=%d, speed=%d)n",
-ch->adc_idx, speed));
-
-if ((freq = ((speed << 15) + 24000) / 48000) != 0) {
-freq--;
-}
+ struct sc_rchinfo *ch = chdata;
+ struct sc_info *sc = ch->parent;
+ u_int32_t freq;
+
+ M3_LOCK(sc);
+ M3_DEBUG(CHANGE, ("m3_rchan_setspeed(adc=%d, speed=%d)\n",
+ ch->adc_idx, speed));
+
+ if ((freq = ((speed << 15) + 24000) / 48000) != 0) {
+ freq--;
+ }
+
+ m3_wr_assp_data(sc, ch->adc_data + CDATA_FREQUENCY, freq);
+ ch->spd = speed;
+ M3_UNLOCK(sc);
-m3_wr_assp_data(sc, ch->adc_data + CDATA_FREQUENCY, freq);
-ch->spd = speed;
-M3_UNLOCK(sc);
-
-/* return closest possible speed */
-return (speed);
+ /* return closest possible speed */
+ return (speed);
}
static int
m3_rchan_setblocksize(kobj_t kobj, void *chdata, u_int32_t blocksize)
{
-struct sc_rchinfo *ch = chdata;
+ struct sc_rchinfo *ch = chdata;
-M3_DEBUG(CHANGE, ("m3_rchan_setblocksize(adc=%d, blocksize=%d)n",
-ch->adc_idx, blocksize));
+ M3_DEBUG(CHANGE, ("m3_rchan_setblocksize(adc=%d, blocksize=%d)\n",
+ ch->adc_idx, blocksize));
-return (sndbuf_getblksz(ch->buffer));
+ return (sndbuf_getblksz(ch->buffer));
}
static int
m3_rchan_trigger(kobj_t kobj, void *chdata, int go)
{
-struct sc_rchinfo *ch = chdata;
-struct sc_info *sc = ch->parent;
-int ret;
-
-M3_LOCK(sc);
-ret = m3_rchan_trigger_locked(kobj, chdata, go);
-M3_UNLOCK(sc);
+ struct sc_rchinfo *ch = chdata;
+ struct sc_info *sc = ch->parent;
+ int ret;
+
+ if (!PCMTRIG_COMMON(go))
+ return (0);
+
+ M3_LOCK(sc);
+ ret = m3_rchan_trigger_locked(kobj, chdata, go);
+ M3_UNLOCK(sc);
-return (ret);
+ return (ret);
}
static int
m3_rchan_trigger_locked(kobj_t kobj, void *chdata, int go)
{
-struct sc_rchinfo *ch = chdata;
-struct sc_info *sc = ch->parent;
-u_int32_t data;
-
-M3_LOCK_ASSERT(sc);
-M3_DEBUG(go == PCMTRIG_START ? CHANGE :
-go == PCMTRIG_STOP ? CHANGE :
-go == PCMTRIG_ABORT ? CHANGE :
-CALL,
-("m3_rchan_trigger(adc=%d, go=0x%x{%s})n", ch->adc_idx, go,
-go == PCMTRIG_START ? "PCMTRIG_START" :
-go == PCMTRIG_STOP ? "PCMTRIG_STOP" :
-go == PCMTRIG_ABORT ? "PCMTRIG_ABORT" : "ignore"));
-
-switch(go) {
-case PCMTRIG_START:
-if (ch->active) {
-return 0;
-}
-ch->active = 1;
-ch->ptr = 0;
-ch->prevptr = 0;
-
-/*[[inc_timer_users]]*/
-if (m3_chan_active(sc) == 1) {
-m3_wr_assp_data(sc, KDATA_TIMER_COUNT_RELOAD, 240);
-m3_wr_assp_data(sc, KDATA_TIMER_COUNT_CURRENT, 240);
-data = m3_rd_2(sc, HOST_INT_CTRL);
-m3_wr_2(sc, HOST_INT_CTRL, data | CLKRUN_GEN_ENABLE);
-}
-
-m3_wr_assp_data(sc, KDATA_ADC1_REQUEST, 1);
-m3_wr_assp_data(sc, ch->adc_data + CDATA_INSTANCE_READY, 1);
-break;
-
-case PCMTRIG_STOP:
-case PCMTRIG_ABORT:
-if (ch->active == 0) {
-return 0;
-}
-ch->active = 0;
-
-/*[[dec_timer_users]]*/
-if (m3_chan_active(sc) == 0) {
-m3_wr_assp_data(sc, KDATA_TIMER_COUNT_RELOAD, 0);
-m3_wr_assp_data(sc, KDATA_TIMER_COUNT_CURRENT, 0);
-data = m3_rd_2(sc, HOST_INT_CTRL);
-m3_wr_2(sc, HOST_INT_CTRL, data & ~CLKRUN_GEN_ENABLE);
-}
-
-m3_wr_assp_data(sc, ch->adc_data + CDATA_INSTANCE_READY, 0);
-m3_wr_assp_data(sc, KDATA_ADC1_REQUEST, 0);
-break;
-
-case PCMTRIG_EMLDMAWR:
-/* got play irq, transfer next buffer - ignore if using dma */
-case PCMTRIG_EMLDMARD:
-/* got rec irq, transfer next buffer - ignore if using dma */
-default:
-break;
-}
-return 0;
+ struct sc_rchinfo *ch = chdata;
+ struct sc_info *sc = ch->parent;
+ u_int32_t data;
+
+ M3_LOCK_ASSERT(sc);
+ M3_DEBUG(go == PCMTRIG_START ? CHANGE :
+ go == PCMTRIG_STOP ? CHANGE :
+ go == PCMTRIG_ABORT ? CHANGE :
+ CALL,
+ ("m3_rchan_trigger(adc=%d, go=0x%x{%s})\n", ch->adc_idx, go,
+ go == PCMTRIG_START ? "PCMTRIG_START" :
+ go == PCMTRIG_STOP ? "PCMTRIG_STOP" :
+ go == PCMTRIG_ABORT ? "PCMTRIG_ABORT" : "ignore"));
+
+ switch(go) {
+ case PCMTRIG_START:
+ if (ch->active) {
+ return 0;
+ }
+ ch->active = 1;
+ ch->ptr = 0;
+ ch->prevptr = 0;
+
+ /*[[inc_timer_users]]*/
+ if (m3_chan_active(sc) == 1) {
+ m3_wr_assp_data(sc, KDATA_TIMER_COUNT_RELOAD, 240);
+ m3_wr_assp_data(sc, KDATA_TIMER_COUNT_CURRENT, 240);
+ data = m3_rd_2(sc, HOST_INT_CTRL);
+ m3_wr_2(sc, HOST_INT_CTRL, data | CLKRUN_GEN_ENABLE);
+ }
+
+ m3_wr_assp_data(sc, KDATA_ADC1_REQUEST, 1);
+ m3_wr_assp_data(sc, ch->adc_data + CDATA_INSTANCE_READY, 1);
+ break;
+
+ case PCMTRIG_STOP:
+ case PCMTRIG_ABORT:
+ if (ch->active == 0) {
+ return 0;
+ }
+ ch->active = 0;
+
+ /*[[dec_timer_users]]*/
+ if (m3_chan_active(sc) == 0) {
+ m3_wr_assp_data(sc, KDATA_TIMER_COUNT_RELOAD, 0);
+ m3_wr_assp_data(sc, KDATA_TIMER_COUNT_CURRENT, 0);
+ data = m3_rd_2(sc, HOST_INT_CTRL);
+ m3_wr_2(sc, HOST_INT_CTRL, data & ~CLKRUN_GEN_ENABLE);
+ }
+
+ m3_wr_assp_data(sc, ch->adc_data + CDATA_INSTANCE_READY, 0);
+ m3_wr_assp_data(sc, KDATA_ADC1_REQUEST, 0);
+ break;
+
+ case PCMTRIG_EMLDMAWR:
+ /* got play irq, transfer next buffer - ignore if using dma */
+ case PCMTRIG_EMLDMARD:
+ /* got rec irq, transfer next buffer - ignore if using dma */
+ default:
+ break;
+ }
+ return 0;
}
static u_int32_t
m3_rchan_getptr_internal(struct sc_rchinfo *ch)
{
-struct sc_info *sc = ch->parent;
-u_int32_t hi, lo, bus_base, bus_crnt;
+ struct sc_info *sc = ch->parent;
+ u_int32_t hi, lo, bus_base, bus_crnt;
-bus_base = sndbuf_getbufaddr(ch->buffer);
-hi = m3_rd_assp_data(sc, ch->adc_data + CDATA_HOST_SRC_CURRENTH);
-lo = m3_rd_assp_data(sc, ch->adc_data + CDATA_HOST_SRC_CURRENTL);
-bus_crnt = lo | (hi << 16);
+ bus_base = sndbuf_getbufaddr(ch->buffer);
+ hi = m3_rd_assp_data(sc, ch->adc_data + CDATA_HOST_SRC_CURRENTH);
+ lo = m3_rd_assp_data(sc, ch->adc_data + CDATA_HOST_SRC_CURRENTL);
+ bus_crnt = lo | (hi << 16);
-M3_DEBUG(CALL, ("m3_rchan_getptr(adc=%d) result=%dn",
-ch->adc_idx, bus_crnt - bus_base));
+ M3_DEBUG(CALL, ("m3_rchan_getptr(adc=%d) result=%d\n",
+ ch->adc_idx, bus_crnt - bus_base));
-return (bus_crnt - bus_base); /* current byte offset of channel */
+ return (bus_crnt - bus_base); /* current byte offset of channel */
}
static u_int32_t
m3_rchan_getptr(kobj_t kobj, void *chdata)
{
-struct sc_rchinfo *ch = chdata;
-struct sc_info *sc = ch->parent;
-u_int32_t ptr;
-
-M3_LOCK(sc);
-ptr = ch->ptr;
-M3_UNLOCK(sc);
+ struct sc_rchinfo *ch = chdata;
+ struct sc_info *sc = ch->parent;
+ u_int32_t ptr;
+
+ M3_LOCK(sc);
+ ptr = ch->ptr;
+ M3_UNLOCK(sc);
-return (ptr);
+ return (ptr);
}
static struct pcmchan_caps *
m3_rchan_getcaps(kobj_t kobj, void *chdata)
{
-struct sc_rchinfo *ch = chdata;
+ struct sc_rchinfo *ch = chdata;
-M3_DEBUG(CALL, ("m3_rchan_getcaps(adc=%d)n", ch->adc_idx));
+ M3_DEBUG(CALL, ("m3_rchan_getcaps(adc=%d)\n", ch->adc_idx));
-return &m3_reccaps;
+ return &m3_reccaps;
}
/* -------------------------------------------------------------------- */
@@ -1033,92 +1043,92 @@
static void
m3_intr(void *p)
{
-struct sc_info *sc = (struct sc_info *)p;
-struct sc_pchinfo *pch;
-struct sc_rchinfo *rch;
-u_int32_t status, ctl, i, delta;
+ struct sc_info *sc = (struct sc_info *)p;
+ struct sc_pchinfo *pch;
+ struct sc_rchinfo *rch;
+ u_int32_t status, ctl, i, delta;
+
+ M3_DEBUG(INTR, ("m3_intr\n"));
+
+ M3_LOCK(sc);
+ status = m3_rd_1(sc, HOST_INT_STATUS);
+ if (!status) {
+ M3_UNLOCK(sc);
+ return;
+ }
+
+ m3_wr_1(sc, HOST_INT_STATUS, 0xff); /* ack the int? */
+
+ if (status & HV_INT_PENDING) {
+ u_int8_t event;
+
+ event = m3_rd_1(sc, HW_VOL_COUNTER_MASTER);
+ switch (event) {
+ case 0x99:
+ mixer_hwvol_mute(sc->dev);
+ break;
+ case 0xaa:
+ mixer_hwvol_step(sc->dev, 1, 1);
+ break;
+ case 0x66:
+ mixer_hwvol_step(sc->dev, -1, -1);
+ break;
+ case 0x88:
+ break;
+ default:
+ device_printf(sc->dev, "Unknown HWVOL event\n");
+ }
+ m3_wr_1(sc, HW_VOL_COUNTER_MASTER, 0x88);
+
+ }
+
+ if (status & ASSP_INT_PENDING) {
+ ctl = m3_rd_1(sc, ASSP_CONTROL_B);
+ if (!(ctl & STOP_ASSP_CLOCK)) {
+ ctl = m3_rd_1(sc, ASSP_HOST_INT_STATUS);
+ if (ctl & DSP2HOST_REQ_TIMER) {
+ m3_wr_1(sc, ASSP_HOST_INT_STATUS,
+ DSP2HOST_REQ_TIMER);
+ /*[[ess_update_ptr]]*/
+ goto m3_handle_channel_intr;
+ }
+ }
+ }
-M3_DEBUG(INTR, ("m3_intrn"));
-
-M3_LOCK(sc);
-status = m3_rd_1(sc, HOST_INT_STATUS);
-if (!status) {
-M3_UNLOCK(sc);
-return;
-}
-
-m3_wr_1(sc, HOST_INT_STATUS, 0xff); /* ack the int? */
-
-if (status & HV_INT_PENDING) {
-u_int8_t event;
-
-event = m3_rd_1(sc, HW_VOL_COUNTER_MASTER);
-switch (event) {
-case 0x99:
-mixer_hwvol_mute(sc->dev);
-break;
-case 0xaa:
-mixer_hwvol_step(sc->dev, 1, 1);
-break;
-case 0x66:
-mixer_hwvol_step(sc->dev, -1, -1);
-break;
-case 0x88:
-break;
-default:
-device_printf(sc->dev, "Unknown HWVOL eventn");
-}
-m3_wr_1(sc, HW_VOL_COUNTER_MASTER, 0x88);
-
-}
-
-if (status & ASSP_INT_PENDING) {
-ctl = m3_rd_1(sc, ASSP_CONTROL_B);
-if (!(ctl & STOP_ASSP_CLOCK)) {
-ctl = m3_rd_1(sc, ASSP_HOST_INT_STATUS);
-if (ctl & DSP2HOST_REQ_TIMER) {
-m3_wr_1(sc, ASSP_HOST_INT_STATUS,
-DSP2HOST_REQ_TIMER);
-/*[[ess_update_ptr]]*/
-goto m3_handle_channel_intr;
-}
-}
-}
-
-goto m3_handle_channel_intr_out;
+ goto m3_handle_channel_intr_out;
m3_handle_channel_intr:
-for (i=0 ; i<sc->pch_cnt ; i++) {
-pch = &sc->pch[i];
-if (pch->active) {
-pch->ptr = m3_pchan_getptr_internal(pch);
-delta = pch->bufsize + pch->ptr - pch->prevptr;
-delta %= pch->bufsize;
-if (delta < sndbuf_getblksz(pch->buffer))
-continue;
-pch->prevptr = pch->ptr;
-M3_UNLOCK(sc);
-chn_intr(pch->channel);
-M3_LOCK(sc);
-}
-}
-for (i=0 ; i<sc->rch_cnt ; i++) {
-rch = &sc->rch[i];
-if (rch->active) {
-rch->ptr = m3_rchan_getptr_internal(rch);
-delta = rch->bufsize + rch->ptr - rch->prevptr;
-delta %= rch->bufsize;
-if (delta < sndbuf_getblksz(rch->buffer))
-continue;
-rch->prevptr = rch->ptr;
-M3_UNLOCK(sc);
-chn_intr(rch->channel);
-M3_LOCK(sc);
-}
-}
+ for (i=0 ; i<sc->pch_cnt ; i++) {
+ pch = &sc->pch[i];
+ if (pch->active) {
+ pch->ptr = m3_pchan_getptr_internal(pch);
+ delta = pch->bufsize + pch->ptr - pch->prevptr;
+ delta %= pch->bufsize;
+ if (delta < sndbuf_getblksz(pch->buffer))
+ continue;
+ pch->prevptr = pch->ptr;
+ M3_UNLOCK(sc);
+ chn_intr(pch->channel);
+ M3_LOCK(sc);
+ }
+ }
+ for (i=0 ; i<sc->rch_cnt ; i++) {
+ rch = &sc->rch[i];
+ if (rch->active) {
+ rch->ptr = m3_rchan_getptr_internal(rch);
+ delta = rch->bufsize + rch->ptr - rch->prevptr;
+ delta %= rch->bufsize;
+ if (delta < sndbuf_getblksz(rch->buffer))
+ continue;
+ rch->prevptr = rch->ptr;
+ M3_UNLOCK(sc);
+ chn_intr(rch->channel);
+ M3_LOCK(sc);
+ }
+ }
m3_handle_channel_intr_out:
-M3_UNLOCK(sc);
+ M3_UNLOCK(sc);
}
/* -------------------------------------------------------------------- */
@@ -1127,101 +1137,101 @@
static int
m3_power(struct sc_info *sc, int state)
{
-u_int32_t data;
+ u_int32_t data;
-M3_DEBUG(CHANGE, ("m3_power(%d)n", state));
-M3_LOCK_ASSERT(sc);
+ M3_DEBUG(CHANGE, ("m3_power(%d)\n", state));
+ M3_LOCK_ASSERT(sc);
-data = pci_read_config(sc->dev, 0x34, 1);
-if (pci_read_config(sc->dev, data, 1) == 1) {
-pci_write_config(sc->dev, data + 4, state, 1);
-}
+ data = pci_read_config(sc->dev, 0x34, 1);
+ if (pci_read_config(sc->dev, data, 1) == 1) {
+ pci_write_config(sc->dev, data + 4, state, 1);
+ }
-return 0;
+ return 0;
}
static int
m3_init(struct sc_info *sc)
{
-u_int32_t data, i, size;
-u_int8_t reset_state;
+ u_int32_t data, i, size;
+ u_int8_t reset_state;
-M3_LOCK_ASSERT(sc);
-M3_DEBUG(CHANGE, ("m3_initn"));
+ M3_LOCK_ASSERT(sc);
+ M3_DEBUG(CHANGE, ("m3_init\n"));
-/* diable legacy emulations. */
-data = pci_read_config(sc->dev, PCI_LEGACY_AUDIO_CTRL, 2);
-data |= DISABLE_LEGACY;
-pci_write_config(sc->dev, PCI_LEGACY_AUDIO_CTRL, data, 2);
-
-m3_config(sc);
-
-reset_state = m3_assp_halt(sc);
-
-m3_codec_reset(sc);
-
-/* [m3_assp_init] */
-/* zero kernel data */
-size = REV_B_DATA_MEMORY_UNIT_LENGTH * NUM_UNITS_KERNEL_DATA;
-for(i = 0 ; i < size / 2 ; i++) {
-m3_wr_assp_data(sc, KDATA_BASE_ADDR + i, 0);
-}
-/* zero mixer data? */
-size = REV_B_DATA_MEMORY_UNIT_LENGTH * NUM_UNITS_KERNEL_DATA;
-for(i = 0 ; i < size / 2 ; i++) {
-m3_wr_assp_data(sc, KDATA_BASE_ADDR2 + i, 0);
-}
-/* init dma pointer */
-m3_wr_assp_data(sc, KDATA_CURRENT_DMA,
-KDATA_DMA_XFER0);
-/* write kernel into code memory */
-size = sizeof(assp_kernel_image);
-for(i = 0 ; i < size / 2; i++) {
-m3_wr_assp_code(sc, REV_B_CODE_MEMORY_BEGIN + i,
-assp_kernel_image[i]);
-}
-/*
-* We only have this one client and we know that 0x400 is free in
-* our kernel's mem map, so lets just drop it there. It seems that
-* the minisrc doesn't need vectors, so we won't bother with them..
-*/
-size = sizeof(assp_minisrc_image);
-for(i = 0 ; i < size / 2; i++) {
-m3_wr_assp_code(sc, 0x400 + i, assp_minisrc_image[i]);
-}
-/* write the coefficients for the low pass filter? */
-size = sizeof(minisrc_lpf_image);
-for(i = 0; i < size / 2 ; i++) {
-m3_wr_assp_code(sc,0x400 + MINISRC_COEF_LOC + i,
-minisrc_lpf_image[i]);
-}
-m3_wr_assp_code(sc, 0x400 + MINISRC_COEF_LOC + size, 0x8000);
-/* the minisrc is the only thing on our task list */
-m3_wr_assp_data(sc, KDATA_TASK0, 0x400);
-/* init the mixer number */
-m3_wr_assp_data(sc, KDATA_MIXER_TASK_NUMBER, 0);
-/* extreme kernel master volume */
-m3_wr_assp_data(sc, KDATA_DAC_LEFT_VOLUME, ARB_VOLUME);
-m3_wr_assp_data(sc, KDATA_DAC_RIGHT_VOLUME, ARB_VOLUME);
-
-m3_amp_enable(sc);
-
-/* [m3_assp_client_init] (only one client at index 0) */
-for (i=0x1100 ; i<0x1c00 ; i++) {
-m3_wr_assp_data(sc, i, 0); /* zero entire dac/adc area */
-}
+ /* diable legacy emulations. */
+ data = pci_read_config(sc->dev, PCI_LEGACY_AUDIO_CTRL, 2);
+ data |= DISABLE_LEGACY;
+ pci_write_config(sc->dev, PCI_LEGACY_AUDIO_CTRL, data, 2);
+
+ m3_config(sc);
+
+ reset_state = m3_assp_halt(sc);
+
+ m3_codec_reset(sc);
+
+ /* [m3_assp_init] */
+ /* zero kernel data */
+ size = REV_B_DATA_MEMORY_UNIT_LENGTH * NUM_UNITS_KERNEL_DATA;
+ for(i = 0 ; i < size / 2 ; i++) {
+ m3_wr_assp_data(sc, KDATA_BASE_ADDR + i, 0);
+ }
+ /* zero mixer data? */
+ size = REV_B_DATA_MEMORY_UNIT_LENGTH * NUM_UNITS_KERNEL_DATA;
+ for(i = 0 ; i < size / 2 ; i++) {
+ m3_wr_assp_data(sc, KDATA_BASE_ADDR2 + i, 0);
+ }
+ /* init dma pointer */
+ m3_wr_assp_data(sc, KDATA_CURRENT_DMA,
+ KDATA_DMA_XFER0);
+ /* write kernel into code memory */
+ size = sizeof(assp_kernel_image);
+ for(i = 0 ; i < size / 2; i++) {
+ m3_wr_assp_code(sc, REV_B_CODE_MEMORY_BEGIN + i,
+ assp_kernel_image[i]);
+ }
+ /*
+ * We only have this one client and we know that 0x400 is free in
+ * our kernel's mem map, so lets just drop it there. It seems that
+ * the minisrc doesn't need vectors, so we won't bother with them..
+ */
+ size = sizeof(assp_minisrc_image);
+ for(i = 0 ; i < size / 2; i++) {
+ m3_wr_assp_code(sc, 0x400 + i, assp_minisrc_image[i]);
+ }
+ /* write the coefficients for the low pass filter? */
+ size = sizeof(minisrc_lpf_image);
+ for(i = 0; i < size / 2 ; i++) {
+ m3_wr_assp_code(sc,0x400 + MINISRC_COEF_LOC + i,
+ minisrc_lpf_image[i]);
+ }
+ m3_wr_assp_code(sc, 0x400 + MINISRC_COEF_LOC + size, 0x8000);
+ /* the minisrc is the only thing on our task list */
+ m3_wr_assp_data(sc, KDATA_TASK0, 0x400);
+ /* init the mixer number */
+ m3_wr_assp_data(sc, KDATA_MIXER_TASK_NUMBER, 0);
+ /* extreme kernel master volume */
+ m3_wr_assp_data(sc, KDATA_DAC_LEFT_VOLUME, ARB_VOLUME);
+ m3_wr_assp_data(sc, KDATA_DAC_RIGHT_VOLUME, ARB_VOLUME);
+
+ m3_amp_enable(sc);
+
+ /* [m3_assp_client_init] (only one client at index 0) */
+ for (i=0x1100 ; i<0x1c00 ; i++) {
+ m3_wr_assp_data(sc, i, 0); /* zero entire dac/adc area */
+ }
-/* [m3_assp_continue] */
-m3_wr_1(sc, DSP_PORT_CONTROL_REG_B, reset_state | REGB_ENABLE_RESET);
+ /* [m3_assp_continue] */
+ m3_wr_1(sc, DSP_PORT_CONTROL_REG_B, reset_state | REGB_ENABLE_RESET);
-return 0;
+ return 0;
}
static int
m3_uninit(struct sc_info *sc)
{
-M3_DEBUG(CHANGE, ("m3_uninitn"));
-return 0;
+ M3_DEBUG(CHANGE, ("m3_uninit\n"));
+ return 0;
}
/* -------------------------------------------------------------------- */
@@ -1230,514 +1240,501 @@
static int
m3_pci_probe(device_t dev)
{
-struct m3_card_type *card;
+ struct m3_card_type *card;
-M3_DEBUG(CALL, ("m3_pci_probe(0x%x)n", pci_get_devid(dev)));
+ M3_DEBUG(CALL, ("m3_pci_probe(0x%x)\n", pci_get_devid(dev)));
-for (card = m3_card_types ; card->pci_id ; card++) {
-if (pci_get_devid(dev) == card->pci_id) {
-device_set_desc(dev, card->name);
-return BUS_PROBE_DEFAULT;
-}
-}
-return ENXIO;
+ for (card = m3_card_types ; card->pci_id ; card++) {
+ if (pci_get_devid(dev) == card->pci_id) {
+ device_set_desc(dev, card->name);
+ return BUS_PROBE_DEFAULT;
+ }
+ }
+ return ENXIO;
}
static int
m3_pci_attach(device_t dev)
{
-struct sc_info *sc;
-struct ac97_info *codec = NULL;
-u_int32_t data;
-char status[SND_STATUSLEN];
-struct m3_card_type *card;
-int i, len, dacn, adcn;
-
-M3_DEBUG(CALL, ("m3_pci_attachn"));
-
-if ((sc = malloc(sizeof(*sc), M_DEVBUF, M_NOWAIT | M_ZERO)) == NULL) {
-device_printf(dev, "cannot allocate softcn");
-return ENXIO;
-}
-
-sc->dev = dev;
-sc->type = pci_get_devid(dev);
-sc->sc_lock = snd_mtxcreate(device_get_nameunit(dev),
-"sound softc");
-if (sc->sc_lock == NULL) {
-device_printf(dev, "cannot create mutexn");
-free(sc, M_DEVBUF);
-return (ENXIO);
-}
-for (card = m3_card_types ; card->pci_id ; card++) {
-if (sc->type == card->pci_id) {
-sc->which = card->which;
-sc->delay1 = card->delay1;
-sc->delay2 = card->delay2;
-break;
-}
-}
-
-if (resource_int_value(device_get_name(dev), device_get_unit(dev),
-"dac", &i) == 0) {
-if (i < 1)
-dacn = 1;
-else if (i > M3_PCHANS)
-dacn = M3_PCHANS;
-else
-dacn = i;
-} else
-dacn = M3_PCHANS;
-
-adcn = M3_RCHANS;
-
-data = pci_read_config(dev, PCIR_COMMAND, 2);
-data |= (PCIM_CMD_PORTEN | PCIM_CMD_MEMEN | PCIM_CMD_BUSMASTEREN);
-pci_write_config(dev, PCIR_COMMAND, data, 2);
-
-sc->regid = PCIR_BAR(0);
-sc->regtype = SYS_RES_MEMORY;
-sc->reg = bus_alloc_resource_any(dev, sc->regtype, &sc->regid,
-RF_ACTIVE);
-if (!sc->reg) {
-sc->regtype = SYS_RES_IOPORT;
-sc->reg = bus_alloc_resource_any(dev, sc->regtype, &sc->regid,
-RF_ACTIVE);
-}
-if (!sc->reg) {
-device_printf(dev, "unable to allocate register spacen");
-goto bad;
-}
-sc->st = rman_get_bustag(sc->reg);
-sc->sh = rman_get_bushandle(sc->reg);
-
-sc->irqid = 0;
-sc->irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &sc->irqid,
-RF_ACTIVE | RF_SHAREABLE);
-if (!sc->irq) {
-device_printf(dev, "unable to allocate interruptn");
-goto bad;
-}
-
-if (snd_setup_intr(dev, sc->irq, INTR_MPSAFE, m3_intr, sc, &sc->ih)) {
-device_printf(dev, "unable to setup interruptn");
-goto bad;
-}
-
-sc->bufsz = pcm_getbuffersize(dev, M3_BUFSIZE_MIN, M3_BUFSIZE_DEFAULT,
-M3_BUFSIZE_MAX);
-
-if (bus_dma_tag_create(
-NULL, /* parent */
-2, 0, /* alignment, boundary */
-M3_MAXADDR, /* lowaddr */
-BUS_SPACE_MAXADDR, /* highaddr */
-NULL, NULL, /* filtfunc, filtfuncarg */
-sc->bufsz, /* maxsize */
-1, /* nsegments */
-0x3ffff, /* maxsegz */
-0, /* flags */
-NULL, /* lockfunc */
-NULL, /* lockfuncarg */
-&sc->parent_dmat) != 0) {
-device_printf(dev, "unable to create dma tagn");
-goto bad;
-}
-
-M3_LOCK(sc);
-m3_power(sc, 0); /* power up */
-/* init chip */
-i = m3_init(sc);
-M3_UNLOCK(sc);
-if (i == -1) {
-device_printf(dev, "unable to initialize the cardn");
-goto bad;
-}
-
-/* create/init mixer */
-codec = AC97_CREATE(dev, sc, m3_codec);
-if (codec == NULL) {
-device_printf(dev, "ac97_create errorn");
-goto bad;
-}
-if (mixer_init(dev, ac97_getmixerclass(), codec)) {
-device_printf(dev, "mixer_init errorn");
-goto bad;
-}
-
-m3_enable_ints(sc);
-
-if (pcm_register(dev, sc, dacn, adcn)) {
-device_printf(dev, "pcm_register errorn");
-goto bad;
-}
-for (i=0 ; i<dacn ; i++) {
-if (pcm_addchan(dev, PCMDIR_PLAY, &m3_pch_class, sc)) {
-device_printf(dev, "pcm_addchan (play) errorn");
-goto bad;
-}
-}
-for (i=0 ; i<adcn ; i++) {
-if (pcm_addchan(dev, PCMDIR_REC, &m3_rch_class, sc)) {
-device_printf(dev, "pcm_addchan (rec) errorn");
-goto bad;
-}
-}
-snprintf(status, SND_STATUSLEN, "at %s 0x%lx irq %ld %s",
-(sc->regtype == SYS_RES_IOPORT)? "io" : "memory",
-rman_get_start(sc->reg), rman_get_start(sc->irq),
-PCM_KLDSTRING(snd_maestro3));
-if (pcm_setstatus(dev, status)) {
-device_printf(dev, "attach: pcm_setstatus errorn");
-goto bad;
-}
-
-mixer_hwvol_init(dev);
-
-/* Create the buffer for saving the card state during suspend */
-len = sizeof(u_int16_t) * (REV_B_CODE_MEMORY_LENGTH +
-REV_B_DATA_MEMORY_LENGTH);
-sc->savemem = (u_int16_t*)malloc(len, M_DEVBUF, M_NOWAIT | M_ZERO);
-if (sc->savemem == NULL) {
-device_printf(dev, "Failed to create suspend buffern");
-goto bad;
-}
-
-return 0;
-
-bad:
-if (codec)
-ac97_destroy(codec);
-if (sc->ih)
-bus_teardown_intr(dev, sc->irq, sc->ih);
-if (sc->irq)
-bus_release_resource(dev, SYS_RES_IRQ, sc->irqid, sc->irq);
-if (sc->reg)
-bus_release_resource(dev, sc->regtype, sc->regid, sc->reg);
-if (sc->parent_dmat)
-bus_dma_tag_destroy(sc->parent_dmat);
-if (sc->sc_lock)
-snd_mtxfree(sc->sc_lock);
-free(sc, M_DEVBUF);
-return ENXIO;
+ struct sc_info *sc;
+ struct ac97_info *codec = NULL;
+ u_int32_t data;
+ char status[SND_STATUSLEN];
+ struct m3_card_type *card;
+ int i, len, dacn, adcn;
+
+ M3_DEBUG(CALL, ("m3_pci_attach\n"));
+
+ sc = malloc(sizeof(*sc), M_DEVBUF, M_WAITOK | M_ZERO);
+ sc->dev = dev;
+ sc->type = pci_get_devid(dev);
+ sc->sc_lock = snd_mtxcreate(device_get_nameunit(dev),
+ "snd_maestro3 softc");
+ for (card = m3_card_types ; card->pci_id ; card++) {
+ if (sc->type == card->pci_id) {
+ sc->which = card->which;
+ sc->delay1 = card->delay1;
+ sc->delay2 = card->delay2;
+ break;
+ }
+ }
+
+ if (resource_int_value(device_get_name(dev), device_get_unit(dev),
+ "dac", &i) == 0) {
+ if (i < 1)
+ dacn = 1;
+ else if (i > M3_PCHANS)
+ dacn = M3_PCHANS;
+ else
+ dacn = i;
+ } else
+ dacn = M3_PCHANS;
+
+ adcn = M3_RCHANS;
+
+ data = pci_read_config(dev, PCIR_COMMAND, 2);
+ data |= (PCIM_CMD_PORTEN | PCIM_CMD_MEMEN | PCIM_CMD_BUSMASTEREN);
+ pci_write_config(dev, PCIR_COMMAND, data, 2);
+
+ sc->regid = PCIR_BAR(0);
+ sc->regtype = SYS_RES_MEMORY;
+ sc->reg = bus_alloc_resource_any(dev, sc->regtype, &sc->regid,
+ RF_ACTIVE);
+ if (!sc->reg) {
+ sc->regtype = SYS_RES_IOPORT;
+ sc->reg = bus_alloc_resource_any(dev, sc->regtype, &sc->regid,
+ RF_ACTIVE);
+ }
+ if (!sc->reg) {
+ device_printf(dev, "unable to allocate register space\n");
+ goto bad;
+ }
+ sc->st = rman_get_bustag(sc->reg);
+ sc->sh = rman_get_bushandle(sc->reg);
+
+ sc->irqid = 0;
+ sc->irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &sc->irqid,
+ RF_ACTIVE | RF_SHAREABLE);
+ if (!sc->irq) {
+ device_printf(dev, "unable to allocate interrupt\n");
+ goto bad;
+ }
+
+ if (snd_setup_intr(dev, sc->irq, INTR_MPSAFE, m3_intr, sc, &sc->ih)) {
+ device_printf(dev, "unable to setup interrupt\n");
+ goto bad;
+ }
+
+ sc->bufsz = pcm_getbuffersize(dev, M3_BUFSIZE_MIN, M3_BUFSIZE_DEFAULT,
+ M3_BUFSIZE_MAX);
+
+ if (bus_dma_tag_create(
+ bus_get_dma_tag(dev), /* parent */
+ 2, 0, /* alignment, boundary */
+ M3_MAXADDR, /* lowaddr */
+ BUS_SPACE_MAXADDR, /* highaddr */
+ NULL, NULL, /* filtfunc, filtfuncarg */
+ sc->bufsz, /* maxsize */
+ 1, /* nsegments */
+ 0x3ffff, /* maxsegz */
+ 0, /* flags */
+ NULL, /* lockfunc */
+ NULL, /* lockfuncarg */
+ &sc->parent_dmat) != 0) {
+ device_printf(dev, "unable to create dma tag\n");
+ goto bad;
+ }
+
+ M3_LOCK(sc);
+ m3_power(sc, 0); /* power up */
+ /* init chip */
+ i = m3_init(sc);
+ M3_UNLOCK(sc);
+ if (i == -1) {
+ device_printf(dev, "unable to initialize the card\n");
+ goto bad;
+ }
+
+ /* create/init mixer */
+ codec = AC97_CREATE(dev, sc, m3_codec);
+ if (codec == NULL) {
+ device_printf(dev, "ac97_create error\n");
+ goto bad;
+ }
+ if (mixer_init(dev, ac97_getmixerclass(), codec)) {
+ device_printf(dev, "mixer_init error\n");
+ goto bad;
+ }
+
+ m3_enable_ints(sc);
+
+ if (pcm_register(dev, sc, dacn, adcn)) {
+ device_printf(dev, "pcm_register error\n");
+ goto bad;
+ }
+ for (i=0 ; i<dacn ; i++) {
+ if (pcm_addchan(dev, PCMDIR_PLAY, &m3_pch_class, sc)) {
+ device_printf(dev, "pcm_addchan (play) error\n");
+ goto bad;
+ }
+ }
+ for (i=0 ; i<adcn ; i++) {
+ if (pcm_addchan(dev, PCMDIR_REC, &m3_rch_class, sc)) {
+ device_printf(dev, "pcm_addchan (rec) error\n");
+ goto bad;
+ }
+ }
+ snprintf(status, SND_STATUSLEN, "at %s 0x%lx irq %ld %s",
+ (sc->regtype == SYS_RES_IOPORT)? "io" : "memory",
+ rman_get_start(sc->reg), rman_get_start(sc->irq),
+ PCM_KLDSTRING(snd_maestro3));
+ if (pcm_setstatus(dev, status)) {
+ device_printf(dev, "attach: pcm_setstatus error\n");
+ goto bad;
+ }
+
+ mixer_hwvol_init(dev);
+
+ /* Create the buffer for saving the card state during suspend */
+ len = sizeof(u_int16_t) * (REV_B_CODE_MEMORY_LENGTH +
+ REV_B_DATA_MEMORY_LENGTH);
+ sc->savemem = (u_int16_t*)malloc(len, M_DEVBUF, M_WAITOK | M_ZERO);
+
+ return 0;
+
+ bad:
+ if (codec)
+ ac97_destroy(codec);
+ if (sc->ih)
+ bus_teardown_intr(dev, sc->irq, sc->ih);
+ if (sc->irq)
+ bus_release_resource(dev, SYS_RES_IRQ, sc->irqid, sc->irq);
+ if (sc->reg)
+ bus_release_resource(dev, sc->regtype, sc->regid, sc->reg);
+ if (sc->parent_dmat)
+ bus_dma_tag_destroy(sc->parent_dmat);
+ if (sc->sc_lock)
+ snd_mtxfree(sc->sc_lock);
+ free(sc, M_DEVBUF);
+ return ENXIO;
}
static int
m3_pci_detach(device_t dev)
{
-struct sc_info *sc = pcm_getdevinfo(dev);
-int r;
+ struct sc_info *sc = pcm_getdevinfo(dev);
+ int r;
-M3_DEBUG(CALL, ("m3_pci_detachn"));
+ M3_DEBUG(CALL, ("m3_pci_detach\n"));
-if ((r = pcm_unregister(dev)) != 0) {
-return r;
-}
-
-M3_LOCK(sc);
-m3_uninit(sc); /* shutdown chip */
-m3_power(sc, 3); /* power off */
-M3_UNLOCK(sc);
-
-bus_teardown_intr(dev, sc->irq, sc->ih);
-bus_release_resource(dev, SYS_RES_IRQ, sc->irqid, sc->irq);
-bus_release_resource(dev, sc->regtype, sc->regid, sc->reg);
-bus_dma_tag_destroy(sc->parent_dmat);
-
-free(sc->savemem, M_DEVBUF);
-snd_mtxfree(sc->sc_lock);
-free(sc, M_DEVBUF);
-return 0;
+ if ((r = pcm_unregister(dev)) != 0) {
+ return r;
+ }
+
+ M3_LOCK(sc);
+ m3_uninit(sc); /* shutdown chip */
+ m3_power(sc, 3); /* power off */
+ M3_UNLOCK(sc);
+
+ bus_teardown_intr(dev, sc->irq, sc->ih);
+ bus_release_resource(dev, SYS_RES_IRQ, sc->irqid, sc->irq);
+ bus_release_resource(dev, sc->regtype, sc->regid, sc->reg);
+ bus_dma_tag_destroy(sc->parent_dmat);
+
+ free(sc->savemem, M_DEVBUF);
+ snd_mtxfree(sc->sc_lock);
+ free(sc, M_DEVBUF);
+ return 0;
}
static int
m3_pci_suspend(device_t dev)
{
-struct sc_info *sc = pcm_getdevinfo(dev);
-int i, index = 0;
+ struct sc_info *sc = pcm_getdevinfo(dev);
+ int i, index = 0;
-M3_DEBUG(CHANGE, ("m3_pci_suspendn"));
+ M3_DEBUG(CHANGE, ("m3_pci_suspend\n"));
-M3_LOCK(sc);
-for (i=0 ; i<sc->pch_cnt ; i++) {
-if (sc->pch[i].active) {
-m3_pchan_trigger_locked(NULL, &sc->pch[i],
-PCMTRIG_STOP);
-}
-}
-for (i=0 ; i<sc->rch_cnt ; i++) {
-if (sc->rch[i].active) {
-m3_rchan_trigger_locked(NULL, &sc->rch[i],
-PCMTRIG_STOP);
-}
-}
-DELAY(10 * 1000); /* give things a chance to stop */
-
-/* Disable interrupts */
-m3_wr_2(sc, HOST_INT_CTRL, 0);
-m3_wr_1(sc, ASSP_CONTROL_C, 0);
-
-m3_assp_halt(sc);
+ M3_LOCK(sc);
+ for (i=0 ; i<sc->pch_cnt ; i++) {
+ if (sc->pch[i].active) {
+ m3_pchan_trigger_locked(NULL, &sc->pch[i],
+ PCMTRIG_STOP);
+ }
+ }
+ for (i=0 ; i<sc->rch_cnt ; i++) {
+ if (sc->rch[i].active) {
+ m3_rchan_trigger_locked(NULL, &sc->rch[i],
+ PCMTRIG_STOP);
+ }
+ }
+ DELAY(10 * 1000); /* give things a chance to stop */
+
+ /* Disable interrupts */
+ m3_wr_2(sc, HOST_INT_CTRL, 0);
+ m3_wr_1(sc, ASSP_CONTROL_C, 0);
+
+ m3_assp_halt(sc);
+
+ /* Save the state of the ASSP */
+ for (i = REV_B_CODE_MEMORY_BEGIN; i <= REV_B_CODE_MEMORY_END; i++)
+ sc->savemem[index++] = m3_rd_assp_code(sc, i);
+ for (i = REV_B_DATA_MEMORY_BEGIN; i <= REV_B_DATA_MEMORY_END; i++)
+ sc->savemem[index++] = m3_rd_assp_data(sc, i);
+
+ /* Power down the card to D3 state */
+ m3_power(sc, 3);
+ M3_UNLOCK(sc);
-/* Save the state of the ASSP */
-for (i = REV_B_CODE_MEMORY_BEGIN; i <= REV_B_CODE_MEMORY_END; i++)
-sc->savemem[index++] = m3_rd_assp_code(sc, i);
-for (i = REV_B_DATA_MEMORY_BEGIN; i <= REV_B_DATA_MEMORY_END; i++)
-sc->savemem[index++] = m3_rd_assp_data(sc, i);
-
-/* Power down the card to D3 state */
-m3_power(sc, 3);
-M3_UNLOCK(sc);
-
-return 0;
+ return 0;
}
static int
m3_pci_resume(device_t dev)
{
-struct sc_info *sc = pcm_getdevinfo(dev);
-int i, index = 0;
-u_int8_t reset_state;
-
-M3_DEBUG(CHANGE, ("m3_pci_resumen"));
-
-M3_LOCK(sc);
-/* Power the card back to D0 */
-m3_power(sc, 0);
+ struct sc_info *sc = pcm_getdevinfo(dev);
+ int i, index = 0;
+ u_int8_t reset_state;
+
+ M3_DEBUG(CHANGE, ("m3_pci_resume\n"));
+
+ M3_LOCK(sc);
+ /* Power the card back to D0 */
+ m3_power(sc, 0);
+
+ m3_config(sc);
+
+ reset_state = m3_assp_halt(sc);
+
+ m3_codec_reset(sc);
+
+ /* Restore the ASSP state */
+ for (i = REV_B_CODE_MEMORY_BEGIN; i <= REV_B_CODE_MEMORY_END; i++)
+ m3_wr_assp_code(sc, i, sc->savemem[index++]);
+ for (i = REV_B_DATA_MEMORY_BEGIN; i <= REV_B_DATA_MEMORY_END; i++)
+ m3_wr_assp_data(sc, i, sc->savemem[index++]);
+
+ /* Restart the DMA engine */
+ m3_wr_assp_data(sc, KDATA_DMA_ACTIVE, 0);
+
+ /* [m3_assp_continue] */
+ m3_wr_1(sc, DSP_PORT_CONTROL_REG_B, reset_state | REGB_ENABLE_RESET);
+
+ m3_amp_enable(sc);
+
+ m3_enable_ints(sc);
+
+ M3_UNLOCK(sc); /* XXX */
+ if (mixer_reinit(dev) == -1) {
+ device_printf(dev, "unable to reinitialize the mixer\n");
+ return (ENXIO);
+ }
+ M3_LOCK(sc);
+
+ /* Turn the channels back on */
+ for (i=0 ; i<sc->pch_cnt ; i++) {
+ if (sc->pch[i].active) {
+ m3_pchan_trigger_locked(NULL, &sc->pch[i],
+ PCMTRIG_START);
+ }
+ }
+ for (i=0 ; i<sc->rch_cnt ; i++) {
+ if (sc->rch[i].active) {
+ m3_rchan_trigger_locked(NULL, &sc->rch[i],
+ PCMTRIG_START);
+ }
+ }
-m3_config(sc);
-
-reset_state = m3_assp_halt(sc);
-
-m3_codec_reset(sc);
-
-/* Restore the ASSP state */
-for (i = REV_B_CODE_MEMORY_BEGIN; i <= REV_B_CODE_MEMORY_END; i++)
-m3_wr_assp_code(sc, i, sc->savemem[index++]);
-for (i = REV_B_DATA_MEMORY_BEGIN; i <= REV_B_DATA_MEMORY_END; i++)
-m3_wr_assp_data(sc, i, sc->savemem[index++]);
-
-/* Restart the DMA engine */
-m3_wr_assp_data(sc, KDATA_DMA_ACTIVE, 0);
-
-/* [m3_assp_continue] */
-m3_wr_1(sc, DSP_PORT_CONTROL_REG_B, reset_state | REGB_ENABLE_RESET);
-
-m3_amp_enable(sc);
-
-m3_enable_ints(sc);
-
-M3_UNLOCK(sc); /* XXX */
-if (mixer_reinit(dev) == -1) {
-device_printf(dev, "unable to reinitialize the mixern");
-return (ENXIO);
-}
-M3_LOCK(sc);
-
-/* Turn the channels back on */
-for (i=0 ; i<sc->pch_cnt ; i++) {
-if (sc->pch[i].active) {
-m3_pchan_trigger_locked(NULL, &sc->pch[i],
-PCMTRIG_START);
-}
-}
-for (i=0 ; i<sc->rch_cnt ; i++) {
-if (sc->rch[i].active) {
-m3_rchan_trigger_locked(NULL, &sc->rch[i],
-PCMTRIG_START);
-}
-}
-
-M3_UNLOCK(sc);
-return 0;
+ M3_UNLOCK(sc);
+ return 0;
}
static int
m3_pci_shutdown(device_t dev)
{
-struct sc_info *sc = pcm_getdevinfo(dev);
+ struct sc_info *sc = pcm_getdevinfo(dev);
-M3_DEBUG(CALL, ("m3_pci_shutdownn"));
+ M3_DEBUG(CALL, ("m3_pci_shutdown\n"));
-M3_LOCK(sc);
-m3_power(sc, 3); /* power off */
-M3_UNLOCK(sc);
+ M3_LOCK(sc);
+ m3_power(sc, 3); /* power off */
+ M3_UNLOCK(sc);
-return 0;
+ return 0;
}
static u_int8_t
m3_assp_halt(struct sc_info *sc)
{
-u_int8_t data, reset_state;
+ u_int8_t data, reset_state;
-M3_LOCK_ASSERT(sc);
+ M3_LOCK_ASSERT(sc);
-data = m3_rd_1(sc, DSP_PORT_CONTROL_REG_B);
-reset_state = data & ~REGB_STOP_CLOCK; /* remember for continue */
-DELAY(10 * 1000);
-m3_wr_1(sc, DSP_PORT_CONTROL_REG_B, reset_state & ~REGB_ENABLE_RESET);
-DELAY(10 * 1000); /* necessary? */
+ data = m3_rd_1(sc, DSP_PORT_CONTROL_REG_B);
+ reset_state = data & ~REGB_STOP_CLOCK; /* remember for continue */
+ DELAY(10 * 1000);
+ m3_wr_1(sc, DSP_PORT_CONTROL_REG_B, reset_state & ~REGB_ENABLE_RESET);
+ DELAY(10 * 1000); /* necessary? */
-return reset_state;
+ return reset_state;
}
static void
m3_config(struct sc_info *sc)
{
-u_int32_t data, hv_cfg;
-int hint;
+ u_int32_t data, hv_cfg;
+ int hint;
-M3_LOCK_ASSERT(sc);
+ M3_LOCK_ASSERT(sc);
-M3_UNLOCK(sc);
-/*
-* The volume buttons can be wired up via two different sets of pins.
-* This presents a problem since we can't tell which way it's
-* configured. Allow the user to set a hint in order to twiddle
-* the proper bits.
-*/
-if (resource_int_value(device_get_name(sc->dev),
-device_get_unit(sc->dev),
-"hwvol_config", &hint) == 0)
-hv_cfg = (hint > 0) ? HV_BUTTON_FROM_GD : 0;
-else
-hv_cfg = HV_BUTTON_FROM_GD;
-M3_LOCK(sc);
-
-data = pci_read_config(sc->dev, PCI_ALLEGRO_CONFIG, 4);
-data &= ~HV_BUTTON_FROM_GD;
-data |= REDUCED_DEBOUNCE | HV_CTRL_ENABLE | hv_cfg;
-data |= PM_CTRL_ENABLE | CLK_DIV_BY_49 | USE_PCI_TIMING;
-pci_write_config(sc->dev, PCI_ALLEGRO_CONFIG, data, 4);
-
-m3_wr_1(sc, ASSP_CONTROL_B, RESET_ASSP);
-data = pci_read_config(sc->dev, PCI_ALLEGRO_CONFIG, 4);
-data &= ~INT_CLK_SELECT;
-if (sc->which == ESS_MAESTRO3) {
-data &= ~INT_CLK_MULT_ENABLE;
-data |= INT_CLK_SRC_NOT_PCI;
-}
-data &= ~(CLK_MULT_MODE_SELECT | CLK_MULT_MODE_SELECT_2);
-pci_write_config(sc->dev, PCI_ALLEGRO_CONFIG, data, 4);
-
-if (sc->which == ESS_ALLEGRO_1) {
-data = pci_read_config(sc->dev, PCI_USER_CONFIG, 4);
-data |= IN_CLK_12MHZ_SELECT;
-pci_write_config(sc->dev, PCI_USER_CONFIG, data, 4);
-}
-
-data = m3_rd_1(sc, ASSP_CONTROL_A);
-data &= ~(DSP_CLK_36MHZ_SELECT | ASSP_CLK_49MHZ_SELECT);
-data |= ASSP_CLK_49MHZ_SELECT; /*XXX assumes 49MHZ dsp XXX*/
-data |= ASSP_0_WS_ENABLE;
-m3_wr_1(sc, ASSP_CONTROL_A, data);
+ M3_UNLOCK(sc);
+ /*
+ * The volume buttons can be wired up via two different sets of pins.
+ * This presents a problem since we can't tell which way it's
+ * configured. Allow the user to set a hint in order to twiddle
+ * the proper bits.
+ */
+ if (resource_int_value(device_get_name(sc->dev),
+ device_get_unit(sc->dev),
+ "hwvol_config", &hint) == 0)
+ hv_cfg = (hint > 0) ? HV_BUTTON_FROM_GD : 0;
+ else
+ hv_cfg = HV_BUTTON_FROM_GD;
+ M3_LOCK(sc);
+
+ data = pci_read_config(sc->dev, PCI_ALLEGRO_CONFIG, 4);
+ data &= ~HV_BUTTON_FROM_GD;
+ data |= REDUCED_DEBOUNCE | HV_CTRL_ENABLE | hv_cfg;
+ data |= PM_CTRL_ENABLE | CLK_DIV_BY_49 | USE_PCI_TIMING;
+ pci_write_config(sc->dev, PCI_ALLEGRO_CONFIG, data, 4);
+
+ m3_wr_1(sc, ASSP_CONTROL_B, RESET_ASSP);
+ data = pci_read_config(sc->dev, PCI_ALLEGRO_CONFIG, 4);
+ data &= ~INT_CLK_SELECT;
+ if (sc->which == ESS_MAESTRO3) {
+ data &= ~INT_CLK_MULT_ENABLE;
+ data |= INT_CLK_SRC_NOT_PCI;
+ }
+ data &= ~(CLK_MULT_MODE_SELECT | CLK_MULT_MODE_SELECT_2);
+ pci_write_config(sc->dev, PCI_ALLEGRO_CONFIG, data, 4);
+
+ if (sc->which == ESS_ALLEGRO_1) {
+ data = pci_read_config(sc->dev, PCI_USER_CONFIG, 4);
+ data |= IN_CLK_12MHZ_SELECT;
+ pci_write_config(sc->dev, PCI_USER_CONFIG, data, 4);
+ }
+
+ data = m3_rd_1(sc, ASSP_CONTROL_A);
+ data &= ~(DSP_CLK_36MHZ_SELECT | ASSP_CLK_49MHZ_SELECT);
+ data |= ASSP_CLK_49MHZ_SELECT; /*XXX assumes 49MHZ dsp XXX*/
+ data |= ASSP_0_WS_ENABLE;
+ m3_wr_1(sc, ASSP_CONTROL_A, data);
-m3_wr_1(sc, ASSP_CONTROL_B, RUN_ASSP);
+ m3_wr_1(sc, ASSP_CONTROL_B, RUN_ASSP);
}
static void
m3_enable_ints(struct sc_info *sc)
{
-u_int8_t data;
+ u_int8_t data;
-m3_wr_2(sc, HOST_INT_CTRL, ASSP_INT_ENABLE | HV_INT_ENABLE);
-data = m3_rd_1(sc, ASSP_CONTROL_C);
-m3_wr_1(sc, ASSP_CONTROL_C, data | ASSP_HOST_INT_ENABLE);
+ m3_wr_2(sc, HOST_INT_CTRL, ASSP_INT_ENABLE | HV_INT_ENABLE);
+ data = m3_rd_1(sc, ASSP_CONTROL_C);
+ m3_wr_1(sc, ASSP_CONTROL_C, data | ASSP_HOST_INT_ENABLE);
}
static void
m3_amp_enable(struct sc_info *sc)
{
-u_int32_t gpo, polarity_port, polarity;
-u_int16_t data;
+ u_int32_t gpo, polarity_port, polarity;
+ u_int16_t data;
-M3_LOCK_ASSERT(sc);
+ M3_LOCK_ASSERT(sc);
-switch (sc->which) {
-case ESS_ALLEGRO_1:
-polarity_port = 0x1800;
-break;
-case ESS_MAESTRO3:
-polarity_port = 0x1100;
-break;
-default:
-panic("bad sc->which");
-}
-gpo = (polarity_port >> 8) & 0x0f;
-polarity = polarity_port >> 12;
-polarity = !polarity; /* enable */
-polarity = polarity << gpo;
-gpo = 1 << gpo;
-m3_wr_2(sc, GPIO_MASK, ~gpo);
-data = m3_rd_2(sc, GPIO_DIRECTION);
-m3_wr_2(sc, GPIO_DIRECTION, data | gpo);
-data = GPO_SECONDARY_AC97 | GPO_PRIMARY_AC97 | polarity;
-m3_wr_2(sc, GPIO_DATA, data);
-m3_wr_2(sc, GPIO_MASK, ~0);
+ switch (sc->which) {
+ case ESS_ALLEGRO_1:
+ polarity_port = 0x1800;
+ break;
+ case ESS_MAESTRO3:
+ polarity_port = 0x1100;
+ break;
+ default:
+ panic("bad sc->which");
+ }
+ gpo = (polarity_port >> 8) & 0x0f;
+ polarity = polarity_port >> 12;
+ polarity = !polarity; /* enable */
+ polarity = polarity << gpo;
+ gpo = 1 << gpo;
+ m3_wr_2(sc, GPIO_MASK, ~gpo);
+ data = m3_rd_2(sc, GPIO_DIRECTION);
+ m3_wr_2(sc, GPIO_DIRECTION, data | gpo);
+ data = GPO_SECONDARY_AC97 | GPO_PRIMARY_AC97 | polarity;
+ m3_wr_2(sc, GPIO_DATA, data);
+ m3_wr_2(sc, GPIO_MASK, ~0);
}
static void
m3_codec_reset(struct sc_info *sc)
{
-u_int16_t data, dir;
-int retry = 0;
+ u_int16_t data, dir;
+ int retry = 0;
-M3_LOCK_ASSERT(sc);
-do {
-data = m3_rd_2(sc, GPIO_DIRECTION);
-dir = data | 0x10; /* assuming pci bus master? */
-
-/* [[remote_codec_config]] */
-data = m3_rd_2(sc, RING_BUS_CTRL_B);
-m3_wr_2(sc, RING_BUS_CTRL_B, data & ~SECOND_CODEC_ID_MASK);
-data = m3_rd_2(sc, SDO_OUT_DEST_CTRL);
-m3_wr_2(sc, SDO_OUT_DEST_CTRL, data & ~COMMAND_ADDR_OUT);
-data = m3_rd_2(sc, SDO_IN_DEST_CTRL);
-m3_wr_2(sc, SDO_IN_DEST_CTRL, data & ~STATUS_ADDR_IN);
-
-m3_wr_2(sc, RING_BUS_CTRL_A, IO_SRAM_ENABLE);
-DELAY(20);
-
-m3_wr_2(sc, GPIO_DIRECTION, dir & ~GPO_PRIMARY_AC97);
-m3_wr_2(sc, GPIO_MASK, ~GPO_PRIMARY_AC97);
-m3_wr_2(sc, GPIO_DATA, 0);
-m3_wr_2(sc, GPIO_DIRECTION, dir | GPO_PRIMARY_AC97);
-DELAY(sc->delay1 * 1000); /*delay1 (ALLEGRO:50, MAESTRO3:20)*/
-m3_wr_2(sc, GPIO_DATA, GPO_PRIMARY_AC97);
-DELAY(5);
-m3_wr_2(sc, RING_BUS_CTRL_A, IO_SRAM_ENABLE |
-SERIAL_AC_LINK_ENABLE);
-m3_wr_2(sc, GPIO_MASK, ~0);
-DELAY(sc->delay2 * 1000); /*delay2 (ALLEGRO:800, MAESTRO3:500)*/
-
-/* [[try read vendor]] */
-data = m3_rdcd(NULL, sc, 0x7c);
-if ((data == 0) || (data == 0xffff)) {
-retry++;
-if (retry > 3) {
-device_printf(sc->dev, "Codec reset failedn");
-break;
-}
-device_printf(sc->dev, "Codec reset retryn");
-} else retry = 0;
-} while (retry);
+ M3_LOCK_ASSERT(sc);
+ do {
+ data = m3_rd_2(sc, GPIO_DIRECTION);
+ dir = data | 0x10; /* assuming pci bus master? */
+
+ /* [[remote_codec_config]] */
+ data = m3_rd_2(sc, RING_BUS_CTRL_B);
+ m3_wr_2(sc, RING_BUS_CTRL_B, data & ~SECOND_CODEC_ID_MASK);
+ data = m3_rd_2(sc, SDO_OUT_DEST_CTRL);
+ m3_wr_2(sc, SDO_OUT_DEST_CTRL, data & ~COMMAND_ADDR_OUT);
+ data = m3_rd_2(sc, SDO_IN_DEST_CTRL);
+ m3_wr_2(sc, SDO_IN_DEST_CTRL, data & ~STATUS_ADDR_IN);
+
+ m3_wr_2(sc, RING_BUS_CTRL_A, IO_SRAM_ENABLE);
+ DELAY(20);
+
+ m3_wr_2(sc, GPIO_DIRECTION, dir & ~GPO_PRIMARY_AC97);
+ m3_wr_2(sc, GPIO_MASK, ~GPO_PRIMARY_AC97);
+ m3_wr_2(sc, GPIO_DATA, 0);
+ m3_wr_2(sc, GPIO_DIRECTION, dir | GPO_PRIMARY_AC97);
+ DELAY(sc->delay1 * 1000); /*delay1 (ALLEGRO:50, MAESTRO3:20)*/
+ m3_wr_2(sc, GPIO_DATA, GPO_PRIMARY_AC97);
+ DELAY(5);
+ m3_wr_2(sc, RING_BUS_CTRL_A, IO_SRAM_ENABLE |
+ SERIAL_AC_LINK_ENABLE);
+ m3_wr_2(sc, GPIO_MASK, ~0);
+ DELAY(sc->delay2 * 1000); /*delay2 (ALLEGRO:800, MAESTRO3:500)*/
+
+ /* [[try read vendor]] */
+ data = m3_rdcd(NULL, sc, 0x7c);
+ if ((data == 0) || (data == 0xffff)) {
+ retry++;
+ if (retry > 3) {
+ device_printf(sc->dev, "Codec reset failed\n");
+ break;
+ }
+ device_printf(sc->dev, "Codec reset retry\n");
+ } else retry = 0;
+ } while (retry);
}
static device_method_t m3_methods[] = {
-DEVMETHOD(device_probe, m3_pci_probe),
-DEVMETHOD(device_attach, m3_pci_attach),
-DEVMETHOD(device_detach, m3_pci_detach),
-DEVMETHOD(device_suspend, m3_pci_suspend),
-DEVMETHOD(device_resume, m3_pci_resume),
-DEVMETHOD(device_shutdown, m3_pci_shutdown),
-{ 0, 0 }
+ DEVMETHOD(device_probe, m3_pci_probe),
+ DEVMETHOD(device_attach, m3_pci_attach),
+ DEVMETHOD(device_detach, m3_pci_detach),
+ DEVMETHOD(device_suspend, m3_pci_suspend),
+ DEVMETHOD(device_resume, m3_pci_resume),
+ DEVMETHOD(device_shutdown, m3_pci_shutdown),
+ { 0, 0 }
};
static driver_t m3_driver = {
-"pcm",
-m3_methods,
-PCM_SOFTC_SIZE,
+ "pcm",
+ m3_methods,
+ PCM_SOFTC_SIZE,
};
DRIVER_MODULE(snd_maestro3, pci, m3_driver, pcm_devclass, 0, 0);
Index: solo.c
===================================================================
RCS file: /home/cvs/src/sys/dev/sound/pci/solo.c,v
retrieving revision 1.2
retrieving revision 1.3
diff -L sys/dev/sound/pci/solo.c -L sys/dev/sound/pci/solo.c -u -r1.2 -r1.3
--- sys/dev/sound/pci/solo.c
+++ sys/dev/sound/pci/solo.c
@@ -1,27 +1,27 @@
/*-
-* Copyright (c) 1999 Cameron Grant <cg at freebsd.org>
-*
-* Redistribution and use in source and binary forms, with or without
-* modification, are permitted provided that the following conditions
-* are met:
-* 1. Redistributions of source code must retain the above copyright
-* notice, this list of conditions and the following disclaimer.
-* 2. Redistributions in binary form must reproduce the above copyright
-* notice, this list of conditions and the following disclaimer in the
-* documentation and/or other materials provided with the distribution.
-*
-* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
-* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
-* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
-* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
-* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
-* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
-* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
-* SUCH DAMAGE.
-*/
+ * Copyright (c) 1999 Cameron Grant <cg at freebsd.org>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
#include <dev/sound/pcm/sound.h>
@@ -33,7 +33,7 @@
#include "mixer_if.h"
-SND_DECLARE_FILE("$MidnightBSD$");
+SND_DECLARE_FILE("$FreeBSD: src/sys/dev/sound/pci/solo.c,v 1.45 2007/06/17 06:10:42 ariff Exp $");
#define SOLO_DEFAULT_BUFSZ 16384
#define ABS(x) (((x) < 0)? -(x) : (x))
@@ -48,56 +48,57 @@
#define ESS18XX_MPSAFE 1
static u_int32_t ess_playfmt[] = {
-AFMT_U8,
-AFMT_STEREO | AFMT_U8,
-AFMT_S8,
-AFMT_STEREO | AFMT_S8,
-AFMT_S16_LE,
-AFMT_STEREO | AFMT_S16_LE,
-AFMT_U16_LE,
-AFMT_STEREO | AFMT_U16_LE,
-0
+ AFMT_U8,
+ AFMT_STEREO | AFMT_U8,
+ AFMT_S8,
+ AFMT_STEREO | AFMT_S8,
+ AFMT_S16_LE,
+ AFMT_STEREO | AFMT_S16_LE,
+ AFMT_U16_LE,
+ AFMT_STEREO | AFMT_U16_LE,
+ 0
};
static struct pcmchan_caps ess_playcaps = {6000, 48000, ess_playfmt, 0};
/*
-* Recording output is byte-swapped
-*/
+ * Recording output is byte-swapped
+ */
static u_int32_t ess_recfmt[] = {
-AFMT_U8,
-AFMT_STEREO | AFMT_U8,
-AFMT_S8,
-AFMT_STEREO | AFMT_S8,
-AFMT_S16_BE,
-AFMT_STEREO | AFMT_S16_BE,
-AFMT_U16_BE,
-AFMT_STEREO | AFMT_U16_BE,
-0
+ AFMT_U8,
+ AFMT_STEREO | AFMT_U8,
+ AFMT_S8,
+ AFMT_STEREO | AFMT_S8,
+ AFMT_S16_BE,
+ AFMT_STEREO | AFMT_S16_BE,
+ AFMT_U16_BE,
+ AFMT_STEREO | AFMT_U16_BE,
+ 0
};
static struct pcmchan_caps ess_reccaps = {6000, 48000, ess_recfmt, 0};
struct ess_info;
struct ess_chinfo {
-struct ess_info *parent;
-struct pcm_channel *channel;
-struct snd_dbuf *buffer;
-int dir, hwch, stopping;
-u_int32_t fmt, spd, blksz;
+ struct ess_info *parent;
+ struct pcm_channel *channel;
+ struct snd_dbuf *buffer;
+ int dir, hwch, stopping;
+ u_int32_t fmt, spd, blksz;
};
struct ess_info {
-struct resource *io, *sb, *vc, *mpu, *gp; /* I/O address for the board */
-struct resource *irq;
-void *ih;
-bus_dma_tag_t parent_dmat;
+ struct resource *io, *sb, *vc, *mpu, *gp; /* I/O address for the board */
+ struct resource *irq;
+ void *ih;
+ bus_dma_tag_t parent_dmat;
+
+ int simplex_dir, type, dmasz[2];
+ unsigned int duplex:1, newspeed:1;
+ unsigned int bufsz;
-int simplex_dir, type, duplex:1, newspeed:1, dmasz[2];
-unsigned int bufsz;
-
-struct ess_chinfo pch, rch;
+ struct ess_chinfo pch, rch;
#if ESS18XX_MPSAFE == 1
-struct mtx *lock;
+ struct mtx *lock;
#endif
};
@@ -134,395 +135,395 @@
static int ess_dmatrigger(struct ess_info *sc, int ch, int go);
/*
-* Common code for the midi and pcm functions
-*
-* ess_cmd write a single byte to the CMD port.
-* ess_cmd1 write a CMD + 1 byte arg
-* ess_cmd2 write a CMD + 2 byte arg
-* ess_get_byte returns a single byte from the DSP data port
-*
-* ess_write is actually ess_cmd1
-* ess_read access ext. regs via ess_cmd(0xc0, reg) followed by ess_get_byte
-*/
+ * Common code for the midi and pcm functions
+ *
+ * ess_cmd write a single byte to the CMD port.
+ * ess_cmd1 write a CMD + 1 byte arg
+ * ess_cmd2 write a CMD + 2 byte arg
+ * ess_get_byte returns a single byte from the DSP data port
+ *
+ * ess_write is actually ess_cmd1
+ * ess_read access ext. regs via ess_cmd(0xc0, reg) followed by ess_get_byte
+ */
static int
port_rd(struct resource *port, int regno, int size)
{
-bus_space_tag_t st = rman_get_bustag(port);
-bus_space_handle_t sh = rman_get_bushandle(port);
+ bus_space_tag_t st = rman_get_bustag(port);
+ bus_space_handle_t sh = rman_get_bushandle(port);
-switch (size) {
-case 1:
-return bus_space_read_1(st, sh, regno);
-case 2:
-return bus_space_read_2(st, sh, regno);
-case 4:
-return bus_space_read_4(st, sh, regno);
-default:
-return 0xffffffff;
-}
+ switch (size) {
+ case 1:
+ return bus_space_read_1(st, sh, regno);
+ case 2:
+ return bus_space_read_2(st, sh, regno);
+ case 4:
+ return bus_space_read_4(st, sh, regno);
+ default:
+ return 0xffffffff;
+ }
}
static void
port_wr(struct resource *port, int regno, u_int32_t data, int size)
{
-bus_space_tag_t st = rman_get_bustag(port);
-bus_space_handle_t sh = rman_get_bushandle(port);
+ bus_space_tag_t st = rman_get_bustag(port);
+ bus_space_handle_t sh = rman_get_bushandle(port);
-switch (size) {
-case 1:
-bus_space_write_1(st, sh, regno, data);
-break;
-case 2:
-bus_space_write_2(st, sh, regno, data);
-break;
-case 4:
-bus_space_write_4(st, sh, regno, data);
-break;
-}
+ switch (size) {
+ case 1:
+ bus_space_write_1(st, sh, regno, data);
+ break;
+ case 2:
+ bus_space_write_2(st, sh, regno, data);
+ break;
+ case 4:
+ bus_space_write_4(st, sh, regno, data);
+ break;
+ }
}
static int
ess_rd(struct ess_info *sc, int reg)
{
-return port_rd(sc->sb, reg, 1);
+ return port_rd(sc->sb, reg, 1);
}
static void
ess_wr(struct ess_info *sc, int reg, u_int8_t val)
{
-port_wr(sc->sb, reg, val, 1);
+ port_wr(sc->sb, reg, val, 1);
}
static int
ess_dspready(struct ess_info *sc)
{
-return ((ess_rd(sc, SBDSP_STATUS) & 0x80) == 0);
+ return ((ess_rd(sc, SBDSP_STATUS) & 0x80) == 0);
}
static int
ess_dspwr(struct ess_info *sc, u_char val)
{
-int i;
+ int i;
-for (i = 0; i < 1000; i++) {
-if (ess_dspready(sc)) {
-ess_wr(sc, SBDSP_CMD, val);
-return 1;
-}
-if (i > 10) DELAY((i > 100)? 1000 : 10);
-}
-printf("ess_dspwr(0x%02x) timed out.n", val);
-return 0;
+ for (i = 0; i < 1000; i++) {
+ if (ess_dspready(sc)) {
+ ess_wr(sc, SBDSP_CMD, val);
+ return 1;
+ }
+ if (i > 10) DELAY((i > 100)? 1000 : 10);
+ }
+ printf("ess_dspwr(0x%02x) timed out.\n", val);
+ return 0;
}
static int
ess_cmd(struct ess_info *sc, u_char val)
{
-DEB(printf("ess_cmd: %xn", val));
-return ess_dspwr(sc, val);
+ DEB(printf("ess_cmd: %x\n", val));
+ return ess_dspwr(sc, val);
}
static int
ess_cmd1(struct ess_info *sc, u_char cmd, int val)
{
-DEB(printf("ess_cmd1: %x, %xn", cmd, val));
-if (ess_dspwr(sc, cmd)) {
-return ess_dspwr(sc, val & 0xff);
-} else return 0;
+ DEB(printf("ess_cmd1: %x, %x\n", cmd, val));
+ if (ess_dspwr(sc, cmd)) {
+ return ess_dspwr(sc, val & 0xff);
+ } else return 0;
}
static void
ess_setmixer(struct ess_info *sc, u_int port, u_int value)
{
-DEB(printf("ess_setmixer: reg=%x, val=%xn", port, value);)
-ess_wr(sc, SB_MIX_ADDR, (u_char) (port & 0xff)); /* Select register */
-DELAY(10);
-ess_wr(sc, SB_MIX_DATA, (u_char) (value & 0xff));
-DELAY(10);
+ DEB(printf("ess_setmixer: reg=%x, val=%x\n", port, value);)
+ ess_wr(sc, SB_MIX_ADDR, (u_char) (port & 0xff)); /* Select register */
+ DELAY(10);
+ ess_wr(sc, SB_MIX_DATA, (u_char) (value & 0xff));
+ DELAY(10);
}
static int
ess_getmixer(struct ess_info *sc, u_int port)
{
-int val;
+ int val;
-ess_wr(sc, SB_MIX_ADDR, (u_char) (port & 0xff)); /* Select register */
-DELAY(10);
-val = ess_rd(sc, SB_MIX_DATA);
-DELAY(10);
+ ess_wr(sc, SB_MIX_ADDR, (u_char) (port & 0xff)); /* Select register */
+ DELAY(10);
+ val = ess_rd(sc, SB_MIX_DATA);
+ DELAY(10);
-return val;
+ return val;
}
static int
ess_get_byte(struct ess_info *sc)
{
-int i;
+ int i;
-for (i = 1000; i > 0; i--) {
-if (ess_rd(sc, 0xc) & 0x40)
-return ess_rd(sc, DSP_READ);
-else
-DELAY(20);
-}
-return -1;
+ for (i = 1000; i > 0; i--) {
+ if (ess_rd(sc, 0xc) & 0x40)
+ return ess_rd(sc, DSP_READ);
+ else
+ DELAY(20);
+ }
+ return -1;
}
static int
ess_write(struct ess_info *sc, u_char reg, int val)
{
-return ess_cmd1(sc, reg, val);
+ return ess_cmd1(sc, reg, val);
}
static int
ess_read(struct ess_info *sc, u_char reg)
{
-return (ess_cmd(sc, 0xc0) && ess_cmd(sc, reg))? ess_get_byte(sc) : -1;
+ return (ess_cmd(sc, 0xc0) && ess_cmd(sc, reg))? ess_get_byte(sc) : -1;
}
static int
ess_reset_dsp(struct ess_info *sc)
{
-DEB(printf("ess_reset_dspn"));
-ess_wr(sc, SBDSP_RST, 3);
-DELAY(100);
-ess_wr(sc, SBDSP_RST, 0);
-if (ess_get_byte(sc) != 0xAA) {
-DEB(printf("ess_reset_dsp failedn"));
+ DEB(printf("ess_reset_dsp\n"));
+ ess_wr(sc, SBDSP_RST, 3);
+ DELAY(100);
+ ess_wr(sc, SBDSP_RST, 0);
+ if (ess_get_byte(sc) != 0xAA) {
+ DEB(printf("ess_reset_dsp failed\n"));
/*
-rman_get_start(d->io_base)));
+ rman_get_start(d->io_base)));
*/
-return ENXIO; /* Sorry */
-}
-ess_cmd(sc, 0xc6);
-return 0;
+ return ENXIO; /* Sorry */
+ }
+ ess_cmd(sc, 0xc6);
+ return 0;
}
static void
ess_intr(void *arg)
{
-struct ess_info *sc = (struct ess_info *)arg;
-int src, pirq = 0, rirq = 0;
+ struct ess_info *sc = (struct ess_info *)arg;
+ int src, pirq = 0, rirq = 0;
-ess_lock(sc);
-src = 0;
-if (ess_getmixer(sc, 0x7a) & 0x80)
-src |= 2;
-if (ess_rd(sc, 0x0c) & 0x01)
-src |= 1;
-
-if (src == 0) {
-ess_unlock(sc);
-return;
-}
-
-if (sc->duplex) {
-pirq = (src & sc->pch.hwch)? 1 : 0;
-rirq = (src & sc->rch.hwch)? 1 : 0;
-} else {
-if (sc->simplex_dir == PCMDIR_PLAY)
-pirq = 1;
-if (sc->simplex_dir == PCMDIR_REC)
-rirq = 1;
-if (!pirq && !rirq)
-printf("solo: IRQ neither playback nor rec!n");
-}
-
-DEB(printf("ess_intr: pirq:%d rirq:%dn",pirq,rirq));
-
-if (pirq) {
-if (sc->pch.stopping) {
-ess_dmatrigger(sc, sc->pch.hwch, 0);
-sc->pch.stopping = 0;
-if (sc->pch.hwch == 1)
-ess_write(sc, 0xb8, ess_read(sc, 0xb8) & ~0x01);
-else
-ess_setmixer(sc, 0x78, ess_getmixer(sc, 0x78) & ~0x03);
-}
-ess_unlock(sc);
-chn_intr(sc->pch.channel);
-ess_lock(sc);
-}
-
-if (rirq) {
-if (sc->rch.stopping) {
-ess_dmatrigger(sc, sc->rch.hwch, 0);
-sc->rch.stopping = 0;
-/* XXX: will this stop audio2? */
-ess_write(sc, 0xb8, ess_read(sc, 0xb8) & ~0x01);
-}
-ess_unlock(sc);
-chn_intr(sc->rch.channel);
-ess_lock(sc);
-}
-
-if (src & 2)
-ess_setmixer(sc, 0x7a, ess_getmixer(sc, 0x7a) & ~0x80);
-if (src & 1)
-ess_rd(sc, DSP_DATA_AVAIL);
+ ess_lock(sc);
+ src = 0;
+ if (ess_getmixer(sc, 0x7a) & 0x80)
+ src |= 2;
+ if (ess_rd(sc, 0x0c) & 0x01)
+ src |= 1;
+
+ if (src == 0) {
+ ess_unlock(sc);
+ return;
+ }
+
+ if (sc->duplex) {
+ pirq = (src & sc->pch.hwch)? 1 : 0;
+ rirq = (src & sc->rch.hwch)? 1 : 0;
+ } else {
+ if (sc->simplex_dir == PCMDIR_PLAY)
+ pirq = 1;
+ if (sc->simplex_dir == PCMDIR_REC)
+ rirq = 1;
+ if (!pirq && !rirq)
+ printf("solo: IRQ neither playback nor rec!\n");
+ }
+
+ DEB(printf("ess_intr: pirq:%d rirq:%d\n",pirq,rirq));
+
+ if (pirq) {
+ if (sc->pch.stopping) {
+ ess_dmatrigger(sc, sc->pch.hwch, 0);
+ sc->pch.stopping = 0;
+ if (sc->pch.hwch == 1)
+ ess_write(sc, 0xb8, ess_read(sc, 0xb8) & ~0x01);
+ else
+ ess_setmixer(sc, 0x78, ess_getmixer(sc, 0x78) & ~0x03);
+ }
+ ess_unlock(sc);
+ chn_intr(sc->pch.channel);
+ ess_lock(sc);
+ }
+
+ if (rirq) {
+ if (sc->rch.stopping) {
+ ess_dmatrigger(sc, sc->rch.hwch, 0);
+ sc->rch.stopping = 0;
+ /* XXX: will this stop audio2? */
+ ess_write(sc, 0xb8, ess_read(sc, 0xb8) & ~0x01);
+ }
+ ess_unlock(sc);
+ chn_intr(sc->rch.channel);
+ ess_lock(sc);
+ }
+
+ if (src & 2)
+ ess_setmixer(sc, 0x7a, ess_getmixer(sc, 0x7a) & ~0x80);
+ if (src & 1)
+ ess_rd(sc, DSP_DATA_AVAIL);
-ess_unlock(sc);
+ ess_unlock(sc);
}
/* utility functions for ESS */
static u_int8_t
ess_calcspeed8(int *spd)
{
-int speed = *spd;
-u_int32_t t;
+ int speed = *spd;
+ u_int32_t t;
-if (speed > 22000) {
-t = (795500 + speed / 2) / speed;
-speed = (795500 + t / 2) / t;
-t = (256 - t) | 0x80;
-} else {
-t = (397700 + speed / 2) / speed;
-speed = (397700 + t / 2) / t;
-t = 128 - t;
-}
-*spd = speed;
-return t & 0x000000ff;
+ if (speed > 22000) {
+ t = (795500 + speed / 2) / speed;
+ speed = (795500 + t / 2) / t;
+ t = (256 - t) | 0x80;
+ } else {
+ t = (397700 + speed / 2) / speed;
+ speed = (397700 + t / 2) / t;
+ t = 128 - t;
+ }
+ *spd = speed;
+ return t & 0x000000ff;
}
static u_int8_t
ess_calcspeed9(int *spd)
{
-int speed, s0, s1, use0;
-u_int8_t t0, t1;
+ int speed, s0, s1, use0;
+ u_int8_t t0, t1;
-/* rate = source / (256 - divisor) */
-/* divisor = 256 - (source / rate) */
-speed = *spd;
-t0 = 128 - (793800 / speed);
-s0 = 793800 / (128 - t0);
-
-t1 = 128 - (768000 / speed);
-s1 = 768000 / (128 - t1);
-t1 |= 0x80;
+ /* rate = source / (256 - divisor) */
+ /* divisor = 256 - (source / rate) */
+ speed = *spd;
+ t0 = 128 - (793800 / speed);
+ s0 = 793800 / (128 - t0);
+
+ t1 = 128 - (768000 / speed);
+ s1 = 768000 / (128 - t1);
+ t1 |= 0x80;
-use0 = (ABS(speed - s0) < ABS(speed - s1))? 1 : 0;
+ use0 = (ABS(speed - s0) < ABS(speed - s1))? 1 : 0;
-*spd = use0? s0 : s1;
-return use0? t0 : t1;
+ *spd = use0? s0 : s1;
+ return use0? t0 : t1;
}
static u_int8_t
ess_calcfilter(int spd)
{
-int cutoff;
+ int cutoff;
-/* cutoff = 7160000 / (256 - divisor) */
-/* divisor = 256 - (7160000 / cutoff) */
-cutoff = (spd * 9 * 82) / 20;
-return (256 - (7160000 / cutoff));
+ /* cutoff = 7160000 / (256 - divisor) */
+ /* divisor = 256 - (7160000 / cutoff) */
+ cutoff = (spd * 9 * 82) / 20;
+ return (256 - (7160000 / cutoff));
}
static int
ess_setupch(struct ess_info *sc, int ch, int dir, int spd, u_int32_t fmt, int len)
{
-int play = (dir == PCMDIR_PLAY)? 1 : 0;
-int b16 = (fmt & AFMT_16BIT)? 1 : 0;
-int stereo = (fmt & AFMT_STEREO)? 1 : 0;
-int unsign = (fmt == AFMT_U8 || fmt == AFMT_U16_LE || fmt == AFMT_U16_BE)? 1 : 0;
-u_int8_t spdval, fmtval;
-
-DEB(printf("ess_setupchn"));
-spdval = (sc->newspeed)? ess_calcspeed9(&spd) : ess_calcspeed8(&spd);
-
-sc->simplex_dir = play ? PCMDIR_PLAY : PCMDIR_REC ;
-
-if (ch == 1) {
-KASSERT((dir == PCMDIR_PLAY) || (dir == PCMDIR_REC), ("ess_setupch: dir1 bad"));
-len = -len;
-/* transfer length low */
-ess_write(sc, 0xa4, len & 0x00ff);
-/* transfer length high */
-ess_write(sc, 0xa5, (len & 0xff00) >> 8);
-/* autoinit, dma dir */
-ess_write(sc, 0xb8, 0x04 | (play? 0x00 : 0x0a));
-/* mono/stereo */
-ess_write(sc, 0xa8, (ess_read(sc, 0xa8) & ~0x03) | (stereo? 0x01 : 0x02));
-/* demand mode, 4 bytes/xfer */
-ess_write(sc, 0xb9, 0x02);
-/* sample rate */
-ess_write(sc, 0xa1, spdval);
-/* filter cutoff */
-ess_write(sc, 0xa2, ess_calcfilter(spd));
-/* setup dac/adc */
-/*
-if (play)
-ess_write(sc, 0xb6, unsign? 0x80 : 0x00);
-*/
-/* mono, b16: signed, load signal */
-/*
-ess_write(sc, 0xb7, 0x51 | (unsign? 0x00 : 0x20));
-*/
-/* setup fifo */
-ess_write(sc, 0xb7, 0x91 | (unsign? 0x00 : 0x20) |
-(b16? 0x04 : 0x00) |
-(stereo? 0x08 : 0x40));
-/* irq control */
-ess_write(sc, 0xb1, (ess_read(sc, 0xb1) & 0x0f) | 0x50);
-/* drq control */
-ess_write(sc, 0xb2, (ess_read(sc, 0xb2) & 0x0f) | 0x50);
-} else if (ch == 2) {
-KASSERT(dir == PCMDIR_PLAY, ("ess_setupch: dir2 bad"));
-len >>= 1;
-len = -len;
-/* transfer length low */
-ess_setmixer(sc, 0x74, len & 0x00ff);
-/* transfer length high */
-ess_setmixer(sc, 0x76, (len & 0xff00) >> 8);
-/* autoinit, 4 bytes/req */
-ess_setmixer(sc, 0x78, 0x10);
-fmtval = b16 | (stereo << 1) | ((!unsign) << 2);
-/* enable irq, set format */
-ess_setmixer(sc, 0x7a, 0x40 | fmtval);
-if (sc->newspeed) {
-/* sample rate */
-ess_setmixer(sc, 0x70, spdval);
-/* filter cutoff */
-ess_setmixer(sc, 0x72, ess_calcfilter(spd));
-}
+ int play = (dir == PCMDIR_PLAY)? 1 : 0;
+ int b16 = (fmt & AFMT_16BIT)? 1 : 0;
+ int stereo = (fmt & AFMT_STEREO)? 1 : 0;
+ int unsign = (fmt == AFMT_U8 || fmt == AFMT_U16_LE || fmt == AFMT_U16_BE)? 1 : 0;
+ u_int8_t spdval, fmtval;
+
+ DEB(printf("ess_setupch\n"));
+ spdval = (sc->newspeed)? ess_calcspeed9(&spd) : ess_calcspeed8(&spd);
+
+ sc->simplex_dir = play ? PCMDIR_PLAY : PCMDIR_REC ;
+
+ if (ch == 1) {
+ KASSERT((dir == PCMDIR_PLAY) || (dir == PCMDIR_REC), ("ess_setupch: dir1 bad"));
+ len = -len;
+ /* transfer length low */
+ ess_write(sc, 0xa4, len & 0x00ff);
+ /* transfer length high */
+ ess_write(sc, 0xa5, (len & 0xff00) >> 8);
+ /* autoinit, dma dir */
+ ess_write(sc, 0xb8, 0x04 | (play? 0x00 : 0x0a));
+ /* mono/stereo */
+ ess_write(sc, 0xa8, (ess_read(sc, 0xa8) & ~0x03) | (stereo? 0x01 : 0x02));
+ /* demand mode, 4 bytes/xfer */
+ ess_write(sc, 0xb9, 0x02);
+ /* sample rate */
+ ess_write(sc, 0xa1, spdval);
+ /* filter cutoff */
+ ess_write(sc, 0xa2, ess_calcfilter(spd));
+ /* setup dac/adc */
+ /*
+ if (play)
+ ess_write(sc, 0xb6, unsign? 0x80 : 0x00);
+ */
+ /* mono, b16: signed, load signal */
+ /*
+ ess_write(sc, 0xb7, 0x51 | (unsign? 0x00 : 0x20));
+ */
+ /* setup fifo */
+ ess_write(sc, 0xb7, 0x91 | (unsign? 0x00 : 0x20) |
+ (b16? 0x04 : 0x00) |
+ (stereo? 0x08 : 0x40));
+ /* irq control */
+ ess_write(sc, 0xb1, (ess_read(sc, 0xb1) & 0x0f) | 0x50);
+ /* drq control */
+ ess_write(sc, 0xb2, (ess_read(sc, 0xb2) & 0x0f) | 0x50);
+ } else if (ch == 2) {
+ KASSERT(dir == PCMDIR_PLAY, ("ess_setupch: dir2 bad"));
+ len >>= 1;
+ len = -len;
+ /* transfer length low */
+ ess_setmixer(sc, 0x74, len & 0x00ff);
+ /* transfer length high */
+ ess_setmixer(sc, 0x76, (len & 0xff00) >> 8);
+ /* autoinit, 4 bytes/req */
+ ess_setmixer(sc, 0x78, 0x10);
+ fmtval = b16 | (stereo << 1) | ((!unsign) << 2);
+ /* enable irq, set format */
+ ess_setmixer(sc, 0x7a, 0x40 | fmtval);
+ if (sc->newspeed) {
+ /* sample rate */
+ ess_setmixer(sc, 0x70, spdval);
+ /* filter cutoff */
+ ess_setmixer(sc, 0x72, ess_calcfilter(spd));
+ }
-}
-return 0;
+ }
+ return 0;
}
static int
ess_start(struct ess_chinfo *ch)
{
-struct ess_info *sc = ch->parent;
+ struct ess_info *sc = ch->parent;
-DEB(printf("ess_startn"););
-ess_setupch(sc, ch->hwch, ch->dir, ch->spd, ch->fmt, ch->blksz);
-ch->stopping = 0;
-if (ch->hwch == 1) {
-ess_write(sc, 0xb8, ess_read(sc, 0xb8) | 0x01);
-if (ch->dir == PCMDIR_PLAY) {
+ DEB(printf("ess_start\n"););
+ ess_setupch(sc, ch->hwch, ch->dir, ch->spd, ch->fmt, ch->blksz);
+ ch->stopping = 0;
+ if (ch->hwch == 1) {
+ ess_write(sc, 0xb8, ess_read(sc, 0xb8) | 0x01);
+ if (ch->dir == PCMDIR_PLAY) {
#if 0
-DELAY(100000); /* 100 ms */
+ DELAY(100000); /* 100 ms */
#endif
-ess_cmd(sc, 0xd1);
-}
-} else
-ess_setmixer(sc, 0x78, ess_getmixer(sc, 0x78) | 0x03);
-return 0;
+ ess_cmd(sc, 0xd1);
+ }
+ } else
+ ess_setmixer(sc, 0x78, ess_getmixer(sc, 0x78) | 0x03);
+ return 0;
}
static int
ess_stop(struct ess_chinfo *ch)
{
-struct ess_info *sc = ch->parent;
+ struct ess_info *sc = ch->parent;
-DEB(printf("ess_stopn"));
-ch->stopping = 1;
-if (ch->hwch == 1)
-ess_write(sc, 0xb8, ess_read(sc, 0xb8) & ~0x04);
-else
-ess_setmixer(sc, 0x78, ess_getmixer(sc, 0x78) & ~0x10);
-DEB(printf("done with stopn"));
-return 0;
+ DEB(printf("ess_stop\n"));
+ ch->stopping = 1;
+ if (ch->hwch == 1)
+ ess_write(sc, 0xb8, ess_read(sc, 0xb8) & ~0x04);
+ else
+ ess_setmixer(sc, 0x78, ess_getmixer(sc, 0x78) & ~0x10);
+ DEB(printf("done with stop\n"));
+ return 0;
}
/* -------------------------------------------------------------------- */
@@ -530,112 +531,113 @@
static void *
esschan_init(kobj_t obj, void *devinfo, struct snd_dbuf *b, struct pcm_channel *c, int dir)
{
-struct ess_info *sc = devinfo;
-struct ess_chinfo *ch = (dir == PCMDIR_PLAY)? &sc->pch : &sc->rch;
+ struct ess_info *sc = devinfo;
+ struct ess_chinfo *ch = (dir == PCMDIR_PLAY)? &sc->pch : &sc->rch;
-DEB(printf("esschan_initn"));
-ch->parent = sc;
-ch->channel = c;
-ch->buffer = b;
-ch->dir = dir;
-if (sndbuf_alloc(ch->buffer, sc->parent_dmat, sc->bufsz) != 0)
-return NULL;
-ch->hwch = 1;
-if ((dir == PCMDIR_PLAY) && (sc->duplex))
-ch->hwch = 2;
-return ch;
+ DEB(printf("esschan_init\n"));
+ ch->parent = sc;
+ ch->channel = c;
+ ch->buffer = b;
+ ch->dir = dir;
+ if (sndbuf_alloc(ch->buffer, sc->parent_dmat, 0, sc->bufsz) != 0)
+ return NULL;
+ ch->hwch = 1;
+ if ((dir == PCMDIR_PLAY) && (sc->duplex))
+ ch->hwch = 2;
+ return ch;
}
static int
esschan_setformat(kobj_t obj, void *data, u_int32_t format)
{
-struct ess_chinfo *ch = data;
+ struct ess_chinfo *ch = data;
-ch->fmt = format;
-return 0;
+ ch->fmt = format;
+ return 0;
}
static int
esschan_setspeed(kobj_t obj, void *data, u_int32_t speed)
{
-struct ess_chinfo *ch = data;
-struct ess_info *sc = ch->parent;
+ struct ess_chinfo *ch = data;
+ struct ess_info *sc = ch->parent;
-ch->spd = speed;
-if (sc->newspeed)
-ess_calcspeed9(&ch->spd);
-else
-ess_calcspeed8(&ch->spd);
-return ch->spd;
+ ch->spd = speed;
+ if (sc->newspeed)
+ ess_calcspeed9(&ch->spd);
+ else
+ ess_calcspeed8(&ch->spd);
+ return ch->spd;
}
static int
esschan_setblocksize(kobj_t obj, void *data, u_int32_t blocksize)
{
-struct ess_chinfo *ch = data;
+ struct ess_chinfo *ch = data;
-ch->blksz = blocksize;
-return ch->blksz;
+ ch->blksz = blocksize;
+ return ch->blksz;
}
static int
esschan_trigger(kobj_t obj, void *data, int go)
{
-struct ess_chinfo *ch = data;
-struct ess_info *sc = ch->parent;
+ struct ess_chinfo *ch = data;
+ struct ess_info *sc = ch->parent;
-DEB(printf("esschan_trigger: %dn",go));
-if (go == PCMTRIG_EMLDMAWR || go == PCMTRIG_EMLDMARD)
-return 0;
-
-ess_lock(sc);
-switch (go) {
-case PCMTRIG_START:
-ess_dmasetup(sc, ch->hwch, sndbuf_getbufaddr(ch->buffer), sndbuf_getsize(ch->buffer), ch->dir);
-ess_dmatrigger(sc, ch->hwch, 1);
-ess_start(ch);
-break;
-
-case PCMTRIG_STOP:
-case PCMTRIG_ABORT:
-default:
-ess_stop(ch);
-break;
-}
-ess_unlock(sc);
-return 0;
+ if (!PCMTRIG_COMMON(go))
+ return 0;
+
+ DEB(printf("esschan_trigger: %d\n",go));
+
+ ess_lock(sc);
+ switch (go) {
+ case PCMTRIG_START:
+ ess_dmasetup(sc, ch->hwch, sndbuf_getbufaddr(ch->buffer), sndbuf_getsize(ch->buffer), ch->dir);
+ ess_dmatrigger(sc, ch->hwch, 1);
+ ess_start(ch);
+ break;
+
+ case PCMTRIG_STOP:
+ case PCMTRIG_ABORT:
+ default:
+ ess_stop(ch);
+ break;
+ }
+ ess_unlock(sc);
+ return 0;
}
static int
esschan_getptr(kobj_t obj, void *data)
{
-struct ess_chinfo *ch = data;
-struct ess_info *sc = ch->parent;
-int ret;
-
-ess_lock(sc);
-ret = ess_dmapos(sc, ch->hwch);
-ess_unlock(sc);
-return ret;
+ struct ess_chinfo *ch = data;
+ struct ess_info *sc = ch->parent;
+ int ret;
+
+ ess_lock(sc);
+ ret = ess_dmapos(sc, ch->hwch);
+ ess_unlock(sc);
+ return ret;
}
static struct pcmchan_caps *
esschan_getcaps(kobj_t obj, void *data)
{
-struct ess_chinfo *ch = data;
+ struct ess_chinfo *ch = data;
-return (ch->dir == PCMDIR_PLAY)? &ess_playcaps : &ess_reccaps;
+ return (ch->dir == PCMDIR_PLAY)? &ess_playcaps : &ess_reccaps;
}
static kobj_method_t esschan_methods[] = {
-KOBJMETHOD(channel_init, esschan_init),
-KOBJMETHOD(channel_setformat, esschan_setformat),
-KOBJMETHOD(channel_setspeed, esschan_setspeed),
-KOBJMETHOD(channel_setblocksize, esschan_setblocksize),
-KOBJMETHOD(channel_trigger, esschan_trigger),
-KOBJMETHOD(channel_getptr, esschan_getptr),
-KOBJMETHOD(channel_getcaps, esschan_getcaps),
-{ 0, 0 }
+ KOBJMETHOD(channel_init, esschan_init),
+ KOBJMETHOD(channel_setformat, esschan_setformat),
+ KOBJMETHOD(channel_setspeed, esschan_setspeed),
+ KOBJMETHOD(channel_setblocksize, esschan_setblocksize),
+ KOBJMETHOD(channel_trigger, esschan_trigger),
+ KOBJMETHOD(channel_getptr, esschan_getptr),
+ KOBJMETHOD(channel_getcaps, esschan_getcaps),
+ { 0, 0 }
};
CHANNEL_DECLARE(esschan);
@@ -644,116 +646,116 @@
static int
essmix_init(struct snd_mixer *m)
{
-struct ess_info *sc = mix_getdevinfo(m);
+ struct ess_info *sc = mix_getdevinfo(m);
-mix_setrecdevs(m, SOUND_MASK_CD | SOUND_MASK_MIC | SOUND_MASK_LINE |
-SOUND_MASK_IMIX);
+ mix_setrecdevs(m, SOUND_MASK_CD | SOUND_MASK_MIC | SOUND_MASK_LINE |
+ SOUND_MASK_IMIX);
-mix_setdevs(m, SOUND_MASK_SYNTH | SOUND_MASK_PCM | SOUND_MASK_LINE |
-SOUND_MASK_MIC | SOUND_MASK_CD | SOUND_MASK_VOLUME |
-SOUND_MASK_LINE1);
+ mix_setdevs(m, SOUND_MASK_SYNTH | SOUND_MASK_PCM | SOUND_MASK_LINE |
+ SOUND_MASK_MIC | SOUND_MASK_CD | SOUND_MASK_VOLUME |
+ SOUND_MASK_LINE1);
-ess_setmixer(sc, 0, 0); /* reset */
+ ess_setmixer(sc, 0, 0); /* reset */
-return 0;
+ return 0;
}
static int
essmix_set(struct snd_mixer *m, unsigned dev, unsigned left, unsigned right)
{
-struct ess_info *sc = mix_getdevinfo(m);
-int preg = 0, rreg = 0, l, r;
+ struct ess_info *sc = mix_getdevinfo(m);
+ int preg = 0, rreg = 0, l, r;
-l = (left * 15) / 100;
-r = (right * 15) / 100;
-switch (dev) {
-case SOUND_MIXER_SYNTH:
-preg = 0x36;
-rreg = 0x6b;
-break;
-
-case SOUND_MIXER_PCM:
-preg = 0x14;
-rreg = 0x7c;
-break;
-
-case SOUND_MIXER_LINE:
-preg = 0x3e;
-rreg = 0x6e;
-break;
-
-case SOUND_MIXER_MIC:
-preg = 0x1a;
-rreg = 0x68;
-break;
-
-case SOUND_MIXER_LINE1:
-preg = 0x3a;
-rreg = 0x6c;
-break;
-
-case SOUND_MIXER_CD:
-preg = 0x38;
-rreg = 0x6a;
-break;
-
-case SOUND_MIXER_VOLUME:
-l = left? (left * 63) / 100 : 64;
-r = right? (right * 63) / 100 : 64;
-ess_setmixer(sc, 0x60, l);
-ess_setmixer(sc, 0x62, r);
-left = (l == 64)? 0 : (l * 100) / 63;
-right = (r == 64)? 0 : (r * 100) / 63;
-return left | (right << 8);
-}
-
-if (preg)
-ess_setmixer(sc, preg, (l << 4) | r);
-if (rreg)
-ess_setmixer(sc, rreg, (l << 4) | r);
+ l = (left * 15) / 100;
+ r = (right * 15) / 100;
+ switch (dev) {
+ case SOUND_MIXER_SYNTH:
+ preg = 0x36;
+ rreg = 0x6b;
+ break;
+
+ case SOUND_MIXER_PCM:
+ preg = 0x14;
+ rreg = 0x7c;
+ break;
+
+ case SOUND_MIXER_LINE:
+ preg = 0x3e;
+ rreg = 0x6e;
+ break;
+
+ case SOUND_MIXER_MIC:
+ preg = 0x1a;
+ rreg = 0x68;
+ break;
+
+ case SOUND_MIXER_LINE1:
+ preg = 0x3a;
+ rreg = 0x6c;
+ break;
+
+ case SOUND_MIXER_CD:
+ preg = 0x38;
+ rreg = 0x6a;
+ break;
+
+ case SOUND_MIXER_VOLUME:
+ l = left? (left * 63) / 100 : 64;
+ r = right? (right * 63) / 100 : 64;
+ ess_setmixer(sc, 0x60, l);
+ ess_setmixer(sc, 0x62, r);
+ left = (l == 64)? 0 : (l * 100) / 63;
+ right = (r == 64)? 0 : (r * 100) / 63;
+ return left | (right << 8);
+ }
+
+ if (preg)
+ ess_setmixer(sc, preg, (l << 4) | r);
+ if (rreg)
+ ess_setmixer(sc, rreg, (l << 4) | r);
-left = (l * 100) / 15;
-right = (r * 100) / 15;
+ left = (l * 100) / 15;
+ right = (r * 100) / 15;
-return left | (right << 8);
+ return left | (right << 8);
}
static int
essmix_setrecsrc(struct snd_mixer *m, u_int32_t src)
{
-struct ess_info *sc = mix_getdevinfo(m);
-u_char recdev;
-
-switch (src) {
-case SOUND_MASK_CD:
-recdev = 0x02;
-break;
+ struct ess_info *sc = mix_getdevinfo(m);
+ u_char recdev;
-case SOUND_MASK_LINE:
-recdev = 0x06;
-break;
-
-case SOUND_MASK_IMIX:
-recdev = 0x05;
-break;
-
-case SOUND_MASK_MIC:
-default:
-recdev = 0x00;
-src = SOUND_MASK_MIC;
-break;
-}
+ switch (src) {
+ case SOUND_MASK_CD:
+ recdev = 0x02;
+ break;
+
+ case SOUND_MASK_LINE:
+ recdev = 0x06;
+ break;
+
+ case SOUND_MASK_IMIX:
+ recdev = 0x05;
+ break;
+
+ case SOUND_MASK_MIC:
+ default:
+ recdev = 0x00;
+ src = SOUND_MASK_MIC;
+ break;
+ }
-ess_setmixer(sc, 0x1c, recdev);
+ ess_setmixer(sc, 0x1c, recdev);
-return src;
+ return src;
}
static kobj_method_t solomixer_methods[] = {
-KOBJMETHOD(mixer_init, essmix_init),
-KOBJMETHOD(mixer_set, essmix_set),
-KOBJMETHOD(mixer_setrecsrc, essmix_setrecsrc),
-{ 0, 0 }
+ KOBJMETHOD(mixer_init, essmix_init),
+ KOBJMETHOD(mixer_set, essmix_set),
+ KOBJMETHOD(mixer_setrecsrc, essmix_setrecsrc),
+ { 0, 0 }
};
MIXER_DECLARE(solomixer);
@@ -762,171 +764,171 @@
static int
ess_dmasetup(struct ess_info *sc, int ch, u_int32_t base, u_int16_t cnt, int dir)
{
-KASSERT(ch == 1 || ch == 2, ("bad ch"));
-sc->dmasz[ch - 1] = cnt;
-if (ch == 1) {
-port_wr(sc->vc, 0x8, 0xc4, 1); /* command */
-port_wr(sc->vc, 0xd, 0xff, 1); /* reset */
-port_wr(sc->vc, 0xf, 0x01, 1); /* mask */
-port_wr(sc->vc, 0xb, dir == PCMDIR_PLAY? 0x58 : 0x54, 1); /* mode */
-port_wr(sc->vc, 0x0, base, 4);
-port_wr(sc->vc, 0x4, cnt - 1, 2);
-
-} else if (ch == 2) {
-port_wr(sc->io, 0x6, 0x08, 1); /* autoinit */
-port_wr(sc->io, 0x0, base, 4);
-port_wr(sc->io, 0x4, cnt, 2);
-}
-return 0;
+ KASSERT(ch == 1 || ch == 2, ("bad ch"));
+ sc->dmasz[ch - 1] = cnt;
+ if (ch == 1) {
+ port_wr(sc->vc, 0x8, 0xc4, 1); /* command */
+ port_wr(sc->vc, 0xd, 0xff, 1); /* reset */
+ port_wr(sc->vc, 0xf, 0x01, 1); /* mask */
+ port_wr(sc->vc, 0xb, dir == PCMDIR_PLAY? 0x58 : 0x54, 1); /* mode */
+ port_wr(sc->vc, 0x0, base, 4);
+ port_wr(sc->vc, 0x4, cnt - 1, 2);
+
+ } else if (ch == 2) {
+ port_wr(sc->io, 0x6, 0x08, 1); /* autoinit */
+ port_wr(sc->io, 0x0, base, 4);
+ port_wr(sc->io, 0x4, cnt, 2);
+ }
+ return 0;
}
static int
ess_dmapos(struct ess_info *sc, int ch)
{
-int p = 0, i = 0, j = 0;
+ int p = 0, i = 0, j = 0;
-KASSERT(ch == 1 || ch == 2, ("bad ch"));
-if (ch == 1) {
+ KASSERT(ch == 1 || ch == 2, ("bad ch"));
+ if (ch == 1) {
/*
-* During recording, this register is known to give back
-* garbage if it's not quiescent while being read. That's
-* why we spl, stop the DMA, and try over and over until
-* adjacent reads are "close", in the right order and not
-* bigger than is otherwise possible.
-*/
-ess_dmatrigger(sc, ch, 0);
-DELAY(20);
-do {
-DELAY(10);
-if (j > 1)
-printf("DMA count reg bogus: %04x & %04xn",
-i, p);
-i = port_rd(sc->vc, 0x4, 2) + 1;
-p = port_rd(sc->vc, 0x4, 2) + 1;
-} while ((p > sc->dmasz[ch - 1] || i < p || (p - i) > 0x8) && j++ < 1000);
-ess_dmatrigger(sc, ch, 1);
-}
-else if (ch == 2)
-p = port_rd(sc->io, 0x4, 2);
-return sc->dmasz[ch - 1] - p;
+ * During recording, this register is known to give back
+ * garbage if it's not quiescent while being read. That's
+ * why we spl, stop the DMA, and try over and over until
+ * adjacent reads are "close", in the right order and not
+ * bigger than is otherwise possible.
+ */
+ ess_dmatrigger(sc, ch, 0);
+ DELAY(20);
+ do {
+ DELAY(10);
+ if (j > 1)
+ printf("DMA count reg bogus: %04x & %04x\n",
+ i, p);
+ i = port_rd(sc->vc, 0x4, 2) + 1;
+ p = port_rd(sc->vc, 0x4, 2) + 1;
+ } while ((p > sc->dmasz[ch - 1] || i < p || (p - i) > 0x8) && j++ < 1000);
+ ess_dmatrigger(sc, ch, 1);
+ }
+ else if (ch == 2)
+ p = port_rd(sc->io, 0x4, 2);
+ return sc->dmasz[ch - 1] - p;
}
static int
ess_dmatrigger(struct ess_info *sc, int ch, int go)
{
-KASSERT(ch == 1 || ch == 2, ("bad ch"));
-if (ch == 1)
-port_wr(sc->vc, 0xf, go? 0x00 : 0x01, 1); /* mask */
-else if (ch == 2)
-port_wr(sc->io, 0x6, 0x08 | (go? 0x02 : 0x00), 1); /* autoinit */
-return 0;
+ KASSERT(ch == 1 || ch == 2, ("bad ch"));
+ if (ch == 1)
+ port_wr(sc->vc, 0xf, go? 0x00 : 0x01, 1); /* mask */
+ else if (ch == 2)
+ port_wr(sc->io, 0x6, 0x08 | (go? 0x02 : 0x00), 1); /* autoinit */
+ return 0;
}
static void
ess_release_resources(struct ess_info *sc, device_t dev)
{
-if (sc->irq) {
-if (sc->ih)
-bus_teardown_intr(dev, sc->irq, sc->ih);
-bus_release_resource(dev, SYS_RES_IRQ, 0, sc->irq);
-sc->irq = 0;
-}
-if (sc->io) {
-bus_release_resource(dev, SYS_RES_IOPORT, PCIR_BAR(0), sc->io);
-sc->io = 0;
-}
-
-if (sc->sb) {
-bus_release_resource(dev, SYS_RES_IOPORT, PCIR_BAR(1), sc->sb);
-sc->sb = 0;
-}
-
-if (sc->vc) {
-bus_release_resource(dev, SYS_RES_IOPORT, PCIR_BAR(2), sc->vc);
-sc->vc = 0;
-}
-
-if (sc->mpu) {
-bus_release_resource(dev, SYS_RES_IOPORT, PCIR_BAR(3), sc->mpu);
-sc->mpu = 0;
-}
-
-if (sc->gp) {
-bus_release_resource(dev, SYS_RES_IOPORT, PCIR_BAR(4), sc->gp);
-sc->gp = 0;
-}
-
-if (sc->parent_dmat) {
-bus_dma_tag_destroy(sc->parent_dmat);
-sc->parent_dmat = 0;
-}
+ if (sc->irq) {
+ if (sc->ih)
+ bus_teardown_intr(dev, sc->irq, sc->ih);
+ bus_release_resource(dev, SYS_RES_IRQ, 0, sc->irq);
+ sc->irq = 0;
+ }
+ if (sc->io) {
+ bus_release_resource(dev, SYS_RES_IOPORT, PCIR_BAR(0), sc->io);
+ sc->io = 0;
+ }
+
+ if (sc->sb) {
+ bus_release_resource(dev, SYS_RES_IOPORT, PCIR_BAR(1), sc->sb);
+ sc->sb = 0;
+ }
+
+ if (sc->vc) {
+ bus_release_resource(dev, SYS_RES_IOPORT, PCIR_BAR(2), sc->vc);
+ sc->vc = 0;
+ }
+
+ if (sc->mpu) {
+ bus_release_resource(dev, SYS_RES_IOPORT, PCIR_BAR(3), sc->mpu);
+ sc->mpu = 0;
+ }
+
+ if (sc->gp) {
+ bus_release_resource(dev, SYS_RES_IOPORT, PCIR_BAR(4), sc->gp);
+ sc->gp = 0;
+ }
+
+ if (sc->parent_dmat) {
+ bus_dma_tag_destroy(sc->parent_dmat);
+ sc->parent_dmat = 0;
+ }
#if ESS18XX_MPSAFE == 1
-if (sc->lock) {
-snd_mtxfree(sc->lock);
-sc->lock = NULL;
-}
+ if (sc->lock) {
+ snd_mtxfree(sc->lock);
+ sc->lock = NULL;
+ }
#endif
-free(sc, M_DEVBUF);
+ free(sc, M_DEVBUF);
}
static int
ess_alloc_resources(struct ess_info *sc, device_t dev)
{
-int rid;
+ int rid;
-rid = PCIR_BAR(0);
-sc->io = bus_alloc_resource_any(dev, SYS_RES_IOPORT, &rid, RF_ACTIVE);
+ rid = PCIR_BAR(0);
+ sc->io = bus_alloc_resource_any(dev, SYS_RES_IOPORT, &rid, RF_ACTIVE);
-rid = PCIR_BAR(1);
-sc->sb = bus_alloc_resource_any(dev, SYS_RES_IOPORT, &rid, RF_ACTIVE);
+ rid = PCIR_BAR(1);
+ sc->sb = bus_alloc_resource_any(dev, SYS_RES_IOPORT, &rid, RF_ACTIVE);
-rid = PCIR_BAR(2);
-sc->vc = bus_alloc_resource_any(dev, SYS_RES_IOPORT, &rid, RF_ACTIVE);
+ rid = PCIR_BAR(2);
+ sc->vc = bus_alloc_resource_any(dev, SYS_RES_IOPORT, &rid, RF_ACTIVE);
-rid = PCIR_BAR(3);
-sc->mpu = bus_alloc_resource_any(dev, SYS_RES_IOPORT, &rid, RF_ACTIVE);
+ rid = PCIR_BAR(3);
+ sc->mpu = bus_alloc_resource_any(dev, SYS_RES_IOPORT, &rid, RF_ACTIVE);
-rid = PCIR_BAR(4);
-sc->gp = bus_alloc_resource_any(dev, SYS_RES_IOPORT, &rid, RF_ACTIVE);
+ rid = PCIR_BAR(4);
+ sc->gp = bus_alloc_resource_any(dev, SYS_RES_IOPORT, &rid, RF_ACTIVE);
-rid = 0;
-sc->irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid,
-RF_ACTIVE | RF_SHAREABLE);
+ rid = 0;
+ sc->irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid,
+ RF_ACTIVE | RF_SHAREABLE);
#if ESS18XX_MPSAFE == 1
-sc->lock = snd_mtxcreate(device_get_nameunit(dev), "sound softc");
+ sc->lock = snd_mtxcreate(device_get_nameunit(dev), "snd_solo softc");
-return (sc->irq && sc->io && sc->sb && sc->vc &&
-sc->mpu && sc->gp && sc->lock)? 0 : ENXIO;
+ return (sc->irq && sc->io && sc->sb && sc->vc &&
+ sc->mpu && sc->gp && sc->lock)? 0 : ENXIO;
#else
-return (sc->irq && sc->io && sc->sb && sc->vc && sc->mpu && sc->gp)? 0 : ENXIO;
+ return (sc->irq && sc->io && sc->sb && sc->vc && sc->mpu && sc->gp)? 0 : ENXIO;
#endif
}
static int
ess_probe(device_t dev)
{
-char *s = NULL;
-u_int32_t subdev;
+ char *s = NULL;
+ u_int32_t subdev;
-subdev = (pci_get_subdevice(dev) << 16) | pci_get_subvendor(dev);
-switch (pci_get_devid(dev)) {
-case 0x1969125d:
-if (subdev == 0x8888125d)
-s = "ESS Solo-1E";
-else if (subdev == 0x1818125d)
-s = "ESS Solo-1";
-else
-s = "ESS Solo-1 (unknown vendor)";
-break;
-}
-
-if (s)
-device_set_desc(dev, s);
-return s ? BUS_PROBE_DEFAULT : ENXIO;
+ subdev = (pci_get_subdevice(dev) << 16) | pci_get_subvendor(dev);
+ switch (pci_get_devid(dev)) {
+ case 0x1969125d:
+ if (subdev == 0x8888125d)
+ s = "ESS Solo-1E";
+ else if (subdev == 0x1818125d)
+ s = "ESS Solo-1";
+ else
+ s = "ESS Solo-1 (unknown vendor)";
+ break;
+ }
+
+ if (s)
+ device_set_desc(dev, s);
+ return s ? BUS_PROBE_DEFAULT : ENXIO;
}
#define ESS_PCI_LEGACYCONTROL 0x40
@@ -936,175 +938,172 @@
static int
ess_suspend(device_t dev)
{
-return 0;
+ return 0;
}
static int
ess_resume(device_t dev)
{
-uint16_t ddma;
-uint32_t data;
-struct ess_info *sc = pcm_getdevinfo(dev);
-
-ess_lock(sc);
-data = pci_read_config(dev, PCIR_COMMAND, 2);
-data |= PCIM_CMD_PORTEN | PCIM_CMD_BUSMASTEREN;
-pci_write_config(dev, PCIR_COMMAND, data, 2);
-data = pci_read_config(dev, PCIR_COMMAND, 2);
-
-ddma = rman_get_start(sc->vc) | 1;
-pci_write_config(dev, ESS_PCI_LEGACYCONTROL, 0x805f, 2);
-pci_write_config(dev, ESS_PCI_DDMACONTROL, ddma, 2);
-pci_write_config(dev, ESS_PCI_CONFIG, 0, 2);
-
-if (ess_reset_dsp(sc)) {
-ess_unlock(sc);
-goto no;
-}
-ess_unlock(sc);
-if (mixer_reinit(dev))
-goto no;
-ess_lock(sc);
-if (sc->newspeed)
-ess_setmixer(sc, 0x71, 0x2a);
-
-port_wr(sc->io, 0x7, 0xb0, 1); /* enable irqs */
-ess_unlock(sc);
-
-return 0;
-no:
-return EIO;
+ uint16_t ddma;
+ uint32_t data;
+ struct ess_info *sc = pcm_getdevinfo(dev);
+
+ ess_lock(sc);
+ data = pci_read_config(dev, PCIR_COMMAND, 2);
+ data |= PCIM_CMD_PORTEN | PCIM_CMD_BUSMASTEREN;
+ pci_write_config(dev, PCIR_COMMAND, data, 2);
+ data = pci_read_config(dev, PCIR_COMMAND, 2);
+
+ ddma = rman_get_start(sc->vc) | 1;
+ pci_write_config(dev, ESS_PCI_LEGACYCONTROL, 0x805f, 2);
+ pci_write_config(dev, ESS_PCI_DDMACONTROL, ddma, 2);
+ pci_write_config(dev, ESS_PCI_CONFIG, 0, 2);
+
+ if (ess_reset_dsp(sc)) {
+ ess_unlock(sc);
+ goto no;
+ }
+ ess_unlock(sc);
+ if (mixer_reinit(dev))
+ goto no;
+ ess_lock(sc);
+ if (sc->newspeed)
+ ess_setmixer(sc, 0x71, 0x2a);
+
+ port_wr(sc->io, 0x7, 0xb0, 1); /* enable irqs */
+ ess_unlock(sc);
+
+ return 0;
+ no:
+ return EIO;
}
static int
ess_attach(device_t dev)
{
-struct ess_info *sc;
-char status[SND_STATUSLEN];
-u_int16_t ddma;
-u_int32_t data;
-
-sc = (struct ess_info *)malloc(sizeof *sc, M_DEVBUF, M_NOWAIT | M_ZERO);
-if (!sc)
-return ENXIO;
-
-data = pci_read_config(dev, PCIR_COMMAND, 2);
-data |= PCIM_CMD_PORTEN | PCIM_CMD_BUSMASTEREN;
-pci_write_config(dev, PCIR_COMMAND, data, 2);
-data = pci_read_config(dev, PCIR_COMMAND, 2);
-
-if (ess_alloc_resources(sc, dev))
-goto no;
-
-sc->bufsz = pcm_getbuffersize(dev, 4096, SOLO_DEFAULT_BUFSZ, 65536);
-
-ddma = rman_get_start(sc->vc) | 1;
-pci_write_config(dev, ESS_PCI_LEGACYCONTROL, 0x805f, 2);
-pci_write_config(dev, ESS_PCI_DDMACONTROL, ddma, 2);
-pci_write_config(dev, ESS_PCI_CONFIG, 0, 2);
+ struct ess_info *sc;
+ char status[SND_STATUSLEN];
+ u_int16_t ddma;
+ u_int32_t data;
+
+ sc = malloc(sizeof(*sc), M_DEVBUF, M_WAITOK | M_ZERO);
+ data = pci_read_config(dev, PCIR_COMMAND, 2);
+ data |= PCIM_CMD_PORTEN | PCIM_CMD_BUSMASTEREN;
+ pci_write_config(dev, PCIR_COMMAND, data, 2);
+ data = pci_read_config(dev, PCIR_COMMAND, 2);
+
+ if (ess_alloc_resources(sc, dev))
+ goto no;
+
+ sc->bufsz = pcm_getbuffersize(dev, 4096, SOLO_DEFAULT_BUFSZ, 65536);
+
+ ddma = rman_get_start(sc->vc) | 1;
+ pci_write_config(dev, ESS_PCI_LEGACYCONTROL, 0x805f, 2);
+ pci_write_config(dev, ESS_PCI_DDMACONTROL, ddma, 2);
+ pci_write_config(dev, ESS_PCI_CONFIG, 0, 2);
-port_wr(sc->io, 0x7, 0xb0, 1); /* enable irqs */
+ port_wr(sc->io, 0x7, 0xb0, 1); /* enable irqs */
#ifdef ESS18XX_DUPLEX
-sc->duplex = 1;
+ sc->duplex = 1;
#else
-sc->duplex = 0;
+ sc->duplex = 0;
#endif
#ifdef ESS18XX_NEWSPEED
-sc->newspeed = 1;
+ sc->newspeed = 1;
#else
-sc->newspeed = 0;
+ sc->newspeed = 0;
#endif
-if (snd_setup_intr(dev, sc->irq,
+ if (snd_setup_intr(dev, sc->irq,
#if ESS18XX_MPSAFE == 1
-INTR_MPSAFE
+ INTR_MPSAFE
#else
-0
+ 0
#endif
-, ess_intr, sc, &sc->ih)) {
-device_printf(dev, "unable to map interruptn");
-goto no;
-}
+ , ess_intr, sc, &sc->ih)) {
+ device_printf(dev, "unable to map interrupt\n");
+ goto no;
+ }
-if (!sc->duplex)
-pcm_setflags(dev, pcm_getflags(dev) | SD_F_SIMPLEX);
+ if (!sc->duplex)
+ pcm_setflags(dev, pcm_getflags(dev) | SD_F_SIMPLEX);
#if 0
-if (bus_dma_tag_create(/*parent*/NULL, /*alignment*/65536, /*boundary*/0,
+ if (bus_dma_tag_create(/*parent*/bus_get_dma_tag(dev), /*alignment*/65536, /*boundary*/0,
#endif
-if (bus_dma_tag_create(/*parent*/NULL, /*alignment*/2, /*boundary*/0,
-/*lowaddr*/BUS_SPACE_MAXADDR_24BIT,
-/*highaddr*/BUS_SPACE_MAXADDR,
-/*filter*/NULL, /*filterarg*/NULL,
-/*maxsize*/sc->bufsz, /*nsegments*/1,
-/*maxsegz*/0x3ffff,
-/*flags*/0,
+ if (bus_dma_tag_create(/*parent*/bus_get_dma_tag(dev), /*alignment*/2, /*boundary*/0,
+ /*lowaddr*/BUS_SPACE_MAXADDR_24BIT,
+ /*highaddr*/BUS_SPACE_MAXADDR,
+ /*filter*/NULL, /*filterarg*/NULL,
+ /*maxsize*/sc->bufsz, /*nsegments*/1,
+ /*maxsegz*/0x3ffff,
+ /*flags*/0,
#if ESS18XX_MPSAFE == 1
-/*lockfunc*/NULL, /*lockarg*/NULL,
+ /*lockfunc*/NULL, /*lockarg*/NULL,
#else
-/*lockfunc*/busdma_lock_mutex, /*lockarg*/&Giant,
+ /*lockfunc*/busdma_lock_mutex, /*lockarg*/&Giant,
#endif
-&sc->parent_dmat) != 0) {
-device_printf(dev, "unable to create dma tagn");
-goto no;
-}
-
-if (ess_reset_dsp(sc))
-goto no;
-
-if (sc->newspeed)
-ess_setmixer(sc, 0x71, 0x2a);
-
-if (mixer_init(dev, &solomixer_class, sc))
-goto no;
-
-snprintf(status, SND_STATUSLEN, "at io 0x%lx,0x%lx,0x%lx irq %ld %s",
-rman_get_start(sc->io), rman_get_start(sc->sb), rman_get_start(sc->vc),
-rman_get_start(sc->irq),PCM_KLDSTRING(snd_solo));
-
-if (pcm_register(dev, sc, 1, 1))
-goto no;
-pcm_addchan(dev, PCMDIR_REC, &esschan_class, sc);
-pcm_addchan(dev, PCMDIR_PLAY, &esschan_class, sc);
-pcm_setstatus(dev, status);
+ &sc->parent_dmat) != 0) {
+ device_printf(dev, "unable to create dma tag\n");
+ goto no;
+ }
+
+ if (ess_reset_dsp(sc))
+ goto no;
+
+ if (sc->newspeed)
+ ess_setmixer(sc, 0x71, 0x2a);
+
+ if (mixer_init(dev, &solomixer_class, sc))
+ goto no;
+
+ snprintf(status, SND_STATUSLEN, "at io 0x%lx,0x%lx,0x%lx irq %ld %s",
+ rman_get_start(sc->io), rman_get_start(sc->sb), rman_get_start(sc->vc),
+ rman_get_start(sc->irq),PCM_KLDSTRING(snd_solo));
+
+ if (pcm_register(dev, sc, 1, 1))
+ goto no;
+ pcm_addchan(dev, PCMDIR_REC, &esschan_class, sc);
+ pcm_addchan(dev, PCMDIR_PLAY, &esschan_class, sc);
+ pcm_setstatus(dev, status);
-return 0;
+ return 0;
no:
-ess_release_resources(sc, dev);
-return ENXIO;
+ ess_release_resources(sc, dev);
+ return ENXIO;
}
static int
ess_detach(device_t dev)
{
-int r;
-struct ess_info *sc;
+ int r;
+ struct ess_info *sc;
-r = pcm_unregister(dev);
-if (r)
-return r;
-
-sc = pcm_getdevinfo(dev);
-ess_release_resources(sc, dev);
-return 0;
+ r = pcm_unregister(dev);
+ if (r)
+ return r;
+
+ sc = pcm_getdevinfo(dev);
+ ess_release_resources(sc, dev);
+ return 0;
}
static device_method_t ess_methods[] = {
-/* Device interface */
-DEVMETHOD(device_probe, ess_probe),
-DEVMETHOD(device_attach, ess_attach),
-DEVMETHOD(device_detach, ess_detach),
-DEVMETHOD(device_resume, ess_resume),
-DEVMETHOD(device_suspend, ess_suspend),
+ /* Device interface */
+ DEVMETHOD(device_probe, ess_probe),
+ DEVMETHOD(device_attach, ess_attach),
+ DEVMETHOD(device_detach, ess_detach),
+ DEVMETHOD(device_resume, ess_resume),
+ DEVMETHOD(device_suspend, ess_suspend),
-{ 0, 0 }
+ { 0, 0 }
};
static driver_t ess_driver = {
-"pcm",
-ess_methods,
-PCM_SOFTC_SIZE,
+ "pcm",
+ ess_methods,
+ PCM_SOFTC_SIZE,
};
DRIVER_MODULE(snd_solo, pci, ess_driver, pcm_devclass, 0, 0);
Index: aureal.h
===================================================================
RCS file: /home/cvs/src/sys/dev/sound/pci/aureal.h,v
retrieving revision 1.2
retrieving revision 1.3
diff -L sys/dev/sound/pci/aureal.h -L sys/dev/sound/pci/aureal.h -u -r1.2 -r1.3
--- sys/dev/sound/pci/aureal.h
+++ sys/dev/sound/pci/aureal.h
@@ -1,31 +1,30 @@
/*-
-* Copyright (c) 1999 Cameron Grant <cg at freebsd.org>
-* All rights reserved.
-*
-* Redistribution and use in source and binary forms, with or without
-* modification, are permitted provided that the following conditions
-* are met:
-* 1. Redistributions of source code must retain the above copyright
-* notice, this list of conditions and the following disclaimer.
-* 2. Redistributions in binary form must reproduce the above copyright
-* notice, this list of conditions and the following disclaimer in the
-* documentation and/or other materials provided with the distribution.
-*
-* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
-* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
-* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
-* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
-* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
-* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
-* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
-* SUCH DAMAGE.
-*
-* $MidnightBSD$
-* $FreeBSD: src/sys/dev/sound/pci/aureal.h,v 1.4 2005/01/06 01:43:18 imp Exp $
-*/
+ * Copyright (c) 1999 Cameron Grant <cg at freebsd.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD: src/sys/dev/sound/pci/aureal.h,v 1.4 2005/01/06 01:43:18 imp Exp $
+ */
#ifndef _AU8820_REG_H
#define _AU8820_REG_H
--- /dev/null
+++ sys/dev/sound/pci/envy24.h
@@ -0,0 +1,495 @@
+/*
+ * Copyright (c) 2001 Katsurajima Naoto <raven at katsurajima.seya.yokohama.jp>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHERIN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THEPOSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD: src/sys/dev/sound/pci/envy24.h,v 1.2 2007/05/27 19:58:39 joel Exp $
+ */
+
+
+/* -------------------------------------------------------------------- */
+
+/* PCI device ID */
+#define PCIV_ENVY24 0x1412
+#define PCID_ENVY24 0x1712
+
+/* PCI Registers */
+
+#define PCIR_CCS 0x10 /* Controller I/O Base Address */
+#define PCIR_DDMA 0x14 /* DDMA I/O Base Address */
+#define PCIR_DS 0x18 /* DMA Path Registers I/O Base Address */
+#define PCIR_MT 0x1c /* Professional Multi-Track I/O Base Address */
+
+#define PCIR_LAC 0x40 /* Legacy Audio Control */
+#define PCIM_LAC_DISABLE 0x8000 /* Legacy Audio Hardware disabled */
+#define PCIM_LAC_SBDMA0 0x0000 /* SB DMA Channel Select: 0 */
+#define PCIM_LAC_SBDMA1 0x0040 /* SB DMA Channel Select: 1 */
+#define PCIM_LAC_SBDMA3 0x00c0 /* SB DMA Channel Select: 3 */
+#define PCIM_LAC_IOADDR10 0x0020 /* I/O Address Alias Control */
+#define PCIM_LAC_MPU401 0x0008 /* MPU-401 I/O enable */
+#define PCIM_LAC_GAME 0x0004 /* Game Port enable (200h) */
+#define PCIM_LAC_FM 0x0002 /* FM I/O enable (AdLib 388h base) */
+#define PCIM_LAC_SB 0x0001 /* SB I/O enable */
+
+#define PCIR_LCC 0x42 /* Legacy Configuration Control */
+#define PCIM_LCC_VINT 0xff00 /* Interrupt vector to be snooped */
+#define PCIM_LCC_SVIDRW 0x0080 /* SVID read/write enable */
+#define PCIM_LCC_SNPSB 0x0040 /* snoop SB 22C/24Ch I/O write cycle */
+#define PCIM_LCC_SNPPIC 0x0020 /* snoop PIC I/O R/W cycle */
+#define PCIM_LCC_SNPPCI 0x0010 /* snoop PCI bus interrupt acknowledge cycle */
+#define PCIM_LCC_SBBASE 0x0008 /* SB base 240h(1)/220h(0) */
+#define PCIM_LCC_MPUBASE 0x0006 /* MPU-401 base 300h-330h */
+#define PCIM_LCC_LDMA 0x0001 /* Legacy DMA enable */
+
+#define PCIR_SCFG 0x60 /* System Configuration Register */
+#define PCIM_SCFG_XIN2 0xc0 /* XIN2 Clock Source Configuration */
+ /* 00: 22.5792MHz(44.1kHz*512) */
+ /* 01: 16.9344MHz(44.1kHz*384) */
+ /* 10: from external clock synthesizer chip */
+#define PCIM_SCFG_MPU 0x20 /* 1(0)/2(1) MPU-401 UART(s) */
+#define PCIM_SCFG_AC97 0x10 /* 0: AC'97 codec exist */
+ /* 1: AC'97 codec not exist */
+#define PCIM_SCFG_ADC 0x0c /* 1-4 stereo ADC connected */
+#define PCIM_SCFG_DAC 0x03 /* 1-4 stereo DAC connected */
+
+#define PCIR_ACL 0x61 /* AC-Link Configuration Register */
+#define PCIM_ACL_MTC 0x80 /* Multi-track converter type: 0:AC'97 1:I2S */
+#define PCIM_ACL_OMODE 0x02 /* AC 97 codec SDATA_OUT 0:split 1:packed */
+#define PCIM_ACL_IMODE 0x01 /* AC 97 codec SDATA_IN 0:split 1:packed */
+
+#define PCIR_I2S 0x62 /* I2S Converters Features Register */
+#define PCIM_I2S_VOL 0x80 /* I2S codec Volume and mute */
+#define PCIM_I2S_96KHZ 0x40 /* I2S converter 96kHz sampling rate support */
+#define PCIM_I2S_RES 0x30 /* Converter resolution */
+#define PCIM_I2S_16BIT 0x00 /* 16bit */
+#define PCIM_I2S_18BIT 0x10 /* 18bit */
+#define PCIM_I2S_20BIT 0x20 /* 20bit */
+#define PCIM_I2S_24BIT 0x30 /* 24bit */
+#define PCIM_I2S_ID 0x0f /* Other I2S IDs */
+
+#define PCIR_SPDIF 0x63 /* S/PDIF Configuration Register */
+#define PCIM_SPDIF_ID 0xfc /* S/PDIF chip ID */
+#define PCIM_SPDIF_IN 0x02 /* S/PDIF Stereo In is present */
+#define PCIM_SPDIF_OUT 0x01 /* S/PDIF Stereo Out is present */
+
+#define PCIR_POWER_STAT 0x84 /* Power Management Control and Status */
+
+/* Controller Registers */
+
+#define ENVY24_CCS_CTL 0x00 /* Control/Status Register */
+#define ENVY24_CCS_CTL_RESET 0x80 /* Entire Chip soft reset */
+#define ENVY24_CCS_CTL_DMAINT 0x40 /* DS DMA Channel-C interrupt */
+#define ENVY24_CCS_CTL_DOSVOL 0x10 /* set the DOS WT volume control */
+#define ENVY24_CCS_CTL_EDGE 0x08 /* SERR# edge (only one PCI clock width) */
+#define ENVY24_CCS_CTL_SBINT 0x02 /* SERR# assertion for SB interrupt */
+#define ENVY24_CCS_CTL_NATIVE 0x01 /* Mode select: 0:SB mode 1:native mode */
+
+#define ENVY24_CCS_IMASK 0x01 /* Interrupt Mask Register */
+#define ENVY24_CCS_IMASK_PMIDI 0x80 /* Primary MIDI */
+#define ENVY24_CCS_IMASK_TIMER 0x40 /* Timer */
+#define ENVY24_CCS_IMASK_SMIDI 0x20 /* Secondary MIDI */
+#define ENVY24_CCS_IMASK_PMT 0x10 /* Professional Multi-track */
+#define ENVY24_CCS_IMASK_FM 0x08 /* FM/MIDI trapping */
+#define ENVY24_CCS_IMASK_PDMA 0x04 /* Playback DS DMA */
+#define ENVY24_CCS_IMASK_RDMA 0x02 /* Consumer record DMA */
+#define ENVY24_CCS_IMASK_SB 0x01 /* Consumer/SB mode playback */
+
+#define ENVY24_CCS_ISTAT 0x02 /* Interrupt Status Register */
+#define ENVY24_CCS_ISTAT_PMIDI 0x80 /* Primary MIDI */
+#define ENVY24_CCS_ISTAT_TIMER 0x40 /* Timer */
+#define ENVY24_CCS_ISTAT_SMIDI 0x20 /* Secondary MIDI */
+#define ENVY24_CCS_ISTAT_PMT 0x10 /* Professional Multi-track */
+#define ENVY24_CCS_ISTAT_FM 0x08 /* FM/MIDI trapping */
+#define ENVY24_CCS_ISTAT_PDMA 0x04 /* Playback DS DMA */
+#define ENVY24_CCS_ISTAT_RDMA 0x02 /* Consumer record DMA */
+#define ENVY24_CCS_ISTAT_SB 0x01 /* Consumer/SB mode playback */
+
+#define ENVY24_CCS_INDEX 0x03 /* Envy24 Index Register */
+#define ENVY24_CCS_DATA 0x04 /* Envy24 Data Register */
+
+#define ENVY24_CCS_NMI1 0x05 /* NMI Status Register 1 */
+#define ENVY24_CCS_NMI1_PCI 0x80 /* PCI I/O read/write cycle */
+#define ENVY24_CCS_NMI1_SB 0x40 /* SB 22C/24C write */
+#define ENVY24_CCS_NMI1_SBDMA 0x10 /* SB interrupt (SB DMA/SB F2 command) */
+#define ENVY24_CCS_NMI1_DSDMA 0x08 /* DS channel C DMA interrupt */
+#define ENVY24_CCS_NMI1_MIDI 0x04 /* MIDI 330h or [PCI_10]h+Ch write */
+#define ENVY24_CCS_NMI1_FM 0x01 /* FM data register write */
+
+#define ENVY24_CCS_NMIDAT 0x06 /* NMI Data Register */
+#define ENVY24_CCS_NMIIDX 0x07 /* NMI Index Register */
+#define ENVY24_CCS_AC97IDX 0x08 /* Consumer AC'97 Index Register */
+
+#define ENVY24_CCS_AC97CMD 0x09 /* Consumer AC'97 Command/Status Register */
+#define ENVY24_CCS_AC97CMD_COLD 0x80 /* Cold reset */
+#define ENVY24_CCS_AC97CMD_WARM 0x40 /* Warm reset */
+#define ENVY24_CCS_AC97CMD_WRCODEC 0x20 /* Write to AC'97 codec registers */
+#define ENVY24_CCS_AC97CMD_RDCODEC 0x10 /* Read from AC'97 codec registers */
+#define ENVY24_CCS_AC97CMD_READY 0x08 /* AC'97 codec ready status bit */
+#define ENVY24_CCS_AC97CMD_PVSR 0x02 /* VSR for Playback */
+#define ENVY24_CCS_AC97CMD_RVSR 0x01 /* VSR for Record */
+
+#define ENVY24_CCS_AC97DAT 0x0a /* Consumer AC'97 Data Port Register */
+#define ENVY24_CCS_PMIDIDAT 0x0c /* Primary MIDI UART Data Register */
+#define ENVY24_CCS_PMIDICMD 0x0d /* Primary MIDI UART Command/Status Register */
+
+#define ENVY24_CCS_NMI2 0x0e /* NMI Status Register 2 */
+#define ENVY24_CCS_NMI2_FMBANK 0x30 /* FM bank indicator */
+#define ENVY24_CCS_NMI2_FM0 0x10 /* FM bank 0 (388h/220h/228h) */
+#define ENVY24_CCS_NMI2_FM1 0x20 /* FM bank 1 (38ah/222h) */
+#define ENVY24_CCS_NMI2_PICIO 0x0f /* PIC I/O cycle */
+#define ENVY24_CCS_NMI2_PIC20W 0x01 /* 20h write */
+#define ENVY24_CCS_NMI2_PICA0W 0x02 /* a0h write */
+#define ENVY24_CCS_NMI2_PIC21W 0x05 /* 21h write */
+#define ENVY24_CCS_NMI2_PICA1W 0x06 /* a1h write */
+#define ENVY24_CCS_NMI2_PIC20R 0x09 /* 20h read */
+#define ENVY24_CCS_NMI2_PICA0R 0x0a /* a0h read */
+#define ENVY24_CCS_NMI2_PIC21R 0x0d /* 21h read */
+#define ENVY24_CCS_NMI2_PICA1R 0x0e /* a1h read */
+
+#define ENVY24_CCS_JOY 0x0f /* Game port register */
+
+#define ENVY24_CCS_I2CDEV 0x10 /* I2C Port Device Address Register */
+#define ENVY24_CCS_I2CDEV_ADDR 0xfe /* I2C device address */
+#define ENVY24_CCS_I2CDEV_ROM 0xa0 /* reserved for the external I2C E2PROM */
+#define ENVY24_CCS_I2CDEV_WR 0x01 /* write */
+#define ENVY24_CCS_I2CDEV_RD 0x00 /* read */
+
+#define ENVY24_CCS_I2CADDR 0x11 /* I2C Port Byte Address Register */
+#define ENVY24_CCS_I2CDATA 0x12 /* I2C Port Read/Write Data Register */
+
+#define ENVY24_CCS_I2CSTAT 0x13 /* I2C Port Control and Status Register */
+#define ENVY24_CCS_I2CSTAT_ROM 0x80 /* external E2PROM exists */
+#define ENVY24_CCS_I2CSTAT_BSY 0x01 /* I2C port read/write status busy */
+
+#define ENVY24_CCS_CDMABASE 0x14 /* Consumer Record DMA Current/Base Address Register */
+#define ENVY24_CCS_CDMACNT 0x18 /* Consumer Record DMA Current/Base Count Register */
+#define ENVY24_CCS_SERR 0x1b /* PCI Configuration SERR# Shadow Register */
+#define ENVY24_CCS_SMIDIDAT 0x1c /* Secondary MIDI UART Data Register */
+#define ENVY24_CCS_SMIDICMD 0x1d /* Secondary MIDI UART Command/Status Register */
+
+#define ENVY24_CCS_TIMER 0x1e /* Timer Register */
+#define ENVY24_CCS_TIMER_EN 0x8000 /* Timer count enable */
+#define ENVY24_CCS_TIMER_MASK 0x7fff /* Timer counter mask */
+
+/* Controller Indexed Registers */
+
+#define ENVY24_CCI_PTCHIGH 0x00 /* Playback Terminal Count Register (High Byte) */
+#define ENVY24_CCI_PTCLOW 0x01 /* Playback Terminal Count Register (Low Byte) */
+
+#define ENVY24_CCI_PCTL 0x02 /* Playback Control Register */
+#define ENVY24_CCI_PCTL_TURBO 0x80 /* 4x up sampling in the host by software */
+#define ENVY24_CCI_PCTL_U8 0x10 /* 8 bits unsigned */
+#define ENVY24_CCI_PCTL_S16 0x00 /* 16 bits signed */
+#define ENVY24_CCI_PCTL_STEREO 0x08 /* stereo */
+#define ENVY24_CCI_PCTL_MONO 0x00 /* mono */
+#define ENVY24_CCI_PCTL_FLUSH 0x04 /* FIFO flush (sticky bit. Requires toggling) */
+#define ENVY24_CCI_PCTL_PAUSE 0x02 /* Pause */
+#define ENVY24_CCI_PCTL_ENABLE 0x01 /* Playback enable */
+
+#define ENVY24_CCI_PLVOL 0x03 /* Playback Left Volume/Pan Register */
+#define ENVY24_CCI_PRVOL 0x04 /* Playback Right Volume/Pan Register */
+#define ENVY24_CCI_VOL_MASK 0x3f /* Volume value mask */
+
+#define ENVY24_CCI_SOFTVOL 0x05 /* Soft Volume/Mute Control Register */
+#define ENVY24_CCI_PSRLOW 0x06 /* Playback Sampling Rate Register (Low Byte) */
+#define ENVY24_CCI_PSRMID 0x07 /* Playback Sampling Rate Register (Middle Byte) */
+#define ENVY24_CCI_PSRHIGH 0x08 /* Playback Sampling Rate Register (High Byte) */
+#define ENVY24_CCI_RTCHIGH 0x10 /* Record Terminal Count Register (High Byte) */
+#define ENVY24_CCI_RTCLOW 0x11 /* Record Terminal Count Register (Low Byte) */
+
+#define ENVY24_CCI_RCTL 0x12 /* Record Control Register */
+#define ENVY24_CCI_RCTL_DRTN 0x80 /* Digital return enable */
+#define ENVY24_CCI_RCTL_U8 0x04 /* 8 bits unsigned */
+#define ENVY24_CCI_RCTL_S16 0x00 /* 16 bits signed */
+#define ENVY24_CCI_RCTL_STEREO 0x00 /* stereo */
+#define ENVY24_CCI_RCTL_MONO 0x02 /* mono */
+#define ENVY24_CCI_RCTL_ENABLE 0x01 /* Record enable */
+
+#define ENVY24_CCI_GPIODAT 0x20 /* GPIO Data Register */
+#define ENVY24_CCI_GPIOMASK 0x21 /* GPIO Write Mask Register */
+
+#define ENVY24_CCI_GPIOCTL 0x22 /* GPIO Direction Control Register */
+#define ENVY24_CCI_GPIO_OUT 1 /* output */
+#define ENVY24_CCI_GPIO_IN 0 /* input */
+
+#define ENVY24_CCI_CPDWN 0x30 /* Consumer Section Power Down Register */
+#define ENVY24_CCI_CPDWN_XTAL 0x80 /* Crystal clock generation power down for XTAL_1 */
+#define ENVY24_CCI_CPDWN_GAME 0x40 /* Game port analog power down */
+#define ENVY24_CCI_CPDWN_I2C 0x10 /* I2C port clock */
+#define ENVY24_CCI_CPDWN_MIDI 0x08 /* MIDI clock */
+#define ENVY24_CCI_CPDWN_AC97 0x04 /* AC'97 clock */
+#define ENVY24_CCI_CPDWN_DS 0x02 /* DS Block clock */
+#define ENVY24_CCI_CPDWN_PCI 0x01 /* PCI clock for SB, DMA controller */
+
+#define ENVY24_CCI_MTPDWN 0x31 /* Multi-Track Section Power Down Register */
+#define ENVY24_CCI_MTPDWN_XTAL 0x80 /* Crystal clock generation power down for XTAL_2 */
+#define ENVY24_CCI_MTPDWN_SPDIF 0x04 /* S/PDIF clock */
+#define ENVY24_CCI_MTPDWN_MIX 0x02 /* Professional digital mixer clock */
+#define ENVY24_CCI_MTPDWN_I2S 0x01 /* Multi-track I2S serial interface clock */
+
+/* DDMA Registers */
+
+#define ENVY24_DDMA_ADDR0 0x00 /* DMA Base and Current Address bit 0-7 */
+#define ENVY24_DDMA_ADDR8 0x01 /* DMA Base and Current Address bit 8-15 */
+#define ENVY24_DDMA_ADDR16 0x02 /* DMA Base and Current Address bit 16-23 */
+#define ENVY24_DDMA_ADDR24 0x03 /* DMA Base and Current Address bit 24-31 */
+#define ENVY24_DDMA_CNT0 0x04 /* DMA Base and Current Count 0-7 */
+#define ENVY24_DDMA_CNT8 0x05 /* DMA Base and Current Count 8-15 */
+#define ENVY24_DDMA_CNT16 0x06 /* (not supported) */
+#define ENVY24_DDMA_CMD 0x08 /* Status and Command */
+#define ENVY24_DDMA_MODE 0x0b /* Mode */
+#define ENVY24_DDMA_RESET 0x0c /* Master reset */
+#define ENVY24_DDMA_CHAN 0x0f /* Channel Mask */
+
+/* Consumer Section DMA Channel Registers */
+
+#define ENVY24_CS_INTMASK 0x00 /* DirectSound DMA Interrupt Mask Register */
+#define ENVY24_CS_INTSTAT 0x02 /* DirectSound DMA Interrupt Status Register */
+#define ENVY24_CS_CHDAT 0x04 /* Channel Data register */
+
+#define ENVY24_CS_CHIDX 0x08 /* Channel Index Register */
+#define ENVY24_CS_CHIDX_NUM 0xf0 /* Channel number */
+#define ENVY24_CS_CHIDX_ADDR0 0x00 /* Buffer_0 DMA base address */
+#define ENVY24_CS_CHIDX_CNT0 0x01 /* Buffer_0 DMA base count */
+#define ENVY24_CS_CHIDX_ADDR1 0x02 /* Buffer_1 DMA base address */
+#define ENVY24_CS_CHIDX_CNT1 0x03 /* Buffer_1 DMA base count */
+#define ENVY24_CS_CHIDX_CTL 0x04 /* Channel Control and Status register */
+#define ENVY24_CS_CHIDX_RATE 0x05 /* Channel Sampling Rate */
+#define ENVY24_CS_CHIDX_VOL 0x06 /* Channel left and right volume/pan control */
+/* Channel Control and Status Register at Index 4h */
+#define ENVY24_CS_CTL_BUF 0x80 /* indicating that the current active buffer */
+#define ENVY24_CS_CTL_AUTO1 0x40 /* Buffer_1 auto init. enable */
+#define ENVY24_CS_CTL_AUTO0 0x20 /* Buffer_0 auto init. enable */
+#define ENVY24_CS_CTL_FLUSH 0x10 /* Flush FIFO */
+#define ENVY24_CS_CTL_STEREO 0x08 /* stereo(or mono) */
+#define ENVY24_CS_CTL_U8 0x04 /* 8-bit unsigned(or 16-bit signed) */
+#define ENVY24_CS_CTL_PAUSE 0x02 /* DMA request 1:pause */
+#define ENVY24_CS_CTL_START 0x01 /* DMA request 1: start, 0:stop */
+/* Consumer mode Left/Right Volume Register at Index 06h */
+#define ENVY24_CS_VOL_RIGHT 0x3f00
+#define ENVY24_CS_VOL_LEFT 0x003f
+
+/* Professional Multi-Track Control Registers */
+
+#define ENVY24_MT_INT 0x00 /* DMA Interrupt Mask and Status Register */
+#define ENVY24_MT_INT_RMASK 0x80 /* Multi-track record interrupt mask */
+#define ENVY24_MT_INT_PMASK 0x40 /* Multi-track playback interrupt mask */
+#define ENVY24_MT_INT_RSTAT 0x02 /* Multi-track record interrupt status */
+#define ENVY24_MT_INT_PSTAT 0x01 /* Multi-track playback interrupt status */
+
+#define ENVY24_MT_RATE 0x01 /* Sampling Rate Select Register */
+#define ENVY24_MT_RATE_SPDIF 0x10 /* S/PDIF input clock as the master */
+#define ENVY24_MT_RATE_48000 0x00
+#define ENVY24_MT_RATE_24000 0x01
+#define ENVY24_MT_RATE_12000 0x02
+#define ENVY24_MT_RATE_9600 0x03
+#define ENVY24_MT_RATE_32000 0x04
+#define ENVY24_MT_RATE_16000 0x05
+#define ENVY24_MT_RATE_8000 0x06
+#define ENVY24_MT_RATE_96000 0x07
+#define ENVY24_MT_RATE_64000 0x0f
+#define ENVY24_MT_RATE_44100 0x08
+#define ENVY24_MT_RATE_22050 0x09
+#define ENVY24_MT_RATE_11025 0x0a
+#define ENVY24_MT_RATE_88200 0x0b
+#define ENVY24_MT_RATE_MASK 0x0f
+
+#define ENVY24_MT_I2S 0x02 /* I2S Data Format Register */
+#define ENVY24_MT_I2S_MLR128 0x08 /* MCLK/LRCLK ratio 128x(or 256x) */
+#define ENVY24_MT_I2S_SLR48 0x04 /* SCLK/LRCLK ratio 48bpf(or 64bpf) */
+#define ENVY24_MT_I2S_FORM 0x00 /* I2S data format */
+
+#define ENVY24_MT_AC97IDX 0x04 /* Index Register for AC'97 Codecs */
+
+#define ENVY24_MT_AC97CMD 0x05 /* Command and Status Register for AC'97 Codecs */
+#define ENVY24_MT_AC97CMD_CLD 0x80 /* Cold reset */
+#define ENVY24_MT_AC97CMD_WRM 0x40 /* Warm reset */
+#define ENVY24_MT_AC97CMD_WR 0x20 /* write to AC'97 codec register */
+#define ENVY24_MT_AC97CMD_RD 0x10 /* read AC'97 CODEC register */
+#define ENVY24_MT_AC97CMD_RDY 0x08 /* AC'97 codec ready status bit */
+#define ENVY24_MT_AC97CMD_ID 0x03 /* ID(0-3) for external AC 97 registers */
+
+#define ENVY24_MT_AC97DLO 0x06 /* AC'97 codec register data low byte */
+#define ENVY24_MT_AC97DHI 0x07 /* AC'97 codec register data high byte */
+#define ENVY24_MT_PADDR 0x10 /* Playback DMA Current/Base Address Register */
+#define ENVY24_MT_PCNT 0x14 /* Playback DMA Current/Base Count Register */
+#define ENVY24_MT_PTERM 0x16 /* Playback Current/Base Terminal Count Register */
+#define ENVY24_MT_PCTL 0x18 /* Playback and Record Control Register */
+#define ENVY24_MT_PCTL_RSTART 0x04 /* 1: Record start; 0: Record stop */
+#define ENVY24_MT_PCTL_PAUSE 0x02 /* 1: Pause; 0: Resume */
+#define ENVY24_MT_PCTL_PSTART 0x01 /* 1: Playback start; 0: Playback stop */
+
+#define ENVY24_MT_RADDR 0x20 /* Record DMA Current/Base Address Register */
+#define ENVY24_MT_RCNT 0x24 /* Record DMA Current/Base Count Register */
+#define ENVY24_MT_RTERM 0x26 /* Record Current/Base Terminal Count Register */
+#define ENVY24_MT_RCTL 0x28 /* Record Control Register */
+#define ENVY24_MT_RCTL_RSTART 0x01 /* 1: Record start; 0: Record stop */
+
+#define ENVY24_MT_PSDOUT 0x30 /* Routing Control Register for Data to PSDOUT[0:3] */
+#define ENVY24_MT_SPDOUT 0x32 /* Routing Control Register for SPDOUT */
+#define ENVY24_MT_RECORD 0x34 /* Captured (Recorded) data Routing Selection Register */
+
+#define BUS_SPACE_MAXADDR_ENVY24 0x0fffffff /* Address space beyond 256MB is not supported */
+#define BUS_SPACE_MAXSIZE_ENVY24 0x3fffc /* 64k x 4byte(1dword) */
+
+#define ENVY24_MT_VOLUME 0x38 /* Left/Right Volume Control Data Register */
+#define ENVY24_MT_VOLUME_L 0x007f /* Left Volume Mask */
+#define ENVY24_MT_VOLUME_R 0x7f00 /* Right Volume Mask */
+
+#define ENVY24_MT_VOLIDX 0x3a /* Volume Control Stream Index Register */
+#define ENVY24_MT_VOLRATE 0x3b /* Volume Control Rate Register */
+#define ENVY24_MT_MONAC97 0x3c /* Digital Mixer Monitor Routing Control Register */
+#define ENVY24_MT_PEAKIDX 0x3e /* Peak Meter Index Register */
+#define ENVY24_MT_PEAKDAT 0x3f /* Peak Meter Data Register */
+
+/* -------------------------------------------------------------------- */
+
+/* ENVY24 mixer channel defines */
+/*
+ ENVY24 mixer has original line matrix. So, general mixer command is not
+ able to use for this. If system has consumer AC'97 output, AC'97 line is
+ used as master mixer, and it is able to control.
+*/
+#define ENVY24_CHAN_NUM 11 /* Play * 5 + Record * 5 + Mix * 1 */
+
+#define ENVY24_CHAN_PLAY_DAC1 0
+#define ENVY24_CHAN_PLAY_DAC2 1
+#define ENVY24_CHAN_PLAY_DAC3 2
+#define ENVY24_CHAN_PLAY_DAC4 3
+#define ENVY24_CHAN_PLAY_SPDIF 4
+#define ENVY24_CHAN_REC_ADC1 5
+#define ENVY24_CHAN_REC_ADC2 6
+#define ENVY24_CHAN_REC_ADC3 7
+#define ENVY24_CHAN_REC_ADC4 8
+#define ENVY24_CHAN_REC_SPDIF 9
+#define ENVY24_CHAN_REC_MIX 10
+
+#define ENVY24_MIX_MASK 0x3ff
+#define ENVY24_MIX_REC_MASK 0x3e0
+
+/* volume value constants */
+#define ENVY24_VOL_MAX 0 /* 0db(negate) */
+#define ENVY24_VOL_MIN 96 /* -144db(negate) */
+#define ENVY24_VOL_MUTE 127 /* mute */
+
+/* -------------------------------------------------------------------- */
+
+/* ENVY24 routing control defines */
+/*
+ ENVY24 has input->output data routing matrix switch. But original ENVY24
+ matrix control is so complex. So, in this driver, matrix control is
+ defined 4 parameters.
+
+ 1: output DAC channels (include S/PDIF output)
+ 2: output data classes
+ a. direct output from DMA
+ b. MIXER output which mixed the DMA outputs and input channels
+ (NOTICE: this class is able to set only DAC-1 and S/PDIF output)
+ c. direct input from ADC
+ d. direct input from S/PDIF
+ 3: input ADC channel selection(when 2:c. is selected)
+ 4: left/right reverse
+
+ These parameters matrix is bit reduced from original ENVY24 matrix
+ pattern(ex. route different ADC input to one DAC). But almost case
+ this is enough to use.
+*/
+#define ENVY24_ROUTE_DAC_1 0
+#define ENVY24_ROUTE_DAC_2 1
+#define ENVY24_ROUTE_DAC_3 2
+#define ENVY24_ROUTE_DAC_4 3
+#define ENVY24_ROUTE_DAC_SPDIF 4
+
+#define ENVY24_ROUTE_CLASS_DMA 0
+#define ENVY24_ROUTE_CLASS_MIX 1
+#define ENVY24_ROUTE_CLASS_ADC 2
+#define ENVY24_ROUTE_CLASS_SPDIF 3
+
+#define ENVY24_ROUTE_ADC_1 0
+#define ENVY24_ROUTE_ADC_2 1
+#define ENVY24_ROUTE_ADC_3 2
+#define ENVY24_ROUTE_ADC_4 3
+
+#define ENVY24_ROUTE_NORMAL 0
+#define ENVY24_ROUTE_REVERSE 1
+#define ENVY24_ROUTE_LEFT 0
+#define ENVY24_ROUTE_RIGHT 1
+
+/* -------------------------------------------------------------------- */
+
+/*
+ These map values are refferd from ALSA sound driver.
+*/
+/* ENVY24 configuration E2PROM map */
+#define ENVY24_E2PROM_SUBVENDOR 0x00
+#define ENVY24_E2PROM_SUBDEVICE 0x02
+#define ENVY24_E2PROM_SIZE 0x04
+#define ENVY24_E2PROM_VERSION 0x05
+#define ENVY24_E2PROM_SCFG 0x06
+#define ENVY24_E2PROM_ACL 0x07
+#define ENVY24_E2PROM_I2S 0x08
+#define ENVY24_E2PROM_SPDIF 0x09
+#define ENVY24_E2PROM_GPIOMASK 0x0a
+#define ENVY24_E2PROM_GPIOSTATE 0x0b
+#define ENVY24_E2PROM_GPIODIR 0x0c
+#define ENVY24_E2PROM_AC97MAIN 0x0d
+#define ENVY24_E2PROM_AC97PCM 0x0f
+#define ENVY24_E2PROM_AC97REC 0x11
+#define ENVY24_E2PROM_AC97RECSRC 0x13
+#define ENVY24_E2PROM_DACID 0x14
+#define ENVY24_E2PROM_ADCID 0x18
+#define ENVY24_E2PROM_EXTRA 0x1c
+
+/* GPIO connect map of M-Audio Delta series */
+#define ENVY24_GPIO_CS84X4_PRO 0x01
+#define ENVY24_GPIO_CS8414_STATUS 0x02
+#define ENVY24_GPIO_CS84X4_CLK 0x04
+#define ENVY24_GPIO_CS84X4_DATA 0x08
+#define ENVY24_GPIO_AK4524_CDTI 0x10 /* this value is duplicated to input select */
+#define ENVY24_GPIO_AK4524_CCLK 0x20
+#define ENVY24_GPIO_AK4524_CS0 0x40
+#define ENVY24_GPIO_AK4524_CS1 0x80
+
+/* M-Audio Delta series S/PDIF(CS84[01]4) control pin values */
+#define ENVY24_CS8404_PRO_RATE 0x18
+#define ENVY24_CS8404_PRO_RATE32 0x00
+#define ENVY24_CS8404_PRO_RATE441 0x10
+#define ENVY24_CS8404_PRO_RATE48 0x08
+
+/* M-Audio Delta series parameter */
+#define ENVY24_DELTA_AK4524_CIF 0
+
+#define I2C_DELAY 1000
+
+/* PCA9554 registers */
+#define PCA9554_I2CDEV 0x40 /* I2C device address */
+#define PCA9554_IN 0x00 /* input port */
+#define PCA9554_OUT 0x01 /* output port */
+#define PCA9554_INVERT 0x02 /* polarity invert */
+#define PCA9554_DIR 0x03 /* port directions */
+
+/* PCF8574 registers */
+#define PCF8574_I2CDEV_DAC 0x48
+#define PCF8574_SENSE_MASK 0x40
+
+/* end of file */
Index: maestro_reg.h
===================================================================
RCS file: /home/cvs/src/sys/dev/sound/pci/maestro_reg.h,v
retrieving revision 1.2
retrieving revision 1.3
diff -L sys/dev/sound/pci/maestro_reg.h -L sys/dev/sound/pci/maestro_reg.h -u -r1.2 -r1.3
--- sys/dev/sound/pci/maestro_reg.h
+++ sys/dev/sound/pci/maestro_reg.h
@@ -1,39 +1,38 @@
/*-
-* Copyright (c) 1999-2000 Taku YAMAMOTO <taku at cent.saitama-u.ac.jp>
-* All rights reserved.
-*
-* Redistribution and use in source and binary forms, with or without
-* modification, are permitted provided that the following conditions
-* are met:
-* 1. Redistributions of source code must retain the above copyright
-* notice, this list of conditions and the following disclaimer.
-* 2. Redistributions in binary form must reproduce the above copyright
-* notice, this list of conditions and the following disclaimer in the
-* documentation and/or other materials provided with the distribution.
-*
-* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
-* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
-* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
-* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
-* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
-* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
-* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
-* SUCH DAMAGE.
-*
-* maestro_reg.h,v 1.13 2001/11/11 18:29:46 taku Exp
-* $MidnightBSD$
-* $FreeBSD: src/sys/dev/sound/pci/maestro_reg.h,v 1.3 2004/11/10 04:29:09 julian Exp $
-*/
+ * Copyright (c) 1999-2000 Taku YAMAMOTO <taku at cent.saitama-u.ac.jp>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * maestro_reg.h,v 1.13 2001/11/11 18:29:46 taku Exp
+ * $FreeBSD: src/sys/dev/sound/pci/maestro_reg.h,v 1.3 2004/11/10 04:29:09 julian Exp $
+ */
#ifndef MAESTRO_REG_H_INCLUDED
#define MAESTRO_REG_H_INCLUDED
/* -----------------------------
-* PCI config registers
-*/
+ * PCI config registers
+ */
/* Legacy emulation */
#define CONF_LEGACY 0x40
@@ -81,8 +80,8 @@
/* -----------------------------
-* I/O ports
-*/
+ * I/O ports
+ */
/* Direct Sound Processor (aka WP) */
#define PORT_DSP_DATA 0x00 /* WORD RW */
@@ -213,8 +212,8 @@
/* -----------------------------
-* Wave Processor Indexed Data Registers.
-*/
+ * Wave Processor Indexed Data Registers.
+ */
#define WPREG_DATA_PORT 0
#define WPREG_CRAM_PTR 1
@@ -251,8 +250,8 @@
/* -----------------------------
-* Audio Processing Unit.
-*/
+ * Audio Processing Unit.
+ */
#define APUREG_APUTYPE 0
#define APU_DMA_ENABLED 0x4000
#define APU_INT_ON_LOOP 0x2000
@@ -377,8 +376,8 @@
/* -----------------------------
-* Limits.
-*/
+ * Limits.
+ */
#define WPWA_MAXADDR ((1 << 23) - 1)
#define MAESTRO_MAXADDR ((1 << 28) - 1)
Index: es137x.h
===================================================================
RCS file: /home/cvs/src/sys/dev/sound/pci/es137x.h,v
retrieving revision 1.2
retrieving revision 1.3
diff -L sys/dev/sound/pci/es137x.h -L sys/dev/sound/pci/es137x.h -u -r1.2 -r1.3
--- sys/dev/sound/pci/es137x.h
+++ sys/dev/sound/pci/es137x.h
@@ -1,26 +1,25 @@
/*-
-* This supports the ENSONIQ AudioPCI board based on the ES1370.
-*
-* Copyright (c) 1998 Joachim Kuebart <joki at kuebart.stuttgart.netsurf.de>
-* All rights reserved.
-*
-* Redistribution and use in source and binary forms, with or without
-* modification, are permitted provided that the following conditions
-* are met:
-* 1. Redistributions of source code must retain the above copyright
-* notice immediately at the beginning of the file, without modification,
-* this list of conditions, and the following disclaimer.
-* 2. Redistributions in binary form must reproduce the above copyright
-* notice, this list of conditions and the following disclaimer in the
-* documentation and/or other materials provided with the distribution.
-* 3. Absolutely no warranty of function or purpose is made by the author
-* Joachim Kuebart.
-* 4. Modifications may be freely made to this file if the above conditions
-* are met.
-*
-* $MidnightBSD$
-* $FreeBSD: src/sys/dev/sound/pci/es137x.h,v 1.5.2.1 2005/12/30 19:55:53 netchild Exp $
-*/
+ * This supports the ENSONIQ AudioPCI board based on the ES1370.
+ *
+ * Copyright (c) 1998 Joachim Kuebart <joki at kuebart.stuttgart.netsurf.de>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice immediately at the beginning of the file, without modification,
+ * this list of conditions, and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Absolutely no warranty of function or purpose is made by the author
+ * Joachim Kuebart.
+ * 4. Modifications may be freely made to this file if the above conditions
+ * are met.
+ *
+ * $FreeBSD: src/sys/dev/sound/pci/es137x.h,v 1.6 2005/07/31 13:19:38 netchild Exp $
+ */
#ifndef _ES1370_REG_H
#define _ES1370_REG_H
@@ -52,19 +51,19 @@
#define CTRL_ADC_STOP 0x80000000 /* 1 = ADC stopped */
#define CTRL_XCTL1 0x40000000 /* SERR pin if enabled */
#define CTRL_OPEN 0x20000000 /* no function, can be read and
-* written */
+ * written */
#define CTRL_PCLKDIV 0x1fff0000 /* ADC/DAC2 clock divider */
#define CTRL_SH_PCLKDIV 16
#define CTRL_MSFMTSEL 0x00008000 /* MPEG serial data fmt: 0 = Sony, 1
-* = I2S */
+ * = I2S */
#define CTRL_M_SBB 0x00004000 /* DAC2 clock: 0 = PCLKDIV, 1 = MPEG */
#define CTRL_WTSRSEL 0x00003000 /* DAC1 clock freq: 0=5512, 1=11025,
-* 2=22050, 3=44100 */
+ * 2=22050, 3=44100 */
#define CTRL_SH_WTSRSEL 12
#define CTRL_DAC_SYNC 0x00000800 /* 1 = DAC2 runs off DAC1 clock */
#define CTRL_CCB_INTRM 0x00000400 /* 1 = CCB "voice" ints enabled */
#define CTRL_M_CB 0x00000200 /* recording source: 0 = ADC, 1 =
-* MPEG */
+ * MPEG */
#define CTRL_XCTL0 0x00000100 /* 0 = Line in, 1 = Line out */
#define CTRL_BREQ 0x00000080 /* 1 = test mode (internal mem test) */
#define CTRL_DAC1_EN 0x00000040 /* enable DAC1 */
@@ -72,7 +71,7 @@
#define CTRL_ADC_EN 0x00000010 /* enable ADC */
#define CTRL_UART_EN 0x00000008 /* enable MIDI uart */
#define CTRL_JYSTK_EN 0x00000004 /* enable Joystick port (presumably
-* at address 0x200) */
+ * at address 0x200) */
#define CTRL_CDC_EN 0x00000002 /* enable serial (CODEC) interface */
#define CTRL_SERR_DIS 0x00000001 /* 1 = disable PCI SERR signal */
@@ -89,9 +88,9 @@
#define SCTRL_P2INTEN 0x00000200 /* enable interrupt */
#define SCTRL_P1INTEN 0x00000100 /* enable interrupt */
#define SCTRL_P1SCTRLD 0x00000080 /* reload sample count register for
-* DAC1 */
+ * DAC1 */
#define SCTRL_P2DACSEN 0x00000040 /* 1 = DAC2 play back last sample
-* when disabled */
+ * when disabled */
#define SCTRL_R1SEB 0x00000020 /* 1 = 16bit */
#define SCTRL_R1SMB 0x00000010 /* 1 = stereo */
#define SCTRL_R1FMT 0x00000030 /* format mask */
@@ -107,11 +106,11 @@
#define STAT_INTR 0x80000000 /* wired or of all interrupt bits */
#define STAT_CSTAT 0x00000400 /* 1 = codec busy or codec write in
-* progress */
+ * progress */
#define STAT_CBUSY 0x00000200 /* 1 = codec busy */
#define STAT_CWRIP 0x00000100 /* 1 = codec write in progress */
#define STAT_VC 0x00000060 /* CCB int source, 0=DAC1, 1=DAC2,
-* 2=ADC, 3=undef */
+ * 2=ADC, 3=undef */
#define STAT_SH_VC 5
#define STAT_MCCB 0x00000010 /* CCB int pending */
#define STAT_UART 0x00000008 /* UART int pending */
@@ -168,8 +167,8 @@
#define ES1371_SRC_RAM_DATAI(i) (((i)>>0)&0xffff) /* current value of the sample rate converter */
/*
-* S/PDIF specific
-*/
+ * S/PDIF specific
+ */
/* Use ES1370_REG_CONTROL */
#define RECEN_B 0x08000000 /* Used to control mixing of analog with digital data */
@@ -179,8 +178,8 @@
#define TEST_SPDIF 0x00020000 /* Used to put the S/PDIF module in "test mode" */
/*
-* Sample rate converter addresses
-*/
+ * Sample rate converter addresses
+ */
#define ES_SMPREG_DAC1 0x70
#define ES_SMPREG_DAC2 0x74
Index: es137x.c
===================================================================
RCS file: /home/cvs/src/sys/dev/sound/pci/es137x.c,v
retrieving revision 1.2
retrieving revision 1.3
diff -L sys/dev/sound/pci/es137x.c -L sys/dev/sound/pci/es137x.c -u -r1.2 -r1.3
--- sys/dev/sound/pci/es137x.c
+++ sys/dev/sound/pci/es137x.c
@@ -1,51 +1,51 @@
/*-
-* Support the ENSONIQ AudioPCI board and Creative Labs SoundBlaster PCI
-* boards based on the ES1370, ES1371 and ES1373 chips.
-*
-* Copyright (c) 1999 Russell Cattelan <cattelan at thebarn.com>
-* Copyright (c) 1999 Cameron Grant <cg at freebsd.org>
-* Copyright (c) 1998 by Joachim Kuebart. All rights reserved.
-*
-* Redistribution and use in source and binary forms, with or without
-* modification, are permitted provided that the following conditions
-* are met:
-*
-* 1. Redistributions of source code must retain the above copyright
-* notice, this list of conditions and the following disclaimer.
-*
-* 2. Redistributions in binary form must reproduce the above copyright
-* notice, this list of conditions and the following disclaimer in
-* the documentation and/or other materials provided with the
-* distribution.
-*
-* 3. All advertising materials mentioning features or use of this
-* software must display the following acknowledgement:
-* This product includes software developed by Joachim Kuebart.
-*
-* 4. The name of the author may not be used to endorse or promote
-* products derived from this software without specific prior
-* written permission.
-*
-* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
-* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
-* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-* DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
-* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
-* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
-* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
-* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
-* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
-* OF THE POSSIBILITY OF SUCH DAMAGE.
-*/
+ * Support the ENSONIQ AudioPCI board and Creative Labs SoundBlaster PCI
+ * boards based on the ES1370, ES1371 and ES1373 chips.
+ *
+ * Copyright (c) 1999 Russell Cattelan <cattelan at thebarn.com>
+ * Copyright (c) 1999 Cameron Grant <cg at freebsd.org>
+ * Copyright (c) 1998 by Joachim Kuebart. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ * software must display the following acknowledgement:
+ * This product includes software developed by Joachim Kuebart.
+ *
+ * 4. The name of the author may not be used to endorse or promote
+ * products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
/*
-* Part of this code was heavily inspired by the linux driver from
-* Thomas Sailer (sailer at ife.ee.ethz.ch)
-* Just about everything has been touched and reworked in some way but
-* the all the underlying sequences/timing/register values are from
-* Thomas' code.
-*
+ * Part of this code was heavily inspired by the linux driver from
+ * Thomas Sailer (sailer at ife.ee.ethz.ch)
+ * Just about everything has been touched and reworked in some way but
+ * the all the underlying sequences/timing/register values are from
+ * Thomas' code.
+ *
*/
#include <dev/sound/pcm/sound.h>
@@ -59,7 +59,7 @@
#include "mixer_if.h"
-SND_DECLARE_FILE("$MidnightBSD$");
+SND_DECLARE_FILE("$FreeBSD: src/sys/dev/sound/pci/es137x.c,v 1.71 2007/07/05 10:22:37 ariff Exp $");
#define MEM_MAP_REG 0x14
@@ -93,6 +93,11 @@
#define ES_ADC 2
#define ES_NCHANS 3
+#define ES_DMA_SEGS_MIN 2
+#define ES_DMA_SEGS_MAX 256
+#define ES_BLK_MIN 64
+#define ES_BLK_ALIGN (~(ES_BLK_MIN - 1))
+
#define ES1370_DAC1_MINSPEED 5512
#define ES1370_DAC1_MAXSPEED 44100
@@ -100,75 +105,99 @@
struct es_info;
struct es_chinfo {
-struct es_info *parent;
-struct pcm_channel *channel;
-struct snd_dbuf *buffer;
-struct pcmchan_caps caps;
-int dir, num, index;
-u_int32_t fmt, blksz, bufsz;
+ struct es_info *parent;
+ struct pcm_channel *channel;
+ struct snd_dbuf *buffer;
+ struct pcmchan_caps caps;
+ int dir, num, index;
+ uint32_t fmt, blksz, blkcnt, bufsz;
+ uint32_t ptr, prevptr;
+ int active;
};
/*
-* 32bit Ensoniq Configuration (es->escfg).
-* ----------------------------------------
-*
-* +-------+--------+------+------+---------+--------+---------+---------+
-* len | 16 | 1 | 1 | 1 | 2 | 2 | 1 | 8 |
-* +-------+--------+------+------+---------+--------+---------+---------+
-* | fixed | single | | | | | is | general |
-* | rate | pcm | DACx | DACy | numplay | numrec | es1370? | purpose |
-* | | mixer | | | | | | |
-* +-------+--------+------+------+---------+--------+---------+---------+
-*/
-#define ES_FIXED_RATE(cfgv) (((cfgv) & 0xffff0000) >> 16)
-#define ES_SET_FIXED_RATE(cfgv, nv) (((cfgv) & ~0xffff0000) | (((nv) & 0xffff) << 16))
-#define ES_SINGLE_PCM_MIX(cfgv) (((cfgv) & 0x8000) >> 15)
-#define ES_SET_SINGLE_PCM_MIX(cfgv, nv) (((cfgv) & ~0x8000) | (((nv) ? 1 : 0) << 15))
-#define ES_DAC_FIRST(cfgv) (((cfgv) & 0x4000) >> 14)
-#define ES_SET_DAC_FIRST(cfgv, nv) (((cfgv) & ~0x4000) | (((nv) & 0x1) << 14))
-#define ES_DAC_SECOND(cfgv) (((cfgv) & 0x2000) >> 13)
-#define ES_SET_DAC_SECOND(cfgv, nv) (((cfgv) & ~0x2000) | (((nv) & 0x1) << 13))
-#define ES_NUMPLAY(cfgv) (((cfgv) & 0x1800) >> 11)
-#define ES_SET_NUMPLAY(cfgv, nv) (((cfgv) & ~0x1800) | (((nv) & 0x3) << 11))
-#define ES_NUMREC(cfgv) (((cfgv) & 0x600) >> 9)
-#define ES_SET_NUMREC(cfgv, nv) (((cfgv) & ~0x600) | (((nv) & 0x3) << 9))
-#define ES_IS_ES1370(cfgv) (((cfgv) & 0x100) >> 8)
-#define ES_SET_IS_ES1370(cfgv, nv) (((cfgv) & ~0x100) | (((nv) ? 1 : 0) << 8))
-#define ES_GP(cfgv) ((cfgv) & 0xff)
-#define ES_SET_GP(cfgv, nv) (((cfgv) & ~0xff) | ((nv) & 0xff))
-
-#define ES_DAC1_ENABLED(cfgv) (ES_NUMPLAY(cfgv) > 1 || (ES_NUMPLAY(cfgv) == 1 && ES_DAC_FIRST(cfgv) == ES_DAC1))
-#define ES_DAC2_ENABLED(cfgv) (ES_NUMPLAY(cfgv) > 1 || (ES_NUMPLAY(cfgv) == 1 && ES_DAC_FIRST(cfgv) == ES_DAC2))
+ * 32bit Ensoniq Configuration (es->escfg).
+ * ----------------------------------------
+ *
+ * +-------+--------+------+------+---------+--------+---------+---------+
+ * len | 16 | 1 | 1 | 1 | 2 | 2 | 1 | 8 |
+ * +-------+--------+------+------+---------+--------+---------+---------+
+ * | fixed | single | | | | | is | general |
+ * | rate | pcm | DACx | DACy | numplay | numrec | es1370? | purpose |
+ * | | mixer | | | | | | |
+ * +-------+--------+------+------+---------+--------+---------+---------+
+ */
+#define ES_FIXED_RATE(cfgv) \
+ (((cfgv) & 0xffff0000) >> 16)
+#define ES_SET_FIXED_RATE(cfgv, nv) \
+ (((cfgv) & ~0xffff0000) | (((nv) & 0xffff) << 16))
+#define ES_SINGLE_PCM_MIX(cfgv) \
+ (((cfgv) & 0x8000) >> 15)
+#define ES_SET_SINGLE_PCM_MIX(cfgv, nv) \
+ (((cfgv) & ~0x8000) | (((nv) ? 1 : 0) << 15))
+#define ES_DAC_FIRST(cfgv) \
+ (((cfgv) & 0x4000) >> 14)
+#define ES_SET_DAC_FIRST(cfgv, nv) \
+ (((cfgv) & ~0x4000) | (((nv) & 0x1) << 14))
+#define ES_DAC_SECOND(cfgv) \
+ (((cfgv) & 0x2000) >> 13)
+#define ES_SET_DAC_SECOND(cfgv, nv) \
+ (((cfgv) & ~0x2000) | (((nv) & 0x1) << 13))
+#define ES_NUMPLAY(cfgv) \
+ (((cfgv) & 0x1800) >> 11)
+#define ES_SET_NUMPLAY(cfgv, nv) \
+ (((cfgv) & ~0x1800) | (((nv) & 0x3) << 11))
+#define ES_NUMREC(cfgv) \
+ (((cfgv) & 0x600) >> 9)
+#define ES_SET_NUMREC(cfgv, nv) \
+ (((cfgv) & ~0x600) | (((nv) & 0x3) << 9))
+#define ES_IS_ES1370(cfgv) \
+ (((cfgv) & 0x100) >> 8)
+#define ES_SET_IS_ES1370(cfgv, nv) \
+ (((cfgv) & ~0x100) | (((nv) ? 1 : 0) << 8))
+#define ES_GP(cfgv) \
+ ((cfgv) & 0xff)
+#define ES_SET_GP(cfgv, nv) \
+ (((cfgv) & ~0xff) | ((nv) & 0xff))
+
+#define ES_DAC1_ENABLED(cfgv) \
+ (ES_NUMPLAY(cfgv) > 1 || \
+ (ES_NUMPLAY(cfgv) == 1 && ES_DAC_FIRST(cfgv) == ES_DAC1))
+#define ES_DAC2_ENABLED(cfgv) \
+ (ES_NUMPLAY(cfgv) > 1 || \
+ (ES_NUMPLAY(cfgv) == 1 && ES_DAC_FIRST(cfgv) == ES_DAC2))
/*
-* DAC 1/2 configuration through kernel hint - hint.pcm.<unit>.dac="val"
-*
-* 0 = Enable both DACs - Default
-* 1 = Enable single DAC (DAC1)
-* 2 = Enable single DAC (DAC2)
-* 3 = Enable both DACs, swap position (DAC2 comes first instead of DAC1)
-*/
-#define ES_DEFAULT_DAC_CFG 2
+ * DAC 1/2 configuration through kernel hint - hint.pcm.<unit>.dac="val"
+ *
+ * 0 = Enable both DACs - Default
+ * 1 = Enable single DAC (DAC1)
+ * 2 = Enable single DAC (DAC2)
+ * 3 = Enable both DACs, swap position (DAC2 comes first instead of DAC1)
+ */
+#define ES_DEFAULT_DAC_CFG 0
struct es_info {
-bus_space_tag_t st;
-bus_space_handle_t sh;
-bus_dma_tag_t parent_dmat;
-
-struct resource *reg, *irq;
-int regtype, regid, irqid;
-void *ih;
-
-device_t dev;
-int num;
-unsigned int bufsz;
-
-/* Contents of board's registers */
-uint32_t ctrl;
-uint32_t sctrl;
-uint32_t escfg;
-struct es_chinfo ch[ES_NCHANS];
-struct mtx *lock;
+ bus_space_tag_t st;
+ bus_space_handle_t sh;
+ bus_dma_tag_t parent_dmat;
+
+ struct resource *reg, *irq;
+ int regtype, regid, irqid;
+ void *ih;
+
+ device_t dev;
+ int num;
+ unsigned int bufsz, blkcnt;
+
+ /* Contents of board's registers */
+ uint32_t ctrl;
+ uint32_t sctrl;
+ uint32_t escfg;
+ struct es_chinfo ch[ES_NCHANS];
+ struct mtx *lock;
+ struct callout poll_timer;
+ int poll_ticks, polling;
};
#define ES_LOCK(sc) snd_mtxlock((sc)->lock)
@@ -178,72 +207,73 @@
/* prototypes */
static void es_intr(void *);
static uint32_t es1371_wait_src_ready(struct es_info *);
-static void es1371_src_write(struct es_info *, u_short, unsigned short);
-static u_int es1371_adc_rate(struct es_info *, u_int, int);
-static u_int es1371_dac_rate(struct es_info *, u_int, int);
+static void es1371_src_write(struct es_info *,
+ unsigned short, unsigned short);
+static unsigned int es1371_adc_rate(struct es_info *, unsigned int, int);
+static unsigned int es1371_dac_rate(struct es_info *, unsigned int, int);
static int es1371_init(struct es_info *);
static int es1370_init(struct es_info *);
-static int es1370_wrcodec(struct es_info *, u_char, u_char);
+static int es1370_wrcodec(struct es_info *, unsigned char, unsigned char);
-static u_int32_t es_fmt[] = {
-AFMT_U8,
-AFMT_STEREO | AFMT_U8,
-AFMT_S16_LE,
-AFMT_STEREO | AFMT_S16_LE,
-0
+static uint32_t es_fmt[] = {
+ AFMT_U8,
+ AFMT_STEREO | AFMT_U8,
+ AFMT_S16_LE,
+ AFMT_STEREO | AFMT_S16_LE,
+ 0
};
static struct pcmchan_caps es_caps = {4000, 48000, es_fmt, 0};
static const struct {
-unsigned volidx:4;
-unsigned left:4;
-unsigned right:4;
-unsigned stereo:1;
-unsigned recmask:13;
-unsigned avail:1;
+ unsigned volidx:4;
+ unsigned left:4;
+ unsigned right:4;
+ unsigned stereo:1;
+ unsigned recmask:13;
+ unsigned avail:1;
} mixtable[SOUND_MIXER_NRDEVICES] = {
-[SOUND_MIXER_VOLUME] = { 0, 0x0, 0x1, 1, 0x1f7f, 1 },
-[SOUND_MIXER_PCM] = { 1, 0x2, 0x3, 1, 0x0400, 1 },
-[SOUND_MIXER_SYNTH] = { 2, 0x4, 0x5, 1, 0x0060, 1 },
-[SOUND_MIXER_CD] = { 3, 0x6, 0x7, 1, 0x0006, 1 },
-[SOUND_MIXER_LINE] = { 4, 0x8, 0x9, 1, 0x0018, 1 },
-[SOUND_MIXER_LINE1] = { 5, 0xa, 0xb, 1, 0x1800, 1 },
-[SOUND_MIXER_LINE2] = { 6, 0xc, 0x0, 0, 0x0100, 1 },
-[SOUND_MIXER_LINE3] = { 7, 0xd, 0x0, 0, 0x0200, 1 },
-[SOUND_MIXER_MIC] = { 8, 0xe, 0x0, 0, 0x0001, 1 },
-[SOUND_MIXER_OGAIN] = { 9, 0xf, 0x0, 0, 0x0000, 1 }
+ [SOUND_MIXER_VOLUME] = { 0, 0x0, 0x1, 1, 0x1f7f, 1 },
+ [SOUND_MIXER_PCM] = { 1, 0x2, 0x3, 1, 0x0400, 1 },
+ [SOUND_MIXER_SYNTH] = { 2, 0x4, 0x5, 1, 0x0060, 1 },
+ [SOUND_MIXER_CD] = { 3, 0x6, 0x7, 1, 0x0006, 1 },
+ [SOUND_MIXER_LINE] = { 4, 0x8, 0x9, 1, 0x0018, 1 },
+ [SOUND_MIXER_LINE1] = { 5, 0xa, 0xb, 1, 0x1800, 1 },
+ [SOUND_MIXER_LINE2] = { 6, 0xc, 0x0, 0, 0x0100, 1 },
+ [SOUND_MIXER_LINE3] = { 7, 0xd, 0x0, 0, 0x0200, 1 },
+ [SOUND_MIXER_MIC] = { 8, 0xe, 0x0, 0, 0x0001, 1 },
+ [SOUND_MIXER_OGAIN] = { 9, 0xf, 0x0, 0, 0x0000, 1 }
};
-static __inline u_int32_t
+static __inline uint32_t
es_rd(struct es_info *es, int regno, int size)
{
-switch (size) {
-case 1:
-return bus_space_read_1(es->st, es->sh, regno);
-case 2:
-return bus_space_read_2(es->st, es->sh, regno);
-case 4:
-return bus_space_read_4(es->st, es->sh, regno);
-default:
-return 0xFFFFFFFF;
-}
+ switch (size) {
+ case 1:
+ return (bus_space_read_1(es->st, es->sh, regno));
+ case 2:
+ return (bus_space_read_2(es->st, es->sh, regno));
+ case 4:
+ return (bus_space_read_4(es->st, es->sh, regno));
+ default:
+ return (0xFFFFFFFF);
+ }
}
static __inline void
-es_wr(struct es_info *es, int regno, u_int32_t data, int size)
+es_wr(struct es_info *es, int regno, uint32_t data, int size)
{
-switch (size) {
-case 1:
-bus_space_write_1(es->st, es->sh, regno, data);
-break;
-case 2:
-bus_space_write_2(es->st, es->sh, regno, data);
-break;
-case 4:
-bus_space_write_4(es->st, es->sh, regno, data);
-break;
-}
+ switch (size) {
+ case 1:
+ bus_space_write_1(es->st, es->sh, regno, data);
+ break;
+ case 2:
+ bus_space_write_2(es->st, es->sh, regno, data);
+ break;
+ case 4:
+ bus_space_write_4(es->st, es->sh, regno, data);
+ break;
+ }
}
/* -------------------------------------------------------------------- */
@@ -252,431 +282,605 @@
static int
es1370_mixinit(struct snd_mixer *m)
{
-struct es_info *es;
-int i;
-u_int32_t v;
-
-es = mix_getdevinfo(m);
-v = 0;
-for (i = 0; i < SOUND_MIXER_NRDEVICES; i++)
-if (mixtable[i].avail) v |= (1 << i);
-/*
-* Each DAC1/2 for ES1370 can be controlled independently
-* DAC1 = controlled by synth
-* DAC2 = controlled by pcm
-* This is indeed can confuse user if DAC1 become primary playback
-* channel. Try to be smart and combine both if necessary.
-*/
-if (ES_SINGLE_PCM_MIX(es->escfg))
-v &= ~(1 << SOUND_MIXER_SYNTH);
-mix_setdevs(m, v);
-v = 0;
-for (i = 0; i < SOUND_MIXER_NRDEVICES; i++)
-if (mixtable[i].recmask) v |= (1 << i);
-if (ES_SINGLE_PCM_MIX(es->escfg)) /* ditto */
-v &= ~(1 << SOUND_MIXER_SYNTH);
-mix_setrecdevs(m, v);
-return 0;
+ struct es_info *es;
+ int i;
+ uint32_t v;
+
+ es = mix_getdevinfo(m);
+ v = 0;
+ for (i = 0; i < SOUND_MIXER_NRDEVICES; i++) {
+ if (mixtable[i].avail)
+ v |= (1 << i);
+ }
+ /*
+ * Each DAC1/2 for ES1370 can be controlled independently
+ * DAC1 = controlled by synth
+ * DAC2 = controlled by pcm
+ * This is indeed can confuse user if DAC1 become primary playback
+ * channel. Try to be smart and combine both if necessary.
+ */
+ if (ES_SINGLE_PCM_MIX(es->escfg))
+ v &= ~(1 << SOUND_MIXER_SYNTH);
+ mix_setdevs(m, v);
+ v = 0;
+ for (i = 0; i < SOUND_MIXER_NRDEVICES; i++) {
+ if (mixtable[i].recmask)
+ v |= (1 << i);
+ }
+ if (ES_SINGLE_PCM_MIX(es->escfg)) /* ditto */
+ v &= ~(1 << SOUND_MIXER_SYNTH);
+ mix_setrecdevs(m, v);
+ return (0);
}
static int
es1370_mixset(struct snd_mixer *m, unsigned dev, unsigned left, unsigned right)
{
-struct es_info *es;
-int l, r, rl, rr, set_dac1;
+ struct es_info *es;
+ int l, r, rl, rr, set_dac1;
+
+ if (!mixtable[dev].avail)
+ return (-1);
+ l = left;
+ r = (mixtable[dev].stereo) ? right : l;
+ if (mixtable[dev].left == 0xf)
+ rl = (l < 2) ? 0x80 : 7 - (l - 2) / 14;
+ else
+ rl = (l < 10) ? 0x80 : 15 - (l - 10) / 6;
+ es = mix_getdevinfo(m);
+ ES_LOCK(es);
+ if (dev == SOUND_MIXER_PCM && (ES_SINGLE_PCM_MIX(es->escfg)) &&
+ ES_DAC1_ENABLED(es->escfg))
+ set_dac1 = 1;
+ else
+ set_dac1 = 0;
+ if (mixtable[dev].stereo) {
+ rr = (r < 10) ? 0x80 : 15 - (r - 10) / 6;
+ es1370_wrcodec(es, mixtable[dev].right, rr);
+ if (set_dac1 && mixtable[SOUND_MIXER_SYNTH].stereo)
+ es1370_wrcodec(es,
+ mixtable[SOUND_MIXER_SYNTH].right, rr);
+ }
+ es1370_wrcodec(es, mixtable[dev].left, rl);
+ if (set_dac1)
+ es1370_wrcodec(es, mixtable[SOUND_MIXER_SYNTH].left, rl);
+ ES_UNLOCK(es);
-if (!mixtable[dev].avail) return -1;
-l = left;
-r = mixtable[dev].stereo? right : l;
-if (mixtable[dev].left == 0xf) {
-rl = (l < 2)? 0x80 : 7 - (l - 2) / 14;
-} else {
-rl = (l < 10)? 0x80 : 15 - (l - 10) / 6;
-}
-es = mix_getdevinfo(m);
-ES_LOCK(es);
-if (dev == SOUND_MIXER_PCM && (ES_SINGLE_PCM_MIX(es->escfg)) &&
-ES_DAC1_ENABLED(es->escfg)) {
-set_dac1 = 1;
-} else {
-set_dac1 = 0;
-}
-if (mixtable[dev].stereo) {
-rr = (r < 10)? 0x80 : 15 - (r - 10) / 6;
-es1370_wrcodec(es, mixtable[dev].right, rr);
-if (set_dac1 && mixtable[SOUND_MIXER_SYNTH].stereo)
-es1370_wrcodec(es, mixtable[SOUND_MIXER_SYNTH].right, rr);
-}
-es1370_wrcodec(es, mixtable[dev].left, rl);
-if (set_dac1)
-es1370_wrcodec(es, mixtable[SOUND_MIXER_SYNTH].left, rl);
-ES_UNLOCK(es);
-
-return l | (r << 8);
+ return (l | (r << 8));
}
static int
-es1370_mixsetrecsrc(struct snd_mixer *m, u_int32_t src)
-{
-struct es_info *es;
-int i, j = 0;
-
-es = mix_getdevinfo(m);
-if (src == 0) src = 1 << SOUND_MIXER_MIC;
-src &= mix_getrecdevs(m);
-for (i = 0; i < SOUND_MIXER_NRDEVICES; i++)
-if ((src & (1 << i)) != 0) j |= mixtable[i].recmask;
-
-ES_LOCK(es);
-if ((src & (1 << SOUND_MIXER_PCM)) && ES_SINGLE_PCM_MIX(es->escfg) &&
-ES_DAC1_ENABLED(es->escfg)) {
-j |= mixtable[SOUND_MIXER_SYNTH].recmask;
-}
-es1370_wrcodec(es, CODEC_LIMIX1, j & 0x55);
-es1370_wrcodec(es, CODEC_RIMIX1, j & 0xaa);
-es1370_wrcodec(es, CODEC_LIMIX2, (j >> 8) & 0x17);
-es1370_wrcodec(es, CODEC_RIMIX2, (j >> 8) & 0x0f);
-es1370_wrcodec(es, CODEC_OMIX1, 0x7f);
-es1370_wrcodec(es, CODEC_OMIX2, 0x3f);
-ES_UNLOCK(es);
+es1370_mixsetrecsrc(struct snd_mixer *m, uint32_t src)
+{
+ struct es_info *es;
+ int i, j = 0;
+
+ es = mix_getdevinfo(m);
+ if (src == 0) src = 1 << SOUND_MIXER_MIC;
+ src &= mix_getrecdevs(m);
+ for (i = 0; i < SOUND_MIXER_NRDEVICES; i++)
+ if ((src & (1 << i)) != 0) j |= mixtable[i].recmask;
+
+ ES_LOCK(es);
+ if ((src & (1 << SOUND_MIXER_PCM)) && ES_SINGLE_PCM_MIX(es->escfg) &&
+ ES_DAC1_ENABLED(es->escfg))
+ j |= mixtable[SOUND_MIXER_SYNTH].recmask;
+ es1370_wrcodec(es, CODEC_LIMIX1, j & 0x55);
+ es1370_wrcodec(es, CODEC_RIMIX1, j & 0xaa);
+ es1370_wrcodec(es, CODEC_LIMIX2, (j >> 8) & 0x17);
+ es1370_wrcodec(es, CODEC_RIMIX2, (j >> 8) & 0x0f);
+ es1370_wrcodec(es, CODEC_OMIX1, 0x7f);
+ es1370_wrcodec(es, CODEC_OMIX2, 0x3f);
+ ES_UNLOCK(es);
-return src;
+ return (src);
}
static kobj_method_t es1370_mixer_methods[] = {
-KOBJMETHOD(mixer_init, es1370_mixinit),
-KOBJMETHOD(mixer_set, es1370_mixset),
-KOBJMETHOD(mixer_setrecsrc, es1370_mixsetrecsrc),
-{ 0, 0 }
+ KOBJMETHOD(mixer_init, es1370_mixinit),
+ KOBJMETHOD(mixer_set, es1370_mixset),
+ KOBJMETHOD(mixer_setrecsrc, es1370_mixsetrecsrc),
+ { 0, 0 }
};
MIXER_DECLARE(es1370_mixer);
/* -------------------------------------------------------------------- */
static int
-es1370_wrcodec(struct es_info *es, u_char i, u_char data)
+es1370_wrcodec(struct es_info *es, unsigned char i, unsigned char data)
{
-u_int t;
+ unsigned int t;
-ES_LOCK_ASSERT(es);
+ ES_LOCK_ASSERT(es);
-for (t = 0; t < 0x1000; t++) {
-if ((es_rd(es, ES1370_REG_STATUS, 4) &
-STAT_CSTAT) == 0) {
-es_wr(es, ES1370_REG_CODEC,
-((u_short)i << CODEC_INDEX_SHIFT) | data, 2);
-return 0;
-}
-DELAY(1);
-}
-device_printf(es->dev, "%s: timed outn", __func__);
-return -1;
+ for (t = 0; t < 0x1000; t++) {
+ if ((es_rd(es, ES1370_REG_STATUS, 4) &
+ STAT_CSTAT) == 0) {
+ es_wr(es, ES1370_REG_CODEC,
+ ((unsigned short)i << CODEC_INDEX_SHIFT) | data, 2);
+ return (0);
+ }
+ DELAY(1);
+ }
+ device_printf(es->dev, "%s: timed out\n", __func__);
+ return (-1);
}
/* -------------------------------------------------------------------- */
/* channel interface */
static void *
-eschan_init(kobj_t obj, void *devinfo, struct snd_dbuf *b, struct pcm_channel *c, int dir)
+eschan_init(kobj_t obj, void *devinfo, struct snd_dbuf *b,
+ struct pcm_channel *c, int dir)
{
-struct es_info *es = devinfo;
-struct es_chinfo *ch;
-uint32_t index;
-
-ES_LOCK(es);
-
-if (dir == PCMDIR_PLAY) {
-index = ES_GP(es->escfg);
-es->escfg = ES_SET_GP(es->escfg, index + 1);
-if (index == 0) {
-index = ES_DAC_FIRST(es->escfg);
-} else if (index == 1) {
-index = ES_DAC_SECOND(es->escfg);
-} else {
-device_printf(es->dev, "Invalid ES_GP index: %dn", index);
-ES_UNLOCK(es);
-return NULL;
-}
-if (!(index == ES_DAC1 || index == ES_DAC2)) {
-device_printf(es->dev, "Unknown DAC: %dn",
-index + 1);
-ES_UNLOCK(es);
-return NULL;
-}
-if (es->ch[index].channel != NULL) {
-device_printf(es->dev, "DAC%d already initialized!n",
-index + 1);
-ES_UNLOCK(es);
-return NULL;
-}
-} else
-index = ES_ADC;
-
-ch = &es->ch[index];
-ch->index = index;
-ch->num = es->num++;
-ch->caps = es_caps;
-if (ES_IS_ES1370(es->escfg)) {
-if (ch->index == ES_DAC1) {
-ch->caps.maxspeed = ES1370_DAC1_MAXSPEED;
-ch->caps.minspeed = ES1370_DAC1_MINSPEED;
-} else {
-uint32_t fixed_rate = ES_FIXED_RATE(es->escfg);
-if (!(fixed_rate < es_caps.minspeed ||
-fixed_rate > es_caps.maxspeed)) {
-ch->caps.maxspeed = fixed_rate;
-ch->caps.minspeed = fixed_rate;
-}
-}
-}
-ch->parent = es;
-ch->channel = c;
-ch->buffer = b;
-ch->bufsz = es->bufsz;
-ch->blksz = ch->bufsz / 2;
-ch->dir = dir;
-ES_UNLOCK(es);
-if (sndbuf_alloc(ch->buffer, es->parent_dmat, ch->bufsz) != 0)
-return NULL;
-ES_LOCK(es);
-if (dir == PCMDIR_PLAY) {
-if (ch->index == ES_DAC1) {
-es_wr(es, ES1370_REG_MEMPAGE, ES1370_REG_DAC1_FRAMEADR >> 8, 1);
-es_wr(es, ES1370_REG_DAC1_FRAMEADR & 0xff, sndbuf_getbufaddr(ch->buffer), 4);
-es_wr(es, ES1370_REG_DAC1_FRAMECNT & 0xff, (ch->bufsz >> 2) - 1, 4);
-} else {
-es_wr(es, ES1370_REG_MEMPAGE, ES1370_REG_DAC2_FRAMEADR >> 8, 1);
-es_wr(es, ES1370_REG_DAC2_FRAMEADR & 0xff, sndbuf_getbufaddr(ch->buffer), 4);
-es_wr(es, ES1370_REG_DAC2_FRAMECNT & 0xff, (ch->bufsz >> 2) - 1, 4);
-}
-} else {
-es_wr(es, ES1370_REG_MEMPAGE, ES1370_REG_ADC_FRAMEADR >> 8, 1);
-es_wr(es, ES1370_REG_ADC_FRAMEADR & 0xff, sndbuf_getbufaddr(ch->buffer), 4);
-es_wr(es, ES1370_REG_ADC_FRAMECNT & 0xff, (ch->bufsz >> 2) - 1, 4);
-}
-ES_UNLOCK(es);
-return ch;
-}
-
-static int
-eschan_setformat(kobj_t obj, void *data, u_int32_t format)
-{
-struct es_chinfo *ch = data;
-struct es_info *es = ch->parent;
-
-ES_LOCK(es);
-if (ch->dir == PCMDIR_PLAY) {
-if (ch->index == ES_DAC1) {
-es->sctrl &= ~SCTRL_P1FMT;
-if (format & AFMT_S16_LE) es->sctrl |= SCTRL_P1SEB;
-if (format & AFMT_STEREO) es->sctrl |= SCTRL_P1SMB;
-} else {
-es->sctrl &= ~SCTRL_P2FMT;
-if (format & AFMT_S16_LE) es->sctrl |= SCTRL_P2SEB;
-if (format & AFMT_STEREO) es->sctrl |= SCTRL_P2SMB;
-}
-} else {
-es->sctrl &= ~SCTRL_R1FMT;
-if (format & AFMT_S16_LE) es->sctrl |= SCTRL_R1SEB;
-if (format & AFMT_STEREO) es->sctrl |= SCTRL_R1SMB;
-}
-es_wr(es, ES1370_REG_SERIAL_CONTROL, es->sctrl, 4);
-ES_UNLOCK(es);
-ch->fmt = format;
-return 0;
-}
-
-static int
-eschan1370_setspeed(kobj_t obj, void *data, u_int32_t speed)
-{
-struct es_chinfo *ch = data;
-struct es_info *es = ch->parent;
-
-/* Fixed rate , do nothing. */
-if (ch->caps.minspeed == ch->caps.maxspeed)
-return ch->caps.maxspeed;
-if (speed < ch->caps.minspeed)
-speed = ch->caps.minspeed;
-if (speed > ch->caps.maxspeed)
-speed = ch->caps.maxspeed;
-ES_LOCK(es);
-if (ch->index == ES_DAC1) {
-/*
-* DAC1 does not support continuous rate settings.
-* Pick the nearest and use it since FEEDER_RATE will
-* do the the proper conversion for us.
-*/
-es->ctrl &= ~CTRL_WTSRSEL;
-if (speed < 8268) {
-speed = 5512;
-es->ctrl |= 0 << CTRL_SH_WTSRSEL;
-} else if (speed < 16537) {
-speed = 11025;
-es->ctrl |= 1 << CTRL_SH_WTSRSEL;
-} else if (speed < 33075) {
-speed = 22050;
-es->ctrl |= 2 << CTRL_SH_WTSRSEL;
-} else {
-speed = 44100;
-es->ctrl |= 3 << CTRL_SH_WTSRSEL;
-}
-} else {
-es->ctrl &= ~CTRL_PCLKDIV;
-es->ctrl |= DAC2_SRTODIV(speed) << CTRL_SH_PCLKDIV;
-}
-es_wr(es, ES1370_REG_CONTROL, es->ctrl, 4);
-ES_UNLOCK(es);
-return speed;
-}
-
-static int
-eschan1371_setspeed(kobj_t obj, void *data, u_int32_t speed)
-{
-struct es_chinfo *ch = data;
-struct es_info *es = ch->parent;
-uint32_t i;
-int delta;
-
-ES_LOCK(es);
-if (ch->dir == PCMDIR_PLAY)
-i = es1371_dac_rate(es, speed, ch->index); /* play */
-else
-i = es1371_adc_rate(es, speed, ch->index); /* record */
-ES_UNLOCK(es);
-delta = (speed > i) ? speed - i : i - speed;
-if (delta < 2)
-return speed;
-return i;
-}
-
-static int
-eschan_setblocksize(kobj_t obj, void *data, u_int32_t blocksize)
-{
-struct es_info *es;
-struct es_chinfo *ch = data;
-uint32_t oblksz, obufsz;
-int error;
-
-oblksz = ch->blksz;
-obufsz = ch->bufsz;
-ch->blksz = blocksize;
-ch->bufsz = ch->blksz * 2;
-error = sndbuf_resize(ch->buffer, 2, ch->blksz);
-if (error != 0) {
-ch->blksz = oblksz;
-ch->bufsz = obufsz;
-es = ch->parent;
-device_printf(es->dev, "unable to set block size, blksz = %d, "
-"error = %d", blocksize, error);
+ struct es_info *es = devinfo;
+ struct es_chinfo *ch;
+ uint32_t index;
+
+ ES_LOCK(es);
+
+ if (dir == PCMDIR_PLAY) {
+ index = ES_GP(es->escfg);
+ es->escfg = ES_SET_GP(es->escfg, index + 1);
+ if (index == 0)
+ index = ES_DAC_FIRST(es->escfg);
+ else if (index == 1)
+ index = ES_DAC_SECOND(es->escfg);
+ else {
+ device_printf(es->dev,
+ "Invalid ES_GP index: %d\n", index);
+ ES_UNLOCK(es);
+ return (NULL);
+ }
+ if (!(index == ES_DAC1 || index == ES_DAC2)) {
+ device_printf(es->dev, "Unknown DAC: %d\n", index + 1);
+ ES_UNLOCK(es);
+ return (NULL);
+ }
+ if (es->ch[index].channel != NULL) {
+ device_printf(es->dev, "DAC%d already initialized!\n",
+ index + 1);
+ ES_UNLOCK(es);
+ return (NULL);
+ }
+ } else
+ index = ES_ADC;
+
+ ch = &es->ch[index];
+ ch->index = index;
+ ch->num = es->num++;
+ ch->caps = es_caps;
+ if (ES_IS_ES1370(es->escfg)) {
+ if (ch->index == ES_DAC1) {
+ ch->caps.maxspeed = ES1370_DAC1_MAXSPEED;
+ ch->caps.minspeed = ES1370_DAC1_MINSPEED;
+ } else {
+ uint32_t fixed_rate = ES_FIXED_RATE(es->escfg);
+ if (!(fixed_rate < es_caps.minspeed ||
+ fixed_rate > es_caps.maxspeed)) {
+ ch->caps.maxspeed = fixed_rate;
+ ch->caps.minspeed = fixed_rate;
+ }
+ }
+ }
+ ch->parent = es;
+ ch->channel = c;
+ ch->buffer = b;
+ ch->bufsz = es->bufsz;
+ ch->blkcnt = es->blkcnt;
+ ch->blksz = ch->bufsz / ch->blkcnt;
+ ch->dir = dir;
+ ES_UNLOCK(es);
+ if (sndbuf_alloc(ch->buffer, es->parent_dmat, 0, ch->bufsz) != 0)
+ return (NULL);
+ ES_LOCK(es);
+ if (dir == PCMDIR_PLAY) {
+ if (ch->index == ES_DAC1) {
+ es_wr(es, ES1370_REG_MEMPAGE,
+ ES1370_REG_DAC1_FRAMEADR >> 8, 1);
+ es_wr(es, ES1370_REG_DAC1_FRAMEADR & 0xff,
+ sndbuf_getbufaddr(ch->buffer), 4);
+ es_wr(es, ES1370_REG_DAC1_FRAMECNT & 0xff,
+ (ch->bufsz >> 2) - 1, 4);
+ } else {
+ es_wr(es, ES1370_REG_MEMPAGE,
+ ES1370_REG_DAC2_FRAMEADR >> 8, 1);
+ es_wr(es, ES1370_REG_DAC2_FRAMEADR & 0xff,
+ sndbuf_getbufaddr(ch->buffer), 4);
+ es_wr(es, ES1370_REG_DAC2_FRAMECNT & 0xff,
+ (ch->bufsz >> 2) - 1, 4);
+ }
+ } else {
+ es_wr(es, ES1370_REG_MEMPAGE, ES1370_REG_ADC_FRAMEADR >> 8, 1);
+ es_wr(es, ES1370_REG_ADC_FRAMEADR & 0xff,
+ sndbuf_getbufaddr(ch->buffer), 4);
+ es_wr(es, ES1370_REG_ADC_FRAMECNT & 0xff,
+ (ch->bufsz >> 2) - 1, 4);
+ }
+ ES_UNLOCK(es);
+ return (ch);
+}
+
+static int
+eschan_setformat(kobj_t obj, void *data, uint32_t format)
+{
+ struct es_chinfo *ch = data;
+ struct es_info *es = ch->parent;
+
+ ES_LOCK(es);
+ if (ch->dir == PCMDIR_PLAY) {
+ if (ch->index == ES_DAC1) {
+ es->sctrl &= ~SCTRL_P1FMT;
+ if (format & AFMT_S16_LE)
+ es->sctrl |= SCTRL_P1SEB;
+ if (format & AFMT_STEREO)
+ es->sctrl |= SCTRL_P1SMB;
+ } else {
+ es->sctrl &= ~SCTRL_P2FMT;
+ if (format & AFMT_S16_LE)
+ es->sctrl |= SCTRL_P2SEB;
+ if (format & AFMT_STEREO)
+ es->sctrl |= SCTRL_P2SMB;
+ }
+ } else {
+ es->sctrl &= ~SCTRL_R1FMT;
+ if (format & AFMT_S16_LE)
+ es->sctrl |= SCTRL_R1SEB;
+ if (format & AFMT_STEREO)
+ es->sctrl |= SCTRL_R1SMB;
+ }
+ es_wr(es, ES1370_REG_SERIAL_CONTROL, es->sctrl, 4);
+ ES_UNLOCK(es);
+ ch->fmt = format;
+ return (0);
+}
+
+static int
+eschan1370_setspeed(kobj_t obj, void *data, uint32_t speed)
+{
+ struct es_chinfo *ch = data;
+ struct es_info *es = ch->parent;
+
+ ES_LOCK(es);
+ /* Fixed rate , do nothing. */
+ if (ch->caps.minspeed == ch->caps.maxspeed) {
+ ES_UNLOCK(es);
+ return (ch->caps.maxspeed);
+ }
+ if (speed < ch->caps.minspeed)
+ speed = ch->caps.minspeed;
+ if (speed > ch->caps.maxspeed)
+ speed = ch->caps.maxspeed;
+ if (ch->index == ES_DAC1) {
+ /*
+ * DAC1 does not support continuous rate settings.
+ * Pick the nearest and use it since FEEDER_RATE will
+ * do the the proper conversion for us.
+ */
+ es->ctrl &= ~CTRL_WTSRSEL;
+ if (speed < 8268) {
+ speed = 5512;
+ es->ctrl |= 0 << CTRL_SH_WTSRSEL;
+ } else if (speed < 16537) {
+ speed = 11025;
+ es->ctrl |= 1 << CTRL_SH_WTSRSEL;
+ } else if (speed < 33075) {
+ speed = 22050;
+ es->ctrl |= 2 << CTRL_SH_WTSRSEL;
+ } else {
+ speed = 44100;
+ es->ctrl |= 3 << CTRL_SH_WTSRSEL;
+ }
+ } else {
+ es->ctrl &= ~CTRL_PCLKDIV;
+ es->ctrl |= DAC2_SRTODIV(speed) << CTRL_SH_PCLKDIV;
+ }
+ es_wr(es, ES1370_REG_CONTROL, es->ctrl, 4);
+ ES_UNLOCK(es);
+ return (speed);
+}
+
+static int
+eschan1371_setspeed(kobj_t obj, void *data, uint32_t speed)
+{
+ struct es_chinfo *ch = data;
+ struct es_info *es = ch->parent;
+ uint32_t i;
+ int delta;
+
+ ES_LOCK(es);
+ if (ch->dir == PCMDIR_PLAY)
+ i = es1371_dac_rate(es, speed, ch->index); /* play */
+ else
+ i = es1371_adc_rate(es, speed, ch->index); /* record */
+ ES_UNLOCK(es);
+ delta = (speed > i) ? (speed - i) : (i - speed);
+ if (delta < 2)
+ return (speed);
+ return (i);
+}
+
+static int
+eschan_setfragments(kobj_t obj, void *data, uint32_t blksz, uint32_t blkcnt)
+{
+ struct es_chinfo *ch = data;
+ struct es_info *es = ch->parent;
+
+ blksz &= ES_BLK_ALIGN;
+
+ if (blksz > (sndbuf_getmaxsize(ch->buffer) / ES_DMA_SEGS_MIN))
+ blksz = sndbuf_getmaxsize(ch->buffer) / ES_DMA_SEGS_MIN;
+ if (blksz < ES_BLK_MIN)
+ blksz = ES_BLK_MIN;
+ if (blkcnt > ES_DMA_SEGS_MAX)
+ blkcnt = ES_DMA_SEGS_MAX;
+ if (blkcnt < ES_DMA_SEGS_MIN)
+ blkcnt = ES_DMA_SEGS_MIN;
+
+ while ((blksz * blkcnt) > sndbuf_getmaxsize(ch->buffer)) {
+ if ((blkcnt >> 1) >= ES_DMA_SEGS_MIN)
+ blkcnt >>= 1;
+ else if ((blksz >> 1) >= ES_BLK_MIN)
+ blksz >>= 1;
+ else
+ break;
+ }
+
+ if ((sndbuf_getblksz(ch->buffer) != blksz ||
+ sndbuf_getblkcnt(ch->buffer) != blkcnt) &&
+ sndbuf_resize(ch->buffer, blkcnt, blksz) != 0)
+ device_printf(es->dev, "%s: failed blksz=%u blkcnt=%u\n",
+ __func__, blksz, blkcnt);
+
+ ch->bufsz = sndbuf_getsize(ch->buffer);
+ ch->blksz = sndbuf_getblksz(ch->buffer);
+ ch->blkcnt = sndbuf_getblkcnt(ch->buffer);
+
+ return (1);
+}
+
+static int
+eschan_setblocksize(kobj_t obj, void *data, uint32_t blksz)
+{
+ struct es_chinfo *ch = data;
+ struct es_info *es = ch->parent;
+
+ eschan_setfragments(obj, data, blksz, es->blkcnt);
+
+ return (ch->blksz);
+}
+
+#define es_chan_active(es) ((es)->ch[ES_DAC1].active + \
+ (es)->ch[ES_DAC2].active + \
+ (es)->ch[ES_ADC].active)
+
+static __inline int
+es_poll_channel(struct es_chinfo *ch)
+{
+ struct es_info *es;
+ uint32_t sz, delta;
+ uint32_t reg, ptr;
+
+ if (ch == NULL || ch->channel == NULL || ch->active == 0)
+ return (0);
+
+ es = ch->parent;
+ if (ch->dir == PCMDIR_PLAY) {
+ if (ch->index == ES_DAC1)
+ reg = ES1370_REG_DAC1_FRAMECNT;
+ else
+ reg = ES1370_REG_DAC2_FRAMECNT;
+ } else
+ reg = ES1370_REG_ADC_FRAMECNT;
+ sz = ch->blksz * ch->blkcnt;
+ es_wr(es, ES1370_REG_MEMPAGE, reg >> 8, 4);
+ ptr = es_rd(es, reg & 0x000000ff, 4) >> 16;
+ ptr <<= 2;
+ ch->ptr = ptr;
+ ptr %= sz;
+ ptr &= ~(ch->blksz - 1);
+ delta = (sz + ptr - ch->prevptr) % sz;
+
+ if (delta < ch->blksz)
+ return (0);
+
+ ch->prevptr = ptr;
+
+ return (1);
}
-return ch->blksz;
+
+static void
+es_poll_callback(void *arg)
+{
+ struct es_info *es = arg;
+ uint32_t trigger = 0;
+ int i;
+
+ if (es == NULL)
+ return;
+
+ ES_LOCK(es);
+ if (es->polling == 0 || es_chan_active(es) == 0) {
+ ES_UNLOCK(es);
+ return;
+ }
+
+ for (i = 0; i < ES_NCHANS; i++) {
+ if (es_poll_channel(&es->ch[i]) != 0)
+ trigger |= 1 << i;
+ }
+
+ /* XXX */
+ callout_reset(&es->poll_timer, 1/*es->poll_ticks*/,
+ es_poll_callback, es);
+
+ ES_UNLOCK(es);
+
+ for (i = 0; i < ES_NCHANS; i++) {
+ if (trigger & (1 << i))
+ chn_intr(es->ch[i].channel);
+ }
}
static int
eschan_trigger(kobj_t obj, void *data, int go)
{
-struct es_chinfo *ch = data;
-struct es_info *es = ch->parent;
-uint32_t cnt, b = 0;
-
-if (go == PCMTRIG_EMLDMAWR || go == PCMTRIG_EMLDMARD)
-return 0;
-
-cnt = (ch->blksz / sndbuf_getbps(ch->buffer)) - 1;
-if (ch->fmt & AFMT_16BIT)
-b |= 0x02;
-if (ch->fmt & AFMT_STEREO)
-b |= 0x01;
-ES_LOCK(es);
-if (ch->dir == PCMDIR_PLAY) {
-if (go == PCMTRIG_START) {
-if (ch->index == ES_DAC1) {
-es->ctrl |= CTRL_DAC1_EN;
-es->sctrl &= ~(SCTRL_P1LOOPSEL | SCTRL_P1PAUSE | SCTRL_P1SCTRLD);
-es->sctrl |= SCTRL_P1INTEN | b;
-es_wr(es, ES1370_REG_DAC1_SCOUNT, cnt, 4);
-/* start at beginning of buffer */
-es_wr(es, ES1370_REG_MEMPAGE, ES1370_REG_DAC1_FRAMECNT >> 8, 4);
-es_wr(es, ES1370_REG_DAC1_FRAMECNT & 0xff, (ch->bufsz >> 2) - 1, 4);
-} else {
-es->ctrl |= CTRL_DAC2_EN;
-es->sctrl &= ~(SCTRL_P2ENDINC | SCTRL_P2STINC | SCTRL_P2LOOPSEL | SCTRL_P2PAUSE | SCTRL_P2DACSEN);
-es->sctrl |= SCTRL_P2INTEN | (b << 2) |
-(((b & 2) ? : 1) << SCTRL_SH_P2ENDINC);
-es_wr(es, ES1370_REG_DAC2_SCOUNT, cnt, 4);
-/* start at beginning of buffer */
-es_wr(es, ES1370_REG_MEMPAGE, ES1370_REG_DAC2_FRAMECNT >> 8, 4);
-es_wr(es, ES1370_REG_DAC2_FRAMECNT & 0xff, (ch->bufsz >> 2) - 1, 4);
-}
-} else es->ctrl &= ~(ch->index == ES_DAC1 ? CTRL_DAC1_EN : CTRL_DAC2_EN);
-} else {
-if (go == PCMTRIG_START) {
-es->ctrl |= CTRL_ADC_EN;
-es->sctrl &= ~SCTRL_R1LOOPSEL;
-es->sctrl |= SCTRL_R1INTEN | (b << 4);
-es_wr(es, ES1370_REG_ADC_SCOUNT, cnt, 4);
-/* start at beginning of buffer */
-es_wr(es, ES1370_REG_MEMPAGE, ES1370_REG_ADC_FRAMECNT >> 8, 4);
-es_wr(es, ES1370_REG_ADC_FRAMECNT & 0xff, (ch->bufsz >> 2) - 1, 4);
-} else es->ctrl &= ~CTRL_ADC_EN;
-}
-es_wr(es, ES1370_REG_SERIAL_CONTROL, es->sctrl, 4);
-es_wr(es, ES1370_REG_CONTROL, es->ctrl, 4);
-ES_UNLOCK(es);
-return 0;
+ struct es_chinfo *ch = data;
+ struct es_info *es = ch->parent;
+ uint32_t cnt, b = 0;
+
+ if (!PCMTRIG_COMMON(go))
+ return 0;
+
+ ES_LOCK(es);
+ cnt = (ch->blksz / sndbuf_getbps(ch->buffer)) - 1;
+ if (ch->fmt & AFMT_16BIT)
+ b |= 0x02;
+ if (ch->fmt & AFMT_STEREO)
+ b |= 0x01;
+ if (ch->dir == PCMDIR_PLAY) {
+ if (go == PCMTRIG_START) {
+ if (ch->index == ES_DAC1) {
+ es->ctrl |= CTRL_DAC1_EN;
+ es->sctrl &= ~(SCTRL_P1LOOPSEL |
+ SCTRL_P1PAUSE | SCTRL_P1SCTRLD);
+ if (es->polling == 0)
+ es->sctrl |= SCTRL_P1INTEN;
+ else
+ es->sctrl &= ~SCTRL_P1INTEN;
+ es->sctrl |= b;
+ es_wr(es, ES1370_REG_DAC1_SCOUNT, cnt, 4);
+ /* start at beginning of buffer */
+ es_wr(es, ES1370_REG_MEMPAGE,
+ ES1370_REG_DAC1_FRAMECNT >> 8, 4);
+ es_wr(es, ES1370_REG_DAC1_FRAMECNT & 0xff,
+ (ch->bufsz >> 2) - 1, 4);
+ } else {
+ es->ctrl |= CTRL_DAC2_EN;
+ es->sctrl &= ~(SCTRL_P2ENDINC | SCTRL_P2STINC |
+ SCTRL_P2LOOPSEL | SCTRL_P2PAUSE |
+ SCTRL_P2DACSEN);
+ if (es->polling == 0)
+ es->sctrl |= SCTRL_P2INTEN;
+ else
+ es->sctrl &= ~SCTRL_P2INTEN;
+ es->sctrl |= (b << 2) |
+ ((((b >> 1) & 1) + 1) << SCTRL_SH_P2ENDINC);
+ es_wr(es, ES1370_REG_DAC2_SCOUNT, cnt, 4);
+ /* start at beginning of buffer */
+ es_wr(es, ES1370_REG_MEMPAGE,
+ ES1370_REG_DAC2_FRAMECNT >> 8, 4);
+ es_wr(es, ES1370_REG_DAC2_FRAMECNT & 0xff,
+ (ch->bufsz >> 2) - 1, 4);
+ }
+ } else
+ es->ctrl &= ~((ch->index == ES_DAC1) ?
+ CTRL_DAC1_EN : CTRL_DAC2_EN);
+ } else {
+ if (go == PCMTRIG_START) {
+ es->ctrl |= CTRL_ADC_EN;
+ es->sctrl &= ~SCTRL_R1LOOPSEL;
+ if (es->polling == 0)
+ es->sctrl |= SCTRL_R1INTEN;
+ else
+ es->sctrl &= ~SCTRL_R1INTEN;
+ es->sctrl |= b << 4;
+ es_wr(es, ES1370_REG_ADC_SCOUNT, cnt, 4);
+ /* start at beginning of buffer */
+ es_wr(es, ES1370_REG_MEMPAGE,
+ ES1370_REG_ADC_FRAMECNT >> 8, 4);
+ es_wr(es, ES1370_REG_ADC_FRAMECNT & 0xff,
+ (ch->bufsz >> 2) - 1, 4);
+ } else
+ es->ctrl &= ~CTRL_ADC_EN;
+ }
+ es_wr(es, ES1370_REG_SERIAL_CONTROL, es->sctrl, 4);
+ es_wr(es, ES1370_REG_CONTROL, es->ctrl, 4);
+ if (go == PCMTRIG_START) {
+ if (es->polling != 0) {
+ ch->ptr = 0;
+ ch->prevptr = 0;
+ if (es_chan_active(es) == 0) {
+ es->poll_ticks = 1;
+ callout_reset(&es->poll_timer, 1,
+ es_poll_callback, es);
+ }
+ }
+ ch->active = 1;
+ } else {
+ ch->active = 0;
+ if (es->polling != 0) {
+ if (es_chan_active(es) == 0) {
+ callout_stop(&es->poll_timer);
+ es->poll_ticks = 1;
+ }
+ }
+ }
+ ES_UNLOCK(es);
+ return (0);
}
static int
eschan_getptr(kobj_t obj, void *data)
{
-struct es_chinfo *ch = data;
-struct es_info *es = ch->parent;
-u_int32_t reg, cnt;
-
-if (ch->dir == PCMDIR_PLAY) {
-if (ch->index == ES_DAC1)
-reg = ES1370_REG_DAC1_FRAMECNT;
-else
-reg = ES1370_REG_DAC2_FRAMECNT;
-} else
-reg = ES1370_REG_ADC_FRAMECNT;
-ES_LOCK(es);
-es_wr(es, ES1370_REG_MEMPAGE, reg >> 8, 4);
-cnt = es_rd(es, reg & 0x000000ff, 4) >> 16;
-ES_UNLOCK(es);
-/* cnt is longwords */
-return cnt << 2;
+ struct es_chinfo *ch = data;
+ struct es_info *es = ch->parent;
+ uint32_t reg, cnt;
+
+ ES_LOCK(es);
+ if (es->polling != 0)
+ cnt = ch->ptr;
+ else {
+ if (ch->dir == PCMDIR_PLAY) {
+ if (ch->index == ES_DAC1)
+ reg = ES1370_REG_DAC1_FRAMECNT;
+ else
+ reg = ES1370_REG_DAC2_FRAMECNT;
+ } else
+ reg = ES1370_REG_ADC_FRAMECNT;
+ es_wr(es, ES1370_REG_MEMPAGE, reg >> 8, 4);
+ cnt = es_rd(es, reg & 0x000000ff, 4) >> 16;
+ /* cnt is longwords */
+ cnt <<= 2;
+ }
+ ES_UNLOCK(es);
+
+ cnt &= ES_BLK_ALIGN;
+
+ return (cnt);
}
static struct pcmchan_caps *
eschan_getcaps(kobj_t obj, void *data)
{
-struct es_chinfo *ch = data;
+ struct es_chinfo *ch = data;
-return &ch->caps;
+ return (&ch->caps);
}
static kobj_method_t eschan1370_methods[] = {
-KOBJMETHOD(channel_init, eschan_init),
-KOBJMETHOD(channel_setformat, eschan_setformat),
-KOBJMETHOD(channel_setspeed, eschan1370_setspeed),
-KOBJMETHOD(channel_setblocksize, eschan_setblocksize),
-KOBJMETHOD(channel_trigger, eschan_trigger),
-KOBJMETHOD(channel_getptr, eschan_getptr),
-KOBJMETHOD(channel_getcaps, eschan_getcaps),
-{ 0, 0 }
+ KOBJMETHOD(channel_init, eschan_init),
+ KOBJMETHOD(channel_setformat, eschan_setformat),
+ KOBJMETHOD(channel_setspeed, eschan1370_setspeed),
+ KOBJMETHOD(channel_setblocksize, eschan_setblocksize),
+ KOBJMETHOD(channel_setfragments, eschan_setfragments),
+ KOBJMETHOD(channel_trigger, eschan_trigger),
+ KOBJMETHOD(channel_getptr, eschan_getptr),
+ KOBJMETHOD(channel_getcaps, eschan_getcaps),
+ { 0, 0 }
};
CHANNEL_DECLARE(eschan1370);
static kobj_method_t eschan1371_methods[] = {
-KOBJMETHOD(channel_init, eschan_init),
-KOBJMETHOD(channel_setformat, eschan_setformat),
-KOBJMETHOD(channel_setspeed, eschan1371_setspeed),
-KOBJMETHOD(channel_setblocksize, eschan_setblocksize),
-KOBJMETHOD(channel_trigger, eschan_trigger),
-KOBJMETHOD(channel_getptr, eschan_getptr),
-KOBJMETHOD(channel_getcaps, eschan_getcaps),
-{ 0, 0 }
+ KOBJMETHOD(channel_init, eschan_init),
+ KOBJMETHOD(channel_setformat, eschan_setformat),
+ KOBJMETHOD(channel_setspeed, eschan1371_setspeed),
+ KOBJMETHOD(channel_setblocksize, eschan_setblocksize),
+ KOBJMETHOD(channel_setfragments, eschan_setfragments),
+ KOBJMETHOD(channel_trigger, eschan_trigger),
+ KOBJMETHOD(channel_getptr, eschan_getptr),
+ KOBJMETHOD(channel_getcaps, eschan_getcaps),
+ { 0, 0 }
};
CHANNEL_DECLARE(eschan1371);
@@ -685,912 +889,1035 @@
static void
es_intr(void *p)
{
-struct es_info *es = p;
-uint32_t intsrc, sctrl;
+ struct es_info *es = p;
+ uint32_t intsrc, sctrl;
-ES_LOCK(es);
-intsrc = es_rd(es, ES1370_REG_STATUS, 4);
-if ((intsrc & STAT_INTR) == 0) {
-ES_UNLOCK(es);
-return;
-}
-
-sctrl = es->sctrl;
-if (intsrc & STAT_ADC) sctrl &= ~SCTRL_R1INTEN;
-if (intsrc & STAT_DAC1) sctrl &= ~SCTRL_P1INTEN;
-if (intsrc & STAT_DAC2) sctrl &= ~SCTRL_P2INTEN;
-
-es_wr(es, ES1370_REG_SERIAL_CONTROL, sctrl, 4);
-es_wr(es, ES1370_REG_SERIAL_CONTROL, es->sctrl, 4);
-ES_UNLOCK(es);
-
-if (intsrc & STAT_ADC) chn_intr(es->ch[ES_ADC].channel);
-if (intsrc & STAT_DAC1) chn_intr(es->ch[ES_DAC1].channel);
-if (intsrc & STAT_DAC2) chn_intr(es->ch[ES_DAC2].channel);
+ ES_LOCK(es);
+ if (es->polling != 0) {
+ ES_UNLOCK(es);
+ return;
+ }
+ intsrc = es_rd(es, ES1370_REG_STATUS, 4);
+ if ((intsrc & STAT_INTR) == 0) {
+ ES_UNLOCK(es);
+ return;
+ }
+
+ sctrl = es->sctrl;
+ if (intsrc & STAT_ADC)
+ sctrl &= ~SCTRL_R1INTEN;
+ if (intsrc & STAT_DAC1)
+ sctrl &= ~SCTRL_P1INTEN;
+ if (intsrc & STAT_DAC2)
+ sctrl &= ~SCTRL_P2INTEN;
+
+ es_wr(es, ES1370_REG_SERIAL_CONTROL, sctrl, 4);
+ es_wr(es, ES1370_REG_SERIAL_CONTROL, es->sctrl, 4);
+ ES_UNLOCK(es);
+
+ if (intsrc & STAT_ADC)
+ chn_intr(es->ch[ES_ADC].channel);
+ if (intsrc & STAT_DAC1)
+ chn_intr(es->ch[ES_DAC1].channel);
+ if (intsrc & STAT_DAC2)
+ chn_intr(es->ch[ES_DAC2].channel);
}
/* ES1370 specific */
static int
es1370_init(struct es_info *es)
{
-uint32_t fixed_rate;
-int r, single_pcm;
+ uint32_t fixed_rate;
+ int r, single_pcm;
-/* ES1370 default to fixed rate operation */
-if (resource_int_value(device_get_name(es->dev),
-device_get_unit(es->dev), "fixed_rate", &r) == 0) {
-fixed_rate = r;
-if (fixed_rate) {
-if (fixed_rate < es_caps.minspeed)
-fixed_rate = es_caps.minspeed;
-if (fixed_rate > es_caps.maxspeed)
-fixed_rate = es_caps.maxspeed;
-}
-} else
-fixed_rate = es_caps.maxspeed;
-
-if (resource_int_value(device_get_name(es->dev),
-device_get_unit(es->dev), "single_pcm_mixer", &r) == 0)
-single_pcm = (r) ? 1 : 0;
-else
-single_pcm = 1;
-
-ES_LOCK(es);
-if (ES_NUMPLAY(es->escfg) == 1)
-single_pcm = 1;
-/* This is ES1370 */
-es->escfg = ES_SET_IS_ES1370(es->escfg, 1);
-if (fixed_rate) {
-es->escfg = ES_SET_FIXED_RATE(es->escfg, fixed_rate);
-} else {
-es->escfg = ES_SET_FIXED_RATE(es->escfg, 0);
-fixed_rate = DSP_DEFAULT_SPEED;
-}
-if (single_pcm) {
-es->escfg = ES_SET_SINGLE_PCM_MIX(es->escfg, 1);
-} else {
-es->escfg = ES_SET_SINGLE_PCM_MIX(es->escfg, 0);
-}
-es->ctrl = CTRL_CDC_EN | CTRL_JYSTK_EN | CTRL_SERR_DIS |
-(DAC2_SRTODIV(fixed_rate) << CTRL_SH_PCLKDIV);
-es->ctrl |= 3 << CTRL_SH_WTSRSEL;
-es_wr(es, ES1370_REG_CONTROL, es->ctrl, 4);
-
-es->sctrl = 0;
-es_wr(es, ES1370_REG_SERIAL_CONTROL, es->sctrl, 4);
-
-es1370_wrcodec(es, CODEC_RES_PD, 3);/* No RST, PD */
-es1370_wrcodec(es, CODEC_CSEL, 0); /* CODEC ADC and CODEC DAC use
-* {LR,B}CLK2 and run off the LRCLK2
-* PLL; program DAC_SYNC=0! */
-es1370_wrcodec(es, CODEC_ADSEL, 0);/* Recording source is mixer */
-es1370_wrcodec(es, CODEC_MGAIN, 0);/* MIC amp is 0db */
-ES_UNLOCK(es);
+ /* ES1370 default to fixed rate operation */
+ if (resource_int_value(device_get_name(es->dev),
+ device_get_unit(es->dev), "fixed_rate", &r) == 0) {
+ fixed_rate = r;
+ if (fixed_rate) {
+ if (fixed_rate < es_caps.minspeed)
+ fixed_rate = es_caps.minspeed;
+ if (fixed_rate > es_caps.maxspeed)
+ fixed_rate = es_caps.maxspeed;
+ }
+ } else
+ fixed_rate = es_caps.maxspeed;
+
+ if (resource_int_value(device_get_name(es->dev),
+ device_get_unit(es->dev), "single_pcm_mixer", &r) == 0)
+ single_pcm = (r != 0) ? 1 : 0;
+ else
+ single_pcm = 1;
+
+ ES_LOCK(es);
+ if (ES_NUMPLAY(es->escfg) == 1)
+ single_pcm = 1;
+ /* This is ES1370 */
+ es->escfg = ES_SET_IS_ES1370(es->escfg, 1);
+ if (fixed_rate)
+ es->escfg = ES_SET_FIXED_RATE(es->escfg, fixed_rate);
+ else {
+ es->escfg = ES_SET_FIXED_RATE(es->escfg, 0);
+ fixed_rate = DSP_DEFAULT_SPEED;
+ }
+ if (single_pcm)
+ es->escfg = ES_SET_SINGLE_PCM_MIX(es->escfg, 1);
+ else
+ es->escfg = ES_SET_SINGLE_PCM_MIX(es->escfg, 0);
+ es->ctrl = CTRL_CDC_EN | CTRL_JYSTK_EN | CTRL_SERR_DIS |
+ (DAC2_SRTODIV(fixed_rate) << CTRL_SH_PCLKDIV);
+ es->ctrl |= 3 << CTRL_SH_WTSRSEL;
+ es_wr(es, ES1370_REG_CONTROL, es->ctrl, 4);
+
+ es->sctrl = 0;
+ es_wr(es, ES1370_REG_SERIAL_CONTROL, es->sctrl, 4);
+
+ /* No RST, PD */
+ es1370_wrcodec(es, CODEC_RES_PD, 3);
+ /*
+ * CODEC ADC and CODEC DAC use {LR,B}CLK2 and run off the LRCLK2 PLL;
+ * program DAC_SYNC=0!
+ */
+ es1370_wrcodec(es, CODEC_CSEL, 0);
+ /* Recording source is mixer */
+ es1370_wrcodec(es, CODEC_ADSEL, 0);
+ /* MIC amp is 0db */
+ es1370_wrcodec(es, CODEC_MGAIN, 0);
+ ES_UNLOCK(es);
-return 0;
+ return (0);
}
/* ES1371 specific */
int
es1371_init(struct es_info *es)
{
-uint32_t cssr, devid, revid, subdev;
-int idx;
+ uint32_t cssr, devid, revid, subdev;
+ int idx;
-ES_LOCK(es);
-/* This is NOT ES1370 */
-es->escfg = ES_SET_IS_ES1370(es->escfg, 0);
-es->num = 0;
-es->sctrl = 0;
-cssr = 0;
-devid = pci_get_devid(es->dev);
-revid = pci_get_revid(es->dev);
-subdev = (pci_get_subdevice(es->dev) << 16) | pci_get_subvendor(es->dev);
-/*
-* Joyport blacklist. Either we're facing with broken hardware
-* or because this hardware need special (unknown) initialization
-* procedures.
-*/
-switch (subdev) {
-case 0x20001274: /* old Ensoniq */
-es->ctrl = 0;
-break;
-default:
-es->ctrl = CTRL_JYSTK_EN;
-break;
-}
-if (devid == CT4730_PCI_ID) {
-/* XXX amplifier hack? */
-es->ctrl |= (1 << 16);
-}
-/* initialize the chips */
-es_wr(es, ES1370_REG_CONTROL, es->ctrl, 4);
-es_wr(es, ES1370_REG_SERIAL_CONTROL, es->sctrl, 4);
-es_wr(es, ES1371_REG_LEGACY, 0, 4);
-if ((devid == ES1371_PCI_ID && revid == ES1371REV_ES1373_8) ||
-(devid == ES1371_PCI_ID && revid == ES1371REV_CT5880_A) ||
-(devid == CT5880_PCI_ID && revid == CT5880REV_CT5880_C) ||
-(devid == CT5880_PCI_ID && revid == CT5880REV_CT5880_D) ||
-(devid == CT5880_PCI_ID && revid == CT5880REV_CT5880_E)) {
-cssr = 1 << 29;
-es_wr(es, ES1370_REG_STATUS, cssr, 4);
-DELAY(20000);
-}
-/* AC'97 warm reset to start the bitclk */
-es_wr(es, ES1370_REG_CONTROL, es->ctrl, 4);
-es_wr(es, ES1371_REG_LEGACY, ES1371_SYNC_RES, 4);
-DELAY(2000);
-es_wr(es, ES1370_REG_CONTROL, es->sctrl, 4);
-es1371_wait_src_ready(es);
-/* Init the sample rate converter */
-es_wr(es, ES1371_REG_SMPRATE, ES1371_DIS_SRC, 4);
-for (idx = 0; idx < 0x80; idx++)
-es1371_src_write(es, idx, 0);
-es1371_src_write(es, ES_SMPREG_DAC1 + ES_SMPREG_TRUNC_N, 16 << 4);
-es1371_src_write(es, ES_SMPREG_DAC1 + ES_SMPREG_INT_REGS, 16 << 10);
-es1371_src_write(es, ES_SMPREG_DAC2 + ES_SMPREG_TRUNC_N, 16 << 4);
-es1371_src_write(es, ES_SMPREG_DAC2 + ES_SMPREG_INT_REGS, 16 << 10);
-es1371_src_write(es, ES_SMPREG_VOL_ADC, 1 << 12);
-es1371_src_write(es, ES_SMPREG_VOL_ADC + 1, 1 << 12);
-es1371_src_write(es, ES_SMPREG_VOL_DAC1, 1 << 12);
-es1371_src_write(es, ES_SMPREG_VOL_DAC1 + 1, 1 << 12);
-es1371_src_write(es, ES_SMPREG_VOL_DAC2, 1 << 12);
-es1371_src_write(es, ES_SMPREG_VOL_DAC2 + 1, 1 << 12);
-es1371_adc_rate(es, 22050, ES_ADC);
-es1371_dac_rate(es, 22050, ES_DAC1);
-es1371_dac_rate(es, 22050, ES_DAC2);
-/* WARNING:
-* enabling the sample rate converter without properly programming
-* its parameters causes the chip to lock up (the SRC busy bit will
-* be stuck high, and I've found no way to rectify this other than
-* power cycle)
-*/
-es1371_wait_src_ready(es);
-es_wr(es, ES1371_REG_SMPRATE, 0, 4);
-/* try to reset codec directly */
-es_wr(es, ES1371_REG_CODEC, 0, 4);
-es_wr(es, ES1370_REG_STATUS, cssr, 4);
-ES_UNLOCK(es);
+ ES_LOCK(es);
+ /* This is NOT ES1370 */
+ es->escfg = ES_SET_IS_ES1370(es->escfg, 0);
+ es->num = 0;
+ es->sctrl = 0;
+ cssr = 0;
+ devid = pci_get_devid(es->dev);
+ revid = pci_get_revid(es->dev);
+ subdev = (pci_get_subdevice(es->dev) << 16) |
+ pci_get_subvendor(es->dev);
+ /*
+ * Joyport blacklist. Either we're facing with broken hardware
+ * or because this hardware need special (unknown) initialization
+ * procedures.
+ */
+ switch (subdev) {
+ case 0x20001274: /* old Ensoniq */
+ es->ctrl = 0;
+ break;
+ default:
+ es->ctrl = CTRL_JYSTK_EN;
+ break;
+ }
+ if (devid == CT4730_PCI_ID) {
+ /* XXX amplifier hack? */
+ es->ctrl |= (1 << 16);
+ }
+ /* initialize the chips */
+ es_wr(es, ES1370_REG_CONTROL, es->ctrl, 4);
+ es_wr(es, ES1370_REG_SERIAL_CONTROL, es->sctrl, 4);
+ es_wr(es, ES1371_REG_LEGACY, 0, 4);
+ if ((devid == ES1371_PCI_ID && revid == ES1371REV_ES1373_8) ||
+ (devid == ES1371_PCI_ID && revid == ES1371REV_CT5880_A) ||
+ (devid == CT5880_PCI_ID && revid == CT5880REV_CT5880_C) ||
+ (devid == CT5880_PCI_ID && revid == CT5880REV_CT5880_D) ||
+ (devid == CT5880_PCI_ID && revid == CT5880REV_CT5880_E)) {
+ cssr = 1 << 29;
+ es_wr(es, ES1370_REG_STATUS, cssr, 4);
+ DELAY(20000);
+ }
+ /* AC'97 warm reset to start the bitclk */
+ es_wr(es, ES1370_REG_CONTROL, es->ctrl, 4);
+ es_wr(es, ES1371_REG_LEGACY, ES1371_SYNC_RES, 4);
+ DELAY(2000);
+ es_wr(es, ES1370_REG_CONTROL, es->sctrl, 4);
+ es1371_wait_src_ready(es);
+ /* Init the sample rate converter */
+ es_wr(es, ES1371_REG_SMPRATE, ES1371_DIS_SRC, 4);
+ for (idx = 0; idx < 0x80; idx++)
+ es1371_src_write(es, idx, 0);
+ es1371_src_write(es, ES_SMPREG_DAC1 + ES_SMPREG_TRUNC_N, 16 << 4);
+ es1371_src_write(es, ES_SMPREG_DAC1 + ES_SMPREG_INT_REGS, 16 << 10);
+ es1371_src_write(es, ES_SMPREG_DAC2 + ES_SMPREG_TRUNC_N, 16 << 4);
+ es1371_src_write(es, ES_SMPREG_DAC2 + ES_SMPREG_INT_REGS, 16 << 10);
+ es1371_src_write(es, ES_SMPREG_VOL_ADC, 1 << 12);
+ es1371_src_write(es, ES_SMPREG_VOL_ADC + 1, 1 << 12);
+ es1371_src_write(es, ES_SMPREG_VOL_DAC1, 1 << 12);
+ es1371_src_write(es, ES_SMPREG_VOL_DAC1 + 1, 1 << 12);
+ es1371_src_write(es, ES_SMPREG_VOL_DAC2, 1 << 12);
+ es1371_src_write(es, ES_SMPREG_VOL_DAC2 + 1, 1 << 12);
+ es1371_adc_rate(es, 22050, ES_ADC);
+ es1371_dac_rate(es, 22050, ES_DAC1);
+ es1371_dac_rate(es, 22050, ES_DAC2);
+ /*
+ * WARNING:
+ * enabling the sample rate converter without properly programming
+ * its parameters causes the chip to lock up (the SRC busy bit will
+ * be stuck high, and I've found no way to rectify this other than
+ * power cycle)
+ */
+ es1371_wait_src_ready(es);
+ es_wr(es, ES1371_REG_SMPRATE, 0, 4);
+ /* try to reset codec directly */
+ es_wr(es, ES1371_REG_CODEC, 0, 4);
+ es_wr(es, ES1370_REG_STATUS, cssr, 4);
+ ES_UNLOCK(es);
-return (0);
+ return (0);
}
/* -------------------------------------------------------------------- */
static int
-es1371_wrcd(kobj_t obj, void *s, int addr, u_int32_t data)
+es1371_wrcd(kobj_t obj, void *s, int addr, uint32_t data)
{
-uint32_t t, x, orig;
-struct es_info *es = (struct es_info*)s;
+ uint32_t t, x, orig;
+ struct es_info *es = (struct es_info*)s;
-for (t = 0; t < 0x1000; t++)
-if (!es_rd(es, ES1371_REG_CODEC & CODEC_WIP, 4))
-break;
-/* save the current state for later */
-x = orig = es_rd(es, ES1371_REG_SMPRATE, 4);
-/* enable SRC state data in SRC mux */
-es_wr(es, ES1371_REG_SMPRATE,
-(x &
-(ES1371_DIS_SRC | ES1371_DIS_P1 | ES1371_DIS_P2 | ES1371_DIS_R1)) |
-0x00010000, 4);
-/* busy wait */
-for (t = 0; t < 0x1000; t++)
-if ((es_rd(es, ES1371_REG_SMPRATE, 4) & 0x00870000) == 0x00000000)
-break;
-/* wait for a SAFE time to write addr/data and then do it, dammit */
-for (t = 0; t < 0x1000; t++)
-if ((es_rd(es, ES1371_REG_SMPRATE, 4) & 0x00870000) == 0x00010000)
-break;
-
-es_wr(es, ES1371_REG_CODEC,
-((addr << CODEC_POADD_SHIFT) & CODEC_POADD_MASK) |
-((data << CODEC_PODAT_SHIFT) & CODEC_PODAT_MASK), 4);
-/* restore SRC reg */
-es1371_wait_src_ready(s);
-es_wr(es, ES1371_REG_SMPRATE, orig, 4);
+ for (t = 0; t < 0x1000; t++) {
+ if (!es_rd(es, ES1371_REG_CODEC & CODEC_WIP, 4))
+ break;
+ }
+ /* save the current state for later */
+ x = orig = es_rd(es, ES1371_REG_SMPRATE, 4);
+ /* enable SRC state data in SRC mux */
+ es_wr(es, ES1371_REG_SMPRATE, (x & (ES1371_DIS_SRC | ES1371_DIS_P1 |
+ ES1371_DIS_P2 | ES1371_DIS_R1)) | 0x00010000, 4);
+ /* busy wait */
+ for (t = 0; t < 0x1000; t++) {
+ if ((es_rd(es, ES1371_REG_SMPRATE, 4) & 0x00870000) ==
+ 0x00000000)
+ break;
+ }
+ /* wait for a SAFE time to write addr/data and then do it, dammit */
+ for (t = 0; t < 0x1000; t++) {
+ if ((es_rd(es, ES1371_REG_SMPRATE, 4) & 0x00870000) ==
+ 0x00010000)
+ break;
+ }
+
+ es_wr(es, ES1371_REG_CODEC, ((addr << CODEC_POADD_SHIFT) &
+ CODEC_POADD_MASK) | ((data << CODEC_PODAT_SHIFT) &
+ CODEC_PODAT_MASK), 4);
+ /* restore SRC reg */
+ es1371_wait_src_ready(s);
+ es_wr(es, ES1371_REG_SMPRATE, orig, 4);
-return 0;
+ return (0);
}
static int
es1371_rdcd(kobj_t obj, void *s, int addr)
{
-uint32_t t, x, orig;
-struct es_info *es = (struct es_info *)s;
+ uint32_t t, x, orig;
+ struct es_info *es = (struct es_info *)s;
-for (t = 0; t < 0x1000; t++)
-if (!(x = es_rd(es, ES1371_REG_CODEC, 4) & CODEC_WIP))
-break;
-
-/* save the current state for later */
-x = orig = es_rd(es, ES1371_REG_SMPRATE, 4);
-/* enable SRC state data in SRC mux */
-es_wr(es, ES1371_REG_SMPRATE,
-(x &
-(ES1371_DIS_SRC | ES1371_DIS_P1 | ES1371_DIS_P2 | ES1371_DIS_R1)) |
-0x00010000, 4);
-/* busy wait */
-for (t = 0; t < 0x1000; t++)
-if ((x = es_rd(es, ES1371_REG_SMPRATE, 4) & 0x00870000) == 0x00000000)
-break;
-/* wait for a SAFE time to write addr/data and then do it, dammit */
-for (t = 0; t < 0x1000; t++)
-if ((x = es_rd(es, ES1371_REG_SMPRATE, 4) & 0x00870000) == 0x00010000)
-break;
-
-es_wr(es, ES1371_REG_CODEC,
-((addr << CODEC_POADD_SHIFT) & CODEC_POADD_MASK) |
-CODEC_PORD, 4);
-
-/* restore SRC reg */
-es1371_wait_src_ready(s);
-es_wr(es, ES1371_REG_SMPRATE, orig, 4);
-
-/* now wait for the stinkin' data (RDY) */
-for (t = 0; t < 0x1000; t++)
-if ((x = es_rd(es, ES1371_REG_CODEC, 4)) & CODEC_RDY)
-break;
+ for (t = 0; t < 0x1000; t++) {
+ if (!(x = es_rd(es, ES1371_REG_CODEC, 4) & CODEC_WIP))
+ break;
+ }
+
+ /* save the current state for later */
+ x = orig = es_rd(es, ES1371_REG_SMPRATE, 4);
+ /* enable SRC state data in SRC mux */
+ es_wr(es, ES1371_REG_SMPRATE, (x & (ES1371_DIS_SRC | ES1371_DIS_P1 |
+ ES1371_DIS_P2 | ES1371_DIS_R1)) | 0x00010000, 4);
+ /* busy wait */
+ for (t = 0; t < 0x1000; t++) {
+ if ((x = es_rd(es, ES1371_REG_SMPRATE, 4) & 0x00870000) ==
+ 0x00000000)
+ break;
+ }
+ /* wait for a SAFE time to write addr/data and then do it, dammit */
+ for (t = 0; t < 0x1000; t++) {
+ if ((x = es_rd(es, ES1371_REG_SMPRATE, 4) & 0x00870000) ==
+ 0x00010000)
+ break;
+ }
+
+ es_wr(es, ES1371_REG_CODEC, ((addr << CODEC_POADD_SHIFT) &
+ CODEC_POADD_MASK) | CODEC_PORD, 4);
+
+ /* restore SRC reg */
+ es1371_wait_src_ready(s);
+ es_wr(es, ES1371_REG_SMPRATE, orig, 4);
+
+ /* now wait for the stinkin' data (RDY) */
+ for (t = 0; t < 0x1000; t++) {
+ if ((x = es_rd(es, ES1371_REG_CODEC, 4)) & CODEC_RDY)
+ break;
+ }
-return ((x & CODEC_PIDAT_MASK) >> CODEC_PIDAT_SHIFT);
+ return ((x & CODEC_PIDAT_MASK) >> CODEC_PIDAT_SHIFT);
}
static kobj_method_t es1371_ac97_methods[] = {
-KOBJMETHOD(ac97_read, es1371_rdcd),
-KOBJMETHOD(ac97_write, es1371_wrcd),
-{ 0, 0 }
+ KOBJMETHOD(ac97_read, es1371_rdcd),
+ KOBJMETHOD(ac97_write, es1371_wrcd),
+ { 0, 0 }
};
AC97_DECLARE(es1371_ac97);
/* -------------------------------------------------------------------- */
-static u_int
-es1371_src_read(struct es_info *es, u_short reg)
+static unsigned int
+es1371_src_read(struct es_info *es, unsigned short reg)
{
-uint32_t r;
+ uint32_t r;
-r = es1371_wait_src_ready(es) &
-(ES1371_DIS_SRC | ES1371_DIS_P1 | ES1371_DIS_P2 | ES1371_DIS_R1);
-r |= ES1371_SRC_RAM_ADDRO(reg);
-es_wr(es, ES1371_REG_SMPRATE, r, 4);
-return ES1371_SRC_RAM_DATAI(es1371_wait_src_ready(es));
+ r = es1371_wait_src_ready(es) & (ES1371_DIS_SRC | ES1371_DIS_P1 |
+ ES1371_DIS_P2 | ES1371_DIS_R1);
+ r |= ES1371_SRC_RAM_ADDRO(reg);
+ es_wr(es, ES1371_REG_SMPRATE, r, 4);
+ return (ES1371_SRC_RAM_DATAI(es1371_wait_src_ready(es)));
}
static void
-es1371_src_write(struct es_info *es, u_short reg, u_short data)
+es1371_src_write(struct es_info *es, unsigned short reg, unsigned short data)
{
-uint32_t r;
+ uint32_t r;
-r = es1371_wait_src_ready(es) &
-(ES1371_DIS_SRC | ES1371_DIS_P1 | ES1371_DIS_P2 | ES1371_DIS_R1);
-r |= ES1371_SRC_RAM_ADDRO(reg) | ES1371_SRC_RAM_DATAO(data);
-es_wr(es, ES1371_REG_SMPRATE, r | ES1371_SRC_RAM_WE, 4);
-}
-
-static u_int
-es1371_adc_rate(struct es_info *es, u_int rate, int set)
-{
-u_int n, truncm, freq, result;
-
-ES_LOCK_ASSERT(es);
-
-if (rate > 48000) rate = 48000;
-if (rate < 4000) rate = 4000;
-n = rate / 3000;
-if ((1 << n) & ((1 << 15) | (1 << 13) | (1 << 11) | (1 << 9)))
-n--;
-truncm = (21 * n - 1) | 1;
-freq = ((48000UL << 15) / rate) * n;
-result = (48000UL << 15) / (freq / n);
-if (set) {
-if (rate >= 24000) {
-if (truncm > 239) truncm = 239;
-es1371_src_write(es, ES_SMPREG_ADC + ES_SMPREG_TRUNC_N,
-(((239 - truncm) >> 1) << 9) | (n << 4));
-} else {
-if (truncm > 119) truncm = 119;
-es1371_src_write(es, ES_SMPREG_ADC + ES_SMPREG_TRUNC_N,
-0x8000 | (((119 - truncm) >> 1) << 9) | (n << 4));
-}
-es1371_src_write(es, ES_SMPREG_ADC + ES_SMPREG_INT_REGS,
-(es1371_src_read(es, ES_SMPREG_ADC + ES_SMPREG_INT_REGS) &
-0x00ff) | ((freq >> 5) & 0xfc00));
-es1371_src_write(es, ES_SMPREG_ADC + ES_SMPREG_VFREQ_FRAC, freq & 0x7fff);
-es1371_src_write(es, ES_SMPREG_VOL_ADC, n << 8);
-es1371_src_write(es, ES_SMPREG_VOL_ADC + 1, n << 8);
-}
-return result;
-}
-
-static u_int
-es1371_dac_rate(struct es_info *es, u_int rate, int set)
-{
-u_int freq, r, result, dac, dis;
-
-ES_LOCK_ASSERT(es);
-
-if (rate > 48000) rate = 48000;
-if (rate < 4000) rate = 4000;
-freq = ((rate << 15) + 1500) / 3000;
-result = (freq * 3000) >> 15;
-
-dac = (set == ES_DAC1) ? ES_SMPREG_DAC1 : ES_SMPREG_DAC2;
-dis = (set == ES_DAC1) ? ES1371_DIS_P2 : ES1371_DIS_P1;
-r = (es1371_wait_src_ready(es) & (ES1371_DIS_SRC | ES1371_DIS_P1 | ES1371_DIS_P2 | ES1371_DIS_R1));
-es_wr(es, ES1371_REG_SMPRATE, r, 4);
-es1371_src_write(es, dac + ES_SMPREG_INT_REGS,
-(es1371_src_read(es, dac + ES_SMPREG_INT_REGS) & 0x00ff) | ((freq >> 5) & 0xfc00));
-es1371_src_write(es, dac + ES_SMPREG_VFREQ_FRAC, freq & 0x7fff);
-r = (es1371_wait_src_ready(es) & (ES1371_DIS_SRC | dis | ES1371_DIS_R1));
-es_wr(es, ES1371_REG_SMPRATE, r, 4);
-return result;
+ r = es1371_wait_src_ready(es) & (ES1371_DIS_SRC | ES1371_DIS_P1 |
+ ES1371_DIS_P2 | ES1371_DIS_R1);
+ r |= ES1371_SRC_RAM_ADDRO(reg) | ES1371_SRC_RAM_DATAO(data);
+ es_wr(es, ES1371_REG_SMPRATE, r | ES1371_SRC_RAM_WE, 4);
+}
+
+static unsigned int
+es1371_adc_rate(struct es_info *es, unsigned int rate, int set)
+{
+ unsigned int n, truncm, freq, result;
+
+ ES_LOCK_ASSERT(es);
+
+ if (rate > 48000)
+ rate = 48000;
+ if (rate < 4000)
+ rate = 4000;
+ n = rate / 3000;
+ if ((1 << n) & ((1 << 15) | (1 << 13) | (1 << 11) | (1 << 9)))
+ n--;
+ truncm = (21 * n - 1) | 1;
+ freq = ((48000UL << 15) / rate) * n;
+ result = (48000UL << 15) / (freq / n);
+ if (set) {
+ if (rate >= 24000) {
+ if (truncm > 239)
+ truncm = 239;
+ es1371_src_write(es, ES_SMPREG_ADC + ES_SMPREG_TRUNC_N,
+ (((239 - truncm) >> 1) << 9) | (n << 4));
+ } else {
+ if (truncm > 119)
+ truncm = 119;
+ es1371_src_write(es, ES_SMPREG_ADC + ES_SMPREG_TRUNC_N,
+ 0x8000 | (((119 - truncm) >> 1) << 9) | (n << 4));
+ }
+ es1371_src_write(es, ES_SMPREG_ADC + ES_SMPREG_INT_REGS,
+ (es1371_src_read(es, ES_SMPREG_ADC + ES_SMPREG_INT_REGS) &
+ 0x00ff) | ((freq >> 5) & 0xfc00));
+ es1371_src_write(es, ES_SMPREG_ADC + ES_SMPREG_VFREQ_FRAC,
+ freq & 0x7fff);
+ es1371_src_write(es, ES_SMPREG_VOL_ADC, n << 8);
+ es1371_src_write(es, ES_SMPREG_VOL_ADC + 1, n << 8);
+ }
+ return (result);
+}
+
+static unsigned int
+es1371_dac_rate(struct es_info *es, unsigned int rate, int set)
+{
+ unsigned int freq, r, result, dac, dis;
+
+ ES_LOCK_ASSERT(es);
+
+ if (rate > 48000)
+ rate = 48000;
+ if (rate < 4000)
+ rate = 4000;
+ freq = ((rate << 15) + 1500) / 3000;
+ result = (freq * 3000) >> 15;
+
+ dac = (set == ES_DAC1) ? ES_SMPREG_DAC1 : ES_SMPREG_DAC2;
+ dis = (set == ES_DAC1) ? ES1371_DIS_P2 : ES1371_DIS_P1;
+ r = (es1371_wait_src_ready(es) & (ES1371_DIS_SRC | ES1371_DIS_P1 |
+ ES1371_DIS_P2 | ES1371_DIS_R1));
+ es_wr(es, ES1371_REG_SMPRATE, r, 4);
+ es1371_src_write(es, dac + ES_SMPREG_INT_REGS,
+ (es1371_src_read(es, dac + ES_SMPREG_INT_REGS) & 0x00ff) |
+ ((freq >> 5) & 0xfc00));
+ es1371_src_write(es, dac + ES_SMPREG_VFREQ_FRAC, freq & 0x7fff);
+ r = (es1371_wait_src_ready(es) &
+ (ES1371_DIS_SRC | dis | ES1371_DIS_R1));
+ es_wr(es, ES1371_REG_SMPRATE, r, 4);
+ return (result);
}
static uint32_t
es1371_wait_src_ready(struct es_info *es)
{
-uint32_t t, r;
+ uint32_t t, r;
-for (t = 0; t < 0x1000; t++) {
-if (!((r = es_rd(es, ES1371_REG_SMPRATE, 4)) & ES1371_SRC_RAM_BUSY))
-return r;
-DELAY(1);
-}
-device_printf(es->dev, "%s: timed out 0x%x [0x%x]n", __func__,
-ES1371_REG_SMPRATE, r);
-return 0;
+ for (t = 0; t < 0x1000; t++) {
+ if (!((r = es_rd(es, ES1371_REG_SMPRATE, 4)) &
+ ES1371_SRC_RAM_BUSY))
+ return (r);
+ DELAY(1);
+ }
+ device_printf(es->dev, "%s: timed out 0x%x [0x%x]\n", __func__,
+ ES1371_REG_SMPRATE, r);
+ return (0);
}
/* -------------------------------------------------------------------- */
/*
-* Probe and attach the card
-*/
+ * Probe and attach the card
+ */
static int
es_pci_probe(device_t dev)
{
-switch(pci_get_devid(dev)) {
-case ES1370_PCI_ID:
-device_set_desc(dev, "AudioPCI ES1370");
-return BUS_PROBE_DEFAULT;
-
-case ES1371_PCI_ID:
-switch(pci_get_revid(dev)) {
-case ES1371REV_ES1371_A:
-device_set_desc(dev, "AudioPCI ES1371-A");
-return BUS_PROBE_DEFAULT;
-
-case ES1371REV_ES1371_B:
-device_set_desc(dev, "AudioPCI ES1371-B");
-return BUS_PROBE_DEFAULT;
-
-case ES1371REV_ES1373_A:
-device_set_desc(dev, "AudioPCI ES1373-A");
-return BUS_PROBE_DEFAULT;
-
-case ES1371REV_ES1373_B:
-device_set_desc(dev, "AudioPCI ES1373-B");
-return BUS_PROBE_DEFAULT;
-
-case ES1371REV_ES1373_8:
-device_set_desc(dev, "AudioPCI ES1373-8");
-return BUS_PROBE_DEFAULT;
-
-case ES1371REV_CT5880_A:
-device_set_desc(dev, "Creative CT5880-A");
-return BUS_PROBE_DEFAULT;
-
-default:
-device_set_desc(dev, "AudioPCI ES1371-?");
-device_printf(dev, "unknown revision %d -- please report to cg at freebsd.orgn", pci_get_revid(dev));
-return BUS_PROBE_DEFAULT;
-}
-
-case ES1371_PCI_ID2:
-device_set_desc(dev, "Strange AudioPCI ES1371-? (vid=3274)");
-device_printf(dev, "unknown revision %d -- please report to cg at freebsd.orgn", pci_get_revid(dev));
-return BUS_PROBE_DEFAULT;
-
-case CT4730_PCI_ID:
-switch(pci_get_revid(dev)) {
-case CT4730REV_CT4730_A:
-device_set_desc(dev, "Creative SB AudioPCI CT4730/EV1938");
-return BUS_PROBE_DEFAULT;
-default:
-device_set_desc(dev, "Creative SB AudioPCI CT4730-?");
-device_printf(dev, "unknown revision %d -- please report to cg at freebsd.orgn", pci_get_revid(dev));
-return BUS_PROBE_DEFAULT;
-}
-
-case CT5880_PCI_ID:
-switch(pci_get_revid(dev)) {
-case CT5880REV_CT5880_C:
-device_set_desc(dev, "Creative CT5880-C");
-return BUS_PROBE_DEFAULT;
-
-case CT5880REV_CT5880_D:
-device_set_desc(dev, "Creative CT5880-D");
-return BUS_PROBE_DEFAULT;
-
-case CT5880REV_CT5880_E:
-device_set_desc(dev, "Creative CT5880-E");
-return BUS_PROBE_DEFAULT;
-
-default:
-device_set_desc(dev, "Creative CT5880-?");
-device_printf(dev, "unknown revision %d -- please report to cg at freebsd.orgn", pci_get_revid(dev));
-return BUS_PROBE_DEFAULT;
-}
-
-default:
-return ENXIO;
-}
+ switch(pci_get_devid(dev)) {
+ case ES1370_PCI_ID:
+ device_set_desc(dev, "AudioPCI ES1370");
+ return (BUS_PROBE_DEFAULT);
+ case ES1371_PCI_ID:
+ switch(pci_get_revid(dev)) {
+ case ES1371REV_ES1371_A:
+ device_set_desc(dev, "AudioPCI ES1371-A");
+ return (BUS_PROBE_DEFAULT);
+ case ES1371REV_ES1371_B:
+ device_set_desc(dev, "AudioPCI ES1371-B");
+ return (BUS_PROBE_DEFAULT);
+ case ES1371REV_ES1373_A:
+ device_set_desc(dev, "AudioPCI ES1373-A");
+ return (BUS_PROBE_DEFAULT);
+ case ES1371REV_ES1373_B:
+ device_set_desc(dev, "AudioPCI ES1373-B");
+ return (BUS_PROBE_DEFAULT);
+ case ES1371REV_ES1373_8:
+ device_set_desc(dev, "AudioPCI ES1373-8");
+ return (BUS_PROBE_DEFAULT);
+ case ES1371REV_CT5880_A:
+ device_set_desc(dev, "Creative CT5880-A");
+ return (BUS_PROBE_DEFAULT);
+ default:
+ device_set_desc(dev, "AudioPCI ES1371-?");
+ device_printf(dev,
+ "unknown revision %d -- please report to "
+ "freebsd-multimedia at freebsd.org\n",
+ pci_get_revid(dev));
+ return (BUS_PROBE_DEFAULT);
+ }
+ case ES1371_PCI_ID2:
+ device_set_desc(dev, "Strange AudioPCI ES1371-? (vid=3274)");
+ device_printf(dev,
+ "unknown revision %d -- please report to "
+ "freebsd-multimedia at freebsd.org\n", pci_get_revid(dev));
+ return (BUS_PROBE_DEFAULT);
+ case CT4730_PCI_ID:
+ switch(pci_get_revid(dev)) {
+ case CT4730REV_CT4730_A:
+ device_set_desc(dev,
+ "Creative SB AudioPCI CT4730/EV1938");
+ return (BUS_PROBE_DEFAULT);
+ default:
+ device_set_desc(dev, "Creative SB AudioPCI CT4730-?");
+ device_printf(dev,
+ "unknown revision %d -- please report to "
+ "freebsd-multimedia at freebsd.org\n",
+ pci_get_revid(dev));
+ return (BUS_PROBE_DEFAULT);
+ }
+ case CT5880_PCI_ID:
+ switch(pci_get_revid(dev)) {
+ case CT5880REV_CT5880_C:
+ device_set_desc(dev, "Creative CT5880-C");
+ return (BUS_PROBE_DEFAULT);
+ case CT5880REV_CT5880_D:
+ device_set_desc(dev, "Creative CT5880-D");
+ return (BUS_PROBE_DEFAULT);
+ case CT5880REV_CT5880_E:
+ device_set_desc(dev, "Creative CT5880-E");
+ return (BUS_PROBE_DEFAULT);
+ default:
+ device_set_desc(dev, "Creative CT5880-?");
+ device_printf(dev,
+ "unknown revision %d -- please report to "
+ "freebsd-multimedia at freebsd.org\n",
+ pci_get_revid(dev));
+ return (BUS_PROBE_DEFAULT);
+ }
+ default:
+ return (ENXIO);
+ }
}
#ifdef SND_DYNSYSCTL
static int
sysctl_es137x_spdif_enable(SYSCTL_HANDLER_ARGS)
{
-struct es_info *es;
-device_t dev;
-uint32_t r;
-int err, new_en;
-
-dev = oidp->oid_arg1;
-es = pcm_getdevinfo(dev);
-ES_LOCK(es);
-r = es_rd(es, ES1370_REG_STATUS, 4);
-ES_UNLOCK(es);
-new_en = (r & ENABLE_SPDIF) ? 1 : 0;
-err = sysctl_handle_int(oidp, &new_en, sizeof(new_en), req);
-
-if (err || req->newptr == NULL)
-return (err);
-if (new_en < 0 || new_en > 1)
-return (EINVAL);
-
-ES_LOCK(es);
-if (new_en) {
-r |= ENABLE_SPDIF;
-es->ctrl |= SPDIFEN_B;
-es->ctrl |= RECEN_B;
-} else {
-r &= ~ENABLE_SPDIF;
-es->ctrl &= ~SPDIFEN_B;
-es->ctrl &= ~RECEN_B;
-}
-es_wr(es, ES1370_REG_CONTROL, es->ctrl, 4);
-es_wr(es, ES1370_REG_STATUS, r, 4);
-ES_UNLOCK(es);
+ struct es_info *es;
+ device_t dev;
+ uint32_t r;
+ int err, new_en;
+
+ dev = oidp->oid_arg1;
+ es = pcm_getdevinfo(dev);
+ ES_LOCK(es);
+ r = es_rd(es, ES1370_REG_STATUS, 4);
+ ES_UNLOCK(es);
+ new_en = (r & ENABLE_SPDIF) ? 1 : 0;
+ err = sysctl_handle_int(oidp, &new_en, 0, req);
+
+ if (err || req->newptr == NULL)
+ return (err);
+ if (new_en < 0 || new_en > 1)
+ return (EINVAL);
+
+ ES_LOCK(es);
+ if (new_en) {
+ r |= ENABLE_SPDIF;
+ es->ctrl |= SPDIFEN_B;
+ es->ctrl |= RECEN_B;
+ } else {
+ r &= ~ENABLE_SPDIF;
+ es->ctrl &= ~SPDIFEN_B;
+ es->ctrl &= ~RECEN_B;
+ }
+ es_wr(es, ES1370_REG_CONTROL, es->ctrl, 4);
+ es_wr(es, ES1370_REG_STATUS, r, 4);
+ ES_UNLOCK(es);
-return (0);
+ return (0);
}
-#if 0
static int
sysctl_es137x_latency_timer(SYSCTL_HANDLER_ARGS)
{
-struct es_info *es;
-device_t dev;
-uint32_t val;
-int err;
-
-dev = oidp->oid_arg1;
-es = pcm_getdevinfo(dev);
-ES_LOCK(es);
-val = pci_read_config(dev, PCIR_LATTIMER, 1);
-ES_UNLOCK(es);
-err = sysctl_handle_int(oidp, &val, sizeof(val), req);
-
-if (err || req->newptr == NULL)
-return (err);
-if (val > 255)
-return (EINVAL);
-
-ES_LOCK(es);
-pci_write_config(dev, PCIR_LATTIMER, val, 1);
-ES_UNLOCK(es);
+ struct es_info *es;
+ device_t dev;
+ uint32_t val;
+ int err;
+
+ dev = oidp->oid_arg1;
+ es = pcm_getdevinfo(dev);
+ ES_LOCK(es);
+ val = pci_read_config(dev, PCIR_LATTIMER, 1);
+ ES_UNLOCK(es);
+ err = sysctl_handle_int(oidp, &val, 0, req);
+
+ if (err || req->newptr == NULL)
+ return (err);
+ if (val > 255)
+ return (EINVAL);
+
+ ES_LOCK(es);
+ pci_write_config(dev, PCIR_LATTIMER, val, 1);
+ ES_UNLOCK(es);
-return (0);
+ return (0);
}
static int
sysctl_es137x_fixed_rate(SYSCTL_HANDLER_ARGS)
{
-struct es_info *es;
-device_t dev;
-uint32_t val;
-int err;
-
-dev = oidp->oid_arg1;
-es = pcm_getdevinfo(dev);
-ES_LOCK(es);
-val = ES_FIXED_RATE(es->escfg);
-if (val < es_caps.minspeed)
-val = 0;
-ES_UNLOCK(es);
-err = sysctl_handle_int(oidp, &val, sizeof(val), req);
-
-if (err || req->newptr == NULL)
-return (err);
-if (val != 0 && (val < es_caps.minspeed || val > es_caps.maxspeed))
-return (EINVAL);
-
-ES_LOCK(es);
-if (es->ctrl & (CTRL_DAC2_EN|CTRL_ADC_EN)) {
-ES_UNLOCK(es);
-return (EBUSY);
-}
-if (val) {
-if (val != ES_FIXED_RATE(es->escfg)) {
-es->escfg = ES_SET_FIXED_RATE(es->escfg, val);
-es->ch[ES_DAC2].caps.maxspeed = val;
-es->ch[ES_DAC2].caps.minspeed = val;
-es->ch[ES_ADC].caps.maxspeed = val;
-es->ch[ES_ADC].caps.minspeed = val;
-es->ctrl &= ~CTRL_PCLKDIV;
-es->ctrl |= DAC2_SRTODIV(val) << CTRL_SH_PCLKDIV;
-es_wr(es, ES1370_REG_CONTROL, es->ctrl, 4);
-}
-} else {
-es->escfg = ES_SET_FIXED_RATE(es->escfg, 0);
-es->ch[ES_DAC2].caps = es_caps;
-es->ch[ES_ADC].caps = es_caps;
-}
-ES_UNLOCK(es);
+ struct es_info *es;
+ device_t dev;
+ uint32_t val;
+ int err;
+
+ dev = oidp->oid_arg1;
+ es = pcm_getdevinfo(dev);
+ ES_LOCK(es);
+ val = ES_FIXED_RATE(es->escfg);
+ if (val < es_caps.minspeed)
+ val = 0;
+ ES_UNLOCK(es);
+ err = sysctl_handle_int(oidp, &val, 0, req);
+
+ if (err || req->newptr == NULL)
+ return (err);
+ if (val != 0 && (val < es_caps.minspeed || val > es_caps.maxspeed))
+ return (EINVAL);
+
+ ES_LOCK(es);
+ if (es->ctrl & (CTRL_DAC2_EN|CTRL_ADC_EN)) {
+ ES_UNLOCK(es);
+ return (EBUSY);
+ }
+ if (val) {
+ if (val != ES_FIXED_RATE(es->escfg)) {
+ es->escfg = ES_SET_FIXED_RATE(es->escfg, val);
+ es->ch[ES_DAC2].caps.maxspeed = val;
+ es->ch[ES_DAC2].caps.minspeed = val;
+ es->ch[ES_ADC].caps.maxspeed = val;
+ es->ch[ES_ADC].caps.minspeed = val;
+ es->ctrl &= ~CTRL_PCLKDIV;
+ es->ctrl |= DAC2_SRTODIV(val) << CTRL_SH_PCLKDIV;
+ es_wr(es, ES1370_REG_CONTROL, es->ctrl, 4);
+ }
+ } else {
+ es->escfg = ES_SET_FIXED_RATE(es->escfg, 0);
+ es->ch[ES_DAC2].caps = es_caps;
+ es->ch[ES_ADC].caps = es_caps;
+ }
+ ES_UNLOCK(es);
-return (0);
+ return (0);
}
static int
sysctl_es137x_single_pcm_mixer(SYSCTL_HANDLER_ARGS)
{
-struct es_info *es;
-struct snddev_info *d;
-struct snd_mixer *m;
-struct cdev *i_dev;
-device_t dev;
-uint32_t val, set;
-int recsrc, level, err;
-
-dev = oidp->oid_arg1;
-d = device_get_softc(dev);
-if (d == NULL || d->mixer_dev == NULL || d->mixer_dev->si_drv1 == NULL)
-return (EINVAL);
-es = d->devinfo;
-if (es == NULL)
-return (EINVAL);
-ES_LOCK(es);
-set = ES_SINGLE_PCM_MIX(es->escfg);
-val = set;
-ES_UNLOCK(es);
-err = sysctl_handle_int(oidp, &val, sizeof(val), req);
-
-if (err || req->newptr == NULL)
-return (err);
-if (!(val == 0 || val == 1))
-return (EINVAL);
-if (val == set)
-return (0);
-i_dev = d->mixer_dev;
-if (mixer_ioctl(i_dev, 0, (caddr_t)&recsrc, 0, NULL) != EBADF)
-return (EBUSY);
-err = mixer_ioctl(i_dev, MIXER_READ(SOUND_MIXER_PCM),
-(caddr_t)&level, -1, NULL);
-if (!err)
-err = mixer_ioctl(i_dev, MIXER_READ(SOUND_MIXER_RECSRC),
-(caddr_t)&recsrc, -1, NULL);
-if (err)
-return (err);
-if (level < 0)
-return (EINVAL);
-
-ES_LOCK(es);
-if (es->ctrl & (CTRL_ADC_EN | CTRL_DAC1_EN | CTRL_DAC2_EN)) {
-ES_UNLOCK(es);
-return (EBUSY);
-}
-if (val) {
-es->escfg = ES_SET_SINGLE_PCM_MIX(es->escfg, 1);
-} else {
-es->escfg = ES_SET_SINGLE_PCM_MIX(es->escfg, 0);
-}
-ES_UNLOCK(es);
-m = i_dev->si_drv1;
-if (!val) {
-mix_setdevs(m, mix_getdevs(d->mixer_dev->si_drv1) |
-(1 << SOUND_MIXER_SYNTH));
-mix_setrecdevs(m, mix_getrecdevs(d->mixer_dev->si_drv1) |
-(1 << SOUND_MIXER_SYNTH));
-err = mixer_ioctl(i_dev, MIXER_WRITE(SOUND_MIXER_SYNTH),
-(caddr_t)&level, -1, NULL);
-} else {
-err = mixer_ioctl(i_dev, MIXER_WRITE(SOUND_MIXER_SYNTH),
-(caddr_t)&level, -1, NULL);
-mix_setdevs(m, mix_getdevs(d->mixer_dev->si_drv1) &
-~(1 << SOUND_MIXER_SYNTH));
-mix_setrecdevs(m, mix_getrecdevs(d->mixer_dev->si_drv1) &
-~(1 << SOUND_MIXER_SYNTH));
-}
-if (!err) {
-level = recsrc;
-if (recsrc & (1 << SOUND_MIXER_PCM))
-recsrc |= 1 << SOUND_MIXER_SYNTH;
-else if (recsrc & (1 << SOUND_MIXER_SYNTH))
-recsrc |= 1 << SOUND_MIXER_PCM;
-if (level != recsrc)
-err = mixer_ioctl(i_dev, MIXER_WRITE(SOUND_MIXER_RECSRC),
-(caddr_t)&recsrc, -1, NULL);
+ struct es_info *es;
+ struct snddev_info *d;
+ struct snd_mixer *m;
+ device_t dev;
+ uint32_t val, set;
+ int recsrc, level, err;
+
+ dev = oidp->oid_arg1;
+ d = device_get_softc(dev);
+ if (!PCM_REGISTERED(d) || d->mixer_dev == NULL ||
+ d->mixer_dev->si_drv1 == NULL)
+ return (EINVAL);
+ es = d->devinfo;
+ if (es == NULL)
+ return (EINVAL);
+ ES_LOCK(es);
+ set = ES_SINGLE_PCM_MIX(es->escfg);
+ val = set;
+ ES_UNLOCK(es);
+ err = sysctl_handle_int(oidp, &val, 0, req);
+
+ if (err || req->newptr == NULL)
+ return (err);
+ if (!(val == 0 || val == 1))
+ return (EINVAL);
+ if (val == set)
+ return (0);
+ PCM_ACQUIRE_QUICK(d);
+ m = (d->mixer_dev != NULL) ? d->mixer_dev->si_drv1 : NULL;
+ if (m == NULL) {
+ PCM_RELEASE_QUICK(d);
+ return (ENODEV);
+ }
+ if (mixer_busy(m) != 0) {
+ PCM_RELEASE_QUICK(d);
+ return (EBUSY);
+ }
+ level = mix_get(m, SOUND_MIXER_PCM);
+ recsrc = mix_getrecsrc(m);
+ if (level < 0 || recsrc < 0) {
+ PCM_RELEASE_QUICK(d);
+ return (ENXIO);
+ }
+
+ ES_LOCK(es);
+ if (es->ctrl & (CTRL_ADC_EN | CTRL_DAC1_EN | CTRL_DAC2_EN)) {
+ ES_UNLOCK(es);
+ PCM_RELEASE_QUICK(d);
+ return (EBUSY);
+ }
+ if (val)
+ es->escfg = ES_SET_SINGLE_PCM_MIX(es->escfg, 1);
+ else
+ es->escfg = ES_SET_SINGLE_PCM_MIX(es->escfg, 0);
+ ES_UNLOCK(es);
+ if (!val) {
+ mix_setdevs(m, mix_getdevs(m) | (1 << SOUND_MIXER_SYNTH));
+ mix_setrecdevs(m, mix_getrecdevs(m) | (1 << SOUND_MIXER_SYNTH));
+ err = mix_set(m, SOUND_MIXER_SYNTH, level & 0x7f,
+ (level >> 8) & 0x7f);
+ } else {
+ err = mix_set(m, SOUND_MIXER_SYNTH, level & 0x7f,
+ (level >> 8) & 0x7f);
+ mix_setdevs(m, mix_getdevs(m) & ~(1 << SOUND_MIXER_SYNTH));
+ mix_setrecdevs(m, mix_getrecdevs(m) &
+ ~(1 << SOUND_MIXER_SYNTH));
+ }
+ if (!err) {
+ level = recsrc;
+ if (recsrc & (1 << SOUND_MIXER_PCM))
+ recsrc |= 1 << SOUND_MIXER_SYNTH;
+ else if (recsrc & (1 << SOUND_MIXER_SYNTH))
+ recsrc |= 1 << SOUND_MIXER_PCM;
+ if (level != recsrc)
+ err = mix_setrecsrc(m, recsrc);
+ }
+
+ PCM_RELEASE_QUICK(d);
+
+ return (err);
}
-return (err);
+
+static int
+sysctl_es_polling(SYSCTL_HANDLER_ARGS)
+{
+ struct es_info *es;
+ device_t dev;
+ int err, val;
+
+ dev = oidp->oid_arg1;
+ es = pcm_getdevinfo(dev);
+ if (es == NULL)
+ return (EINVAL);
+ ES_LOCK(es);
+ val = es->polling;
+ ES_UNLOCK(es);
+ err = sysctl_handle_int(oidp, &val, 0, req);
+
+ if (err || req->newptr == NULL)
+ return (err);
+ if (val < 0 || val > 1)
+ return (EINVAL);
+
+ ES_LOCK(es);
+ if (val != es->polling) {
+ if (es_chan_active(es) != 0)
+ err = EBUSY;
+ else if (val == 0)
+ es->polling = 0;
+ else
+ es->polling = 1;
+ }
+ ES_UNLOCK(es);
+
+ return (err);
}
-#endif
#endif /* SND_DYNSYSCTL */
static void
es_init_sysctls(device_t dev)
{
#ifdef SND_DYNSYSCTL
-struct es_info *es;
-int r, devid, revid;
+ struct es_info *es;
+ int r, devid, revid;
-devid = pci_get_devid(dev);
-revid = pci_get_revid(dev);
-es = pcm_getdevinfo(dev);
-if ((devid == ES1371_PCI_ID && revid == ES1371REV_ES1373_8) ||
-(devid == ES1371_PCI_ID && revid == ES1371REV_CT5880_A) ||
-(devid == CT5880_PCI_ID && revid == CT5880REV_CT5880_C) ||
-(devid == CT5880_PCI_ID && revid == CT5880REV_CT5880_D) ||
-(devid == CT5880_PCI_ID && revid == CT5880REV_CT5880_E)) {
-SYSCTL_ADD_PROC(snd_sysctl_tree(dev),
-SYSCTL_CHILDREN(snd_sysctl_tree_top(dev)),
-OID_AUTO, "spdif_enabled",
-CTLTYPE_INT | CTLFLAG_RW, dev, sizeof(dev),
-sysctl_es137x_spdif_enable, "I",
-"Enable S/PDIF output on primary playback channel");
-#if 0
-} else if (devid == ES1370_PCI_ID) {
-/*
-* Enable fixed rate sysctl if both DAC2 / ADC enabled.
-*/
-if (es->ch[ES_DAC2].channel != NULL && es->ch[ES_ADC].channel != NULL) {
-SYSCTL_ADD_PROC(snd_sysctl_tree(dev),
-SYSCTL_CHILDREN(snd_sysctl_tree_top(dev)),
-OID_AUTO, "fixed_rate",
-CTLTYPE_INT | CTLFLAG_RW, dev, sizeof(dev),
-sysctl_es137x_fixed_rate, "I",
-"Enable fixed rate playback/recording");
-}
-/*
-* Enable single pcm mixer sysctl if both DAC1/2 enabled.
-*/
-if (es->ch[ES_DAC1].channel != NULL && es->ch[ES_DAC2].channel != NULL) {
-SYSCTL_ADD_PROC(snd_sysctl_tree(dev),
-SYSCTL_CHILDREN(snd_sysctl_tree_top(dev)),
-OID_AUTO, "single_pcm_mixer",
-CTLTYPE_INT | CTLFLAG_RW, dev, sizeof(dev),
-sysctl_es137x_single_pcm_mixer, "I",
-"Single PCM mixer controller for both DAC1/DAC2");
-}
-#endif
-}
-if (resource_int_value(device_get_name(dev),
-device_get_unit(dev), "latency_timer", &r) == 0 &&
-!(r < 0 || r > 255))
-pci_write_config(dev, PCIR_LATTIMER, r, 1);
-#if 0
-SYSCTL_ADD_PROC(snd_sysctl_tree(dev),
-SYSCTL_CHILDREN(snd_sysctl_tree_top(dev)),
-OID_AUTO, "latency_timer",
-CTLTYPE_INT | CTLFLAG_RW, dev, sizeof(dev),
-sysctl_es137x_latency_timer, "I",
-"PCI Latency Timer configuration");
-#endif
+ devid = pci_get_devid(dev);
+ revid = pci_get_revid(dev);
+ es = pcm_getdevinfo(dev);
+ if ((devid == ES1371_PCI_ID && revid == ES1371REV_ES1373_8) ||
+ (devid == ES1371_PCI_ID && revid == ES1371REV_CT5880_A) ||
+ (devid == CT5880_PCI_ID && revid == CT5880REV_CT5880_C) ||
+ (devid == CT5880_PCI_ID && revid == CT5880REV_CT5880_D) ||
+ (devid == CT5880_PCI_ID && revid == CT5880REV_CT5880_E)) {
+ /* XXX: an user should be able to set this with a control tool,
+ if not done before 7.0-RELEASE, this needs to be converted
+ to a device specific sysctl "dev.pcm.X.yyy" via
+ device_get_sysctl_*() as discussed on multimedia@ in msg-id
+ <861wujij2q.fsf at xps.des.no> */
+ SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev),
+ SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO,
+ "spdif_enabled", CTLTYPE_INT | CTLFLAG_RW, dev, sizeof(dev),
+ sysctl_es137x_spdif_enable, "I",
+ "Enable S/PDIF output on primary playback channel");
+ } else if (devid == ES1370_PCI_ID) {
+ /*
+ * Enable fixed rate sysctl if both DAC2 / ADC enabled.
+ */
+ if (es->ch[ES_DAC2].channel != NULL &&
+ es->ch[ES_ADC].channel != NULL) {
+ /* XXX: an user should be able to set this with a control tool,
+ if not done before 7.0-RELEASE, this needs to be converted
+ to a device specific sysctl "dev.pcm.X.yyy" via
+ device_get_sysctl_*() as discussed on multimedia@ in msg-id
+ <861wujij2q.fsf at xps.des.no> */
+ SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev),
+ SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
+ OID_AUTO, "fixed_rate", CTLTYPE_INT | CTLFLAG_RW,
+ dev, sizeof(dev), sysctl_es137x_fixed_rate, "I",
+ "Enable fixed rate playback/recording");
+ }
+ /*
+ * Enable single pcm mixer sysctl if both DAC1/2 enabled.
+ */
+ if (es->ch[ES_DAC1].channel != NULL &&
+ es->ch[ES_DAC2].channel != NULL) {
+ /* XXX: an user should be able to set this with a control tool,
+ if not done before 7.0-RELEASE, this needs to be converted
+ to a device specific sysctl "dev.pcm.X.yyy" via
+ device_get_sysctl_*() as discussed on multimedia@ in msg-id
+ <861wujij2q.fsf at xps.des.no> */
+ SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev),
+ SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
+ OID_AUTO, "single_pcm_mixer",
+ CTLTYPE_INT | CTLFLAG_RW, dev, sizeof(dev),
+ sysctl_es137x_single_pcm_mixer, "I",
+ "Single PCM mixer controller for both DAC1/DAC2");
+ }
+ }
+ if (resource_int_value(device_get_name(dev), device_get_unit(dev),
+ "latency_timer", &r) == 0 && !(r < 0 || r > 255))
+ pci_write_config(dev, PCIR_LATTIMER, r, 1);
+ /* XXX: this needs to be converted to a device specific sysctl
+ "dev.pcm.X.yyy" via device_get_sysctl_*() as discussed on
+ multimedia@ in msg-id <861wujij2q.fsf at xps.des.no> */
+ SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev),
+ SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO,
+ "latency_timer", CTLTYPE_INT | CTLFLAG_RW, dev, sizeof(dev),
+ sysctl_es137x_latency_timer, "I",
+ "PCI Latency Timer configuration");
+ SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev),
+ SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO,
+ "polling", CTLTYPE_INT | CTLFLAG_RW, dev, sizeof(dev),
+ sysctl_es_polling, "I",
+ "Enable polling mode");
#endif /* SND_DYNSYSCTL */
}
static int
es_pci_attach(device_t dev)
{
-u_int32_t data;
-struct es_info *es = NULL;
-int mapped, i, numplay, dac_cfg;
-char status[SND_STATUSLEN];
-struct ac97_info *codec = NULL;
-kobj_class_t ct = NULL;
-uint32_t devid;
-
-if ((es = malloc(sizeof *es, M_DEVBUF, M_NOWAIT | M_ZERO)) == NULL) {
-device_printf(dev, "cannot allocate softcn");
-return ENXIO;
-}
-es->lock = snd_mtxcreate(device_get_nameunit(dev), "sound softc");
-es->dev = dev;
-es->escfg = 0;
-mapped = 0;
-
-pci_enable_busmaster(dev);
-data = pci_read_config(dev, PCIR_COMMAND, 2);
-data |= (PCIM_CMD_PORTEN|PCIM_CMD_MEMEN);
-pci_write_config(dev, PCIR_COMMAND, data, 2);
-data = pci_read_config(dev, PCIR_COMMAND, 2);
-if (mapped == 0 && (data & PCIM_CMD_MEMEN)) {
-es->regid = MEM_MAP_REG;
-es->regtype = SYS_RES_MEMORY;
-es->reg = bus_alloc_resource_any(dev, es->regtype, &es->regid,
-RF_ACTIVE);
-if (es->reg)
-mapped++;
-}
-if (mapped == 0 && (data & PCIM_CMD_PORTEN)) {
-es->regid = PCIR_BAR(0);
-es->regtype = SYS_RES_IOPORT;
-es->reg = bus_alloc_resource_any(dev, es->regtype, &es->regid,
-RF_ACTIVE);
-if (es->reg)
-mapped++;
-}
-if (mapped == 0) {
-device_printf(dev, "unable to map register spacen");
-goto bad;
-}
-
-es->st = rman_get_bustag(es->reg);
-es->sh = rman_get_bushandle(es->reg);
-es->bufsz = pcm_getbuffersize(dev, 4096, ES_DEFAULT_BUFSZ, 65536);
-
-if (resource_int_value(device_get_name(dev),
-device_get_unit(dev), "dac", &dac_cfg) == 0) {
-if (dac_cfg < 0 || dac_cfg > 3)
-dac_cfg = ES_DEFAULT_DAC_CFG;
-} else
-dac_cfg = ES_DEFAULT_DAC_CFG;
-
-switch (dac_cfg) {
-case 0: /* Enable all DAC: DAC1, DAC2 */
-numplay = 2;
-es->escfg = ES_SET_DAC_FIRST(es->escfg, ES_DAC1);
-es->escfg = ES_SET_DAC_SECOND(es->escfg, ES_DAC2);
-break;
-case 1: /* Only DAC1 */
-numplay = 1;
-es->escfg = ES_SET_DAC_FIRST(es->escfg, ES_DAC1);
-break;
-case 3: /* Enable all DAC / swap position: DAC2, DAC1 */
-numplay = 2;
-es->escfg = ES_SET_DAC_FIRST(es->escfg, ES_DAC2);
-es->escfg = ES_SET_DAC_SECOND(es->escfg, ES_DAC1);
-break;
-case 2: /* Only DAC2 */
-default:
-numplay = 1;
-es->escfg = ES_SET_DAC_FIRST(es->escfg, ES_DAC2);
-break;
-}
-es->escfg = ES_SET_NUMPLAY(es->escfg, numplay);
-es->escfg = ES_SET_NUMREC(es->escfg, 1);
-
-devid = pci_get_devid(dev);
-switch (devid) {
-case ES1371_PCI_ID:
-case ES1371_PCI_ID2:
-case CT5880_PCI_ID:
-case CT4730_PCI_ID:
-es1371_init(es);
-codec = AC97_CREATE(dev, es, es1371_ac97);
-if (codec == NULL)
-goto bad;
-/* our init routine does everything for us */
-/* set to NULL; flag mixer_init not to run the ac97_init */
-/* ac97_mixer.init = NULL; */
-if (mixer_init(dev, ac97_getmixerclass(), codec))
-goto bad;
-ct = &eschan1371_class;
-break;
-case ES1370_PCI_ID:
-es1370_init(es);
-/*
-* Disable fixed rate operation if DAC2 disabled.
-* This is a special case for es1370 only, where the
-* speed of both ADC and DAC2 locked together.
-*/
-if (!ES_DAC2_ENABLED(es->escfg)) {
-es->escfg = ES_SET_FIXED_RATE(es->escfg, 0);
-}
-if (mixer_init(dev, &es1370_mixer_class, es))
-goto bad;
-ct = &eschan1370_class;
-break;
-default:
-goto bad;
-/* NOTREACHED */
-}
-
-es->irqid = 0;
-es->irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &es->irqid,
-RF_ACTIVE | RF_SHAREABLE);
-if (!es->irq || snd_setup_intr(dev, es->irq, INTR_MPSAFE, es_intr, es, &es->ih)) {
-device_printf(dev, "unable to map interruptn");
-goto bad;
-}
-
-if (bus_dma_tag_create(/*parent*/NULL, /*alignment*/2, /*boundary*/0,
-/*lowaddr*/BUS_SPACE_MAXADDR_32BIT,
-/*highaddr*/BUS_SPACE_MAXADDR,
-/*filter*/NULL, /*filterarg*/NULL,
-/*maxsize*/es->bufsz, /*nsegments*/1, /*maxsegz*/0x3ffff,
-/*flags*/0, /*lockfunc*/NULL,
-/*lockarg*/NULL, &es->parent_dmat) != 0) {
-device_printf(dev, "unable to create dma tagn");
-goto bad;
-}
-
-snprintf(status, SND_STATUSLEN, "at %s 0x%lx irq %ld %s",
-(es->regtype == SYS_RES_IOPORT)? "io" : "memory",
-rman_get_start(es->reg), rman_get_start(es->irq),PCM_KLDSTRING(snd_es137x));
-
-if (pcm_register(dev, es, numplay, 1))
-goto bad;
-for (i = 0; i < numplay; i++)
-pcm_addchan(dev, PCMDIR_PLAY, ct, es);
-pcm_addchan(dev, PCMDIR_REC, ct, es);
-es_init_sysctls(dev);
-pcm_setstatus(dev, status);
-es->escfg = ES_SET_GP(es->escfg, 0);
-if (numplay == 1) {
-device_printf(dev, "<Playback: DAC%d / Record: ADC>n",
-ES_DAC_FIRST(es->escfg) + 1);
-} else if (numplay == 2) {
-device_printf(dev, "<Playback: DAC%d,DAC%d / Record: ADC>n",
-ES_DAC_FIRST(es->escfg) + 1,
-ES_DAC_SECOND(es->escfg) + 1);
-}
-return 0;
+ uint32_t data;
+ struct es_info *es = NULL;
+ int mapped, i, numplay, dac_cfg;
+ char status[SND_STATUSLEN];
+ struct ac97_info *codec = NULL;
+ kobj_class_t ct = NULL;
+ uint32_t devid;
+
+ es = malloc(sizeof *es, M_DEVBUF, M_WAITOK | M_ZERO);
+ es->lock = snd_mtxcreate(device_get_nameunit(dev), "snd_es137x softc");
+ es->dev = dev;
+ es->escfg = 0;
+ mapped = 0;
+
+ pci_enable_busmaster(dev);
+ data = pci_read_config(dev, PCIR_COMMAND, 2);
+ data |= (PCIM_CMD_PORTEN|PCIM_CMD_MEMEN);
+ pci_write_config(dev, PCIR_COMMAND, data, 2);
+ data = pci_read_config(dev, PCIR_COMMAND, 2);
+ if (mapped == 0 && (data & PCIM_CMD_MEMEN)) {
+ es->regid = MEM_MAP_REG;
+ es->regtype = SYS_RES_MEMORY;
+ es->reg = bus_alloc_resource_any(dev, es->regtype, &es->regid,
+ RF_ACTIVE);
+ if (es->reg)
+ mapped++;
+ }
+ if (mapped == 0 && (data & PCIM_CMD_PORTEN)) {
+ es->regid = PCIR_BAR(0);
+ es->regtype = SYS_RES_IOPORT;
+ es->reg = bus_alloc_resource_any(dev, es->regtype, &es->regid,
+ RF_ACTIVE);
+ if (es->reg)
+ mapped++;
+ }
+ if (mapped == 0) {
+ device_printf(dev, "unable to map register space\n");
+ goto bad;
+ }
+
+ es->st = rman_get_bustag(es->reg);
+ es->sh = rman_get_bushandle(es->reg);
+ callout_init(&es->poll_timer, CALLOUT_MPSAFE);
+ es->poll_ticks = 1;
+
+ if (resource_int_value(device_get_name(dev),
+ device_get_unit(dev), "polling", &i) == 0 && i != 0)
+ es->polling = 1;
+ else
+ es->polling = 0;
+
+ es->bufsz = pcm_getbuffersize(dev, 4096, ES_DEFAULT_BUFSZ, 65536);
+ if (resource_int_value(device_get_name(dev),
+ device_get_unit(dev), "blocksize", &i) == 0 && i > 0) {
+ i &= ES_BLK_ALIGN;
+ if (i < ES_BLK_MIN)
+ i = ES_BLK_MIN;
+ es->blkcnt = es->bufsz / i;
+ i = 0;
+ while (es->blkcnt >> i)
+ i++;
+ es->blkcnt = 1 << (i - 1);
+ if (es->blkcnt < ES_DMA_SEGS_MIN)
+ es->blkcnt = ES_DMA_SEGS_MIN;
+ else if (es->blkcnt > ES_DMA_SEGS_MAX)
+ es->blkcnt = ES_DMA_SEGS_MAX;
+
+ } else
+ es->blkcnt = 2;
+
+ if (resource_int_value(device_get_name(dev), device_get_unit(dev),
+ "dac", &dac_cfg) == 0) {
+ if (dac_cfg < 0 || dac_cfg > 3)
+ dac_cfg = ES_DEFAULT_DAC_CFG;
+ } else
+ dac_cfg = ES_DEFAULT_DAC_CFG;
+
+ switch (dac_cfg) {
+ case 0: /* Enable all DAC: DAC1, DAC2 */
+ numplay = 2;
+ es->escfg = ES_SET_DAC_FIRST(es->escfg, ES_DAC1);
+ es->escfg = ES_SET_DAC_SECOND(es->escfg, ES_DAC2);
+ break;
+ case 1: /* Only DAC1 */
+ numplay = 1;
+ es->escfg = ES_SET_DAC_FIRST(es->escfg, ES_DAC1);
+ break;
+ case 3: /* Enable all DAC / swap position: DAC2, DAC1 */
+ numplay = 2;
+ es->escfg = ES_SET_DAC_FIRST(es->escfg, ES_DAC2);
+ es->escfg = ES_SET_DAC_SECOND(es->escfg, ES_DAC1);
+ break;
+ case 2: /* Only DAC2 */
+ default:
+ numplay = 1;
+ es->escfg = ES_SET_DAC_FIRST(es->escfg, ES_DAC2);
+ break;
+ }
+ es->escfg = ES_SET_NUMPLAY(es->escfg, numplay);
+ es->escfg = ES_SET_NUMREC(es->escfg, 1);
+
+ devid = pci_get_devid(dev);
+ switch (devid) {
+ case ES1371_PCI_ID:
+ case ES1371_PCI_ID2:
+ case CT5880_PCI_ID:
+ case CT4730_PCI_ID:
+ es1371_init(es);
+ codec = AC97_CREATE(dev, es, es1371_ac97);
+ if (codec == NULL)
+ goto bad;
+ /* our init routine does everything for us */
+ /* set to NULL; flag mixer_init not to run the ac97_init */
+ /* ac97_mixer.init = NULL; */
+ if (mixer_init(dev, ac97_getmixerclass(), codec))
+ goto bad;
+ ct = &eschan1371_class;
+ break;
+ case ES1370_PCI_ID:
+ es1370_init(es);
+ /*
+ * Disable fixed rate operation if DAC2 disabled.
+ * This is a special case for es1370 only, where the
+ * speed of both ADC and DAC2 locked together.
+ */
+ if (!ES_DAC2_ENABLED(es->escfg))
+ es->escfg = ES_SET_FIXED_RATE(es->escfg, 0);
+ if (mixer_init(dev, &es1370_mixer_class, es))
+ goto bad;
+ ct = &eschan1370_class;
+ break;
+ default:
+ goto bad;
+ /* NOTREACHED */
+ }
+
+ es->irqid = 0;
+ es->irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &es->irqid,
+ RF_ACTIVE | RF_SHAREABLE);
+ if (!es->irq || snd_setup_intr(dev, es->irq, INTR_MPSAFE, es_intr,
+ es, &es->ih)) {
+ device_printf(dev, "unable to map interrupt\n");
+ goto bad;
+ }
+
+ if (bus_dma_tag_create(/*parent*/bus_get_dma_tag(dev),
+ /*alignment*/2, /*boundary*/0,
+ /*lowaddr*/BUS_SPACE_MAXADDR_32BIT,
+ /*highaddr*/BUS_SPACE_MAXADDR,
+ /*filter*/NULL, /*filterarg*/NULL,
+ /*maxsize*/es->bufsz, /*nsegments*/1, /*maxsegz*/0x3ffff,
+ /*flags*/0, /*lockfunc*/NULL,
+ /*lockarg*/NULL, &es->parent_dmat) != 0) {
+ device_printf(dev, "unable to create dma tag\n");
+ goto bad;
+ }
+
+ snprintf(status, SND_STATUSLEN, "at %s 0x%lx irq %ld %s",
+ (es->regtype == SYS_RES_IOPORT)? "io" : "memory",
+ rman_get_start(es->reg), rman_get_start(es->irq),
+ PCM_KLDSTRING(snd_es137x));
+
+ if (pcm_register(dev, es, numplay, 1))
+ goto bad;
+ for (i = 0; i < numplay; i++)
+ pcm_addchan(dev, PCMDIR_PLAY, ct, es);
+ pcm_addchan(dev, PCMDIR_REC, ct, es);
+ es_init_sysctls(dev);
+ pcm_setstatus(dev, status);
+ es->escfg = ES_SET_GP(es->escfg, 0);
+ if (numplay == 1)
+ device_printf(dev, "<Playback: DAC%d / Record: ADC>\n",
+ ES_DAC_FIRST(es->escfg) + 1);
+ else if (numplay == 2)
+ device_printf(dev, "<Playback: DAC%d,DAC%d / Record: ADC>\n",
+ ES_DAC_FIRST(es->escfg) + 1, ES_DAC_SECOND(es->escfg) + 1);
+ return (0);
bad:
-if (es->parent_dmat) bus_dma_tag_destroy(es->parent_dmat);
-if (es->ih) bus_teardown_intr(dev, es->irq, es->ih);
-if (es->irq) bus_release_resource(dev, SYS_RES_IRQ, es->irqid, es->irq);
-if (codec) ac97_destroy(codec);
-if (es->reg) bus_release_resource(dev, es->regtype, es->regid, es->reg);
-if (es->lock) snd_mtxfree(es->lock);
-if (es) free(es, M_DEVBUF);
-return ENXIO;
+ if (es->parent_dmat)
+ bus_dma_tag_destroy(es->parent_dmat);
+ if (es->ih)
+ bus_teardown_intr(dev, es->irq, es->ih);
+ if (es->irq)
+ bus_release_resource(dev, SYS_RES_IRQ, es->irqid, es->irq);
+ if (codec)
+ ac97_destroy(codec);
+ if (es->reg)
+ bus_release_resource(dev, es->regtype, es->regid, es->reg);
+ if (es->lock)
+ snd_mtxfree(es->lock);
+ if (es)
+ free(es, M_DEVBUF);
+ return (ENXIO);
}
static int
es_pci_detach(device_t dev)
{
-int r;
-struct es_info *es;
-
-r = pcm_unregister(dev);
-if (r) return r;
+ int r;
+ struct es_info *es;
-es = pcm_getdevinfo(dev);
-bus_teardown_intr(dev, es->irq, es->ih);
-bus_release_resource(dev, SYS_RES_IRQ, es->irqid, es->irq);
-bus_release_resource(dev, es->regtype, es->regid, es->reg);
-bus_dma_tag_destroy(es->parent_dmat);
-snd_mtxfree(es->lock);
-free(es, M_DEVBUF);
+ r = pcm_unregister(dev);
+ if (r)
+ return (r);
+
+ es = pcm_getdevinfo(dev);
+
+ if (es != NULL && es->num != 0) {
+ ES_LOCK(es);
+ es->polling = 0;
+ callout_stop(&es->poll_timer);
+ ES_UNLOCK(es);
+ callout_drain(&es->poll_timer);
+ }
+
+ bus_teardown_intr(dev, es->irq, es->ih);
+ bus_release_resource(dev, SYS_RES_IRQ, es->irqid, es->irq);
+ bus_release_resource(dev, es->regtype, es->regid, es->reg);
+ bus_dma_tag_destroy(es->parent_dmat);
+ snd_mtxfree(es->lock);
+ free(es, M_DEVBUF);
-return 0;
+ return (0);
}
static device_method_t es_methods[] = {
-/* Device interface */
-DEVMETHOD(device_probe, es_pci_probe),
-DEVMETHOD(device_attach, es_pci_attach),
-DEVMETHOD(device_detach, es_pci_detach),
+ /* Device interface */
+ DEVMETHOD(device_probe, es_pci_probe),
+ DEVMETHOD(device_attach, es_pci_attach),
+ DEVMETHOD(device_detach, es_pci_detach),
-{ 0, 0 }
+ { 0, 0 }
};
static driver_t es_driver = {
-"pcm",
-es_methods,
-PCM_SOFTC_SIZE,
+ "pcm",
+ es_methods,
+ PCM_SOFTC_SIZE,
};
DRIVER_MODULE(snd_es137x, pci, es_driver, pcm_devclass, 0, 0);
Index: t4dwave.h
===================================================================
RCS file: /home/cvs/src/sys/dev/sound/pci/t4dwave.h,v
retrieving revision 1.2
retrieving revision 1.3
diff -L sys/dev/sound/pci/t4dwave.h -L sys/dev/sound/pci/t4dwave.h -u -r1.2 -r1.3
--- sys/dev/sound/pci/t4dwave.h
+++ sys/dev/sound/pci/t4dwave.h
@@ -1,31 +1,30 @@
/*-
-* Copyright (c) 1999 Cameron Grant <cg at freebsd.org>
-* All rights reserved.
-*
-* Redistribution and use in source and binary forms, with or without
-* modification, are permitted provided that the following conditions
-* are met:
-* 1. Redistributions of source code must retain the above copyright
-* notice, this list of conditions and the following disclaimer.
-* 2. Redistributions in binary form must reproduce the above copyright
-* notice, this list of conditions and the following disclaimer in the
-* documentation and/or other materials provided with the distribution.
-*
-* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
-* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
-* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
-* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
-* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
-* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
-* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
-* SUCH DAMAGE.
-*
-* $MidnightBSD$
-* $FreeBSD: src/sys/dev/sound/pci/t4dwave.h,v 1.7 2005/01/06 01:43:19 imp Exp $
-*/
+ * Copyright (c) 1999 Cameron Grant <cg at freebsd.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD: src/sys/dev/sound/pci/t4dwave.h,v 1.7 2005/01/06 01:43:19 imp Exp $
+ */
#ifndef _T4DWAVE_REG_H
#define _T4DWAVE_REG_H
Index: atiixp.h
===================================================================
RCS file: /home/cvs/src/sys/dev/sound/pci/atiixp.h,v
retrieving revision 1.3
retrieving revision 1.4
diff -L sys/dev/sound/pci/atiixp.h -L sys/dev/sound/pci/atiixp.h -u -r1.3 -r1.4
--- sys/dev/sound/pci/atiixp.h
+++ sys/dev/sound/pci/atiixp.h
@@ -1,66 +1,65 @@
/*-
-* Copyright (c) 2005 Ariff Abdullah <ariff at FreeBSD.org>
-* All rights reserved.
-*
-* Redistribution and use in source and binary forms, with or without
-* modification, are permitted provided that the following conditions
-* are met:
-* 1. Redistributions of source code must retain the above copyright
-* notice, this list of conditions and the following disclaimer.
-* 2. Redistributions in binary form must reproduce the above copyright
-* notice, this list of conditions and the following disclaimer in the
-* documentation and/or other materials provided with the distribution.
-*
-* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
-* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
-* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
-* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
-* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
-* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
-* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
-* SUCH DAMAGE.
-*
-* $MidnightBSD$
-* $FreeBSD: src/sys/dev/sound/pci/atiixp.h,v 1.1.2.2 2006/03/02 00:09:30 ariff Exp $
-*/
+ * Copyright (c) 2005 Ariff Abdullah <ariff at FreeBSD.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD: src/sys/dev/sound/pci/atiixp.h,v 1.3.2.1 2007/11/06 02:07:56 ariff Exp $
+ */
#ifndef _ATIIXP_H_
#define _ATIIXP_H_
/*
-* Constants, pretty much FreeBSD specific.
-*/
-
+ * Constants, pretty much FreeBSD specific.
+ */
+
/* Number of playback / recording channel */
#define ATI_IXP_NPCHAN 1
#define ATI_IXP_NRCHAN 1
#define ATI_IXP_NCHANS (ATI_IXP_NPCHAN + ATI_IXP_NRCHAN)
/*
-* Maximum segments/descriptors is 256, but 2 for
-* each channel should be more than enough for us.
-*/
+ * Maximum segments/descriptors is 256, but 2 for
+ * each channel should be more than enough for us.
+ */
#define ATI_IXP_DMA_CHSEGS 2
#define ATI_IXP_DMA_CHSEGS_MIN 2
#define ATI_IXP_DMA_CHSEGS_MAX 256
-#define ATI_IXP_DEFAULT_BUFSZ (1 << 13) /* 8192 */
-
#define ATI_VENDOR_ID 0x1002 /* ATI Technologies */
+
#define ATI_IXP_200_ID 0x4341
#define ATI_IXP_300_ID 0x4361
#define ATI_IXP_400_ID 0x4370
+#define ATI_IXP_SB600_ID 0x4384
#define ATI_IXP_BASE_RATE 48000
/*
-* Register definitions for ATI IXP
-*
-* References: ALSA snd-atiixp.c , OpenBSD/NetBSD auixp-*.h
-*/
+ * Register definitions for ATI IXP
+ *
+ * References: ALSA snd-atiixp.c , OpenBSD/NetBSD auixp-*.h
+ */
#define ATI_IXP_CODECS 3
@@ -196,7 +195,9 @@
#define ATI_MAX_DESCRIPTORS 256 /* max number of descriptor packets */
/* codec detection constant indicating the interrupt flags */
-#define ALL_CODECS_NOT_READY (ATI_REG_ISR_CODEC0_NOT_READY | ATI_REG_ISR_CODEC1_NOT_READY | ATI_REG_ISR_CODEC2_NOT_READY)
+#define ALL_CODECS_NOT_READY \
+ (ATI_REG_ISR_CODEC0_NOT_READY | ATI_REG_ISR_CODEC1_NOT_READY |\
+ ATI_REG_ISR_CODEC2_NOT_READY)
#define CODEC_CHECK_BITS (ALL_CODECS_NOT_READY|ATI_REG_ISR_NEW_FRAME)
#endif
--- /dev/null
+++ sys/dev/sound/pci/envy24ht.h
@@ -0,0 +1,188 @@
+/*
+ * Copyright (c) 2006 Konstantin Dimitrov <kosio.dimitrov at gmail.com>
+ * Copyright (c) 2001 Katsurajima Naoto <raven at katsurajima.seya.yokohama.jp>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHERIN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THEPOSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD: src/sys/dev/sound/pci/envy24ht.h,v 1.5 2007/05/27 19:58:39 joel Exp $
+ */
+
+
+/* -------------------------------------------------------------------- */
+
+/* PCI device ID */
+#define PCIV_ENVY24 0x1412
+#define PCID_ENVY24HT 0x1724
+
+#define PCIR_CCS 0x10 /* Controller I/O Base Address */
+#define ENVY24HT_PCIR_MT 0x14 /* Multi-Track I/O Base Address */
+
+/* Controller Registers */
+
+#define ENVY24HT_CCS_CTL 0x00 /* Control/Status Register */
+#define ENVY24HT_CCS_CTL_RESET 0x80 /* Entire Chip soft reset */
+
+#define ENVY24HT_CCS_IMASK 0x01 /* Interrupt Mask Register */
+#define ENVY24HT_CCS_IMASK_PMT 0x10 /* Professional Multi-track */
+
+#define ENVY24HT_CCS_I2CDEV 0x10 /* I2C Port Device Address Register */
+#define ENVY24HT_CCS_I2CDEV_ADDR 0xfe /* I2C device address */
+#define ENVY24HT_CCS_I2CDEV_ROM 0xa0 /* reserved for the external I2C E2PROM */
+#define ENVY24HT_CCS_I2CDEV_WR 0x01 /* write */
+#define ENVY24HT_CCS_I2CDEV_RD 0x00 /* read */
+
+#define ENVY24HT_CCS_I2CADDR 0x11 /* I2C Port Byte Address Register */
+#define ENVY24HT_CCS_I2CDATA 0x12 /* I2C Port Read/Write Data Register */
+
+#define ENVY24HT_CCS_I2CSTAT 0x13 /* I2C Port Control and Status Register */
+#define ENVY24HT_CCS_I2CSTAT_ROM 0x80 /* external E2PROM exists */
+#define ENVY24HT_CCS_I2CSTAT_BSY 0x01 /* I2C port read/write status busy */
+
+#define ENVY24HT_CCS_SCFG 0x04 /* System Configuration Register */
+#define ENVY24HT_CCSM_SCFG_XIN2 0xc0 /* XIN2 Clock Source Configuration */
+ /* 00: 24.576MHz(96kHz*256) */
+ /* 01: 49.152MHz(192kHz*256) */
+ /* 1x: Reserved */
+#define ENVY24HT_CCSM_SCFG_MPU 0x20 /* 0(not implemented)/1(1) MPU-401 UART */
+#define ENVY24HT_CCSM_SCFG_ADC 0x0c /* 1-2 stereo ADC connected, S/PDIF receiver connected */
+#define ENVY24HT_CCSM_SCFG_DAC 0x03 /* 1-4 stereo DAC connected */
+
+#define ENVY24HT_CCS_ACL 0x05 /* AC-Link Configuration Register */
+#define ENVY24HT_CCSM_ACL_MTC 0x80 /* Multi-track converter type: 0:AC'97 1:I2S */
+#define ENVY24HT_CCSM_ACL_OMODE 0x02 /* AC 97 codec SDATA_OUT 0:split 1:packed */
+
+#define ENVY24HT_CCS_I2S 0x06 /* I2S Converters Features Register */
+#define ENVY24HT_CCSM_I2S_VOL 0x80 /* I2S codec Volume and mute */
+#define ENVY24HT_CCSM_I2S_96KHZ 0x40 /* I2S converter 96kHz sampling rate support */
+#define ENVY24HT_CCSM_I2S_192KHZ 0x08 /* I2S converter 192kHz sampling rate support */
+#define ENVY24HT_CCSM_I2S_RES 0x30 /* Converter resolution */
+#define ENVY24HT_CCSM_I2S_16BIT 0x00 /* 16bit */
+#define ENVY24HT_CCSM_I2S_18BIT 0x10 /* 18bit */
+#define ENVY24HT_CCSM_I2S_20BIT 0x20 /* 20bit */
+#define ENVY24HT_CCSM_I2S_24BIT 0x30 /* 24bit */
+#define ENVY24HT_CCSM_I2S_ID 0x07 /* Other I2S IDs */
+
+#define ENVY24HT_CCS_SPDIF 0x07 /* S/PDIF Configuration Register */
+#define ENVY24HT_CCSM_SPDIF_INT_EN 0x80 /* Enable integrated S/PDIF transmitter */
+#define ENVY24HT_CCSM_SPDIF_INT_OUT 0x40 /* Internal S/PDIF Out implemented */
+#define ENVY24HT_CCSM_SPDIF_ID 0x3c /* S/PDIF chip ID */
+#define ENVY24HT_CCSM_SPDIF_IN 0x02 /* S/PDIF Stereo In is present */
+#define ENVY24HT_CCSM_SPDIF_OUT 0x01 /* External S/PDIF Out implemented */
+
+/* Professional Multi-Track Control Registers */
+
+#define ENVY24HT_MT_INT_STAT 0x00 /* DMA Interrupt Mask and Status Register */
+#define ENVY24HT_MT_INT_RSTAT 0x02 /* Multi-track record interrupt status */
+#define ENVY24HT_MT_INT_PSTAT 0x01 /* Multi-track playback interrupt status */
+#define ENVY24HT_MT_INT_MASK 0x03
+#define ENVY24HT_MT_INT_RMASK 0x02 /* Multi-track record interrupt mask */
+#define ENVY24HT_MT_INT_PMASK 0x01 /* Multi-track playback interrupt mask */
+
+#define ENVY24HT_MT_RATE 0x01 /* Sampling Rate Select Register */
+#define ENVY24HT_MT_RATE_SPDIF 0x10 /* S/PDIF input clock as the master */
+#define ENVY24HT_MT_RATE_48000 0x00
+#define ENVY24HT_MT_RATE_24000 0x01
+#define ENVY24HT_MT_RATE_12000 0x02
+#define ENVY24HT_MT_RATE_9600 0x03
+#define ENVY24HT_MT_RATE_32000 0x04
+#define ENVY24HT_MT_RATE_16000 0x05
+#define ENVY24HT_MT_RATE_8000 0x06
+#define ENVY24HT_MT_RATE_96000 0x07
+#define ENVY24HT_MT_RATE_192000 0x0e
+#define ENVY24HT_MT_RATE_64000 0x0f
+#define ENVY24HT_MT_RATE_44100 0x08
+#define ENVY24HT_MT_RATE_22050 0x09
+#define ENVY24HT_MT_RATE_11025 0x0a
+#define ENVY24HT_MT_RATE_88200 0x0b
+#define ENVY24HT_MT_RATE_176400 0x0c
+#define ENVY24HT_MT_RATE_MASK 0x0f
+
+#define ENVY24HT_MT_I2S 0x02 /* I2S Data Format Register */
+#define ENVY24HT_MT_I2S_MLR128 0x08 /* MCLK/LRCLK ratio 128x (or 256x) */
+
+#define ENVY24HT_MT_PADDR 0x10 /* Playback DMA Current/Base Address Register */
+#define ENVY24HT_MT_PCNT 0x14 /* Playback DMA Current/Base Count Register */
+#define ENVY24HT_MT_PTERM 0x1C /* Playback Current/Base Terminal Count Register */
+
+#define ENVY24HT_MT_PCTL 0x18 /* Global Playback and Record DMA Start/Stop Register */
+#define ENVY24HT_MT_PCTL_RSTART 0x02 /* 1: Record start; 0: Record stop */
+#define ENVY24HT_MT_PCTL_PSTART 0x01 /* 1: Playback start; 0: Playback stop */
+
+#define ENVY24HT_MT_RADDR 0x20 /* Record DMA Current/Base Address Register */
+#define ENVY24HT_MT_RCNT 0x24 /* Record DMA Current/Base Count Register */
+#define ENVY24HT_MT_RTERM 0x26 /* Record Current/Base Terminal Count Register */
+
+/*
+ These map values are refferd from ALSA sound driver.
+*/
+/* ENVY24 configuration E2PROM map */
+#define ENVY24HT_E2PROM_SUBVENDOR 0x02
+#define ENVY24HT_E2PROM_SUBDEVICE 0x00
+#define ENVY24HT_E2PROM_SIZE 0x04
+#define ENVY24HT_E2PROM_VERSION 0x05
+#define ENVY24HT_E2PROM_SCFG 0x06
+#define ENVY24HT_E2PROM_ACL 0x07
+#define ENVY24HT_E2PROM_I2S 0x08
+#define ENVY24HT_E2PROM_SPDIF 0x09
+#define ENVY24HT_E2PROM_GPIOMASK 0x0d
+#define ENVY24HT_E2PROM_GPIOSTATE 0x10
+#define ENVY24HT_E2PROM_GPIODIR 0x0a
+
+/* ENVY24 mixer channel defines */
+/*
+ ENVY24 mixer has original line matrix. So, general mixer command is not
+ able to use for this. If system has consumer AC'97 output, AC'97 line is
+ used as master mixer, and it is able to control.
+*/
+#define ENVY24HT_CHAN_NUM 11 /* Play * 5 + Record * 5 + Mix * 1 */
+
+#define ENVY24HT_CHAN_PLAY_DAC1 0
+#define ENVY24HT_CHAN_PLAY_DAC2 1
+#define ENVY24HT_CHAN_PLAY_DAC3 2
+#define ENVY24HT_CHAN_PLAY_DAC4 3
+#define ENVY24HT_CHAN_PLAY_SPDIF 4
+#define ENVY24HT_CHAN_REC_ADC1 5
+#define ENVY24HT_CHAN_REC_ADC2 6
+#define ENVY24HT_CHAN_REC_ADC3 7
+#define ENVY24HT_CHAN_REC_ADC4 8
+#define ENVY24HT_CHAN_REC_SPDIF 9
+#define ENVY24HT_CHAN_REC_MIX 10
+
+#define ENVY24HT_MIX_MASK 0x3fd
+#define ENVY24HT_MIX_REC_MASK 0x3e0
+
+/* volume value constants */
+#define ENVY24HT_VOL_MAX 0 /* 0db(negate) */
+#define ENVY24HT_VOL_MIN 96 /* -144db(negate) */
+#define ENVY24HT_VOL_MUTE 127 /* mute */
+
+#define BUS_SPACE_MAXADDR_ENVY24 0x0fffffff /* Address space beyond 256MB is not
+ supported */
+#define BUS_SPACE_MAXSIZE_ENVY24 0x3fffc /* 64k x 4byte(1dword) */
+
+#define ENVY24HT_CCS_GPIO_HDATA 0x1E
+#define ENVY24HT_CCS_GPIO_LDATA 0x14
+#define ENVY24HT_CCS_GPIO_LMASK 0x16
+#define ENVY24HT_CCS_GPIO_HMASK 0x1F
+#define ENVY24HT_CCS_GPIO_CTLDIR 0x18
+
--- /dev/null
+++ sys/dev/sound/pci/envy24.c
@@ -0,0 +1,2654 @@
+/*
+ * Copyright (c) 2001 Katsurajima Naoto <raven at katsurajima.seya.yokohama.jp>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHERIN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THEPOSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+
+#include <dev/sound/pcm/sound.h>
+#include <dev/sound/pcm/ac97.h>
+#include <dev/sound/pci/spicds.h>
+#include <dev/sound/pci/envy24.h>
+
+#include <dev/pci/pcireg.h>
+#include <dev/pci/pcivar.h>
+
+#include "mixer_if.h"
+
+SND_DECLARE_FILE("$FreeBSD: src/sys/dev/sound/pci/envy24.c,v 1.13 2007/05/27 19:58:39 joel Exp $");
+
+MALLOC_DEFINE(M_ENVY24, "envy24", "envy24 audio");
+
+/* -------------------------------------------------------------------- */
+
+struct sc_info;
+
+#define ENVY24_PLAY_CHNUM 10
+#define ENVY24_REC_CHNUM 12
+#define ENVY24_PLAY_BUFUNIT (4 /* byte/sample */ * 10 /* channel */)
+#define ENVY24_REC_BUFUNIT (4 /* byte/sample */ * 12 /* channel */)
+#define ENVY24_SAMPLE_NUM 4096
+
+#define ENVY24_TIMEOUT 1000
+
+#define ENVY24_DEFAULT_FORMAT (AFMT_STEREO | AFMT_S16_LE)
+
+#define ENVY24_NAMELEN 32
+
+#define SDA_GPIO 0x10
+#define SCL_GPIO 0x20
+
+struct envy24_sample {
+ volatile u_int32_t buffer;
+};
+
+typedef struct envy24_sample sample32_t;
+
+/* channel registers */
+struct sc_chinfo {
+ struct snd_dbuf *buffer;
+ struct pcm_channel *channel;
+ struct sc_info *parent;
+ int dir;
+ unsigned num; /* hw channel number */
+
+ /* channel information */
+ u_int32_t format;
+ u_int32_t speed;
+ u_int32_t blk; /* hw block size(dword) */
+
+ /* format conversion structure */
+ u_int8_t *data;
+ unsigned int size; /* data buffer size(byte) */
+ int unit; /* sample size(byte) */
+ unsigned int offset; /* samples number offset */
+ void (*emldma)(struct sc_chinfo *);
+
+ /* flags */
+ int run;
+};
+
+/* codec interface entrys */
+struct codec_entry {
+ void *(*create)(device_t dev, void *devinfo, int dir, int num);
+ void (*destroy)(void *codec);
+ void (*init)(void *codec);
+ void (*reinit)(void *codec);
+ void (*setvolume)(void *codec, int dir, unsigned int left, unsigned int right);
+ void (*setrate)(void *codec, int which, int rate);
+};
+
+/* system configuration information */
+struct cfg_info {
+ char *name;
+ u_int16_t subvendor, subdevice;
+ u_int8_t scfg, acl, i2s, spdif;
+ u_int8_t gpiomask, gpiostate, gpiodir;
+ u_int8_t cdti, cclk, cs, cif, type;
+ u_int8_t free;
+ struct codec_entry *codec;
+};
+
+/* device private data */
+struct sc_info {
+ device_t dev;
+ struct mtx *lock;
+
+ /* Control/Status registor */
+ struct resource *cs;
+ int csid;
+ bus_space_tag_t cst;
+ bus_space_handle_t csh;
+ /* DDMA registor */
+ struct resource *ddma;
+ int ddmaid;
+ bus_space_tag_t ddmat;
+ bus_space_handle_t ddmah;
+ /* Consumer Section DMA Channel Registers */
+ struct resource *ds;
+ int dsid;
+ bus_space_tag_t dst;
+ bus_space_handle_t dsh;
+ /* MultiTrack registor */
+ struct resource *mt;
+ int mtid;
+ bus_space_tag_t mtt;
+ bus_space_handle_t mth;
+ /* DMA tag */
+ bus_dma_tag_t dmat;
+ /* IRQ resource */
+ struct resource *irq;
+ int irqid;
+ void *ih;
+
+ /* system configuration data */
+ struct cfg_info *cfg;
+
+ /* ADC/DAC number and info */
+ int adcn, dacn;
+ void *adc[4], *dac[4];
+
+ /* mixer control data */
+ u_int32_t src;
+ u_int8_t left[ENVY24_CHAN_NUM];
+ u_int8_t right[ENVY24_CHAN_NUM];
+
+ /* Play/Record DMA fifo */
+ sample32_t *pbuf;
+ sample32_t *rbuf;
+ u_int32_t psize, rsize; /* DMA buffer size(byte) */
+ u_int16_t blk[2]; /* transfer check blocksize(dword) */
+ bus_dmamap_t pmap, rmap;
+
+ /* current status */
+ u_int32_t speed;
+ int run[2];
+ u_int16_t intr[2];
+ struct pcmchan_caps caps[2];
+
+ /* channel info table */
+ unsigned chnum;
+ struct sc_chinfo chan[11];
+};
+
+/* -------------------------------------------------------------------- */
+
+/*
+ * prototypes
+ */
+
+/* DMA emulator */
+static void envy24_p8u(struct sc_chinfo *);
+static void envy24_p16sl(struct sc_chinfo *);
+static void envy24_p32sl(struct sc_chinfo *);
+static void envy24_r16sl(struct sc_chinfo *);
+static void envy24_r32sl(struct sc_chinfo *);
+
+/* channel interface */
+static void *envy24chan_init(kobj_t, void *, struct snd_dbuf *, struct pcm_channel *, int);
+static int envy24chan_setformat(kobj_t, void *, u_int32_t);
+static int envy24chan_setspeed(kobj_t, void *, u_int32_t);
+static int envy24chan_setblocksize(kobj_t, void *, u_int32_t);
+static int envy24chan_trigger(kobj_t, void *, int);
+static int envy24chan_getptr(kobj_t, void *);
+static struct pcmchan_caps *envy24chan_getcaps(kobj_t, void *);
+
+/* mixer interface */
+static int envy24mixer_init(struct snd_mixer *);
+static int envy24mixer_reinit(struct snd_mixer *);
+static int envy24mixer_uninit(struct snd_mixer *);
+static int envy24mixer_set(struct snd_mixer *, unsigned, unsigned, unsigned);
+static u_int32_t envy24mixer_setrecsrc(struct snd_mixer *, u_int32_t);
+
+/* M-Audio Delta series AK4524 access interface */
+static void *envy24_delta_ak4524_create(device_t, void *, int, int);
+static void envy24_delta_ak4524_destroy(void *);
+static void envy24_delta_ak4524_init(void *);
+static void envy24_delta_ak4524_reinit(void *);
+static void envy24_delta_ak4524_setvolume(void *, int, unsigned int, unsigned int);
+
+/* -------------------------------------------------------------------- */
+
+/*
+ system constant tables
+*/
+
+/* API -> hardware channel map */
+static unsigned envy24_chanmap[ENVY24_CHAN_NUM] = {
+ ENVY24_CHAN_PLAY_SPDIF, /* 0 */
+ ENVY24_CHAN_PLAY_DAC1, /* 1 */
+ ENVY24_CHAN_PLAY_DAC2, /* 2 */
+ ENVY24_CHAN_PLAY_DAC3, /* 3 */
+ ENVY24_CHAN_PLAY_DAC4, /* 4 */
+ ENVY24_CHAN_REC_MIX, /* 5 */
+ ENVY24_CHAN_REC_SPDIF, /* 6 */
+ ENVY24_CHAN_REC_ADC1, /* 7 */
+ ENVY24_CHAN_REC_ADC2, /* 8 */
+ ENVY24_CHAN_REC_ADC3, /* 9 */
+ ENVY24_CHAN_REC_ADC4, /* 10 */
+};
+
+/* mixer -> API channel map. see above */
+static int envy24_mixmap[] = {
+ -1, /* Master output level. It is depend on codec support */
+ -1, /* Treble level of all output channels */
+ -1, /* Bass level of all output channels */
+ -1, /* Volume of synthesier input */
+ 0, /* Output level for the audio device */
+ -1, /* Output level for the PC speaker */
+ 7, /* line in jack */
+ -1, /* microphone jack */
+ -1, /* CD audio input */
+ -1, /* Recording monitor */
+ 1, /* alternative codec */
+ -1, /* global recording level */
+ -1, /* Input gain */
+ -1, /* Output gain */
+ 8, /* Input source 1 */
+ 9, /* Input source 2 */
+ 10, /* Input source 3 */
+ 6, /* Digital (input) 1 */
+ -1, /* Digital (input) 2 */
+ -1, /* Digital (input) 3 */
+ -1, /* Phone input */
+ -1, /* Phone output */
+ -1, /* Video/TV (audio) in */
+ -1, /* Radio in */
+ -1, /* Monitor volume */
+};
+
+/* variable rate audio */
+static u_int32_t envy24_speed[] = {
+ 96000, 88200, 64000, 48000, 44100, 32000, 24000, 22050, 16000,
+ 12000, 11025, 9600, 8000, 0
+};
+
+/* known boards configuration */
+static struct codec_entry delta_codec = {
+ envy24_delta_ak4524_create,
+ envy24_delta_ak4524_destroy,
+ envy24_delta_ak4524_init,
+ envy24_delta_ak4524_reinit,
+ envy24_delta_ak4524_setvolume,
+ NULL, /* setrate */
+};
+
+static struct cfg_info cfg_table[] = {
+ {
+ "Envy24 audio (M Audio Delta Dio 2496)",
+ 0x1412, 0xd631,
+ 0x10, 0x80, 0xf0, 0x03,
+ 0xff, 0x00, 0x00,
+ 0x10, 0x20, 0x40, 0x00, 0x00,
+ 0x00,
+ &delta_codec,
+ },
+ {
+ "Envy24 audio (Terratec DMX 6fire)",
+ 0x153b, 0x1138,
+ 0x2f, 0x80, 0xf0, 0x03,
+ 0xc0, 0xff, 0x7f,
+ 0x10, 0x20, 0x01, 0x01, 0x00,
+ 0x00,
+ &delta_codec,
+ },
+ {
+ "Envy24 audio (M Audio Audiophile 2496)",
+ 0x1412, 0xd634,
+ 0x10, 0x80, 0x72, 0x03,
+ 0x04, 0xfe, 0xfb,
+ 0x08, 0x02, 0x20, 0x00, 0x01,
+ 0x00,
+ &delta_codec,
+ },
+ {
+ "Envy24 audio (Generic)",
+ 0, 0,
+ 0x0f, 0x00, 0x01, 0x03,
+ 0xff, 0x00, 0x00,
+ 0x10, 0x20, 0x40, 0x00, 0x00,
+ 0x00,
+ &delta_codec, /* default codec routines */
+ }
+};
+
+static u_int32_t envy24_recfmt[] = {
+ AFMT_STEREO | AFMT_S16_LE,
+ AFMT_STEREO | AFMT_S32_LE,
+ 0
+};
+static struct pcmchan_caps envy24_reccaps = {8000, 96000, envy24_recfmt, 0};
+
+static u_int32_t envy24_playfmt[] = {
+ AFMT_STEREO | AFMT_U8,
+ AFMT_STEREO | AFMT_S16_LE,
+ AFMT_STEREO | AFMT_S32_LE,
+ 0
+};
+
+static struct pcmchan_caps envy24_playcaps = {8000, 96000, envy24_playfmt, 0};
+
+struct envy24_emldma {
+ u_int32_t format;
+ void (*emldma)(struct sc_chinfo *);
+ int unit;
+};
+
+static struct envy24_emldma envy24_pemltab[] = {
+ {AFMT_STEREO | AFMT_U8, envy24_p8u, 2},
+ {AFMT_STEREO | AFMT_S16_LE, envy24_p16sl, 4},
+ {AFMT_STEREO | AFMT_S32_LE, envy24_p32sl, 8},
+ {0, NULL, 0}
+};
+
+static struct envy24_emldma envy24_remltab[] = {
+ {AFMT_STEREO | AFMT_S16_LE, envy24_r16sl, 4},
+ {AFMT_STEREO | AFMT_S32_LE, envy24_r32sl, 8},
+ {0, NULL, 0}
+};
+
+/* -------------------------------------------------------------------- */
+
+/* common routines */
+static u_int32_t
+envy24_rdcs(struct sc_info *sc, int regno, int size)
+{
+ switch (size) {
+ case 1:
+ return bus_space_read_1(sc->cst, sc->csh, regno);
+ case 2:
+ return bus_space_read_2(sc->cst, sc->csh, regno);
+ case 4:
+ return bus_space_read_4(sc->cst, sc->csh, regno);
+ default:
+ return 0xffffffff;
+ }
+}
+
+static void
+envy24_wrcs(struct sc_info *sc, int regno, u_int32_t data, int size)
+{
+ switch (size) {
+ case 1:
+ bus_space_write_1(sc->cst, sc->csh, regno, data);
+ break;
+ case 2:
+ bus_space_write_2(sc->cst, sc->csh, regno, data);
+ break;
+ case 4:
+ bus_space_write_4(sc->cst, sc->csh, regno, data);
+ break;
+ }
+}
+
+static u_int32_t
+envy24_rdmt(struct sc_info *sc, int regno, int size)
+{
+ switch (size) {
+ case 1:
+ return bus_space_read_1(sc->mtt, sc->mth, regno);
+ case 2:
+ return bus_space_read_2(sc->mtt, sc->mth, regno);
+ case 4:
+ return bus_space_read_4(sc->mtt, sc->mth, regno);
+ default:
+ return 0xffffffff;
+ }
+}
+
+static void
+envy24_wrmt(struct sc_info *sc, int regno, u_int32_t data, int size)
+{
+ switch (size) {
+ case 1:
+ bus_space_write_1(sc->mtt, sc->mth, regno, data);
+ break;
+ case 2:
+ bus_space_write_2(sc->mtt, sc->mth, regno, data);
+ break;
+ case 4:
+ bus_space_write_4(sc->mtt, sc->mth, regno, data);
+ break;
+ }
+}
+
+static u_int32_t
+envy24_rdci(struct sc_info *sc, int regno)
+{
+ envy24_wrcs(sc, ENVY24_CCS_INDEX, regno, 1);
+ return envy24_rdcs(sc, ENVY24_CCS_DATA, 1);
+}
+
+static void
+envy24_wrci(struct sc_info *sc, int regno, u_int32_t data)
+{
+ envy24_wrcs(sc, ENVY24_CCS_INDEX, regno, 1);
+ envy24_wrcs(sc, ENVY24_CCS_DATA, data, 1);
+}
+
+/* -------------------------------------------------------------------- */
+
+/* I2C port/E2PROM access routines */
+
+static int
+envy24_rdi2c(struct sc_info *sc, u_int32_t dev, u_int32_t addr)
+{
+ u_int32_t data;
+ int i;
+
+#if(0)
+ device_printf(sc->dev, "envy24_rdi2c(sc, 0x%02x, 0x%02x)\n", dev, addr);
+#endif
+ for (i = 0; i < ENVY24_TIMEOUT; i++) {
+ data = envy24_rdcs(sc, ENVY24_CCS_I2CSTAT, 1);
+ if ((data & ENVY24_CCS_I2CSTAT_BSY) == 0)
+ break;
+ DELAY(32); /* 31.25kHz */
+ }
+ if (i == ENVY24_TIMEOUT) {
+ return -1;
+ }
+ envy24_wrcs(sc, ENVY24_CCS_I2CADDR, addr, 1);
+ envy24_wrcs(sc, ENVY24_CCS_I2CDEV,
+ (dev & ENVY24_CCS_I2CDEV_ADDR) | ENVY24_CCS_I2CDEV_RD, 1);
+ for (i = 0; i < ENVY24_TIMEOUT; i++) {
+ data = envy24_rdcs(sc, ENVY24_CCS_I2CSTAT, 1);
+ if ((data & ENVY24_CCS_I2CSTAT_BSY) == 0)
+ break;
+ DELAY(32); /* 31.25kHz */
+ }
+ if (i == ENVY24_TIMEOUT) {
+ return -1;
+ }
+ data = envy24_rdcs(sc, ENVY24_CCS_I2CDATA, 1);
+
+#if(0)
+ device_printf(sc->dev, "envy24_rdi2c(): return 0x%x\n", data);
+#endif
+ return (int)data;
+}
+
+#if 0
+static int
+envy24_wri2c(struct sc_info *sc, u_int32_t dev, u_int32_t addr, u_int32_t data)
+{
+ u_int32_t tmp;
+ int i;
+
+#if(0)
+ device_printf(sc->dev, "envy24_rdi2c(sc, 0x%02x, 0x%02x)\n", dev, addr);
+#endif
+ for (i = 0; i < ENVY24_TIMEOUT; i++) {
+ tmp = envy24_rdcs(sc, ENVY24_CCS_I2CSTAT, 1);
+ if ((tmp & ENVY24_CCS_I2CSTAT_BSY) == 0)
+ break;
+ DELAY(32); /* 31.25kHz */
+ }
+ if (i == ENVY24_TIMEOUT) {
+ return -1;
+ }
+ envy24_wrcs(sc, ENVY24_CCS_I2CADDR, addr, 1);
+ envy24_wrcs(sc, ENVY24_CCS_I2CDATA, data, 1);
+ envy24_wrcs(sc, ENVY24_CCS_I2CDEV,
+ (dev & ENVY24_CCS_I2CDEV_ADDR) | ENVY24_CCS_I2CDEV_WR, 1);
+ for (i = 0; i < ENVY24_TIMEOUT; i++) {
+ data = envy24_rdcs(sc, ENVY24_CCS_I2CSTAT, 1);
+ if ((data & ENVY24_CCS_I2CSTAT_BSY) == 0)
+ break;
+ DELAY(32); /* 31.25kHz */
+ }
+ if (i == ENVY24_TIMEOUT) {
+ return -1;
+ }
+
+ return 0;
+}
+#endif
+
+static int
+envy24_rdrom(struct sc_info *sc, u_int32_t addr)
+{
+ u_int32_t data;
+
+#if(0)
+ device_printf(sc->dev, "envy24_rdrom(sc, 0x%02x)\n", addr);
+#endif
+ data = envy24_rdcs(sc, ENVY24_CCS_I2CSTAT, 1);
+ if ((data & ENVY24_CCS_I2CSTAT_ROM) == 0) {
+#if(0)
+ device_printf(sc->dev, "envy24_rdrom(): E2PROM not presented\n");
+#endif
+ return -1;
+ }
+
+ return envy24_rdi2c(sc, ENVY24_CCS_I2CDEV_ROM, addr);
+}
+
+static struct cfg_info *
+envy24_rom2cfg(struct sc_info *sc)
+{
+ struct cfg_info *buff;
+ int size;
+ int i;
+
+#if(0)
+ device_printf(sc->dev, "envy24_rom2cfg(sc)\n");
+#endif
+ size = envy24_rdrom(sc, ENVY24_E2PROM_SIZE);
+ if (size < ENVY24_E2PROM_GPIODIR + 1) {
+#if(0)
+ device_printf(sc->dev, "envy24_rom2cfg(): ENVY24_E2PROM_SIZE-->%d\n", size);
+#endif
+ return NULL;
+ }
+ buff = malloc(sizeof(*buff), M_ENVY24, M_NOWAIT);
+ if (buff == NULL) {
+#if(0)
+ device_printf(sc->dev, "envy24_rom2cfg(): malloc()\n");
+#endif
+ return NULL;
+ }
+ buff->free = 1;
+
+ buff->subvendor = envy24_rdrom(sc, ENVY24_E2PROM_SUBVENDOR) << 8;
+ buff->subvendor += envy24_rdrom(sc, ENVY24_E2PROM_SUBVENDOR + 1);
+ buff->subdevice = envy24_rdrom(sc, ENVY24_E2PROM_SUBDEVICE) << 8;
+ buff->subdevice += envy24_rdrom(sc, ENVY24_E2PROM_SUBDEVICE + 1);
+ buff->scfg = envy24_rdrom(sc, ENVY24_E2PROM_SCFG);
+ buff->acl = envy24_rdrom(sc, ENVY24_E2PROM_ACL);
+ buff->i2s = envy24_rdrom(sc, ENVY24_E2PROM_I2S);
+ buff->spdif = envy24_rdrom(sc, ENVY24_E2PROM_SPDIF);
+ buff->gpiomask = envy24_rdrom(sc, ENVY24_E2PROM_GPIOMASK);
+ buff->gpiostate = envy24_rdrom(sc, ENVY24_E2PROM_GPIOSTATE);
+ buff->gpiodir = envy24_rdrom(sc, ENVY24_E2PROM_GPIODIR);
+
+ for (i = 0; cfg_table[i].subvendor != 0 || cfg_table[i].subdevice != 0; i++)
+ if (cfg_table[i].subvendor == buff->subvendor &&
+ cfg_table[i].subdevice == buff->subdevice)
+ break;
+ buff->name = cfg_table[i].name;
+ buff->codec = cfg_table[i].codec;
+
+ return buff;
+}
+
+static void
+envy24_cfgfree(struct cfg_info *cfg) {
+ if (cfg == NULL)
+ return;
+ if (cfg->free)
+ free(cfg, M_ENVY24);
+ return;
+}
+
+/* -------------------------------------------------------------------- */
+
+/* AC'97 codec access routines */
+
+#if 0
+static int
+envy24_coldcd(struct sc_info *sc)
+{
+ u_int32_t data;
+ int i;
+
+#if(0)
+ device_printf(sc->dev, "envy24_coldcd()\n");
+#endif
+ envy24_wrmt(sc, ENVY24_MT_AC97CMD, ENVY24_MT_AC97CMD_CLD, 1);
+ DELAY(10);
+ envy24_wrmt(sc, ENVY24_MT_AC97CMD, 0, 1);
+ DELAY(1000);
+ for (i = 0; i < ENVY24_TIMEOUT; i++) {
+ data = envy24_rdmt(sc, ENVY24_MT_AC97CMD, 1);
+ if (data & ENVY24_MT_AC97CMD_RDY) {
+ return 0;
+ }
+ }
+
+ return -1;
+}
+#endif
+
+static int
+envy24_slavecd(struct sc_info *sc)
+{
+ u_int32_t data;
+ int i;
+
+#if(0)
+ device_printf(sc->dev, "envy24_slavecd()\n");
+#endif
+ envy24_wrmt(sc, ENVY24_MT_AC97CMD,
+ ENVY24_MT_AC97CMD_CLD | ENVY24_MT_AC97CMD_WRM, 1);
+ DELAY(10);
+ envy24_wrmt(sc, ENVY24_MT_AC97CMD, 0, 1);
+ DELAY(1000);
+ for (i = 0; i < ENVY24_TIMEOUT; i++) {
+ data = envy24_rdmt(sc, ENVY24_MT_AC97CMD, 1);
+ if (data & ENVY24_MT_AC97CMD_RDY) {
+ return 0;
+ }
+ }
+
+ return -1;
+}
+
+#if 0
+static int
+envy24_rdcd(kobj_t obj, void *devinfo, int regno)
+{
+ struct sc_info *sc = (struct sc_info *)devinfo;
+ u_int32_t data;
+ int i;
+
+#if(0)
+ device_printf(sc->dev, "envy24_rdcd(obj, sc, 0x%02x)\n", regno);
+#endif
+ envy24_wrmt(sc, ENVY24_MT_AC97IDX, (u_int32_t)regno, 1);
+ envy24_wrmt(sc, ENVY24_MT_AC97CMD, ENVY24_MT_AC97CMD_RD, 1);
+ for (i = 0; i < ENVY24_TIMEOUT; i++) {
+ data = envy24_rdmt(sc, ENVY24_MT_AC97CMD, 1);
+ if ((data & ENVY24_MT_AC97CMD_RD) == 0)
+ break;
+ }
+ data = envy24_rdmt(sc, ENVY24_MT_AC97DLO, 2);
+
+#if(0)
+ device_printf(sc->dev, "envy24_rdcd(): return 0x%x\n", data);
+#endif
+ return (int)data;
+}
+
+static int
+envy24_wrcd(kobj_t obj, void *devinfo, int regno, u_int16_t data)
+{
+ struct sc_info *sc = (struct sc_info *)devinfo;
+ u_int32_t cmd;
+ int i;
+
+#if(0)
+ device_printf(sc->dev, "envy24_wrcd(obj, sc, 0x%02x, 0x%04x)\n", regno, data);
+#endif
+ envy24_wrmt(sc, ENVY24_MT_AC97IDX, (u_int32_t)regno, 1);
+ envy24_wrmt(sc, ENVY24_MT_AC97DLO, (u_int32_t)data, 2);
+ envy24_wrmt(sc, ENVY24_MT_AC97CMD, ENVY24_MT_AC97CMD_WR, 1);
+ for (i = 0; i < ENVY24_TIMEOUT; i++) {
+ cmd = envy24_rdmt(sc, ENVY24_MT_AC97CMD, 1);
+ if ((cmd & ENVY24_MT_AC97CMD_WR) == 0)
+ break;
+ }
+
+ return 0;
+}
+
+static kobj_method_t envy24_ac97_methods[] = {
+ KOBJMETHOD(ac97_read, envy24_rdcd),
+ KOBJMETHOD(ac97_write, envy24_wrcd),
+ {0, 0}
+};
+AC97_DECLARE(envy24_ac97);
+#endif
+
+/* -------------------------------------------------------------------- */
+
+/* GPIO access routines */
+
+static u_int32_t
+envy24_gpiord(struct sc_info *sc)
+{
+ return envy24_rdci(sc, ENVY24_CCI_GPIODAT);
+}
+
+static void
+envy24_gpiowr(struct sc_info *sc, u_int32_t data)
+{
+#if(0)
+ device_printf(sc->dev, "envy24_gpiowr(sc, 0x%02x)\n", data & 0xff);
+ return;
+#endif
+ envy24_wrci(sc, ENVY24_CCI_GPIODAT, data);
+ return;
+}
+
+#if 0
+static u_int32_t
+envy24_gpiogetmask(struct sc_info *sc)
+{
+ return envy24_rdci(sc, ENVY24_CCI_GPIOMASK);
+}
+#endif
+
+static void
+envy24_gpiosetmask(struct sc_info *sc, u_int32_t mask)
+{
+ envy24_wrci(sc, ENVY24_CCI_GPIOMASK, mask);
+ return;
+}
+
+#if 0
+static u_int32_t
+envy24_gpiogetdir(struct sc_info *sc)
+{
+ return envy24_rdci(sc, ENVY24_CCI_GPIOCTL);
+}
+#endif
+
+static void
+envy24_gpiosetdir(struct sc_info *sc, u_int32_t dir)
+{
+ envy24_wrci(sc, ENVY24_CCI_GPIOCTL, dir);
+ return;
+}
+
+/* -------------------------------------------------------------------- */
+
+/* Envy24 I2C through GPIO bit-banging */
+
+struct envy24_delta_ak4524_codec {
+ struct spicds_info *info;
+ struct sc_info *parent;
+ int dir;
+ int num;
+ int cs, cclk, cdti;
+};
+
+static void
+envy24_gpio_i2c_ctl(void *codec, unsigned int scl, unsigned int sda)
+{
+ u_int32_t data = 0;
+ struct envy24_delta_ak4524_codec *ptr = codec;
+#if(0)
+ device_printf(ptr->parent->dev, "--> %d, %d\n", scl, sda);
+#endif
+ data = envy24_gpiord(ptr->parent);
+ data &= ~(SDA_GPIO | SCL_GPIO);
+ if (scl) data += SCL_GPIO;
+ if (sda) data += SDA_GPIO;
+ envy24_gpiowr(ptr->parent, data);
+ return;
+}
+
+static void
+i2c_wrbit(void *codec, void (*ctrl)(void*, unsigned int, unsigned int), int bit)
+{
+ struct envy24_delta_ak4524_codec *ptr = codec;
+ unsigned int sda;
+
+ if (bit)
+ sda = 1;
+ else
+ sda = 0;
+
+ ctrl(ptr, 0, sda);
+ DELAY(I2C_DELAY);
+ ctrl(ptr, 1, sda);
+ DELAY(I2C_DELAY);
+ ctrl(ptr, 0, sda);
+ DELAY(I2C_DELAY);
+}
+
+static void
+i2c_start(void *codec, void (*ctrl)(void*, unsigned int, unsigned int))
+{
+ struct envy24_delta_ak4524_codec *ptr = codec;
+
+ ctrl(ptr, 1, 1);
+ DELAY(I2C_DELAY);
+ ctrl(ptr, 1, 0);
+ DELAY(I2C_DELAY);
+ ctrl(ptr, 0, 0);
+ DELAY(I2C_DELAY);
+}
+
+static void
+i2c_stop(void *codec, void (*ctrl)(void*, unsigned int, unsigned int))
+{
+ struct envy24_delta_ak4524_codec *ptr = codec;
+
+ ctrl(ptr, 0, 0);
+ DELAY(I2C_DELAY);
+ ctrl(ptr, 1, 0);
+ DELAY(I2C_DELAY);
+ ctrl(ptr, 1, 1);
+ DELAY(I2C_DELAY);
+}
+
+static void
+i2c_ack(void *codec, void (*ctrl)(void*, unsigned int, unsigned int))
+{
+ struct envy24_delta_ak4524_codec *ptr = codec;
+
+ ctrl(ptr, 0, 1);
+ DELAY(I2C_DELAY);
+ ctrl(ptr, 1, 1);
+ DELAY(I2C_DELAY);
+ /* dummy, need routine to change gpio direction */
+ ctrl(ptr, 0, 1);
+ DELAY(I2C_DELAY);
+}
+
+static void
+i2c_wr(void *codec, void (*ctrl)(void*, unsigned int, unsigned int), u_int32_t dev, int reg, u_int8_t val)
+{
+ struct envy24_delta_ak4524_codec *ptr = codec;
+ int mask;
+
+ i2c_start(ptr, ctrl);
+
+ for (mask = 0x80; mask != 0; mask >>= 1)
+ i2c_wrbit(ptr, ctrl, dev & mask);
+ i2c_ack(ptr, ctrl);
+
+ if (reg != 0xff) {
+ for (mask = 0x80; mask != 0; mask >>= 1)
+ i2c_wrbit(ptr, ctrl, reg & mask);
+ i2c_ack(ptr, ctrl);
+ }
+
+ for (mask = 0x80; mask != 0; mask >>= 1)
+ i2c_wrbit(ptr, ctrl, val & mask);
+ i2c_ack(ptr, ctrl);
+
+ i2c_stop(ptr, ctrl);
+}
+
+/* -------------------------------------------------------------------- */
+
+/* M-Audio Delta series AK4524 access interface routine */
+
+static void
+envy24_delta_ak4524_ctl(void *codec, unsigned int cs, unsigned int cclk, unsigned int cdti)
+{
+ u_int32_t data = 0;
+ struct envy24_delta_ak4524_codec *ptr = codec;
+
+#if(0)
+ device_printf(ptr->parent->dev, "--> %d, %d, %d\n", cs, cclk, cdti);
+#endif
+ data = envy24_gpiord(ptr->parent);
+ data &= ~(ptr->cs | ptr->cclk | ptr->cdti);
+ if (cs) data += ptr->cs;
+ if (cclk) data += ptr->cclk;
+ if (cdti) data += ptr->cdti;
+ envy24_gpiowr(ptr->parent, data);
+ return;
+}
+
+static void *
+envy24_delta_ak4524_create(device_t dev, void *info, int dir, int num)
+{
+ struct sc_info *sc = info;
+ struct envy24_delta_ak4524_codec *buff = NULL;
+
+#if(0)
+ device_printf(sc->dev, "envy24_delta_ak4524_create(dev, sc, %d, %d)\n", dir, num);
+#endif
+
+ buff = malloc(sizeof(*buff), M_ENVY24, M_NOWAIT);
+ if (buff == NULL)
+ return NULL;
+
+ if (dir == PCMDIR_REC && sc->adc[num] != NULL)
+ buff->info = ((struct envy24_delta_ak4524_codec *)sc->adc[num])->info;
+ else if (dir == PCMDIR_PLAY && sc->dac[num] != NULL)
+ buff->info = ((struct envy24_delta_ak4524_codec *)sc->dac[num])->info;
+ else
+ buff->info = spicds_create(dev, buff, num, envy24_delta_ak4524_ctl);
+ if (buff->info == NULL) {
+ free(buff, M_ENVY24);
+ return NULL;
+ }
+
+ buff->parent = sc;
+ buff->dir = dir;
+ buff->num = num;
+
+ return (void *)buff;
+}
+
+static void
+envy24_delta_ak4524_destroy(void *codec)
+{
+ struct envy24_delta_ak4524_codec *ptr = codec;
+ if (ptr == NULL)
+ return;
+#if(0)
+ device_printf(ptr->parent->dev, "envy24_delta_ak4524_destroy()\n");
+#endif
+
+ if (ptr->dir == PCMDIR_PLAY) {
+ if (ptr->parent->dac[ptr->num] != NULL)
+ spicds_destroy(ptr->info);
+ }
+ else {
+ if (ptr->parent->adc[ptr->num] != NULL)
+ spicds_destroy(ptr->info);
+ }
+
+ free(codec, M_ENVY24);
+}
+
+static void
+envy24_delta_ak4524_init(void *codec)
+{
+#if 0
+ u_int32_t gpiomask, gpiodir;
+#endif
+ struct envy24_delta_ak4524_codec *ptr = codec;
+ if (ptr == NULL)
+ return;
+#if(0)
+ device_printf(ptr->parent->dev, "envy24_delta_ak4524_init()\n");
+#endif
+
+ /*
+ gpiomask = envy24_gpiogetmask(ptr->parent);
+ gpiomask &= ~(ENVY24_GPIO_AK4524_CDTI | ENVY24_GPIO_AK4524_CCLK | ENVY24_GPIO_AK4524_CS0 | ENVY24_GPIO_AK4524_CS1);
+ envy24_gpiosetmask(ptr->parent, gpiomask);
+ gpiodir = envy24_gpiogetdir(ptr->parent);
+ gpiodir |= ENVY24_GPIO_AK4524_CDTI | ENVY24_GPIO_AK4524_CCLK | ENVY24_GPIO_AK4524_CS0 | ENVY24_GPIO_AK4524_CS1;
+ envy24_gpiosetdir(ptr->parent, gpiodir);
+ */
+ ptr->cs = ptr->parent->cfg->cs;
+#if 0
+ envy24_gpiosetmask(ptr->parent, ENVY24_GPIO_CS8414_STATUS);
+ envy24_gpiosetdir(ptr->parent, ~ENVY24_GPIO_CS8414_STATUS);
+ if (ptr->num == 0)
+ ptr->cs = ENVY24_GPIO_AK4524_CS0;
+ else
+ ptr->cs = ENVY24_GPIO_AK4524_CS1;
+ ptr->cclk = ENVY24_GPIO_AK4524_CCLK;
+#endif
+ ptr->cclk = ptr->parent->cfg->cclk;
+ ptr->cdti = ptr->parent->cfg->cdti;
+ spicds_settype(ptr->info, ptr->parent->cfg->type);
+ spicds_setcif(ptr->info, ptr->parent->cfg->cif);
+ spicds_setformat(ptr->info,
+ AK452X_FORMAT_I2S | AK452X_FORMAT_256FSN | AK452X_FORMAT_1X);
+ spicds_setdvc(ptr->info, AK452X_DVC_DEMOFF);
+ /* for the time being, init only first codec */
+ if (ptr->num == 0)
+ spicds_init(ptr->info);
+
+ /* 6fire rear input init test, set ptr->num to 1 for test */
+ if (ptr->parent->cfg->subvendor == 0x153b && \
+ ptr->parent->cfg->subdevice == 0x1138 && ptr->num == 100) {
+ ptr->cs = 0x02;
+ spicds_init(ptr->info);
+ device_printf(ptr->parent->dev, "6fire rear input init\n");
+ i2c_wr(ptr, envy24_gpio_i2c_ctl, \
+ PCA9554_I2CDEV, PCA9554_DIR, 0x80);
+ i2c_wr(ptr, envy24_gpio_i2c_ctl, \
+ PCA9554_I2CDEV, PCA9554_OUT, 0x02);
+ }
+}
+
+static void
+envy24_delta_ak4524_reinit(void *codec)
+{
+ struct envy24_delta_ak4524_codec *ptr = codec;
+ if (ptr == NULL)
+ return;
+#if(0)
+ device_printf(ptr->parent->dev, "envy24_delta_ak4524_reinit()\n");
+#endif
+
+ spicds_reinit(ptr->info);
+}
+
+static void
+envy24_delta_ak4524_setvolume(void *codec, int dir, unsigned int left, unsigned int right)
+{
+ struct envy24_delta_ak4524_codec *ptr = codec;
+ if (ptr == NULL)
+ return;
+#if(0)
+ device_printf(ptr->parent->dev, "envy24_delta_ak4524_set()\n");
+#endif
+
+ spicds_set(ptr->info, dir, left, right);
+}
+
+/*
+ There is no need for AK452[48] codec to set sample rate
+ static void
+ envy24_delta_ak4524_setrate(struct envy24_delta_ak4524_codec *codec, int which, int rate)
+ {
+ }
+*/
+
+/* -------------------------------------------------------------------- */
+
+/* hardware access routeines */
+
+static struct {
+ u_int32_t speed;
+ u_int32_t code;
+} envy24_speedtab[] = {
+ {48000, ENVY24_MT_RATE_48000},
+ {24000, ENVY24_MT_RATE_24000},
+ {12000, ENVY24_MT_RATE_12000},
+ {9600, ENVY24_MT_RATE_9600},
+ {32000, ENVY24_MT_RATE_32000},
+ {16000, ENVY24_MT_RATE_16000},
+ {8000, ENVY24_MT_RATE_8000},
+ {96000, ENVY24_MT_RATE_96000},
+ {64000, ENVY24_MT_RATE_64000},
+ {44100, ENVY24_MT_RATE_44100},
+ {22050, ENVY24_MT_RATE_22050},
+ {11025, ENVY24_MT_RATE_11025},
+ {88200, ENVY24_MT_RATE_88200},
+ {0, 0x10}
+};
+
+static int
+envy24_setspeed(struct sc_info *sc, u_int32_t speed) {
+ u_int32_t code;
+ int i = 0;
+
+#if(0)
+ device_printf(sc->dev, "envy24_setspeed(sc, %d)\n", speed);
+#endif
+ if (speed == 0) {
+ code = ENVY24_MT_RATE_SPDIF; /* external master clock */
+ envy24_slavecd(sc);
+ }
+ else {
+ for (i = 0; envy24_speedtab[i].speed != 0; i++) {
+ if (envy24_speedtab[i].speed == speed)
+ break;
+ }
+ code = envy24_speedtab[i].code;
+ }
+#if(0)
+ device_printf(sc->dev, "envy24_setspeed(): speed %d/code 0x%04x\n", envy24_speedtab[i].speed, code);
+#endif
+ if (code < 0x10) {
+ envy24_wrmt(sc, ENVY24_MT_RATE, code, 1);
+ code = envy24_rdmt(sc, ENVY24_MT_RATE, 1);
+ code &= ENVY24_MT_RATE_MASK;
+ for (i = 0; envy24_speedtab[i].code < 0x10; i++) {
+ if (envy24_speedtab[i].code == code)
+ break;
+ }
+ speed = envy24_speedtab[i].speed;
+ }
+ else
+ speed = 0;
+
+#if(0)
+ device_printf(sc->dev, "envy24_setspeed(): return %d\n", speed);
+#endif
+ return speed;
+}
+
+static void
+envy24_setvolume(struct sc_info *sc, unsigned ch)
+{
+#if(0)
+ device_printf(sc->dev, "envy24_setvolume(sc, %d)\n", ch);
+#endif
+if (sc->cfg->subvendor==0x153b && sc->cfg->subdevice==0x1138 ) {
+ envy24_wrmt(sc, ENVY24_MT_VOLIDX, 16, 1);
+ envy24_wrmt(sc, ENVY24_MT_VOLUME, 0x7f7f, 2);
+ envy24_wrmt(sc, ENVY24_MT_VOLIDX, 17, 1);
+ envy24_wrmt(sc, ENVY24_MT_VOLUME, 0x7f7f, 2);
+ }
+
+ envy24_wrmt(sc, ENVY24_MT_VOLIDX, ch * 2, 1);
+ envy24_wrmt(sc, ENVY24_MT_VOLUME, 0x7f00 | sc->left[ch], 2);
+ envy24_wrmt(sc, ENVY24_MT_VOLIDX, ch * 2 + 1, 1);
+ envy24_wrmt(sc, ENVY24_MT_VOLUME, (sc->right[ch] << 8) | 0x7f, 2);
+}
+
+static void
+envy24_mutevolume(struct sc_info *sc, unsigned ch)
+{
+ u_int32_t vol;
+
+#if(0)
+ device_printf(sc->dev, "envy24_mutevolume(sc, %d)\n", ch);
+#endif
+ vol = ENVY24_VOL_MUTE << 8 | ENVY24_VOL_MUTE;
+ envy24_wrmt(sc, ENVY24_MT_VOLIDX, ch * 2, 1);
+ envy24_wrmt(sc, ENVY24_MT_VOLUME, vol, 2);
+ envy24_wrmt(sc, ENVY24_MT_VOLIDX, ch * 2 + 1, 1);
+ envy24_wrmt(sc, ENVY24_MT_VOLUME, vol, 2);
+}
+
+static u_int32_t
+envy24_gethwptr(struct sc_info *sc, int dir)
+{
+ int unit, regno;
+ u_int32_t ptr, rtn;
+
+#if(0)
+ device_printf(sc->dev, "envy24_gethwptr(sc, %d)\n", dir);
+#endif
+ if (dir == PCMDIR_PLAY) {
+ rtn = sc->psize / 4;
+ unit = ENVY24_PLAY_BUFUNIT / 4;
+ regno = ENVY24_MT_PCNT;
+ }
+ else {
+ rtn = sc->rsize / 4;
+ unit = ENVY24_REC_BUFUNIT / 4;
+ regno = ENVY24_MT_RCNT;
+ }
+
+ ptr = envy24_rdmt(sc, regno, 2);
+ rtn -= (ptr + 1);
+ rtn /= unit;
+
+#if(0)
+ device_printf(sc->dev, "envy24_gethwptr(): return %d\n", rtn);
+#endif
+ return rtn;
+}
+
+static void
+envy24_updintr(struct sc_info *sc, int dir)
+{
+ int regptr, regintr;
+ u_int32_t mask, intr;
+ u_int32_t ptr, size, cnt;
+ u_int16_t blk;
+
+#if(0)
+ device_printf(sc->dev, "envy24_updintr(sc, %d)\n", dir);
+#endif
+ if (dir == PCMDIR_PLAY) {
+ blk = sc->blk[0];
+ size = sc->psize / 4;
+ regptr = ENVY24_MT_PCNT;
+ regintr = ENVY24_MT_PTERM;
+ mask = ~ENVY24_MT_INT_PMASK;
+ }
+ else {
+ blk = sc->blk[1];
+ size = sc->rsize / 4;
+ regptr = ENVY24_MT_RCNT;
+ regintr = ENVY24_MT_RTERM;
+ mask = ~ENVY24_MT_INT_RMASK;
+ }
+
+ ptr = size - envy24_rdmt(sc, regptr, 2) - 1;
+ /*
+ cnt = blk - ptr % blk - 1;
+ if (cnt == 0)
+ cnt = blk - 1;
+ */
+ cnt = blk - 1;
+#if(0)
+ device_printf(sc->dev, "envy24_updintr():ptr = %d, blk = %d, cnt = %d\n", ptr, blk, cnt);
+#endif
+ envy24_wrmt(sc, regintr, cnt, 2);
+ intr = envy24_rdmt(sc, ENVY24_MT_INT, 1);
+#if(0)
+ device_printf(sc->dev, "envy24_updintr():intr = 0x%02x, mask = 0x%02x\n", intr, mask);
+#endif
+ envy24_wrmt(sc, ENVY24_MT_INT, intr & mask, 1);
+#if(0)
+ device_printf(sc->dev, "envy24_updintr():INT-->0x%02x\n",
+ envy24_rdmt(sc, ENVY24_MT_INT, 1));
+#endif
+
+ return;
+}
+
+#if 0
+static void
+envy24_maskintr(struct sc_info *sc, int dir)
+{
+ u_int32_t mask, intr;
+
+#if(0)
+ device_printf(sc->dev, "envy24_maskintr(sc, %d)\n", dir);
+#endif
+ if (dir == PCMDIR_PLAY)
+ mask = ENVY24_MT_INT_PMASK;
+ else
+ mask = ENVY24_MT_INT_RMASK;
+ intr = envy24_rdmt(sc, ENVY24_MT_INT, 1);
+ envy24_wrmt(sc, ENVY24_MT_INT, intr | mask, 1);
+
+ return;
+}
+#endif
+
+static int
+envy24_checkintr(struct sc_info *sc, int dir)
+{
+ u_int32_t mask, stat, intr, rtn;
+
+#if(0)
+ device_printf(sc->dev, "envy24_checkintr(sc, %d)\n", dir);
+#endif
+ intr = envy24_rdmt(sc, ENVY24_MT_INT, 1);
+ if (dir == PCMDIR_PLAY) {
+ if ((rtn = intr & ENVY24_MT_INT_PSTAT) != 0) {
+ mask = ~ENVY24_MT_INT_RSTAT;
+ stat = ENVY24_MT_INT_PSTAT | ENVY24_MT_INT_PMASK;
+ envy24_wrmt(sc, ENVY24_MT_INT, (intr & mask) | stat, 1);
+ }
+ }
+ else {
+ if ((rtn = intr & ENVY24_MT_INT_RSTAT) != 0) {
+ mask = ~ENVY24_MT_INT_PSTAT;
+ stat = ENVY24_MT_INT_RSTAT | ENVY24_MT_INT_RMASK;
+ envy24_wrmt(sc, ENVY24_MT_INT, (intr & mask) | stat, 1);
+ }
+ }
+
+ return rtn;
+}
+
+static void
+envy24_start(struct sc_info *sc, int dir)
+{
+ u_int32_t stat, sw;
+
+#if(0)
+ device_printf(sc->dev, "envy24_start(sc, %d)\n", dir);
+#endif
+ if (dir == PCMDIR_PLAY)
+ sw = ENVY24_MT_PCTL_PSTART;
+ else
+ sw = ENVY24_MT_PCTL_RSTART;
+
+ stat = envy24_rdmt(sc, ENVY24_MT_PCTL, 1);
+ envy24_wrmt(sc, ENVY24_MT_PCTL, stat | sw, 1);
+#if(0)
+ DELAY(100);
+ device_printf(sc->dev, "PADDR:0x%08x\n", envy24_rdmt(sc, ENVY24_MT_PADDR, 4));
+ device_printf(sc->dev, "PCNT:%ld\n", envy24_rdmt(sc, ENVY24_MT_PCNT, 2));
+#endif
+
+ return;
+}
+
+static void
+envy24_stop(struct sc_info *sc, int dir)
+{
+ u_int32_t stat, sw;
+
+#if(0)
+ device_printf(sc->dev, "envy24_stop(sc, %d)\n", dir);
+#endif
+ if (dir == PCMDIR_PLAY)
+ sw = ~ENVY24_MT_PCTL_PSTART;
+ else
+ sw = ~ENVY24_MT_PCTL_RSTART;
+
+ stat = envy24_rdmt(sc, ENVY24_MT_PCTL, 1);
+ envy24_wrmt(sc, ENVY24_MT_PCTL, stat & sw, 1);
+
+ return;
+}
+
+static int
+envy24_route(struct sc_info *sc, int dac, int class, int adc, int rev)
+{
+ u_int32_t reg, mask;
+ u_int32_t left, right;
+
+#if(0)
+ device_printf(sc->dev, "envy24_route(sc, %d, %d, %d, %d)\n",
+ dac, class, adc, rev);
+#endif
+ /* parameter pattern check */
+ if (dac < 0 || ENVY24_ROUTE_DAC_SPDIF < dac)
+ return -1;
+ if (class == ENVY24_ROUTE_CLASS_MIX &&
+ (dac != ENVY24_ROUTE_DAC_1 && dac != ENVY24_ROUTE_DAC_SPDIF))
+ return -1;
+ if (rev) {
+ left = ENVY24_ROUTE_RIGHT;
+ right = ENVY24_ROUTE_LEFT;
+ }
+ else {
+ left = ENVY24_ROUTE_LEFT;
+ right = ENVY24_ROUTE_RIGHT;
+ }
+
+ if (dac == ENVY24_ROUTE_DAC_SPDIF) {
+ reg = class | class << 2 |
+ ((adc << 1 | left) | left << 3) << 8 |
+ ((adc << 1 | right) | right << 3) << 12;
+#if(0)
+ device_printf(sc->dev, "envy24_route(): MT_SPDOUT-->0x%04x\n", reg);
+#endif
+ envy24_wrmt(sc, ENVY24_MT_SPDOUT, reg, 2);
+ }
+ else {
+ mask = ~(0x0303 << dac * 2);
+ reg = envy24_rdmt(sc, ENVY24_MT_PSDOUT, 2);
+ reg = (reg & mask) | ((class | class << 8) << dac * 2);
+#if(0)
+ device_printf(sc->dev, "envy24_route(): MT_PSDOUT-->0x%04x\n", reg);
+#endif
+ envy24_wrmt(sc, ENVY24_MT_PSDOUT, reg, 2);
+ mask = ~(0xff << dac * 8);
+ reg = envy24_rdmt(sc, ENVY24_MT_RECORD, 4);
+ reg = (reg & mask) |
+ (((adc << 1 | left) | left << 3) |
+ ((adc << 1 | right) | right << 3) << 4) << dac * 8;
+#if(0)
+ device_printf(sc->dev, "envy24_route(): MT_RECORD-->0x%08x\n", reg);
+#endif
+ envy24_wrmt(sc, ENVY24_MT_RECORD, reg, 4);
+
+ /* 6fire rear input init test */
+ envy24_wrmt(sc, ENVY24_MT_RECORD, 0x00, 4);
+ }
+
+ return 0;
+}
+
+/* -------------------------------------------------------------------- */
+
+/* buffer copy routines */
+static void
+envy24_p32sl(struct sc_chinfo *ch)
+{
+ int length;
+ sample32_t *dmabuf;
+ u_int32_t *data;
+ int src, dst, ssize, dsize, slot;
+ int i;
+
+ length = sndbuf_getready(ch->buffer) / 8;
+ dmabuf = ch->parent->pbuf;
+ data = (u_int32_t *)ch->data;
+ src = sndbuf_getreadyptr(ch->buffer) / 4;
+ dst = src / 2 + ch->offset;
+ ssize = ch->size / 4;
+ dsize = ch->size / 8;
+ slot = ch->num * 2;
+
+ for (i = 0; i < length; i++) {
+ dmabuf[dst * ENVY24_PLAY_CHNUM + slot].buffer = data[src];
+ dmabuf[dst * ENVY24_PLAY_CHNUM + slot + 1].buffer = data[src + 1];
+ dst++;
+ dst %= dsize;
+ src += 2;
+ src %= ssize;
+ }
+
+ return;
+}
+
+static void
+envy24_p16sl(struct sc_chinfo *ch)
+{
+ int length;
+ sample32_t *dmabuf;
+ u_int16_t *data;
+ int src, dst, ssize, dsize, slot;
+ int i;
+
+#if(0)
+ device_printf(ch->parent->dev, "envy24_p16sl()\n");
+#endif
+ length = sndbuf_getready(ch->buffer) / 4;
+ dmabuf = ch->parent->pbuf;
+ data = (u_int16_t *)ch->data;
+ src = sndbuf_getreadyptr(ch->buffer) / 2;
+ dst = src / 2 + ch->offset;
+ ssize = ch->size / 2;
+ dsize = ch->size / 4;
+ slot = ch->num * 2;
+#if(0)
+ device_printf(ch->parent->dev, "envy24_p16sl():%lu-->%lu(%lu)\n", src, dst, length);
+#endif
+
+ for (i = 0; i < length; i++) {
+ dmabuf[dst * ENVY24_PLAY_CHNUM + slot].buffer = (u_int32_t)data[src] << 16;
+ dmabuf[dst * ENVY24_PLAY_CHNUM + slot + 1].buffer = (u_int32_t)data[src + 1] << 16;
+#if(0)
+ if (i < 16) {
+ printf("%08x", dmabuf[dst * ENVY24_PLAY_CHNUM + slot]);
+ printf("%08x", dmabuf[dst * ENVY24_PLAY_CHNUM + slot + 1]);
+ }
+#endif
+ dst++;
+ dst %= dsize;
+ src += 2;
+ src %= ssize;
+ }
+#if(0)
+ printf("\n");
+#endif
+
+ return;
+}
+
+static void
+envy24_p8u(struct sc_chinfo *ch)
+{
+ int length;
+ sample32_t *dmabuf;
+ u_int8_t *data;
+ int src, dst, ssize, dsize, slot;
+ int i;
+
+ length = sndbuf_getready(ch->buffer) / 2;
+ dmabuf = ch->parent->pbuf;
+ data = (u_int8_t *)ch->data;
+ src = sndbuf_getreadyptr(ch->buffer);
+ dst = src / 2 + ch->offset;
+ ssize = ch->size;
+ dsize = ch->size / 4;
+ slot = ch->num * 2;
+
+ for (i = 0; i < length; i++) {
+ dmabuf[dst * ENVY24_PLAY_CHNUM + slot].buffer = ((u_int32_t)data[src] ^ 0x80) << 24;
+ dmabuf[dst * ENVY24_PLAY_CHNUM + slot + 1].buffer = ((u_int32_t)data[src + 1] ^ 0x80) << 24;
+ dst++;
+ dst %= dsize;
+ src += 2;
+ src %= ssize;
+ }
+
+ return;
+}
+
+static void
+envy24_r32sl(struct sc_chinfo *ch)
+{
+ int length;
+ sample32_t *dmabuf;
+ u_int32_t *data;
+ int src, dst, ssize, dsize, slot;
+ int i;
+
+ length = sndbuf_getfree(ch->buffer) / 8;
+ dmabuf = ch->parent->rbuf;
+ data = (u_int32_t *)ch->data;
+ dst = sndbuf_getfreeptr(ch->buffer) / 4;
+ src = dst / 2 + ch->offset;
+ dsize = ch->size / 4;
+ ssize = ch->size / 8;
+ slot = (ch->num - ENVY24_CHAN_REC_ADC1) * 2;
+
+ for (i = 0; i < length; i++) {
+ data[dst] = dmabuf[src * ENVY24_REC_CHNUM + slot].buffer;
+ data[dst + 1] = dmabuf[src * ENVY24_REC_CHNUM + slot + 1].buffer;
+ dst += 2;
+ dst %= dsize;
+ src++;
+ src %= ssize;
+ }
+
+ return;
+}
+
+static void
+envy24_r16sl(struct sc_chinfo *ch)
+{
+ int length;
+ sample32_t *dmabuf;
+ u_int16_t *data;
+ int src, dst, ssize, dsize, slot;
+ int i;
+
+ length = sndbuf_getfree(ch->buffer) / 4;
+ dmabuf = ch->parent->rbuf;
+ data = (u_int16_t *)ch->data;
+ dst = sndbuf_getfreeptr(ch->buffer) / 2;
+ src = dst / 2 + ch->offset;
+ dsize = ch->size / 2;
+ ssize = ch->size / 8;
+ slot = (ch->num - ENVY24_CHAN_REC_ADC1) * 2;
+
+ for (i = 0; i < length; i++) {
+ data[dst] = dmabuf[src * ENVY24_REC_CHNUM + slot].buffer;
+ data[dst + 1] = dmabuf[src * ENVY24_REC_CHNUM + slot + 1].buffer;
+ dst += 2;
+ dst %= dsize;
+ src++;
+ src %= ssize;
+ }
+
+ return;
+}
+
+/* -------------------------------------------------------------------- */
+
+/* channel interface */
+static void *
+envy24chan_init(kobj_t obj, void *devinfo, struct snd_dbuf *b, struct pcm_channel *c, int dir)
+{
+ struct sc_info *sc = (struct sc_info *)devinfo;
+ struct sc_chinfo *ch;
+ unsigned num;
+
+#if(0)
+ device_printf(sc->dev, "envy24chan_init(obj, devinfo, b, c, %d)\n", dir);
+#endif
+ snd_mtxlock(sc->lock);
+ if ((sc->chnum > ENVY24_CHAN_PLAY_SPDIF && dir != PCMDIR_REC) ||
+ (sc->chnum < ENVY24_CHAN_REC_ADC1 && dir != PCMDIR_PLAY)) {
+ snd_mtxunlock(sc->lock);
+ return NULL;
+ }
+ num = sc->chnum;
+
+ ch = &sc->chan[num];
+ ch->size = 8 * ENVY24_SAMPLE_NUM;
+ ch->data = malloc(ch->size, M_ENVY24, M_NOWAIT);
+ if (ch->data == NULL) {
+ ch->size = 0;
+ ch = NULL;
+ }
+ else {
+ ch->buffer = b;
+ ch->channel = c;
+ ch->parent = sc;
+ ch->dir = dir;
+ /* set channel map */
+ ch->num = envy24_chanmap[num];
+ snd_mtxunlock(sc->lock);
+ sndbuf_setup(ch->buffer, ch->data, ch->size);
+ snd_mtxlock(sc->lock);
+ /* these 2 values are dummy */
+ ch->unit = 4;
+ ch->blk = 10240;
+ }
+ snd_mtxunlock(sc->lock);
+
+ return ch;
+}
+
+static int
+envy24chan_free(kobj_t obj, void *data)
+{
+ struct sc_chinfo *ch = data;
+ struct sc_info *sc = ch->parent;
+
+#if(0)
+ device_printf(sc->dev, "envy24chan_free()\n");
+#endif
+ snd_mtxlock(sc->lock);
+ if (ch->data != NULL) {
+ free(ch->data, M_ENVY24);
+ ch->data = NULL;
+ }
+ snd_mtxunlock(sc->lock);
+
+ return 0;
+}
+
+static int
+envy24chan_setformat(kobj_t obj, void *data, u_int32_t format)
+{
+ struct sc_chinfo *ch = data;
+ struct sc_info *sc = ch->parent;
+ struct envy24_emldma *emltab;
+ /* unsigned int bcnt, bsize; */
+ int i;
+
+#if(0)
+ device_printf(sc->dev, "envy24chan_setformat(obj, data, 0x%08x)\n", format);
+#endif
+ snd_mtxlock(sc->lock);
+ /* check and get format related information */
+ if (ch->dir == PCMDIR_PLAY)
+ emltab = envy24_pemltab;
+ else
+ emltab = envy24_remltab;
+ if (emltab == NULL) {
+ snd_mtxunlock(sc->lock);
+ return -1;
+ }
+ for (i = 0; emltab[i].format != 0; i++)
+ if (emltab[i].format == format)
+ break;
+ if (emltab[i].format == 0) {
+ snd_mtxunlock(sc->lock);
+ return -1;
+ }
+
+ /* set format information */
+ ch->format = format;
+ ch->emldma = emltab[i].emldma;
+ if (ch->unit > emltab[i].unit)
+ ch->blk *= ch->unit / emltab[i].unit;
+ else
+ ch->blk /= emltab[i].unit / ch->unit;
+ ch->unit = emltab[i].unit;
+
+ /* set channel buffer information */
+ ch->size = ch->unit * ENVY24_SAMPLE_NUM;
+#if 0
+ if (ch->dir == PCMDIR_PLAY)
+ bsize = ch->blk * 4 / ENVY24_PLAY_BUFUNIT;
+ else
+ bsize = ch->blk * 4 / ENVY24_REC_BUFUNIT;
+ bsize *= ch->unit;
+ bcnt = ch->size / bsize;
+ sndbuf_resize(ch->buffer, bcnt, bsize);
+#endif
+ snd_mtxunlock(sc->lock);
+
+#if(0)
+ device_printf(sc->dev, "envy24chan_setformat(): return 0x%08x\n", 0);
+#endif
+ return 0;
+}
+
+/*
+ IMPLEMENT NOTICE: In this driver, setspeed function only do setting
+ of speed information value. And real hardware speed setting is done
+ at start triggered(see envy24chan_trigger()). So, at this function
+ is called, any value that ENVY24 can use is able to set. But, at
+ start triggerd, some other channel is running, and that channel's
+ speed isn't same with, then trigger function will fail.
+*/
+static int
+envy24chan_setspeed(kobj_t obj, void *data, u_int32_t speed)
+{
+ struct sc_chinfo *ch = data;
+ u_int32_t val, prev;
+ int i;
+
+#if(0)
+ device_printf(ch->parent->dev, "envy24chan_setspeed(obj, data, %d)\n", speed);
+#endif
+ prev = 0x7fffffff;
+ for (i = 0; (val = envy24_speed[i]) != 0; i++) {
+ if (abs(val - speed) < abs(prev - speed))
+ prev = val;
+ else
+ break;
+ }
+ ch->speed = prev;
+
+#if(0)
+ device_printf(ch->parent->dev, "envy24chan_setspeed(): return %d\n", ch->speed);
+#endif
+ return ch->speed;
+}
+
+static int
+envy24chan_setblocksize(kobj_t obj, void *data, u_int32_t blocksize)
+{
+ struct sc_chinfo *ch = data;
+ /* struct sc_info *sc = ch->parent; */
+ u_int32_t size, prev;
+ unsigned int bcnt, bsize;
+
+#if(0)
+ device_printf(sc->dev, "envy24chan_setblocksize(obj, data, %d)\n", blocksize);
+#endif
+ prev = 0x7fffffff;
+ /* snd_mtxlock(sc->lock); */
+ for (size = ch->size / 2; size > 0; size /= 2) {
+ if (abs(size - blocksize) < abs(prev - blocksize))
+ prev = size;
+ else
+ break;
+ }
+
+ ch->blk = prev / ch->unit;
+ if (ch->dir == PCMDIR_PLAY)
+ ch->blk *= ENVY24_PLAY_BUFUNIT / 4;
+ else
+ ch->blk *= ENVY24_REC_BUFUNIT / 4;
+ /* set channel buffer information */
+ /* ch->size = ch->unit * ENVY24_SAMPLE_NUM; */
+ if (ch->dir == PCMDIR_PLAY)
+ bsize = ch->blk * 4 / ENVY24_PLAY_BUFUNIT;
+ else
+ bsize = ch->blk * 4 / ENVY24_REC_BUFUNIT;
+ bsize *= ch->unit;
+ bcnt = ch->size / bsize;
+ sndbuf_resize(ch->buffer, bcnt, bsize);
+ /* snd_mtxunlock(sc->lock); */
+
+#if(0)
+ device_printf(sc->dev, "envy24chan_setblocksize(): return %d\n", prev);
+#endif
+ return prev;
+}
+
+/* semantic note: must start at beginning of buffer */
+static int
+envy24chan_trigger(kobj_t obj, void *data, int go)
+{
+ struct sc_chinfo *ch = data;
+ struct sc_info *sc = ch->parent;
+ u_int32_t ptr;
+ int slot;
+#if 0
+ int i;
+
+ device_printf(sc->dev, "envy24chan_trigger(obj, data, %d)\n", go);
+#endif
+ snd_mtxlock(sc->lock);
+ if (ch->dir == PCMDIR_PLAY)
+ slot = 0;
+ else
+ slot = 1;
+ switch (go) {
+ case PCMTRIG_START:
+#if(0)
+ device_printf(sc->dev, "envy24chan_trigger(): start\n");
+#endif
+ /* check or set channel speed */
+ if (sc->run[0] == 0 && sc->run[1] == 0) {
+ sc->speed = envy24_setspeed(sc, ch->speed);
+ sc->caps[0].minspeed = sc->caps[0].maxspeed = sc->speed;
+ sc->caps[1].minspeed = sc->caps[1].maxspeed = sc->speed;
+ }
+ else if (ch->speed != 0 && ch->speed != sc->speed)
+ return -1;
+ if (ch->speed == 0)
+ ch->channel->speed = sc->speed;
+ /* start or enable channel */
+ sc->run[slot]++;
+ if (sc->run[slot] == 1) {
+ /* first channel */
+ ch->offset = 0;
+ sc->blk[slot] = ch->blk;
+ }
+ else {
+ ptr = envy24_gethwptr(sc, ch->dir);
+ ch->offset = ((ptr / ch->blk + 1) * ch->blk %
+ (ch->size / 4)) * 4 / ch->unit;
+ if (ch->blk < sc->blk[slot])
+ sc->blk[slot] = ch->blk;
+ }
+ if (ch->dir == PCMDIR_PLAY) {
+ ch->emldma(ch);
+ envy24_setvolume(sc, ch->num);
+ }
+ envy24_updintr(sc, ch->dir);
+ if (sc->run[slot] == 1)
+ envy24_start(sc, ch->dir);
+ ch->run = 1;
+ break;
+ case PCMTRIG_EMLDMAWR:
+#if(0)
+ device_printf(sc->dev, "envy24chan_trigger(): emldmawr\n");
+#endif
+ if (ch->run != 1)
+ return -1;
+ ch->emldma(ch);
+ break;
+ case PCMTRIG_EMLDMARD:
+#if(0)
+ device_printf(sc->dev, "envy24chan_trigger(): emldmard\n");
+#endif
+ if (ch->run != 1)
+ return -1;
+ ch->emldma(ch);
+ break;
+ case PCMTRIG_ABORT:
+ if (ch->run) {
+#if(0)
+ device_printf(sc->dev, "envy24chan_trigger(): abort\n");
+#endif
+ ch->run = 0;
+ sc->run[slot]--;
+ if (ch->dir == PCMDIR_PLAY)
+ envy24_mutevolume(sc, ch->num);
+ if (sc->run[slot] == 0) {
+ envy24_stop(sc, ch->dir);
+ sc->intr[slot] = 0;
+ }
+#if 0
+ else if (ch->blk == sc->blk[slot]) {
+ sc->blk[slot] = ENVY24_SAMPLE_NUM / 2;
+ for (i = 0; i < ENVY24_CHAN_NUM; i++) {
+ if (sc->chan[i].dir == ch->dir &&
+ sc->chan[i].run == 1 &&
+ sc->chan[i].blk < sc->blk[slot])
+ sc->blk[slot] = sc->chan[i].blk;
+ }
+ if (ch->blk != sc->blk[slot])
+ envy24_updintr(sc, ch->dir);
+ }
+#endif
+ }
+ break;
+ }
+ snd_mtxunlock(sc->lock);
+
+ return 0;
+}
+
+static int
+envy24chan_getptr(kobj_t obj, void *data)
+{
+ struct sc_chinfo *ch = data;
+ struct sc_info *sc = ch->parent;
+ u_int32_t ptr;
+ int rtn;
+
+#if(0)
+ device_printf(sc->dev, "envy24chan_getptr()\n");
+#endif
+ snd_mtxlock(sc->lock);
+ ptr = envy24_gethwptr(sc, ch->dir);
+ rtn = ptr * ch->unit;
+ snd_mtxunlock(sc->lock);
+
+#if(0)
+ device_printf(sc->dev, "envy24chan_getptr(): return %d\n",
+ rtn);
+#endif
+ return rtn;
+}
+
+static struct pcmchan_caps *
+envy24chan_getcaps(kobj_t obj, void *data)
+{
+ struct sc_chinfo *ch = data;
+ struct sc_info *sc = ch->parent;
+ struct pcmchan_caps *rtn;
+
+#if(0)
+ device_printf(sc->dev, "envy24chan_getcaps()\n");
+#endif
+ snd_mtxlock(sc->lock);
+ if (ch->dir == PCMDIR_PLAY) {
+ if (sc->run[0] == 0)
+ rtn = &envy24_playcaps;
+ else
+ rtn = &sc->caps[0];
+ }
+ else {
+ if (sc->run[1] == 0)
+ rtn = &envy24_reccaps;
+ else
+ rtn = &sc->caps[1];
+ }
+ snd_mtxunlock(sc->lock);
+
+ return rtn;
+}
+
+static kobj_method_t envy24chan_methods[] = {
+ KOBJMETHOD(channel_init, envy24chan_init),
+ KOBJMETHOD(channel_free, envy24chan_free),
+ KOBJMETHOD(channel_setformat, envy24chan_setformat),
+ KOBJMETHOD(channel_setspeed, envy24chan_setspeed),
+ KOBJMETHOD(channel_setblocksize, envy24chan_setblocksize),
+ KOBJMETHOD(channel_trigger, envy24chan_trigger),
+ KOBJMETHOD(channel_getptr, envy24chan_getptr),
+ KOBJMETHOD(channel_getcaps, envy24chan_getcaps),
+ { 0, 0 }
+};
+CHANNEL_DECLARE(envy24chan);
+
+/* -------------------------------------------------------------------- */
+
+/* mixer interface */
+
+static int
+envy24mixer_init(struct snd_mixer *m)
+{
+ struct sc_info *sc = mix_getdevinfo(m);
+
+#if(0)
+ device_printf(sc->dev, "envy24mixer_init()\n");
+#endif
+ if (sc == NULL)
+ return -1;
+
+ /* set volume control rate */
+ snd_mtxlock(sc->lock);
+ envy24_wrmt(sc, ENVY24_MT_VOLRATE, 0x30, 1); /* 0x30 is default value */
+
+ mix_setdevs(m, ENVY24_MIX_MASK);
+ mix_setrecdevs(m, ENVY24_MIX_REC_MASK);
+ snd_mtxunlock(sc->lock);
+
+ return 0;
+}
+
+static int
+envy24mixer_reinit(struct snd_mixer *m)
+{
+ struct sc_info *sc = mix_getdevinfo(m);
+
+ if (sc == NULL)
+ return -1;
+#if(0)
+ device_printf(sc->dev, "envy24mixer_reinit()\n");
+#endif
+
+ return 0;
+}
+
+static int
+envy24mixer_uninit(struct snd_mixer *m)
+{
+ struct sc_info *sc = mix_getdevinfo(m);
+
+ if (sc == NULL)
+ return -1;
+#if(0)
+ device_printf(sc->dev, "envy24mixer_uninit()\n");
+#endif
+
+ return 0;
+}
+
+static int
+envy24mixer_set(struct snd_mixer *m, unsigned dev, unsigned left, unsigned right)
+{
+ struct sc_info *sc = mix_getdevinfo(m);
+ int ch = envy24_mixmap[dev];
+ int hwch;
+ int i;
+
+ if (sc == NULL)
+ return -1;
+ if (dev == 0 && sc->cfg->codec->setvolume == NULL)
+ return -1;
+ if (dev != 0 && ch == -1)
+ return -1;
+ hwch = envy24_chanmap[ch];
+#if(0)
+ device_printf(sc->dev, "envy24mixer_set(m, %d, %d, %d)\n",
+ dev, left, right);
+#endif
+
+ snd_mtxlock(sc->lock);
+ if (dev == 0) {
+ for (i = 0; i < sc->dacn; i++) {
+ sc->cfg->codec->setvolume(sc->dac[i], PCMDIR_PLAY, left, right);
+ }
+ }
+ else {
+ /* set volume value for hardware */
+ if ((sc->left[hwch] = 100 - left) > ENVY24_VOL_MIN)
+ sc->left[hwch] = ENVY24_VOL_MUTE;
+ if ((sc->right[hwch] = 100 - right) > ENVY24_VOL_MIN)
+ sc->right[hwch] = ENVY24_VOL_MUTE;
+
+ /* set volume for record channel and running play channel */
+ if (hwch > ENVY24_CHAN_PLAY_SPDIF || sc->chan[ch].run)
+ envy24_setvolume(sc, hwch);
+ }
+ snd_mtxunlock(sc->lock);
+
+ return right << 8 | left;
+}
+
+static u_int32_t
+envy24mixer_setrecsrc(struct snd_mixer *m, u_int32_t src)
+{
+ struct sc_info *sc = mix_getdevinfo(m);
+ int ch = envy24_mixmap[src];
+#if(0)
+ device_printf(sc->dev, "envy24mixer_setrecsrc(m, %d)\n", src);
+#endif
+
+ if (ch > ENVY24_CHAN_PLAY_SPDIF)
+ sc->src = ch;
+ return src;
+}
+
+static kobj_method_t envy24mixer_methods[] = {
+ KOBJMETHOD(mixer_init, envy24mixer_init),
+ KOBJMETHOD(mixer_reinit, envy24mixer_reinit),
+ KOBJMETHOD(mixer_uninit, envy24mixer_uninit),
+ KOBJMETHOD(mixer_set, envy24mixer_set),
+ KOBJMETHOD(mixer_setrecsrc, envy24mixer_setrecsrc),
+ { 0, 0 }
+};
+MIXER_DECLARE(envy24mixer);
+
+/* -------------------------------------------------------------------- */
+
+/* The interrupt handler */
+static void
+envy24_intr(void *p)
+{
+ struct sc_info *sc = (struct sc_info *)p;
+ struct sc_chinfo *ch;
+ u_int32_t ptr, dsize, feed;
+ int i;
+
+#if(0)
+ device_printf(sc->dev, "envy24_intr()\n");
+#endif
+ snd_mtxlock(sc->lock);
+ if (envy24_checkintr(sc, PCMDIR_PLAY)) {
+#if(0)
+ device_printf(sc->dev, "envy24_intr(): play\n");
+#endif
+ dsize = sc->psize / 4;
+ ptr = dsize - envy24_rdmt(sc, ENVY24_MT_PCNT, 2) - 1;
+#if(0)
+ device_printf(sc->dev, "envy24_intr(): ptr = %d-->", ptr);
+#endif
+ ptr -= ptr % sc->blk[0];
+ feed = (ptr + dsize - sc->intr[0]) % dsize;
+#if(0)
+ printf("%d intr = %d feed = %d\n", ptr, sc->intr[0], feed);
+#endif
+ for (i = ENVY24_CHAN_PLAY_DAC1; i <= ENVY24_CHAN_PLAY_SPDIF; i++) {
+ ch = &sc->chan[i];
+#if(0)
+ if (ch->run)
+ device_printf(sc->dev, "envy24_intr(): chan[%d].blk = %d\n", i, ch->blk);
+#endif
+ if (ch->run && ch->blk <= feed) {
+ snd_mtxunlock(sc->lock);
+ chn_intr(ch->channel);
+ snd_mtxlock(sc->lock);
+ }
+ }
+ sc->intr[0] = ptr;
+ envy24_updintr(sc, PCMDIR_PLAY);
+ }
+ if (envy24_checkintr(sc, PCMDIR_REC)) {
+#if(0)
+ device_printf(sc->dev, "envy24_intr(): rec\n");
+#endif
+ dsize = sc->rsize / 4;
+ ptr = dsize - envy24_rdmt(sc, ENVY24_MT_RCNT, 2) - 1;
+ ptr -= ptr % sc->blk[1];
+ feed = (ptr + dsize - sc->intr[1]) % dsize;
+ for (i = ENVY24_CHAN_REC_ADC1; i <= ENVY24_CHAN_REC_SPDIF; i++) {
+ ch = &sc->chan[i];
+ if (ch->run && ch->blk <= feed) {
+ snd_mtxunlock(sc->lock);
+ chn_intr(ch->channel);
+ snd_mtxlock(sc->lock);
+ }
+ }
+ sc->intr[1] = ptr;
+ envy24_updintr(sc, PCMDIR_REC);
+ }
+ snd_mtxunlock(sc->lock);
+
+ return;
+}
+
+/*
+ * Probe and attach the card
+ */
+
+static int
+envy24_pci_probe(device_t dev)
+{
+ u_int16_t sv, sd;
+ int i;
+
+#if(0)
+ printf("envy24_pci_probe()\n");
+#endif
+ if (pci_get_device(dev) == PCID_ENVY24 &&
+ pci_get_vendor(dev) == PCIV_ENVY24) {
+ sv = pci_get_subvendor(dev);
+ sd = pci_get_subdevice(dev);
+ for (i = 0; cfg_table[i].subvendor != 0 || cfg_table[i].subdevice != 0; i++) {
+ if (cfg_table[i].subvendor == sv &&
+ cfg_table[i].subdevice == sd) {
+ break;
+ }
+ }
+ device_set_desc(dev, cfg_table[i].name);
+#if(0)
+ printf("envy24_pci_probe(): return 0\n");
+#endif
+ return 0;
+ }
+ else {
+#if(0)
+ printf("envy24_pci_probe(): return ENXIO\n");
+#endif
+ return ENXIO;
+ }
+}
+
+static void
+envy24_dmapsetmap(void *arg, bus_dma_segment_t *segs, int nseg, int error)
+{
+ /* struct sc_info *sc = (struct sc_info *)arg; */
+
+#if(0)
+ device_printf(sc->dev, "envy24_dmapsetmap()\n");
+ if (bootverbose) {
+ printf("envy24(play): setmap %lx, %lx; ",
+ (unsigned long)segs->ds_addr,
+ (unsigned long)segs->ds_len);
+ printf("%p -> %lx\n", sc->pmap, (unsigned long)vtophys(sc->pmap));
+ }
+#endif
+}
+
+static void
+envy24_dmarsetmap(void *arg, bus_dma_segment_t *segs, int nseg, int error)
+{
+ /* struct sc_info *sc = (struct sc_info *)arg; */
+
+#if(0)
+ device_printf(sc->dev, "envy24_dmarsetmap()\n");
+ if (bootverbose) {
+ printf("envy24(record): setmap %lx, %lx; ",
+ (unsigned long)segs->ds_addr,
+ (unsigned long)segs->ds_len);
+ printf("%p -> %lx\n", sc->rmap, (unsigned long)vtophys(sc->pmap));
+ }
+#endif
+}
+
+static void
+envy24_dmafree(struct sc_info *sc)
+{
+#if(0)
+ device_printf(sc->dev, "envy24_dmafree():");
+ if (sc->rmap) printf(" sc->rmap(0x%08x)", (u_int32_t)sc->rmap);
+ else printf(" sc->rmap(null)");
+ if (sc->pmap) printf(" sc->pmap(0x%08x)", (u_int32_t)sc->pmap);
+ else printf(" sc->pmap(null)");
+ if (sc->rbuf) printf(" sc->rbuf(0x%08x)", (u_int32_t)sc->rbuf);
+ else printf(" sc->rbuf(null)");
+ if (sc->pbuf) printf(" sc->pbuf(0x%08x)\n", (u_int32_t)sc->pbuf);
+ else printf(" sc->pbuf(null)\n");
+#endif
+#if(0)
+ if (sc->rmap)
+ bus_dmamap_unload(sc->dmat, sc->rmap);
+ if (sc->pmap)
+ bus_dmamap_unload(sc->dmat, sc->pmap);
+ if (sc->rbuf)
+ bus_dmamem_free(sc->dmat, sc->rbuf, sc->rmap);
+ if (sc->pbuf)
+ bus_dmamem_free(sc->dmat, sc->pbuf, sc->pmap);
+#else
+ bus_dmamap_unload(sc->dmat, sc->rmap);
+ bus_dmamap_unload(sc->dmat, sc->pmap);
+ bus_dmamem_free(sc->dmat, sc->rbuf, sc->rmap);
+ bus_dmamem_free(sc->dmat, sc->pbuf, sc->pmap);
+#endif
+
+ sc->rmap = sc->pmap = NULL;
+ sc->pbuf = NULL;
+ sc->rbuf = NULL;
+
+ return;
+}
+
+static int
+envy24_dmainit(struct sc_info *sc)
+{
+ u_int32_t addr;
+
+#if(0)
+ device_printf(sc->dev, "envy24_dmainit()\n");
+#endif
+ /* init values */
+ sc->psize = ENVY24_PLAY_BUFUNIT * ENVY24_SAMPLE_NUM;
+ sc->rsize = ENVY24_REC_BUFUNIT * ENVY24_SAMPLE_NUM;
+ sc->pbuf = NULL;
+ sc->rbuf = NULL;
+ sc->pmap = sc->rmap = NULL;
+ sc->blk[0] = sc->blk[1] = 0;
+
+ /* allocate DMA buffer */
+#if(0)
+ device_printf(sc->dev, "envy24_dmainit(): bus_dmamem_alloc(): sc->pbuf\n");
+#endif
+ if (bus_dmamem_alloc(sc->dmat, (void **)&sc->pbuf, BUS_DMA_NOWAIT, &sc->pmap))
+ goto bad;
+#if(0)
+ device_printf(sc->dev, "envy24_dmainit(): bus_dmamem_alloc(): sc->rbuf\n");
+#endif
+ if (bus_dmamem_alloc(sc->dmat, (void **)&sc->rbuf, BUS_DMA_NOWAIT, &sc->rmap))
+ goto bad;
+#if(0)
+ device_printf(sc->dev, "envy24_dmainit(): bus_dmamem_load(): sc->pmap\n");
+#endif
+ if (bus_dmamap_load(sc->dmat, sc->pmap, sc->pbuf, sc->psize, envy24_dmapsetmap, sc, 0))
+ goto bad;
+#if(0)
+ device_printf(sc->dev, "envy24_dmainit(): bus_dmamem_load(): sc->rmap\n");
+#endif
+ if (bus_dmamap_load(sc->dmat, sc->rmap, sc->rbuf, sc->rsize, envy24_dmarsetmap, sc, 0))
+ goto bad;
+ bzero(sc->pbuf, sc->psize);
+ bzero(sc->rbuf, sc->rsize);
+
+ /* set values to register */
+ addr = vtophys(sc->pbuf);
+#if(0)
+ device_printf(sc->dev, "pbuf(0x%08x)\n", addr);
+#endif
+ envy24_wrmt(sc, ENVY24_MT_PADDR, addr, 4);
+#if(0)
+ device_printf(sc->dev, "PADDR-->(0x%08x)\n", envy24_rdmt(sc, ENVY24_MT_PADDR, 4));
+ device_printf(sc->dev, "psize(%ld)\n", sc->psize / 4 - 1);
+#endif
+ envy24_wrmt(sc, ENVY24_MT_PCNT, sc->psize / 4 - 1, 2);
+#if(0)
+ device_printf(sc->dev, "PCNT-->(%ld)\n", envy24_rdmt(sc, ENVY24_MT_PCNT, 2));
+#endif
+ addr = vtophys(sc->rbuf);
+ envy24_wrmt(sc, ENVY24_MT_RADDR, addr, 4);
+ envy24_wrmt(sc, ENVY24_MT_RCNT, sc->rsize / 4 - 1, 2);
+
+ return 0;
+ bad:
+ envy24_dmafree(sc);
+ return ENOSPC;
+}
+
+static void
+envy24_putcfg(struct sc_info *sc)
+{
+ device_printf(sc->dev, "system configuration\n");
+ printf(" SubVendorID: 0x%04x, SubDeviceID: 0x%04x\n",
+ sc->cfg->subvendor, sc->cfg->subdevice);
+ printf(" XIN2 Clock Source: ");
+ switch (sc->cfg->scfg & PCIM_SCFG_XIN2) {
+ case 0x00:
+ printf("22.5792MHz(44.1kHz*512)\n");
+ break;
+ case 0x40:
+ printf("16.9344MHz(44.1kHz*384)\n");
+ break;
+ case 0x80:
+ printf("from external clock synthesizer chip\n");
+ break;
+ default:
+ printf("illeagal system setting\n");
+ }
+ printf(" MPU-401 UART(s) #: ");
+ if (sc->cfg->scfg & PCIM_SCFG_MPU)
+ printf("2\n");
+ else
+ printf("1\n");
+ printf(" AC'97 codec: ");
+ if (sc->cfg->scfg & PCIM_SCFG_AC97)
+ printf("not exist\n");
+ else
+ printf("exist\n");
+ printf(" ADC #: ");
+ printf("%d\n", sc->adcn);
+ printf(" DAC #: ");
+ printf("%d\n", sc->dacn);
+ printf(" Multi-track converter type: ");
+ if ((sc->cfg->acl & PCIM_ACL_MTC) == 0) {
+ printf("AC'97(SDATA_OUT:");
+ if (sc->cfg->acl & PCIM_ACL_OMODE)
+ printf("packed");
+ else
+ printf("split");
+ printf("|SDATA_IN:");
+ if (sc->cfg->acl & PCIM_ACL_IMODE)
+ printf("packed");
+ else
+ printf("split");
+ printf(")\n");
+ }
+ else {
+ printf("I2S(");
+ if (sc->cfg->i2s & PCIM_I2S_VOL)
+ printf("with volume, ");
+ if (sc->cfg->i2s & PCIM_I2S_96KHZ)
+ printf("96KHz support, ");
+ switch (sc->cfg->i2s & PCIM_I2S_RES) {
+ case PCIM_I2S_16BIT:
+ printf("16bit resolution, ");
+ break;
+ case PCIM_I2S_18BIT:
+ printf("18bit resolution, ");
+ break;
+ case PCIM_I2S_20BIT:
+ printf("20bit resolution, ");
+ break;
+ case PCIM_I2S_24BIT:
+ printf("24bit resolution, ");
+ break;
+ }
+ printf("ID#0x%x)\n", sc->cfg->i2s & PCIM_I2S_ID);
+ }
+ printf(" S/PDIF(IN/OUT): ");
+ if (sc->cfg->spdif & PCIM_SPDIF_IN)
+ printf("1/");
+ else
+ printf("0/");
+ if (sc->cfg->spdif & PCIM_SPDIF_OUT)
+ printf("1 ");
+ else
+ printf("0 ");
+ if (sc->cfg->spdif & (PCIM_SPDIF_IN | PCIM_SPDIF_OUT))
+ printf("ID# 0x%02x\n", (sc->cfg->spdif & PCIM_SPDIF_ID) >> 2);
+ printf(" GPIO(mask/dir/state): 0x%02x/0x%02x/0x%02x\n",
+ sc->cfg->gpiomask, sc->cfg->gpiodir, sc->cfg->gpiostate);
+}
+
+static int
+envy24_init(struct sc_info *sc)
+{
+ u_int32_t data;
+#if(0)
+ int rtn;
+#endif
+ int i;
+ u_int32_t sv, sd;
+
+
+#if(0)
+ device_printf(sc->dev, "envy24_init()\n");
+#endif
+
+ /* reset chip */
+ envy24_wrcs(sc, ENVY24_CCS_CTL, ENVY24_CCS_CTL_RESET | ENVY24_CCS_CTL_NATIVE, 1);
+ DELAY(200);
+ envy24_wrcs(sc, ENVY24_CCS_CTL, ENVY24_CCS_CTL_NATIVE, 1);
+ DELAY(200);
+
+ /* legacy hardware disable */
+ data = pci_read_config(sc->dev, PCIR_LAC, 2);
+ data |= PCIM_LAC_DISABLE;
+ pci_write_config(sc->dev, PCIR_LAC, data, 2);
+
+ /* check system configuration */
+ sc->cfg = NULL;
+ for (i = 0; cfg_table[i].subvendor != 0 || cfg_table[i].subdevice != 0; i++) {
+ /* 1st: search configuration from table */
+ sv = pci_get_subvendor(sc->dev);
+ sd = pci_get_subdevice(sc->dev);
+ if (sv == cfg_table[i].subvendor && sd == cfg_table[i].subdevice) {
+#if(0)
+ device_printf(sc->dev, "Set configuration from table\n");
+#endif
+ sc->cfg = &cfg_table[i];
+ break;
+ }
+ }
+ if (sc->cfg == NULL) {
+ /* 2nd: read configuration from table */
+ sc->cfg = envy24_rom2cfg(sc);
+ }
+ sc->adcn = ((sc->cfg->scfg & PCIM_SCFG_ADC) >> 2) + 1;
+ sc->dacn = (sc->cfg->scfg & PCIM_SCFG_DAC) + 1;
+
+ if (1 /* bootverbose */) {
+ envy24_putcfg(sc);
+ }
+
+ /* set system configuration */
+ pci_write_config(sc->dev, PCIR_SCFG, sc->cfg->scfg, 1);
+ pci_write_config(sc->dev, PCIR_ACL, sc->cfg->acl, 1);
+ pci_write_config(sc->dev, PCIR_I2S, sc->cfg->i2s, 1);
+ pci_write_config(sc->dev, PCIR_SPDIF, sc->cfg->spdif, 1);
+ envy24_gpiosetmask(sc, sc->cfg->gpiomask);
+ envy24_gpiosetdir(sc, sc->cfg->gpiodir);
+ envy24_gpiowr(sc, sc->cfg->gpiostate);
+ for (i = 0; i < sc->adcn; i++) {
+ sc->adc[i] = sc->cfg->codec->create(sc->dev, sc, PCMDIR_REC, i);
+ sc->cfg->codec->init(sc->adc[i]);
+ }
+ for (i = 0; i < sc->dacn; i++) {
+ sc->dac[i] = sc->cfg->codec->create(sc->dev, sc, PCMDIR_PLAY, i);
+ sc->cfg->codec->init(sc->dac[i]);
+ }
+
+ /* initialize DMA buffer */
+#if(0)
+ device_printf(sc->dev, "envy24_init(): initialize DMA buffer\n");
+#endif
+ if (envy24_dmainit(sc))
+ return ENOSPC;
+
+ /* initialize status */
+ sc->run[0] = sc->run[1] = 0;
+ sc->intr[0] = sc->intr[1] = 0;
+ sc->speed = 0;
+ sc->caps[0].fmtlist = envy24_playfmt;
+ sc->caps[1].fmtlist = envy24_recfmt;
+
+ /* set channel router */
+ envy24_route(sc, ENVY24_ROUTE_DAC_1, ENVY24_ROUTE_CLASS_MIX, 0, 0);
+ envy24_route(sc, ENVY24_ROUTE_DAC_SPDIF, ENVY24_ROUTE_CLASS_DMA, 0, 0);
+ /* envy24_route(sc, ENVY24_ROUTE_DAC_SPDIF, ENVY24_ROUTE_CLASS_MIX, 0, 0); */
+
+ /* set macro interrupt mask */
+ data = envy24_rdcs(sc, ENVY24_CCS_IMASK, 1);
+ envy24_wrcs(sc, ENVY24_CCS_IMASK, data & ~ENVY24_CCS_IMASK_PMT, 1);
+ data = envy24_rdcs(sc, ENVY24_CCS_IMASK, 1);
+#if(0)
+ device_printf(sc->dev, "envy24_init(): CCS_IMASK-->0x%02x\n", data);
+#endif
+
+ return 0;
+}
+
+static int
+envy24_alloc_resource(struct sc_info *sc)
+{
+ /* allocate I/O port resource */
+ sc->csid = PCIR_CCS;
+ sc->cs = bus_alloc_resource(sc->dev, SYS_RES_IOPORT,
+ &sc->csid, 0, ~0, 1, RF_ACTIVE);
+ sc->ddmaid = PCIR_DDMA;
+ sc->ddma = bus_alloc_resource(sc->dev, SYS_RES_IOPORT,
+ &sc->ddmaid, 0, ~0, 1, RF_ACTIVE);
+ sc->dsid = PCIR_DS;
+ sc->ds = bus_alloc_resource(sc->dev, SYS_RES_IOPORT,
+ &sc->dsid, 0, ~0, 1, RF_ACTIVE);
+ sc->mtid = PCIR_MT;
+ sc->mt = bus_alloc_resource(sc->dev, SYS_RES_IOPORT,
+ &sc->mtid, 0, ~0, 1, RF_ACTIVE);
+ if (!sc->cs || !sc->ddma || !sc->ds || !sc->mt) {
+ device_printf(sc->dev, "unable to map IO port space\n");
+ return ENXIO;
+ }
+ sc->cst = rman_get_bustag(sc->cs);
+ sc->csh = rman_get_bushandle(sc->cs);
+ sc->ddmat = rman_get_bustag(sc->ddma);
+ sc->ddmah = rman_get_bushandle(sc->ddma);
+ sc->dst = rman_get_bustag(sc->ds);
+ sc->dsh = rman_get_bushandle(sc->ds);
+ sc->mtt = rman_get_bustag(sc->mt);
+ sc->mth = rman_get_bushandle(sc->mt);
+#if(0)
+ device_printf(sc->dev,
+ "IO port register values\nCCS: 0x%lx\nDDMA: 0x%lx\nDS: 0x%lx\nMT: 0x%lx\n",
+ pci_read_config(sc->dev, PCIR_CCS, 4),
+ pci_read_config(sc->dev, PCIR_DDMA, 4),
+ pci_read_config(sc->dev, PCIR_DS, 4),
+ pci_read_config(sc->dev, PCIR_MT, 4));
+#endif
+
+ /* allocate interupt resource */
+ sc->irqid = 0;
+ sc->irq = bus_alloc_resource(sc->dev, SYS_RES_IRQ, &sc->irqid,
+ 0, ~0, 1, RF_ACTIVE | RF_SHAREABLE);
+ if (!sc->irq ||
+ snd_setup_intr(sc->dev, sc->irq, INTR_MPSAFE, envy24_intr, sc, &sc->ih)) {
+ device_printf(sc->dev, "unable to map interrupt\n");
+ return ENXIO;
+ }
+
+ /* allocate DMA resource */
+ if (bus_dma_tag_create(/*parent*/bus_get_dma_tag(sc->dev),
+ /*alignment*/4,
+ /*boundary*/0,
+ /*lowaddr*/BUS_SPACE_MAXADDR_ENVY24,
+ /*highaddr*/BUS_SPACE_MAXADDR_ENVY24,
+ /*filter*/NULL, /*filterarg*/NULL,
+ /*maxsize*/BUS_SPACE_MAXSIZE_ENVY24,
+ /*nsegments*/1, /*maxsegsz*/0x3ffff,
+ /*flags*/0, /*lockfunc*/busdma_lock_mutex,
+ /*lockarg*/&Giant, &sc->dmat) != 0) {
+ device_printf(sc->dev, "unable to create dma tag\n");
+ return ENXIO;
+ }
+
+ return 0;
+}
+
+static int
+envy24_pci_attach(device_t dev)
+{
+ u_int32_t data;
+ struct sc_info *sc;
+ char status[SND_STATUSLEN];
+ int err = 0;
+ int i;
+
+#if(0)
+ device_printf(dev, "envy24_pci_attach()\n");
+#endif
+ /* get sc_info data area */
+ if ((sc = malloc(sizeof(*sc), M_ENVY24, M_NOWAIT)) == NULL) {
+ device_printf(dev, "cannot allocate softc\n");
+ return ENXIO;
+ }
+
+ bzero(sc, sizeof(*sc));
+ sc->lock = snd_mtxcreate(device_get_nameunit(dev), "snd_envy24 softc");
+ sc->dev = dev;
+
+ /* initialize PCI interface */
+ data = pci_read_config(dev, PCIR_COMMAND, 2);
+ data |= (PCIM_CMD_PORTEN | PCIM_CMD_BUSMASTEREN);
+ pci_write_config(dev, PCIR_COMMAND, data, 2);
+ data = pci_read_config(dev, PCIR_COMMAND, 2);
+
+ /* allocate resources */
+ err = envy24_alloc_resource(sc);
+ if (err) {
+ device_printf(dev, "unable to allocate system resources\n");
+ goto bad;
+ }
+
+ /* initialize card */
+ err = envy24_init(sc);
+ if (err) {
+ device_printf(dev, "unable to initialize the card\n");
+ goto bad;
+ }
+
+ /* set multi track mixer */
+ mixer_init(dev, &envy24mixer_class, sc);
+
+ /* set channel information */
+ err = pcm_register(dev, sc, 5, 2 + sc->adcn);
+ if (err)
+ goto bad;
+ sc->chnum = 0;
+ for (i = 0; i < 5; i++) {
+ pcm_addchan(dev, PCMDIR_PLAY, &envy24chan_class, sc);
+ sc->chnum++;
+ }
+ for (i = 0; i < 2 + sc->adcn; i++) {
+ pcm_addchan(dev, PCMDIR_REC, &envy24chan_class, sc);
+ sc->chnum++;
+ }
+
+ /* set status iformation */
+ snprintf(status, SND_STATUSLEN,
+ "at io 0x%lx:%ld,0x%lx:%ld,0x%lx:%ld,0x%lx:%ld irq %ld",
+ rman_get_start(sc->cs),
+ rman_get_end(sc->cs) - rman_get_start(sc->cs) + 1,
+ rman_get_start(sc->ddma),
+ rman_get_end(sc->ddma) - rman_get_start(sc->ddma) + 1,
+ rman_get_start(sc->ds),
+ rman_get_end(sc->ds) - rman_get_start(sc->ds) + 1,
+ rman_get_start(sc->mt),
+ rman_get_end(sc->mt) - rman_get_start(sc->mt) + 1,
+ rman_get_start(sc->irq));
+ pcm_setstatus(dev, status);
+
+ return 0;
+
+bad:
+ if (sc->ih)
+ bus_teardown_intr(dev, sc->irq, sc->ih);
+ if (sc->irq)
+ bus_release_resource(dev, SYS_RES_IRQ, sc->irqid, sc->irq);
+ envy24_dmafree(sc);
+ if (sc->dmat)
+ bus_dma_tag_destroy(sc->dmat);
+ if (sc->cfg->codec->destroy != NULL) {
+ for (i = 0; i < sc->adcn; i++)
+ sc->cfg->codec->destroy(sc->adc[i]);
+ for (i = 0; i < sc->dacn; i++)
+ sc->cfg->codec->destroy(sc->dac[i]);
+ }
+ envy24_cfgfree(sc->cfg);
+ if (sc->cs)
+ bus_release_resource(dev, SYS_RES_IOPORT, sc->csid, sc->cs);
+ if (sc->ddma)
+ bus_release_resource(dev, SYS_RES_IOPORT, sc->ddmaid, sc->ddma);
+ if (sc->ds)
+ bus_release_resource(dev, SYS_RES_IOPORT, sc->dsid, sc->ds);
+ if (sc->mt)
+ bus_release_resource(dev, SYS_RES_IOPORT, sc->mtid, sc->mt);
+ if (sc->lock)
+ snd_mtxfree(sc->lock);
+ free(sc, M_ENVY24);
+ return err;
+}
+
+static int
+envy24_pci_detach(device_t dev)
+{
+ struct sc_info *sc;
+ int r;
+ int i;
+
+#if(0)
+ device_printf(dev, "envy24_pci_detach()\n");
+#endif
+ sc = pcm_getdevinfo(dev);
+ if (sc == NULL)
+ return 0;
+ r = pcm_unregister(dev);
+ if (r)
+ return r;
+
+ envy24_dmafree(sc);
+ if (sc->cfg->codec->destroy != NULL) {
+ for (i = 0; i < sc->adcn; i++)
+ sc->cfg->codec->destroy(sc->adc[i]);
+ for (i = 0; i < sc->dacn; i++)
+ sc->cfg->codec->destroy(sc->dac[i]);
+ }
+ envy24_cfgfree(sc->cfg);
+ bus_dma_tag_destroy(sc->dmat);
+ bus_teardown_intr(dev, sc->irq, sc->ih);
+ bus_release_resource(dev, SYS_RES_IRQ, sc->irqid, sc->irq);
+ bus_release_resource(dev, SYS_RES_IOPORT, sc->csid, sc->cs);
+ bus_release_resource(dev, SYS_RES_IOPORT, sc->ddmaid, sc->ddma);
+ bus_release_resource(dev, SYS_RES_IOPORT, sc->dsid, sc->ds);
+ bus_release_resource(dev, SYS_RES_IOPORT, sc->mtid, sc->mt);
+ snd_mtxfree(sc->lock);
+ free(sc, M_ENVY24);
+ return 0;
+}
+
+static device_method_t envy24_methods[] = {
+ /* Device interface */
+ DEVMETHOD(device_probe, envy24_pci_probe),
+ DEVMETHOD(device_attach, envy24_pci_attach),
+ DEVMETHOD(device_detach, envy24_pci_detach),
+ { 0, 0 }
+};
+
+static driver_t envy24_driver = {
+ "pcm",
+ envy24_methods,
+#if __FreeBSD_version > 500000
+ PCM_SOFTC_SIZE,
+#else
+ sizeof(struct snddev_info),
+#endif
+};
+
+DRIVER_MODULE(snd_envy24, pci, envy24_driver, pcm_devclass, 0, 0);
+MODULE_DEPEND(snd_envy24, sound, SOUND_MINVER, SOUND_PREFVER, SOUND_MAXVER);
+MODULE_DEPEND(snd_envy24, snd_spicds, 1, 1, 1);
+MODULE_VERSION(snd_envy24, 1);
Index: fm801.c
===================================================================
RCS file: /home/cvs/src/sys/dev/sound/pci/fm801.c,v
retrieving revision 1.2
retrieving revision 1.3
diff -L sys/dev/sound/pci/fm801.c -L sys/dev/sound/pci/fm801.c -u -r1.2 -r1.3
--- sys/dev/sound/pci/fm801.c
+++ sys/dev/sound/pci/fm801.c
@@ -1,39 +1,39 @@
/*-
-* Copyright (c) 2000 Dmitry Dicky diwil at dataart.com
-* All rights reserved.
-*
-* Redistribution and use in source and binary forms, with or without
-* modification, are permitted provided that the following conditions
-* are met:
-* 1. Redistributions of source code must retain the above copyright
-* notice, this list of conditions and the following disclaimer.
-* 2. Redistributions in binary form must reproduce the above copyright
-* notice, this list of conditions and the following disclaimer in the
-* documentation and/or other materials provided with the distribution.
-*
-* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS `AS IS'' AND
-* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
-* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
-* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
-* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
-* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
-* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
-* SUCH DAMAGE.
-*/
+ * Copyright (c) 2000 Dmitry Dicky diwil at dataart.com
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS `AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
#include <dev/sound/pcm/sound.h>
#include <dev/sound/pcm/ac97.h>
#include <dev/pci/pcireg.h>
#include <dev/pci/pcivar.h>
-SND_DECLARE_FILE("$MidnightBSD$");
+SND_DECLARE_FILE("$FreeBSD: src/sys/dev/sound/pci/fm801.c,v 1.33 2007/06/17 06:10:42 ariff Exp $");
#define PCI_VENDOR_FORTEMEDIA 0x1319
-#define PCI_DEVICE_FORTEMEDIA1 0x08011319
-#define PCI_DEVICE_FORTEMEDIA2 0x08021319 /* ??? have no idea what's this... */
+#define PCI_DEVICE_FORTEMEDIA1 0x08011319 /* Audio controller */
+#define PCI_DEVICE_FORTEMEDIA2 0x08021319 /* Joystick controller */
#define FM_PCM_VOLUME 0x00
#define FM_FM_VOLUME 0x02
@@ -106,219 +106,219 @@
*/
static u_int32_t fmts[] = {
-AFMT_U8,
-AFMT_STEREO | AFMT_U8,
-AFMT_S16_LE,
-AFMT_STEREO | AFMT_S16_LE,
-0
+ AFMT_U8,
+ AFMT_STEREO | AFMT_U8,
+ AFMT_S16_LE,
+ AFMT_STEREO | AFMT_S16_LE,
+ 0
};
static struct pcmchan_caps fm801ch_caps = {
-5500, 48000,
-fmts, 0
+ 5500, 48000,
+ fmts, 0
};
struct fm801_info;
struct fm801_chinfo {
-struct fm801_info *parent;
-struct pcm_channel *channel;
-struct snd_dbuf *buffer;
-u_int32_t spd, dir, fmt; /* speed, direction, format */
-u_int32_t shift;
+ struct fm801_info *parent;
+ struct pcm_channel *channel;
+ struct snd_dbuf *buffer;
+ u_int32_t spd, dir, fmt; /* speed, direction, format */
+ u_int32_t shift;
};
struct fm801_info {
-int type;
-bus_space_tag_t st;
-bus_space_handle_t sh;
-bus_dma_tag_t parent_dmat;
-
-device_t dev;
-int num;
-u_int32_t unit;
-
-struct resource *reg, *irq;
-int regtype, regid, irqid;
-void *ih;
-
-u_int32_t play_flip,
-play_nextblk,
-play_start,
-play_blksize,
-play_fmt,
-play_shift,
-play_size;
-
-u_int32_t rec_flip,
-rec_nextblk,
-rec_start,
-rec_blksize,
-rec_fmt,
-rec_shift,
-rec_size;
+ int type;
+ bus_space_tag_t st;
+ bus_space_handle_t sh;
+ bus_dma_tag_t parent_dmat;
+
+ device_t dev;
+ int num;
+ u_int32_t unit;
+
+ struct resource *reg, *irq;
+ int regtype, regid, irqid;
+ void *ih;
+
+ u_int32_t play_flip,
+ play_nextblk,
+ play_start,
+ play_blksize,
+ play_fmt,
+ play_shift,
+ play_size;
+
+ u_int32_t rec_flip,
+ rec_nextblk,
+ rec_start,
+ rec_blksize,
+ rec_fmt,
+ rec_shift,
+ rec_size;
-unsigned int bufsz;
+ unsigned int bufsz;
-struct fm801_chinfo pch, rch;
+ struct fm801_chinfo pch, rch;
-device_t radio;
+ device_t radio;
};
/* Bus Read / Write routines */
static u_int32_t
fm801_rd(struct fm801_info *fm801, int regno, int size)
{
-switch(size) {
-case 1:
-return (bus_space_read_1(fm801->st, fm801->sh, regno));
-case 2:
-return (bus_space_read_2(fm801->st, fm801->sh, regno));
-case 4:
-return (bus_space_read_4(fm801->st, fm801->sh, regno));
-default:
-return 0xffffffff;
-}
+ switch(size) {
+ case 1:
+ return (bus_space_read_1(fm801->st, fm801->sh, regno));
+ case 2:
+ return (bus_space_read_2(fm801->st, fm801->sh, regno));
+ case 4:
+ return (bus_space_read_4(fm801->st, fm801->sh, regno));
+ default:
+ return 0xffffffff;
+ }
}
static void
fm801_wr(struct fm801_info *fm801, int regno, u_int32_t data, int size)
{
-switch(size) {
-case 1:
-bus_space_write_1(fm801->st, fm801->sh, regno, data);
-break;
-case 2:
-bus_space_write_2(fm801->st, fm801->sh, regno, data);
-break;
-case 4:
-bus_space_write_4(fm801->st, fm801->sh, regno, data);
-break;
-}
+ switch(size) {
+ case 1:
+ bus_space_write_1(fm801->st, fm801->sh, regno, data);
+ break;
+ case 2:
+ bus_space_write_2(fm801->st, fm801->sh, regno, data);
+ break;
+ case 4:
+ bus_space_write_4(fm801->st, fm801->sh, regno, data);
+ break;
+ }
}
/* -------------------------------------------------------------------- */
/*
-* ac97 codec routines
-*/
+ * ac97 codec routines
+ */
#define TIMO 50
static int
fm801_rdcd(kobj_t obj, void *devinfo, int regno)
{
-struct fm801_info *fm801 = (struct fm801_info *)devinfo;
-int i;
+ struct fm801_info *fm801 = (struct fm801_info *)devinfo;
+ int i;
-for (i = 0; i < TIMO && fm801_rd(fm801,FM_CODEC_CMD,2) & FM_CODEC_CMD_BUSY; i++) {
-DELAY(10000);
-DPRINT("fm801 rdcd: 1 - DELAYn");
-}
-if (i >= TIMO) {
-printf("fm801 rdcd: codec busyn");
-return 0;
-}
+ for (i = 0; i < TIMO && fm801_rd(fm801,FM_CODEC_CMD,2) & FM_CODEC_CMD_BUSY; i++) {
+ DELAY(10000);
+ DPRINT("fm801 rdcd: 1 - DELAY\n");
+ }
+ if (i >= TIMO) {
+ printf("fm801 rdcd: codec busy\n");
+ return 0;
+ }
+
+ fm801_wr(fm801,FM_CODEC_CMD, regno|FM_CODEC_CMD_READ,2);
+
+ for (i = 0; i < TIMO && !(fm801_rd(fm801,FM_CODEC_CMD,2) & FM_CODEC_CMD_VALID); i++)
+ {
+ DELAY(10000);
+ DPRINT("fm801 rdcd: 2 - DELAY\n");
+ }
+ if (i >= TIMO) {
+ printf("fm801 rdcd: write codec invalid\n");
+ return 0;
+ }
-fm801_wr(fm801,FM_CODEC_CMD, regno|FM_CODEC_CMD_READ,2);
-
-for (i = 0; i < TIMO && !(fm801_rd(fm801,FM_CODEC_CMD,2) & FM_CODEC_CMD_VALID); i++)
-{
-DELAY(10000);
-DPRINT("fm801 rdcd: 2 - DELAYn");
-}
-if (i >= TIMO) {
-printf("fm801 rdcd: write codec invalidn");
-return 0;
-}
-
-return fm801_rd(fm801,FM_CODEC_DATA,2);
+ return fm801_rd(fm801,FM_CODEC_DATA,2);
}
static int
fm801_wrcd(kobj_t obj, void *devinfo, int regno, u_int32_t data)
{
-struct fm801_info *fm801 = (struct fm801_info *)devinfo;
-int i;
+ struct fm801_info *fm801 = (struct fm801_info *)devinfo;
+ int i;
-DPRINT("fm801_wrcd reg 0x%x val 0x%xn",regno, data);
+ DPRINT("fm801_wrcd reg 0x%x val 0x%x\n",regno, data);
/*
-if(regno == AC97_REG_RECSEL) return;
+ if(regno == AC97_REG_RECSEL) return;
*/
-/* Poll until codec is ready */
-for (i = 0; i < TIMO && fm801_rd(fm801,FM_CODEC_CMD,2) & FM_CODEC_CMD_BUSY; i++) {
-DELAY(10000);
-DPRINT("fm801 rdcd: 1 - DELAYn");
-}
-if (i >= TIMO) {
-printf("fm801 wrcd: read codec busyn");
-return -1;
-}
-
-fm801_wr(fm801,FM_CODEC_DATA,data, 2);
-fm801_wr(fm801,FM_CODEC_CMD, regno,2);
-
-/* wait until codec is ready */
-for (i = 0; i < TIMO && fm801_rd(fm801,FM_CODEC_CMD,2) & FM_CODEC_CMD_BUSY; i++) {
-DELAY(10000);
-DPRINT("fm801 wrcd: 2 - DELAYn");
-}
-if (i >= TIMO) {
-printf("fm801 wrcd: read codec busyn");
-return -1;
-}
-DPRINT("fm801 wrcd release reg 0x%x val 0x%xn",regno, data);
-return 0;
+ /* Poll until codec is ready */
+ for (i = 0; i < TIMO && fm801_rd(fm801,FM_CODEC_CMD,2) & FM_CODEC_CMD_BUSY; i++) {
+ DELAY(10000);
+ DPRINT("fm801 rdcd: 1 - DELAY\n");
+ }
+ if (i >= TIMO) {
+ printf("fm801 wrcd: read codec busy\n");
+ return -1;
+ }
+
+ fm801_wr(fm801,FM_CODEC_DATA,data, 2);
+ fm801_wr(fm801,FM_CODEC_CMD, regno,2);
+
+ /* wait until codec is ready */
+ for (i = 0; i < TIMO && fm801_rd(fm801,FM_CODEC_CMD,2) & FM_CODEC_CMD_BUSY; i++) {
+ DELAY(10000);
+ DPRINT("fm801 wrcd: 2 - DELAY\n");
+ }
+ if (i >= TIMO) {
+ printf("fm801 wrcd: read codec busy\n");
+ return -1;
+ }
+ DPRINT("fm801 wrcd release reg 0x%x val 0x%x\n",regno, data);
+ return 0;
}
static kobj_method_t fm801_ac97_methods[] = {
-KOBJMETHOD(ac97_read, fm801_rdcd),
-KOBJMETHOD(ac97_write, fm801_wrcd),
-{ 0, 0 }
+ KOBJMETHOD(ac97_read, fm801_rdcd),
+ KOBJMETHOD(ac97_write, fm801_wrcd),
+ { 0, 0 }
};
AC97_DECLARE(fm801_ac97);
/* -------------------------------------------------------------------- */
/*
-* The interrupt handler
-*/
+ * The interrupt handler
+ */
static void
fm801_intr(void *p)
{
-struct fm801_info *fm801 = (struct fm801_info *)p;
-u_int32_t intsrc = fm801_rd(fm801, FM_INTSTATUS, 2);
+ struct fm801_info *fm801 = (struct fm801_info *)p;
+ u_int32_t intsrc = fm801_rd(fm801, FM_INTSTATUS, 2);
-DPRINT("nfm801_intr intsrc 0x%x ", intsrc);
+ DPRINT("\nfm801_intr intsrc 0x%x ", intsrc);
-if(intsrc & FM_INTSTATUS_PLAY) {
-fm801->play_flip++;
-if(fm801->play_flip & 1) {
-fm801_wr(fm801, FM_PLAY_DMABUF1, fm801->play_start,4);
-} else
-fm801_wr(fm801, FM_PLAY_DMABUF2, fm801->play_nextblk,4);
-chn_intr(fm801->pch.channel);
-}
+ if(intsrc & FM_INTSTATUS_PLAY) {
+ fm801->play_flip++;
+ if(fm801->play_flip & 1) {
+ fm801_wr(fm801, FM_PLAY_DMABUF1, fm801->play_start,4);
+ } else
+ fm801_wr(fm801, FM_PLAY_DMABUF2, fm801->play_nextblk,4);
+ chn_intr(fm801->pch.channel);
+ }
+
+ if(intsrc & FM_INTSTATUS_REC) {
+ fm801->rec_flip++;
+ if(fm801->rec_flip & 1) {
+ fm801_wr(fm801, FM_REC_DMABUF1, fm801->rec_start,4);
+ } else
+ fm801_wr(fm801, FM_REC_DMABUF2, fm801->rec_nextblk,4);
+ chn_intr(fm801->rch.channel);
+ }
+
+ if ( intsrc & FM_INTSTATUS_MPU ) {
+ /* This is a TODOish thing... */
+ fm801_wr(fm801, FM_INTSTATUS, intsrc & FM_INTSTATUS_MPU,2);
+ }
+
+ if ( intsrc & FM_INTSTATUS_VOL ) {
+ /* This is a TODOish thing... */
+ fm801_wr(fm801, FM_INTSTATUS, intsrc & FM_INTSTATUS_VOL,2);
+ }
-if(intsrc & FM_INTSTATUS_REC) {
-fm801->rec_flip++;
-if(fm801->rec_flip & 1) {
-fm801_wr(fm801, FM_REC_DMABUF1, fm801->rec_start,4);
-} else
-fm801_wr(fm801, FM_REC_DMABUF2, fm801->rec_nextblk,4);
-chn_intr(fm801->rch.channel);
-}
-
-if ( intsrc & FM_INTSTATUS_MPU ) {
-/* This is a TODOish thing... */
-fm801_wr(fm801, FM_INTSTATUS, intsrc & FM_INTSTATUS_MPU,2);
-}
-
-if ( intsrc & FM_INTSTATUS_VOL ) {
-/* This is a TODOish thing... */
-fm801_wr(fm801, FM_INTSTATUS, intsrc & FM_INTSTATUS_VOL,2);
-}
-
-DPRINT("fm801_intr clearnn");
-fm801_wr(fm801, FM_INTSTATUS, intsrc & (FM_INTSTATUS_PLAY | FM_INTSTATUS_REC), 2);
+ DPRINT("fm801_intr clear\n\n");
+ fm801_wr(fm801, FM_INTSTATUS, intsrc & (FM_INTSTATUS_PLAY | FM_INTSTATUS_REC), 2);
}
/* -------------------------------------------------------------------- */
@@ -326,439 +326,436 @@
static void *
fm801ch_init(kobj_t obj, void *devinfo, struct snd_dbuf *b, struct pcm_channel *c, int dir)
{
-struct fm801_info *fm801 = (struct fm801_info *)devinfo;
-struct fm801_chinfo *ch = (dir == PCMDIR_PLAY)? &fm801->pch : &fm801->rch;
+ struct fm801_info *fm801 = (struct fm801_info *)devinfo;
+ struct fm801_chinfo *ch = (dir == PCMDIR_PLAY)? &fm801->pch : &fm801->rch;
-DPRINT("fm801ch_init, direction = %dn", dir);
-ch->parent = fm801;
-ch->channel = c;
-ch->buffer = b;
-ch->dir = dir;
-if (sndbuf_alloc(ch->buffer, fm801->parent_dmat, fm801->bufsz) != 0)
-return NULL;
-return (void *)ch;
+ DPRINT("fm801ch_init, direction = %d\n", dir);
+ ch->parent = fm801;
+ ch->channel = c;
+ ch->buffer = b;
+ ch->dir = dir;
+ if (sndbuf_alloc(ch->buffer, fm801->parent_dmat, 0, fm801->bufsz) != 0)
+ return NULL;
+ return (void *)ch;
}
static int
fm801ch_setformat(kobj_t obj, void *data, u_int32_t format)
{
-struct fm801_chinfo *ch = data;
-struct fm801_info *fm801 = ch->parent;
-
-DPRINT("fm801ch_setformat 0x%x : %s, %s, %s, %sn", format,
-(format & AFMT_STEREO)?"stereo":"mono",
-(format & (AFMT_S16_LE | AFMT_S16_BE | AFMT_U16_LE | AFMT_U16_BE)) ? "16bit":"8bit",
-(format & AFMT_SIGNED)? "signed":"unsigned",
-(format & AFMT_BIGENDIAN)?"bigendiah":"littleendian" );
-
-if(ch->dir == PCMDIR_PLAY) {
-fm801->play_fmt = (format & AFMT_STEREO)? FM_PLAY_STEREO : 0;
-fm801->play_fmt |= (format & AFMT_16BIT) ? FM_PLAY_16BIT : 0;
-return 0;
-}
+ struct fm801_chinfo *ch = data;
+ struct fm801_info *fm801 = ch->parent;
-if(ch->dir == PCMDIR_REC ) {
-fm801->rec_fmt = (format & AFMT_STEREO)? FM_REC_STEREO:0;
-fm801->rec_fmt |= (format & AFMT_16BIT) ? FM_PLAY_16BIT : 0;
-return 0;
-}
+ DPRINT("fm801ch_setformat 0x%x : %s, %s, %s, %s\n", format,
+ (format & AFMT_STEREO)?"stereo":"mono",
+ (format & (AFMT_S16_LE | AFMT_S16_BE | AFMT_U16_LE | AFMT_U16_BE)) ? "16bit":"8bit",
+ (format & AFMT_SIGNED)? "signed":"unsigned",
+ (format & AFMT_BIGENDIAN)?"bigendiah":"littleendian" );
+
+ if(ch->dir == PCMDIR_PLAY) {
+ fm801->play_fmt = (format & AFMT_STEREO)? FM_PLAY_STEREO : 0;
+ fm801->play_fmt |= (format & AFMT_16BIT) ? FM_PLAY_16BIT : 0;
+ return 0;
+ }
+
+ if(ch->dir == PCMDIR_REC ) {
+ fm801->rec_fmt = (format & AFMT_STEREO)? FM_REC_STEREO:0;
+ fm801->rec_fmt |= (format & AFMT_16BIT) ? FM_PLAY_16BIT : 0;
+ return 0;
+ }
-return 0;
+ return 0;
}
struct {
-int limit;
-int rate;
+ int limit;
+ int rate;
} fm801_rates[11] = {
-{ 6600, 5500 },
-{ 8750, 8000 },
-{ 10250, 9600 },
-{ 13200, 11025 },
-{ 17500, 16000 },
-{ 20500, 19200 },
-{ 26500, 22050 },
-{ 35000, 32000 },
-{ 41000, 38400 },
-{ 46000, 44100 },
-{ 48000, 48000 },
+ { 6600, 5500 },
+ { 8750, 8000 },
+ { 10250, 9600 },
+ { 13200, 11025 },
+ { 17500, 16000 },
+ { 20500, 19200 },
+ { 26500, 22050 },
+ { 35000, 32000 },
+ { 41000, 38400 },
+ { 46000, 44100 },
+ { 48000, 48000 },
/* anything above -> 48000 */
};
static int
fm801ch_setspeed(kobj_t obj, void *data, u_int32_t speed)
{
-struct fm801_chinfo *ch = data;
-struct fm801_info *fm801 = ch->parent;
-register int i;
+ struct fm801_chinfo *ch = data;
+ struct fm801_info *fm801 = ch->parent;
+ register int i;
-for (i = 0; i < 10 && fm801_rates[i].limit <= speed; i++) ;
+ for (i = 0; i < 10 && fm801_rates[i].limit <= speed; i++) ;
-if(ch->dir == PCMDIR_PLAY) {
-fm801->pch.spd = fm801_rates[i].rate;
-fm801->play_shift = (i<<8);
-fm801->play_shift &= FM_PLAY_RATE_MASK;
-}
+ if(ch->dir == PCMDIR_PLAY) {
+ fm801->pch.spd = fm801_rates[i].rate;
+ fm801->play_shift = (i<<8);
+ fm801->play_shift &= FM_PLAY_RATE_MASK;
+ }
-if(ch->dir == PCMDIR_REC ) {
-fm801->rch.spd = fm801_rates[i].rate;
-fm801->rec_shift = (i<<8);
-fm801->rec_shift &= FM_REC_RATE_MASK;
-}
+ if(ch->dir == PCMDIR_REC ) {
+ fm801->rch.spd = fm801_rates[i].rate;
+ fm801->rec_shift = (i<<8);
+ fm801->rec_shift &= FM_REC_RATE_MASK;
+ }
-ch->spd = fm801_rates[i].rate;
+ ch->spd = fm801_rates[i].rate;
-return fm801_rates[i].rate;
+ return fm801_rates[i].rate;
}
static int
fm801ch_setblocksize(kobj_t obj, void *data, u_int32_t blocksize)
{
-struct fm801_chinfo *ch = data;
-struct fm801_info *fm801 = ch->parent;
+ struct fm801_chinfo *ch = data;
+ struct fm801_info *fm801 = ch->parent;
-if(ch->dir == PCMDIR_PLAY) {
-if(fm801->play_flip) return fm801->play_blksize;
-fm801->play_blksize = blocksize;
-}
+ /*
+ * Don't mind for play_flip, set the blocksize to the
+ * desired values in any case - otherwise sound playback
+ * breaks here.
+ */
+ if(ch->dir == PCMDIR_PLAY)
+ fm801->play_blksize = blocksize;
-if(ch->dir == PCMDIR_REC) {
-if(fm801->rec_flip) return fm801->rec_blksize;
-fm801->rec_blksize = blocksize;
-}
+ if(ch->dir == PCMDIR_REC)
+ fm801->rec_blksize = blocksize;
-DPRINT("fm801ch_setblocksize %d (dir %d)n",blocksize, ch->dir);
+ DPRINT("fm801ch_setblocksize %d (dir %d)\n",blocksize, ch->dir);
-return blocksize;
+ return blocksize;
}
static int
fm801ch_trigger(kobj_t obj, void *data, int go)
{
-struct fm801_chinfo *ch = data;
-struct fm801_info *fm801 = ch->parent;
-u_int32_t baseaddr = sndbuf_getbufaddr(ch->buffer);
-u_int32_t k1;
-
-DPRINT("fm801ch_trigger go %d , ", go);
-
-if (go == PCMTRIG_EMLDMAWR || go == PCMTRIG_EMLDMARD) {
-return 0;
-}
-
-if (ch->dir == PCMDIR_PLAY) {
-if (go == PCMTRIG_START) {
-
-fm801->play_start = baseaddr;
-fm801->play_nextblk = fm801->play_start + fm801->play_blksize;
-fm801->play_flip = 0;
-fm801_wr(fm801, FM_PLAY_DMALEN, fm801->play_blksize - 1, 2);
-fm801_wr(fm801, FM_PLAY_DMABUF1,fm801->play_start,4);
-fm801_wr(fm801, FM_PLAY_DMABUF2,fm801->play_nextblk,4);
-fm801_wr(fm801, FM_PLAY_CTL,
-FM_PLAY_START | FM_PLAY_STOPNOW | fm801->play_fmt | fm801->play_shift,
-2 );
-} else {
-fm801->play_flip = 0;
-k1 = fm801_rd(fm801, FM_PLAY_CTL,2);
-fm801_wr(fm801, FM_PLAY_CTL,
-(k1 & ~(FM_PLAY_STOPNOW | FM_PLAY_START)) |
-FM_PLAY_BUF1_LAST | FM_PLAY_BUF2_LAST, 2 );
-}
-} else if(ch->dir == PCMDIR_REC) {
-if (go == PCMTRIG_START) {
-fm801->rec_start = baseaddr;
-fm801->rec_nextblk = fm801->rec_start + fm801->rec_blksize;
-fm801->rec_flip = 0;
-fm801_wr(fm801, FM_REC_DMALEN, fm801->rec_blksize - 1, 2);
-fm801_wr(fm801, FM_REC_DMABUF1,fm801->rec_start,4);
-fm801_wr(fm801, FM_REC_DMABUF2,fm801->rec_nextblk,4);
-fm801_wr(fm801, FM_REC_CTL,
-FM_REC_START | FM_REC_STOPNOW | fm801->rec_fmt | fm801->rec_shift,
-2 );
-} else {
-fm801->rec_flip = 0;
-k1 = fm801_rd(fm801, FM_REC_CTL,2);
-fm801_wr(fm801, FM_REC_CTL,
-(k1 & ~(FM_REC_STOPNOW | FM_REC_START)) |
-FM_REC_BUF1_LAST | FM_REC_BUF2_LAST, 2);
-}
-}
+ struct fm801_chinfo *ch = data;
+ struct fm801_info *fm801 = ch->parent;
+ u_int32_t baseaddr = sndbuf_getbufaddr(ch->buffer);
+ u_int32_t k1;
+
+ DPRINT("fm801ch_trigger go %d , ", go);
+
+ if (!PCMTRIG_COMMON(go))
+ return 0;
+
+ if (ch->dir == PCMDIR_PLAY) {
+ if (go == PCMTRIG_START) {
+
+ fm801->play_start = baseaddr;
+ fm801->play_nextblk = fm801->play_start + fm801->play_blksize;
+ fm801->play_flip = 0;
+ fm801_wr(fm801, FM_PLAY_DMALEN, fm801->play_blksize - 1, 2);
+ fm801_wr(fm801, FM_PLAY_DMABUF1,fm801->play_start,4);
+ fm801_wr(fm801, FM_PLAY_DMABUF2,fm801->play_nextblk,4);
+ fm801_wr(fm801, FM_PLAY_CTL,
+ FM_PLAY_START | FM_PLAY_STOPNOW | fm801->play_fmt | fm801->play_shift,
+ 2 );
+ } else {
+ fm801->play_flip = 0;
+ k1 = fm801_rd(fm801, FM_PLAY_CTL,2);
+ fm801_wr(fm801, FM_PLAY_CTL,
+ (k1 & ~(FM_PLAY_STOPNOW | FM_PLAY_START)) |
+ FM_PLAY_BUF1_LAST | FM_PLAY_BUF2_LAST, 2 );
+ }
+ } else if(ch->dir == PCMDIR_REC) {
+ if (go == PCMTRIG_START) {
+ fm801->rec_start = baseaddr;
+ fm801->rec_nextblk = fm801->rec_start + fm801->rec_blksize;
+ fm801->rec_flip = 0;
+ fm801_wr(fm801, FM_REC_DMALEN, fm801->rec_blksize - 1, 2);
+ fm801_wr(fm801, FM_REC_DMABUF1,fm801->rec_start,4);
+ fm801_wr(fm801, FM_REC_DMABUF2,fm801->rec_nextblk,4);
+ fm801_wr(fm801, FM_REC_CTL,
+ FM_REC_START | FM_REC_STOPNOW | fm801->rec_fmt | fm801->rec_shift,
+ 2 );
+ } else {
+ fm801->rec_flip = 0;
+ k1 = fm801_rd(fm801, FM_REC_CTL,2);
+ fm801_wr(fm801, FM_REC_CTL,
+ (k1 & ~(FM_REC_STOPNOW | FM_REC_START)) |
+ FM_REC_BUF1_LAST | FM_REC_BUF2_LAST, 2);
+ }
+ }
-return 0;
+ return 0;
}
/* Almost ALSA copy */
static int
fm801ch_getptr(kobj_t obj, void *data)
{
-struct fm801_chinfo *ch = data;
-struct fm801_info *fm801 = ch->parent;
-int result = 0;
-
-if (ch->dir == PCMDIR_PLAY) {
-result = fm801_rd(fm801,
-(fm801->play_flip&1) ?
-FM_PLAY_DMABUF2:FM_PLAY_DMABUF1, 4) - fm801->play_start;
-}
-
-if (ch->dir == PCMDIR_REC) {
-result = fm801_rd(fm801,
-(fm801->rec_flip&1) ?
-FM_REC_DMABUF2:FM_REC_DMABUF1, 4) - fm801->rec_start;
-}
+ struct fm801_chinfo *ch = data;
+ struct fm801_info *fm801 = ch->parent;
+ int result = 0;
+
+ if (ch->dir == PCMDIR_PLAY) {
+ result = fm801_rd(fm801,
+ (fm801->play_flip&1) ?
+ FM_PLAY_DMABUF2:FM_PLAY_DMABUF1, 4) - fm801->play_start;
+ }
+
+ if (ch->dir == PCMDIR_REC) {
+ result = fm801_rd(fm801,
+ (fm801->rec_flip&1) ?
+ FM_REC_DMABUF2:FM_REC_DMABUF1, 4) - fm801->rec_start;
+ }
-return result;
+ return result;
}
static struct pcmchan_caps *
fm801ch_getcaps(kobj_t obj, void *data)
{
-return &fm801ch_caps;
+ return &fm801ch_caps;
}
static kobj_method_t fm801ch_methods[] = {
-KOBJMETHOD(channel_init, fm801ch_init),
-KOBJMETHOD(channel_setformat, fm801ch_setformat),
-KOBJMETHOD(channel_setspeed, fm801ch_setspeed),
-KOBJMETHOD(channel_setblocksize, fm801ch_setblocksize),
-KOBJMETHOD(channel_trigger, fm801ch_trigger),
-KOBJMETHOD(channel_getptr, fm801ch_getptr),
-KOBJMETHOD(channel_getcaps, fm801ch_getcaps),
-{ 0, 0 }
+ KOBJMETHOD(channel_init, fm801ch_init),
+ KOBJMETHOD(channel_setformat, fm801ch_setformat),
+ KOBJMETHOD(channel_setspeed, fm801ch_setspeed),
+ KOBJMETHOD(channel_setblocksize, fm801ch_setblocksize),
+ KOBJMETHOD(channel_trigger, fm801ch_trigger),
+ KOBJMETHOD(channel_getptr, fm801ch_getptr),
+ KOBJMETHOD(channel_getcaps, fm801ch_getcaps),
+ { 0, 0 }
};
CHANNEL_DECLARE(fm801ch);
/* -------------------------------------------------------------------- */
/*
-* Init routine is taken from an original NetBSD driver
-*/
+ * Init routine is taken from an original NetBSD driver
+ */
static int
fm801_init(struct fm801_info *fm801)
{
-u_int32_t k1;
+ u_int32_t k1;
-/* reset codec */
-fm801_wr(fm801, FM_CODEC_CTL, 0x0020,2);
-DELAY(100000);
-fm801_wr(fm801, FM_CODEC_CTL, 0x0000,2);
-DELAY(100000);
-
-fm801_wr(fm801, FM_PCM_VOLUME, 0x0808,2);
-fm801_wr(fm801, FM_FM_VOLUME, 0x0808,2);
-fm801_wr(fm801, FM_I2S_VOLUME, 0x0808,2);
-fm801_wr(fm801, 0x40,0x107f,2); /* enable legacy audio */
-
-fm801_wr((void *)fm801, FM_RECORD_SOURCE, 0x0000,2);
-
-/* Unmask playback, record and mpu interrupts, mask the rest */
-k1 = fm801_rd((void *)fm801, FM_INTMASK,2);
-fm801_wr(fm801, FM_INTMASK,
-(k1 & ~(FM_INTMASK_PLAY | FM_INTMASK_REC | FM_INTMASK_MPU)) |
-FM_INTMASK_VOL,2);
-fm801_wr(fm801, FM_INTSTATUS,
-FM_INTSTATUS_PLAY | FM_INTSTATUS_REC | FM_INTSTATUS_MPU |
-FM_INTSTATUS_VOL,2);
+ /* reset codec */
+ fm801_wr(fm801, FM_CODEC_CTL, 0x0020,2);
+ DELAY(100000);
+ fm801_wr(fm801, FM_CODEC_CTL, 0x0000,2);
+ DELAY(100000);
+
+ fm801_wr(fm801, FM_PCM_VOLUME, 0x0808,2);
+ fm801_wr(fm801, FM_FM_VOLUME, 0x0808,2);
+ fm801_wr(fm801, FM_I2S_VOLUME, 0x0808,2);
+ fm801_wr(fm801, 0x40,0x107f,2); /* enable legacy audio */
+
+ fm801_wr((void *)fm801, FM_RECORD_SOURCE, 0x0000,2);
+
+ /* Unmask playback, record and mpu interrupts, mask the rest */
+ k1 = fm801_rd((void *)fm801, FM_INTMASK,2);
+ fm801_wr(fm801, FM_INTMASK,
+ (k1 & ~(FM_INTMASK_PLAY | FM_INTMASK_REC | FM_INTMASK_MPU)) |
+ FM_INTMASK_VOL,2);
+ fm801_wr(fm801, FM_INTSTATUS,
+ FM_INTSTATUS_PLAY | FM_INTSTATUS_REC | FM_INTSTATUS_MPU |
+ FM_INTSTATUS_VOL,2);
-DPRINT("FM801 init Okn");
-return 0;
+ DPRINT("FM801 init Ok\n");
+ return 0;
}
static int
fm801_pci_attach(device_t dev)
{
-u_int32_t data;
-struct ac97_info *codec = 0;
-struct fm801_info *fm801;
-int i;
-int mapped = 0;
-char status[SND_STATUSLEN];
-
-if ((fm801 = (struct fm801_info *)malloc(sizeof(*fm801), M_DEVBUF, M_NOWAIT | M_ZERO)) == NULL) {
-device_printf(dev, "cannot allocate softcn");
-return ENXIO;
-}
-
-fm801->type = pci_get_devid(dev);
-
-data = pci_read_config(dev, PCIR_COMMAND, 2);
-data |= (PCIM_CMD_PORTEN|PCIM_CMD_MEMEN|PCIM_CMD_BUSMASTEREN);
-pci_write_config(dev, PCIR_COMMAND, data, 2);
-data = pci_read_config(dev, PCIR_COMMAND, 2);
-
-for (i = 0; (mapped == 0) && (i < PCI_MAXMAPS_0); i++) {
-fm801->regid = PCIR_BAR(i);
-fm801->regtype = SYS_RES_MEMORY;
-fm801->reg = bus_alloc_resource_any(dev, fm801->regtype,
-&fm801->regid, RF_ACTIVE);
-if(!fm801->reg)
-{
-fm801->regtype = SYS_RES_IOPORT;
-fm801->reg = bus_alloc_resource_any(dev,
-fm801->regtype,
-&fm801->regid,
-RF_ACTIVE);
-}
-
-if(fm801->reg) {
-fm801->st = rman_get_bustag(fm801->reg);
-fm801->sh = rman_get_bushandle(fm801->reg);
-mapped++;
-}
-}
-
-if (mapped == 0) {
-device_printf(dev, "unable to map register spacen");
-goto oops;
-}
-
-fm801->bufsz = pcm_getbuffersize(dev, 4096, FM801_DEFAULT_BUFSZ, 65536);
-
-fm801_init(fm801);
-
-codec = AC97_CREATE(dev, fm801, fm801_ac97);
-if (codec == NULL) goto oops;
-
-if (mixer_init(dev, ac97_getmixerclass(), codec) == -1) goto oops;
-
-fm801->irqid = 0;
-fm801->irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &fm801->irqid,
-RF_ACTIVE | RF_SHAREABLE);
-if (!fm801->irq || snd_setup_intr(dev, fm801->irq, 0, fm801_intr, fm801, &fm801->ih)) {
-device_printf(dev, "unable to map interruptn");
-goto oops;
-}
-
-if (bus_dma_tag_create(/*parent*/NULL, /*alignment*/2, /*boundary*/0,
-/*lowaddr*/BUS_SPACE_MAXADDR_32BIT,
-/*highaddr*/BUS_SPACE_MAXADDR,
-/*filter*/NULL, /*filterarg*/NULL,
-/*maxsize*/fm801->bufsz, /*nsegments*/1, /*maxsegz*/0x3ffff,
-/*flags*/0, /*lockfunc*/busdma_lock_mutex,
-/*lockarg*/&Giant, &fm801->parent_dmat) != 0) {
-device_printf(dev, "unable to create dma tagn");
-goto oops;
-}
-
-snprintf(status, 64, "at %s 0x%lx irq %ld %s",
-(fm801->regtype == SYS_RES_IOPORT)? "io" : "memory",
-rman_get_start(fm801->reg), rman_get_start(fm801->irq),PCM_KLDSTRING(snd_fm801));
+ u_int32_t data;
+ struct ac97_info *codec = 0;
+ struct fm801_info *fm801;
+ int i;
+ int mapped = 0;
+ char status[SND_STATUSLEN];
+
+ fm801 = malloc(sizeof(*fm801), M_DEVBUF, M_WAITOK | M_ZERO);
+ fm801->type = pci_get_devid(dev);
+
+ data = pci_read_config(dev, PCIR_COMMAND, 2);
+ data |= (PCIM_CMD_PORTEN|PCIM_CMD_MEMEN|PCIM_CMD_BUSMASTEREN);
+ pci_write_config(dev, PCIR_COMMAND, data, 2);
+ data = pci_read_config(dev, PCIR_COMMAND, 2);
+
+ for (i = 0; (mapped == 0) && (i < PCI_MAXMAPS_0); i++) {
+ fm801->regid = PCIR_BAR(i);
+ fm801->regtype = SYS_RES_MEMORY;
+ fm801->reg = bus_alloc_resource_any(dev, fm801->regtype,
+ &fm801->regid, RF_ACTIVE);
+ if(!fm801->reg)
+ {
+ fm801->regtype = SYS_RES_IOPORT;
+ fm801->reg = bus_alloc_resource_any(dev,
+ fm801->regtype,
+ &fm801->regid,
+ RF_ACTIVE);
+ }
+
+ if(fm801->reg) {
+ fm801->st = rman_get_bustag(fm801->reg);
+ fm801->sh = rman_get_bushandle(fm801->reg);
+ mapped++;
+ }
+ }
+
+ if (mapped == 0) {
+ device_printf(dev, "unable to map register space\n");
+ goto oops;
+ }
+
+ fm801->bufsz = pcm_getbuffersize(dev, 4096, FM801_DEFAULT_BUFSZ, 65536);
+
+ fm801_init(fm801);
+
+ codec = AC97_CREATE(dev, fm801, fm801_ac97);
+ if (codec == NULL) goto oops;
+
+ if (mixer_init(dev, ac97_getmixerclass(), codec) == -1) goto oops;
+
+ fm801->irqid = 0;
+ fm801->irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &fm801->irqid,
+ RF_ACTIVE | RF_SHAREABLE);
+ if (!fm801->irq || snd_setup_intr(dev, fm801->irq, 0, fm801_intr, fm801, &fm801->ih)) {
+ device_printf(dev, "unable to map interrupt\n");
+ goto oops;
+ }
+
+ if (bus_dma_tag_create(/*parent*/bus_get_dma_tag(dev), /*alignment*/2,
+ /*boundary*/0,
+ /*lowaddr*/BUS_SPACE_MAXADDR_32BIT,
+ /*highaddr*/BUS_SPACE_MAXADDR,
+ /*filter*/NULL, /*filterarg*/NULL,
+ /*maxsize*/fm801->bufsz, /*nsegments*/1, /*maxsegz*/0x3ffff,
+ /*flags*/0, /*lockfunc*/busdma_lock_mutex,
+ /*lockarg*/&Giant, &fm801->parent_dmat) != 0) {
+ device_printf(dev, "unable to create dma tag\n");
+ goto oops;
+ }
+
+ snprintf(status, 64, "at %s 0x%lx irq %ld %s",
+ (fm801->regtype == SYS_RES_IOPORT)? "io" : "memory",
+ rman_get_start(fm801->reg), rman_get_start(fm801->irq),PCM_KLDSTRING(snd_fm801));
#define FM801_MAXPLAYCH 1
-if (pcm_register(dev, fm801, FM801_MAXPLAYCH, 1)) goto oops;
-pcm_addchan(dev, PCMDIR_PLAY, &fm801ch_class, fm801);
-pcm_addchan(dev, PCMDIR_REC, &fm801ch_class, fm801);
-pcm_setstatus(dev, status);
+ if (pcm_register(dev, fm801, FM801_MAXPLAYCH, 1)) goto oops;
+ pcm_addchan(dev, PCMDIR_PLAY, &fm801ch_class, fm801);
+ pcm_addchan(dev, PCMDIR_REC, &fm801ch_class, fm801);
+ pcm_setstatus(dev, status);
-fm801->radio = device_add_child(dev, "radio", -1);
-bus_generic_attach(dev);
+ fm801->radio = device_add_child(dev, "radio", -1);
+ bus_generic_attach(dev);
-return 0;
+ return 0;
oops:
-if (codec) ac97_destroy(codec);
-if (fm801->reg) bus_release_resource(dev, fm801->regtype, fm801->regid, fm801->reg);
-if (fm801->ih) bus_teardown_intr(dev, fm801->irq, fm801->ih);
-if (fm801->irq) bus_release_resource(dev, SYS_RES_IRQ, fm801->irqid, fm801->irq);
-if (fm801->parent_dmat) bus_dma_tag_destroy(fm801->parent_dmat);
-free(fm801, M_DEVBUF);
-return ENXIO;
+ if (codec) ac97_destroy(codec);
+ if (fm801->reg) bus_release_resource(dev, fm801->regtype, fm801->regid, fm801->reg);
+ if (fm801->ih) bus_teardown_intr(dev, fm801->irq, fm801->ih);
+ if (fm801->irq) bus_release_resource(dev, SYS_RES_IRQ, fm801->irqid, fm801->irq);
+ if (fm801->parent_dmat) bus_dma_tag_destroy(fm801->parent_dmat);
+ free(fm801, M_DEVBUF);
+ return ENXIO;
}
static int
fm801_pci_detach(device_t dev)
{
-int r;
-struct fm801_info *fm801;
+ int r;
+ struct fm801_info *fm801;
-DPRINT("Forte Media FM801 detachn");
+ DPRINT("Forte Media FM801 detach\n");
-fm801 = pcm_getdevinfo(dev);
+ fm801 = pcm_getdevinfo(dev);
-r = bus_generic_detach(dev);
-if (r)
-return r;
-if (fm801->radio != NULL) {
-r = device_delete_child(dev, fm801->radio);
-if (r)
-return r;
-fm801->radio = NULL;
-}
-
-r = pcm_unregister(dev);
-if (r)
-return r;
-
-bus_release_resource(dev, fm801->regtype, fm801->regid, fm801->reg);
-bus_teardown_intr(dev, fm801->irq, fm801->ih);
-bus_release_resource(dev, SYS_RES_IRQ, fm801->irqid, fm801->irq);
-bus_dma_tag_destroy(fm801->parent_dmat);
-free(fm801, M_DEVBUF);
-return 0;
+ r = bus_generic_detach(dev);
+ if (r)
+ return r;
+ if (fm801->radio != NULL) {
+ r = device_delete_child(dev, fm801->radio);
+ if (r)
+ return r;
+ fm801->radio = NULL;
+ }
+
+ r = pcm_unregister(dev);
+ if (r)
+ return r;
+
+ bus_release_resource(dev, fm801->regtype, fm801->regid, fm801->reg);
+ bus_teardown_intr(dev, fm801->irq, fm801->ih);
+ bus_release_resource(dev, SYS_RES_IRQ, fm801->irqid, fm801->irq);
+ bus_dma_tag_destroy(fm801->parent_dmat);
+ free(fm801, M_DEVBUF);
+ return 0;
}
static int
fm801_pci_probe( device_t dev )
{
-int id;
+ int id;
-if ((id = pci_get_devid(dev)) == PCI_DEVICE_FORTEMEDIA1 ) {
-device_set_desc(dev, "Forte Media FM801 Audio Controller");
-return BUS_PROBE_DEFAULT;
-}
+ if ((id = pci_get_devid(dev)) == PCI_DEVICE_FORTEMEDIA1 ) {
+ device_set_desc(dev, "Forte Media FM801 Audio Controller");
+ return BUS_PROBE_DEFAULT;
+ }
/*
-if ((id = pci_get_devid(dev)) == PCI_DEVICE_FORTEMEDIA2 ) {
-device_set_desc(dev, "Forte Media FM801 Joystick (Not Supported)");
-return ENXIO;
-}
+ if ((id = pci_get_devid(dev)) == PCI_DEVICE_FORTEMEDIA2 ) {
+ device_set_desc(dev, "Forte Media FM801 Joystick (Not Supported)");
+ return ENXIO;
+ }
*/
-return ENXIO;
+ return ENXIO;
}
static struct resource *
fm801_alloc_resource(device_t bus, device_t child, int type, int *rid,
-u_long start, u_long end, u_long count, u_int flags)
+ u_long start, u_long end, u_long count, u_int flags)
{
-struct fm801_info *fm801;
+ struct fm801_info *fm801;
-fm801 = pcm_getdevinfo(bus);
+ fm801 = pcm_getdevinfo(bus);
-if (type == SYS_RES_IOPORT && *rid == PCIR_BAR(0))
-return (fm801->reg);
+ if (type == SYS_RES_IOPORT && *rid == PCIR_BAR(0))
+ return (fm801->reg);
-return (NULL);
+ return (NULL);
}
static int
fm801_release_resource(device_t bus, device_t child, int type, int rid,
-struct resource *r)
+ struct resource *r)
{
-return (0);
+ return (0);
}
static device_method_t fm801_methods[] = {
-/* Device interface */
-DEVMETHOD(device_probe, fm801_pci_probe),
-DEVMETHOD(device_attach, fm801_pci_attach),
-DEVMETHOD(device_detach, fm801_pci_detach),
-DEVMETHOD(device_shutdown, bus_generic_shutdown),
-DEVMETHOD(device_suspend, bus_generic_suspend),
-DEVMETHOD(device_resume, bus_generic_resume),
-
-/* Bus interface */
-DEVMETHOD(bus_print_child, bus_generic_print_child),
-DEVMETHOD(bus_alloc_resource, fm801_alloc_resource),
-DEVMETHOD(bus_release_resource, fm801_release_resource),
-DEVMETHOD(bus_activate_resource, bus_generic_activate_resource),
-DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource),
-{ 0, 0}
+ /* Device interface */
+ DEVMETHOD(device_probe, fm801_pci_probe),
+ DEVMETHOD(device_attach, fm801_pci_attach),
+ DEVMETHOD(device_detach, fm801_pci_detach),
+ DEVMETHOD(device_shutdown, bus_generic_shutdown),
+ DEVMETHOD(device_suspend, bus_generic_suspend),
+ DEVMETHOD(device_resume, bus_generic_resume),
+
+ /* Bus interface */
+ DEVMETHOD(bus_print_child, bus_generic_print_child),
+ DEVMETHOD(bus_alloc_resource, fm801_alloc_resource),
+ DEVMETHOD(bus_release_resource, fm801_release_resource),
+ DEVMETHOD(bus_activate_resource, bus_generic_activate_resource),
+ DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource),
+ { 0, 0}
};
static driver_t fm801_driver = {
-"pcm",
-fm801_methods,
-PCM_SOFTC_SIZE,
+ "pcm",
+ fm801_methods,
+ PCM_SOFTC_SIZE,
};
DRIVER_MODULE(snd_fm801, pci, fm801_driver, pcm_devclass, 0, 0);
Index: maestro.c
===================================================================
RCS file: /home/cvs/src/sys/dev/sound/pci/maestro.c,v
retrieving revision 1.2
retrieving revision 1.3
diff -L sys/dev/sound/pci/maestro.c -L sys/dev/sound/pci/maestro.c -u -r1.2 -r1.3
--- sys/dev/sound/pci/maestro.c
+++ sys/dev/sound/pci/maestro.c
@@ -1,51 +1,51 @@
/*-
-* Copyright (c) 2000-2004 Taku YAMAMOTO <taku at tackymt.homeip.net>
-* All rights reserved.
-*
-* Redistribution and use in source and binary forms, with or without
-* modification, are permitted provided that the following conditions
-* are met:
-* 1. Redistributions of source code must retain the above copyright
-* notice, this list of conditions and the following disclaimer.
-* 2. Redistributions in binary form must reproduce the above copyright
-* notice, this list of conditions and the following disclaimer in the
-* documentation and/or other materials provided with the distribution.
-*
-* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
-* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
-* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
-* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
-* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
-* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
-* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
-* SUCH DAMAGE.
-*
-* maestro.c,v 1.23.2.1 2003/10/03 18:21:38 taku Exp
-*/
+ * Copyright (c) 2000-2004 Taku YAMAMOTO <taku at tackymt.homeip.net>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * maestro.c,v 1.23.2.1 2003/10/03 18:21:38 taku Exp
+ */
/*
-* Credits:
-*
-* Part of this code (especially in many magic numbers) was heavily inspired
-* by the Linux driver originally written by
-* Alan Cox <alan.cox at linux.org>, modified heavily by
-* Zach Brown <zab at zabbo.net>.
-*
-* busdma()-ize and buffer size reduction were suggested by
-* Cameron Grant <cg at freebsd.org>.
-* Also he showed me the way to use busdma() suite.
-*
-* Internal speaker problems on NEC VersaPro's and Dell Inspiron 7500
-* were looked at by
-* Munehiro Matsuda <haro at tk.kubota.co.jp>,
-* who brought patches based on the Linux driver with some simplification.
-*
-* Hardware volume controller was implemented by
-* John Baldwin <jhb at freebsd.org>.
-*/
+ * Credits:
+ *
+ * Part of this code (especially in many magic numbers) was heavily inspired
+ * by the Linux driver originally written by
+ * Alan Cox <alan.cox at linux.org>, modified heavily by
+ * Zach Brown <zab at zabbo.net>.
+ *
+ * busdma()-ize and buffer size reduction were suggested by
+ * Cameron Grant <cg at freebsd.org>.
+ * Also he showed me the way to use busdma() suite.
+ *
+ * Internal speaker problems on NEC VersaPro's and Dell Inspiron 7500
+ * were looked at by
+ * Munehiro Matsuda <haro at tk.kubota.co.jp>,
+ * who brought patches based on the Linux driver with some simplification.
+ *
+ * Hardware volume controller was implemented by
+ * John Baldwin <jhb at freebsd.org>.
+ */
#include <dev/sound/pcm/sound.h>
#include <dev/sound/pcm/ac97.h>
@@ -54,18 +54,15 @@
#include <dev/sound/pci/maestro_reg.h>
-SND_DECLARE_FILE("$MidnightBSD$");
-
-
-#define inline __inline
+SND_DECLARE_FILE("$FreeBSD: src/sys/dev/sound/pci/maestro.c,v 1.36.2.1 2007/12/15 04:07:25 ariff Exp $");
/*
-* PCI IDs of supported chips:
-*
-* MAESTRO-1 0x01001285
-* MAESTRO-2 0x1968125d
-* MAESTRO-2E 0x1978125d
-*/
+ * PCI IDs of supported chips:
+ *
+ * MAESTRO-1 0x01001285
+ * MAESTRO-2 0x1968125d
+ * MAESTRO-2E 0x1978125d
+ */
#define MAESTRO_1_PCI_ID 0x01001285
#define MAESTRO_2_PCI_ID 0x1968125d
@@ -98,89 +95,89 @@
/* -----------------------------
-* Data structures.
-*/
+ * Data structures.
+ */
struct agg_chinfo {
-/* parent softc */
-struct agg_info *parent;
+ /* parent softc */
+ struct agg_info *parent;
-/* FreeBSD newpcm related */
-struct pcm_channel *channel;
-struct snd_dbuf *buffer;
-
-/* OS independent */
-bus_addr_t phys; /* channel buffer physical address */
-bus_addr_t base; /* channel buffer segment base */
-u_int32_t blklen; /* DMA block length in WORDs */
-u_int32_t buflen; /* channel buffer length in WORDs */
-u_int32_t speed;
-unsigned num : 3;
-unsigned stereo : 1;
-unsigned qs16 : 1; /* quantum size is 16bit */
-unsigned us : 1; /* in unsigned format */
+ /* FreeBSD newpcm related */
+ struct pcm_channel *channel;
+ struct snd_dbuf *buffer;
+
+ /* OS independent */
+ bus_addr_t phys; /* channel buffer physical address */
+ bus_addr_t base; /* channel buffer segment base */
+ u_int32_t blklen; /* DMA block length in WORDs */
+ u_int32_t buflen; /* channel buffer length in WORDs */
+ u_int32_t speed;
+ unsigned num : 3;
+ unsigned stereo : 1;
+ unsigned qs16 : 1; /* quantum size is 16bit */
+ unsigned us : 1; /* in unsigned format */
};
struct agg_rchinfo {
-/* parent softc */
-struct agg_info *parent;
+ /* parent softc */
+ struct agg_info *parent;
-/* FreeBSD newpcm related */
-struct pcm_channel *channel;
-struct snd_dbuf *buffer;
-
-/* OS independent */
-bus_addr_t phys; /* channel buffer physical address */
-bus_addr_t base; /* channel buffer segment base */
-u_int32_t blklen; /* DMA block length in WORDs */
-u_int32_t buflen; /* channel buffer length in WORDs */
-u_int32_t speed;
-unsigned : 3;
-unsigned stereo : 1;
-bus_addr_t srcphys;
-int16_t *src; /* stereo peer buffer */
-int16_t *sink; /* channel buffer pointer */
-volatile u_int32_t hwptr; /* ready point in 16bit sample */
+ /* FreeBSD newpcm related */
+ struct pcm_channel *channel;
+ struct snd_dbuf *buffer;
+
+ /* OS independent */
+ bus_addr_t phys; /* channel buffer physical address */
+ bus_addr_t base; /* channel buffer segment base */
+ u_int32_t blklen; /* DMA block length in WORDs */
+ u_int32_t buflen; /* channel buffer length in WORDs */
+ u_int32_t speed;
+ unsigned : 3;
+ unsigned stereo : 1;
+ bus_addr_t srcphys;
+ int16_t *src; /* stereo peer buffer */
+ int16_t *sink; /* channel buffer pointer */
+ volatile u_int32_t hwptr; /* ready point in 16bit sample */
};
struct agg_info {
-/* FreeBSD newbus related */
-device_t dev;
+ /* FreeBSD newbus related */
+ device_t dev;
-/* I wonder whether bus_space_* are in common in *BSD... */
-struct resource *reg;
-int regid;
-bus_space_tag_t st;
-bus_space_handle_t sh;
-
-struct resource *irq;
-int irqid;
-void *ih;
+ /* I wonder whether bus_space_* are in common in *BSD... */
+ struct resource *reg;
+ int regid;
+ bus_space_tag_t st;
+ bus_space_handle_t sh;
+
+ struct resource *irq;
+ int irqid;
+ void *ih;
-bus_dma_tag_t buf_dmat;
-bus_dma_tag_t stat_dmat;
+ bus_dma_tag_t buf_dmat;
+ bus_dma_tag_t stat_dmat;
-/* FreeBSD SMPng related */
+ /* FreeBSD SMPng related */
#ifdef USING_MUTEX
-struct mtx lock; /* mutual exclusion */
+ struct mtx lock; /* mutual exclusion */
#endif
-/* FreeBSD newpcm related */
-struct ac97_info *codec;
+ /* FreeBSD newpcm related */
+ struct ac97_info *codec;
-/* OS independent */
-u_int8_t *stat; /* status buffer pointer */
-bus_addr_t phys; /* status buffer physical address */
-unsigned int bufsz; /* channel buffer size in bytes */
-u_int playchns;
-volatile u_int active;
-struct agg_chinfo pch[AGG_MAXPLAYCH];
-struct agg_rchinfo rch;
-volatile u_int8_t curpwr; /* current power status: D[0-3] */
+ /* OS independent */
+ u_int8_t *stat; /* status buffer pointer */
+ bus_addr_t phys; /* status buffer physical address */
+ unsigned int bufsz; /* channel buffer size in bytes */
+ u_int playchns;
+ volatile u_int active;
+ struct agg_chinfo pch[AGG_MAXPLAYCH];
+ struct agg_rchinfo rch;
+ volatile u_int8_t curpwr; /* current power status: D[0-3] */
};
/* -----------------------------
-* Sysctls for debug.
-*/
+ * Sysctls for debug.
+ */
static unsigned int powerstate_active = PCI_POWERSTATE_D1;
#ifdef MAESTRO_AGGRESSIVE_POWERSAVE
static unsigned int powerstate_idle = PCI_POWERSTATE_D2;
@@ -189,644 +186,650 @@
#endif
static unsigned int powerstate_init = PCI_POWERSTATE_D2;
+/* XXX: this should move to a device specific sysctl dev.pcm.X.debug.Y via
+ device_get_sysctl_*() as discussed on multimedia@ in msg-id
+ <861wujij2q.fsf at xps.des.no> */
SYSCTL_NODE(_debug, OID_AUTO, maestro, CTLFLAG_RD, 0, "");
SYSCTL_UINT(_debug_maestro, OID_AUTO, powerstate_active, CTLFLAG_RW,
-&powerstate_active, 0, "The Dx power state when active (0-1)");
+ &powerstate_active, 0, "The Dx power state when active (0-1)");
SYSCTL_UINT(_debug_maestro, OID_AUTO, powerstate_idle, CTLFLAG_RW,
-&powerstate_idle, 0, "The Dx power state when idle (0-2)");
+ &powerstate_idle, 0, "The Dx power state when idle (0-2)");
SYSCTL_UINT(_debug_maestro, OID_AUTO, powerstate_init, CTLFLAG_RW,
-&powerstate_init, 0, "The Dx power state prior to the first use (0-2)");
+ &powerstate_init, 0,
+ "The Dx power state prior to the first use (0-2)");
/* -----------------------------
-* Prototypes
-*/
+ * Prototypes
+ */
-static inline void agg_lock(struct agg_info*);
-static inline void agg_unlock(struct agg_info*);
-static inline void agg_sleep(struct agg_info*, const char *wmesg, int msec);
-
-static inline u_int32_t agg_rd(struct agg_info*, int, int size);
-static inline void agg_wr(struct agg_info*, int, u_int32_t data, int size);
-
-static inline int agg_rdcodec(struct agg_info*, int);
-static inline int agg_wrcodec(struct agg_info*, int, u_int32_t);
-
-static inline void ringbus_setdest(struct agg_info*, int, int);
-
-static inline u_int16_t wp_rdreg(struct agg_info*, u_int16_t);
-static inline void wp_wrreg(struct agg_info*, u_int16_t, u_int16_t);
-static inline u_int16_t wp_rdapu(struct agg_info*, unsigned, u_int16_t);
-static inline void wp_wrapu(struct agg_info*, unsigned, u_int16_t, u_int16_t);
-static inline void wp_settimer(struct agg_info*, u_int);
-static inline void wp_starttimer(struct agg_info*);
-static inline void wp_stoptimer(struct agg_info*);
-
-static inline u_int16_t wc_rdreg(struct agg_info*, u_int16_t);
-static inline void wc_wrreg(struct agg_info*, u_int16_t, u_int16_t);
-static inline u_int16_t wc_rdchctl(struct agg_info*, int);
-static inline void wc_wrchctl(struct agg_info*, int, u_int16_t);
-
-static inline void agg_stopclock(struct agg_info*, int part, int st);
-
-static inline void agg_initcodec(struct agg_info*);
-static void agg_init(struct agg_info*);
-static void agg_power(struct agg_info*, int);
-
-static void aggch_start_dac(struct agg_chinfo*);
-static void aggch_stop_dac(struct agg_chinfo*);
-static void aggch_start_adc(struct agg_rchinfo*);
-static void aggch_stop_adc(struct agg_rchinfo*);
-static void aggch_feed_adc_stereo(struct agg_rchinfo*);
-static void aggch_feed_adc_mono(struct agg_rchinfo*);
-
-static inline void suppress_jitter(struct agg_chinfo*);
-static inline void suppress_rec_jitter(struct agg_rchinfo*);
-
-static void set_timer(struct agg_info*);
-
-static void agg_intr(void *);
-static int agg_probe(device_t);
-static int agg_attach(device_t);
-static int agg_detach(device_t);
-static int agg_suspend(device_t);
-static int agg_resume(device_t);
-static int agg_shutdown(device_t);
+static void agg_sleep(struct agg_info*, const char *wmesg, int msec);
-static void *dma_malloc(bus_dma_tag_t, u_int32_t, bus_addr_t*);
-static void dma_free(bus_dma_tag_t, void *);
+static __inline u_int32_t agg_rd(struct agg_info*, int, int size);
+static __inline void agg_wr(struct agg_info*, int, u_int32_t data,
+ int size);
+static int agg_rdcodec(struct agg_info*, int);
+static int agg_wrcodec(struct agg_info*, int, u_int32_t);
+
+static void ringbus_setdest(struct agg_info*, int, int);
+
+static u_int16_t wp_rdreg(struct agg_info*, u_int16_t);
+static void wp_wrreg(struct agg_info*, u_int16_t, u_int16_t);
+static u_int16_t wp_rdapu(struct agg_info*, unsigned, u_int16_t);
+static void wp_wrapu(struct agg_info*, unsigned, u_int16_t, u_int16_t);
+static void wp_settimer(struct agg_info*, u_int);
+static void wp_starttimer(struct agg_info*);
+static void wp_stoptimer(struct agg_info*);
+#if 0
+static u_int16_t wc_rdreg(struct agg_info*, u_int16_t);
+#endif
+static void wc_wrreg(struct agg_info*, u_int16_t, u_int16_t);
+#if 0
+static u_int16_t wc_rdchctl(struct agg_info*, int);
+#endif
+static void wc_wrchctl(struct agg_info*, int, u_int16_t);
-/* -----------------------------
-* Subsystems.
-*/
+static void agg_stopclock(struct agg_info*, int part, int st);
-/* locking */
+static void agg_initcodec(struct agg_info*);
+static void agg_init(struct agg_info*);
+static void agg_power(struct agg_info*, int);
+
+static void aggch_start_dac(struct agg_chinfo*);
+static void aggch_stop_dac(struct agg_chinfo*);
+static void aggch_start_adc(struct agg_rchinfo*);
+static void aggch_stop_adc(struct agg_rchinfo*);
+static void aggch_feed_adc_stereo(struct agg_rchinfo*);
+static void aggch_feed_adc_mono(struct agg_rchinfo*);
-static inline void
-agg_lock(struct agg_info *sc)
-{
-#ifdef USING_MUTEX
-mtx_lock(&sc->lock);
+#ifdef AGG_JITTER_CORRECTION
+static void suppress_jitter(struct agg_chinfo*);
+static void suppress_rec_jitter(struct agg_rchinfo*);
#endif
-}
-static inline void
-agg_unlock(struct agg_info *sc)
-{
-#ifdef USING_MUTEX
-mtx_unlock(&sc->lock);
-#endif
-}
+static void set_timer(struct agg_info*);
+
+static void agg_intr(void *);
+static int agg_probe(device_t);
+static int agg_attach(device_t);
+static int agg_detach(device_t);
+static int agg_suspend(device_t);
+static int agg_resume(device_t);
+static int agg_shutdown(device_t);
+
+static void *dma_malloc(bus_dma_tag_t, u_int32_t, bus_addr_t*);
+static void dma_free(bus_dma_tag_t, void *);
+
+
+/* -----------------------------
+ * Subsystems.
+ */
-static inline void
+/* locking */
+#define agg_lock(sc) snd_mtxlock(&((sc)->lock))
+#define agg_unlock(sc) snd_mtxunlock(&((sc)->lock))
+
+static void
agg_sleep(struct agg_info *sc, const char *wmesg, int msec)
{
-int timo;
+ int timo;
-timo = msec * hz / 1000;
-if (timo == 0)
-timo = 1;
+ timo = msec * hz / 1000;
+ if (timo == 0)
+ timo = 1;
#ifdef USING_MUTEX
-msleep(sc, &sc->lock, PWAIT, wmesg, timo);
+ msleep(sc, &sc->lock, PWAIT, wmesg, timo);
#else
-tsleep(sc, PWAIT, wmesg, timo);
+ tsleep(sc, PWAIT, wmesg, timo);
#endif
}
/* I/O port */
-static inline u_int32_t
+static __inline u_int32_t
agg_rd(struct agg_info *sc, int regno, int size)
{
-switch (size) {
-case 1:
-return bus_space_read_1(sc->st, sc->sh, regno);
-case 2:
-return bus_space_read_2(sc->st, sc->sh, regno);
-case 4:
-return bus_space_read_4(sc->st, sc->sh, regno);
-default:
-return ~(u_int32_t)0;
-}
-}
-
-#define AGG_RD(sc, regno, size) bus_space_read_##size( ((struct agg_info*)(sc))->st, ((struct agg_info*)(sc))->sh, (regno))
+ switch (size) {
+ case 1:
+ return bus_space_read_1(sc->st, sc->sh, regno);
+ case 2:
+ return bus_space_read_2(sc->st, sc->sh, regno);
+ case 4:
+ return bus_space_read_4(sc->st, sc->sh, regno);
+ default:
+ return ~(u_int32_t)0;
+ }
+}
+
+#define AGG_RD(sc, regno, size) \
+ bus_space_read_##size( \
+ ((struct agg_info*)(sc))->st, \
+ ((struct agg_info*)(sc))->sh, (regno))
-static inline void
+static __inline void
agg_wr(struct agg_info *sc, int regno, u_int32_t data, int size)
{
-switch (size) {
-case 1:
-bus_space_write_1(sc->st, sc->sh, regno, data);
-break;
-case 2:
-bus_space_write_2(sc->st, sc->sh, regno, data);
-break;
-case 4:
-bus_space_write_4(sc->st, sc->sh, regno, data);
-break;
-}
-}
-
-#define AGG_WR(sc, regno, data, size) bus_space_write_##size( ((struct agg_info*)(sc))->st, ((struct agg_info*)(sc))->sh, (regno), (data))
+ switch (size) {
+ case 1:
+ bus_space_write_1(sc->st, sc->sh, regno, data);
+ break;
+ case 2:
+ bus_space_write_2(sc->st, sc->sh, regno, data);
+ break;
+ case 4:
+ bus_space_write_4(sc->st, sc->sh, regno, data);
+ break;
+ }
+}
+
+#define AGG_WR(sc, regno, data, size) \
+ bus_space_write_##size( \
+ ((struct agg_info*)(sc))->st, \
+ ((struct agg_info*)(sc))->sh, (regno), (data))
/* -------------------------------------------------------------------- */
/* Codec/Ringbus */
-static inline int
+static int
agg_codec_wait4idle(struct agg_info *ess)
{
-unsigned t = 26;
+ unsigned t = 26;
-while (AGG_RD(ess, PORT_CODEC_STAT, 1) & CODEC_STAT_MASK) {
-if (--t == 0)
-return EBUSY;
-DELAY(2); /* 20.8us / 13 */
-}
-return 0;
+ while (AGG_RD(ess, PORT_CODEC_STAT, 1) & CODEC_STAT_MASK) {
+ if (--t == 0)
+ return EBUSY;
+ DELAY(2); /* 20.8us / 13 */
+ }
+ return 0;
}
-static inline int
+static int
agg_rdcodec(struct agg_info *ess, int regno)
{
-int ret;
-
-/* We have to wait for a SAFE time to write addr/data */
-if (agg_codec_wait4idle(ess)) {
-/* Timed out. No read performed. */
-device_printf(ess->dev, "agg_rdcodec() PROGLESS timed out.n");
-return -1;
-}
+ int ret;
-AGG_WR(ess, PORT_CODEC_CMD, CODEC_CMD_READ | regno, 1);
-/*DELAY(21); * AC97 cycle = 20.8usec */
+ /* We have to wait for a SAFE time to write addr/data */
+ if (agg_codec_wait4idle(ess)) {
+ /* Timed out. No read performed. */
+ device_printf(ess->dev, "agg_rdcodec() PROGLESS timed out.\n");
+ return -1;
+ }
+
+ AGG_WR(ess, PORT_CODEC_CMD, CODEC_CMD_READ | regno, 1);
+ /*DELAY(21); * AC97 cycle = 20.8usec */
+
+ /* Wait for data retrieve */
+ if (!agg_codec_wait4idle(ess)) {
+ ret = AGG_RD(ess, PORT_CODEC_REG, 2);
+ } else {
+ /* Timed out. No read performed. */
+ device_printf(ess->dev, "agg_rdcodec() RW_DONE timed out.\n");
+ ret = -1;
+ }
-/* Wait for data retrieve */
-if (!agg_codec_wait4idle(ess)) {
-ret = AGG_RD(ess, PORT_CODEC_REG, 2);
-} else {
-/* Timed out. No read performed. */
-device_printf(ess->dev, "agg_rdcodec() RW_DONE timed out.n");
-ret = -1;
+ return ret;
}
-return ret;
-}
-
-static inline int
+static int
agg_wrcodec(struct agg_info *ess, int regno, u_int32_t data)
{
-/* We have to wait for a SAFE time to write addr/data */
-if (agg_codec_wait4idle(ess)) {
-/* Timed out. Abort writing. */
-device_printf(ess->dev, "agg_wrcodec() PROGLESS timed out.n");
-return -1;
-}
-
-AGG_WR(ess, PORT_CODEC_REG, data, 2);
-AGG_WR(ess, PORT_CODEC_CMD, CODEC_CMD_WRITE | regno, 1);
+ /* We have to wait for a SAFE time to write addr/data */
+ if (agg_codec_wait4idle(ess)) {
+ /* Timed out. Abort writing. */
+ device_printf(ess->dev, "agg_wrcodec() PROGLESS timed out.\n");
+ return -1;
+ }
+
+ AGG_WR(ess, PORT_CODEC_REG, data, 2);
+ AGG_WR(ess, PORT_CODEC_CMD, CODEC_CMD_WRITE | regno, 1);
+
+ /* Wait for write completion */
+ if (agg_codec_wait4idle(ess)) {
+ /* Timed out. */
+ device_printf(ess->dev, "agg_wrcodec() RW_DONE timed out.\n");
+ return -1;
+ }
-/* Wait for write completion */
-if (agg_codec_wait4idle(ess)) {
-/* Timed out. */
-device_printf(ess->dev, "agg_wrcodec() RW_DONE timed out.n");
-return -1;
+ return 0;
}
-return 0;
-}
-
-static inline void
+static void
ringbus_setdest(struct agg_info *ess, int src, int dest)
{
-u_int32_t data;
+ u_int32_t data;
-data = AGG_RD(ess, PORT_RINGBUS_CTRL, 4);
-data &= ~(0xfU << src);
-data |= (0xfU & dest) << src;
-AGG_WR(ess, PORT_RINGBUS_CTRL, data, 4);
+ data = AGG_RD(ess, PORT_RINGBUS_CTRL, 4);
+ data &= ~(0xfU << src);
+ data |= (0xfU & dest) << src;
+ AGG_WR(ess, PORT_RINGBUS_CTRL, data, 4);
}
/* -------------------------------------------------------------------- */
/* Wave Processor */
-static inline u_int16_t
+static u_int16_t
wp_rdreg(struct agg_info *ess, u_int16_t reg)
{
-AGG_WR(ess, PORT_DSP_INDEX, reg, 2);
-return AGG_RD(ess, PORT_DSP_DATA, 2);
+ AGG_WR(ess, PORT_DSP_INDEX, reg, 2);
+ return AGG_RD(ess, PORT_DSP_DATA, 2);
}
-static inline void
+static void
wp_wrreg(struct agg_info *ess, u_int16_t reg, u_int16_t data)
{
-AGG_WR(ess, PORT_DSP_INDEX, reg, 2);
-AGG_WR(ess, PORT_DSP_DATA, data, 2);
+ AGG_WR(ess, PORT_DSP_INDEX, reg, 2);
+ AGG_WR(ess, PORT_DSP_DATA, data, 2);
}
-static inline int
+static int
wp_wait_data(struct agg_info *ess, u_int16_t data)
{
-unsigned t = 0;
+ unsigned t = 0;
-while (AGG_RD(ess, PORT_DSP_DATA, 2) != data) {
-if (++t == 1000) {
-return EAGAIN;
-}
-AGG_WR(ess, PORT_DSP_DATA, data, 2);
-}
+ while (AGG_RD(ess, PORT_DSP_DATA, 2) != data) {
+ if (++t == 1000) {
+ return EAGAIN;
+ }
+ AGG_WR(ess, PORT_DSP_DATA, data, 2);
+ }
-return 0;
+ return 0;
}
-static inline u_int16_t
+static u_int16_t
wp_rdapu(struct agg_info *ess, unsigned ch, u_int16_t reg)
{
-wp_wrreg(ess, WPREG_CRAM_PTR, reg | (ch << 4));
-if (wp_wait_data(ess, reg | (ch << 4)) != 0)
-device_printf(ess->dev, "wp_rdapu() indexing timed out.n");
-return wp_rdreg(ess, WPREG_DATA_PORT);
+ wp_wrreg(ess, WPREG_CRAM_PTR, reg | (ch << 4));
+ if (wp_wait_data(ess, reg | (ch << 4)) != 0)
+ device_printf(ess->dev, "wp_rdapu() indexing timed out.\n");
+ return wp_rdreg(ess, WPREG_DATA_PORT);
}
-static inline void
+static void
wp_wrapu(struct agg_info *ess, unsigned ch, u_int16_t reg, u_int16_t data)
{
-wp_wrreg(ess, WPREG_CRAM_PTR, reg | (ch << 4));
-if (wp_wait_data(ess, reg | (ch << 4)) == 0) {
-wp_wrreg(ess, WPREG_DATA_PORT, data);
-if (wp_wait_data(ess, data) != 0)
-device_printf(ess->dev, "wp_wrapu() write timed out.n");
-} else {
-device_printf(ess->dev, "wp_wrapu() indexing timed out.n");
-}
+ wp_wrreg(ess, WPREG_CRAM_PTR, reg | (ch << 4));
+ if (wp_wait_data(ess, reg | (ch << 4)) == 0) {
+ wp_wrreg(ess, WPREG_DATA_PORT, data);
+ if (wp_wait_data(ess, data) != 0)
+ device_printf(ess->dev,
+ "wp_wrapu() write timed out.\n");
+ } else {
+ device_printf(ess->dev, "wp_wrapu() indexing timed out.\n");
+ }
}
static void
apu_setparam(struct agg_info *ess, int apuch,
-u_int32_t wpwa, u_int16_t size, int16_t pan, u_int dv)
+ u_int32_t wpwa, u_int16_t size, int16_t pan, u_int dv)
{
-wp_wrapu(ess, apuch, APUREG_WAVESPACE, (wpwa >> 8) & APU_64KPAGE_MASK);
-wp_wrapu(ess, apuch, APUREG_CURPTR, wpwa);
-wp_wrapu(ess, apuch, APUREG_ENDPTR, wpwa + size);
-wp_wrapu(ess, apuch, APUREG_LOOPLEN, size);
-wp_wrapu(ess, apuch, APUREG_ROUTING, 0);
-wp_wrapu(ess, apuch, APUREG_AMPLITUDE, 0xf000);
-wp_wrapu(ess, apuch, APUREG_POSITION, 0x8f00
-| (APU_RADIUS_MASK & (RADIUS_CENTERCIRCLE << APU_RADIUS_SHIFT))
-| (APU_PAN_MASK & ((pan + PAN_FRONT) << APU_PAN_SHIFT)));
-wp_wrapu(ess, apuch, APUREG_FREQ_LOBYTE,
-APU_plus6dB | ((dv & 0xff) << APU_FREQ_LOBYTE_SHIFT));
-wp_wrapu(ess, apuch, APUREG_FREQ_HIWORD, dv >> 8);
+ wp_wrapu(ess, apuch, APUREG_WAVESPACE, (wpwa >> 8) & APU_64KPAGE_MASK);
+ wp_wrapu(ess, apuch, APUREG_CURPTR, wpwa);
+ wp_wrapu(ess, apuch, APUREG_ENDPTR, wpwa + size);
+ wp_wrapu(ess, apuch, APUREG_LOOPLEN, size);
+ wp_wrapu(ess, apuch, APUREG_ROUTING, 0);
+ wp_wrapu(ess, apuch, APUREG_AMPLITUDE, 0xf000);
+ wp_wrapu(ess, apuch, APUREG_POSITION, 0x8f00
+ | (APU_RADIUS_MASK & (RADIUS_CENTERCIRCLE << APU_RADIUS_SHIFT))
+ | (APU_PAN_MASK & ((pan + PAN_FRONT) << APU_PAN_SHIFT)));
+ wp_wrapu(ess, apuch, APUREG_FREQ_LOBYTE,
+ APU_plus6dB | ((dv & 0xff) << APU_FREQ_LOBYTE_SHIFT));
+ wp_wrapu(ess, apuch, APUREG_FREQ_HIWORD, dv >> 8);
}
-static inline void
+static void
wp_settimer(struct agg_info *ess, u_int divide)
{
-u_int prescale = 0;
+ u_int prescale = 0;
-RANGE(divide, 2, 32 << 7);
+ RANGE(divide, 2, 32 << 7);
-for (; divide > 32; divide >>= 1) {
-prescale++;
-divide++;
+ for (; divide > 32; divide >>= 1) {
+ prescale++;
+ divide++;
+ }
+
+ for (; prescale < 7 && divide > 2 && !(divide & 1); divide >>= 1)
+ prescale++;
+
+ wp_wrreg(ess, WPREG_TIMER_ENABLE, 0);
+ wp_wrreg(ess, WPREG_TIMER_FREQ, 0x9000 |
+ (prescale << WP_TIMER_FREQ_PRESCALE_SHIFT) | (divide - 1));
+ wp_wrreg(ess, WPREG_TIMER_ENABLE, 1);
}
-for (; prescale < 7 && divide > 2 && !(divide & 1); divide >>= 1)
-prescale++;
-
-wp_wrreg(ess, WPREG_TIMER_ENABLE, 0);
-wp_wrreg(ess, WPREG_TIMER_FREQ, 0x9000 |
-(prescale << WP_TIMER_FREQ_PRESCALE_SHIFT) | (divide - 1));
-wp_wrreg(ess, WPREG_TIMER_ENABLE, 1);
-}
-
-static inline void
+static void
wp_starttimer(struct agg_info *ess)
{
-AGG_WR(ess, PORT_INT_STAT, 1, 2);
-AGG_WR(ess, PORT_HOSTINT_CTRL, HOSTINT_CTRL_DSOUND_INT_ENABLED
-| AGG_RD(ess, PORT_HOSTINT_CTRL, 2), 2);
-wp_wrreg(ess, WPREG_TIMER_START, 1);
+ AGG_WR(ess, PORT_INT_STAT, 1, 2);
+ AGG_WR(ess, PORT_HOSTINT_CTRL, HOSTINT_CTRL_DSOUND_INT_ENABLED
+ | AGG_RD(ess, PORT_HOSTINT_CTRL, 2), 2);
+ wp_wrreg(ess, WPREG_TIMER_START, 1);
}
-static inline void
+static void
wp_stoptimer(struct agg_info *ess)
{
-AGG_WR(ess, PORT_HOSTINT_CTRL, ~HOSTINT_CTRL_DSOUND_INT_ENABLED
-& AGG_RD(ess, PORT_HOSTINT_CTRL, 2), 2);
-AGG_WR(ess, PORT_INT_STAT, 1, 2);
-wp_wrreg(ess, WPREG_TIMER_START, 0);
+ AGG_WR(ess, PORT_HOSTINT_CTRL, ~HOSTINT_CTRL_DSOUND_INT_ENABLED
+ & AGG_RD(ess, PORT_HOSTINT_CTRL, 2), 2);
+ AGG_WR(ess, PORT_INT_STAT, 1, 2);
+ wp_wrreg(ess, WPREG_TIMER_START, 0);
}
/* -------------------------------------------------------------------- */
/* WaveCache */
-static inline u_int16_t
+#if 0
+static u_int16_t
wc_rdreg(struct agg_info *ess, u_int16_t reg)
{
-AGG_WR(ess, PORT_WAVCACHE_INDEX, reg, 2);
-return AGG_RD(ess, PORT_WAVCACHE_DATA, 2);
+ AGG_WR(ess, PORT_WAVCACHE_INDEX, reg, 2);
+ return AGG_RD(ess, PORT_WAVCACHE_DATA, 2);
}
+#endif
-static inline void
+static void
wc_wrreg(struct agg_info *ess, u_int16_t reg, u_int16_t data)
{
-AGG_WR(ess, PORT_WAVCACHE_INDEX, reg, 2);
-AGG_WR(ess, PORT_WAVCACHE_DATA, data, 2);
+ AGG_WR(ess, PORT_WAVCACHE_INDEX, reg, 2);
+ AGG_WR(ess, PORT_WAVCACHE_DATA, data, 2);
}
-static inline u_int16_t
+#if 0
+static u_int16_t
wc_rdchctl(struct agg_info *ess, int ch)
{
-return wc_rdreg(ess, ch << 3);
+ return wc_rdreg(ess, ch << 3);
}
+#endif
-static inline void
+static void
wc_wrchctl(struct agg_info *ess, int ch, u_int16_t data)
{
-wc_wrreg(ess, ch << 3, data);
+ wc_wrreg(ess, ch << 3, data);
}
/* -------------------------------------------------------------------- */
/* Power management */
-static inline void
+static void
agg_stopclock(struct agg_info *ess, int part, int st)
{
-u_int32_t data;
+ u_int32_t data;
-data = pci_read_config(ess->dev, CONF_ACPI_STOPCLOCK, 4);
-if (part < 16) {
-if (st == PCI_POWERSTATE_D1)
-data &= ~(1 << part);
-else
-data |= (1 << part);
-if (st == PCI_POWERSTATE_D1 || st == PCI_POWERSTATE_D2)
-data |= (0x10000 << part);
-else
-data &= ~(0x10000 << part);
-pci_write_config(ess->dev, CONF_ACPI_STOPCLOCK, data, 4);
-}
+ data = pci_read_config(ess->dev, CONF_ACPI_STOPCLOCK, 4);
+ if (part < 16) {
+ if (st == PCI_POWERSTATE_D1)
+ data &= ~(1 << part);
+ else
+ data |= (1 << part);
+ if (st == PCI_POWERSTATE_D1 || st == PCI_POWERSTATE_D2)
+ data |= (0x10000 << part);
+ else
+ data &= ~(0x10000 << part);
+ pci_write_config(ess->dev, CONF_ACPI_STOPCLOCK, data, 4);
+ }
}
/* -----------------------------
-* Controller.
-*/
+ * Controller.
+ */
-static inline void
+static void
agg_initcodec(struct agg_info* ess)
{
-u_int16_t data;
+ u_int16_t data;
-if (AGG_RD(ess, PORT_RINGBUS_CTRL, 4) & RINGBUS_CTRL_ACLINK_ENABLED) {
-AGG_WR(ess, PORT_RINGBUS_CTRL, 0, 4);
-DELAY(104); /* 20.8us * (4 + 1) */
-}
-/* XXX - 2nd codec should be looked at. */
-AGG_WR(ess, PORT_RINGBUS_CTRL, RINGBUS_CTRL_AC97_SWRESET, 4);
-DELAY(2);
-AGG_WR(ess, PORT_RINGBUS_CTRL, RINGBUS_CTRL_ACLINK_ENABLED, 4);
-DELAY(50);
-
-if (agg_rdcodec(ess, 0) < 0) {
-AGG_WR(ess, PORT_RINGBUS_CTRL, 0, 4);
-DELAY(21);
-
-/* Try cold reset. */
-device_printf(ess->dev, "will perform cold reset.n");
-data = AGG_RD(ess, PORT_GPIO_DIR, 2);
-if (pci_read_config(ess->dev, 0x58, 2) & 1)
-data |= 0x10;
-data |= 0x009 & ~AGG_RD(ess, PORT_GPIO_DATA, 2);
-AGG_WR(ess, PORT_GPIO_MASK, 0xff6, 2);
-AGG_WR(ess, PORT_GPIO_DIR, data | 0x009, 2);
-AGG_WR(ess, PORT_GPIO_DATA, 0x000, 2);
-DELAY(2);
-AGG_WR(ess, PORT_GPIO_DATA, 0x001, 2);
-DELAY(1);
-AGG_WR(ess, PORT_GPIO_DATA, 0x009, 2);
-agg_sleep(ess, "agginicd", 500);
-AGG_WR(ess, PORT_GPIO_DIR, data, 2);
-DELAY(84); /* 20.8us * 4 */
-AGG_WR(ess, PORT_RINGBUS_CTRL, RINGBUS_CTRL_ACLINK_ENABLED, 4);
-DELAY(50);
-}
+ if (AGG_RD(ess, PORT_RINGBUS_CTRL, 4) & RINGBUS_CTRL_ACLINK_ENABLED) {
+ AGG_WR(ess, PORT_RINGBUS_CTRL, 0, 4);
+ DELAY(104); /* 20.8us * (4 + 1) */
+ }
+ /* XXX - 2nd codec should be looked at. */
+ AGG_WR(ess, PORT_RINGBUS_CTRL, RINGBUS_CTRL_AC97_SWRESET, 4);
+ DELAY(2);
+ AGG_WR(ess, PORT_RINGBUS_CTRL, RINGBUS_CTRL_ACLINK_ENABLED, 4);
+ DELAY(50);
+
+ if (agg_rdcodec(ess, 0) < 0) {
+ AGG_WR(ess, PORT_RINGBUS_CTRL, 0, 4);
+ DELAY(21);
+
+ /* Try cold reset. */
+ device_printf(ess->dev, "will perform cold reset.\n");
+ data = AGG_RD(ess, PORT_GPIO_DIR, 2);
+ if (pci_read_config(ess->dev, 0x58, 2) & 1)
+ data |= 0x10;
+ data |= 0x009 & ~AGG_RD(ess, PORT_GPIO_DATA, 2);
+ AGG_WR(ess, PORT_GPIO_MASK, 0xff6, 2);
+ AGG_WR(ess, PORT_GPIO_DIR, data | 0x009, 2);
+ AGG_WR(ess, PORT_GPIO_DATA, 0x000, 2);
+ DELAY(2);
+ AGG_WR(ess, PORT_GPIO_DATA, 0x001, 2);
+ DELAY(1);
+ AGG_WR(ess, PORT_GPIO_DATA, 0x009, 2);
+ agg_sleep(ess, "agginicd", 500);
+ AGG_WR(ess, PORT_GPIO_DIR, data, 2);
+ DELAY(84); /* 20.8us * 4 */
+ AGG_WR(ess, PORT_RINGBUS_CTRL, RINGBUS_CTRL_ACLINK_ENABLED, 4);
+ DELAY(50);
+ }
}
static void
agg_init(struct agg_info* ess)
{
-u_int32_t data;
-
-/* Setup PCI config registers. */
+ u_int32_t data;
-/* Disable all legacy emulations. */
-data = pci_read_config(ess->dev, CONF_LEGACY, 2);
-data |= LEGACY_DISABLED;
-pci_write_config(ess->dev, CONF_LEGACY, data, 2);
-
-/* Disconnect from CHI. (Makes Dell inspiron 7500 work?)
-* Enable posted write.
-* Prefer PCI timing rather than that of ISA.
-* Don't swap L/R. */
-data = pci_read_config(ess->dev, CONF_MAESTRO, 4);
-data |= MAESTRO_PMC;
-data |= MAESTRO_CHIBUS | MAESTRO_POSTEDWRITE | MAESTRO_DMA_PCITIMING;
-data &= ~MAESTRO_SWAP_LR;
-pci_write_config(ess->dev, CONF_MAESTRO, data, 4);
-
-/* Turn off unused parts if necessary. */
-/* consult CONF_MAESTRO. */
-if (data & MAESTRO_SPDIF)
-agg_stopclock(ess, ACPI_PART_SPDIF, PCI_POWERSTATE_D2);
-else
-agg_stopclock(ess, ACPI_PART_SPDIF, PCI_POWERSTATE_D1);
-if (data & MAESTRO_HWVOL)
-agg_stopclock(ess, ACPI_PART_HW_VOL, PCI_POWERSTATE_D3);
-else
-agg_stopclock(ess, ACPI_PART_HW_VOL, PCI_POWERSTATE_D1);
-
-/* parts that never be used */
-agg_stopclock(ess, ACPI_PART_978, PCI_POWERSTATE_D1);
-agg_stopclock(ess, ACPI_PART_DAA, PCI_POWERSTATE_D1);
-agg_stopclock(ess, ACPI_PART_GPIO, PCI_POWERSTATE_D1);
-agg_stopclock(ess, ACPI_PART_SB, PCI_POWERSTATE_D1);
-agg_stopclock(ess, ACPI_PART_FM, PCI_POWERSTATE_D1);
-agg_stopclock(ess, ACPI_PART_MIDI, PCI_POWERSTATE_D1);
-agg_stopclock(ess, ACPI_PART_GAME_PORT, PCI_POWERSTATE_D1);
-
-/* parts that will be used only when play/recording */
-agg_stopclock(ess, ACPI_PART_WP, PCI_POWERSTATE_D2);
-
-/* parts that should always be turned on */
-agg_stopclock(ess, ACPI_PART_CODEC_CLOCK, PCI_POWERSTATE_D3);
-agg_stopclock(ess, ACPI_PART_GLUE, PCI_POWERSTATE_D3);
-agg_stopclock(ess, ACPI_PART_PCI_IF, PCI_POWERSTATE_D3);
-agg_stopclock(ess, ACPI_PART_RINGBUS, PCI_POWERSTATE_D3);
-
-/* Reset direct sound. */
-AGG_WR(ess, PORT_HOSTINT_CTRL, HOSTINT_CTRL_SOFT_RESET, 2);
-DELAY(100);
-AGG_WR(ess, PORT_HOSTINT_CTRL, 0, 2);
-DELAY(100);
-AGG_WR(ess, PORT_HOSTINT_CTRL, HOSTINT_CTRL_DSOUND_RESET, 2);
-DELAY(100);
-AGG_WR(ess, PORT_HOSTINT_CTRL, 0, 2);
-DELAY(100);
-
-/* Enable hardware volume control interruption. */
-if (data & MAESTRO_HWVOL) /* XXX - why not use device flags? */
-AGG_WR(ess, PORT_HOSTINT_CTRL,HOSTINT_CTRL_HWVOL_ENABLED, 2);
-
-/* Setup Wave Processor. */
-
-/* Enable WaveCache, set DMA base address. */
-wp_wrreg(ess, WPREG_WAVE_ROMRAM,
-WP_WAVE_VIRTUAL_ENABLED | WP_WAVE_DRAM_ENABLED);
-wp_wrreg(ess, WPREG_CRAM_DATA, 0);
-
-AGG_WR(ess, PORT_WAVCACHE_CTRL,
-WAVCACHE_ENABLED | WAVCACHE_WTSIZE_2MB | WAVCACHE_SGC_32_47, 2);
-
-for (data = WAVCACHE_PCMBAR; data < WAVCACHE_PCMBAR + 4; data++)
-wc_wrreg(ess, data, ess->phys >> WAVCACHE_BASEADDR_SHIFT);
-
-/* Setup Codec/Ringbus. */
-agg_initcodec(ess);
-AGG_WR(ess, PORT_RINGBUS_CTRL,
-RINGBUS_CTRL_RINGBUS_ENABLED | RINGBUS_CTRL_ACLINK_ENABLED, 4);
-
-wp_wrreg(ess, 0x08, 0xB004);
-wp_wrreg(ess, 0x09, 0x001B);
-wp_wrreg(ess, 0x0A, 0x8000);
-wp_wrreg(ess, 0x0B, 0x3F37);
-wp_wrreg(ess, WPREG_BASE, 0x8598); /* Parallel I/O */
-wp_wrreg(ess, WPREG_BASE + 1, 0x7632);
-ringbus_setdest(ess, RINGBUS_SRC_ADC,
-RINGBUS_DEST_STEREO | RINGBUS_DEST_DSOUND_IN);
-ringbus_setdest(ess, RINGBUS_SRC_DSOUND,
-RINGBUS_DEST_STEREO | RINGBUS_DEST_DAC);
-
-/* Enable S/PDIF if necessary. */
-if (pci_read_config(ess->dev, CONF_MAESTRO, 4) & MAESTRO_SPDIF)
-/* XXX - why not use device flags? */
-AGG_WR(ess, PORT_RINGBUS_CTRL_B, RINGBUS_CTRL_SPDIF |
-AGG_RD(ess, PORT_RINGBUS_CTRL_B, 1), 1);
-
-/* Setup ASSP. Needed for Dell Inspiron 7500? */
-AGG_WR(ess, PORT_ASSP_CTRL_B, 0x00, 1);
-AGG_WR(ess, PORT_ASSP_CTRL_A, 0x03, 1);
-AGG_WR(ess, PORT_ASSP_CTRL_C, 0x00, 1);
+ /* Setup PCI config registers. */
-/*
-* Setup GPIO.
-* There seems to be speciality with NEC systems.
-*/
-switch (pci_get_subvendor(ess->dev)
-| (pci_get_subdevice(ess->dev) << 16)) {
-case NEC_SUBID1:
-case NEC_SUBID2:
-/* Matthew Braithwaite <matt at braithwaite.net> reported that
-* NEC Versa LX doesn't need GPIO operation. */
-AGG_WR(ess, PORT_GPIO_MASK, 0x9ff, 2);
-AGG_WR(ess, PORT_GPIO_DIR,
-AGG_RD(ess, PORT_GPIO_DIR, 2) | 0x600, 2);
-AGG_WR(ess, PORT_GPIO_DATA, 0x200, 2);
-break;
-}
+ /* Disable all legacy emulations. */
+ data = pci_read_config(ess->dev, CONF_LEGACY, 2);
+ data |= LEGACY_DISABLED;
+ pci_write_config(ess->dev, CONF_LEGACY, data, 2);
+
+ /* Disconnect from CHI. (Makes Dell inspiron 7500 work?)
+ * Enable posted write.
+ * Prefer PCI timing rather than that of ISA.
+ * Don't swap L/R. */
+ data = pci_read_config(ess->dev, CONF_MAESTRO, 4);
+ data |= MAESTRO_PMC;
+ data |= MAESTRO_CHIBUS | MAESTRO_POSTEDWRITE | MAESTRO_DMA_PCITIMING;
+ data &= ~MAESTRO_SWAP_LR;
+ pci_write_config(ess->dev, CONF_MAESTRO, data, 4);
+
+ /* Turn off unused parts if necessary. */
+ /* consult CONF_MAESTRO. */
+ if (data & MAESTRO_SPDIF)
+ agg_stopclock(ess, ACPI_PART_SPDIF, PCI_POWERSTATE_D2);
+ else
+ agg_stopclock(ess, ACPI_PART_SPDIF, PCI_POWERSTATE_D1);
+ if (data & MAESTRO_HWVOL)
+ agg_stopclock(ess, ACPI_PART_HW_VOL, PCI_POWERSTATE_D3);
+ else
+ agg_stopclock(ess, ACPI_PART_HW_VOL, PCI_POWERSTATE_D1);
+
+ /* parts that never be used */
+ agg_stopclock(ess, ACPI_PART_978, PCI_POWERSTATE_D1);
+ agg_stopclock(ess, ACPI_PART_DAA, PCI_POWERSTATE_D1);
+ agg_stopclock(ess, ACPI_PART_GPIO, PCI_POWERSTATE_D1);
+ agg_stopclock(ess, ACPI_PART_SB, PCI_POWERSTATE_D1);
+ agg_stopclock(ess, ACPI_PART_FM, PCI_POWERSTATE_D1);
+ agg_stopclock(ess, ACPI_PART_MIDI, PCI_POWERSTATE_D1);
+ agg_stopclock(ess, ACPI_PART_GAME_PORT, PCI_POWERSTATE_D1);
+
+ /* parts that will be used only when play/recording */
+ agg_stopclock(ess, ACPI_PART_WP, PCI_POWERSTATE_D2);
+
+ /* parts that should always be turned on */
+ agg_stopclock(ess, ACPI_PART_CODEC_CLOCK, PCI_POWERSTATE_D3);
+ agg_stopclock(ess, ACPI_PART_GLUE, PCI_POWERSTATE_D3);
+ agg_stopclock(ess, ACPI_PART_PCI_IF, PCI_POWERSTATE_D3);
+ agg_stopclock(ess, ACPI_PART_RINGBUS, PCI_POWERSTATE_D3);
+
+ /* Reset direct sound. */
+ AGG_WR(ess, PORT_HOSTINT_CTRL, HOSTINT_CTRL_SOFT_RESET, 2);
+ DELAY(100);
+ AGG_WR(ess, PORT_HOSTINT_CTRL, 0, 2);
+ DELAY(100);
+ AGG_WR(ess, PORT_HOSTINT_CTRL, HOSTINT_CTRL_DSOUND_RESET, 2);
+ DELAY(100);
+ AGG_WR(ess, PORT_HOSTINT_CTRL, 0, 2);
+ DELAY(100);
+
+ /* Enable hardware volume control interruption. */
+ if (data & MAESTRO_HWVOL) /* XXX - why not use device flags? */
+ AGG_WR(ess, PORT_HOSTINT_CTRL,HOSTINT_CTRL_HWVOL_ENABLED, 2);
+
+ /* Setup Wave Processor. */
+
+ /* Enable WaveCache, set DMA base address. */
+ wp_wrreg(ess, WPREG_WAVE_ROMRAM,
+ WP_WAVE_VIRTUAL_ENABLED | WP_WAVE_DRAM_ENABLED);
+ wp_wrreg(ess, WPREG_CRAM_DATA, 0);
+
+ AGG_WR(ess, PORT_WAVCACHE_CTRL,
+ WAVCACHE_ENABLED | WAVCACHE_WTSIZE_2MB | WAVCACHE_SGC_32_47, 2);
+
+ for (data = WAVCACHE_PCMBAR; data < WAVCACHE_PCMBAR + 4; data++)
+ wc_wrreg(ess, data, ess->phys >> WAVCACHE_BASEADDR_SHIFT);
+
+ /* Setup Codec/Ringbus. */
+ agg_initcodec(ess);
+ AGG_WR(ess, PORT_RINGBUS_CTRL,
+ RINGBUS_CTRL_RINGBUS_ENABLED | RINGBUS_CTRL_ACLINK_ENABLED, 4);
+
+ wp_wrreg(ess, 0x08, 0xB004);
+ wp_wrreg(ess, 0x09, 0x001B);
+ wp_wrreg(ess, 0x0A, 0x8000);
+ wp_wrreg(ess, 0x0B, 0x3F37);
+ wp_wrreg(ess, WPREG_BASE, 0x8598); /* Parallel I/O */
+ wp_wrreg(ess, WPREG_BASE + 1, 0x7632);
+ ringbus_setdest(ess, RINGBUS_SRC_ADC,
+ RINGBUS_DEST_STEREO | RINGBUS_DEST_DSOUND_IN);
+ ringbus_setdest(ess, RINGBUS_SRC_DSOUND,
+ RINGBUS_DEST_STEREO | RINGBUS_DEST_DAC);
+
+ /* Enable S/PDIF if necessary. */
+ if (pci_read_config(ess->dev, CONF_MAESTRO, 4) & MAESTRO_SPDIF)
+ /* XXX - why not use device flags? */
+ AGG_WR(ess, PORT_RINGBUS_CTRL_B, RINGBUS_CTRL_SPDIF |
+ AGG_RD(ess, PORT_RINGBUS_CTRL_B, 1), 1);
+
+ /* Setup ASSP. Needed for Dell Inspiron 7500? */
+ AGG_WR(ess, PORT_ASSP_CTRL_B, 0x00, 1);
+ AGG_WR(ess, PORT_ASSP_CTRL_A, 0x03, 1);
+ AGG_WR(ess, PORT_ASSP_CTRL_C, 0x00, 1);
+
+ /*
+ * Setup GPIO.
+ * There seems to be speciality with NEC systems.
+ */
+ switch (pci_get_subvendor(ess->dev)
+ | (pci_get_subdevice(ess->dev) << 16)) {
+ case NEC_SUBID1:
+ case NEC_SUBID2:
+ /* Matthew Braithwaite <matt at braithwaite.net> reported that
+ * NEC Versa LX doesn't need GPIO operation. */
+ AGG_WR(ess, PORT_GPIO_MASK, 0x9ff, 2);
+ AGG_WR(ess, PORT_GPIO_DIR,
+ AGG_RD(ess, PORT_GPIO_DIR, 2) | 0x600, 2);
+ AGG_WR(ess, PORT_GPIO_DATA, 0x200, 2);
+ break;
+ }
}
/* Deals power state transition. Must be called with softc->lock held. */
static void
agg_power(struct agg_info *ess, int status)
{
-u_int8_t lastpwr;
+ u_int8_t lastpwr;
-lastpwr = ess->curpwr;
-if (lastpwr == status)
-return;
-
-switch (status) {
-case PCI_POWERSTATE_D0:
-case PCI_POWERSTATE_D1:
-switch (lastpwr) {
-case PCI_POWERSTATE_D2:
-pci_set_powerstate(ess->dev, status);
-/* Turn on PCM-related parts. */
-agg_wrcodec(ess, AC97_REG_POWER, 0);
-DELAY(100);
+ lastpwr = ess->curpwr;
+ if (lastpwr == status)
+ return;
+
+ switch (status) {
+ case PCI_POWERSTATE_D0:
+ case PCI_POWERSTATE_D1:
+ switch (lastpwr) {
+ case PCI_POWERSTATE_D2:
+ pci_set_powerstate(ess->dev, status);
+ /* Turn on PCM-related parts. */
+ agg_wrcodec(ess, AC97_REG_POWER, 0);
+ DELAY(100);
#if 0
-if ((agg_rdcodec(ess, AC97_REG_POWER) & 3) != 3)
-device_printf(ess->dev, "warning: codec not ready.n");
-#endif
-AGG_WR(ess, PORT_RINGBUS_CTRL,
-(AGG_RD(ess, PORT_RINGBUS_CTRL, 4)
-& ~RINGBUS_CTRL_ACLINK_ENABLED)
-| RINGBUS_CTRL_RINGBUS_ENABLED, 4);
-DELAY(50);
-AGG_WR(ess, PORT_RINGBUS_CTRL,
-AGG_RD(ess, PORT_RINGBUS_CTRL, 4)
-| RINGBUS_CTRL_ACLINK_ENABLED, 4);
-break;
-case PCI_POWERSTATE_D3:
-/* Initialize. */
-pci_set_powerstate(ess->dev, PCI_POWERSTATE_D0);
-DELAY(100);
-agg_init(ess);
-/* FALLTHROUGH */
-case PCI_POWERSTATE_D0:
-case PCI_POWERSTATE_D1:
-pci_set_powerstate(ess->dev, status);
-break;
-}
-break;
-case PCI_POWERSTATE_D2:
-switch (lastpwr) {
-case PCI_POWERSTATE_D3:
-/* Initialize. */
-pci_set_powerstate(ess->dev, PCI_POWERSTATE_D0);
-DELAY(100);
-agg_init(ess);
-/* FALLTHROUGH */
-case PCI_POWERSTATE_D0:
-case PCI_POWERSTATE_D1:
-/* Turn off PCM-related parts. */
-AGG_WR(ess, PORT_RINGBUS_CTRL,
-AGG_RD(ess, PORT_RINGBUS_CTRL, 4)
-& ~RINGBUS_CTRL_RINGBUS_ENABLED, 4);
-DELAY(100);
-agg_wrcodec(ess, AC97_REG_POWER, 0x300);
-DELAY(100);
-break;
-}
-pci_set_powerstate(ess->dev, status);
-break;
-case PCI_POWERSTATE_D3:
-/* Entirely power down. */
-agg_wrcodec(ess, AC97_REG_POWER, 0xdf00);
-DELAY(100);
-AGG_WR(ess, PORT_RINGBUS_CTRL, 0, 4);
-/*DELAY(1);*/
-if (lastpwr != PCI_POWERSTATE_D2)
-wp_stoptimer(ess);
-AGG_WR(ess, PORT_HOSTINT_CTRL, 0, 2);
-AGG_WR(ess, PORT_HOSTINT_STAT, 0xff, 1);
-pci_set_powerstate(ess->dev, status);
-break;
-default:
-/* Invalid power state; let it ignored. */
-status = lastpwr;
-break;
-}
+ if ((agg_rdcodec(ess, AC97_REG_POWER) & 3) != 3)
+ device_printf(ess->dev,
+ "warning: codec not ready.\n");
+#endif
+ AGG_WR(ess, PORT_RINGBUS_CTRL,
+ (AGG_RD(ess, PORT_RINGBUS_CTRL, 4)
+ & ~RINGBUS_CTRL_ACLINK_ENABLED)
+ | RINGBUS_CTRL_RINGBUS_ENABLED, 4);
+ DELAY(50);
+ AGG_WR(ess, PORT_RINGBUS_CTRL,
+ AGG_RD(ess, PORT_RINGBUS_CTRL, 4)
+ | RINGBUS_CTRL_ACLINK_ENABLED, 4);
+ break;
+ case PCI_POWERSTATE_D3:
+ /* Initialize. */
+ pci_set_powerstate(ess->dev, PCI_POWERSTATE_D0);
+ DELAY(100);
+ agg_init(ess);
+ /* FALLTHROUGH */
+ case PCI_POWERSTATE_D0:
+ case PCI_POWERSTATE_D1:
+ pci_set_powerstate(ess->dev, status);
+ break;
+ }
+ break;
+ case PCI_POWERSTATE_D2:
+ switch (lastpwr) {
+ case PCI_POWERSTATE_D3:
+ /* Initialize. */
+ pci_set_powerstate(ess->dev, PCI_POWERSTATE_D0);
+ DELAY(100);
+ agg_init(ess);
+ /* FALLTHROUGH */
+ case PCI_POWERSTATE_D0:
+ case PCI_POWERSTATE_D1:
+ /* Turn off PCM-related parts. */
+ AGG_WR(ess, PORT_RINGBUS_CTRL,
+ AGG_RD(ess, PORT_RINGBUS_CTRL, 4)
+ & ~RINGBUS_CTRL_RINGBUS_ENABLED, 4);
+ DELAY(100);
+ agg_wrcodec(ess, AC97_REG_POWER, 0x300);
+ DELAY(100);
+ break;
+ }
+ pci_set_powerstate(ess->dev, status);
+ break;
+ case PCI_POWERSTATE_D3:
+ /* Entirely power down. */
+ agg_wrcodec(ess, AC97_REG_POWER, 0xdf00);
+ DELAY(100);
+ AGG_WR(ess, PORT_RINGBUS_CTRL, 0, 4);
+ /*DELAY(1);*/
+ if (lastpwr != PCI_POWERSTATE_D2)
+ wp_stoptimer(ess);
+ AGG_WR(ess, PORT_HOSTINT_CTRL, 0, 2);
+ AGG_WR(ess, PORT_HOSTINT_STAT, 0xff, 1);
+ pci_set_powerstate(ess->dev, status);
+ break;
+ default:
+ /* Invalid power state; let it ignored. */
+ status = lastpwr;
+ break;
+ }
-ess->curpwr = status;
+ ess->curpwr = status;
}
/* -------------------------------------------------------------------- */
@@ -836,432 +839,434 @@
static void
aggch_start_dac(struct agg_chinfo *ch)
{
-bus_addr_t wpwa;
-u_int32_t speed;
-u_int16_t size, apuch, wtbar, wcreg, aputype;
-u_int dv;
-int pan;
-
-speed = ch->speed;
-wpwa = (ch->phys - ch->base) >> 1;
-wtbar = 0xc & (wpwa >> WPWA_WTBAR_SHIFT(2));
-wcreg = (ch->phys - 16) & WAVCACHE_CHCTL_ADDRTAG_MASK;
-size = ch->buflen;
-apuch = (ch->num << 1) | 32;
-pan = PAN_RIGHT - PAN_FRONT;
-
-if (ch->stereo) {
-wcreg |= WAVCACHE_CHCTL_STEREO;
-if (ch->qs16) {
-aputype = APUTYPE_16BITSTEREO;
-wpwa >>= 1;
-size >>= 1;
-pan = -pan;
-} else
-aputype = APUTYPE_8BITSTEREO;
-} else {
-pan = 0;
-if (ch->qs16)
-aputype = APUTYPE_16BITLINEAR;
-else {
-aputype = APUTYPE_8BITLINEAR;
-speed >>= 1;
-}
-}
-if (ch->us)
-wcreg |= WAVCACHE_CHCTL_U8;
-
-if (wtbar > 8)
-wtbar = (wtbar >> 1) + 4;
-
-dv = (((speed % 48000) << 16) + 24000) / 48000
-+ ((speed / 48000) << 16);
-
-agg_lock(ch->parent);
-agg_power(ch->parent, powerstate_active);
-
-wc_wrreg(ch->parent, WAVCACHE_WTBAR + wtbar,
-ch->base >> WAVCACHE_BASEADDR_SHIFT);
-wc_wrreg(ch->parent, WAVCACHE_WTBAR + wtbar + 1,
-ch->base >> WAVCACHE_BASEADDR_SHIFT);
-if (wtbar < 8) {
-wc_wrreg(ch->parent, WAVCACHE_WTBAR + wtbar + 2,
-ch->base >> WAVCACHE_BASEADDR_SHIFT);
-wc_wrreg(ch->parent, WAVCACHE_WTBAR + wtbar + 3,
-ch->base >> WAVCACHE_BASEADDR_SHIFT);
-}
-wc_wrchctl(ch->parent, apuch, wcreg);
-wc_wrchctl(ch->parent, apuch + 1, wcreg);
-
-apu_setparam(ch->parent, apuch, wpwa, size, pan, dv);
-if (ch->stereo) {
-if (ch->qs16)
-wpwa |= (WPWA_STEREO >> 1);
-apu_setparam(ch->parent, apuch + 1, wpwa, size, -pan, dv);
-
-critical_enter();
-wp_wrapu(ch->parent, apuch, APUREG_APUTYPE,
-(aputype << APU_APUTYPE_SHIFT) | APU_DMA_ENABLED | 0xf);
-wp_wrapu(ch->parent, apuch + 1, APUREG_APUTYPE,
-(aputype << APU_APUTYPE_SHIFT) | APU_DMA_ENABLED | 0xf);
-critical_exit();
-} else {
-wp_wrapu(ch->parent, apuch, APUREG_APUTYPE,
-(aputype << APU_APUTYPE_SHIFT) | APU_DMA_ENABLED | 0xf);
-}
-
-/* to mark that this channel is ready for intr. */
-ch->parent->active |= (1 << ch->num);
-
-set_timer(ch->parent);
-wp_starttimer(ch->parent);
-agg_unlock(ch->parent);
+ bus_addr_t wpwa;
+ u_int32_t speed;
+ u_int16_t size, apuch, wtbar, wcreg, aputype;
+ u_int dv;
+ int pan;
+
+ speed = ch->speed;
+ wpwa = (ch->phys - ch->base) >> 1;
+ wtbar = 0xc & (wpwa >> WPWA_WTBAR_SHIFT(2));
+ wcreg = (ch->phys - 16) & WAVCACHE_CHCTL_ADDRTAG_MASK;
+ size = ch->buflen;
+ apuch = (ch->num << 1) | 32;
+ pan = PAN_RIGHT - PAN_FRONT;
+
+ if (ch->stereo) {
+ wcreg |= WAVCACHE_CHCTL_STEREO;
+ if (ch->qs16) {
+ aputype = APUTYPE_16BITSTEREO;
+ wpwa >>= 1;
+ size >>= 1;
+ pan = -pan;
+ } else
+ aputype = APUTYPE_8BITSTEREO;
+ } else {
+ pan = 0;
+ if (ch->qs16)
+ aputype = APUTYPE_16BITLINEAR;
+ else {
+ aputype = APUTYPE_8BITLINEAR;
+ speed >>= 1;
+ }
+ }
+ if (ch->us)
+ wcreg |= WAVCACHE_CHCTL_U8;
+
+ if (wtbar > 8)
+ wtbar = (wtbar >> 1) + 4;
+
+ dv = (((speed % 48000) << 16) + 24000) / 48000
+ + ((speed / 48000) << 16);
+
+ agg_lock(ch->parent);
+ agg_power(ch->parent, powerstate_active);
+
+ wc_wrreg(ch->parent, WAVCACHE_WTBAR + wtbar,
+ ch->base >> WAVCACHE_BASEADDR_SHIFT);
+ wc_wrreg(ch->parent, WAVCACHE_WTBAR + wtbar + 1,
+ ch->base >> WAVCACHE_BASEADDR_SHIFT);
+ if (wtbar < 8) {
+ wc_wrreg(ch->parent, WAVCACHE_WTBAR + wtbar + 2,
+ ch->base >> WAVCACHE_BASEADDR_SHIFT);
+ wc_wrreg(ch->parent, WAVCACHE_WTBAR + wtbar + 3,
+ ch->base >> WAVCACHE_BASEADDR_SHIFT);
+ }
+ wc_wrchctl(ch->parent, apuch, wcreg);
+ wc_wrchctl(ch->parent, apuch + 1, wcreg);
+
+ apu_setparam(ch->parent, apuch, wpwa, size, pan, dv);
+ if (ch->stereo) {
+ if (ch->qs16)
+ wpwa |= (WPWA_STEREO >> 1);
+ apu_setparam(ch->parent, apuch + 1, wpwa, size, -pan, dv);
+
+ critical_enter();
+ wp_wrapu(ch->parent, apuch, APUREG_APUTYPE,
+ (aputype << APU_APUTYPE_SHIFT) | APU_DMA_ENABLED | 0xf);
+ wp_wrapu(ch->parent, apuch + 1, APUREG_APUTYPE,
+ (aputype << APU_APUTYPE_SHIFT) | APU_DMA_ENABLED | 0xf);
+ critical_exit();
+ } else {
+ wp_wrapu(ch->parent, apuch, APUREG_APUTYPE,
+ (aputype << APU_APUTYPE_SHIFT) | APU_DMA_ENABLED | 0xf);
+ }
+
+ /* to mark that this channel is ready for intr. */
+ ch->parent->active |= (1 << ch->num);
+
+ set_timer(ch->parent);
+ wp_starttimer(ch->parent);
+ agg_unlock(ch->parent);
}
static void
aggch_stop_dac(struct agg_chinfo *ch)
{
-agg_lock(ch->parent);
+ agg_lock(ch->parent);
-/* to mark that this channel no longer needs further intrs. */
-ch->parent->active &= ~(1 << ch->num);
+ /* to mark that this channel no longer needs further intrs. */
+ ch->parent->active &= ~(1 << ch->num);
-wp_wrapu(ch->parent, (ch->num << 1) | 32, APUREG_APUTYPE,
-APUTYPE_INACTIVE << APU_APUTYPE_SHIFT);
-wp_wrapu(ch->parent, (ch->num << 1) | 33, APUREG_APUTYPE,
-APUTYPE_INACTIVE << APU_APUTYPE_SHIFT);
-
-if (ch->parent->active) {
-set_timer(ch->parent);
-wp_starttimer(ch->parent);
-} else {
-wp_stoptimer(ch->parent);
-agg_power(ch->parent, powerstate_idle);
-}
-agg_unlock(ch->parent);
+ wp_wrapu(ch->parent, (ch->num << 1) | 32, APUREG_APUTYPE,
+ APUTYPE_INACTIVE << APU_APUTYPE_SHIFT);
+ wp_wrapu(ch->parent, (ch->num << 1) | 33, APUREG_APUTYPE,
+ APUTYPE_INACTIVE << APU_APUTYPE_SHIFT);
+
+ if (ch->parent->active) {
+ set_timer(ch->parent);
+ wp_starttimer(ch->parent);
+ } else {
+ wp_stoptimer(ch->parent);
+ agg_power(ch->parent, powerstate_idle);
+ }
+ agg_unlock(ch->parent);
}
static void
aggch_start_adc(struct agg_rchinfo *ch)
{
-bus_addr_t wpwa, wpwa2;
-u_int16_t wcreg, wcreg2;
-u_int dv;
-int pan;
-
-/* speed > 48000 not cared */
-dv = ((ch->speed << 16) + 24000) / 48000;
-
-/* RATECONV doesn't seem to like dv == 0x10000. */
-if (dv == 0x10000)
-dv--;
-
-if (ch->stereo) {
-wpwa = (ch->srcphys - ch->base) >> 1;
-wpwa2 = (ch->srcphys + ch->parent->bufsz/2 - ch->base) >> 1;
-wcreg = (ch->srcphys - 16) & WAVCACHE_CHCTL_ADDRTAG_MASK;
-wcreg2 = (ch->base - 16) & WAVCACHE_CHCTL_ADDRTAG_MASK;
-pan = PAN_LEFT - PAN_FRONT;
-} else {
-wpwa = (ch->phys - ch->base) >> 1;
-wpwa2 = (ch->srcphys - ch->base) >> 1;
-wcreg = (ch->phys - 16) & WAVCACHE_CHCTL_ADDRTAG_MASK;
-wcreg2 = (ch->base - 16) & WAVCACHE_CHCTL_ADDRTAG_MASK;
-pan = 0;
-}
-
-agg_lock(ch->parent);
-
-ch->hwptr = 0;
-agg_power(ch->parent, powerstate_active);
-
-/* Invalidate WaveCache. */
-wc_wrchctl(ch->parent, 0, wcreg | WAVCACHE_CHCTL_STEREO);
-wc_wrchctl(ch->parent, 1, wcreg | WAVCACHE_CHCTL_STEREO);
-wc_wrchctl(ch->parent, 2, wcreg2 | WAVCACHE_CHCTL_STEREO);
-wc_wrchctl(ch->parent, 3, wcreg2 | WAVCACHE_CHCTL_STEREO);
-
-/* Load APU registers. */
-/* APU #0 : Sample rate converter for left/center. */
-apu_setparam(ch->parent, 0, WPWA_USE_SYSMEM | wpwa,
-ch->buflen >> ch->stereo, 0, dv);
-wp_wrapu(ch->parent, 0, APUREG_AMPLITUDE, 0);
-wp_wrapu(ch->parent, 0, APUREG_ROUTING, 2 << APU_DATASRC_A_SHIFT);
-
-/* APU #1 : Sample rate converter for right. */
-apu_setparam(ch->parent, 1, WPWA_USE_SYSMEM | wpwa2,
-ch->buflen >> ch->stereo, 0, dv);
-wp_wrapu(ch->parent, 1, APUREG_AMPLITUDE, 0);
-wp_wrapu(ch->parent, 1, APUREG_ROUTING, 3 << APU_DATASRC_A_SHIFT);
-
-/* APU #2 : Input mixer for left. */
-apu_setparam(ch->parent, 2, WPWA_USE_SYSMEM | 0,
-ch->parent->bufsz >> 2, pan, 0x10000);
-wp_wrapu(ch->parent, 2, APUREG_AMPLITUDE, 0);
-wp_wrapu(ch->parent, 2, APUREG_EFFECT_GAIN, 0xf0);
-wp_wrapu(ch->parent, 2, APUREG_ROUTING, 0x15 << APU_DATASRC_A_SHIFT);
-
-/* APU #3 : Input mixer for right. */
-apu_setparam(ch->parent, 3, WPWA_USE_SYSMEM | (ch->parent->bufsz >> 2),
-ch->parent->bufsz >> 2, -pan, 0x10000);
-wp_wrapu(ch->parent, 3, APUREG_AMPLITUDE, 0);
-wp_wrapu(ch->parent, 3, APUREG_EFFECT_GAIN, 0xf0);
-wp_wrapu(ch->parent, 3, APUREG_ROUTING, 0x14 << APU_DATASRC_A_SHIFT);
-
-/* to mark this channel ready for intr. */
-ch->parent->active |= (1 << ch->parent->playchns);
-
-/* start adc */
-critical_enter();
-wp_wrapu(ch->parent, 0, APUREG_APUTYPE,
-(APUTYPE_RATECONV << APU_APUTYPE_SHIFT) | APU_DMA_ENABLED | 0xf);
-wp_wrapu(ch->parent, 1, APUREG_APUTYPE,
-(APUTYPE_RATECONV << APU_APUTYPE_SHIFT) | APU_DMA_ENABLED | 0xf);
-wp_wrapu(ch->parent, 2, APUREG_APUTYPE,
-(APUTYPE_INPUTMIXER << APU_APUTYPE_SHIFT) | 0xf);
-wp_wrapu(ch->parent, 3, APUREG_APUTYPE,
-(APUTYPE_INPUTMIXER << APU_APUTYPE_SHIFT) | 0xf);
-critical_exit();
-
-set_timer(ch->parent);
-wp_starttimer(ch->parent);
-agg_unlock(ch->parent);
+ bus_addr_t wpwa, wpwa2;
+ u_int16_t wcreg, wcreg2;
+ u_int dv;
+ int pan;
+
+ /* speed > 48000 not cared */
+ dv = ((ch->speed << 16) + 24000) / 48000;
+
+ /* RATECONV doesn't seem to like dv == 0x10000. */
+ if (dv == 0x10000)
+ dv--;
+
+ if (ch->stereo) {
+ wpwa = (ch->srcphys - ch->base) >> 1;
+ wpwa2 = (ch->srcphys + ch->parent->bufsz/2 - ch->base) >> 1;
+ wcreg = (ch->srcphys - 16) & WAVCACHE_CHCTL_ADDRTAG_MASK;
+ wcreg2 = (ch->base - 16) & WAVCACHE_CHCTL_ADDRTAG_MASK;
+ pan = PAN_LEFT - PAN_FRONT;
+ } else {
+ wpwa = (ch->phys - ch->base) >> 1;
+ wpwa2 = (ch->srcphys - ch->base) >> 1;
+ wcreg = (ch->phys - 16) & WAVCACHE_CHCTL_ADDRTAG_MASK;
+ wcreg2 = (ch->base - 16) & WAVCACHE_CHCTL_ADDRTAG_MASK;
+ pan = 0;
+ }
+
+ agg_lock(ch->parent);
+
+ ch->hwptr = 0;
+ agg_power(ch->parent, powerstate_active);
+
+ /* Invalidate WaveCache. */
+ wc_wrchctl(ch->parent, 0, wcreg | WAVCACHE_CHCTL_STEREO);
+ wc_wrchctl(ch->parent, 1, wcreg | WAVCACHE_CHCTL_STEREO);
+ wc_wrchctl(ch->parent, 2, wcreg2 | WAVCACHE_CHCTL_STEREO);
+ wc_wrchctl(ch->parent, 3, wcreg2 | WAVCACHE_CHCTL_STEREO);
+
+ /* Load APU registers. */
+ /* APU #0 : Sample rate converter for left/center. */
+ apu_setparam(ch->parent, 0, WPWA_USE_SYSMEM | wpwa,
+ ch->buflen >> ch->stereo, 0, dv);
+ wp_wrapu(ch->parent, 0, APUREG_AMPLITUDE, 0);
+ wp_wrapu(ch->parent, 0, APUREG_ROUTING, 2 << APU_DATASRC_A_SHIFT);
+
+ /* APU #1 : Sample rate converter for right. */
+ apu_setparam(ch->parent, 1, WPWA_USE_SYSMEM | wpwa2,
+ ch->buflen >> ch->stereo, 0, dv);
+ wp_wrapu(ch->parent, 1, APUREG_AMPLITUDE, 0);
+ wp_wrapu(ch->parent, 1, APUREG_ROUTING, 3 << APU_DATASRC_A_SHIFT);
+
+ /* APU #2 : Input mixer for left. */
+ apu_setparam(ch->parent, 2, WPWA_USE_SYSMEM | 0,
+ ch->parent->bufsz >> 2, pan, 0x10000);
+ wp_wrapu(ch->parent, 2, APUREG_AMPLITUDE, 0);
+ wp_wrapu(ch->parent, 2, APUREG_EFFECT_GAIN, 0xf0);
+ wp_wrapu(ch->parent, 2, APUREG_ROUTING, 0x15 << APU_DATASRC_A_SHIFT);
+
+ /* APU #3 : Input mixer for right. */
+ apu_setparam(ch->parent, 3, WPWA_USE_SYSMEM | (ch->parent->bufsz >> 2),
+ ch->parent->bufsz >> 2, -pan, 0x10000);
+ wp_wrapu(ch->parent, 3, APUREG_AMPLITUDE, 0);
+ wp_wrapu(ch->parent, 3, APUREG_EFFECT_GAIN, 0xf0);
+ wp_wrapu(ch->parent, 3, APUREG_ROUTING, 0x14 << APU_DATASRC_A_SHIFT);
+
+ /* to mark this channel ready for intr. */
+ ch->parent->active |= (1 << ch->parent->playchns);
+
+ /* start adc */
+ critical_enter();
+ wp_wrapu(ch->parent, 0, APUREG_APUTYPE,
+ (APUTYPE_RATECONV << APU_APUTYPE_SHIFT) | APU_DMA_ENABLED | 0xf);
+ wp_wrapu(ch->parent, 1, APUREG_APUTYPE,
+ (APUTYPE_RATECONV << APU_APUTYPE_SHIFT) | APU_DMA_ENABLED | 0xf);
+ wp_wrapu(ch->parent, 2, APUREG_APUTYPE,
+ (APUTYPE_INPUTMIXER << APU_APUTYPE_SHIFT) | 0xf);
+ wp_wrapu(ch->parent, 3, APUREG_APUTYPE,
+ (APUTYPE_INPUTMIXER << APU_APUTYPE_SHIFT) | 0xf);
+ critical_exit();
+
+ set_timer(ch->parent);
+ wp_starttimer(ch->parent);
+ agg_unlock(ch->parent);
}
static void
aggch_stop_adc(struct agg_rchinfo *ch)
{
-int apuch;
-
-agg_lock(ch->parent);
+ int apuch;
-/* to mark that this channel no longer needs further intrs. */
-ch->parent->active &= ~(1 << ch->parent->playchns);
+ agg_lock(ch->parent);
-for (apuch = 0; apuch < 4; apuch++)
-wp_wrapu(ch->parent, apuch, APUREG_APUTYPE,
-APUTYPE_INACTIVE << APU_APUTYPE_SHIFT);
+ /* to mark that this channel no longer needs further intrs. */
+ ch->parent->active &= ~(1 << ch->parent->playchns);
-if (ch->parent->active) {
-set_timer(ch->parent);
-wp_starttimer(ch->parent);
-} else {
-wp_stoptimer(ch->parent);
-agg_power(ch->parent, powerstate_idle);
-}
-agg_unlock(ch->parent);
+ for (apuch = 0; apuch < 4; apuch++)
+ wp_wrapu(ch->parent, apuch, APUREG_APUTYPE,
+ APUTYPE_INACTIVE << APU_APUTYPE_SHIFT);
+
+ if (ch->parent->active) {
+ set_timer(ch->parent);
+ wp_starttimer(ch->parent);
+ } else {
+ wp_stoptimer(ch->parent);
+ agg_power(ch->parent, powerstate_idle);
+ }
+ agg_unlock(ch->parent);
}
/*
-* Feed from L/R channel of ADC to destination with stereo interleaving.
-* This function expects n not overwrapping the buffer boundary.
-* Note that n is measured in sample unit.
-*
-* XXX - this function works in 16bit stereo format only.
-*/
-static inline void
+ * Feed from L/R channel of ADC to destination with stereo interleaving.
+ * This function expects n not overwrapping the buffer boundary.
+ * Note that n is measured in sample unit.
+ *
+ * XXX - this function works in 16bit stereo format only.
+ */
+static void
interleave(int16_t *l, int16_t *r, int16_t *p, unsigned n)
{
-int16_t *end;
+ int16_t *end;
-for (end = l + n; l < end; ) {
-*p++ = *l++;
-*p++ = *r++;
-}
+ for (end = l + n; l < end; ) {
+ *p++ = *l++;
+ *p++ = *r++;
+ }
}
static void
aggch_feed_adc_stereo(struct agg_rchinfo *ch)
{
-unsigned cur, last;
-int16_t *src2;
+ unsigned cur, last;
+ int16_t *src2;
-agg_lock(ch->parent);
-cur = wp_rdapu(ch->parent, 0, APUREG_CURPTR);
-agg_unlock(ch->parent);
-cur -= 0xffff & ((ch->srcphys - ch->base) >> 1);
-last = ch->hwptr;
-src2 = ch->src + ch->parent->bufsz/4;
-
-if (cur < last) {
-interleave(ch->src + last, src2 + last,
-ch->sink + 2*last, ch->buflen/2 - last);
-interleave(ch->src, src2,
-ch->sink, cur);
-} else if (cur > last)
-interleave(ch->src + last, src2 + last,
-ch->sink + 2*last, cur - last);
-ch->hwptr = cur;
+ agg_lock(ch->parent);
+ cur = wp_rdapu(ch->parent, 0, APUREG_CURPTR);
+ agg_unlock(ch->parent);
+ cur -= 0xffff & ((ch->srcphys - ch->base) >> 1);
+ last = ch->hwptr;
+ src2 = ch->src + ch->parent->bufsz/4;
+
+ if (cur < last) {
+ interleave(ch->src + last, src2 + last,
+ ch->sink + 2*last, ch->buflen/2 - last);
+ interleave(ch->src, src2,
+ ch->sink, cur);
+ } else if (cur > last)
+ interleave(ch->src + last, src2 + last,
+ ch->sink + 2*last, cur - last);
+ ch->hwptr = cur;
}
/*
-* Feed from R channel of ADC and mixdown to destination L/center.
-* This function expects n not overwrapping the buffer boundary.
-* Note that n is measured in sample unit.
-*
-* XXX - this function works in 16bit monoral format only.
-*/
-static inline void
+ * Feed from R channel of ADC and mixdown to destination L/center.
+ * This function expects n not overwrapping the buffer boundary.
+ * Note that n is measured in sample unit.
+ *
+ * XXX - this function works in 16bit monoral format only.
+ */
+static void
mixdown(int16_t *src, int16_t *dest, unsigned n)
{
-int16_t *end;
+ int16_t *end;
-for (end = dest + n; dest < end; dest++)
-*dest = (int16_t)(((int)*dest - (int)*src++) / 2);
+ for (end = dest + n; dest < end; dest++)
+ *dest = (int16_t)(((int)*dest - (int)*src++) / 2);
}
static void
aggch_feed_adc_mono(struct agg_rchinfo *ch)
{
-unsigned cur, last;
+ unsigned cur, last;
-agg_lock(ch->parent);
-cur = wp_rdapu(ch->parent, 0, APUREG_CURPTR);
-agg_unlock(ch->parent);
-cur -= 0xffff & ((ch->phys - ch->base) >> 1);
-last = ch->hwptr;
-
-if (cur < last) {
-mixdown(ch->src + last, ch->sink + last, ch->buflen - last);
-mixdown(ch->src, ch->sink, cur);
-} else if (cur > last)
-mixdown(ch->src + last, ch->sink + last, cur - last);
-ch->hwptr = cur;
+ agg_lock(ch->parent);
+ cur = wp_rdapu(ch->parent, 0, APUREG_CURPTR);
+ agg_unlock(ch->parent);
+ cur -= 0xffff & ((ch->phys - ch->base) >> 1);
+ last = ch->hwptr;
+
+ if (cur < last) {
+ mixdown(ch->src + last, ch->sink + last, ch->buflen - last);
+ mixdown(ch->src, ch->sink, cur);
+ } else if (cur > last)
+ mixdown(ch->src + last, ch->sink + last, cur - last);
+ ch->hwptr = cur;
}
+#ifdef AGG_JITTER_CORRECTION
/*
-* Stereo jitter suppressor.
-* Sometimes playback pointers differ in stereo-paired channels.
-* Calling this routine within intr fixes the problem.
-*/
-static inline void
+ * Stereo jitter suppressor.
+ * Sometimes playback pointers differ in stereo-paired channels.
+ * Calling this routine within intr fixes the problem.
+ */
+static void
suppress_jitter(struct agg_chinfo *ch)
{
-if (ch->stereo) {
-int cp1, cp2, diff /*, halfsize*/ ;
+ if (ch->stereo) {
+ int cp1, cp2, diff /*, halfsize*/ ;
-/*halfsize = (ch->qs16? ch->buflen >> 2 : ch->buflen >> 1);*/
-cp1 = wp_rdapu(ch->parent, (ch->num << 1) | 32, APUREG_CURPTR);
-cp2 = wp_rdapu(ch->parent, (ch->num << 1) | 33, APUREG_CURPTR);
-if (cp1 != cp2) {
-diff = (cp1 > cp2 ? cp1 - cp2 : cp2 - cp1);
-if (diff > 1 /* && diff < halfsize*/ )
-AGG_WR(ch->parent, PORT_DSP_DATA, cp1, 2);
-}
-}
+ /*halfsize = (ch->qs16? ch->buflen >> 2 : ch->buflen >> 1);*/
+ cp1 = wp_rdapu(ch->parent, (ch->num << 1) | 32, APUREG_CURPTR);
+ cp2 = wp_rdapu(ch->parent, (ch->num << 1) | 33, APUREG_CURPTR);
+ if (cp1 != cp2) {
+ diff = (cp1 > cp2 ? cp1 - cp2 : cp2 - cp1);
+ if (diff > 1 /* && diff < halfsize*/ )
+ AGG_WR(ch->parent, PORT_DSP_DATA, cp1, 2);
+ }
+ }
}
-static inline void
+static void
suppress_rec_jitter(struct agg_rchinfo *ch)
{
-int cp1, cp2, diff /*, halfsize*/ ;
+ int cp1, cp2, diff /*, halfsize*/ ;
-/*halfsize = (ch->stereo? ch->buflen >> 2 : ch->buflen >> 1);*/
-cp1 = (ch->stereo? ch->parent->bufsz >> 2 : ch->parent->bufsz >> 1)
-+ wp_rdapu(ch->parent, 0, APUREG_CURPTR);
-cp2 = wp_rdapu(ch->parent, 1, APUREG_CURPTR);
-if (cp1 != cp2) {
-diff = (cp1 > cp2 ? cp1 - cp2 : cp2 - cp1);
-if (diff > 1 /* && diff < halfsize*/ )
-AGG_WR(ch->parent, PORT_DSP_DATA, cp1, 2);
-}
+ /*halfsize = (ch->stereo? ch->buflen >> 2 : ch->buflen >> 1);*/
+ cp1 = (ch->stereo? ch->parent->bufsz >> 2 : ch->parent->bufsz >> 1)
+ + wp_rdapu(ch->parent, 0, APUREG_CURPTR);
+ cp2 = wp_rdapu(ch->parent, 1, APUREG_CURPTR);
+ if (cp1 != cp2) {
+ diff = (cp1 > cp2 ? cp1 - cp2 : cp2 - cp1);
+ if (diff > 1 /* && diff < halfsize*/ )
+ AGG_WR(ch->parent, PORT_DSP_DATA, cp1, 2);
+ }
}
+#endif
-static inline u_int
+static u_int
calc_timer_div(struct agg_chinfo *ch)
{
-u_int speed;
+ u_int speed;
-speed = ch->speed;
+ speed = ch->speed;
#ifdef INVARIANTS
-if (speed == 0) {
-printf("snd_maestro: pch[%d].speed == 0, which shouldn'tn",
-ch->num);
-speed = 1;
-}
+ if (speed == 0) {
+ printf("snd_maestro: pch[%d].speed == 0, which shouldn't\n",
+ ch->num);
+ speed = 1;
+ }
#endif
-return (48000 * (ch->blklen << (!ch->qs16 + !ch->stereo))
-+ speed - 1) / speed;
+ return (48000 * (ch->blklen << (!ch->qs16 + !ch->stereo))
+ + speed - 1) / speed;
}
-static inline u_int
+static u_int
calc_timer_div_rch(struct agg_rchinfo *ch)
{
-u_int speed;
+ u_int speed;
-speed = ch->speed;
+ speed = ch->speed;
#ifdef INVARIANTS
-if (speed == 0) {
-printf("snd_maestro: rch.speed == 0, which shouldn'tn");
-speed = 1;
-}
+ if (speed == 0) {
+ printf("snd_maestro: rch.speed == 0, which shouldn't\n");
+ speed = 1;
+ }
#endif
-return (48000 * (ch->blklen << (!ch->stereo))
-+ speed - 1) / speed;
+ return (48000 * (ch->blklen << (!ch->stereo))
+ + speed - 1) / speed;
}
static void
set_timer(struct agg_info *ess)
{
-int i;
-u_int dv = 32 << 7, newdv;
+ int i;
+ u_int dv = 32 << 7, newdv;
-for (i = 0; i < ess->playchns; i++)
-if ((ess->active & (1 << i)) &&
-(dv > (newdv = calc_timer_div(ess->pch + i))))
-dv = newdv;
-if ((ess->active & (1 << i)) &&
-(dv > (newdv = calc_timer_div_rch(&ess->rch))))
-dv = newdv;
+ for (i = 0; i < ess->playchns; i++)
+ if ((ess->active & (1 << i)) &&
+ (dv > (newdv = calc_timer_div(ess->pch + i))))
+ dv = newdv;
+ if ((ess->active & (1 << i)) &&
+ (dv > (newdv = calc_timer_div_rch(&ess->rch))))
+ dv = newdv;
-wp_settimer(ess, dv);
+ wp_settimer(ess, dv);
}
/* -----------------------------
-* Newpcm glue.
-*/
+ * Newpcm glue.
+ */
/* AC97 mixer interface. */
static u_int32_t
agg_ac97_init(kobj_t obj, void *sc)
{
-struct agg_info *ess = sc;
+ struct agg_info *ess = sc;
-return (AGG_RD(ess, PORT_CODEC_STAT, 1) & CODEC_STAT_MASK)? 0 : 1;
+ return (AGG_RD(ess, PORT_CODEC_STAT, 1) & CODEC_STAT_MASK)? 0 : 1;
}
static int
agg_ac97_read(kobj_t obj, void *sc, int regno)
{
-struct agg_info *ess = sc;
-int ret;
+ struct agg_info *ess = sc;
+ int ret;
-/* XXX sound locking violation: agg_lock(ess); */
-ret = agg_rdcodec(ess, regno);
-/* agg_unlock(ess); */
-return ret;
+ /* XXX sound locking violation: agg_lock(ess); */
+ ret = agg_rdcodec(ess, regno);
+ /* agg_unlock(ess); */
+ return ret;
}
static int
agg_ac97_write(kobj_t obj, void *sc, int regno, u_int32_t data)
{
-struct agg_info *ess = sc;
-int ret;
+ struct agg_info *ess = sc;
+ int ret;
-/* XXX sound locking violation: agg_lock(ess); */
-ret = agg_wrcodec(ess, regno, data);
-/* agg_unlock(ess); */
-return ret;
+ /* XXX sound locking violation: agg_lock(ess); */
+ ret = agg_wrcodec(ess, regno, data);
+ /* agg_unlock(ess); */
+ return ret;
}
static kobj_method_t agg_ac97_methods[] = {
-KOBJMETHOD(ac97_init, agg_ac97_init),
-KOBJMETHOD(ac97_read, agg_ac97_read),
-KOBJMETHOD(ac97_write, agg_ac97_write),
-{ 0, 0 }
+ KOBJMETHOD(ac97_init, agg_ac97_init),
+ KOBJMETHOD(ac97_read, agg_ac97_read),
+ KOBJMETHOD(ac97_write, agg_ac97_write),
+ { 0, 0 }
};
AC97_DECLARE(agg_ac97);
@@ -1271,202 +1276,203 @@
/* Playback channel. */
static void *
-aggpch_init(kobj_t obj, void *devinfo, struct snd_dbuf *b, struct pcm_channel *c, int dir)
+aggpch_init(kobj_t obj, void *devinfo, struct snd_dbuf *b,
+ struct pcm_channel *c, int dir)
{
-struct agg_info *ess = devinfo;
-struct agg_chinfo *ch;
-bus_addr_t physaddr;
-void *p;
-
-KASSERT((dir == PCMDIR_PLAY),
-("aggpch_init() called for RECORDING channel!"));
-ch = ess->pch + ess->playchns;
-
-ch->parent = ess;
-ch->channel = c;
-ch->buffer = b;
-ch->num = ess->playchns;
-
-p = dma_malloc(ess->buf_dmat, ess->bufsz, &physaddr);
-if (p == NULL)
-return NULL;
-ch->phys = physaddr;
-ch->base = physaddr & ((~(bus_addr_t)0) << WAVCACHE_BASEADDR_SHIFT);
-
-sndbuf_setup(b, p, ess->bufsz);
-ch->blklen = sndbuf_getblksz(b) / 2;
-ch->buflen = sndbuf_getsize(b) / 2;
-ess->playchns++;
+ struct agg_info *ess = devinfo;
+ struct agg_chinfo *ch;
+ bus_addr_t physaddr;
+ void *p;
+
+ KASSERT((dir == PCMDIR_PLAY),
+ ("aggpch_init() called for RECORDING channel!"));
+ ch = ess->pch + ess->playchns;
+
+ ch->parent = ess;
+ ch->channel = c;
+ ch->buffer = b;
+ ch->num = ess->playchns;
+
+ p = dma_malloc(ess->buf_dmat, ess->bufsz, &physaddr);
+ if (p == NULL)
+ return NULL;
+ ch->phys = physaddr;
+ ch->base = physaddr & ((~(bus_addr_t)0) << WAVCACHE_BASEADDR_SHIFT);
+
+ sndbuf_setup(b, p, ess->bufsz);
+ ch->blklen = sndbuf_getblksz(b) / 2;
+ ch->buflen = sndbuf_getsize(b) / 2;
+ ess->playchns++;
-return ch;
+ return ch;
}
static void
adjust_pchbase(struct agg_chinfo *chans, u_int n, u_int size)
{
-struct agg_chinfo *pchs[AGG_MAXPLAYCH];
-u_int i, j, k;
-bus_addr_t base;
-
-/* sort pchs by phys address */
-for (i = 0; i < n; i++) {
-for (j = 0; j < i; j++)
-if (chans[i].phys < pchs[j]->phys) {
-for (k = i; k > j; k--)
-pchs[k] = pchs[k - 1];
-break;
-}
-pchs[j] = chans + i;
-}
+ struct agg_chinfo *pchs[AGG_MAXPLAYCH];
+ u_int i, j, k;
+ bus_addr_t base;
+
+ /* sort pchs by phys address */
+ for (i = 0; i < n; i++) {
+ for (j = 0; j < i; j++)
+ if (chans[i].phys < pchs[j]->phys) {
+ for (k = i; k > j; k--)
+ pchs[k] = pchs[k - 1];
+ break;
+ }
+ pchs[j] = chans + i;
+ }
-/* use new base register if next buffer can not be addressed
-via current base. */
+ /* use new base register if next buffer can not be addressed
+ via current base. */
#define BASE_SHIFT (WPWA_WTBAR_SHIFT(2) + 2 + 1)
-base = pchs[0]->base;
-for (k = 1, i = 1; i < n; i++) {
-if (pchs[i]->phys + size - base >= 1 << BASE_SHIFT)
-/* not addressable: assign new base */
-base = (pchs[i]->base -= k++ << BASE_SHIFT);
-else
-pchs[i]->base = base;
-}
+ base = pchs[0]->base;
+ for (k = 1, i = 1; i < n; i++) {
+ if (pchs[i]->phys + size - base >= 1 << BASE_SHIFT)
+ /* not addressable: assign new base */
+ base = (pchs[i]->base -= k++ << BASE_SHIFT);
+ else
+ pchs[i]->base = base;
+ }
#undef BASE_SHIFT
-if (bootverbose) {
-printf("Total of %d bases are assigned.n", k);
-for (i = 0; i < n; i++) {
-printf("ch.%d: phys 0x%llx, wpwa 0x%llxn",
-i, (long long)chans[i].phys,
-(long long)(chans[i].phys -
-chans[i].base) >> 1);
-}
-}
+ if (bootverbose) {
+ printf("Total of %d bases are assigned.\n", k);
+ for (i = 0; i < n; i++) {
+ printf("ch.%d: phys 0x%llx, wpwa 0x%llx\n",
+ i, (long long)chans[i].phys,
+ (long long)(chans[i].phys -
+ chans[i].base) >> 1);
+ }
+ }
}
static int
aggpch_free(kobj_t obj, void *data)
{
-struct agg_chinfo *ch = data;
-struct agg_info *ess = ch->parent;
+ struct agg_chinfo *ch = data;
+ struct agg_info *ess = ch->parent;
-/* free up buffer - called after channel stopped */
-dma_free(ess->buf_dmat, sndbuf_getbuf(ch->buffer));
+ /* free up buffer - called after channel stopped */
+ dma_free(ess->buf_dmat, sndbuf_getbuf(ch->buffer));
-/* return 0 if ok */
-return 0;
+ /* return 0 if ok */
+ return 0;
}
static int
aggpch_setformat(kobj_t obj, void *data, u_int32_t format)
{
-struct agg_chinfo *ch = data;
+ struct agg_chinfo *ch = data;
-if (format & AFMT_BIGENDIAN || format & AFMT_U16_LE)
-return EINVAL;
-ch->stereo = ch->qs16 = ch->us = 0;
-if (format & AFMT_STEREO)
-ch->stereo = 1;
-
-if (format & AFMT_U8 || format & AFMT_S8) {
-if (format & AFMT_U8)
-ch->us = 1;
-} else
-ch->qs16 = 1;
-return 0;
+ if (format & AFMT_BIGENDIAN || format & AFMT_U16_LE)
+ return EINVAL;
+ ch->stereo = ch->qs16 = ch->us = 0;
+ if (format & AFMT_STEREO)
+ ch->stereo = 1;
+
+ if (format & AFMT_U8 || format & AFMT_S8) {
+ if (format & AFMT_U8)
+ ch->us = 1;
+ } else
+ ch->qs16 = 1;
+ return 0;
}
static int
aggpch_setspeed(kobj_t obj, void *data, u_int32_t speed)
{
-return ((struct agg_chinfo*)data)->speed = speed;
+ return ((struct agg_chinfo*)data)->speed = speed;
}
static int
aggpch_setblocksize(kobj_t obj, void *data, u_int32_t blocksize)
{
-struct agg_chinfo *ch = data;
-int blkcnt;
+ struct agg_chinfo *ch = data;
+ int blkcnt;
-/* try to keep at least 20msec DMA space */
-blkcnt = (ch->speed << (ch->stereo + ch->qs16)) / (50 * blocksize);
-RANGE(blkcnt, 2, ch->parent->bufsz / blocksize);
-
-if (sndbuf_getsize(ch->buffer) != blkcnt * blocksize) {
-sndbuf_resize(ch->buffer, blkcnt, blocksize);
-blkcnt = sndbuf_getblkcnt(ch->buffer);
-blocksize = sndbuf_getblksz(ch->buffer);
-} else {
-sndbuf_setblkcnt(ch->buffer, blkcnt);
-sndbuf_setblksz(ch->buffer, blocksize);
-}
-
-ch->blklen = blocksize / 2;
-ch->buflen = blkcnt * blocksize / 2;
-return blocksize;
+ /* try to keep at least 20msec DMA space */
+ blkcnt = (ch->speed << (ch->stereo + ch->qs16)) / (50 * blocksize);
+ RANGE(blkcnt, 2, ch->parent->bufsz / blocksize);
+
+ if (sndbuf_getsize(ch->buffer) != blkcnt * blocksize) {
+ sndbuf_resize(ch->buffer, blkcnt, blocksize);
+ blkcnt = sndbuf_getblkcnt(ch->buffer);
+ blocksize = sndbuf_getblksz(ch->buffer);
+ } else {
+ sndbuf_setblkcnt(ch->buffer, blkcnt);
+ sndbuf_setblksz(ch->buffer, blocksize);
+ }
+
+ ch->blklen = blocksize / 2;
+ ch->buflen = blkcnt * blocksize / 2;
+ return blocksize;
}
static int
aggpch_trigger(kobj_t obj, void *data, int go)
{
-struct agg_chinfo *ch = data;
+ struct agg_chinfo *ch = data;
-switch (go) {
-case PCMTRIG_EMLDMAWR:
-break;
-case PCMTRIG_START:
-aggch_start_dac(ch);
-break;
-case PCMTRIG_ABORT:
-case PCMTRIG_STOP:
-aggch_stop_dac(ch);
-break;
-}
-return 0;
+ switch (go) {
+ case PCMTRIG_EMLDMAWR:
+ break;
+ case PCMTRIG_START:
+ aggch_start_dac(ch);
+ break;
+ case PCMTRIG_ABORT:
+ case PCMTRIG_STOP:
+ aggch_stop_dac(ch);
+ break;
+ }
+ return 0;
}
static int
aggpch_getptr(kobj_t obj, void *data)
{
-struct agg_chinfo *ch = data;
-u_int cp;
+ struct agg_chinfo *ch = data;
+ u_int cp;
-agg_lock(ch->parent);
-cp = wp_rdapu(ch->parent, (ch->num << 1) | 32, APUREG_CURPTR);
-agg_unlock(ch->parent);
-
-return ch->qs16 && ch->stereo
-? (cp << 2) - ((0xffff << 2) & (ch->phys - ch->base))
-: (cp << 1) - ((0xffff << 1) & (ch->phys - ch->base));
+ agg_lock(ch->parent);
+ cp = wp_rdapu(ch->parent, (ch->num << 1) | 32, APUREG_CURPTR);
+ agg_unlock(ch->parent);
+
+ return ch->qs16 && ch->stereo
+ ? (cp << 2) - ((0xffff << 2) & (ch->phys - ch->base))
+ : (cp << 1) - ((0xffff << 1) & (ch->phys - ch->base));
}
static struct pcmchan_caps *
aggpch_getcaps(kobj_t obj, void *data)
{
-static u_int32_t playfmt[] = {
-AFMT_U8,
-AFMT_STEREO | AFMT_U8,
-AFMT_S8,
-AFMT_STEREO | AFMT_S8,
-AFMT_S16_LE,
-AFMT_STEREO | AFMT_S16_LE,
-0
-};
-static struct pcmchan_caps playcaps = {8000, 48000, playfmt, 0};
+ static u_int32_t playfmt[] = {
+ AFMT_U8,
+ AFMT_STEREO | AFMT_U8,
+ AFMT_S8,
+ AFMT_STEREO | AFMT_S8,
+ AFMT_S16_LE,
+ AFMT_STEREO | AFMT_S16_LE,
+ 0
+ };
+ static struct pcmchan_caps playcaps = {8000, 48000, playfmt, 0};
-return &playcaps;
+ return &playcaps;
}
static kobj_method_t aggpch_methods[] = {
-KOBJMETHOD(channel_init, aggpch_init),
-KOBJMETHOD(channel_free, aggpch_free),
-KOBJMETHOD(channel_setformat, aggpch_setformat),
-KOBJMETHOD(channel_setspeed, aggpch_setspeed),
-KOBJMETHOD(channel_setblocksize, aggpch_setblocksize),
-KOBJMETHOD(channel_trigger, aggpch_trigger),
-KOBJMETHOD(channel_getptr, aggpch_getptr),
-KOBJMETHOD(channel_getcaps, aggpch_getcaps),
-{ 0, 0 }
+ KOBJMETHOD(channel_init, aggpch_init),
+ KOBJMETHOD(channel_free, aggpch_free),
+ KOBJMETHOD(channel_setformat, aggpch_setformat),
+ KOBJMETHOD(channel_setspeed, aggpch_setspeed),
+ KOBJMETHOD(channel_setblocksize, aggpch_setblocksize),
+ KOBJMETHOD(channel_trigger, aggpch_trigger),
+ KOBJMETHOD(channel_getptr, aggpch_getptr),
+ KOBJMETHOD(channel_getcaps, aggpch_getcaps),
+ { 0, 0 }
};
CHANNEL_DECLARE(aggpch);
@@ -1476,590 +1482,596 @@
/* Recording channel. */
static void *
-aggrch_init(kobj_t obj, void *devinfo, struct snd_dbuf *b, struct pcm_channel *c, int dir)
+aggrch_init(kobj_t obj, void *devinfo, struct snd_dbuf *b,
+ struct pcm_channel *c, int dir)
{
-struct agg_info *ess = devinfo;
-struct agg_rchinfo *ch;
-u_int8_t *p;
-
-KASSERT((dir == PCMDIR_REC),
-("aggrch_init() called for PLAYBACK channel!"));
-ch = &ess->rch;
-
-ch->parent = ess;
-ch->channel = c;
-ch->buffer = b;
-
-/* Uses the bottom-half of the status buffer. */
-p = ess->stat + ess->bufsz;
-ch->phys = ess->phys + ess->bufsz;
-ch->base = ess->phys;
-ch->src = (int16_t *)(p + ess->bufsz);
-ch->srcphys = ch->phys + ess->bufsz;
-ch->sink = (int16_t *)p;
-
-sndbuf_setup(b, p, ess->bufsz);
-ch->blklen = sndbuf_getblksz(b) / 2;
-ch->buflen = sndbuf_getsize(b) / 2;
+ struct agg_info *ess = devinfo;
+ struct agg_rchinfo *ch;
+ u_int8_t *p;
+
+ KASSERT((dir == PCMDIR_REC),
+ ("aggrch_init() called for PLAYBACK channel!"));
+ ch = &ess->rch;
+
+ ch->parent = ess;
+ ch->channel = c;
+ ch->buffer = b;
+
+ /* Uses the bottom-half of the status buffer. */
+ p = ess->stat + ess->bufsz;
+ ch->phys = ess->phys + ess->bufsz;
+ ch->base = ess->phys;
+ ch->src = (int16_t *)(p + ess->bufsz);
+ ch->srcphys = ch->phys + ess->bufsz;
+ ch->sink = (int16_t *)p;
+
+ sndbuf_setup(b, p, ess->bufsz);
+ ch->blklen = sndbuf_getblksz(b) / 2;
+ ch->buflen = sndbuf_getsize(b) / 2;
-return ch;
+ return ch;
}
static int
aggrch_setformat(kobj_t obj, void *data, u_int32_t format)
{
-struct agg_rchinfo *ch = data;
+ struct agg_rchinfo *ch = data;
-if (!(format & AFMT_S16_LE))
-return EINVAL;
-if (format & AFMT_STEREO)
-ch->stereo = 1;
-else
-ch->stereo = 0;
-return 0;
+ if (!(format & AFMT_S16_LE))
+ return EINVAL;
+ if (format & AFMT_STEREO)
+ ch->stereo = 1;
+ else
+ ch->stereo = 0;
+ return 0;
}
static int
aggrch_setspeed(kobj_t obj, void *data, u_int32_t speed)
{
-return ((struct agg_rchinfo*)data)->speed = speed;
+ return ((struct agg_rchinfo*)data)->speed = speed;
}
static int
aggrch_setblocksize(kobj_t obj, void *data, u_int32_t blocksize)
{
-struct agg_rchinfo *ch = data;
-int blkcnt;
+ struct agg_rchinfo *ch = data;
+ int blkcnt;
-/* try to keep at least 20msec DMA space */
-blkcnt = (ch->speed << ch->stereo) / (25 * blocksize);
-RANGE(blkcnt, 2, ch->parent->bufsz / blocksize);
-
-if (sndbuf_getsize(ch->buffer) != blkcnt * blocksize) {
-sndbuf_resize(ch->buffer, blkcnt, blocksize);
-blkcnt = sndbuf_getblkcnt(ch->buffer);
-blocksize = sndbuf_getblksz(ch->buffer);
-} else {
-sndbuf_setblkcnt(ch->buffer, blkcnt);
-sndbuf_setblksz(ch->buffer, blocksize);
-}
-
-ch->blklen = blocksize / 2;
-ch->buflen = blkcnt * blocksize / 2;
-return blocksize;
+ /* try to keep at least 20msec DMA space */
+ blkcnt = (ch->speed << ch->stereo) / (25 * blocksize);
+ RANGE(blkcnt, 2, ch->parent->bufsz / blocksize);
+
+ if (sndbuf_getsize(ch->buffer) != blkcnt * blocksize) {
+ sndbuf_resize(ch->buffer, blkcnt, blocksize);
+ blkcnt = sndbuf_getblkcnt(ch->buffer);
+ blocksize = sndbuf_getblksz(ch->buffer);
+ } else {
+ sndbuf_setblkcnt(ch->buffer, blkcnt);
+ sndbuf_setblksz(ch->buffer, blocksize);
+ }
+
+ ch->blklen = blocksize / 2;
+ ch->buflen = blkcnt * blocksize / 2;
+ return blocksize;
}
static int
aggrch_trigger(kobj_t obj, void *sc, int go)
{
-struct agg_rchinfo *ch = sc;
+ struct agg_rchinfo *ch = sc;
-switch (go) {
-case PCMTRIG_EMLDMARD:
-if (ch->stereo)
-aggch_feed_adc_stereo(ch);
-else
-aggch_feed_adc_mono(ch);
-break;
-case PCMTRIG_START:
-aggch_start_adc(ch);
-break;
-case PCMTRIG_ABORT:
-case PCMTRIG_STOP:
-aggch_stop_adc(ch);
-break;
-}
-return 0;
+ switch (go) {
+ case PCMTRIG_EMLDMARD:
+ if (ch->stereo)
+ aggch_feed_adc_stereo(ch);
+ else
+ aggch_feed_adc_mono(ch);
+ break;
+ case PCMTRIG_START:
+ aggch_start_adc(ch);
+ break;
+ case PCMTRIG_ABORT:
+ case PCMTRIG_STOP:
+ aggch_stop_adc(ch);
+ break;
+ }
+ return 0;
}
static int
aggrch_getptr(kobj_t obj, void *sc)
{
-struct agg_rchinfo *ch = sc;
+ struct agg_rchinfo *ch = sc;
-return ch->stereo? ch->hwptr << 2 : ch->hwptr << 1;
+ return ch->stereo? ch->hwptr << 2 : ch->hwptr << 1;
}
static struct pcmchan_caps *
aggrch_getcaps(kobj_t obj, void *sc)
{
-static u_int32_t recfmt[] = {
-AFMT_S16_LE,
-AFMT_STEREO | AFMT_S16_LE,
-0
-};
-static struct pcmchan_caps reccaps = {8000, 48000, recfmt, 0};
+ static u_int32_t recfmt[] = {
+ AFMT_S16_LE,
+ AFMT_STEREO | AFMT_S16_LE,
+ 0
+ };
+ static struct pcmchan_caps reccaps = {8000, 48000, recfmt, 0};
-return &reccaps;
+ return &reccaps;
}
static kobj_method_t aggrch_methods[] = {
-KOBJMETHOD(channel_init, aggrch_init),
-/* channel_free: no-op */
-KOBJMETHOD(channel_setformat, aggrch_setformat),
-KOBJMETHOD(channel_setspeed, aggrch_setspeed),
-KOBJMETHOD(channel_setblocksize, aggrch_setblocksize),
-KOBJMETHOD(channel_trigger, aggrch_trigger),
-KOBJMETHOD(channel_getptr, aggrch_getptr),
-KOBJMETHOD(channel_getcaps, aggrch_getcaps),
-{ 0, 0 }
+ KOBJMETHOD(channel_init, aggrch_init),
+ /* channel_free: no-op */
+ KOBJMETHOD(channel_setformat, aggrch_setformat),
+ KOBJMETHOD(channel_setspeed, aggrch_setspeed),
+ KOBJMETHOD(channel_setblocksize, aggrch_setblocksize),
+ KOBJMETHOD(channel_trigger, aggrch_trigger),
+ KOBJMETHOD(channel_getptr, aggrch_getptr),
+ KOBJMETHOD(channel_getcaps, aggrch_getcaps),
+ { 0, 0 }
};
CHANNEL_DECLARE(aggrch);
/* -----------------------------
-* Bus space.
-*/
+ * Bus space.
+ */
static void
agg_intr(void *sc)
{
-struct agg_info* ess = sc;
-register u_int8_t status;
-int i;
-u_int m;
-
-status = AGG_RD(ess, PORT_HOSTINT_STAT, 1);
-if (!status)
-return;
+ struct agg_info* ess = sc;
+ register u_int8_t status;
+ int i;
+ u_int m;
+
+ status = AGG_RD(ess, PORT_HOSTINT_STAT, 1);
+ if (!status)
+ return;
-/* Acknowledge intr. */
-AGG_WR(ess, PORT_HOSTINT_STAT, status, 1);
+ /* Acknowledge intr. */
+ AGG_WR(ess, PORT_HOSTINT_STAT, status, 1);
-if (status & HOSTINT_STAT_DSOUND) {
+ if (status & HOSTINT_STAT_DSOUND) {
#ifdef AGG_JITTER_CORRECTION
-agg_lock(ess);
+ agg_lock(ess);
#endif
-if (ess->curpwr <= PCI_POWERSTATE_D1) {
-AGG_WR(ess, PORT_INT_STAT, 1, 2);
+ if (ess->curpwr <= PCI_POWERSTATE_D1) {
+ AGG_WR(ess, PORT_INT_STAT, 1, 2);
#ifdef AGG_JITTER_CORRECTION
-for (i = 0, m = 1; i < ess->playchns; i++, m <<= 1) {
-if (ess->active & m)
-suppress_jitter(ess->pch + i);
-}
-if (ess->active & m)
-suppress_rec_jitter(&ess->rch);
-agg_unlock(ess);
-#endif
-for (i = 0, m = 1; i < ess->playchns; i++, m <<= 1) {
-if (ess->active & m) {
-if (ess->curpwr <= PCI_POWERSTATE_D1)
-chn_intr(ess->pch[i].channel);
-else {
-m = 0;
-break;
-}
-}
-}
-if ((ess->active & m)
-&& ess->curpwr <= PCI_POWERSTATE_D1)
-chn_intr(ess->rch.channel);
-}
+ for (i = 0, m = 1; i < ess->playchns; i++, m <<= 1) {
+ if (ess->active & m)
+ suppress_jitter(ess->pch + i);
+ }
+ if (ess->active & m)
+ suppress_rec_jitter(&ess->rch);
+ agg_unlock(ess);
+#endif
+ for (i = 0, m = 1; i < ess->playchns; i++, m <<= 1) {
+ if (ess->active & m) {
+ if (ess->curpwr <= PCI_POWERSTATE_D1)
+ chn_intr(ess->pch[i].channel);
+ else {
+ m = 0;
+ break;
+ }
+ }
+ }
+ if ((ess->active & m)
+ && ess->curpwr <= PCI_POWERSTATE_D1)
+ chn_intr(ess->rch.channel);
+ }
#ifdef AGG_JITTER_CORRECTION
-else
-agg_unlock(ess);
+ else
+ agg_unlock(ess);
#endif
-}
+ }
-if (status & HOSTINT_STAT_HWVOL) {
-register u_int8_t event;
+ if (status & HOSTINT_STAT_HWVOL) {
+ register u_int8_t event;
-agg_lock(ess);
-event = AGG_RD(ess, PORT_HWVOL_MASTER, 1);
-AGG_WR(ess, PORT_HWVOL_MASTER, HWVOL_NOP, 1);
-agg_unlock(ess);
-
-switch (event) {
-case HWVOL_UP:
-mixer_hwvol_step(ess->dev, 1, 1);
-break;
-case HWVOL_DOWN:
-mixer_hwvol_step(ess->dev, -1, -1);
-break;
-case HWVOL_NOP:
-break;
-default:
-if (event & HWVOL_MUTE) {
-mixer_hwvol_mute(ess->dev);
-break;
-}
-device_printf(ess->dev,
-"%s: unknown HWVOL event 0x%xn",
-device_get_nameunit(ess->dev), event);
-}
-}
+ agg_lock(ess);
+ event = AGG_RD(ess, PORT_HWVOL_MASTER, 1);
+ AGG_WR(ess, PORT_HWVOL_MASTER, HWVOL_NOP, 1);
+ agg_unlock(ess);
+
+ switch (event) {
+ case HWVOL_UP:
+ mixer_hwvol_step(ess->dev, 1, 1);
+ break;
+ case HWVOL_DOWN:
+ mixer_hwvol_step(ess->dev, -1, -1);
+ break;
+ case HWVOL_NOP:
+ break;
+ default:
+ if (event & HWVOL_MUTE) {
+ mixer_hwvol_mute(ess->dev);
+ break;
+ }
+ device_printf(ess->dev,
+ "%s: unknown HWVOL event 0x%x\n",
+ device_get_nameunit(ess->dev), event);
+ }
+ }
}
static void
setmap(void *arg, bus_dma_segment_t *segs, int nseg, int error)
{
-bus_addr_t *phys = arg;
+ bus_addr_t *phys = arg;
-*phys = error? 0 : segs->ds_addr;
+ *phys = error? 0 : segs->ds_addr;
-if (bootverbose) {
-printf("setmap (%lx, %lx), nseg=%d, error=%dn",
-(unsigned long)segs->ds_addr, (unsigned long)segs->ds_len,
-nseg, error);
-}
+ if (bootverbose) {
+ printf("setmap (%lx, %lx), nseg=%d, error=%d\n",
+ (unsigned long)segs->ds_addr, (unsigned long)segs->ds_len,
+ nseg, error);
+ }
}
static void *
dma_malloc(bus_dma_tag_t dmat, u_int32_t sz, bus_addr_t *phys)
{
-void *buf;
-bus_dmamap_t map;
+ void *buf;
+ bus_dmamap_t map;
-if (bus_dmamem_alloc(dmat, &buf, BUS_DMA_NOWAIT, &map))
-return NULL;
-if (bus_dmamap_load(dmat, map, buf, sz, setmap, phys, 0)
-|| !*phys || map) {
-bus_dmamem_free(dmat, buf, map);
-return NULL;
-}
-return buf;
+ if (bus_dmamem_alloc(dmat, &buf, BUS_DMA_NOWAIT, &map))
+ return NULL;
+ if (bus_dmamap_load(dmat, map, buf, sz, setmap, phys, 0)
+ || !*phys || map) {
+ bus_dmamem_free(dmat, buf, map);
+ return NULL;
+ }
+ return buf;
}
static void
dma_free(bus_dma_tag_t dmat, void *buf)
{
-bus_dmamem_free(dmat, buf, NULL);
+ bus_dmamem_free(dmat, buf, NULL);
}
static int
agg_probe(device_t dev)
{
-char *s = NULL;
+ char *s = NULL;
-switch (pci_get_devid(dev)) {
-case MAESTRO_1_PCI_ID:
-s = "ESS Technology Maestro-1";
-break;
-
-case MAESTRO_2_PCI_ID:
-s = "ESS Technology Maestro-2";
-break;
-
-case MAESTRO_2E_PCI_ID:
-s = "ESS Technology Maestro-2E";
-break;
-}
-
-if (s != NULL && pci_get_class(dev) == PCIC_MULTIMEDIA) {
-device_set_desc(dev, s);
-return BUS_PROBE_DEFAULT;
-}
-return ENXIO;
+ switch (pci_get_devid(dev)) {
+ case MAESTRO_1_PCI_ID:
+ s = "ESS Technology Maestro-1";
+ break;
+
+ case MAESTRO_2_PCI_ID:
+ s = "ESS Technology Maestro-2";
+ break;
+
+ case MAESTRO_2E_PCI_ID:
+ s = "ESS Technology Maestro-2E";
+ break;
+ }
+
+ if (s != NULL && pci_get_class(dev) == PCIC_MULTIMEDIA) {
+ device_set_desc(dev, s);
+ return BUS_PROBE_DEFAULT;
+ }
+ return ENXIO;
}
static int
agg_attach(device_t dev)
{
-struct agg_info *ess = NULL;
-u_int32_t data;
-int regid = PCIR_BAR(0);
-struct resource *reg = NULL;
-struct ac97_info *codec = NULL;
-int irqid = 0;
-struct resource *irq = NULL;
-void *ih = NULL;
-char status[SND_STATUSLEN];
-int ret = 0;
-
-if ((ess = malloc(sizeof *ess, M_DEVBUF, M_NOWAIT | M_ZERO)) == NULL) {
-device_printf(dev, "cannot allocate softcn");
-ret = ENOMEM;
-goto bad;
-}
-ess->dev = dev;
+ struct agg_info *ess = NULL;
+ u_int32_t data;
+ int regid = PCIR_BAR(0);
+ struct resource *reg = NULL;
+ struct ac97_info *codec = NULL;
+ int irqid = 0;
+ struct resource *irq = NULL;
+ void *ih = NULL;
+ char status[SND_STATUSLEN];
+ int dacn, ret = 0;
-#ifdef USING_MUTEX
-mtx_init(&ess->lock, device_get_desc(dev), "hardware status lock",
-MTX_DEF | MTX_RECURSE);
-if (!mtx_initialized(&ess->lock)) {
-device_printf(dev, "failed to create a mutex.n");
-ret = ENOMEM;
-goto bad;
-}
-#endif
+ ess = malloc(sizeof(*ess), M_DEVBUF, M_WAITOK | M_ZERO);
+ ess->dev = dev;
-ess->bufsz = pcm_getbuffersize(dev, 4096, AGG_DEFAULT_BUFSZ, 65536);
-if (bus_dma_tag_create(/*parent*/ NULL,
-/*align */ 4, 1 << (16+1),
-/*limit */ MAESTRO_MAXADDR, BUS_SPACE_MAXADDR,
-/*filter*/ NULL, NULL,
-/*size */ ess->bufsz, 1, 0x3ffff,
-/*flags */ 0,
+#ifdef USING_MUTEX
+ mtx_init(&ess->lock, device_get_desc(dev), "snd_maestro softc",
+ MTX_DEF | MTX_RECURSE);
+ if (!mtx_initialized(&ess->lock)) {
+ device_printf(dev, "failed to create a mutex.\n");
+ ret = ENOMEM;
+ goto bad;
+ }
+#endif
+
+ if (resource_int_value(device_get_name(dev), device_get_unit(dev),
+ "dac", &dacn) == 0) {
+ if (dacn < 1)
+ dacn = 1;
+ else if (dacn > AGG_MAXPLAYCH)
+ dacn = AGG_MAXPLAYCH;
+ } else
+ dacn = AGG_MAXPLAYCH;
+
+ ess->bufsz = pcm_getbuffersize(dev, 4096, AGG_DEFAULT_BUFSZ, 65536);
+ if (bus_dma_tag_create(/*parent*/ bus_get_dma_tag(dev),
+ /*align */ 4, 1 << (16+1),
+ /*limit */ MAESTRO_MAXADDR, BUS_SPACE_MAXADDR,
+ /*filter*/ NULL, NULL,
+ /*size */ ess->bufsz, 1, 0x3ffff,
+ /*flags */ 0,
#if __FreeBSD_version >= 501102
-/*lock */ busdma_lock_mutex, &Giant,
+ /*lock */ busdma_lock_mutex, &Giant,
#endif
-&ess->buf_dmat) != 0) {
-device_printf(dev, "unable to create dma tagn");
-ret = ENOMEM;
-goto bad;
-}
-
-if (bus_dma_tag_create(/*parent*/NULL,
-/*align */ 1 << WAVCACHE_BASEADDR_SHIFT,
-1 << (16+1),
-/*limit */ MAESTRO_MAXADDR, BUS_SPACE_MAXADDR,
-/*filter*/ NULL, NULL,
-/*size */ 3*ess->bufsz, 1, 0x3ffff,
-/*flags */ 0,
+ &ess->buf_dmat) != 0) {
+ device_printf(dev, "unable to create dma tag\n");
+ ret = ENOMEM;
+ goto bad;
+ }
+
+ if (bus_dma_tag_create(/*parent*/ bus_get_dma_tag(dev),
+ /*align */ 1 << WAVCACHE_BASEADDR_SHIFT,
+ 1 << (16+1),
+ /*limit */ MAESTRO_MAXADDR, BUS_SPACE_MAXADDR,
+ /*filter*/ NULL, NULL,
+ /*size */ 3*ess->bufsz, 1, 0x3ffff,
+ /*flags */ 0,
#if __FreeBSD_version >= 501102
-/*lock */ busdma_lock_mutex, &Giant,
+ /*lock */ busdma_lock_mutex, &Giant,
#endif
-&ess->stat_dmat) != 0) {
-device_printf(dev, "unable to create dma tagn");
-ret = ENOMEM;
-goto bad;
-}
-
-/* Allocate the room for brain-damaging status buffer. */
-ess->stat = dma_malloc(ess->stat_dmat, 3*ess->bufsz, &ess->phys);
-if (ess->stat == NULL) {
-device_printf(dev, "cannot allocate status buffern");
-ret = ENOMEM;
-goto bad;
-}
-if (bootverbose)
-device_printf(dev, "Maestro status/record buffer: %#llxn",
-(long long)ess->phys);
-
-/* State D0-uninitialized. */
-ess->curpwr = PCI_POWERSTATE_D3;
-pci_set_powerstate(dev, PCI_POWERSTATE_D0);
-
-data = pci_read_config(dev, PCIR_COMMAND, 2);
-data |= (PCIM_CMD_PORTEN|PCIM_CMD_BUSMASTEREN);
-pci_write_config(dev, PCIR_COMMAND, data, 2);
-data = pci_read_config(dev, PCIR_COMMAND, 2);
-
-/* Allocate resources. */
-if (data & PCIM_CMD_PORTEN)
-reg = bus_alloc_resource_any(dev, SYS_RES_IOPORT, ®id,
-RF_ACTIVE);
-if (reg != NULL) {
-ess->reg = reg;
-ess->regid = regid;
-ess->st = rman_get_bustag(reg);
-ess->sh = rman_get_bushandle(reg);
-} else {
-device_printf(dev, "unable to map register spacen");
-ret = ENXIO;
-goto bad;
-}
-irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &irqid,
-RF_ACTIVE | RF_SHAREABLE);
-if (irq != NULL) {
-ess->irq = irq;
-ess->irqid = irqid;
-} else {
-device_printf(dev, "unable to map interruptn");
-ret = ENXIO;
-goto bad;
-}
-
-/* Setup resources. */
-if (snd_setup_intr(dev, irq, INTR_MPSAFE, agg_intr, ess, &ih)) {
-device_printf(dev, "unable to setup interruptn");
-ret = ENXIO;
-goto bad;
-} else
-ess->ih = ih;
-
-/* Transition from D0-uninitialized to D0. */
-agg_lock(ess);
-agg_power(ess, PCI_POWERSTATE_D0);
-if (agg_rdcodec(ess, 0) == 0x80) {
-/* XXX - TODO: PT101 */
-agg_unlock(ess);
-device_printf(dev, "PT101 codec detected!n");
-ret = ENXIO;
-goto bad;
-}
-agg_unlock(ess);
-codec = AC97_CREATE(dev, ess, agg_ac97);
-if (codec == NULL) {
-device_printf(dev, "failed to create AC97 codec softc!n");
-ret = ENOMEM;
-goto bad;
-}
-if (mixer_init(dev, ac97_getmixerclass(), codec) == -1) {
-device_printf(dev, "mixer initialization failed!n");
-ret = ENXIO;
-goto bad;
-}
-ess->codec = codec;
-
-ret = pcm_register(dev, ess, AGG_MAXPLAYCH, 1);
-if (ret)
-goto bad;
-
-mixer_hwvol_init(dev);
-agg_lock(ess);
-agg_power(ess, powerstate_init);
-agg_unlock(ess);
-for (data = 0; data < AGG_MAXPLAYCH; data++)
-pcm_addchan(dev, PCMDIR_PLAY, &aggpch_class, ess);
-pcm_addchan(dev, PCMDIR_REC, &aggrch_class, ess);
-adjust_pchbase(ess->pch, ess->playchns, ess->bufsz);
-
-snprintf(status, SND_STATUSLEN,
-"port 0x%lx-0x%lx irq %ld at device %d.%d on pci%d",
-rman_get_start(reg), rman_get_end(reg), rman_get_start(irq),
-pci_get_slot(dev), pci_get_function(dev), pci_get_bus(dev));
-pcm_setstatus(dev, status);
-
-return 0;
-
-bad:
-if (codec != NULL)
-ac97_destroy(codec);
-if (ih != NULL)
-bus_teardown_intr(dev, irq, ih);
-if (irq != NULL)
-bus_release_resource(dev, SYS_RES_IRQ, irqid, irq);
-if (reg != NULL)
-bus_release_resource(dev, SYS_RES_IOPORT, regid, reg);
-if (ess != NULL) {
-if (ess->stat != NULL)
-dma_free(ess->stat_dmat, ess->stat);
-if (ess->stat_dmat != NULL)
-bus_dma_tag_destroy(ess->stat_dmat);
-if (ess->buf_dmat != NULL)
-bus_dma_tag_destroy(ess->buf_dmat);
+ &ess->stat_dmat) != 0) {
+ device_printf(dev, "unable to create dma tag\n");
+ ret = ENOMEM;
+ goto bad;
+ }
+
+ /* Allocate the room for brain-damaging status buffer. */
+ ess->stat = dma_malloc(ess->stat_dmat, 3*ess->bufsz, &ess->phys);
+ if (ess->stat == NULL) {
+ device_printf(dev, "cannot allocate status buffer\n");
+ ret = ENOMEM;
+ goto bad;
+ }
+ if (bootverbose)
+ device_printf(dev, "Maestro status/record buffer: %#llx\n",
+ (long long)ess->phys);
+
+ /* State D0-uninitialized. */
+ ess->curpwr = PCI_POWERSTATE_D3;
+ pci_set_powerstate(dev, PCI_POWERSTATE_D0);
+
+ data = pci_read_config(dev, PCIR_COMMAND, 2);
+ data |= (PCIM_CMD_PORTEN|PCIM_CMD_BUSMASTEREN);
+ pci_write_config(dev, PCIR_COMMAND, data, 2);
+ data = pci_read_config(dev, PCIR_COMMAND, 2);
+
+ /* Allocate resources. */
+ if (data & PCIM_CMD_PORTEN)
+ reg = bus_alloc_resource_any(dev, SYS_RES_IOPORT, ®id,
+ RF_ACTIVE);
+ if (reg != NULL) {
+ ess->reg = reg;
+ ess->regid = regid;
+ ess->st = rman_get_bustag(reg);
+ ess->sh = rman_get_bushandle(reg);
+ } else {
+ device_printf(dev, "unable to map register space\n");
+ ret = ENXIO;
+ goto bad;
+ }
+ irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &irqid,
+ RF_ACTIVE | RF_SHAREABLE);
+ if (irq != NULL) {
+ ess->irq = irq;
+ ess->irqid = irqid;
+ } else {
+ device_printf(dev, "unable to map interrupt\n");
+ ret = ENXIO;
+ goto bad;
+ }
+
+ /* Setup resources. */
+ if (snd_setup_intr(dev, irq, INTR_MPSAFE, agg_intr, ess, &ih)) {
+ device_printf(dev, "unable to setup interrupt\n");
+ ret = ENXIO;
+ goto bad;
+ } else
+ ess->ih = ih;
+
+ /* Transition from D0-uninitialized to D0. */
+ agg_lock(ess);
+ agg_power(ess, PCI_POWERSTATE_D0);
+ if (agg_rdcodec(ess, 0) == 0x80) {
+ /* XXX - TODO: PT101 */
+ agg_unlock(ess);
+ device_printf(dev, "PT101 codec detected!\n");
+ ret = ENXIO;
+ goto bad;
+ }
+ agg_unlock(ess);
+ codec = AC97_CREATE(dev, ess, agg_ac97);
+ if (codec == NULL) {
+ device_printf(dev, "failed to create AC97 codec softc!\n");
+ ret = ENOMEM;
+ goto bad;
+ }
+ if (mixer_init(dev, ac97_getmixerclass(), codec) == -1) {
+ device_printf(dev, "mixer initialization failed!\n");
+ ret = ENXIO;
+ goto bad;
+ }
+ ess->codec = codec;
+
+ ret = pcm_register(dev, ess, dacn, 1);
+ if (ret)
+ goto bad;
+
+ mixer_hwvol_init(dev);
+ agg_lock(ess);
+ agg_power(ess, powerstate_init);
+ agg_unlock(ess);
+ for (data = 0; data < dacn; data++)
+ pcm_addchan(dev, PCMDIR_PLAY, &aggpch_class, ess);
+ pcm_addchan(dev, PCMDIR_REC, &aggrch_class, ess);
+ adjust_pchbase(ess->pch, ess->playchns, ess->bufsz);
+
+ snprintf(status, SND_STATUSLEN,
+ "port 0x%lx-0x%lx irq %ld at device %d.%d on pci%d",
+ rman_get_start(reg), rman_get_end(reg), rman_get_start(irq),
+ pci_get_slot(dev), pci_get_function(dev), pci_get_bus(dev));
+ pcm_setstatus(dev, status);
+
+ return 0;
+
+ bad:
+ if (codec != NULL)
+ ac97_destroy(codec);
+ if (ih != NULL)
+ bus_teardown_intr(dev, irq, ih);
+ if (irq != NULL)
+ bus_release_resource(dev, SYS_RES_IRQ, irqid, irq);
+ if (reg != NULL)
+ bus_release_resource(dev, SYS_RES_IOPORT, regid, reg);
+ if (ess != NULL) {
+ if (ess->stat != NULL)
+ dma_free(ess->stat_dmat, ess->stat);
+ if (ess->stat_dmat != NULL)
+ bus_dma_tag_destroy(ess->stat_dmat);
+ if (ess->buf_dmat != NULL)
+ bus_dma_tag_destroy(ess->buf_dmat);
#ifdef USING_MUTEX
-if (mtx_initialized(&ess->lock))
-mtx_destroy(&ess->lock);
+ if (mtx_initialized(&ess->lock))
+ mtx_destroy(&ess->lock);
#endif
-free(ess, M_DEVBUF);
-}
+ free(ess, M_DEVBUF);
+ }
-return ret;
+ return ret;
}
static int
agg_detach(device_t dev)
{
-struct agg_info *ess = pcm_getdevinfo(dev);
-int r;
-u_int16_t icr;
-
-icr = AGG_RD(ess, PORT_HOSTINT_CTRL, 2);
-AGG_WR(ess, PORT_HOSTINT_CTRL, 0, 2);
-
-agg_lock(ess);
-if (ess->active) {
-AGG_WR(ess, PORT_HOSTINT_CTRL, icr, 2);
-agg_unlock(ess);
-return EBUSY;
-}
-agg_unlock(ess);
-
-r = pcm_unregister(dev);
-if (r) {
-AGG_WR(ess, PORT_HOSTINT_CTRL, icr, 2);
-return r;
-}
-
-agg_lock(ess);
-agg_power(ess, PCI_POWERSTATE_D3);
-agg_unlock(ess);
-
-bus_teardown_intr(dev, ess->irq, ess->ih);
-bus_release_resource(dev, SYS_RES_IRQ, ess->irqid, ess->irq);
-bus_release_resource(dev, SYS_RES_IOPORT, ess->regid, ess->reg);
-dma_free(ess->stat_dmat, ess->stat);
-bus_dma_tag_destroy(ess->stat_dmat);
-bus_dma_tag_destroy(ess->buf_dmat);
+ struct agg_info *ess = pcm_getdevinfo(dev);
+ int r;
+ u_int16_t icr;
+
+ icr = AGG_RD(ess, PORT_HOSTINT_CTRL, 2);
+ AGG_WR(ess, PORT_HOSTINT_CTRL, 0, 2);
+
+ agg_lock(ess);
+ if (ess->active) {
+ AGG_WR(ess, PORT_HOSTINT_CTRL, icr, 2);
+ agg_unlock(ess);
+ return EBUSY;
+ }
+ agg_unlock(ess);
+
+ r = pcm_unregister(dev);
+ if (r) {
+ AGG_WR(ess, PORT_HOSTINT_CTRL, icr, 2);
+ return r;
+ }
+
+ agg_lock(ess);
+ agg_power(ess, PCI_POWERSTATE_D3);
+ agg_unlock(ess);
+
+ bus_teardown_intr(dev, ess->irq, ess->ih);
+ bus_release_resource(dev, SYS_RES_IRQ, ess->irqid, ess->irq);
+ bus_release_resource(dev, SYS_RES_IOPORT, ess->regid, ess->reg);
+ dma_free(ess->stat_dmat, ess->stat);
+ bus_dma_tag_destroy(ess->stat_dmat);
+ bus_dma_tag_destroy(ess->buf_dmat);
#ifdef USING_MUTEX
-mtx_destroy(&ess->lock);
+ mtx_destroy(&ess->lock);
#endif
-free(ess, M_DEVBUF);
-return 0;
+ free(ess, M_DEVBUF);
+ return 0;
}
static int
agg_suspend(device_t dev)
{
-struct agg_info *ess = pcm_getdevinfo(dev);
+ struct agg_info *ess = pcm_getdevinfo(dev);
#ifndef USING_MUTEX
-int x;
+ int x;
-x = spltty();
+ x = spltty();
#endif
-AGG_WR(ess, PORT_HOSTINT_CTRL, 0, 2);
-agg_lock(ess);
-agg_power(ess, PCI_POWERSTATE_D3);
-agg_unlock(ess);
+ AGG_WR(ess, PORT_HOSTINT_CTRL, 0, 2);
+ agg_lock(ess);
+ agg_power(ess, PCI_POWERSTATE_D3);
+ agg_unlock(ess);
#ifndef USING_MUTEX
-splx(x);
+ splx(x);
#endif
-return 0;
+ return 0;
}
static int
agg_resume(device_t dev)
{
-int i;
-struct agg_info *ess = pcm_getdevinfo(dev);
+ int i;
+ struct agg_info *ess = pcm_getdevinfo(dev);
#ifndef USING_MUTEX
-int x;
+ int x;
-x = spltty();
+ x = spltty();
#endif
-for (i = 0; i < ess->playchns; i++)
-if (ess->active & (1 << i))
-aggch_start_dac(ess->pch + i);
-if (ess->active & (1 << i))
-aggch_start_adc(&ess->rch);
-
-agg_lock(ess);
-if (!ess->active)
-agg_power(ess, powerstate_init);
-agg_unlock(ess);
+ for (i = 0; i < ess->playchns; i++)
+ if (ess->active & (1 << i))
+ aggch_start_dac(ess->pch + i);
+ if (ess->active & (1 << i))
+ aggch_start_adc(&ess->rch);
+
+ agg_lock(ess);
+ if (!ess->active)
+ agg_power(ess, powerstate_init);
+ agg_unlock(ess);
#ifndef USING_MUTEX
-splx(x);
+ splx(x);
#endif
-if (mixer_reinit(dev)) {
-device_printf(dev, "unable to reinitialize the mixern");
-return ENXIO;
-}
+ if (mixer_reinit(dev)) {
+ device_printf(dev, "unable to reinitialize the mixer\n");
+ return ENXIO;
+ }
-return 0;
+ return 0;
}
static int
agg_shutdown(device_t dev)
{
-struct agg_info *ess = pcm_getdevinfo(dev);
+ struct agg_info *ess = pcm_getdevinfo(dev);
-agg_lock(ess);
-agg_power(ess, PCI_POWERSTATE_D3);
-agg_unlock(ess);
+ agg_lock(ess);
+ agg_power(ess, PCI_POWERSTATE_D3);
+ agg_unlock(ess);
-return 0;
+ return 0;
}
static device_method_t agg_methods[] = {
-DEVMETHOD(device_probe, agg_probe),
-DEVMETHOD(device_attach, agg_attach),
-DEVMETHOD(device_detach, agg_detach),
-DEVMETHOD(device_suspend, agg_suspend),
-DEVMETHOD(device_resume, agg_resume),
-DEVMETHOD(device_shutdown, agg_shutdown),
+ DEVMETHOD(device_probe, agg_probe),
+ DEVMETHOD(device_attach, agg_attach),
+ DEVMETHOD(device_detach, agg_detach),
+ DEVMETHOD(device_suspend, agg_suspend),
+ DEVMETHOD(device_resume, agg_resume),
+ DEVMETHOD(device_shutdown, agg_shutdown),
-{ 0, 0 }
+ { 0, 0 }
};
static driver_t agg_driver = {
-"pcm",
-agg_methods,
-PCM_SOFTC_SIZE,
+ "pcm",
+ agg_methods,
+ PCM_SOFTC_SIZE,
};
/*static devclass_t pcm_devclass;*/
Index: csa.c
===================================================================
RCS file: /home/cvs/src/sys/dev/sound/pci/csa.c,v
retrieving revision 1.2
retrieving revision 1.3
diff -L sys/dev/sound/pci/csa.c -L sys/dev/sound/pci/csa.c -u -r1.2 -r1.3
--- sys/dev/sound/pci/csa.c
+++ sys/dev/sound/pci/csa.c
@@ -1,32 +1,32 @@
/*-
-* Copyright (c) 1999 Seigo Tanimura
-* All rights reserved.
-*
-* Portions of this source are based on cwcealdr.cpp and dhwiface.cpp in
-* cwcealdr1.zip, the sample sources by Crystal Semiconductor.
-* Copyright (c) 1996-1998 Crystal Semiconductor Corp.
-*
-* Redistribution and use in source and binary forms, with or without
-* modification, are permitted provided that the following conditions
-* are met:
-* 1. Redistributions of source code must retain the above copyright
-* notice, this list of conditions and the following disclaimer.
-* 2. Redistributions in binary form must reproduce the above copyright
-* notice, this list of conditions and the following disclaimer in the
-* documentation and/or other materials provided with the distribution.
-*
-* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
-* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
-* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
-* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
-* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
-* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
-* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
-* SUCH DAMAGE.
-*/
+ * Copyright (c) 1999 Seigo Tanimura
+ * All rights reserved.
+ *
+ * Portions of this source are based on cwcealdr.cpp and dhwiface.cpp in
+ * cwcealdr1.zip, the sample sources by Crystal Semiconductor.
+ * Copyright (c) 1996-1998 Crystal Semiconductor Corp.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
#include <sys/param.h>
#include <sys/systm.h>
@@ -48,7 +48,7 @@
#include <gnu/dev/sound/pci/csaimg.h>
-SND_DECLARE_FILE("$MidnightBSD$");
+SND_DECLARE_FILE("$FreeBSD: src/sys/dev/sound/pci/csa.c,v 1.37 2007/03/17 19:37:09 ariff Exp $");
/* This is the pci device id. */
#define CS4610_PCI_ID 0x60011013
@@ -57,19 +57,19 @@
/* Here is the parameter structure per a device. */
struct csa_softc {
-device_t dev; /* device */
-csa_res res; /* resources */
+ device_t dev; /* device */
+ csa_res res; /* resources */
-device_t pcm; /* pcm device */
-driver_intr_t* pcmintr; /* pcm intr */
-void *pcmintr_arg; /* pcm intr arg */
-device_t midi; /* midi device */
-driver_intr_t* midiintr; /* midi intr */
-void *midiintr_arg; /* midi intr arg */
-void *ih; /* cookie */
+ device_t pcm; /* pcm device */
+ driver_intr_t* pcmintr; /* pcm intr */
+ void *pcmintr_arg; /* pcm intr arg */
+ device_t midi; /* midi device */
+ driver_intr_t* midiintr; /* midi intr */
+ void *midiintr_arg; /* midi intr arg */
+ void *ih; /* cookie */
-struct csa_card *card;
-struct csa_bridgeinfo binfo; /* The state of this bridge. */
+ struct csa_card *card;
+ struct csa_bridgeinfo binfo; /* The state of this bridge. */
};
typedef struct csa_softc *sc_p;
@@ -77,14 +77,17 @@
static int csa_probe(device_t dev);
static int csa_attach(device_t dev);
static struct resource *csa_alloc_resource(device_t bus, device_t child, int type, int *rid,
-u_long start, u_long end, u_long count, u_int flags);
+ u_long start, u_long end, u_long count, u_int flags);
static int csa_release_resource(device_t bus, device_t child, int type, int rid,
-struct resource *r);
+ struct resource *r);
static int csa_setup_intr(device_t bus, device_t child,
-struct resource *irq, int flags,
-driver_intr_t *intr, void *arg, void **cookiep);
+ struct resource *irq, int flags,
+#if __FreeBSD_version >= 700031
+ driver_filter_t *filter,
+#endif
+ driver_intr_t *intr, void *arg, void **cookiep);
static int csa_teardown_intr(device_t bus, device_t child,
-struct resource *irq, void *cookie);
+ struct resource *irq, void *cookie);
static driver_intr_t csa_intr;
static int csa_initialize(sc_p scp);
static int csa_downloadimage(csa_res *resp);
@@ -105,972 +108,989 @@
clkrun_hack(int run)
{
#ifdef __i386__
-devclass_t pci_devclass;
-device_t *pci_devices, *pci_children, *busp, *childp;
-int pci_count = 0, pci_childcount = 0;
-int i, j, port;
-u_int16_t control;
-bus_space_tag_t btag;
-
-if ((pci_devclass = devclass_find("pci")) == NULL) {
-return ENXIO;
-}
-
-devclass_get_devices(pci_devclass, &pci_devices, &pci_count);
-
-for (i = 0, busp = pci_devices; i < pci_count; i++, busp++) {
-pci_childcount = 0;
-device_get_children(*busp, &pci_children, &pci_childcount);
-for (j = 0, childp = pci_children; j < pci_childcount; j++, childp++) {
-if (pci_get_vendor(*childp) == 0x8086 && pci_get_device(*childp) == 0x7113) {
-port = (pci_read_config(*childp, 0x41, 1) << 8) + 0x10;
-/* XXX */
-btag = I386_BUS_SPACE_IO;
-
-control = bus_space_read_2(btag, 0x0, port);
-control &= ~0x2000;
-control |= run? 0 : 0x2000;
-bus_space_write_2(btag, 0x0, port, control);
-free(pci_devices, M_TEMP);
-free(pci_children, M_TEMP);
-return 0;
-}
-}
-free(pci_children, M_TEMP);
-}
+ devclass_t pci_devclass;
+ device_t *pci_devices, *pci_children, *busp, *childp;
+ int pci_count = 0, pci_childcount = 0;
+ int i, j, port;
+ u_int16_t control;
+ bus_space_tag_t btag;
+
+ if ((pci_devclass = devclass_find("pci")) == NULL) {
+ return ENXIO;
+ }
+
+ devclass_get_devices(pci_devclass, &pci_devices, &pci_count);
+
+ for (i = 0, busp = pci_devices; i < pci_count; i++, busp++) {
+ pci_childcount = 0;
+ device_get_children(*busp, &pci_children, &pci_childcount);
+ for (j = 0, childp = pci_children; j < pci_childcount; j++, childp++) {
+ if (pci_get_vendor(*childp) == 0x8086 && pci_get_device(*childp) == 0x7113) {
+ port = (pci_read_config(*childp, 0x41, 1) << 8) + 0x10;
+ /* XXX */
+ btag = I386_BUS_SPACE_IO;
+
+ control = bus_space_read_2(btag, 0x0, port);
+ control &= ~0x2000;
+ control |= run? 0 : 0x2000;
+ bus_space_write_2(btag, 0x0, port, control);
+ free(pci_devices, M_TEMP);
+ free(pci_children, M_TEMP);
+ return 0;
+ }
+ }
+ free(pci_children, M_TEMP);
+ }
-free(pci_devices, M_TEMP);
-return ENXIO;
+ free(pci_devices, M_TEMP);
+ return ENXIO;
#else
-return 0;
+ return 0;
#endif
}
static struct csa_card cards_4610[] = {
-{0, 0, "Unknown/invalid SSID (CS4610)", NULL, NULL, NULL, 0},
+ {0, 0, "Unknown/invalid SSID (CS4610)", NULL, NULL, NULL, 0},
};
static struct csa_card cards_4614[] = {
-{0x1489, 0x7001, "Genius Soundmaker 128 value", amp_none, NULL, NULL, 0},
-{0x5053, 0x3357, "Turtle Beach Santa Cruz", amp_voyetra, NULL, NULL, 1},
-{0x1071, 0x6003, "Mitac MI6020/21", amp_voyetra, NULL, NULL, 0},
-{0x14AF, 0x0050, "Hercules Game Theatre XP", NULL, NULL, NULL, 0},
-{0x1681, 0x0050, "Hercules Game Theatre XP", NULL, NULL, NULL, 0},
-{0x1014, 0x0132, "Thinkpad 570", amp_none, NULL, NULL, 0},
-{0x1014, 0x0153, "Thinkpad 600X/A20/T20", amp_none, NULL, clkrun_hack, 0},
-{0x1014, 0x1010, "Thinkpad 600E (unsupported)", NULL, NULL, NULL, 0},
-{0, 0, "Unknown/invalid SSID (CS4614)", NULL, NULL, NULL, 0},
+ {0x1489, 0x7001, "Genius Soundmaker 128 value", amp_none, NULL, NULL, 0},
+ {0x5053, 0x3357, "Turtle Beach Santa Cruz", amp_voyetra, NULL, NULL, 1},
+ {0x1071, 0x6003, "Mitac MI6020/21", amp_voyetra, NULL, NULL, 0},
+ {0x14AF, 0x0050, "Hercules Game Theatre XP", NULL, NULL, NULL, 0},
+ {0x1681, 0x0050, "Hercules Game Theatre XP", NULL, NULL, NULL, 0},
+ {0x1014, 0x0132, "Thinkpad 570", amp_none, NULL, NULL, 0},
+ {0x1014, 0x0153, "Thinkpad 600X/A20/T20", amp_none, NULL, clkrun_hack, 0},
+ {0x1014, 0x1010, "Thinkpad 600E (unsupported)", NULL, NULL, NULL, 0},
+ {0, 0, "Unknown/invalid SSID (CS4614)", NULL, NULL, NULL, 0},
};
static struct csa_card cards_4615[] = {
-{0, 0, "Unknown/invalid SSID (CS4615)", NULL, NULL, NULL, 0},
+ {0, 0, "Unknown/invalid SSID (CS4615)", NULL, NULL, NULL, 0},
};
static struct csa_card nocard = {0, 0, "unknown", NULL, NULL, NULL, 0};
struct card_type {
-u_int32_t devid;
-char *name;
-struct csa_card *cards;
+ u_int32_t devid;
+ char *name;
+ struct csa_card *cards;
};
static struct card_type cards[] = {
-{CS4610_PCI_ID, "CS4610/CS4611", cards_4610},
-{CS4614_PCI_ID, "CS4280/CS4614/CS4622/CS4624/CS4630", cards_4614},
-{CS4615_PCI_ID, "CS4615", cards_4615},
-{0, NULL, NULL},
+ {CS4610_PCI_ID, "CS4610/CS4611", cards_4610},
+ {CS4614_PCI_ID, "CS4280/CS4614/CS4622/CS4624/CS4630", cards_4614},
+ {CS4615_PCI_ID, "CS4615", cards_4615},
+ {0, NULL, NULL},
};
static struct card_type *
csa_findcard(device_t dev)
{
-int i;
+ int i;
-i = 0;
-while (cards[i].devid != 0) {
-if (pci_get_devid(dev) == cards[i].devid)
-return &cards[i];
-i++;
-}
-return NULL;
+ i = 0;
+ while (cards[i].devid != 0) {
+ if (pci_get_devid(dev) == cards[i].devid)
+ return &cards[i];
+ i++;
+ }
+ return NULL;
}
struct csa_card *
csa_findsubcard(device_t dev)
{
-int i;
-struct card_type *card;
-struct csa_card *subcard;
-
-card = csa_findcard(dev);
-if (card == NULL)
-return &nocard;
-subcard = card->cards;
-i = 0;
-while (subcard[i].subvendor != 0) {
-if (pci_get_subvendor(dev) == subcard[i].subvendor
-&& pci_get_subdevice(dev) == subcard[i].subdevice) {
-return &subcard[i];
-}
-i++;
-}
-return &subcard[i];
+ int i;
+ struct card_type *card;
+ struct csa_card *subcard;
+
+ card = csa_findcard(dev);
+ if (card == NULL)
+ return &nocard;
+ subcard = card->cards;
+ i = 0;
+ while (subcard[i].subvendor != 0) {
+ if (pci_get_subvendor(dev) == subcard[i].subvendor
+ && pci_get_subdevice(dev) == subcard[i].subdevice) {
+ return &subcard[i];
+ }
+ i++;
+ }
+ return &subcard[i];
}
static int
csa_probe(device_t dev)
{
-struct card_type *card;
+ struct card_type *card;
-card = csa_findcard(dev);
-if (card) {
-device_set_desc(dev, card->name);
-return BUS_PROBE_DEFAULT;
-}
-return ENXIO;
+ card = csa_findcard(dev);
+ if (card) {
+ device_set_desc(dev, card->name);
+ return BUS_PROBE_DEFAULT;
+ }
+ return ENXIO;
}
static int
csa_attach(device_t dev)
{
-u_int32_t stcmd;
-sc_p scp;
-csa_res *resp;
-struct sndcard_func *func;
-int error = ENXIO;
-
-scp = device_get_softc(dev);
-
-/* Fill in the softc. */
-bzero(scp, sizeof(*scp));
-scp->dev = dev;
-
-/* Wake up the device. */
-stcmd = pci_read_config(dev, PCIR_COMMAND, 2);
-if ((stcmd & PCIM_CMD_MEMEN) == 0 || (stcmd & PCIM_CMD_BUSMASTEREN) == 0) {
-stcmd |= (PCIM_CMD_MEMEN | PCIM_CMD_BUSMASTEREN);
-pci_write_config(dev, PCIR_COMMAND, stcmd, 2);
-}
-
-/* Allocate the resources. */
-resp = &scp->res;
-scp->card = csa_findsubcard(dev);
-scp->binfo.card = scp->card;
-printf("csa: card is %sn", scp->card->name);
-resp->io_rid = PCIR_BAR(0);
-resp->io = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
-&resp->io_rid, RF_ACTIVE);
-if (resp->io == NULL)
-return (ENXIO);
-resp->mem_rid = PCIR_BAR(1);
-resp->mem = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
-&resp->mem_rid, RF_ACTIVE);
-if (resp->mem == NULL)
-goto err_io;
-resp->irq_rid = 0;
-resp->irq = bus_alloc_resource_any(dev, SYS_RES_IRQ,
-&resp->irq_rid, RF_ACTIVE | RF_SHAREABLE);
-if (resp->irq == NULL)
-goto err_mem;
-
-/* Enable interrupt. */
-if (snd_setup_intr(dev, resp->irq, 0, csa_intr, scp, &scp->ih))
-goto err_intr;
+ u_int32_t stcmd;
+ sc_p scp;
+ csa_res *resp;
+ struct sndcard_func *func;
+ int error = ENXIO;
+
+ scp = device_get_softc(dev);
+
+ /* Fill in the softc. */
+ bzero(scp, sizeof(*scp));
+ scp->dev = dev;
+
+ /* Wake up the device. */
+ stcmd = pci_read_config(dev, PCIR_COMMAND, 2);
+ if ((stcmd & PCIM_CMD_MEMEN) == 0 || (stcmd & PCIM_CMD_BUSMASTEREN) == 0) {
+ stcmd |= (PCIM_CMD_MEMEN | PCIM_CMD_BUSMASTEREN);
+ pci_write_config(dev, PCIR_COMMAND, stcmd, 2);
+ }
+
+ /* Allocate the resources. */
+ resp = &scp->res;
+ scp->card = csa_findsubcard(dev);
+ scp->binfo.card = scp->card;
+ printf("csa: card is %s\n", scp->card->name);
+ resp->io_rid = PCIR_BAR(0);
+ resp->io = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
+ &resp->io_rid, RF_ACTIVE);
+ if (resp->io == NULL)
+ return (ENXIO);
+ resp->mem_rid = PCIR_BAR(1);
+ resp->mem = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
+ &resp->mem_rid, RF_ACTIVE);
+ if (resp->mem == NULL)
+ goto err_io;
+ resp->irq_rid = 0;
+ resp->irq = bus_alloc_resource_any(dev, SYS_RES_IRQ,
+ &resp->irq_rid, RF_ACTIVE | RF_SHAREABLE);
+ if (resp->irq == NULL)
+ goto err_mem;
+
+ /* Enable interrupt. */
+ if (snd_setup_intr(dev, resp->irq, 0, csa_intr, scp, &scp->ih))
+ goto err_intr;
#if 0
-if ((csa_readio(resp, BA0_HISR) & HISR_INTENA) == 0)
-csa_writeio(resp, BA0_HICR, HICR_IEV | HICR_CHGM);
+ if ((csa_readio(resp, BA0_HISR) & HISR_INTENA) == 0)
+ csa_writeio(resp, BA0_HICR, HICR_IEV | HICR_CHGM);
#endif
-/* Initialize the chip. */
-if (csa_initialize(scp))
-goto err_teardown;
-
-/* Reset the Processor. */
-csa_resetdsp(resp);
-
-/* Download the Processor Image to the processor. */
-if (csa_downloadimage(resp))
-goto err_teardown;
-
-/* Attach the children. */
-
-/* PCM Audio */
-func = malloc(sizeof(struct sndcard_func), M_DEVBUF, M_NOWAIT | M_ZERO);
-if (func == NULL) {
-error = ENOMEM;
-goto err_teardown;
-}
-func->varinfo = &scp->binfo;
-func->func = SCF_PCM;
-scp->pcm = device_add_child(dev, "pcm", -1);
-device_set_ivars(scp->pcm, func);
-
-/* Midi Interface */
-func = malloc(sizeof(struct sndcard_func), M_DEVBUF, M_NOWAIT | M_ZERO);
-if (func == NULL) {
-error = ENOMEM;
-goto err_teardown;
-}
-func->varinfo = &scp->binfo;
-func->func = SCF_MIDI;
-scp->midi = device_add_child(dev, "midi", -1);
-device_set_ivars(scp->midi, func);
+ /* Initialize the chip. */
+ if (csa_initialize(scp))
+ goto err_teardown;
+
+ /* Reset the Processor. */
+ csa_resetdsp(resp);
+
+ /* Download the Processor Image to the processor. */
+ if (csa_downloadimage(resp))
+ goto err_teardown;
+
+ /* Attach the children. */
+
+ /* PCM Audio */
+ func = malloc(sizeof(struct sndcard_func), M_DEVBUF, M_NOWAIT | M_ZERO);
+ if (func == NULL) {
+ error = ENOMEM;
+ goto err_teardown;
+ }
+ func->varinfo = &scp->binfo;
+ func->func = SCF_PCM;
+ scp->pcm = device_add_child(dev, "pcm", -1);
+ device_set_ivars(scp->pcm, func);
+
+ /* Midi Interface */
+ func = malloc(sizeof(struct sndcard_func), M_DEVBUF, M_NOWAIT | M_ZERO);
+ if (func == NULL) {
+ error = ENOMEM;
+ goto err_teardown;
+ }
+ func->varinfo = &scp->binfo;
+ func->func = SCF_MIDI;
+ scp->midi = device_add_child(dev, "midi", -1);
+ device_set_ivars(scp->midi, func);
-bus_generic_attach(dev);
+ bus_generic_attach(dev);
-return (0);
+ return (0);
err_teardown:
-bus_teardown_intr(dev, resp->irq, scp->ih);
+ bus_teardown_intr(dev, resp->irq, scp->ih);
err_intr:
-bus_release_resource(dev, SYS_RES_IRQ, resp->irq_rid, resp->irq);
+ bus_release_resource(dev, SYS_RES_IRQ, resp->irq_rid, resp->irq);
err_mem:
-bus_release_resource(dev, SYS_RES_MEMORY, resp->mem_rid, resp->mem);
+ bus_release_resource(dev, SYS_RES_MEMORY, resp->mem_rid, resp->mem);
err_io:
-bus_release_resource(dev, SYS_RES_MEMORY, resp->io_rid, resp->io);
-return (error);
+ bus_release_resource(dev, SYS_RES_MEMORY, resp->io_rid, resp->io);
+ return (error);
}
static int
csa_detach(device_t dev)
{
-csa_res *resp;
-sc_p scp;
-int err;
-
-scp = device_get_softc(dev);
-resp = &scp->res;
-
-err = 0;
-if (scp->midi != NULL)
-err = device_delete_child(dev, scp->midi);
-if (err)
-return err;
-scp->midi = NULL;
-
-if (scp->pcm != NULL)
-err = device_delete_child(dev, scp->pcm);
-if (err)
-return err;
-scp->pcm = NULL;
-
-bus_teardown_intr(dev, resp->irq, scp->ih);
-bus_release_resource(dev, SYS_RES_IRQ, resp->irq_rid, resp->irq);
-bus_release_resource(dev, SYS_RES_MEMORY, resp->mem_rid, resp->mem);
-bus_release_resource(dev, SYS_RES_MEMORY, resp->io_rid, resp->io);
+ csa_res *resp;
+ sc_p scp;
+ struct sndcard_func *func;
+ int err;
+
+ scp = device_get_softc(dev);
+ resp = &scp->res;
+
+ if (scp->midi != NULL) {
+ func = device_get_ivars(scp->midi);
+ err = device_delete_child(dev, scp->midi);
+ if (err != 0)
+ return err;
+ if (func != NULL)
+ free(func, M_DEVBUF);
+ scp->midi = NULL;
+ }
+
+ if (scp->pcm != NULL) {
+ func = device_get_ivars(scp->pcm);
+ err = device_delete_child(dev, scp->pcm);
+ if (err != 0)
+ return err;
+ if (func != NULL)
+ free(func, M_DEVBUF);
+ scp->pcm = NULL;
+ }
+
+ bus_teardown_intr(dev, resp->irq, scp->ih);
+ bus_release_resource(dev, SYS_RES_IRQ, resp->irq_rid, resp->irq);
+ bus_release_resource(dev, SYS_RES_MEMORY, resp->mem_rid, resp->mem);
+ bus_release_resource(dev, SYS_RES_MEMORY, resp->io_rid, resp->io);
-return bus_generic_detach(dev);
+ return bus_generic_detach(dev);
}
static int
csa_resume(device_t dev)
{
-csa_res *resp;
-sc_p scp;
+ csa_res *resp;
+ sc_p scp;
-scp = device_get_softc(dev);
-resp = &scp->res;
+ scp = device_get_softc(dev);
+ resp = &scp->res;
-/* Initialize the chip. */
-if (csa_initialize(scp))
-return (ENXIO);
+ /* Initialize the chip. */
+ if (csa_initialize(scp))
+ return (ENXIO);
-/* Reset the Processor. */
-csa_resetdsp(resp);
+ /* Reset the Processor. */
+ csa_resetdsp(resp);
-/* Download the Processor Image to the processor. */
-if (csa_downloadimage(resp))
-return (ENXIO);
+ /* Download the Processor Image to the processor. */
+ if (csa_downloadimage(resp))
+ return (ENXIO);
-return (bus_generic_resume(dev));
+ return (bus_generic_resume(dev));
}
static struct resource *
csa_alloc_resource(device_t bus, device_t child, int type, int *rid,
-u_long start, u_long end, u_long count, u_int flags)
+ u_long start, u_long end, u_long count, u_int flags)
{
-sc_p scp;
-csa_res *resp;
-struct resource *res;
-
-scp = device_get_softc(bus);
-resp = &scp->res;
-switch (type) {
-case SYS_RES_IRQ:
-if (*rid != 0)
-return (NULL);
-res = resp->irq;
-break;
-case SYS_RES_MEMORY:
-switch (*rid) {
-case PCIR_BAR(0):
-res = resp->io;
-break;
-case PCIR_BAR(1):
-res = resp->mem;
-break;
-default:
-return (NULL);
-}
-break;
-default:
-return (NULL);
-}
+ sc_p scp;
+ csa_res *resp;
+ struct resource *res;
+
+ scp = device_get_softc(bus);
+ resp = &scp->res;
+ switch (type) {
+ case SYS_RES_IRQ:
+ if (*rid != 0)
+ return (NULL);
+ res = resp->irq;
+ break;
+ case SYS_RES_MEMORY:
+ switch (*rid) {
+ case PCIR_BAR(0):
+ res = resp->io;
+ break;
+ case PCIR_BAR(1):
+ res = resp->mem;
+ break;
+ default:
+ return (NULL);
+ }
+ break;
+ default:
+ return (NULL);
+ }
-return res;
+ return res;
}
static int
csa_release_resource(device_t bus, device_t child, int type, int rid,
-struct resource *r)
+ struct resource *r)
{
-return (0);
+ return (0);
}
/*
-* The following three functions deal with interrupt handling.
-* An interrupt is primarily handled by the bridge driver.
-* The bridge driver then determines the child devices to pass
-* the interrupt. Certain information of the device can be read
-* only once(eg the value of HISR). The bridge driver is responsible
-* to pass such the information to the children.
-*/
+ * The following three functions deal with interrupt handling.
+ * An interrupt is primarily handled by the bridge driver.
+ * The bridge driver then determines the child devices to pass
+ * the interrupt. Certain information of the device can be read
+ * only once(eg the value of HISR). The bridge driver is responsible
+ * to pass such the information to the children.
+ */
static int
csa_setup_intr(device_t bus, device_t child,
-struct resource *irq, int flags,
-driver_intr_t *intr, void *arg, void **cookiep)
+ struct resource *irq, int flags,
+#if __FreeBSD_version >= 700031
+ driver_filter_t *filter,
+#endif
+ driver_intr_t *intr, void *arg, void **cookiep)
{
-sc_p scp;
-csa_res *resp;
-struct sndcard_func *func;
-
-scp = device_get_softc(bus);
-resp = &scp->res;
+ sc_p scp;
+ csa_res *resp;
+ struct sndcard_func *func;
+
+#if __FreeBSD_version >= 700031
+ if (filter != NULL) {
+ printf("ata-csa.c: we cannot use a filter here\n");
+ return (EINVAL);
+ }
+#endif
+ scp = device_get_softc(bus);
+ resp = &scp->res;
-/*
-* Look at the function code of the child to determine
-* the appropriate hander for it.
-*/
-func = device_get_ivars(child);
-if (func == NULL || irq != resp->irq)
-return (EINVAL);
-
-switch (func->func) {
-case SCF_PCM:
-scp->pcmintr = intr;
-scp->pcmintr_arg = arg;
-break;
-
-case SCF_MIDI:
-scp->midiintr = intr;
-scp->midiintr_arg = arg;
-break;
-
-default:
-return (EINVAL);
-}
-*cookiep = scp;
-if ((csa_readio(resp, BA0_HISR) & HISR_INTENA) == 0)
-csa_writeio(resp, BA0_HICR, HICR_IEV | HICR_CHGM);
+ /*
+ * Look at the function code of the child to determine
+ * the appropriate hander for it.
+ */
+ func = device_get_ivars(child);
+ if (func == NULL || irq != resp->irq)
+ return (EINVAL);
+
+ switch (func->func) {
+ case SCF_PCM:
+ scp->pcmintr = intr;
+ scp->pcmintr_arg = arg;
+ break;
+
+ case SCF_MIDI:
+ scp->midiintr = intr;
+ scp->midiintr_arg = arg;
+ break;
+
+ default:
+ return (EINVAL);
+ }
+ *cookiep = scp;
+ if ((csa_readio(resp, BA0_HISR) & HISR_INTENA) == 0)
+ csa_writeio(resp, BA0_HICR, HICR_IEV | HICR_CHGM);
-return (0);
+ return (0);
}
static int
csa_teardown_intr(device_t bus, device_t child,
-struct resource *irq, void *cookie)
+ struct resource *irq, void *cookie)
{
-sc_p scp;
-csa_res *resp;
-struct sndcard_func *func;
-
-scp = device_get_softc(bus);
-resp = &scp->res;
-
-/*
-* Look at the function code of the child to determine
-* the appropriate hander for it.
-*/
-func = device_get_ivars(child);
-if (func == NULL || irq != resp->irq || cookie != scp)
-return (EINVAL);
-
-switch (func->func) {
-case SCF_PCM:
-scp->pcmintr = NULL;
-scp->pcmintr_arg = NULL;
-break;
-
-case SCF_MIDI:
-scp->midiintr = NULL;
-scp->midiintr_arg = NULL;
-break;
+ sc_p scp;
+ csa_res *resp;
+ struct sndcard_func *func;
+
+ scp = device_get_softc(bus);
+ resp = &scp->res;
+
+ /*
+ * Look at the function code of the child to determine
+ * the appropriate hander for it.
+ */
+ func = device_get_ivars(child);
+ if (func == NULL || irq != resp->irq || cookie != scp)
+ return (EINVAL);
+
+ switch (func->func) {
+ case SCF_PCM:
+ scp->pcmintr = NULL;
+ scp->pcmintr_arg = NULL;
+ break;
+
+ case SCF_MIDI:
+ scp->midiintr = NULL;
+ scp->midiintr_arg = NULL;
+ break;
+
+ default:
+ return (EINVAL);
+ }
-default:
-return (EINVAL);
-}
-
-return (0);
+ return (0);
}
/* The interrupt handler */
static void
csa_intr(void *arg)
{
-sc_p scp = arg;
-csa_res *resp;
-u_int32_t hisr;
-
-resp = &scp->res;
-
-/* Is this interrupt for us? */
-hisr = csa_readio(resp, BA0_HISR);
-if ((hisr & 0x7fffffff) == 0) {
-/* Throw an eoi. */
-csa_writeio(resp, BA0_HICR, HICR_IEV | HICR_CHGM);
-return;
-}
-
-/*
-* Pass the value of HISR via struct csa_bridgeinfo.
-* The children get access through their ivars.
-*/
-scp->binfo.hisr = hisr;
-
-/* Invoke the handlers of the children. */
-if ((hisr & (HISR_VC0 | HISR_VC1)) != 0 && scp->pcmintr != NULL) {
-scp->pcmintr(scp->pcmintr_arg);
-hisr &= ~(HISR_VC0 | HISR_VC1);
-}
-if ((hisr & HISR_MIDI) != 0 && scp->midiintr != NULL) {
-scp->midiintr(scp->midiintr_arg);
-hisr &= ~HISR_MIDI;
-}
+ sc_p scp = arg;
+ csa_res *resp;
+ u_int32_t hisr;
+
+ resp = &scp->res;
+
+ /* Is this interrupt for us? */
+ hisr = csa_readio(resp, BA0_HISR);
+ if ((hisr & 0x7fffffff) == 0) {
+ /* Throw an eoi. */
+ csa_writeio(resp, BA0_HICR, HICR_IEV | HICR_CHGM);
+ return;
+ }
+
+ /*
+ * Pass the value of HISR via struct csa_bridgeinfo.
+ * The children get access through their ivars.
+ */
+ scp->binfo.hisr = hisr;
+
+ /* Invoke the handlers of the children. */
+ if ((hisr & (HISR_VC0 | HISR_VC1)) != 0 && scp->pcmintr != NULL) {
+ scp->pcmintr(scp->pcmintr_arg);
+ hisr &= ~(HISR_VC0 | HISR_VC1);
+ }
+ if ((hisr & HISR_MIDI) != 0 && scp->midiintr != NULL) {
+ scp->midiintr(scp->midiintr_arg);
+ hisr &= ~HISR_MIDI;
+ }
-/* Throw an eoi. */
-csa_writeio(resp, BA0_HICR, HICR_IEV | HICR_CHGM);
+ /* Throw an eoi. */
+ csa_writeio(resp, BA0_HICR, HICR_IEV | HICR_CHGM);
}
static int
csa_initialize(sc_p scp)
{
-int i;
-u_int32_t acsts, acisv;
-csa_res *resp;
-
-resp = &scp->res;
-
-/*
-* First, blast the clock control register to zero so that the PLL starts
-* out in a known state, and blast the master serial port control register
-* to zero so that the serial ports also start out in a known state.
-*/
-csa_writeio(resp, BA0_CLKCR1, 0);
-csa_writeio(resp, BA0_SERMC1, 0);
-
-/*
-* If we are in AC97 mode, then we must set the part to a host controlled
-* AC-link. Otherwise, we won't be able to bring up the link.
-*/
+ int i;
+ u_int32_t acsts, acisv;
+ csa_res *resp;
+
+ resp = &scp->res;
+
+ /*
+ * First, blast the clock control register to zero so that the PLL starts
+ * out in a known state, and blast the master serial port control register
+ * to zero so that the serial ports also start out in a known state.
+ */
+ csa_writeio(resp, BA0_CLKCR1, 0);
+ csa_writeio(resp, BA0_SERMC1, 0);
+
+ /*
+ * If we are in AC97 mode, then we must set the part to a host controlled
+ * AC-link. Otherwise, we won't be able to bring up the link.
+ */
#if 1
-csa_writeio(resp, BA0_SERACC, SERACC_HSP | SERACC_CODEC_TYPE_1_03); /* 1.03 codec */
+ csa_writeio(resp, BA0_SERACC, SERACC_HSP | SERACC_CODEC_TYPE_1_03); /* 1.03 codec */
#else
-csa_writeio(resp, BA0_SERACC, SERACC_HSP | SERACC_CODEC_TYPE_2_0); /* 2.0 codec */
+ csa_writeio(resp, BA0_SERACC, SERACC_HSP | SERACC_CODEC_TYPE_2_0); /* 2.0 codec */
#endif /* 1 */
-/*
-* Drive the ARST# pin low for a minimum of 1uS (as defined in the AC97
-* spec) and then drive it high. This is done for non AC97 modes since
-* there might be logic external to the CS461x that uses the ARST# line
-* for a reset.
-*/
-csa_writeio(resp, BA0_ACCTL, 1);
-DELAY(50);
-csa_writeio(resp, BA0_ACCTL, 0);
-DELAY(50);
-csa_writeio(resp, BA0_ACCTL, ACCTL_RSTN);
-
-/*
-* The first thing we do here is to enable sync generation. As soon
-* as we start receiving bit clock, we'll start producing the SYNC
-* signal.
-*/
-csa_writeio(resp, BA0_ACCTL, ACCTL_ESYN | ACCTL_RSTN);
-
-/*
-* Now wait for a short while to allow the AC97 part to start
-* generating bit clock (so we don't try to start the PLL without an
-* input clock).
-*/
-DELAY(50000);
-
-/*
-* Set the serial port timing configuration, so that
-* the clock control circuit gets its clock from the correct place.
-*/
-csa_writeio(resp, BA0_SERMC1, SERMC1_PTC_AC97);
-DELAY(700000);
-
-/*
-* Write the selected clock control setup to the hardware. Do not turn on
-* SWCE yet (if requested), so that the devices clocked by the output of
-* PLL are not clocked until the PLL is stable.
-*/
-csa_writeio(resp, BA0_PLLCC, PLLCC_LPF_1050_2780_KHZ | PLLCC_CDR_73_104_MHZ);
-csa_writeio(resp, BA0_PLLM, 0x3a);
-csa_writeio(resp, BA0_CLKCR2, CLKCR2_PDIVS_8);
-
-/*
-* Power up the PLL.
-*/
-csa_writeio(resp, BA0_CLKCR1, CLKCR1_PLLP);
-
-/*
-* Wait until the PLL has stabilized.
-*/
-DELAY(5000);
-
-/*
-* Turn on clocking of the core so that we can setup the serial ports.
-*/
-csa_writeio(resp, BA0_CLKCR1, csa_readio(resp, BA0_CLKCR1) | CLKCR1_SWCE);
-
-/*
-* Fill the serial port FIFOs with silence.
-*/
-csa_clearserialfifos(resp);
-
-/*
-* Set the serial port FIFO pointer to the first sample in the FIFO.
-*/
+ /*
+ * Drive the ARST# pin low for a minimum of 1uS (as defined in the AC97
+ * spec) and then drive it high. This is done for non AC97 modes since
+ * there might be logic external to the CS461x that uses the ARST# line
+ * for a reset.
+ */
+ csa_writeio(resp, BA0_ACCTL, 1);
+ DELAY(50);
+ csa_writeio(resp, BA0_ACCTL, 0);
+ DELAY(50);
+ csa_writeio(resp, BA0_ACCTL, ACCTL_RSTN);
+
+ /*
+ * The first thing we do here is to enable sync generation. As soon
+ * as we start receiving bit clock, we'll start producing the SYNC
+ * signal.
+ */
+ csa_writeio(resp, BA0_ACCTL, ACCTL_ESYN | ACCTL_RSTN);
+
+ /*
+ * Now wait for a short while to allow the AC97 part to start
+ * generating bit clock (so we don't try to start the PLL without an
+ * input clock).
+ */
+ DELAY(50000);
+
+ /*
+ * Set the serial port timing configuration, so that
+ * the clock control circuit gets its clock from the correct place.
+ */
+ csa_writeio(resp, BA0_SERMC1, SERMC1_PTC_AC97);
+ DELAY(700000);
+
+ /*
+ * Write the selected clock control setup to the hardware. Do not turn on
+ * SWCE yet (if requested), so that the devices clocked by the output of
+ * PLL are not clocked until the PLL is stable.
+ */
+ csa_writeio(resp, BA0_PLLCC, PLLCC_LPF_1050_2780_KHZ | PLLCC_CDR_73_104_MHZ);
+ csa_writeio(resp, BA0_PLLM, 0x3a);
+ csa_writeio(resp, BA0_CLKCR2, CLKCR2_PDIVS_8);
+
+ /*
+ * Power up the PLL.
+ */
+ csa_writeio(resp, BA0_CLKCR1, CLKCR1_PLLP);
+
+ /*
+ * Wait until the PLL has stabilized.
+ */
+ DELAY(5000);
+
+ /*
+ * Turn on clocking of the core so that we can setup the serial ports.
+ */
+ csa_writeio(resp, BA0_CLKCR1, csa_readio(resp, BA0_CLKCR1) | CLKCR1_SWCE);
+
+ /*
+ * Fill the serial port FIFOs with silence.
+ */
+ csa_clearserialfifos(resp);
+
+ /*
+ * Set the serial port FIFO pointer to the first sample in the FIFO.
+ */
#ifdef notdef
-csa_writeio(resp, BA0_SERBSP, 0);
+ csa_writeio(resp, BA0_SERBSP, 0);
#endif /* notdef */
-/*
-* Write the serial port configuration to the part. The master
-* enable bit is not set until all other values have been written.
-*/
-csa_writeio(resp, BA0_SERC1, SERC1_SO1F_AC97 | SERC1_SO1EN);
-csa_writeio(resp, BA0_SERC2, SERC2_SI1F_AC97 | SERC1_SO1EN);
-csa_writeio(resp, BA0_SERMC1, SERMC1_PTC_AC97 | SERMC1_MSPE);
-
-/*
-* Wait for the codec ready signal from the AC97 codec.
-*/
-acsts = 0;
-for (i = 0 ; i < 1000 ; i++) {
-/*
-* First, lets wait a short while to let things settle out a bit,
-* and to prevent retrying the read too quickly.
-*/
-DELAY(125);
-
-/*
-* Read the AC97 status register to see if we've seen a CODEC READY
-* signal from the AC97 codec.
-*/
-acsts = csa_readio(resp, BA0_ACSTS);
-if ((acsts & ACSTS_CRDY) != 0)
-break;
-}
-
-/*
-* Make sure we sampled CODEC READY.
-*/
-if ((acsts & ACSTS_CRDY) == 0)
-return (ENXIO);
-
-/*
-* Assert the vaid frame signal so that we can start sending commands
-* to the AC97 codec.
-*/
-csa_writeio(resp, BA0_ACCTL, ACCTL_VFRM | ACCTL_ESYN | ACCTL_RSTN);
-
-/*
-* Wait until we've sampled input slots 3 and 4 as valid, meaning that
-* the codec is pumping ADC data across the AC-link.
-*/
-acisv = 0;
-for (i = 0 ; i < 1000 ; i++) {
-/*
-* First, lets wait a short while to let things settle out a bit,
-* and to prevent retrying the read too quickly.
-*/
+ /*
+ * Write the serial port configuration to the part. The master
+ * enable bit is not set until all other values have been written.
+ */
+ csa_writeio(resp, BA0_SERC1, SERC1_SO1F_AC97 | SERC1_SO1EN);
+ csa_writeio(resp, BA0_SERC2, SERC2_SI1F_AC97 | SERC1_SO1EN);
+ csa_writeio(resp, BA0_SERMC1, SERMC1_PTC_AC97 | SERMC1_MSPE);
+
+ /*
+ * Wait for the codec ready signal from the AC97 codec.
+ */
+ acsts = 0;
+ for (i = 0 ; i < 1000 ; i++) {
+ /*
+ * First, lets wait a short while to let things settle out a bit,
+ * and to prevent retrying the read too quickly.
+ */
+ DELAY(125);
+
+ /*
+ * Read the AC97 status register to see if we've seen a CODEC READY
+ * signal from the AC97 codec.
+ */
+ acsts = csa_readio(resp, BA0_ACSTS);
+ if ((acsts & ACSTS_CRDY) != 0)
+ break;
+ }
+
+ /*
+ * Make sure we sampled CODEC READY.
+ */
+ if ((acsts & ACSTS_CRDY) == 0)
+ return (ENXIO);
+
+ /*
+ * Assert the vaid frame signal so that we can start sending commands
+ * to the AC97 codec.
+ */
+ csa_writeio(resp, BA0_ACCTL, ACCTL_VFRM | ACCTL_ESYN | ACCTL_RSTN);
+
+ /*
+ * Wait until we've sampled input slots 3 and 4 as valid, meaning that
+ * the codec is pumping ADC data across the AC-link.
+ */
+ acisv = 0;
+ for (i = 0 ; i < 1000 ; i++) {
+ /*
+ * First, lets wait a short while to let things settle out a bit,
+ * and to prevent retrying the read too quickly.
+ */
#ifdef notdef
-DELAY(10000000L); /* clw */
+ DELAY(10000000L); /* clw */
#else
-DELAY(1000);
+ DELAY(1000);
#endif /* notdef */
-/*
-* Read the input slot valid register and see if input slots 3 and
-* 4 are valid yet.
-*/
-acisv = csa_readio(resp, BA0_ACISV);
-if ((acisv & (ACISV_ISV3 | ACISV_ISV4)) == (ACISV_ISV3 | ACISV_ISV4))
-break;
-}
-/*
-* Make sure we sampled valid input slots 3 and 4. If not, then return
-* an error.
-*/
-if ((acisv & (ACISV_ISV3 | ACISV_ISV4)) != (ACISV_ISV3 | ACISV_ISV4))
-return (ENXIO);
-
-/*
-* Now, assert valid frame and the slot 3 and 4 valid bits. This will
-* commense the transfer of digital audio data to the AC97 codec.
-*/
-csa_writeio(resp, BA0_ACOSV, ACOSV_SLV3 | ACOSV_SLV4);
-
-/*
-* Power down the DAC and ADC. We will power them up (if) when we need
-* them.
-*/
+ /*
+ * Read the input slot valid register and see if input slots 3 and
+ * 4 are valid yet.
+ */
+ acisv = csa_readio(resp, BA0_ACISV);
+ if ((acisv & (ACISV_ISV3 | ACISV_ISV4)) == (ACISV_ISV3 | ACISV_ISV4))
+ break;
+ }
+ /*
+ * Make sure we sampled valid input slots 3 and 4. If not, then return
+ * an error.
+ */
+ if ((acisv & (ACISV_ISV3 | ACISV_ISV4)) != (ACISV_ISV3 | ACISV_ISV4))
+ return (ENXIO);
+
+ /*
+ * Now, assert valid frame and the slot 3 and 4 valid bits. This will
+ * commense the transfer of digital audio data to the AC97 codec.
+ */
+ csa_writeio(resp, BA0_ACOSV, ACOSV_SLV3 | ACOSV_SLV4);
+
+ /*
+ * Power down the DAC and ADC. We will power them up (if) when we need
+ * them.
+ */
#ifdef notdef
-csa_writeio(resp, BA0_AC97_POWERDOWN, 0x300);
+ csa_writeio(resp, BA0_AC97_POWERDOWN, 0x300);
#endif /* notdef */
-/*
-* Turn off the Processor by turning off the software clock enable flag in
-* the clock control register.
-*/
+ /*
+ * Turn off the Processor by turning off the software clock enable flag in
+ * the clock control register.
+ */
#ifdef notdef
-clkcr1 = csa_readio(resp, BA0_CLKCR1) & ~CLKCR1_SWCE;
-csa_writeio(resp, BA0_CLKCR1, clkcr1);
+ clkcr1 = csa_readio(resp, BA0_CLKCR1) & ~CLKCR1_SWCE;
+ csa_writeio(resp, BA0_CLKCR1, clkcr1);
#endif /* notdef */
-/*
-* Enable interrupts on the part.
-*/
+ /*
+ * Enable interrupts on the part.
+ */
#if 0
-csa_writeio(resp, BA0_HICR, HICR_IEV | HICR_CHGM);
+ csa_writeio(resp, BA0_HICR, HICR_IEV | HICR_CHGM);
#endif /* notdef */
-return (0);
+ return (0);
}
void
csa_clearserialfifos(csa_res *resp)
{
-int i, j, pwr;
-u_int8_t clkcr1, serbst;
+ int i, j, pwr;
+ u_int8_t clkcr1, serbst;
-/*
-* See if the devices are powered down. If so, we must power them up first
-* or they will not respond.
-*/
-pwr = 1;
-clkcr1 = csa_readio(resp, BA0_CLKCR1);
-if ((clkcr1 & CLKCR1_SWCE) == 0) {
-csa_writeio(resp, BA0_CLKCR1, clkcr1 | CLKCR1_SWCE);
-pwr = 0;
-}
-
-/*
-* We want to clear out the serial port FIFOs so we don't end up playing
-* whatever random garbage happens to be in them. We fill the sample FIFOs
-* with zero (silence).
-*/
-csa_writeio(resp, BA0_SERBWP, 0);
-
-/* Fill all 256 sample FIFO locations. */
-serbst = 0;
-for (i = 0 ; i < 256 ; i++) {
-/* Make sure the previous FIFO write operation has completed. */
-for (j = 0 ; j < 5 ; j++) {
-DELAY(100);
-serbst = csa_readio(resp, BA0_SERBST);
-if ((serbst & SERBST_WBSY) == 0)
-break;
-}
-if ((serbst & SERBST_WBSY) != 0) {
-if (!pwr)
-csa_writeio(resp, BA0_CLKCR1, clkcr1);
-}
-/* Write the serial port FIFO index. */
-csa_writeio(resp, BA0_SERBAD, i);
-/* Tell the serial port to load the new value into the FIFO location. */
-csa_writeio(resp, BA0_SERBCM, SERBCM_WRC);
-}
-/*
-* Now, if we powered up the devices, then power them back down again.
-* This is kinda ugly, but should never happen.
-*/
-if (!pwr)
-csa_writeio(resp, BA0_CLKCR1, clkcr1);
+ /*
+ * See if the devices are powered down. If so, we must power them up first
+ * or they will not respond.
+ */
+ pwr = 1;
+ clkcr1 = csa_readio(resp, BA0_CLKCR1);
+ if ((clkcr1 & CLKCR1_SWCE) == 0) {
+ csa_writeio(resp, BA0_CLKCR1, clkcr1 | CLKCR1_SWCE);
+ pwr = 0;
+ }
+
+ /*
+ * We want to clear out the serial port FIFOs so we don't end up playing
+ * whatever random garbage happens to be in them. We fill the sample FIFOs
+ * with zero (silence).
+ */
+ csa_writeio(resp, BA0_SERBWP, 0);
+
+ /* Fill all 256 sample FIFO locations. */
+ serbst = 0;
+ for (i = 0 ; i < 256 ; i++) {
+ /* Make sure the previous FIFO write operation has completed. */
+ for (j = 0 ; j < 5 ; j++) {
+ DELAY(100);
+ serbst = csa_readio(resp, BA0_SERBST);
+ if ((serbst & SERBST_WBSY) == 0)
+ break;
+ }
+ if ((serbst & SERBST_WBSY) != 0) {
+ if (!pwr)
+ csa_writeio(resp, BA0_CLKCR1, clkcr1);
+ }
+ /* Write the serial port FIFO index. */
+ csa_writeio(resp, BA0_SERBAD, i);
+ /* Tell the serial port to load the new value into the FIFO location. */
+ csa_writeio(resp, BA0_SERBCM, SERBCM_WRC);
+ }
+ /*
+ * Now, if we powered up the devices, then power them back down again.
+ * This is kinda ugly, but should never happen.
+ */
+ if (!pwr)
+ csa_writeio(resp, BA0_CLKCR1, clkcr1);
}
void
csa_resetdsp(csa_res *resp)
{
-int i;
-
-/*
-* Write the reset bit of the SP control register.
-*/
-csa_writemem(resp, BA1_SPCR, SPCR_RSTSP);
+ int i;
-/*
-* Write the control register.
-*/
-csa_writemem(resp, BA1_SPCR, SPCR_DRQEN);
-
-/*
-* Clear the trap registers.
-*/
-for (i = 0 ; i < 8 ; i++) {
-csa_writemem(resp, BA1_DREG, DREG_REGID_TRAP_SELECT + i);
-csa_writemem(resp, BA1_TWPR, 0xffff);
-}
-csa_writemem(resp, BA1_DREG, 0);
-
-/*
-* Set the frame timer to reflect the number of cycles per frame.
-*/
-csa_writemem(resp, BA1_FRMT, 0xadf);
+ /*
+ * Write the reset bit of the SP control register.
+ */
+ csa_writemem(resp, BA1_SPCR, SPCR_RSTSP);
+
+ /*
+ * Write the control register.
+ */
+ csa_writemem(resp, BA1_SPCR, SPCR_DRQEN);
+
+ /*
+ * Clear the trap registers.
+ */
+ for (i = 0 ; i < 8 ; i++) {
+ csa_writemem(resp, BA1_DREG, DREG_REGID_TRAP_SELECT + i);
+ csa_writemem(resp, BA1_TWPR, 0xffff);
+ }
+ csa_writemem(resp, BA1_DREG, 0);
+
+ /*
+ * Set the frame timer to reflect the number of cycles per frame.
+ */
+ csa_writemem(resp, BA1_FRMT, 0xadf);
}
static int
csa_downloadimage(csa_res *resp)
{
-int i;
-u_int32_t tmp, src, dst, count, data;
+ int i;
+ u_int32_t tmp, src, dst, count, data;
-for (i = 0; i < CLEAR__COUNT; i++) {
-dst = ClrStat[i].BA1__DestByteOffset;
-count = ClrStat[i].BA1__SourceSize;
-for (tmp = 0; tmp < count; tmp += 4)
-csa_writemem(resp, dst + tmp, 0x00000000);
-}
+ for (i = 0; i < CLEAR__COUNT; i++) {
+ dst = ClrStat[i].BA1__DestByteOffset;
+ count = ClrStat[i].BA1__SourceSize;
+ for (tmp = 0; tmp < count; tmp += 4)
+ csa_writemem(resp, dst + tmp, 0x00000000);
+ }
+
+ for (i = 0; i < FILL__COUNT; i++) {
+ src = 0;
+ dst = FillStat[i].Offset;
+ count = FillStat[i].Size;
+ for (tmp = 0; tmp < count; tmp += 4) {
+ data = FillStat[i].pFill[src];
+ csa_writemem(resp, dst + tmp, data);
+ src++;
+ }
+ }
-for (i = 0; i < FILL__COUNT; i++) {
-src = 0;
-dst = FillStat[i].Offset;
-count = FillStat[i].Size;
-for (tmp = 0; tmp < count; tmp += 4) {
-data = FillStat[i].pFill[src];
-csa_writemem(resp, dst + tmp, data);
-src++;
-}
-}
-
-return (0);
+ return (0);
}
int
csa_readcodec(csa_res *resp, u_long offset, u_int32_t *data)
{
-int i;
-u_int32_t acsda, acctl, acsts;
-
-/*
-* Make sure that there is not data sitting around from a previous
-* uncompleted access. ACSDA = Status Data Register = 47Ch
-*/
-acsda = csa_readio(resp, BA0_ACSDA);
+ int i;
+ u_int32_t acsda, acctl, acsts;
-/*
-* Setup the AC97 control registers on the CS461x to send the
-* appropriate command to the AC97 to perform the read.
-* ACCAD = Command Address Register = 46Ch
-* ACCDA = Command Data Register = 470h
-* ACCTL = Control Register = 460h
-* set DCV - will clear when process completed
-* set CRW - Read command
-* set VFRM - valid frame enabled
-* set ESYN - ASYNC generation enabled
-* set RSTN - ARST# inactive, AC97 codec not reset
-*/
-
-/*
-* Get the actual AC97 register from the offset
-*/
-csa_writeio(resp, BA0_ACCAD, offset - BA0_AC97_RESET);
-csa_writeio(resp, BA0_ACCDA, 0);
-csa_writeio(resp, BA0_ACCTL, ACCTL_DCV | ACCTL_CRW | ACCTL_VFRM | ACCTL_ESYN | ACCTL_RSTN);
+ /*
+ * Make sure that there is not data sitting around from a previous
+ * uncompleted access. ACSDA = Status Data Register = 47Ch
+ */
+ acsda = csa_readio(resp, BA0_ACSDA);
+
+ /*
+ * Setup the AC97 control registers on the CS461x to send the
+ * appropriate command to the AC97 to perform the read.
+ * ACCAD = Command Address Register = 46Ch
+ * ACCDA = Command Data Register = 470h
+ * ACCTL = Control Register = 460h
+ * set DCV - will clear when process completed
+ * set CRW - Read command
+ * set VFRM - valid frame enabled
+ * set ESYN - ASYNC generation enabled
+ * set RSTN - ARST# inactive, AC97 codec not reset
+ */
+
+ /*
+ * Get the actual AC97 register from the offset
+ */
+ csa_writeio(resp, BA0_ACCAD, offset - BA0_AC97_RESET);
+ csa_writeio(resp, BA0_ACCDA, 0);
+ csa_writeio(resp, BA0_ACCTL, ACCTL_DCV | ACCTL_CRW | ACCTL_VFRM | ACCTL_ESYN | ACCTL_RSTN);
+
+ /*
+ * Wait for the read to occur.
+ */
+ acctl = 0;
+ for (i = 0 ; i < 10 ; i++) {
+ /*
+ * First, we want to wait for a short time.
+ */
+ DELAY(25);
+
+ /*
+ * Now, check to see if the read has completed.
+ * ACCTL = 460h, DCV should be reset by now and 460h = 17h
+ */
+ acctl = csa_readio(resp, BA0_ACCTL);
+ if ((acctl & ACCTL_DCV) == 0)
+ break;
+ }
+
+ /*
+ * Make sure the read completed.
+ */
+ if ((acctl & ACCTL_DCV) != 0)
+ return (EAGAIN);
+
+ /*
+ * Wait for the valid status bit to go active.
+ */
+ acsts = 0;
+ for (i = 0 ; i < 10 ; i++) {
+ /*
+ * Read the AC97 status register.
+ * ACSTS = Status Register = 464h
+ */
+ acsts = csa_readio(resp, BA0_ACSTS);
+ /*
+ * See if we have valid status.
+ * VSTS - Valid Status
+ */
+ if ((acsts & ACSTS_VSTS) != 0)
+ break;
+ /*
+ * Wait for a short while.
+ */
+ DELAY(25);
+ }
+
+ /*
+ * Make sure we got valid status.
+ */
+ if ((acsts & ACSTS_VSTS) == 0)
+ return (EAGAIN);
+
+ /*
+ * Read the data returned from the AC97 register.
+ * ACSDA = Status Data Register = 474h
+ */
+ *data = csa_readio(resp, BA0_ACSDA);
-/*
-* Wait for the read to occur.
-*/
-acctl = 0;
-for (i = 0 ; i < 10 ; i++) {
-/*
-* First, we want to wait for a short time.
-*/
-DELAY(25);
-
-/*
-* Now, check to see if the read has completed.
-* ACCTL = 460h, DCV should be reset by now and 460h = 17h
-*/
-acctl = csa_readio(resp, BA0_ACCTL);
-if ((acctl & ACCTL_DCV) == 0)
-break;
-}
-
-/*
-* Make sure the read completed.
-*/
-if ((acctl & ACCTL_DCV) != 0)
-return (EAGAIN);
-
-/*
-* Wait for the valid status bit to go active.
-*/
-acsts = 0;
-for (i = 0 ; i < 10 ; i++) {
-/*
-* Read the AC97 status register.
-* ACSTS = Status Register = 464h
-*/
-acsts = csa_readio(resp, BA0_ACSTS);
-/*
-* See if we have valid status.
-* VSTS - Valid Status
-*/
-if ((acsts & ACSTS_VSTS) != 0)
-break;
-/*
-* Wait for a short while.
-*/
-DELAY(25);
-}
-
-/*
-* Make sure we got valid status.
-*/
-if ((acsts & ACSTS_VSTS) == 0)
-return (EAGAIN);
-
-/*
-* Read the data returned from the AC97 register.
-* ACSDA = Status Data Register = 474h
-*/
-*data = csa_readio(resp, BA0_ACSDA);
-
-return (0);
+ return (0);
}
int
csa_writecodec(csa_res *resp, u_long offset, u_int32_t data)
{
-int i;
-u_int32_t acctl;
-
-/*
-* Setup the AC97 control registers on the CS461x to send the
-* appropriate command to the AC97 to perform the write.
-* ACCAD = Command Address Register = 46Ch
-* ACCDA = Command Data Register = 470h
-* ACCTL = Control Register = 460h
-* set DCV - will clear when process completed
-* set VFRM - valid frame enabled
-* set ESYN - ASYNC generation enabled
-* set RSTN - ARST# inactive, AC97 codec not reset
-*/
+ int i;
+ u_int32_t acctl;
-/*
-* Get the actual AC97 register from the offset
-*/
-csa_writeio(resp, BA0_ACCAD, offset - BA0_AC97_RESET);
-csa_writeio(resp, BA0_ACCDA, data);
-csa_writeio(resp, BA0_ACCTL, ACCTL_DCV | ACCTL_VFRM | ACCTL_ESYN | ACCTL_RSTN);
+ /*
+ * Setup the AC97 control registers on the CS461x to send the
+ * appropriate command to the AC97 to perform the write.
+ * ACCAD = Command Address Register = 46Ch
+ * ACCDA = Command Data Register = 470h
+ * ACCTL = Control Register = 460h
+ * set DCV - will clear when process completed
+ * set VFRM - valid frame enabled
+ * set ESYN - ASYNC generation enabled
+ * set RSTN - ARST# inactive, AC97 codec not reset
+ */
+
+ /*
+ * Get the actual AC97 register from the offset
+ */
+ csa_writeio(resp, BA0_ACCAD, offset - BA0_AC97_RESET);
+ csa_writeio(resp, BA0_ACCDA, data);
+ csa_writeio(resp, BA0_ACCTL, ACCTL_DCV | ACCTL_VFRM | ACCTL_ESYN | ACCTL_RSTN);
+
+ /*
+ * Wait for the write to occur.
+ */
+ acctl = 0;
+ for (i = 0 ; i < 10 ; i++) {
+ /*
+ * First, we want to wait for a short time.
+ */
+ DELAY(25);
+
+ /*
+ * Now, check to see if the read has completed.
+ * ACCTL = 460h, DCV should be reset by now and 460h = 17h
+ */
+ acctl = csa_readio(resp, BA0_ACCTL);
+ if ((acctl & ACCTL_DCV) == 0)
+ break;
+ }
+
+ /*
+ * Make sure the write completed.
+ */
+ if ((acctl & ACCTL_DCV) != 0)
+ return (EAGAIN);
-/*
-* Wait for the write to occur.
-*/
-acctl = 0;
-for (i = 0 ; i < 10 ; i++) {
-/*
-* First, we want to wait for a short time.
-*/
-DELAY(25);
-
-/*
-* Now, check to see if the read has completed.
-* ACCTL = 460h, DCV should be reset by now and 460h = 17h
-*/
-acctl = csa_readio(resp, BA0_ACCTL);
-if ((acctl & ACCTL_DCV) == 0)
-break;
-}
-
-/*
-* Make sure the write completed.
-*/
-if ((acctl & ACCTL_DCV) != 0)
-return (EAGAIN);
-
-return (0);
+ return (0);
}
u_int32_t
csa_readio(csa_res *resp, u_long offset)
{
-u_int32_t ul;
+ u_int32_t ul;
-if (offset < BA0_AC97_RESET)
-return bus_space_read_4(rman_get_bustag(resp->io), rman_get_bushandle(resp->io), offset) & 0xffffffff;
-else {
-if (csa_readcodec(resp, offset, &ul))
-ul = 0;
-return (ul);
-}
+ if (offset < BA0_AC97_RESET)
+ return bus_space_read_4(rman_get_bustag(resp->io), rman_get_bushandle(resp->io), offset) & 0xffffffff;
+ else {
+ if (csa_readcodec(resp, offset, &ul))
+ ul = 0;
+ return (ul);
+ }
}
void
csa_writeio(csa_res *resp, u_long offset, u_int32_t data)
{
-if (offset < BA0_AC97_RESET)
-bus_space_write_4(rman_get_bustag(resp->io), rman_get_bushandle(resp->io), offset, data);
-else
-csa_writecodec(resp, offset, data);
+ if (offset < BA0_AC97_RESET)
+ bus_space_write_4(rman_get_bustag(resp->io), rman_get_bushandle(resp->io), offset, data);
+ else
+ csa_writecodec(resp, offset, data);
}
u_int32_t
csa_readmem(csa_res *resp, u_long offset)
{
-return bus_space_read_4(rman_get_bustag(resp->mem), rman_get_bushandle(resp->mem), offset);
+ return bus_space_read_4(rman_get_bustag(resp->mem), rman_get_bushandle(resp->mem), offset);
}
void
csa_writemem(csa_res *resp, u_long offset, u_int32_t data)
{
-bus_space_write_4(rman_get_bustag(resp->mem), rman_get_bushandle(resp->mem), offset, data);
+ bus_space_write_4(rman_get_bustag(resp->mem), rman_get_bushandle(resp->mem), offset, data);
}
static device_method_t csa_methods[] = {
-/* Device interface */
-DEVMETHOD(device_probe, csa_probe),
-DEVMETHOD(device_attach, csa_attach),
-DEVMETHOD(device_detach, csa_detach),
-DEVMETHOD(device_shutdown, bus_generic_shutdown),
-DEVMETHOD(device_suspend, bus_generic_suspend),
-DEVMETHOD(device_resume, csa_resume),
-
-/* Bus interface */
-DEVMETHOD(bus_print_child, bus_generic_print_child),
-DEVMETHOD(bus_alloc_resource, csa_alloc_resource),
-DEVMETHOD(bus_release_resource, csa_release_resource),
-DEVMETHOD(bus_activate_resource, bus_generic_activate_resource),
-DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource),
-DEVMETHOD(bus_setup_intr, csa_setup_intr),
-DEVMETHOD(bus_teardown_intr, csa_teardown_intr),
+ /* Device interface */
+ DEVMETHOD(device_probe, csa_probe),
+ DEVMETHOD(device_attach, csa_attach),
+ DEVMETHOD(device_detach, csa_detach),
+ DEVMETHOD(device_shutdown, bus_generic_shutdown),
+ DEVMETHOD(device_suspend, bus_generic_suspend),
+ DEVMETHOD(device_resume, csa_resume),
+
+ /* Bus interface */
+ DEVMETHOD(bus_print_child, bus_generic_print_child),
+ DEVMETHOD(bus_alloc_resource, csa_alloc_resource),
+ DEVMETHOD(bus_release_resource, csa_release_resource),
+ DEVMETHOD(bus_activate_resource, bus_generic_activate_resource),
+ DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource),
+ DEVMETHOD(bus_setup_intr, csa_setup_intr),
+ DEVMETHOD(bus_teardown_intr, csa_teardown_intr),
-{ 0, 0 }
+ { 0, 0 }
};
static driver_t csa_driver = {
-"csa",
-csa_methods,
-sizeof(struct csa_softc),
+ "csa",
+ csa_methods,
+ sizeof(struct csa_softc),
};
/*
-* csa can be attached to a pci bus.
-*/
+ * csa can be attached to a pci bus.
+ */
DRIVER_MODULE(snd_csa, pci, csa_driver, csa_devclass, 0, 0);
MODULE_DEPEND(snd_csa, sound, SOUND_MINVER, SOUND_PREFVER, SOUND_MAXVER);
MODULE_VERSION(snd_csa, 1);
Index: ich.c
===================================================================
RCS file: /home/cvs/src/sys/dev/sound/pci/ich.c,v
retrieving revision 1.3
retrieving revision 1.4
diff -L sys/dev/sound/pci/ich.c -L sys/dev/sound/pci/ich.c -u -r1.3 -r1.4
--- sys/dev/sound/pci/ich.c
+++ sys/dev/sound/pci/ich.c
@@ -1,29 +1,29 @@
/*-
-* Copyright (c) 2000 Katsurajima Naoto <raven at katsurajima.seya.yokohama.jp>
-* Copyright (c) 2001 Cameron Grant <cg at freebsd.org>
-* All rights reserved.
-*
-* Redistribution and use in source and binary forms, with or without
-* modification, are permitted provided that the following conditions
-* are met:
-* 1. Redistributions of source code must retain the above copyright
-* notice, this list of conditions and the following disclaimer.
-* 2. Redistributions in binary form must reproduce the above copyright
-* notice, this list of conditions and the following disclaimer in the
-* documentation and/or other materials provided with the distribution.
-*
-* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
-* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
-* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
-* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
-* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHERIN CONTRACT, STRICT
-* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
-* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THEPOSSIBILITY OF
-* SUCH DAMAGE.
-*/
+ * Copyright (c) 2000 Katsurajima Naoto <raven at katsurajima.seya.yokohama.jp>
+ * Copyright (c) 2001 Cameron Grant <cg at freebsd.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHERIN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THEPOSSIBILITY OF
+ * SUCH DAMAGE.
+ */
#include <dev/sound/pcm/sound.h>
#include <dev/sound/pcm/ac97.h>
@@ -32,14 +32,19 @@
#include <dev/pci/pcireg.h>
#include <dev/pci/pcivar.h>
-SND_DECLARE_FILE("$MidnightBSD$");
+SND_DECLARE_FILE("$FreeBSD: src/sys/dev/sound/pci/ich.c,v 1.78.2.1 2007/12/15 04:06:52 ariff Exp $");
/* -------------------------------------------------------------------- */
-#define ICH_TIMEOUT 1000 /* semaphore timeout polling count */
-#define ICH_DTBL_LENGTH 32
-#define ICH_DEFAULT_BUFSZ 16384
-#define ICH_MAX_BUFSZ 65536
+#define ICH_TIMEOUT 1000 /* semaphore timeout polling count */
+#define ICH_DTBL_LENGTH 32
+#define ICH_DEFAULT_BUFSZ 16384
+#define ICH_MAX_BUFSZ 65536
+#define ICH_MIN_BUFSZ 4096
+#define ICH_DEFAULT_BLKCNT 2
+#define ICH_MAX_BLKCNT 32
+#define ICH_MIN_BLKCNT 2
+#define ICH_MIN_BLKSZ 64
#define INTEL_VENDORID 0x8086
#define SIS_VENDORID 0x1039
@@ -72,199 +77,213 @@
#define ICH_UNLOCK(sc) snd_mtxunlock((sc)->ich_lock)
#define ICH_LOCK_ASSERT(sc) snd_mtxassert((sc)->ich_lock)
+#if 0
+#define ICH_DEBUG(stmt) do { \
+ stmt \
+} while(0)
+#else
+#define ICH_DEBUG(...)
+#endif
+
+#define ICH_CALIBRATE_DONE (1 << 0)
+#define ICH_IGNORE_PCR (1 << 1)
+#define ICH_IGNORE_RESET (1 << 2)
+#define ICH_FIXED_RATE (1 << 3)
+#define ICH_DMA_NOCACHE (1 << 4)
+#define ICH_HIGH_LATENCY (1 << 5)
+
static const struct ich_type {
-uint16_t vendor;
-uint16_t devid;
-uint32_t options;
+ uint16_t vendor;
+ uint16_t devid;
+ uint32_t options;
#define PROBE_LOW 0x01
-char *name;
+ char *name;
} ich_devs[] = {
-{ INTEL_VENDORID, INTEL_82440MX, 0,
-"Intel 440MX" },
-{ INTEL_VENDORID, INTEL_82801AA, 0,
-"Intel ICH (82801AA)" },
-{ INTEL_VENDORID, INTEL_82801AB, 0,
-"Intel ICH (82801AB)" },
-{ INTEL_VENDORID, INTEL_82801BA, 0,
-"Intel ICH2 (82801BA)" },
-{ INTEL_VENDORID, INTEL_82801CA, 0,
-"Intel ICH3 (82801CA)" },
-{ INTEL_VENDORID, INTEL_82801DB, PROBE_LOW,
-"Intel ICH4 (82801DB)" },
-{ INTEL_VENDORID, INTEL_82801EB, PROBE_LOW,
-"Intel ICH5 (82801EB)" },
-{ INTEL_VENDORID, INTEL_6300ESB, PROBE_LOW,
-"Intel 6300ESB" },
-{ INTEL_VENDORID, INTEL_82801FB, PROBE_LOW,
-"Intel ICH6 (82801FB)" },
-{ INTEL_VENDORID, INTEL_82801GB, PROBE_LOW,
-"Intel ICH7 (82801GB)" },
-{ SIS_VENDORID, SIS_7012, 0,
-"SiS 7012" },
-{ NVIDIA_VENDORID, NVIDIA_NFORCE, 0,
-"nVidia nForce" },
-{ NVIDIA_VENDORID, NVIDIA_NFORCE2, 0,
-"nVidia nForce2" },
-{ NVIDIA_VENDORID, NVIDIA_NFORCE2_400, 0,
-"nVidia nForce2 400" },
-{ NVIDIA_VENDORID, NVIDIA_NFORCE3, 0,
-"nVidia nForce3" },
-{ NVIDIA_VENDORID, NVIDIA_NFORCE3_250, 0,
-"nVidia nForce3 250" },
-{ NVIDIA_VENDORID, NVIDIA_NFORCE4, 0,
-"nVidia nForce4" },
-{ NVIDIA_VENDORID, NVIDIA_NFORCE_410_MCP, 0,
-"nVidia nForce 410 MCP" },
-{ NVIDIA_VENDORID, NVIDIA_NFORCE4_MCP, 0,
-"nVidia nForce 4 MCP" },
-{ AMD_VENDORID, AMD_768, 0,
-"AMD-768" },
-{ AMD_VENDORID, AMD_8111, 0,
-"AMD-8111" }
+ { INTEL_VENDORID, INTEL_82440MX, 0,
+ "Intel 440MX" },
+ { INTEL_VENDORID, INTEL_82801AA, 0,
+ "Intel ICH (82801AA)" },
+ { INTEL_VENDORID, INTEL_82801AB, 0,
+ "Intel ICH (82801AB)" },
+ { INTEL_VENDORID, INTEL_82801BA, 0,
+ "Intel ICH2 (82801BA)" },
+ { INTEL_VENDORID, INTEL_82801CA, 0,
+ "Intel ICH3 (82801CA)" },
+ { INTEL_VENDORID, INTEL_82801DB, PROBE_LOW,
+ "Intel ICH4 (82801DB)" },
+ { INTEL_VENDORID, INTEL_82801EB, PROBE_LOW,
+ "Intel ICH5 (82801EB)" },
+ { INTEL_VENDORID, INTEL_6300ESB, PROBE_LOW,
+ "Intel 6300ESB" },
+ { INTEL_VENDORID, INTEL_82801FB, PROBE_LOW,
+ "Intel ICH6 (82801FB)" },
+ { INTEL_VENDORID, INTEL_82801GB, PROBE_LOW,
+ "Intel ICH7 (82801GB)" },
+ { SIS_VENDORID, SIS_7012, 0,
+ "SiS 7012" },
+ { NVIDIA_VENDORID, NVIDIA_NFORCE, 0,
+ "nVidia nForce" },
+ { NVIDIA_VENDORID, NVIDIA_NFORCE2, 0,
+ "nVidia nForce2" },
+ { NVIDIA_VENDORID, NVIDIA_NFORCE2_400, 0,
+ "nVidia nForce2 400" },
+ { NVIDIA_VENDORID, NVIDIA_NFORCE3, 0,
+ "nVidia nForce3" },
+ { NVIDIA_VENDORID, NVIDIA_NFORCE3_250, 0,
+ "nVidia nForce3 250" },
+ { NVIDIA_VENDORID, NVIDIA_NFORCE4, 0,
+ "nVidia nForce4" },
+ { NVIDIA_VENDORID, NVIDIA_NFORCE_410_MCP, 0,
+ "nVidia nForce 410 MCP" },
+ { NVIDIA_VENDORID, NVIDIA_NFORCE4_MCP, 0,
+ "nVidia nForce 4 MCP" },
+ { AMD_VENDORID, AMD_768, 0,
+ "AMD-768" },
+ { AMD_VENDORID, AMD_8111, 0,
+ "AMD-8111" }
};
/* buffer descriptor */
struct ich_desc {
-volatile u_int32_t buffer;
-volatile u_int32_t length;
+ volatile uint32_t buffer;
+ volatile uint32_t length;
};
struct sc_info;
/* channel registers */
struct sc_chinfo {
-u_int32_t num:8, run:1, run_save:1;
-u_int32_t blksz, blkcnt, spd;
-u_int32_t regbase, spdreg;
-u_int32_t imask;
-u_int32_t civ;
-
-struct snd_dbuf *buffer;
-struct pcm_channel *channel;
-struct sc_info *parent;
+ uint32_t num:8, run:1, run_save:1;
+ uint32_t blksz, blkcnt, spd;
+ uint32_t regbase, spdreg;
+ uint32_t imask;
+ uint32_t civ;
+
+ struct snd_dbuf *buffer;
+ struct pcm_channel *channel;
+ struct sc_info *parent;
-struct ich_desc *dtbl;
-bus_addr_t desc_addr;
+ struct ich_desc *dtbl;
+ bus_addr_t desc_addr;
};
/* device private data */
struct sc_info {
-device_t dev;
-int hasvra, hasvrm, hasmic;
-unsigned int chnum, bufsz;
-int sample_size, swap_reg;
-
-struct resource *nambar, *nabmbar, *irq;
-int regtype, nambarid, nabmbarid, irqid;
-bus_space_tag_t nambart, nabmbart;
-bus_space_handle_t nambarh, nabmbarh;
-bus_dma_tag_t dmat;
-bus_dmamap_t dtmap;
-void *ih;
-
-struct ac97_info *codec;
-struct sc_chinfo ch[3];
-int ac97rate;
-struct ich_desc *dtbl;
-bus_addr_t desc_addr;
-struct intr_config_hook intrhook;
-int use_intrhook;
-uint16_t vendor;
-uint16_t devid;
-uint32_t flags;
-#define IGNORE_PCR 0x01
-struct mtx *ich_lock;
+ device_t dev;
+ int hasvra, hasvrm, hasmic;
+ unsigned int chnum, bufsz, blkcnt;
+ int sample_size, swap_reg;
+
+ struct resource *nambar, *nabmbar, *irq;
+ int regtype, nambarid, nabmbarid, irqid;
+ bus_space_tag_t nambart, nabmbart;
+ bus_space_handle_t nambarh, nabmbarh;
+ bus_dma_tag_t dmat, chan_dmat;
+ bus_dmamap_t dtmap;
+ void *ih;
+
+ struct ac97_info *codec;
+ struct sc_chinfo ch[3];
+ int ac97rate;
+ struct ich_desc *dtbl;
+ unsigned int dtbl_size;
+ bus_addr_t desc_addr;
+ struct intr_config_hook intrhook;
+ uint16_t vendor;
+ uint16_t devid;
+ uint32_t flags;
+ struct mtx *ich_lock;
};
/* -------------------------------------------------------------------- */
-static u_int32_t ich_fmt[] = {
-AFMT_STEREO | AFMT_S16_LE,
-0
+static uint32_t ich_fmt[] = {
+ AFMT_STEREO | AFMT_S16_LE,
+ 0
};
static struct pcmchan_caps ich_vrcaps = {8000, 48000, ich_fmt, 0};
static struct pcmchan_caps ich_caps = {48000, 48000, ich_fmt, 0};
/* -------------------------------------------------------------------- */
/* Hardware */
-static __inline u_int32_t
+static __inline uint32_t
ich_rd(struct sc_info *sc, int regno, int size)
{
-switch (size) {
-case 1:
-return bus_space_read_1(sc->nabmbart, sc->nabmbarh, regno);
-case 2:
-return bus_space_read_2(sc->nabmbart, sc->nabmbarh, regno);
-case 4:
-return bus_space_read_4(sc->nabmbart, sc->nabmbarh, regno);
-default:
-return 0xffffffff;
-}
+ switch (size) {
+ case 1:
+ return (bus_space_read_1(sc->nabmbart, sc->nabmbarh, regno));
+ case 2:
+ return (bus_space_read_2(sc->nabmbart, sc->nabmbarh, regno));
+ case 4:
+ return (bus_space_read_4(sc->nabmbart, sc->nabmbarh, regno));
+ default:
+ return (0xffffffff);
+ }
}
static __inline void
-ich_wr(struct sc_info *sc, int regno, u_int32_t data, int size)
+ich_wr(struct sc_info *sc, int regno, uint32_t data, int size)
{
-switch (size) {
-case 1:
-bus_space_write_1(sc->nabmbart, sc->nabmbarh, regno, data);
-break;
-case 2:
-bus_space_write_2(sc->nabmbart, sc->nabmbarh, regno, data);
-break;
-case 4:
-bus_space_write_4(sc->nabmbart, sc->nabmbarh, regno, data);
-break;
-}
+ switch (size) {
+ case 1:
+ bus_space_write_1(sc->nabmbart, sc->nabmbarh, regno, data);
+ break;
+ case 2:
+ bus_space_write_2(sc->nabmbart, sc->nabmbarh, regno, data);
+ break;
+ case 4:
+ bus_space_write_4(sc->nabmbart, sc->nabmbarh, regno, data);
+ break;
+ }
}
/* ac97 codec */
static int
ich_waitcd(void *devinfo)
{
-int i;
-u_int32_t data;
-struct sc_info *sc = (struct sc_info *)devinfo;
-
-for (i = 0; i < ICH_TIMEOUT; i++) {
-data = ich_rd(sc, ICH_REG_ACC_SEMA, 1);
-if ((data & 0x01) == 0)
-return 0;
-DELAY(1);
-}
-if ((sc->flags & IGNORE_PCR) != 0)
-return (0);
-device_printf(sc->dev, "CODEC semaphore timeoutn");
-return ETIMEDOUT;
+ struct sc_info *sc = (struct sc_info *)devinfo;
+ uint32_t data;
+ int i;
+
+ for (i = 0; i < ICH_TIMEOUT; i++) {
+ data = ich_rd(sc, ICH_REG_ACC_SEMA, 1);
+ if ((data & 0x01) == 0)
+ return (0);
+ DELAY(1);
+ }
+ if ((sc->flags & ICH_IGNORE_PCR) != 0)
+ return (0);
+ device_printf(sc->dev, "CODEC semaphore timeout\n");
+ return (ETIMEDOUT);
}
static int
ich_rdcd(kobj_t obj, void *devinfo, int regno)
{
-struct sc_info *sc = (struct sc_info *)devinfo;
+ struct sc_info *sc = (struct sc_info *)devinfo;
-regno &= 0xff;
-ich_waitcd(sc);
+ regno &= 0xff;
+ ich_waitcd(sc);
-return bus_space_read_2(sc->nambart, sc->nambarh, regno);
+ return (bus_space_read_2(sc->nambart, sc->nambarh, regno));
}
static int
-ich_wrcd(kobj_t obj, void *devinfo, int regno, u_int16_t data)
+ich_wrcd(kobj_t obj, void *devinfo, int regno, uint16_t data)
{
-struct sc_info *sc = (struct sc_info *)devinfo;
+ struct sc_info *sc = (struct sc_info *)devinfo;
-regno &= 0xff;
-ich_waitcd(sc);
-bus_space_write_2(sc->nambart, sc->nambarh, regno, data);
+ regno &= 0xff;
+ ich_waitcd(sc);
+ bus_space_write_2(sc->nambart, sc->nambarh, regno, data);
-return 0;
+ return (0);
}
static kobj_method_t ich_ac97_methods[] = {
-KOBJMETHOD(ac97_read, ich_rdcd),
-KOBJMETHOD(ac97_write, ich_wrcd),
-{ 0, 0 }
+ KOBJMETHOD(ac97_read, ich_rdcd),
+ KOBJMETHOD(ac97_write, ich_wrcd),
+ { 0, 0 }
};
AC97_DECLARE(ich_ac97);
@@ -274,53 +293,68 @@
static void
ich_filldtbl(struct sc_chinfo *ch)
{
-struct sc_info *sc = ch->parent;
-u_int32_t base;
-int i;
-
-base = sndbuf_getbufaddr(ch->buffer);
-if (ch->blksz > sc->bufsz / ch->blkcnt)
-ch->blksz = sc->bufsz / ch->blkcnt;
-sndbuf_resize(ch->buffer, ch->blkcnt, ch->blksz);
-ch->blksz = sndbuf_getblksz(ch->buffer);
-
-for (i = 0; i < ICH_DTBL_LENGTH; i++) {
-ch->dtbl[i].buffer = base + (ch->blksz * (i % ch->blkcnt));
-ch->dtbl[i].length = ICH_BDC_IOC
-| (ch->blksz / ch->parent->sample_size);
-}
+ struct sc_info *sc = ch->parent;
+ uint32_t base;
+ int i;
+
+ base = sndbuf_getbufaddr(ch->buffer);
+ if ((ch->blksz * ch->blkcnt) > sndbuf_getmaxsize(ch->buffer))
+ ch->blksz = sndbuf_getmaxsize(ch->buffer) / ch->blkcnt;
+ if ((sndbuf_getblksz(ch->buffer) != ch->blksz ||
+ sndbuf_getblkcnt(ch->buffer) != ch->blkcnt) &&
+ sndbuf_resize(ch->buffer, ch->blkcnt, ch->blksz) != 0)
+ device_printf(sc->dev, "%s: failed blksz=%u blkcnt=%u\n",
+ __func__, ch->blksz, ch->blkcnt);
+ ch->blksz = sndbuf_getblksz(ch->buffer);
+
+ for (i = 0; i < ICH_DTBL_LENGTH; i++) {
+ ch->dtbl[i].buffer = base + (ch->blksz * (i % ch->blkcnt));
+ ch->dtbl[i].length = ICH_BDC_IOC
+ | (ch->blksz / ch->parent->sample_size);
+ }
}
static int
ich_resetchan(struct sc_info *sc, int num)
{
-int i, cr, regbase;
+ int i, cr, regbase;
-if (num == 0)
-regbase = ICH_REG_PO_BASE;
-else if (num == 1)
-regbase = ICH_REG_PI_BASE;
-else if (num == 2)
-regbase = ICH_REG_MC_BASE;
-else
-return ENXIO;
+ if (num == 0)
+ regbase = ICH_REG_PO_BASE;
+ else if (num == 1)
+ regbase = ICH_REG_PI_BASE;
+ else if (num == 2)
+ regbase = ICH_REG_MC_BASE;
+ else
+ return (ENXIO);
-ich_wr(sc, regbase + ICH_REG_X_CR, 0, 1);
+ ich_wr(sc, regbase + ICH_REG_X_CR, 0, 1);
#if 1
-/* This may result in no sound output on NForce 2 MBs, see PR 73987 */
-DELAY(100);
+ /* This may result in no sound output on NForce 2 MBs, see PR 73987 */
+ DELAY(100);
#else
-(void)ich_rd(sc, regbase + ICH_REG_X_CR, 1);
+ (void)ich_rd(sc, regbase + ICH_REG_X_CR, 1);
+#endif
+ ich_wr(sc, regbase + ICH_REG_X_CR, ICH_X_CR_RR, 1);
+ for (i = 0; i < ICH_TIMEOUT; i++) {
+ cr = ich_rd(sc, regbase + ICH_REG_X_CR, 1);
+ if (cr == 0)
+ return (0);
+ DELAY(1);
+ }
+
+ if (sc->flags & ICH_IGNORE_RESET)
+ return (0);
+#if 0
+ else if (sc->vendor == NVIDIA_VENDORID) {
+ sc->flags |= ICH_IGNORE_RESET;
+ device_printf(sc->dev, "ignoring reset failure!\n");
+ return (0);
+ }
#endif
-ich_wr(sc, regbase + ICH_REG_X_CR, ICH_X_CR_RR, 1);
-for (i = 0; i < ICH_TIMEOUT; i++) {
-cr = ich_rd(sc, regbase + ICH_REG_X_CR, 1);
-if (cr == 0)
-return 0;
-}
-device_printf(sc->dev, "cannot reset channel %dn", num);
-return ENXIO;
+ device_printf(sc->dev, "cannot reset channel %d\n", num);
+ return (ENXIO);
}
/* -------------------------------------------------------------------- */
@@ -329,167 +363,227 @@
static void *
ichchan_init(kobj_t obj, void *devinfo, struct snd_dbuf *b, struct pcm_channel *c, int dir)
{
-struct sc_info *sc = devinfo;
-struct sc_chinfo *ch;
-unsigned int num;
-
-ICH_LOCK(sc);
-num = sc->chnum++;
-ch = &sc->ch[num];
-ch->num = num;
-ch->buffer = b;
-ch->channel = c;
-ch->parent = sc;
-ch->run = 0;
-ch->dtbl = sc->dtbl + (ch->num * ICH_DTBL_LENGTH);
-ch->desc_addr = sc->desc_addr + (ch->num * ICH_DTBL_LENGTH) *
-sizeof(struct ich_desc);
-ch->blkcnt = 2;
-ch->blksz = sc->bufsz / ch->blkcnt;
-
-switch(ch->num) {
-case 0: /* play */
-KASSERT(dir == PCMDIR_PLAY, ("wrong direction"));
-ch->regbase = ICH_REG_PO_BASE;
-ch->spdreg = sc->hasvra? AC97_REGEXT_FDACRATE : 0;
-ch->imask = ICH_GLOB_STA_POINT;
-break;
-
-case 1: /* record */
-KASSERT(dir == PCMDIR_REC, ("wrong direction"));
-ch->regbase = ICH_REG_PI_BASE;
-ch->spdreg = sc->hasvra? AC97_REGEXT_LADCRATE : 0;
-ch->imask = ICH_GLOB_STA_PIINT;
-break;
-
-case 2: /* mic */
-KASSERT(dir == PCMDIR_REC, ("wrong direction"));
-ch->regbase = ICH_REG_MC_BASE;
-ch->spdreg = sc->hasvrm? AC97_REGEXT_MADCRATE : 0;
-ch->imask = ICH_GLOB_STA_MINT;
-break;
-
-default:
-return NULL;
-}
-
-ICH_UNLOCK(sc);
-if (sndbuf_alloc(ch->buffer, sc->dmat, sc->bufsz) != 0)
-return NULL;
-
-ICH_LOCK(sc);
-ich_wr(sc, ch->regbase + ICH_REG_X_BDBAR, (u_int32_t)(ch->desc_addr), 4);
-ICH_UNLOCK(sc);
+ struct sc_info *sc = devinfo;
+ struct sc_chinfo *ch;
+ unsigned int num;
+
+ ICH_LOCK(sc);
+ num = sc->chnum++;
+ ch = &sc->ch[num];
+ ch->num = num;
+ ch->buffer = b;
+ ch->channel = c;
+ ch->parent = sc;
+ ch->run = 0;
+ ch->dtbl = sc->dtbl + (ch->num * ICH_DTBL_LENGTH);
+ ch->desc_addr = sc->desc_addr +
+ (ch->num * ICH_DTBL_LENGTH * sizeof(struct ich_desc));
+ ch->blkcnt = sc->blkcnt;
+ ch->blksz = sc->bufsz / ch->blkcnt;
+
+ switch(ch->num) {
+ case 0: /* play */
+ KASSERT(dir == PCMDIR_PLAY, ("wrong direction"));
+ ch->regbase = ICH_REG_PO_BASE;
+ ch->spdreg = (sc->hasvra) ? AC97_REGEXT_FDACRATE : 0;
+ ch->imask = ICH_GLOB_STA_POINT;
+ break;
+
+ case 1: /* record */
+ KASSERT(dir == PCMDIR_REC, ("wrong direction"));
+ ch->regbase = ICH_REG_PI_BASE;
+ ch->spdreg = (sc->hasvra) ? AC97_REGEXT_LADCRATE : 0;
+ ch->imask = ICH_GLOB_STA_PIINT;
+ break;
+
+ case 2: /* mic */
+ KASSERT(dir == PCMDIR_REC, ("wrong direction"));
+ ch->regbase = ICH_REG_MC_BASE;
+ ch->spdreg = (sc->hasvrm) ? AC97_REGEXT_MADCRATE : 0;
+ ch->imask = ICH_GLOB_STA_MINT;
+ break;
+
+ default:
+ return (NULL);
+ }
+
+ if (sc->flags & ICH_FIXED_RATE)
+ ch->spdreg = 0;
+
+ ICH_UNLOCK(sc);
+ if (sndbuf_alloc(ch->buffer, sc->chan_dmat,
+ ((sc->flags & ICH_DMA_NOCACHE) ? BUS_DMA_NOCACHE : 0),
+ sc->bufsz) != 0)
+ return (NULL);
+
+ ICH_LOCK(sc);
+ ich_wr(sc, ch->regbase + ICH_REG_X_BDBAR, (uint32_t)(ch->desc_addr), 4);
+ ICH_UNLOCK(sc);
-return ch;
+ return (ch);
}
static int
-ichchan_setformat(kobj_t obj, void *data, u_int32_t format)
+ichchan_setformat(kobj_t obj, void *data, uint32_t format)
{
-return 0;
+
+ ICH_DEBUG(
+ struct sc_chinfo *ch = data;
+ struct sc_info *sc = ch->parent;
+ if (!(sc->flags & ICH_CALIBRATE_DONE))
+ device_printf(sc->dev,
+ "WARNING: %s() called before calibration!\n",
+ __func__);
+ );
+
+ return (0);
}
static int
-ichchan_setspeed(kobj_t obj, void *data, u_int32_t speed)
+ichchan_setspeed(kobj_t obj, void *data, uint32_t speed)
{
-struct sc_chinfo *ch = data;
-struct sc_info *sc = ch->parent;
-
-if (ch->spdreg) {
-int r, ac97rate;
+ struct sc_chinfo *ch = data;
+ struct sc_info *sc = ch->parent;
-ICH_LOCK(sc);
-if (sc->ac97rate <= 32000 || sc->ac97rate >= 64000)
-sc->ac97rate = 48000;
-ac97rate = sc->ac97rate;
-ICH_UNLOCK(sc);
-r = (speed * 48000) / ac97rate;
-/*
-* Cast the return value of ac97_setrate() to u_int so that
-* the math don't overflow into the negative range.
-*/
-ch->spd = ((u_int)ac97_setrate(sc->codec, ch->spdreg, r) *
-ac97rate) / 48000;
-} else {
-ch->spd = 48000;
-}
-return ch->spd;
+ ICH_DEBUG(
+ if (!(sc->flags & ICH_CALIBRATE_DONE))
+ device_printf(sc->dev,
+ "WARNING: %s() called before calibration!\n",
+ __func__);
+ );
+
+ if (ch->spdreg) {
+ int r, ac97rate;
+
+ ICH_LOCK(sc);
+ if (sc->ac97rate <= 32000 || sc->ac97rate >= 64000)
+ sc->ac97rate = 48000;
+ ac97rate = sc->ac97rate;
+ ICH_UNLOCK(sc);
+ r = (speed * 48000) / ac97rate;
+ /*
+ * Cast the return value of ac97_setrate() to uint64 so that
+ * the math don't overflow into the negative range.
+ */
+ ch->spd = ((uint64_t)ac97_setrate(sc->codec, ch->spdreg, r) *
+ ac97rate) / 48000;
+ } else {
+ ch->spd = 48000;
+ }
+ return (ch->spd);
}
static int
-ichchan_setblocksize(kobj_t obj, void *data, u_int32_t blocksize)
+ichchan_setblocksize(kobj_t obj, void *data, uint32_t blocksize)
{
-struct sc_chinfo *ch = data;
-struct sc_info *sc = ch->parent;
+ struct sc_chinfo *ch = data;
+ struct sc_info *sc = ch->parent;
-ch->blksz = blocksize;
-ich_filldtbl(ch);
-ICH_LOCK(sc);
-ich_wr(sc, ch->regbase + ICH_REG_X_LVI, ch->blkcnt - 1, 1);
-ICH_UNLOCK(sc);
+ ICH_DEBUG(
+ if (!(sc->flags & ICH_CALIBRATE_DONE))
+ device_printf(sc->dev,
+ "WARNING: %s() called before calibration!\n",
+ __func__);
+ );
+
+ if (sc->flags & ICH_HIGH_LATENCY)
+ blocksize = sndbuf_getmaxsize(ch->buffer) / ch->blkcnt;
+
+ if (blocksize < ICH_MIN_BLKSZ)
+ blocksize = ICH_MIN_BLKSZ;
+ blocksize &= ~(ICH_MIN_BLKSZ - 1);
+ ch->blksz = blocksize;
+ ich_filldtbl(ch);
+ ICH_LOCK(sc);
+ ich_wr(sc, ch->regbase + ICH_REG_X_LVI, ch->blkcnt - 1, 1);
+ ICH_UNLOCK(sc);
-return ch->blksz;
+ return (ch->blksz);
}
static int
ichchan_trigger(kobj_t obj, void *data, int go)
{
-struct sc_chinfo *ch = data;
-struct sc_info *sc = ch->parent;
+ struct sc_chinfo *ch = data;
+ struct sc_info *sc = ch->parent;
-switch (go) {
-case PCMTRIG_START:
-ch->run = 1;
-ICH_LOCK(sc);
-ich_wr(sc, ch->regbase + ICH_REG_X_BDBAR, (u_int32_t)(ch->desc_addr), 4);
-ich_wr(sc, ch->regbase + ICH_REG_X_CR, ICH_X_CR_RPBM | ICH_X_CR_LVBIE | ICH_X_CR_IOCE, 1);
-ICH_UNLOCK(sc);
-break;
-
-case PCMTRIG_ABORT:
-ICH_LOCK(sc);
-ich_resetchan(sc, ch->num);
-ICH_UNLOCK(sc);
-ch->run = 0;
-break;
-}
-return 0;
+ ICH_DEBUG(
+ if (!(sc->flags & ICH_CALIBRATE_DONE))
+ device_printf(sc->dev,
+ "WARNING: %s() called before calibration!\n",
+ __func__);
+ );
+
+ switch (go) {
+ case PCMTRIG_START:
+ ch->run = 1;
+ ICH_LOCK(sc);
+ ich_wr(sc, ch->regbase + ICH_REG_X_BDBAR, (uint32_t)(ch->desc_addr), 4);
+ ich_wr(sc, ch->regbase + ICH_REG_X_CR, ICH_X_CR_RPBM | ICH_X_CR_LVBIE | ICH_X_CR_IOCE, 1);
+ ICH_UNLOCK(sc);
+ break;
+ case PCMTRIG_STOP:
+ case PCMTRIG_ABORT:
+ ICH_LOCK(sc);
+ ich_resetchan(sc, ch->num);
+ ICH_UNLOCK(sc);
+ ch->run = 0;
+ break;
+ default:
+ break;
+ }
+ return (0);
}
static int
ichchan_getptr(kobj_t obj, void *data)
{
-struct sc_chinfo *ch = data;
-struct sc_info *sc = ch->parent;
-u_int32_t pos;
+ struct sc_chinfo *ch = data;
+ struct sc_info *sc = ch->parent;
+ uint32_t pos;
+
+ ICH_DEBUG(
+ if (!(sc->flags & ICH_CALIBRATE_DONE))
+ device_printf(sc->dev,
+ "WARNING: %s() called before calibration!\n",
+ __func__);
+ );
+
+ ICH_LOCK(sc);
+ ch->civ = ich_rd(sc, ch->regbase + ICH_REG_X_CIV, 1) % ch->blkcnt;
+ ICH_UNLOCK(sc);
-ICH_LOCK(sc);
-ch->civ = ich_rd(sc, ch->regbase + ICH_REG_X_CIV, 1) % ch->blkcnt;
-ICH_UNLOCK(sc);
+ pos = ch->civ * ch->blksz;
-pos = ch->civ * ch->blksz;
-
-return pos;
+ return (pos);
}
static struct pcmchan_caps *
ichchan_getcaps(kobj_t obj, void *data)
{
-struct sc_chinfo *ch = data;
+ struct sc_chinfo *ch = data;
+
+ ICH_DEBUG(
+ struct sc_info *sc = ch->parent;
+
+ if (!(sc->flags & ICH_CALIBRATE_DONE))
+ device_printf(ch->parent->dev,
+ "WARNING: %s() called before calibration!\n",
+ __func__);
+ );
-return ch->spdreg? &ich_vrcaps : &ich_caps;
+ return ((ch->spdreg) ? &ich_vrcaps : &ich_caps);
}
static kobj_method_t ichchan_methods[] = {
-KOBJMETHOD(channel_init, ichchan_init),
-KOBJMETHOD(channel_setformat, ichchan_setformat),
-KOBJMETHOD(channel_setspeed, ichchan_setspeed),
-KOBJMETHOD(channel_setblocksize, ichchan_setblocksize),
-KOBJMETHOD(channel_trigger, ichchan_trigger),
-KOBJMETHOD(channel_getptr, ichchan_getptr),
-KOBJMETHOD(channel_getcaps, ichchan_getcaps),
-{ 0, 0 }
+ KOBJMETHOD(channel_init, ichchan_init),
+ KOBJMETHOD(channel_setformat, ichchan_setformat),
+ KOBJMETHOD(channel_setspeed, ichchan_setspeed),
+ KOBJMETHOD(channel_setblocksize, ichchan_setblocksize),
+ KOBJMETHOD(channel_trigger, ichchan_trigger),
+ KOBJMETHOD(channel_getptr, ichchan_getptr),
+ KOBJMETHOD(channel_getcaps, ichchan_getcaps),
+ { 0, 0 }
};
CHANNEL_DECLARE(ichchan);
@@ -499,173 +593,220 @@
static void
ich_intr(void *p)
{
-struct sc_info *sc = (struct sc_info *)p;
-struct sc_chinfo *ch;
-u_int32_t cbi, lbi, lvi, st, gs;
-int i;
-
-ICH_LOCK(sc);
-gs = ich_rd(sc, ICH_REG_GLOB_STA, 4) & ICH_GLOB_STA_IMASK;
-if (gs & (ICH_GLOB_STA_PRES | ICH_GLOB_STA_SRES)) {
-/* Clear resume interrupt(s) - nothing doing with them */
-ich_wr(sc, ICH_REG_GLOB_STA, gs, 4);
-}
-gs &= ~(ICH_GLOB_STA_PRES | ICH_GLOB_STA_SRES);
-
-for (i = 0; i < 3; i++) {
-ch = &sc->ch[i];
-if ((ch->imask & gs) == 0)
-continue;
-gs &= ~ch->imask;
-st = ich_rd(sc, ch->regbase +
-(sc->swap_reg ? ICH_REG_X_PICB : ICH_REG_X_SR),
-2);
-st &= ICH_X_SR_FIFOE | ICH_X_SR_BCIS | ICH_X_SR_LVBCI;
-if (st & (ICH_X_SR_BCIS | ICH_X_SR_LVBCI)) {
-/* block complete - update buffer */
-if (ch->run) {
-ICH_UNLOCK(sc);
-chn_intr(ch->channel);
-ICH_LOCK(sc);
-}
-lvi = ich_rd(sc, ch->regbase + ICH_REG_X_LVI, 1);
-cbi = ch->civ % ch->blkcnt;
-if (cbi == 0)
-cbi = ch->blkcnt - 1;
-else
-cbi--;
-lbi = lvi % ch->blkcnt;
-if (cbi >= lbi)
-lvi += cbi - lbi;
-else
-lvi += cbi + ch->blkcnt - lbi;
-lvi %= ICH_DTBL_LENGTH;
-ich_wr(sc, ch->regbase + ICH_REG_X_LVI, lvi, 1);
-
-}
-/* clear status bit */
-ich_wr(sc, ch->regbase +
-(sc->swap_reg ? ICH_REG_X_PICB : ICH_REG_X_SR),
-st, 2);
-}
-ICH_UNLOCK(sc);
-if (gs != 0) {
-device_printf(sc->dev,
-"Unhandled interrupt, gs_intr = %xn", gs);
-}
+ struct sc_info *sc = (struct sc_info *)p;
+ struct sc_chinfo *ch;
+ uint32_t cbi, lbi, lvi, st, gs;
+ int i;
+
+ ICH_LOCK(sc);
+
+ ICH_DEBUG(
+ if (!(sc->flags & ICH_CALIBRATE_DONE))
+ device_printf(sc->dev,
+ "WARNING: %s() called before calibration!\n",
+ __func__);
+ );
+
+ gs = ich_rd(sc, ICH_REG_GLOB_STA, 4) & ICH_GLOB_STA_IMASK;
+ if (gs & (ICH_GLOB_STA_PRES | ICH_GLOB_STA_SRES)) {
+ /* Clear resume interrupt(s) - nothing doing with them */
+ ich_wr(sc, ICH_REG_GLOB_STA, gs, 4);
+ }
+ gs &= ~(ICH_GLOB_STA_PRES | ICH_GLOB_STA_SRES);
+
+ for (i = 0; i < 3; i++) {
+ ch = &sc->ch[i];
+ if ((ch->imask & gs) == 0)
+ continue;
+ gs &= ~ch->imask;
+ st = ich_rd(sc, ch->regbase +
+ ((sc->swap_reg) ? ICH_REG_X_PICB : ICH_REG_X_SR),
+ 2);
+ st &= ICH_X_SR_FIFOE | ICH_X_SR_BCIS | ICH_X_SR_LVBCI;
+ if (st & (ICH_X_SR_BCIS | ICH_X_SR_LVBCI)) {
+ /* block complete - update buffer */
+ if (ch->run) {
+ ICH_UNLOCK(sc);
+ chn_intr(ch->channel);
+ ICH_LOCK(sc);
+ }
+ lvi = ich_rd(sc, ch->regbase + ICH_REG_X_LVI, 1);
+ cbi = ch->civ % ch->blkcnt;
+ if (cbi == 0)
+ cbi = ch->blkcnt - 1;
+ else
+ cbi--;
+ lbi = lvi % ch->blkcnt;
+ if (cbi >= lbi)
+ lvi += cbi - lbi;
+ else
+ lvi += cbi + ch->blkcnt - lbi;
+ lvi %= ICH_DTBL_LENGTH;
+ ich_wr(sc, ch->regbase + ICH_REG_X_LVI, lvi, 1);
+
+ }
+ /* clear status bit */
+ ich_wr(sc, ch->regbase +
+ ((sc->swap_reg) ? ICH_REG_X_PICB : ICH_REG_X_SR),
+ st, 2);
+ }
+ ICH_UNLOCK(sc);
+ if (gs != 0) {
+ device_printf(sc->dev,
+ "Unhandled interrupt, gs_intr = %x\n", gs);
+ }
}
/* ------------------------------------------------------------------------- */
/* Sysctl to control ac97 speed (some boards appear to end up using
-* XTAL_IN rather than BIT_CLK for link timing).
-*/
+ * XTAL_IN rather than BIT_CLK for link timing).
+ */
static int
ich_initsys(struct sc_info* sc)
{
#ifdef SND_DYNSYSCTL
-SYSCTL_ADD_INT(snd_sysctl_tree(sc->dev),
-SYSCTL_CHILDREN(snd_sysctl_tree_top(sc->dev)),
-OID_AUTO, "ac97rate", CTLFLAG_RW,
-&sc->ac97rate, 48000,
-"AC97 link rate (default = 48000)");
+ /* XXX: this should move to a device specific sysctl "dev.pcm.X.yyy"
+ via device_get_sysctl_*() as discussed on multimedia@ in msg-id
+ <861wujij2q.fsf at xps.des.no> */
+ SYSCTL_ADD_INT(device_get_sysctl_ctx(sc->dev),
+ SYSCTL_CHILDREN(device_get_sysctl_tree(sc->dev)),
+ OID_AUTO, "ac97rate", CTLFLAG_RW,
+ &sc->ac97rate, 48000,
+ "AC97 link rate (default = 48000)");
#endif /* SND_DYNSYSCTL */
-return 0;
+ return (0);
}
-/* -------------------------------------------------------------------- */
-/* Calibrate card to determine the clock source. The source maybe a
-* function of the ac97 codec initialization code (to be investigated).
-*/
-
-static
-void ich_calibrate(void *arg)
+static void
+ich_setstatus(struct sc_info *sc)
{
-struct sc_info *sc;
-struct sc_chinfo *ch;
-struct timeval t1, t2;
-u_int8_t ociv, nciv;
-u_int32_t wait_us, actual_48k_rate, bytes;
-
-sc = (struct sc_info *)arg;
-ch = &sc->ch[1];
+ char status[SND_STATUSLEN];
-if (sc->use_intrhook)
-config_intrhook_disestablish(&sc->intrhook);
+ snprintf(status, SND_STATUSLEN,
+ "at io 0x%lx, 0x%lx irq %ld bufsz %u %s",
+ rman_get_start(sc->nambar), rman_get_start(sc->nabmbar),
+ rman_get_start(sc->irq), sc->bufsz,PCM_KLDSTRING(snd_ich));
-/*
-* Grab audio from input for fixed interval and compare how
-* much we actually get with what we expect. Interval needs
-* to be sufficiently short that no interrupts are
-* generated.
-*/
+ if (bootverbose && (sc->flags & ICH_DMA_NOCACHE))
+ device_printf(sc->dev,
+ "PCI Master abort workaround enabled\n");
-KASSERT(ch->regbase == ICH_REG_PI_BASE, ("wrong direction"));
-
-bytes = sndbuf_getsize(ch->buffer) / 2;
-ichchan_setblocksize(0, ch, bytes);
-
-/*
-* our data format is stereo, 16 bit so each sample is 4 bytes.
-* assuming we get 48000 samples per second, we get 192000 bytes/sec.
-* we're going to start recording with interrupts disabled and measure
-* the time taken for one block to complete. we know the block size,
-* we know the time in microseconds, we calculate the sample rate:
-*
-* actual_rate [bps] = bytes / (time [s] * 4)
-* actual_rate [bps] = (bytes * 1000000) / (time [us] * 4)
-* actual_rate [Hz] = (bytes * 250000) / time [us]
-*/
-
-/* prepare */
-ociv = ich_rd(sc, ch->regbase + ICH_REG_X_CIV, 1);
-nciv = ociv;
-ich_wr(sc, ch->regbase + ICH_REG_X_BDBAR, (u_int32_t)(ch->desc_addr), 4);
-
-/* start */
-microtime(&t1);
-ich_wr(sc, ch->regbase + ICH_REG_X_CR, ICH_X_CR_RPBM, 1);
-
-/* wait */
-while (nciv == ociv) {
-microtime(&t2);
-if (t2.tv_sec - t1.tv_sec > 1)
-break;
-nciv = ich_rd(sc, ch->regbase + ICH_REG_X_CIV, 1);
+ pcm_setstatus(sc->dev, status);
}
-microtime(&t2);
-
-/* stop */
-ich_wr(sc, ch->regbase + ICH_REG_X_CR, 0, 1);
-
-/* reset */
-DELAY(100);
-ich_wr(sc, ch->regbase + ICH_REG_X_CR, ICH_X_CR_RR, 1);
-/* turn time delta into us */
-wait_us = ((t2.tv_sec - t1.tv_sec) * 1000000) + t2.tv_usec - t1.tv_usec;
-
-if (nciv == ociv) {
-device_printf(sc->dev, "ac97 link rate calibration timed out after %d usn", wait_us);
-return;
-}
-
-actual_48k_rate = (bytes * 250000) / wait_us;
+/* -------------------------------------------------------------------- */
+/* Calibrate card to determine the clock source. The source maybe a
+ * function of the ac97 codec initialization code (to be investigated).
+ */
-if (actual_48k_rate < 47500 || actual_48k_rate > 48500) {
-sc->ac97rate = actual_48k_rate;
-} else {
-sc->ac97rate = 48000;
-}
+static void
+ich_calibrate(void *arg)
+{
+ struct sc_info *sc;
+ struct sc_chinfo *ch;
+ struct timeval t1, t2;
+ uint8_t ociv, nciv;
+ uint32_t wait_us, actual_48k_rate, oblkcnt;
+
+ sc = (struct sc_info *)arg;
+ ICH_LOCK(sc);
+ ch = &sc->ch[1];
+
+ if (sc->intrhook.ich_func != NULL) {
+ config_intrhook_disestablish(&sc->intrhook);
+ sc->intrhook.ich_func = NULL;
+ }
+
+ /*
+ * Grab audio from input for fixed interval and compare how
+ * much we actually get with what we expect. Interval needs
+ * to be sufficiently short that no interrupts are
+ * generated.
+ */
+
+ KASSERT(ch->regbase == ICH_REG_PI_BASE, ("wrong direction"));
+
+ oblkcnt = ch->blkcnt;
+ ch->blkcnt = 2;
+ sc->flags |= ICH_CALIBRATE_DONE;
+ ICH_UNLOCK(sc);
+ ichchan_setblocksize(0, ch, sndbuf_getmaxsize(ch->buffer) >> 1);
+ ICH_LOCK(sc);
+ sc->flags &= ~ICH_CALIBRATE_DONE;
+
+ /*
+ * our data format is stereo, 16 bit so each sample is 4 bytes.
+ * assuming we get 48000 samples per second, we get 192000 bytes/sec.
+ * we're going to start recording with interrupts disabled and measure
+ * the time taken for one block to complete. we know the block size,
+ * we know the time in microseconds, we calculate the sample rate:
+ *
+ * actual_rate [bps] = bytes / (time [s] * 4)
+ * actual_rate [bps] = (bytes * 1000000) / (time [us] * 4)
+ * actual_rate [Hz] = (bytes * 250000) / time [us]
+ */
+
+ /* prepare */
+ ociv = ich_rd(sc, ch->regbase + ICH_REG_X_CIV, 1);
+ nciv = ociv;
+ ich_wr(sc, ch->regbase + ICH_REG_X_BDBAR, (uint32_t)(ch->desc_addr), 4);
+
+ /* start */
+ microtime(&t1);
+ ich_wr(sc, ch->regbase + ICH_REG_X_CR, ICH_X_CR_RPBM, 1);
+
+ /* wait */
+ do {
+ microtime(&t2);
+ if (t2.tv_sec - t1.tv_sec > 1)
+ break;
+ nciv = ich_rd(sc, ch->regbase + ICH_REG_X_CIV, 1);
+ } while (nciv == ociv);
+
+ /* stop */
+ ich_wr(sc, ch->regbase + ICH_REG_X_CR, 0, 1);
+
+ /* reset */
+ DELAY(100);
+ ich_wr(sc, ch->regbase + ICH_REG_X_CR, ICH_X_CR_RR, 1);
+ ch->blkcnt = oblkcnt;
+
+ /* turn time delta into us */
+ wait_us = ((t2.tv_sec - t1.tv_sec) * 1000000) + t2.tv_usec - t1.tv_usec;
+
+ if (nciv == ociv) {
+ device_printf(sc->dev, "ac97 link rate calibration timed out after %d us\n", wait_us);
+ sc->flags |= ICH_CALIBRATE_DONE;
+ ICH_UNLOCK(sc);
+ ich_setstatus(sc);
+ return;
+ }
+
+ /* Just in case the timecounter screwed. It is possible, really. */
+ if (wait_us > 0)
+ actual_48k_rate = ((uint64_t)ch->blksz * 250000) / wait_us;
+ else
+ actual_48k_rate = 48000;
+
+ if (actual_48k_rate < 47500 || actual_48k_rate > 48500) {
+ sc->ac97rate = actual_48k_rate;
+ } else {
+ sc->ac97rate = 48000;
+ }
+
+ if (bootverbose || sc->ac97rate != 48000) {
+ device_printf(sc->dev, "measured ac97 link rate at %d Hz", actual_48k_rate);
+ if (sc->ac97rate != actual_48k_rate)
+ printf(", will use %d Hz", sc->ac97rate);
+ printf("\n");
+ }
+ sc->flags |= ICH_CALIBRATE_DONE;
+ ICH_UNLOCK(sc);
-if (bootverbose || sc->ac97rate != 48000) {
-device_printf(sc->dev, "measured ac97 link rate at %d Hz", actual_48k_rate);
-if (sc->ac97rate != actual_48k_rate)
-printf(", will use %d Hz", sc->ac97rate);
-printf("n");
-}
+ ich_setstatus(sc);
-return;
+ return;
}
/* -------------------------------------------------------------------- */
@@ -674,372 +815,426 @@
static void
ich_setmap(void *arg, bus_dma_segment_t *segs, int nseg, int error)
{
-struct sc_info *sc = (struct sc_info *)arg;
-sc->desc_addr = segs->ds_addr;
-return;
+ struct sc_info *sc = (struct sc_info *)arg;
+ sc->desc_addr = segs->ds_addr;
+ return;
}
static int
ich_init(struct sc_info *sc)
{
-u_int32_t stat;
+ uint32_t stat;
-ich_wr(sc, ICH_REG_GLOB_CNT, ICH_GLOB_CTL_COLD, 4);
-DELAY(600000);
-stat = ich_rd(sc, ICH_REG_GLOB_STA, 4);
-
-if ((stat & ICH_GLOB_STA_PCR) == 0) {
-/* ICH4/ICH5 may fail when busmastering is enabled. Continue */
-if (sc->vendor == INTEL_VENDORID && (
-sc->devid == INTEL_82801DB || sc->devid == INTEL_82801EB ||
-sc->devid == INTEL_6300ESB || sc->devid == INTEL_82801FB ||
-sc->devid == INTEL_82801GB)) {
-sc->flags |= IGNORE_PCR;
-device_printf(sc->dev, "primary codec not ready!n");
-}
-}
+ ich_wr(sc, ICH_REG_GLOB_CNT, ICH_GLOB_CTL_COLD, 4);
+ DELAY(600000);
+ stat = ich_rd(sc, ICH_REG_GLOB_STA, 4);
+
+ if ((stat & ICH_GLOB_STA_PCR) == 0) {
+ /* ICH4/ICH5 may fail when busmastering is enabled. Continue */
+ if (sc->vendor == INTEL_VENDORID && (
+ sc->devid == INTEL_82801DB || sc->devid == INTEL_82801EB ||
+ sc->devid == INTEL_6300ESB || sc->devid == INTEL_82801FB ||
+ sc->devid == INTEL_82801GB)) {
+ sc->flags |= ICH_IGNORE_PCR;
+ device_printf(sc->dev, "primary codec not ready!\n");
+ }
+ }
#if 0
-ich_wr(sc, ICH_REG_GLOB_CNT, ICH_GLOB_CTL_COLD | ICH_GLOB_CTL_PRES, 4);
+ ich_wr(sc, ICH_REG_GLOB_CNT, ICH_GLOB_CTL_COLD | ICH_GLOB_CTL_PRES, 4);
#else
-ich_wr(sc, ICH_REG_GLOB_CNT, ICH_GLOB_CTL_COLD, 4);
+ ich_wr(sc, ICH_REG_GLOB_CNT, ICH_GLOB_CTL_COLD, 4);
#endif
-if (ich_resetchan(sc, 0) || ich_resetchan(sc, 1))
-return ENXIO;
-if (sc->hasmic && ich_resetchan(sc, 2))
-return ENXIO;
+ if (ich_resetchan(sc, 0) || ich_resetchan(sc, 1))
+ return (ENXIO);
+ if (sc->hasmic && ich_resetchan(sc, 2))
+ return (ENXIO);
-return 0;
+ return (0);
}
static int
ich_pci_probe(device_t dev)
{
-int i;
-uint16_t devid, vendor;
+ int i;
+ uint16_t devid, vendor;
-vendor = pci_get_vendor(dev);
-devid = pci_get_device(dev);
-for (i = 0; i < sizeof(ich_devs)/sizeof(ich_devs[0]); i++) {
-if (vendor == ich_devs[i].vendor &&
-devid == ich_devs[i].devid) {
-device_set_desc(dev, ich_devs[i].name);
-/* allow a better driver to override us */
-if ((ich_devs[i].options & PROBE_LOW) != 0)
-return (BUS_PROBE_LOW_PRIORITY);
-return (BUS_PROBE_DEFAULT);
-}
-}
-return (ENXIO);
+ vendor = pci_get_vendor(dev);
+ devid = pci_get_device(dev);
+ for (i = 0; i < sizeof(ich_devs)/sizeof(ich_devs[0]); i++) {
+ if (vendor == ich_devs[i].vendor &&
+ devid == ich_devs[i].devid) {
+ device_set_desc(dev, ich_devs[i].name);
+ /* allow a better driver to override us */
+ if ((ich_devs[i].options & PROBE_LOW) != 0)
+ return (BUS_PROBE_LOW_PRIORITY);
+ return (BUS_PROBE_DEFAULT);
+ }
+ }
+ return (ENXIO);
}
static int
ich_pci_attach(device_t dev)
{
-uint32_t subdev;
-u_int16_t extcaps;
-uint16_t devid, vendor;
-struct sc_info *sc;
-char status[SND_STATUSLEN];
-
-if ((sc = malloc(sizeof(*sc), M_DEVBUF, M_NOWAIT | M_ZERO)) == NULL) {
-device_printf(dev, "cannot allocate softcn");
-return ENXIO;
-}
-
-sc->ich_lock = snd_mtxcreate(device_get_nameunit(dev), "sound softc");
-sc->dev = dev;
-
-vendor = sc->vendor = pci_get_vendor(dev);
-devid = sc->devid = pci_get_device(dev);
-subdev = (pci_get_subdevice(dev) << 16) | pci_get_subvendor(dev);
-/*
-* The SiS 7012 register set isn't quite like the standard ich.
-* There really should be a general "quirks" mechanism.
-*/
-if (vendor == SIS_VENDORID && devid == SIS_7012) {
-sc->swap_reg = 1;
-sc->sample_size = 1;
-} else {
-sc->swap_reg = 0;
-sc->sample_size = 2;
-}
-
-/*
-* Enable bus master. On ich4/5 this may prevent the detection of
-* the primary codec becoming ready in ich_init().
-*/
-pci_enable_busmaster(dev);
-
-/*
-* By default, ich4 has NAMBAR and NABMBAR i/o spaces as
-* read-only. Need to enable "legacy support", by poking into
-* pci config space. The driver should use MMBAR and MBBAR,
-* but doing so will mess things up here. ich4 has enough new
-* features it warrants it's own driver.
-*/
-if (vendor == INTEL_VENDORID && (devid == INTEL_82801DB ||
-devid == INTEL_82801EB || devid == INTEL_6300ESB ||
-devid == INTEL_82801FB || devid == INTEL_82801GB)) {
-sc->nambarid = PCIR_MMBAR;
-sc->nabmbarid = PCIR_MBBAR;
-sc->regtype = SYS_RES_MEMORY;
-pci_write_config(dev, PCIR_ICH_LEGACY, ICH_LEGACY_ENABLE, 1);
-} else {
-sc->nambarid = PCIR_NAMBAR;
-sc->nabmbarid = PCIR_NABMBAR;
-sc->regtype = SYS_RES_IOPORT;
-}
-
-sc->nambar = bus_alloc_resource_any(dev, sc->regtype,
-&sc->nambarid, RF_ACTIVE);
-sc->nabmbar = bus_alloc_resource_any(dev, sc->regtype,
-&sc->nabmbarid, RF_ACTIVE);
-
-if (!sc->nambar || !sc->nabmbar) {
-device_printf(dev, "unable to map IO port spacen");
-goto bad;
-}
-
-sc->nambart = rman_get_bustag(sc->nambar);
-sc->nambarh = rman_get_bushandle(sc->nambar);
-sc->nabmbart = rman_get_bustag(sc->nabmbar);
-sc->nabmbarh = rman_get_bushandle(sc->nabmbar);
-
-sc->bufsz = pcm_getbuffersize(dev, 4096, ICH_DEFAULT_BUFSZ, ICH_MAX_BUFSZ);
-if (bus_dma_tag_create(NULL, 8, 0, BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR,
-NULL, NULL, sc->bufsz, 1, 0x3ffff, 0,
-NULL, NULL, &sc->dmat) != 0) {
-device_printf(dev, "unable to create dma tagn");
-goto bad;
-}
-
-sc->irqid = 0;
-sc->irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &sc->irqid,
-RF_ACTIVE | RF_SHAREABLE);
-if (!sc->irq || snd_setup_intr(dev, sc->irq, INTR_MPSAFE, ich_intr, sc, &sc->ih)) {
-device_printf(dev, "unable to map interruptn");
-goto bad;
-}
-
-if (ich_init(sc)) {
-device_printf(dev, "unable to initialize the cardn");
-goto bad;
-}
-
-if (bus_dmamem_alloc(sc->dmat, (void **)&sc->dtbl,
-BUS_DMA_NOWAIT, &sc->dtmap))
-goto bad;
-
-if (bus_dmamap_load(sc->dmat, sc->dtmap, sc->dtbl,
-sizeof(struct ich_desc) * ICH_DTBL_LENGTH * 3,
-ich_setmap, sc, 0))
-goto bad;
-
-sc->codec = AC97_CREATE(dev, sc, ich_ac97);
-if (sc->codec == NULL)
-goto bad;
-
-/*
-* Turn on inverted external amplifier sense flags for few
-* 'special' boards.
-*/
-switch (subdev) {
-case 0x202f161f: /* Gateway 7326GZ */
-case 0x203a161f: /* Gateway 4028GZ */
-case 0x204c161f: /* Kvazar-Micro Senator 3592XT */
-case 0x8144104d: /* Sony VAIO PCG-TR* */
-case 0x8197104d: /* Sony S1XP */
-case 0x81c0104d: /* Sony VAIO type T */
-case 0x81c5104d: /* Sony VAIO VGN B1VP/B1XP */
-case 0x3089103c: /* Compaq Presario B3800 */
-case 0x309a103c: /* HP Compaq nx4300 */
-case 0x82131033: /* NEC VersaPro VJ10F/BH */
-case 0x82be1033: /* NEC VersaPro VJ12F/CH */
-ac97_setflags(sc->codec, ac97_getflags(sc->codec) | AC97_F_EAPD_INV);
-break;
-default:
-break;
-}
-
-mixer_init(dev, ac97_getmixerclass(), sc->codec);
-
-/* check and set VRA function */
-extcaps = ac97_getextcaps(sc->codec);
-sc->hasvra = extcaps & AC97_EXTCAP_VRA;
-sc->hasvrm = extcaps & AC97_EXTCAP_VRM;
-sc->hasmic = ac97_getcaps(sc->codec) & AC97_CAP_MICCHANNEL;
-ac97_setextmode(sc->codec, sc->hasvra | sc->hasvrm);
-
-if (pcm_register(dev, sc, 1, sc->hasmic? 2 : 1))
-goto bad;
-
-pcm_addchan(dev, PCMDIR_PLAY, &ichchan_class, sc); /* play */
-pcm_addchan(dev, PCMDIR_REC, &ichchan_class, sc); /* record */
-if (sc->hasmic)
-pcm_addchan(dev, PCMDIR_REC, &ichchan_class, sc); /* record mic */
-
-snprintf(status, SND_STATUSLEN, "at io 0x%lx, 0x%lx irq %ld bufsz %u %s",
-rman_get_start(sc->nambar), rman_get_start(sc->nabmbar), rman_get_start(sc->irq), sc->bufsz,PCM_KLDSTRING(snd_ich));
-
-pcm_setstatus(dev, status);
-
-ich_initsys(sc);
-
-sc->intrhook.ich_func = ich_calibrate;
-sc->intrhook.ich_arg = sc;
-sc->use_intrhook = 1;
-if (config_intrhook_establish(&sc->intrhook) != 0) {
-device_printf(dev, "Cannot establish calibration hook, will calibrate nown");
-sc->use_intrhook = 0;
-ich_calibrate(sc);
-}
+ uint32_t subdev;
+ uint16_t extcaps;
+ uint16_t devid, vendor;
+ struct sc_info *sc;
+ int i;
+
+ sc = malloc(sizeof(*sc), M_DEVBUF, M_WAITOK | M_ZERO);
+ sc->ich_lock = snd_mtxcreate(device_get_nameunit(dev), "snd_ich softc");
+ sc->dev = dev;
+
+ vendor = sc->vendor = pci_get_vendor(dev);
+ devid = sc->devid = pci_get_device(dev);
+ subdev = (pci_get_subdevice(dev) << 16) | pci_get_subvendor(dev);
+ /*
+ * The SiS 7012 register set isn't quite like the standard ich.
+ * There really should be a general "quirks" mechanism.
+ */
+ if (vendor == SIS_VENDORID && devid == SIS_7012) {
+ sc->swap_reg = 1;
+ sc->sample_size = 1;
+ } else {
+ sc->swap_reg = 0;
+ sc->sample_size = 2;
+ }
+
+ /*
+ * Intel 440MX Errata #36
+ * - AC97 Soft Audio and Soft Modem Master Abort Errata
+ *
+ * http://www.intel.com/design/chipsets/specupdt/245051.htm
+ */
+ if (vendor == INTEL_VENDORID && devid == INTEL_82440MX)
+ sc->flags |= ICH_DMA_NOCACHE;
+
+ /*
+ * Enable bus master. On ich4/5 this may prevent the detection of
+ * the primary codec becoming ready in ich_init().
+ */
+ pci_enable_busmaster(dev);
+
+ /*
+ * By default, ich4 has NAMBAR and NABMBAR i/o spaces as
+ * read-only. Need to enable "legacy support", by poking into
+ * pci config space. The driver should use MMBAR and MBBAR,
+ * but doing so will mess things up here. ich4 has enough new
+ * features it warrants it's own driver.
+ */
+ if (vendor == INTEL_VENDORID && (devid == INTEL_82801DB ||
+ devid == INTEL_82801EB || devid == INTEL_6300ESB ||
+ devid == INTEL_82801FB || devid == INTEL_82801GB)) {
+ sc->nambarid = PCIR_MMBAR;
+ sc->nabmbarid = PCIR_MBBAR;
+ sc->regtype = SYS_RES_MEMORY;
+ pci_write_config(dev, PCIR_ICH_LEGACY, ICH_LEGACY_ENABLE, 1);
+ } else {
+ sc->nambarid = PCIR_NAMBAR;
+ sc->nabmbarid = PCIR_NABMBAR;
+ sc->regtype = SYS_RES_IOPORT;
+ }
+
+ sc->nambar = bus_alloc_resource_any(dev, sc->regtype,
+ &sc->nambarid, RF_ACTIVE);
+ sc->nabmbar = bus_alloc_resource_any(dev, sc->regtype,
+ &sc->nabmbarid, RF_ACTIVE);
+
+ if (!sc->nambar || !sc->nabmbar) {
+ device_printf(dev, "unable to map IO port space\n");
+ goto bad;
+ }
+
+ sc->nambart = rman_get_bustag(sc->nambar);
+ sc->nambarh = rman_get_bushandle(sc->nambar);
+ sc->nabmbart = rman_get_bustag(sc->nabmbar);
+ sc->nabmbarh = rman_get_bushandle(sc->nabmbar);
+
+ sc->bufsz = pcm_getbuffersize(dev,
+ ICH_MIN_BUFSZ, ICH_DEFAULT_BUFSZ, ICH_MAX_BUFSZ);
+
+ if (resource_int_value(device_get_name(dev),
+ device_get_unit(dev), "blocksize", &i) == 0 && i > 0) {
+ sc->blkcnt = sc->bufsz / i;
+ i = 0;
+ while (sc->blkcnt >> i)
+ i++;
+ sc->blkcnt = 1 << (i - 1);
+ if (sc->blkcnt < ICH_MIN_BLKCNT)
+ sc->blkcnt = ICH_MIN_BLKCNT;
+ else if (sc->blkcnt > ICH_MAX_BLKCNT)
+ sc->blkcnt = ICH_MAX_BLKCNT;
+ } else
+ sc->blkcnt = ICH_DEFAULT_BLKCNT;
+
+ if (resource_int_value(device_get_name(dev),
+ device_get_unit(dev), "highlatency", &i) == 0 && i != 0) {
+ sc->flags |= ICH_HIGH_LATENCY;
+ sc->blkcnt = ICH_MIN_BLKCNT;
+ }
+
+ if (resource_int_value(device_get_name(dev),
+ device_get_unit(dev), "fixedrate", &i) == 0 && i != 0)
+ sc->flags |= ICH_FIXED_RATE;
+
+ if (resource_int_value(device_get_name(dev),
+ device_get_unit(dev), "micchannel_enabled", &i) == 0 && i != 0)
+ sc->hasmic = 1;
+
+ sc->irqid = 0;
+ sc->irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &sc->irqid,
+ RF_ACTIVE | RF_SHAREABLE);
+ if (!sc->irq || snd_setup_intr(dev, sc->irq, INTR_MPSAFE, ich_intr,
+ sc, &sc->ih)) {
+ device_printf(dev, "unable to map interrupt\n");
+ goto bad;
+ }
+
+ if (ich_init(sc)) {
+ device_printf(dev, "unable to initialize the card\n");
+ goto bad;
+ }
+
+ sc->codec = AC97_CREATE(dev, sc, ich_ac97);
+ if (sc->codec == NULL)
+ goto bad;
+
+ /*
+ * Turn on inverted external amplifier sense flags for few
+ * 'special' boards.
+ */
+ switch (subdev) {
+ case 0x202f161f: /* Gateway 7326GZ */
+ case 0x203a161f: /* Gateway 4028GZ */
+ case 0x204c161f: /* Kvazar-Micro Senator 3592XT */
+ case 0x8144104d: /* Sony VAIO PCG-TR* */
+ case 0x8197104d: /* Sony S1XP */
+ case 0x81c0104d: /* Sony VAIO type T */
+ case 0x81c5104d: /* Sony VAIO VGN B1VP/B1XP */
+ case 0x3089103c: /* Compaq Presario B3800 */
+ case 0x309a103c: /* HP Compaq nx4300 */
+ case 0x82131033: /* NEC VersaPro VJ10F/BH */
+ case 0x82be1033: /* NEC VersaPro VJ12F/CH */
+ ac97_setflags(sc->codec, ac97_getflags(sc->codec) | AC97_F_EAPD_INV);
+ break;
+ default:
+ break;
+ }
+
+ mixer_init(dev, ac97_getmixerclass(), sc->codec);
+
+ /* check and set VRA function */
+ extcaps = ac97_getextcaps(sc->codec);
+ sc->hasvra = extcaps & AC97_EXTCAP_VRA;
+ sc->hasvrm = extcaps & AC97_EXTCAP_VRM;
+ sc->hasmic = (sc->hasmic != 0 &&
+ (ac97_getcaps(sc->codec) & AC97_CAP_MICCHANNEL)) ? 1 : 0;
+ ac97_setextmode(sc->codec, sc->hasvra | sc->hasvrm);
+
+ sc->dtbl_size = sizeof(struct ich_desc) * ICH_DTBL_LENGTH *
+ ((sc->hasmic) ? 3 : 2);
+
+ /* BDL tag */
+ if (bus_dma_tag_create(bus_get_dma_tag(dev), 8, 0,
+ BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL,
+ sc->dtbl_size, 1, 0x3ffff, 0, NULL, NULL, &sc->dmat) != 0) {
+ device_printf(dev, "unable to create dma tag\n");
+ goto bad;
+ }
+
+ /* PCM channel tag */
+ if (bus_dma_tag_create(bus_get_dma_tag(dev), ICH_MIN_BLKSZ, 0,
+ BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL,
+ sc->bufsz, 1, 0x3ffff, 0, NULL, NULL, &sc->chan_dmat) != 0) {
+ device_printf(dev, "unable to create dma tag\n");
+ goto bad;
+ }
+
+ if (bus_dmamem_alloc(sc->dmat, (void **)&sc->dtbl, BUS_DMA_NOWAIT |
+ ((sc->flags & ICH_DMA_NOCACHE) ? BUS_DMA_NOCACHE : 0),
+ &sc->dtmap))
+ goto bad;
+
+ if (bus_dmamap_load(sc->dmat, sc->dtmap, sc->dtbl, sc->dtbl_size,
+ ich_setmap, sc, 0))
+ goto bad;
+
+ if (pcm_register(dev, sc, 1, (sc->hasmic) ? 2 : 1))
+ goto bad;
+
+ pcm_addchan(dev, PCMDIR_PLAY, &ichchan_class, sc); /* play */
+ pcm_addchan(dev, PCMDIR_REC, &ichchan_class, sc); /* record */
+ if (sc->hasmic)
+ pcm_addchan(dev, PCMDIR_REC, &ichchan_class, sc); /* record mic */
+
+ if (sc->flags & ICH_FIXED_RATE) {
+ sc->flags |= ICH_CALIBRATE_DONE;
+ ich_setstatus(sc);
+ } else {
+ ich_initsys(sc);
+
+ sc->intrhook.ich_func = ich_calibrate;
+ sc->intrhook.ich_arg = sc;
+ if (cold == 0 ||
+ config_intrhook_establish(&sc->intrhook) != 0) {
+ sc->intrhook.ich_func = NULL;
+ ich_calibrate(sc);
+ }
+ }
-return 0;
+ return (0);
bad:
-if (sc->codec)
-ac97_destroy(sc->codec);
-if (sc->ih)
-bus_teardown_intr(dev, sc->irq, sc->ih);
-if (sc->irq)
-bus_release_resource(dev, SYS_RES_IRQ, sc->irqid, sc->irq);
-if (sc->nambar)
-bus_release_resource(dev, sc->regtype,
-sc->nambarid, sc->nambar);
-if (sc->nabmbar)
-bus_release_resource(dev, sc->regtype,
-sc->nabmbarid, sc->nabmbar);
-if (sc->dtmap)
-bus_dmamap_unload(sc->dmat, sc->dtmap);
-if (sc->dmat)
-bus_dma_tag_destroy(sc->dmat);
-if (sc->ich_lock)
-snd_mtxfree(sc->ich_lock);
-free(sc, M_DEVBUF);
-return ENXIO;
+ if (sc->codec)
+ ac97_destroy(sc->codec);
+ if (sc->ih)
+ bus_teardown_intr(dev, sc->irq, sc->ih);
+ if (sc->irq)
+ bus_release_resource(dev, SYS_RES_IRQ, sc->irqid, sc->irq);
+ if (sc->nambar)
+ bus_release_resource(dev, sc->regtype,
+ sc->nambarid, sc->nambar);
+ if (sc->nabmbar)
+ bus_release_resource(dev, sc->regtype,
+ sc->nabmbarid, sc->nabmbar);
+ if (sc->dtmap)
+ bus_dmamap_unload(sc->dmat, sc->dtmap);
+ if (sc->dtbl)
+ bus_dmamem_free(sc->dmat, sc->dtbl, sc->dtmap);
+ if (sc->chan_dmat)
+ bus_dma_tag_destroy(sc->chan_dmat);
+ if (sc->dmat)
+ bus_dma_tag_destroy(sc->dmat);
+ if (sc->ich_lock)
+ snd_mtxfree(sc->ich_lock);
+ free(sc, M_DEVBUF);
+ return (ENXIO);
}
static int
ich_pci_detach(device_t dev)
{
-struct sc_info *sc;
-int r;
+ struct sc_info *sc;
+ int r;
-r = pcm_unregister(dev);
-if (r)
-return r;
-sc = pcm_getdevinfo(dev);
-
-bus_teardown_intr(dev, sc->irq, sc->ih);
-bus_release_resource(dev, SYS_RES_IRQ, sc->irqid, sc->irq);
-bus_release_resource(dev, sc->regtype, sc->nambarid, sc->nambar);
-bus_release_resource(dev, sc->regtype, sc->nabmbarid, sc->nabmbar);
-bus_dmamap_unload(sc->dmat, sc->dtmap);
-bus_dma_tag_destroy(sc->dmat);
-snd_mtxfree(sc->ich_lock);
-free(sc, M_DEVBUF);
-return 0;
+ r = pcm_unregister(dev);
+ if (r)
+ return (r);
+ sc = pcm_getdevinfo(dev);
+
+ bus_teardown_intr(dev, sc->irq, sc->ih);
+ bus_release_resource(dev, SYS_RES_IRQ, sc->irqid, sc->irq);
+ bus_release_resource(dev, sc->regtype, sc->nambarid, sc->nambar);
+ bus_release_resource(dev, sc->regtype, sc->nabmbarid, sc->nabmbar);
+ bus_dmamap_unload(sc->dmat, sc->dtmap);
+ bus_dmamem_free(sc->dmat, sc->dtbl, sc->dtmap);
+ bus_dma_tag_destroy(sc->chan_dmat);
+ bus_dma_tag_destroy(sc->dmat);
+ snd_mtxfree(sc->ich_lock);
+ free(sc, M_DEVBUF);
+ return (0);
}
static void
ich_pci_codec_reset(struct sc_info *sc)
{
-int i;
-uint32_t control;
+ int i;
+ uint32_t control;
-control = ich_rd(sc, ICH_REG_GLOB_CNT, 4);
-control &= ~(ICH_GLOB_CTL_SHUT);
-control |= (control & ICH_GLOB_CTL_COLD) ?
-ICH_GLOB_CTL_WARM : ICH_GLOB_CTL_COLD;
-ich_wr(sc, ICH_REG_GLOB_CNT, control, 4);
-
-for (i = 500000; i; i--) {
-if (ich_rd(sc, ICH_REG_GLOB_STA, 4) & ICH_GLOB_STA_PCR)
-break; /* or ICH_SCR? */
-DELAY(1);
-}
+ control = ich_rd(sc, ICH_REG_GLOB_CNT, 4);
+ control &= ~(ICH_GLOB_CTL_SHUT);
+ control |= (control & ICH_GLOB_CTL_COLD) ?
+ ICH_GLOB_CTL_WARM : ICH_GLOB_CTL_COLD;
+ ich_wr(sc, ICH_REG_GLOB_CNT, control, 4);
+
+ for (i = 500000; i; i--) {
+ if (ich_rd(sc, ICH_REG_GLOB_STA, 4) & ICH_GLOB_STA_PCR)
+ break; /* or ICH_SCR? */
+ DELAY(1);
+ }
-if (i <= 0)
-printf("%s: time outn", __func__);
+ if (i <= 0)
+ printf("%s: time out\n", __func__);
}
static int
ich_pci_suspend(device_t dev)
{
-struct sc_info *sc;
-int i;
+ struct sc_info *sc;
+ int i;
-sc = pcm_getdevinfo(dev);
-ICH_LOCK(sc);
-for (i = 0 ; i < 3; i++) {
-sc->ch[i].run_save = sc->ch[i].run;
-if (sc->ch[i].run) {
-ICH_UNLOCK(sc);
-ichchan_trigger(0, &sc->ch[i], PCMTRIG_ABORT);
-ICH_LOCK(sc);
-}
-}
-ICH_UNLOCK(sc);
-return 0;
+ sc = pcm_getdevinfo(dev);
+ ICH_LOCK(sc);
+ for (i = 0 ; i < 3; i++) {
+ sc->ch[i].run_save = sc->ch[i].run;
+ if (sc->ch[i].run) {
+ ICH_UNLOCK(sc);
+ ichchan_trigger(0, &sc->ch[i], PCMTRIG_ABORT);
+ ICH_LOCK(sc);
+ }
+ }
+ ICH_UNLOCK(sc);
+ return (0);
}
static int
ich_pci_resume(device_t dev)
{
-struct sc_info *sc;
-int i;
+ struct sc_info *sc;
+ int i;
-sc = pcm_getdevinfo(dev);
+ sc = pcm_getdevinfo(dev);
-if (sc->regtype == SYS_RES_IOPORT)
-pci_enable_io(dev, SYS_RES_IOPORT);
-else
-pci_enable_io(dev, SYS_RES_MEMORY);
-pci_enable_busmaster(dev);
-
-ICH_LOCK(sc);
-/* Reinit audio device */
-if (ich_init(sc) == -1) {
-device_printf(dev, "unable to reinitialize the cardn");
-ICH_UNLOCK(sc);
-return ENXIO;
-}
-/* Reinit mixer */
-ich_pci_codec_reset(sc);
-ICH_UNLOCK(sc);
-ac97_setextmode(sc->codec, sc->hasvra | sc->hasvrm);
-if (mixer_reinit(dev) == -1) {
-device_printf(dev, "unable to reinitialize the mixern");
-return ENXIO;
-}
-/* Re-start DMA engines */
-for (i = 0 ; i < 3; i++) {
-struct sc_chinfo *ch = &sc->ch[i];
-if (sc->ch[i].run_save) {
-ichchan_setblocksize(0, ch, ch->blksz);
-ichchan_setspeed(0, ch, ch->spd);
-ichchan_trigger(0, ch, PCMTRIG_START);
-}
-}
-return 0;
+ if (sc->regtype == SYS_RES_IOPORT)
+ pci_enable_io(dev, SYS_RES_IOPORT);
+ else
+ pci_enable_io(dev, SYS_RES_MEMORY);
+ pci_enable_busmaster(dev);
+
+ ICH_LOCK(sc);
+ /* Reinit audio device */
+ if (ich_init(sc) == -1) {
+ device_printf(dev, "unable to reinitialize the card\n");
+ ICH_UNLOCK(sc);
+ return (ENXIO);
+ }
+ /* Reinit mixer */
+ ich_pci_codec_reset(sc);
+ ICH_UNLOCK(sc);
+ ac97_setextmode(sc->codec, sc->hasvra | sc->hasvrm);
+ if (mixer_reinit(dev) == -1) {
+ device_printf(dev, "unable to reinitialize the mixer\n");
+ return (ENXIO);
+ }
+ /* Re-start DMA engines */
+ for (i = 0 ; i < 3; i++) {
+ struct sc_chinfo *ch = &sc->ch[i];
+ if (sc->ch[i].run_save) {
+ ichchan_setblocksize(0, ch, ch->blksz);
+ ichchan_setspeed(0, ch, ch->spd);
+ ichchan_trigger(0, ch, PCMTRIG_START);
+ }
+ }
+ return (0);
}
static device_method_t ich_methods[] = {
-/* Device interface */
-DEVMETHOD(device_probe, ich_pci_probe),
-DEVMETHOD(device_attach, ich_pci_attach),
-DEVMETHOD(device_detach, ich_pci_detach),
-DEVMETHOD(device_suspend, ich_pci_suspend),
-DEVMETHOD(device_resume, ich_pci_resume),
-{ 0, 0 }
+ /* Device interface */
+ DEVMETHOD(device_probe, ich_pci_probe),
+ DEVMETHOD(device_attach, ich_pci_attach),
+ DEVMETHOD(device_detach, ich_pci_detach),
+ DEVMETHOD(device_suspend, ich_pci_suspend),
+ DEVMETHOD(device_resume, ich_pci_resume),
+ { 0, 0 }
};
static driver_t ich_driver = {
-"pcm",
-ich_methods,
-PCM_SOFTC_SIZE,
+ "pcm",
+ ich_methods,
+ PCM_SOFTC_SIZE,
};
DRIVER_MODULE(snd_ich, pci, ich_driver, pcm_devclass, 0, 0);
Index: vibes.h
===================================================================
RCS file: /home/cvs/src/sys/dev/sound/pci/vibes.h,v
retrieving revision 1.2
retrieving revision 1.3
diff -L sys/dev/sound/pci/vibes.h -L sys/dev/sound/pci/vibes.h -u -r1.2 -r1.3
--- sys/dev/sound/pci/vibes.h
+++ sys/dev/sound/pci/vibes.h
@@ -1,31 +1,30 @@
/*-
-* Copyright (c) 2001 Orion Hodson <O.Hodson at cs.ucl.ac.uk>
-* All rights reserved.
-*
-* Redistribution and use in source and binary forms, with or without
-* modification, are permitted provided that the following conditions
-* are met:
-* 1. Redistributions of source code must retain the above copyright
-* notice, this list of conditions and the following disclaimer.
-* 2. Redistributions in binary form must reproduce the above copyright
-* notice, this list of conditions and the following disclaimer in the
-* documentation and/or other materials provided with the distribution.
-*
-* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
-* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
-* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
-* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
-* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
-* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
-* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
-* SUCH DAMAGE.
-*
-* $MidnightBSD$
-* $FreeBSD: src/sys/dev/sound/pci/vibes.h,v 1.2 2005/01/06 01:43:19 imp Exp $
-*/
+ * Copyright (c) 2001 Orion Hodson <O.Hodson at cs.ucl.ac.uk>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD: src/sys/dev/sound/pci/vibes.h,v 1.2 2005/01/06 01:43:19 imp Exp $
+ */
/* ------------------------------------------------------------------------- */
/* PCI Configuration Register Offsets */
Index: t4dwave.c
===================================================================
RCS file: /home/cvs/src/sys/dev/sound/pci/t4dwave.c,v
retrieving revision 1.2
retrieving revision 1.3
diff -L sys/dev/sound/pci/t4dwave.c -L sys/dev/sound/pci/t4dwave.c -u -r1.2 -r1.3
--- sys/dev/sound/pci/t4dwave.c
+++ sys/dev/sound/pci/t4dwave.c
@@ -1,28 +1,28 @@
/*-
-* Copyright (c) 1999 Cameron Grant <cg at freebsd.org>
-* All rights reserved.
-*
-* Redistribution and use in source and binary forms, with or without
-* modification, are permitted provided that the following conditions
-* are met:
-* 1. Redistributions of source code must retain the above copyright
-* notice, this list of conditions and the following disclaimer.
-* 2. Redistributions in binary form must reproduce the above copyright
-* notice, this list of conditions and the following disclaimer in the
-* documentation and/or other materials provided with the distribution.
-*
-* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
-* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
-* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
-* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
-* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHERIN CONTRACT, STRICT
-* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
-* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THEPOSSIBILITY OF
-* SUCH DAMAGE.
-*/
+ * Copyright (c) 1999 Cameron Grant <cg at freebsd.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHERIN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THEPOSSIBILITY OF
+ * SUCH DAMAGE.
+ */
#include <dev/sound/pcm/sound.h>
#include <dev/sound/pcm/ac97.h>
@@ -31,7 +31,7 @@
#include <dev/pci/pcireg.h>
#include <dev/pci/pcivar.h>
-SND_DECLARE_FILE("$MidnightBSD$");
+SND_DECLARE_FILE("$FreeBSD: src/sys/dev/sound/pci/t4dwave.c,v 1.53.2.1 2007/11/15 16:59:29 ariff Exp $");
/* -------------------------------------------------------------------- */
@@ -44,13 +44,13 @@
#define TR_TIMEOUT_CDC 0xffff
#define TR_MAXPLAYCH 4
/*
-* Though, it's not clearly documented in trident datasheet, trident
-* audio cards can't handle DMA addresses located above 1GB. The LBA
-* (loop begin address) register which holds DMA base address is 32bits
-* register.
-* But the MSB 2bits are used for other purposes(I guess it is really
-* bad idea). This effectivly limits the DMA address space up to 1GB.
-*/
+ * Though, it's not clearly documented in trident datasheet, trident
+ * audio cards can't handle DMA addresses located above 1GB. The LBA
+ * (loop begin address) register which holds DMA base address is 32bits
+ * register.
+ * But the MSB 2bits are used for other purposes(I guess it is really
+ * bad idea). This effectivly limits the DMA address space up to 1GB.
+ */
#define TR_MAXADDR ((1 << 30) - 1)
@@ -58,73 +58,73 @@
/* channel registers */
struct tr_chinfo {
-u_int32_t cso, alpha, fms, fmc, ec;
-u_int32_t lba;
-u_int32_t eso, delta;
-u_int32_t rvol, cvol;
-u_int32_t gvsel, pan, vol, ctrl;
-u_int32_t active:1, was_active:1;
-int index, bufhalf;
-struct snd_dbuf *buffer;
-struct pcm_channel *channel;
-struct tr_info *parent;
+ u_int32_t cso, alpha, fms, fmc, ec;
+ u_int32_t lba;
+ u_int32_t eso, delta;
+ u_int32_t rvol, cvol;
+ u_int32_t gvsel, pan, vol, ctrl;
+ u_int32_t active:1, was_active:1;
+ int index, bufhalf;
+ struct snd_dbuf *buffer;
+ struct pcm_channel *channel;
+ struct tr_info *parent;
};
struct tr_rchinfo {
-u_int32_t delta;
-u_int32_t active:1, was_active:1;
-struct snd_dbuf *buffer;
-struct pcm_channel *channel;
-struct tr_info *parent;
+ u_int32_t delta;
+ u_int32_t active:1, was_active:1;
+ struct snd_dbuf *buffer;
+ struct pcm_channel *channel;
+ struct tr_info *parent;
};
/* device private data */
struct tr_info {
-u_int32_t type;
-u_int32_t rev;
+ u_int32_t type;
+ u_int32_t rev;
-bus_space_tag_t st;
-bus_space_handle_t sh;
-bus_dma_tag_t parent_dmat;
+ bus_space_tag_t st;
+ bus_space_handle_t sh;
+ bus_dma_tag_t parent_dmat;
-struct resource *reg, *irq;
-int regtype, regid, irqid;
-void *ih;
+ struct resource *reg, *irq;
+ int regtype, regid, irqid;
+ void *ih;
-struct mtx *lock;
+ struct mtx *lock;
-u_int32_t playchns;
-unsigned int bufsz;
+ u_int32_t playchns;
+ unsigned int bufsz;
-struct tr_chinfo chinfo[TR_MAXPLAYCH];
-struct tr_rchinfo recchinfo;
+ struct tr_chinfo chinfo[TR_MAXPLAYCH];
+ struct tr_rchinfo recchinfo;
};
/* -------------------------------------------------------------------- */
static u_int32_t tr_recfmt[] = {
-AFMT_U8,
-AFMT_STEREO | AFMT_U8,
-AFMT_S8,
-AFMT_STEREO | AFMT_S8,
-AFMT_S16_LE,
-AFMT_STEREO | AFMT_S16_LE,
-AFMT_U16_LE,
-AFMT_STEREO | AFMT_U16_LE,
-0
+ AFMT_U8,
+ AFMT_STEREO | AFMT_U8,
+ AFMT_S8,
+ AFMT_STEREO | AFMT_S8,
+ AFMT_S16_LE,
+ AFMT_STEREO | AFMT_S16_LE,
+ AFMT_U16_LE,
+ AFMT_STEREO | AFMT_U16_LE,
+ 0
};
static struct pcmchan_caps tr_reccaps = {4000, 48000, tr_recfmt, 0};
static u_int32_t tr_playfmt[] = {
-AFMT_U8,
-AFMT_STEREO | AFMT_U8,
-AFMT_S8,
-AFMT_STEREO | AFMT_S8,
-AFMT_S16_LE,
-AFMT_STEREO | AFMT_S16_LE,
-AFMT_U16_LE,
-AFMT_STEREO | AFMT_U16_LE,
-0
+ AFMT_U8,
+ AFMT_STEREO | AFMT_U8,
+ AFMT_S8,
+ AFMT_STEREO | AFMT_S8,
+ AFMT_S16_LE,
+ AFMT_STEREO | AFMT_S16_LE,
+ AFMT_U16_LE,
+ AFMT_STEREO | AFMT_U16_LE,
+ 0
};
static struct pcmchan_caps tr_playcaps = {4000, 48000, tr_playfmt, 0};
@@ -135,32 +135,32 @@
static u_int32_t
tr_rd(struct tr_info *tr, int regno, int size)
{
-switch(size) {
-case 1:
-return bus_space_read_1(tr->st, tr->sh, regno);
-case 2:
-return bus_space_read_2(tr->st, tr->sh, regno);
-case 4:
-return bus_space_read_4(tr->st, tr->sh, regno);
-default:
-return 0xffffffff;
-}
+ switch(size) {
+ case 1:
+ return bus_space_read_1(tr->st, tr->sh, regno);
+ case 2:
+ return bus_space_read_2(tr->st, tr->sh, regno);
+ case 4:
+ return bus_space_read_4(tr->st, tr->sh, regno);
+ default:
+ return 0xffffffff;
+ }
}
static void
tr_wr(struct tr_info *tr, int regno, u_int32_t data, int size)
{
-switch(size) {
-case 1:
-bus_space_write_1(tr->st, tr->sh, regno, data);
-break;
-case 2:
-bus_space_write_2(tr->st, tr->sh, regno, data);
-break;
-case 4:
-bus_space_write_4(tr->st, tr->sh, regno, data);
-break;
-}
+ switch(size) {
+ case 1:
+ bus_space_write_1(tr->st, tr->sh, regno, data);
+ break;
+ case 2:
+ bus_space_write_2(tr->st, tr->sh, regno, data);
+ break;
+ case 4:
+ bus_space_write_4(tr->st, tr->sh, regno, data);
+ break;
+ }
}
/* -------------------------------------------------------------------- */
@@ -169,127 +169,127 @@
static int
tr_rdcd(kobj_t obj, void *devinfo, int regno)
{
-struct tr_info *tr = (struct tr_info *)devinfo;
-int i, j, treg, trw;
+ struct tr_info *tr = (struct tr_info *)devinfo;
+ int i, j, treg, trw;
-switch (tr->type) {
-case SPA_PCI_ID:
-treg=SPA_REG_CODECRD;
-trw=SPA_CDC_RWSTAT;
-break;
-case ALI_PCI_ID:
-if (tr->rev > 0x01)
-treg=TDX_REG_CODECWR;
-else
-treg=TDX_REG_CODECRD;
-trw=TDX_CDC_RWSTAT;
-break;
-case TDX_PCI_ID:
-treg=TDX_REG_CODECRD;
-trw=TDX_CDC_RWSTAT;
-break;
-case TNX_PCI_ID:
-treg=(regno & 0x100)? TNX_REG_CODEC2RD : TNX_REG_CODEC1RD;
-trw=TNX_CDC_RWSTAT;
-break;
-default:
-printf("!!! tr_rdcd defaulted !!!n");
-return -1;
-}
-
-i = j = 0;
-
-regno &= 0x7f;
-snd_mtxlock(tr->lock);
-if (tr->type == ALI_PCI_ID) {
-u_int32_t chk1, chk2;
-j = trw;
-for (i = TR_TIMEOUT_CDC; (i > 0) && (j & trw); i--)
-j = tr_rd(tr, treg, 4);
-if (i > 0) {
-chk1 = tr_rd(tr, 0xc8, 4);
-chk2 = tr_rd(tr, 0xc8, 4);
-for (i = TR_TIMEOUT_CDC; (i > 0) && (chk1 == chk2);
-i--)
-chk2 = tr_rd(tr, 0xc8, 4);
-}
-}
-if (tr->type != ALI_PCI_ID || i > 0) {
-tr_wr(tr, treg, regno | trw, 4);
-j=trw;
-for (i=TR_TIMEOUT_CDC; (i > 0) && (j & trw); i--)
-j=tr_rd(tr, treg, 4);
-}
-snd_mtxunlock(tr->lock);
-if (i == 0) printf("codec timeout during read of register %xn", regno);
-return (j >> TR_CDC_DATA) & 0xffff;
+ switch (tr->type) {
+ case SPA_PCI_ID:
+ treg=SPA_REG_CODECRD;
+ trw=SPA_CDC_RWSTAT;
+ break;
+ case ALI_PCI_ID:
+ if (tr->rev > 0x01)
+ treg=TDX_REG_CODECWR;
+ else
+ treg=TDX_REG_CODECRD;
+ trw=TDX_CDC_RWSTAT;
+ break;
+ case TDX_PCI_ID:
+ treg=TDX_REG_CODECRD;
+ trw=TDX_CDC_RWSTAT;
+ break;
+ case TNX_PCI_ID:
+ treg=(regno & 0x100)? TNX_REG_CODEC2RD : TNX_REG_CODEC1RD;
+ trw=TNX_CDC_RWSTAT;
+ break;
+ default:
+ printf("!!! tr_rdcd defaulted !!!\n");
+ return -1;
+ }
+
+ i = j = 0;
+
+ regno &= 0x7f;
+ snd_mtxlock(tr->lock);
+ if (tr->type == ALI_PCI_ID) {
+ u_int32_t chk1, chk2;
+ j = trw;
+ for (i = TR_TIMEOUT_CDC; (i > 0) && (j & trw); i--)
+ j = tr_rd(tr, treg, 4);
+ if (i > 0) {
+ chk1 = tr_rd(tr, 0xc8, 4);
+ chk2 = tr_rd(tr, 0xc8, 4);
+ for (i = TR_TIMEOUT_CDC; (i > 0) && (chk1 == chk2);
+ i--)
+ chk2 = tr_rd(tr, 0xc8, 4);
+ }
+ }
+ if (tr->type != ALI_PCI_ID || i > 0) {
+ tr_wr(tr, treg, regno | trw, 4);
+ j=trw;
+ for (i=TR_TIMEOUT_CDC; (i > 0) && (j & trw); i--)
+ j=tr_rd(tr, treg, 4);
+ }
+ snd_mtxunlock(tr->lock);
+ if (i == 0) printf("codec timeout during read of register %x\n", regno);
+ return (j >> TR_CDC_DATA) & 0xffff;
}
static int
tr_wrcd(kobj_t obj, void *devinfo, int regno, u_int32_t data)
{
-struct tr_info *tr = (struct tr_info *)devinfo;
-int i, j, treg, trw;
+ struct tr_info *tr = (struct tr_info *)devinfo;
+ int i, j, treg, trw;
-switch (tr->type) {
-case SPA_PCI_ID:
-treg=SPA_REG_CODECWR;
-trw=SPA_CDC_RWSTAT;
-break;
-case ALI_PCI_ID:
-case TDX_PCI_ID:
-treg=TDX_REG_CODECWR;
-trw=TDX_CDC_RWSTAT;
-break;
-case TNX_PCI_ID:
-treg=TNX_REG_CODECWR;
-trw=TNX_CDC_RWSTAT | ((regno & 0x100)? TNX_CDC_SEC : 0);
-break;
-default:
-printf("!!! tr_wrcd defaulted !!!");
-return -1;
-}
+ switch (tr->type) {
+ case SPA_PCI_ID:
+ treg=SPA_REG_CODECWR;
+ trw=SPA_CDC_RWSTAT;
+ break;
+ case ALI_PCI_ID:
+ case TDX_PCI_ID:
+ treg=TDX_REG_CODECWR;
+ trw=TDX_CDC_RWSTAT;
+ break;
+ case TNX_PCI_ID:
+ treg=TNX_REG_CODECWR;
+ trw=TNX_CDC_RWSTAT | ((regno & 0x100)? TNX_CDC_SEC : 0);
+ break;
+ default:
+ printf("!!! tr_wrcd defaulted !!!");
+ return -1;
+ }
-i = 0;
+ i = 0;
-regno &= 0x7f;
+ regno &= 0x7f;
#if 0
-printf("tr_wrcd: reg %x was %x", regno, tr_rdcd(devinfo, regno));
+ printf("tr_wrcd: reg %x was %x", regno, tr_rdcd(devinfo, regno));
#endif
-j=trw;
-snd_mtxlock(tr->lock);
-if (tr->type == ALI_PCI_ID) {
-j = trw;
-for (i = TR_TIMEOUT_CDC; (i > 0) && (j & trw); i--)
-j = tr_rd(tr, treg, 4);
-if (i > 0) {
-u_int32_t chk1, chk2;
-chk1 = tr_rd(tr, 0xc8, 4);
-chk2 = tr_rd(tr, 0xc8, 4);
-for (i = TR_TIMEOUT_CDC; (i > 0) && (chk1 == chk2);
-i--)
-chk2 = tr_rd(tr, 0xc8, 4);
-}
-}
-if (tr->type != ALI_PCI_ID || i > 0) {
-for (i=TR_TIMEOUT_CDC; (i>0) && (j & trw); i--)
-j=tr_rd(tr, treg, 4);
-if (tr->type == ALI_PCI_ID && tr->rev > 0x01)
-trw |= 0x0100;
-tr_wr(tr, treg, (data << TR_CDC_DATA) | regno | trw, 4);
-}
+ j=trw;
+ snd_mtxlock(tr->lock);
+ if (tr->type == ALI_PCI_ID) {
+ j = trw;
+ for (i = TR_TIMEOUT_CDC; (i > 0) && (j & trw); i--)
+ j = tr_rd(tr, treg, 4);
+ if (i > 0) {
+ u_int32_t chk1, chk2;
+ chk1 = tr_rd(tr, 0xc8, 4);
+ chk2 = tr_rd(tr, 0xc8, 4);
+ for (i = TR_TIMEOUT_CDC; (i > 0) && (chk1 == chk2);
+ i--)
+ chk2 = tr_rd(tr, 0xc8, 4);
+ }
+ }
+ if (tr->type != ALI_PCI_ID || i > 0) {
+ for (i=TR_TIMEOUT_CDC; (i>0) && (j & trw); i--)
+ j=tr_rd(tr, treg, 4);
+ if (tr->type == ALI_PCI_ID && tr->rev > 0x01)
+ trw |= 0x0100;
+ tr_wr(tr, treg, (data << TR_CDC_DATA) | regno | trw, 4);
+ }
#if 0
-printf(" - wrote %x, now %xn", data, tr_rdcd(devinfo, regno));
+ printf(" - wrote %x, now %x\n", data, tr_rdcd(devinfo, regno));
#endif
-snd_mtxunlock(tr->lock);
-if (i==0) printf("codec timeout writing %x, data %xn", regno, data);
-return (i > 0)? 0 : -1;
+ snd_mtxunlock(tr->lock);
+ if (i==0) printf("codec timeout writing %x, data %x\n", regno, data);
+ return (i > 0)? 0 : -1;
}
static kobj_method_t tr_ac97_methods[] = {
-KOBJMETHOD(ac97_read, tr_rdcd),
-KOBJMETHOD(ac97_write, tr_wrcd),
-{ 0, 0 }
+ KOBJMETHOD(ac97_read, tr_rdcd),
+ KOBJMETHOD(ac97_write, tr_wrcd),
+ { 0, 0 }
};
AC97_DECLARE(tr_ac97);
@@ -300,45 +300,45 @@
static u_int32_t
tr_testint(struct tr_chinfo *ch)
{
-struct tr_info *tr = ch->parent;
-int bank, chan;
+ struct tr_info *tr = ch->parent;
+ int bank, chan;
-bank = (ch->index & 0x20) ? 1 : 0;
-chan = ch->index & 0x1f;
-return tr_rd(tr, bank? TR_REG_ADDRINTB : TR_REG_ADDRINTA, 4) & (1 << chan);
+ bank = (ch->index & 0x20) ? 1 : 0;
+ chan = ch->index & 0x1f;
+ return tr_rd(tr, bank? TR_REG_ADDRINTB : TR_REG_ADDRINTA, 4) & (1 << chan);
}
#endif
static void
tr_clrint(struct tr_chinfo *ch)
{
-struct tr_info *tr = ch->parent;
-int bank, chan;
+ struct tr_info *tr = ch->parent;
+ int bank, chan;
-bank = (ch->index & 0x20) ? 1 : 0;
-chan = ch->index & 0x1f;
-tr_wr(tr, bank? TR_REG_ADDRINTB : TR_REG_ADDRINTA, 1 << chan, 4);
+ bank = (ch->index & 0x20) ? 1 : 0;
+ chan = ch->index & 0x1f;
+ tr_wr(tr, bank? TR_REG_ADDRINTB : TR_REG_ADDRINTA, 1 << chan, 4);
}
static void
tr_enaint(struct tr_chinfo *ch, int enable)
{
-struct tr_info *tr = ch->parent;
-u_int32_t i, reg;
-int bank, chan;
-
-snd_mtxlock(tr->lock);
-bank = (ch->index & 0x20) ? 1 : 0;
-chan = ch->index & 0x1f;
-reg = bank? TR_REG_INTENB : TR_REG_INTENA;
-
-i = tr_rd(tr, reg, 4);
-i &= ~(1 << chan);
-i |= (enable? 1 : 0) << chan;
-
-tr_clrint(ch);
-tr_wr(tr, reg, i, 4);
-snd_mtxunlock(tr->lock);
+ struct tr_info *tr = ch->parent;
+ u_int32_t i, reg;
+ int bank, chan;
+
+ snd_mtxlock(tr->lock);
+ bank = (ch->index & 0x20) ? 1 : 0;
+ chan = ch->index & 0x1f;
+ reg = bank? TR_REG_INTENB : TR_REG_INTENA;
+
+ i = tr_rd(tr, reg, 4);
+ i &= ~(1 << chan);
+ i |= (enable? 1 : 0) << chan;
+
+ tr_clrint(ch);
+ tr_wr(tr, reg, i, 4);
+ snd_mtxunlock(tr->lock);
}
/* playback channels */
@@ -346,137 +346,137 @@
static void
tr_selch(struct tr_chinfo *ch)
{
-struct tr_info *tr = ch->parent;
-int i;
+ struct tr_info *tr = ch->parent;
+ int i;
-i = tr_rd(tr, TR_REG_CIR, 4);
-i &= ~TR_CIR_MASK;
-i |= ch->index & 0x3f;
-tr_wr(tr, TR_REG_CIR, i, 4);
+ i = tr_rd(tr, TR_REG_CIR, 4);
+ i &= ~TR_CIR_MASK;
+ i |= ch->index & 0x3f;
+ tr_wr(tr, TR_REG_CIR, i, 4);
}
static void
tr_startch(struct tr_chinfo *ch)
{
-struct tr_info *tr = ch->parent;
-int bank, chan;
+ struct tr_info *tr = ch->parent;
+ int bank, chan;
-bank = (ch->index & 0x20) ? 1 : 0;
-chan = ch->index & 0x1f;
-tr_wr(tr, bank? TR_REG_STARTB : TR_REG_STARTA, 1 << chan, 4);
+ bank = (ch->index & 0x20) ? 1 : 0;
+ chan = ch->index & 0x1f;
+ tr_wr(tr, bank? TR_REG_STARTB : TR_REG_STARTA, 1 << chan, 4);
}
static void
tr_stopch(struct tr_chinfo *ch)
{
-struct tr_info *tr = ch->parent;
-int bank, chan;
+ struct tr_info *tr = ch->parent;
+ int bank, chan;
-bank = (ch->index & 0x20) ? 1 : 0;
-chan = ch->index & 0x1f;
-tr_wr(tr, bank? TR_REG_STOPB : TR_REG_STOPA, 1 << chan, 4);
+ bank = (ch->index & 0x20) ? 1 : 0;
+ chan = ch->index & 0x1f;
+ tr_wr(tr, bank? TR_REG_STOPB : TR_REG_STOPA, 1 << chan, 4);
}
static void
tr_wrch(struct tr_chinfo *ch)
{
-struct tr_info *tr = ch->parent;
-u_int32_t cr[TR_CHN_REGS], i;
+ struct tr_info *tr = ch->parent;
+ u_int32_t cr[TR_CHN_REGS], i;
-ch->gvsel &= 0x00000001;
-ch->fmc &= 0x00000003;
-ch->fms &= 0x0000000f;
-ch->ctrl &= 0x0000000f;
-ch->pan &= 0x0000007f;
-ch->rvol &= 0x0000007f;
-ch->cvol &= 0x0000007f;
-ch->vol &= 0x000000ff;
-ch->ec &= 0x00000fff;
-ch->alpha &= 0x00000fff;
-ch->delta &= 0x0000ffff;
-ch->lba &= 0x3fffffff;
-
-cr[1]=ch->lba;
-cr[3]=(ch->fmc<<14) | (ch->rvol<<7) | (ch->cvol);
-cr[4]=(ch->gvsel<<31) | (ch->pan<<24) | (ch->vol<<16) | (ch->ctrl<<12) | (ch->ec);
-
-switch (tr->type) {
-case SPA_PCI_ID:
-case ALI_PCI_ID:
-case TDX_PCI_ID:
-ch->cso &= 0x0000ffff;
-ch->eso &= 0x0000ffff;
-cr[0]=(ch->cso<<16) | (ch->alpha<<4) | (ch->fms);
-cr[2]=(ch->eso<<16) | (ch->delta);
-break;
-case TNX_PCI_ID:
-ch->cso &= 0x00ffffff;
-ch->eso &= 0x00ffffff;
-cr[0]=((ch->delta & 0xff)<<24) | (ch->cso);
-cr[2]=((ch->delta>>8)<<24) | (ch->eso);
-cr[3]|=(ch->alpha<<20) | (ch->fms<<16) | (ch->fmc<<14);
-break;
-}
-snd_mtxlock(tr->lock);
-tr_selch(ch);
-for (i=0; i<TR_CHN_REGS; i++)
-tr_wr(tr, TR_REG_CHNBASE+(i<<2), cr[i], 4);
-snd_mtxunlock(tr->lock);
+ ch->gvsel &= 0x00000001;
+ ch->fmc &= 0x00000003;
+ ch->fms &= 0x0000000f;
+ ch->ctrl &= 0x0000000f;
+ ch->pan &= 0x0000007f;
+ ch->rvol &= 0x0000007f;
+ ch->cvol &= 0x0000007f;
+ ch->vol &= 0x000000ff;
+ ch->ec &= 0x00000fff;
+ ch->alpha &= 0x00000fff;
+ ch->delta &= 0x0000ffff;
+ ch->lba &= 0x3fffffff;
+
+ cr[1]=ch->lba;
+ cr[3]=(ch->fmc<<14) | (ch->rvol<<7) | (ch->cvol);
+ cr[4]=(ch->gvsel<<31) | (ch->pan<<24) | (ch->vol<<16) | (ch->ctrl<<12) | (ch->ec);
+
+ switch (tr->type) {
+ case SPA_PCI_ID:
+ case ALI_PCI_ID:
+ case TDX_PCI_ID:
+ ch->cso &= 0x0000ffff;
+ ch->eso &= 0x0000ffff;
+ cr[0]=(ch->cso<<16) | (ch->alpha<<4) | (ch->fms);
+ cr[2]=(ch->eso<<16) | (ch->delta);
+ break;
+ case TNX_PCI_ID:
+ ch->cso &= 0x00ffffff;
+ ch->eso &= 0x00ffffff;
+ cr[0]=((ch->delta & 0xff)<<24) | (ch->cso);
+ cr[2]=((ch->delta>>8)<<24) | (ch->eso);
+ cr[3]|=(ch->alpha<<20) | (ch->fms<<16) | (ch->fmc<<14);
+ break;
+ }
+ snd_mtxlock(tr->lock);
+ tr_selch(ch);
+ for (i=0; i<TR_CHN_REGS; i++)
+ tr_wr(tr, TR_REG_CHNBASE+(i<<2), cr[i], 4);
+ snd_mtxunlock(tr->lock);
}
static void
tr_rdch(struct tr_chinfo *ch)
{
-struct tr_info *tr = ch->parent;
-u_int32_t cr[5], i;
+ struct tr_info *tr = ch->parent;
+ u_int32_t cr[5], i;
-snd_mtxlock(tr->lock);
-tr_selch(ch);
-for (i=0; i<5; i++)
-cr[i]=tr_rd(tr, TR_REG_CHNBASE+(i<<2), 4);
-snd_mtxunlock(tr->lock);
-
-
-ch->lba= (cr[1] & 0x3fffffff);
-ch->fmc= (cr[3] & 0x0000c000) >> 14;
-ch->rvol= (cr[3] & 0x00003f80) >> 7;
-ch->cvol= (cr[3] & 0x0000007f);
-ch->gvsel= (cr[4] & 0x80000000) >> 31;
-ch->pan= (cr[4] & 0x7f000000) >> 24;
-ch->vol= (cr[4] & 0x00ff0000) >> 16;
-ch->ctrl= (cr[4] & 0x0000f000) >> 12;
-ch->ec= (cr[4] & 0x00000fff);
-switch(tr->type) {
-case SPA_PCI_ID:
-case ALI_PCI_ID:
-case TDX_PCI_ID:
-ch->cso= (cr[0] & 0xffff0000) >> 16;
-ch->alpha= (cr[0] & 0x0000fff0) >> 4;
-ch->fms= (cr[0] & 0x0000000f);
-ch->eso= (cr[2] & 0xffff0000) >> 16;
-ch->delta= (cr[2] & 0x0000ffff);
-break;
-case TNX_PCI_ID:
-ch->cso= (cr[0] & 0x00ffffff);
-ch->eso= (cr[2] & 0x00ffffff);
-ch->delta= ((cr[2] & 0xff000000) >> 16) | ((cr[0] & 0xff000000) >> 24);
-ch->alpha= (cr[3] & 0xfff00000) >> 20;
-ch->fms= (cr[3] & 0x000f0000) >> 16;
-break;
-}
+ snd_mtxlock(tr->lock);
+ tr_selch(ch);
+ for (i=0; i<5; i++)
+ cr[i]=tr_rd(tr, TR_REG_CHNBASE+(i<<2), 4);
+ snd_mtxunlock(tr->lock);
+
+
+ ch->lba= (cr[1] & 0x3fffffff);
+ ch->fmc= (cr[3] & 0x0000c000) >> 14;
+ ch->rvol= (cr[3] & 0x00003f80) >> 7;
+ ch->cvol= (cr[3] & 0x0000007f);
+ ch->gvsel= (cr[4] & 0x80000000) >> 31;
+ ch->pan= (cr[4] & 0x7f000000) >> 24;
+ ch->vol= (cr[4] & 0x00ff0000) >> 16;
+ ch->ctrl= (cr[4] & 0x0000f000) >> 12;
+ ch->ec= (cr[4] & 0x00000fff);
+ switch(tr->type) {
+ case SPA_PCI_ID:
+ case ALI_PCI_ID:
+ case TDX_PCI_ID:
+ ch->cso= (cr[0] & 0xffff0000) >> 16;
+ ch->alpha= (cr[0] & 0x0000fff0) >> 4;
+ ch->fms= (cr[0] & 0x0000000f);
+ ch->eso= (cr[2] & 0xffff0000) >> 16;
+ ch->delta= (cr[2] & 0x0000ffff);
+ break;
+ case TNX_PCI_ID:
+ ch->cso= (cr[0] & 0x00ffffff);
+ ch->eso= (cr[2] & 0x00ffffff);
+ ch->delta= ((cr[2] & 0xff000000) >> 16) | ((cr[0] & 0xff000000) >> 24);
+ ch->alpha= (cr[3] & 0xfff00000) >> 20;
+ ch->fms= (cr[3] & 0x000f0000) >> 16;
+ break;
+ }
}
static u_int32_t
tr_fmttobits(u_int32_t fmt)
{
-u_int32_t bits;
+ u_int32_t bits;
-bits = 0;
-bits |= (fmt & AFMT_SIGNED)? 0x2 : 0;
-bits |= (fmt & AFMT_STEREO)? 0x4 : 0;
-bits |= (fmt & AFMT_16BIT)? 0x8 : 0;
+ bits = 0;
+ bits |= (fmt & AFMT_SIGNED)? 0x2 : 0;
+ bits |= (fmt & AFMT_STEREO)? 0x4 : 0;
+ bits |= (fmt & AFMT_16BIT)? 0x8 : 0;
-return bits;
+ return bits;
}
/* -------------------------------------------------------------------- */
@@ -485,106 +485,106 @@
static void *
trpchan_init(kobj_t obj, void *devinfo, struct snd_dbuf *b, struct pcm_channel *c, int dir)
{
-struct tr_info *tr = devinfo;
-struct tr_chinfo *ch;
+ struct tr_info *tr = devinfo;
+ struct tr_chinfo *ch;
-KASSERT(dir == PCMDIR_PLAY, ("trpchan_init: bad direction"));
-ch = &tr->chinfo[tr->playchns];
-ch->index = tr->playchns++;
-ch->buffer = b;
-ch->parent = tr;
-ch->channel = c;
-if (sndbuf_alloc(ch->buffer, tr->parent_dmat, tr->bufsz) != 0)
-return NULL;
+ KASSERT(dir == PCMDIR_PLAY, ("trpchan_init: bad direction"));
+ ch = &tr->chinfo[tr->playchns];
+ ch->index = tr->playchns++;
+ ch->buffer = b;
+ ch->parent = tr;
+ ch->channel = c;
+ if (sndbuf_alloc(ch->buffer, tr->parent_dmat, 0, tr->bufsz) != 0)
+ return NULL;
-return ch;
+ return ch;
}
static int
trpchan_setformat(kobj_t obj, void *data, u_int32_t format)
{
-struct tr_chinfo *ch = data;
+ struct tr_chinfo *ch = data;
-ch->ctrl = tr_fmttobits(format) | 0x01;
+ ch->ctrl = tr_fmttobits(format) | 0x01;
-return 0;
+ return 0;
}
static int
trpchan_setspeed(kobj_t obj, void *data, u_int32_t speed)
{
-struct tr_chinfo *ch = data;
+ struct tr_chinfo *ch = data;
-ch->delta = (speed << 12) / 48000;
-return (ch->delta * 48000) >> 12;
+ ch->delta = (speed << 12) / 48000;
+ return (ch->delta * 48000) >> 12;
}
static int
trpchan_setblocksize(kobj_t obj, void *data, u_int32_t blocksize)
{
-struct tr_chinfo *ch = data;
+ struct tr_chinfo *ch = data;
-sndbuf_resize(ch->buffer, 2, blocksize);
-return blocksize;
+ sndbuf_resize(ch->buffer, 2, blocksize);
+ return blocksize;
}
static int
trpchan_trigger(kobj_t obj, void *data, int go)
{
-struct tr_chinfo *ch = data;
+ struct tr_chinfo *ch = data;
-if (go == PCMTRIG_EMLDMAWR || go == PCMTRIG_EMLDMARD)
-return 0;
+ if (!PCMTRIG_COMMON(go))
+ return 0;
-if (go == PCMTRIG_START) {
-ch->fmc = 3;
-ch->fms = 0;
-ch->ec = 0;
-ch->alpha = 0;
-ch->lba = sndbuf_getbufaddr(ch->buffer);
-ch->cso = 0;
-ch->eso = (sndbuf_getsize(ch->buffer) / sndbuf_getbps(ch->buffer)) - 1;
-ch->rvol = ch->cvol = 0x7f;
-ch->gvsel = 0;
-ch->pan = 0;
-ch->vol = 0;
-ch->bufhalf = 0;
-tr_wrch(ch);
-tr_enaint(ch, 1);
-tr_startch(ch);
-ch->active = 1;
-} else {
-tr_stopch(ch);
-ch->active = 0;
-}
+ if (go == PCMTRIG_START) {
+ ch->fmc = 3;
+ ch->fms = 0;
+ ch->ec = 0;
+ ch->alpha = 0;
+ ch->lba = sndbuf_getbufaddr(ch->buffer);
+ ch->cso = 0;
+ ch->eso = (sndbuf_getsize(ch->buffer) / sndbuf_getbps(ch->buffer)) - 1;
+ ch->rvol = ch->cvol = 0x7f;
+ ch->gvsel = 0;
+ ch->pan = 0;
+ ch->vol = 0;
+ ch->bufhalf = 0;
+ tr_wrch(ch);
+ tr_enaint(ch, 1);
+ tr_startch(ch);
+ ch->active = 1;
+ } else {
+ tr_stopch(ch);
+ ch->active = 0;
+ }
-return 0;
+ return 0;
}
static int
trpchan_getptr(kobj_t obj, void *data)
{
-struct tr_chinfo *ch = data;
+ struct tr_chinfo *ch = data;
-tr_rdch(ch);
-return ch->cso * sndbuf_getbps(ch->buffer);
+ tr_rdch(ch);
+ return ch->cso * sndbuf_getbps(ch->buffer);
}
static struct pcmchan_caps *
trpchan_getcaps(kobj_t obj, void *data)
{
-return &tr_playcaps;
+ return &tr_playcaps;
}
static kobj_method_t trpchan_methods[] = {
-KOBJMETHOD(channel_init, trpchan_init),
-KOBJMETHOD(channel_setformat, trpchan_setformat),
-KOBJMETHOD(channel_setspeed, trpchan_setspeed),
-KOBJMETHOD(channel_setblocksize, trpchan_setblocksize),
-KOBJMETHOD(channel_trigger, trpchan_trigger),
-KOBJMETHOD(channel_getptr, trpchan_getptr),
-KOBJMETHOD(channel_getcaps, trpchan_getcaps),
-{ 0, 0 }
+ KOBJMETHOD(channel_init, trpchan_init),
+ KOBJMETHOD(channel_setformat, trpchan_setformat),
+ KOBJMETHOD(channel_setspeed, trpchan_setspeed),
+ KOBJMETHOD(channel_setblocksize, trpchan_setblocksize),
+ KOBJMETHOD(channel_trigger, trpchan_trigger),
+ KOBJMETHOD(channel_getptr, trpchan_getptr),
+ KOBJMETHOD(channel_getcaps, trpchan_getcaps),
+ { 0, 0 }
};
CHANNEL_DECLARE(trpchan);
@@ -594,120 +594,120 @@
static void *
trrchan_init(kobj_t obj, void *devinfo, struct snd_dbuf *b, struct pcm_channel *c, int dir)
{
-struct tr_info *tr = devinfo;
-struct tr_rchinfo *ch;
+ struct tr_info *tr = devinfo;
+ struct tr_rchinfo *ch;
-KASSERT(dir == PCMDIR_REC, ("trrchan_init: bad direction"));
-ch = &tr->recchinfo;
-ch->buffer = b;
-ch->parent = tr;
-ch->channel = c;
-if (sndbuf_alloc(ch->buffer, tr->parent_dmat, tr->bufsz) != 0)
-return NULL;
+ KASSERT(dir == PCMDIR_REC, ("trrchan_init: bad direction"));
+ ch = &tr->recchinfo;
+ ch->buffer = b;
+ ch->parent = tr;
+ ch->channel = c;
+ if (sndbuf_alloc(ch->buffer, tr->parent_dmat, 0, tr->bufsz) != 0)
+ return NULL;
-return ch;
+ return ch;
}
static int
trrchan_setformat(kobj_t obj, void *data, u_int32_t format)
{
-struct tr_rchinfo *ch = data;
-struct tr_info *tr = ch->parent;
-u_int32_t i, bits;
-
-bits = tr_fmttobits(format);
-/* set # of samples between interrupts */
-i = (sndbuf_runsz(ch->buffer) >> ((bits & 0x08)? 1 : 0)) - 1;
-tr_wr(tr, TR_REG_SBBL, i | (i << 16), 4);
-/* set sample format */
-i = 0x18 | (bits << 4);
-tr_wr(tr, TR_REG_SBCTRL, i, 1);
+ struct tr_rchinfo *ch = data;
+ struct tr_info *tr = ch->parent;
+ u_int32_t i, bits;
+
+ bits = tr_fmttobits(format);
+ /* set # of samples between interrupts */
+ i = (sndbuf_runsz(ch->buffer) >> ((bits & 0x08)? 1 : 0)) - 1;
+ tr_wr(tr, TR_REG_SBBL, i | (i << 16), 4);
+ /* set sample format */
+ i = 0x18 | (bits << 4);
+ tr_wr(tr, TR_REG_SBCTRL, i, 1);
-return 0;
+ return 0;
}
static int
trrchan_setspeed(kobj_t obj, void *data, u_int32_t speed)
{
-struct tr_rchinfo *ch = data;
-struct tr_info *tr = ch->parent;
+ struct tr_rchinfo *ch = data;
+ struct tr_info *tr = ch->parent;
-/* setup speed */
-ch->delta = (48000 << 12) / speed;
-tr_wr(tr, TR_REG_SBDELTA, ch->delta, 2);
+ /* setup speed */
+ ch->delta = (48000 << 12) / speed;
+ tr_wr(tr, TR_REG_SBDELTA, ch->delta, 2);
-/* return closest possible speed */
-return (48000 << 12) / ch->delta;
+ /* return closest possible speed */
+ return (48000 << 12) / ch->delta;
}
static int
trrchan_setblocksize(kobj_t obj, void *data, u_int32_t blocksize)
{
-struct tr_rchinfo *ch = data;
+ struct tr_rchinfo *ch = data;
-sndbuf_resize(ch->buffer, 2, blocksize);
+ sndbuf_resize(ch->buffer, 2, blocksize);
-return blocksize;
+ return blocksize;
}
static int
trrchan_trigger(kobj_t obj, void *data, int go)
{
-struct tr_rchinfo *ch = data;
-struct tr_info *tr = ch->parent;
-u_int32_t i;
-
-if (go == PCMTRIG_EMLDMAWR || go == PCMTRIG_EMLDMARD)
-return 0;
-
-if (go == PCMTRIG_START) {
-/* set up dma mode regs */
-tr_wr(tr, TR_REG_DMAR15, 0, 1);
-i = tr_rd(tr, TR_REG_DMAR11, 1) & 0x03;
-tr_wr(tr, TR_REG_DMAR11, i | 0x54, 1);
-/* set up base address */
-tr_wr(tr, TR_REG_DMAR0, sndbuf_getbufaddr(ch->buffer), 4);
-/* set up buffer size */
-i = tr_rd(tr, TR_REG_DMAR4, 4) & ~0x00ffffff;
-tr_wr(tr, TR_REG_DMAR4, i | (sndbuf_runsz(ch->buffer) - 1), 4);
-/* start */
-tr_wr(tr, TR_REG_SBCTRL, tr_rd(tr, TR_REG_SBCTRL, 1) | 1, 1);
-ch->active = 1;
-} else {
-tr_wr(tr, TR_REG_SBCTRL, tr_rd(tr, TR_REG_SBCTRL, 1) & ~7, 1);
-ch->active = 0;
-}
+ struct tr_rchinfo *ch = data;
+ struct tr_info *tr = ch->parent;
+ u_int32_t i;
+
+ if (!PCMTRIG_COMMON(go))
+ return 0;
+
+ if (go == PCMTRIG_START) {
+ /* set up dma mode regs */
+ tr_wr(tr, TR_REG_DMAR15, 0, 1);
+ i = tr_rd(tr, TR_REG_DMAR11, 1) & 0x03;
+ tr_wr(tr, TR_REG_DMAR11, i | 0x54, 1);
+ /* set up base address */
+ tr_wr(tr, TR_REG_DMAR0, sndbuf_getbufaddr(ch->buffer), 4);
+ /* set up buffer size */
+ i = tr_rd(tr, TR_REG_DMAR4, 4) & ~0x00ffffff;
+ tr_wr(tr, TR_REG_DMAR4, i | (sndbuf_runsz(ch->buffer) - 1), 4);
+ /* start */
+ tr_wr(tr, TR_REG_SBCTRL, tr_rd(tr, TR_REG_SBCTRL, 1) | 1, 1);
+ ch->active = 1;
+ } else {
+ tr_wr(tr, TR_REG_SBCTRL, tr_rd(tr, TR_REG_SBCTRL, 1) & ~7, 1);
+ ch->active = 0;
+ }
-/* return 0 if ok */
-return 0;
+ /* return 0 if ok */
+ return 0;
}
static int
trrchan_getptr(kobj_t obj, void *data)
{
-struct tr_rchinfo *ch = data;
-struct tr_info *tr = ch->parent;
+ struct tr_rchinfo *ch = data;
+ struct tr_info *tr = ch->parent;
-/* return current byte offset of channel */
-return tr_rd(tr, TR_REG_DMAR0, 4) - sndbuf_getbufaddr(ch->buffer);
+ /* return current byte offset of channel */
+ return tr_rd(tr, TR_REG_DMAR0, 4) - sndbuf_getbufaddr(ch->buffer);
}
static struct pcmchan_caps *
trrchan_getcaps(kobj_t obj, void *data)
{
-return &tr_reccaps;
+ return &tr_reccaps;
}
static kobj_method_t trrchan_methods[] = {
-KOBJMETHOD(channel_init, trrchan_init),
-KOBJMETHOD(channel_setformat, trrchan_setformat),
-KOBJMETHOD(channel_setspeed, trrchan_setspeed),
-KOBJMETHOD(channel_setblocksize, trrchan_setblocksize),
-KOBJMETHOD(channel_trigger, trrchan_trigger),
-KOBJMETHOD(channel_getptr, trrchan_getptr),
-KOBJMETHOD(channel_getcaps, trrchan_getcaps),
-{ 0, 0 }
+ KOBJMETHOD(channel_init, trrchan_init),
+ KOBJMETHOD(channel_setformat, trrchan_setformat),
+ KOBJMETHOD(channel_setspeed, trrchan_setspeed),
+ KOBJMETHOD(channel_setblocksize, trrchan_setblocksize),
+ KOBJMETHOD(channel_trigger, trrchan_trigger),
+ KOBJMETHOD(channel_getptr, trrchan_getptr),
+ KOBJMETHOD(channel_getcaps, trrchan_getcaps),
+ { 0, 0 }
};
CHANNEL_DECLARE(trrchan);
@@ -717,271 +717,288 @@
static void
tr_intr(void *p)
{
-struct tr_info *tr = (struct tr_info *)p;
-struct tr_chinfo *ch;
-u_int32_t active, mask, bufhalf, chnum, intsrc;
-int tmp;
-
-intsrc = tr_rd(tr, TR_REG_MISCINT, 4);
-if (intsrc & TR_INT_ADDR) {
-chnum = 0;
-while (chnum < 64) {
-mask = 0x00000001;
-active = tr_rd(tr, (chnum < 32)? TR_REG_ADDRINTA : TR_REG_ADDRINTB, 4);
-bufhalf = tr_rd(tr, (chnum < 32)? TR_REG_CSPF_A : TR_REG_CSPF_B, 4);
-if (active) {
-do {
-if (active & mask) {
-tmp = (bufhalf & mask)? 1 : 0;
-if (chnum < tr->playchns) {
-ch = &tr->chinfo[chnum];
-/* printf("%d @ %d, ", chnum, trpchan_getptr(NULL, ch)); */
-if (ch->bufhalf != tmp) {
-chn_intr(ch->channel);
-ch->bufhalf = tmp;
-}
-}
-}
-chnum++;
-mask <<= 1;
-} while (chnum & 31);
-} else
-chnum += 32;
-
-tr_wr(tr, (chnum <= 32)? TR_REG_ADDRINTA : TR_REG_ADDRINTB, active, 4);
-}
-}
-if (intsrc & TR_INT_SB) {
-chn_intr(tr->recchinfo.channel);
-tr_rd(tr, TR_REG_SBR9, 1);
-tr_rd(tr, TR_REG_SBR10, 1);
-}
+ struct tr_info *tr = (struct tr_info *)p;
+ struct tr_chinfo *ch;
+ u_int32_t active, mask, bufhalf, chnum, intsrc;
+ int tmp;
+
+ intsrc = tr_rd(tr, TR_REG_MISCINT, 4);
+ if (intsrc & TR_INT_ADDR) {
+ chnum = 0;
+ while (chnum < 64) {
+ mask = 0x00000001;
+ active = tr_rd(tr, (chnum < 32)? TR_REG_ADDRINTA : TR_REG_ADDRINTB, 4);
+ bufhalf = tr_rd(tr, (chnum < 32)? TR_REG_CSPF_A : TR_REG_CSPF_B, 4);
+ if (active) {
+ do {
+ if (active & mask) {
+ tmp = (bufhalf & mask)? 1 : 0;
+ if (chnum < tr->playchns) {
+ ch = &tr->chinfo[chnum];
+ /* printf("%d @ %d, ", chnum, trpchan_getptr(NULL, ch)); */
+ if (ch->bufhalf != tmp) {
+ chn_intr(ch->channel);
+ ch->bufhalf = tmp;
+ }
+ }
+ }
+ chnum++;
+ mask <<= 1;
+ } while (chnum & 31);
+ } else
+ chnum += 32;
+
+ tr_wr(tr, (chnum <= 32)? TR_REG_ADDRINTA : TR_REG_ADDRINTB, active, 4);
+ }
+ }
+ if (intsrc & TR_INT_SB) {
+ chn_intr(tr->recchinfo.channel);
+ tr_rd(tr, TR_REG_SBR9, 1);
+ tr_rd(tr, TR_REG_SBR10, 1);
+ }
}
/* -------------------------------------------------------------------- */
/*
-* Probe and attach the card
-*/
+ * Probe and attach the card
+ */
static int
tr_init(struct tr_info *tr)
{
-switch (tr->type) {
-case SPA_PCI_ID:
-tr_wr(tr, SPA_REG_GPIO, 0, 4);
-tr_wr(tr, SPA_REG_CODECST, SPA_RST_OFF, 4);
-break;
-case TDX_PCI_ID:
-tr_wr(tr, TDX_REG_CODECST, TDX_CDC_ON, 4);
-break;
-case TNX_PCI_ID:
-tr_wr(tr, TNX_REG_CODECST, TNX_CDC_ON, 4);
-break;
-}
+ switch (tr->type) {
+ case SPA_PCI_ID:
+ tr_wr(tr, SPA_REG_GPIO, 0, 4);
+ tr_wr(tr, SPA_REG_CODECST, SPA_RST_OFF, 4);
+ break;
+ case TDX_PCI_ID:
+ tr_wr(tr, TDX_REG_CODECST, TDX_CDC_ON, 4);
+ break;
+ case TNX_PCI_ID:
+ tr_wr(tr, TNX_REG_CODECST, TNX_CDC_ON, 4);
+ break;
+ }
-tr_wr(tr, TR_REG_CIR, TR_CIR_MIDENA | TR_CIR_ADDRENA, 4);
-return 0;
+ tr_wr(tr, TR_REG_CIR, TR_CIR_MIDENA | TR_CIR_ADDRENA, 4);
+ return 0;
}
static int
tr_pci_probe(device_t dev)
{
-switch (pci_get_devid(dev)) {
-case SPA_PCI_ID:
-device_set_desc(dev, "SiS 7018");
-return BUS_PROBE_DEFAULT;
-case ALI_PCI_ID:
-device_set_desc(dev, "Acer Labs M5451");
-return BUS_PROBE_DEFAULT;
-case TDX_PCI_ID:
-device_set_desc(dev, "Trident 4DWave DX");
-return BUS_PROBE_DEFAULT;
-case TNX_PCI_ID:
-device_set_desc(dev, "Trident 4DWave NX");
-return BUS_PROBE_DEFAULT;
-}
+ switch (pci_get_devid(dev)) {
+ case SPA_PCI_ID:
+ device_set_desc(dev, "SiS 7018");
+ return BUS_PROBE_DEFAULT;
+ case ALI_PCI_ID:
+ device_set_desc(dev, "Acer Labs M5451");
+ return BUS_PROBE_DEFAULT;
+ case TDX_PCI_ID:
+ device_set_desc(dev, "Trident 4DWave DX");
+ return BUS_PROBE_DEFAULT;
+ case TNX_PCI_ID:
+ device_set_desc(dev, "Trident 4DWave NX");
+ return BUS_PROBE_DEFAULT;
+ }
-return ENXIO;
+ return ENXIO;
}
static int
tr_pci_attach(device_t dev)
{
-u_int32_t data;
-struct tr_info *tr;
-struct ac97_info *codec = 0;
-int i;
-char status[SND_STATUSLEN];
-
-if ((tr = malloc(sizeof(*tr), M_DEVBUF, M_NOWAIT | M_ZERO)) == NULL) {
-device_printf(dev, "cannot allocate softcn");
-return ENXIO;
-}
-
-tr->type = pci_get_devid(dev);
-tr->rev = pci_get_revid(dev);
-tr->lock = snd_mtxcreate(device_get_nameunit(dev), "sound softc");
-
-data = pci_read_config(dev, PCIR_COMMAND, 2);
-data |= (PCIM_CMD_PORTEN|PCIM_CMD_MEMEN|PCIM_CMD_BUSMASTEREN);
-pci_write_config(dev, PCIR_COMMAND, data, 2);
-data = pci_read_config(dev, PCIR_COMMAND, 2);
-
-tr->regid = PCIR_BAR(0);
-tr->regtype = SYS_RES_IOPORT;
-tr->reg = bus_alloc_resource_any(dev, tr->regtype, &tr->regid,
-RF_ACTIVE);
-if (tr->reg) {
-tr->st = rman_get_bustag(tr->reg);
-tr->sh = rman_get_bushandle(tr->reg);
-} else {
-device_printf(dev, "unable to map register spacen");
-goto bad;
-}
-
-tr->bufsz = pcm_getbuffersize(dev, 4096, TR_DEFAULT_BUFSZ, 65536);
-
-if (tr_init(tr) == -1) {
-device_printf(dev, "unable to initialize the cardn");
-goto bad;
-}
-tr->playchns = 0;
-
-codec = AC97_CREATE(dev, tr, tr_ac97);
-if (codec == NULL) goto bad;
-if (mixer_init(dev, ac97_getmixerclass(), codec) == -1) goto bad;
-
-tr->irqid = 0;
-tr->irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &tr->irqid,
-RF_ACTIVE | RF_SHAREABLE);
-if (!tr->irq || snd_setup_intr(dev, tr->irq, 0, tr_intr, tr, &tr->ih)) {
-device_printf(dev, "unable to map interruptn");
-goto bad;
-}
-
-if (bus_dma_tag_create(/*parent*/NULL, /*alignment*/2, /*boundary*/0,
-/*lowaddr*/TR_MAXADDR,
-/*highaddr*/BUS_SPACE_MAXADDR,
-/*filter*/NULL, /*filterarg*/NULL,
-/*maxsize*/tr->bufsz, /*nsegments*/1, /*maxsegz*/0x3ffff,
-/*flags*/0, /*lockfunc*/busdma_lock_mutex,
-/*lockarg*/&Giant, &tr->parent_dmat) != 0) {
-device_printf(dev, "unable to create dma tagn");
-goto bad;
-}
-
-snprintf(status, 64, "at io 0x%lx irq %ld %s",
-rman_get_start(tr->reg), rman_get_start(tr->irq),PCM_KLDSTRING(snd_t4dwave));
-
-if (pcm_register(dev, tr, TR_MAXPLAYCH, 1)) goto bad;
-pcm_addchan(dev, PCMDIR_REC, &trrchan_class, tr);
-for (i = 0; i < TR_MAXPLAYCH; i++)
-pcm_addchan(dev, PCMDIR_PLAY, &trpchan_class, tr);
-pcm_setstatus(dev, status);
+ u_int32_t data;
+ struct tr_info *tr;
+ struct ac97_info *codec = 0;
+ int i, dacn;
+ char status[SND_STATUSLEN];
+
+ tr = malloc(sizeof(*tr), M_DEVBUF, M_WAITOK | M_ZERO);
+ tr->type = pci_get_devid(dev);
+ tr->rev = pci_get_revid(dev);
+ tr->lock = snd_mtxcreate(device_get_nameunit(dev), "snd_t4dwave softc");
+
+ if (resource_int_value(device_get_name(dev), device_get_unit(dev),
+ "dac", &i) == 0) {
+ if (i < 1)
+ dacn = 1;
+ else if (i > TR_MAXPLAYCH)
+ dacn = TR_MAXPLAYCH;
+ else
+ dacn = i;
+ } else {
+ switch (tr->type) {
+ case ALI_PCI_ID:
+ dacn = 1;
+ break;
+ default:
+ dacn = TR_MAXPLAYCH;
+ break;
+ }
+ }
+
+ data = pci_read_config(dev, PCIR_COMMAND, 2);
+ data |= (PCIM_CMD_PORTEN|PCIM_CMD_MEMEN|PCIM_CMD_BUSMASTEREN);
+ pci_write_config(dev, PCIR_COMMAND, data, 2);
+ data = pci_read_config(dev, PCIR_COMMAND, 2);
+
+ tr->regid = PCIR_BAR(0);
+ tr->regtype = SYS_RES_IOPORT;
+ tr->reg = bus_alloc_resource_any(dev, tr->regtype, &tr->regid,
+ RF_ACTIVE);
+ if (tr->reg) {
+ tr->st = rman_get_bustag(tr->reg);
+ tr->sh = rman_get_bushandle(tr->reg);
+ } else {
+ device_printf(dev, "unable to map register space\n");
+ goto bad;
+ }
+
+ tr->bufsz = pcm_getbuffersize(dev, 4096, TR_DEFAULT_BUFSZ, 65536);
+
+ if (tr_init(tr) == -1) {
+ device_printf(dev, "unable to initialize the card\n");
+ goto bad;
+ }
+ tr->playchns = 0;
+
+ codec = AC97_CREATE(dev, tr, tr_ac97);
+ if (codec == NULL) goto bad;
+ if (mixer_init(dev, ac97_getmixerclass(), codec) == -1) goto bad;
+
+ tr->irqid = 0;
+ tr->irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &tr->irqid,
+ RF_ACTIVE | RF_SHAREABLE);
+ if (!tr->irq || snd_setup_intr(dev, tr->irq, 0, tr_intr, tr, &tr->ih)) {
+ device_printf(dev, "unable to map interrupt\n");
+ goto bad;
+ }
+
+ if (bus_dma_tag_create(/*parent*/bus_get_dma_tag(dev), /*alignment*/2,
+ /*boundary*/0,
+ /*lowaddr*/TR_MAXADDR,
+ /*highaddr*/BUS_SPACE_MAXADDR,
+ /*filter*/NULL, /*filterarg*/NULL,
+ /*maxsize*/tr->bufsz, /*nsegments*/1, /*maxsegz*/0x3ffff,
+ /*flags*/0, /*lockfunc*/busdma_lock_mutex,
+ /*lockarg*/&Giant, &tr->parent_dmat) != 0) {
+ device_printf(dev, "unable to create dma tag\n");
+ goto bad;
+ }
+
+ snprintf(status, 64, "at io 0x%lx irq %ld %s",
+ rman_get_start(tr->reg), rman_get_start(tr->irq),PCM_KLDSTRING(snd_t4dwave));
+
+ if (pcm_register(dev, tr, dacn, 1))
+ goto bad;
+ pcm_addchan(dev, PCMDIR_REC, &trrchan_class, tr);
+ for (i = 0; i < dacn; i++)
+ pcm_addchan(dev, PCMDIR_PLAY, &trpchan_class, tr);
+ pcm_setstatus(dev, status);
-return 0;
+ return 0;
bad:
-if (codec) ac97_destroy(codec);
-if (tr->reg) bus_release_resource(dev, tr->regtype, tr->regid, tr->reg);
-if (tr->ih) bus_teardown_intr(dev, tr->irq, tr->ih);
-if (tr->irq) bus_release_resource(dev, SYS_RES_IRQ, tr->irqid, tr->irq);
-if (tr->parent_dmat) bus_dma_tag_destroy(tr->parent_dmat);
-if (tr->lock) snd_mtxfree(tr->lock);
-free(tr, M_DEVBUF);
-return ENXIO;
+ if (codec) ac97_destroy(codec);
+ if (tr->reg) bus_release_resource(dev, tr->regtype, tr->regid, tr->reg);
+ if (tr->ih) bus_teardown_intr(dev, tr->irq, tr->ih);
+ if (tr->irq) bus_release_resource(dev, SYS_RES_IRQ, tr->irqid, tr->irq);
+ if (tr->parent_dmat) bus_dma_tag_destroy(tr->parent_dmat);
+ if (tr->lock) snd_mtxfree(tr->lock);
+ free(tr, M_DEVBUF);
+ return ENXIO;
}
static int
tr_pci_detach(device_t dev)
{
-int r;
-struct tr_info *tr;
+ int r;
+ struct tr_info *tr;
-r = pcm_unregister(dev);
-if (r)
-return r;
-
-tr = pcm_getdevinfo(dev);
-bus_release_resource(dev, tr->regtype, tr->regid, tr->reg);
-bus_teardown_intr(dev, tr->irq, tr->ih);
-bus_release_resource(dev, SYS_RES_IRQ, tr->irqid, tr->irq);
-bus_dma_tag_destroy(tr->parent_dmat);
-snd_mtxfree(tr->lock);
-free(tr, M_DEVBUF);
+ r = pcm_unregister(dev);
+ if (r)
+ return r;
+
+ tr = pcm_getdevinfo(dev);
+ bus_release_resource(dev, tr->regtype, tr->regid, tr->reg);
+ bus_teardown_intr(dev, tr->irq, tr->ih);
+ bus_release_resource(dev, SYS_RES_IRQ, tr->irqid, tr->irq);
+ bus_dma_tag_destroy(tr->parent_dmat);
+ snd_mtxfree(tr->lock);
+ free(tr, M_DEVBUF);
-return 0;
+ return 0;
}
static int
tr_pci_suspend(device_t dev)
{
-int i;
-struct tr_info *tr;
+ int i;
+ struct tr_info *tr;
-tr = pcm_getdevinfo(dev);
+ tr = pcm_getdevinfo(dev);
-for (i = 0; i < tr->playchns; i++) {
-tr->chinfo[i].was_active = tr->chinfo[i].active;
-if (tr->chinfo[i].active) {
-trpchan_trigger(NULL, &tr->chinfo[i], PCMTRIG_STOP);
-}
-}
-
-tr->recchinfo.was_active = tr->recchinfo.active;
-if (tr->recchinfo.active) {
-trrchan_trigger(NULL, &tr->recchinfo, PCMTRIG_STOP);
-}
+ for (i = 0; i < tr->playchns; i++) {
+ tr->chinfo[i].was_active = tr->chinfo[i].active;
+ if (tr->chinfo[i].active) {
+ trpchan_trigger(NULL, &tr->chinfo[i], PCMTRIG_STOP);
+ }
+ }
+
+ tr->recchinfo.was_active = tr->recchinfo.active;
+ if (tr->recchinfo.active) {
+ trrchan_trigger(NULL, &tr->recchinfo, PCMTRIG_STOP);
+ }
-return 0;
+ return 0;
}
static int
tr_pci_resume(device_t dev)
{
-int i;
-struct tr_info *tr;
-
-tr = pcm_getdevinfo(dev);
-
-if (tr_init(tr) == -1) {
-device_printf(dev, "unable to initialize the cardn");
-return ENXIO;
-}
-
-if (mixer_reinit(dev) == -1) {
-device_printf(dev, "unable to initialize the mixern");
-return ENXIO;
-}
+ int i;
+ struct tr_info *tr;
-for (i = 0; i < tr->playchns; i++) {
-if (tr->chinfo[i].was_active) {
-trpchan_trigger(NULL, &tr->chinfo[i], PCMTRIG_START);
-}
-}
+ tr = pcm_getdevinfo(dev);
-if (tr->recchinfo.was_active) {
-trrchan_trigger(NULL, &tr->recchinfo, PCMTRIG_START);
-}
+ if (tr_init(tr) == -1) {
+ device_printf(dev, "unable to initialize the card\n");
+ return ENXIO;
+ }
+
+ if (mixer_reinit(dev) == -1) {
+ device_printf(dev, "unable to initialize the mixer\n");
+ return ENXIO;
+ }
+
+ for (i = 0; i < tr->playchns; i++) {
+ if (tr->chinfo[i].was_active) {
+ trpchan_trigger(NULL, &tr->chinfo[i], PCMTRIG_START);
+ }
+ }
+
+ if (tr->recchinfo.was_active) {
+ trrchan_trigger(NULL, &tr->recchinfo, PCMTRIG_START);
+ }
-return 0;
+ return 0;
}
static device_method_t tr_methods[] = {
-/* Device interface */
-DEVMETHOD(device_probe, tr_pci_probe),
-DEVMETHOD(device_attach, tr_pci_attach),
-DEVMETHOD(device_detach, tr_pci_detach),
-DEVMETHOD(device_suspend, tr_pci_suspend),
-DEVMETHOD(device_resume, tr_pci_resume),
-{ 0, 0 }
+ /* Device interface */
+ DEVMETHOD(device_probe, tr_pci_probe),
+ DEVMETHOD(device_attach, tr_pci_attach),
+ DEVMETHOD(device_detach, tr_pci_detach),
+ DEVMETHOD(device_suspend, tr_pci_suspend),
+ DEVMETHOD(device_resume, tr_pci_resume),
+ { 0, 0 }
};
static driver_t tr_driver = {
-"pcm",
-tr_methods,
-PCM_SOFTC_SIZE,
+ "pcm",
+ tr_methods,
+ PCM_SOFTC_SIZE,
};
DRIVER_MODULE(snd_t4dwave, pci, tr_driver, pcm_devclass, 0, 0);
Index: csareg.h
===================================================================
RCS file: /home/cvs/src/sys/dev/sound/pci/csareg.h,v
retrieving revision 1.2
retrieving revision 1.3
diff -L sys/dev/sound/pci/csareg.h -L sys/dev/sound/pci/csareg.h -u -r1.2 -r1.3
--- sys/dev/sound/pci/csareg.h
+++ sys/dev/sound/pci/csareg.h
@@ -1,50 +1,49 @@
/*-
-* Copyright (c) 1999 Seigo Tanimura
-* All rights reserved.
-*
-* Portions of this source are based on hwdefs.h in cwcealdr1.zip, the
-* sample source by Crystal Semiconductor.
-* Copyright (c) 1996-1998 Crystal Semiconductor Corp.
-*
-* Redistribution and use in source and binary forms, with or without
-* modification, are permitted provided that the following conditions
-* are met:
-* 1. Redistributions of source code must retain the above copyright
-* notice, this list of conditions and the following disclaimer.
-* 2. Redistributions in binary form must reproduce the above copyright
-* notice, this list of conditions and the following disclaimer in the
-* documentation and/or other materials provided with the distribution.
-*
-* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
-* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
-* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
-* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
-* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
-* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
-* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
-* SUCH DAMAGE.
-*
-* $MidnightBSD$
-* $FreeBSD: src/sys/dev/sound/pci/csareg.h,v 1.4 2005/06/27 07:43:57 glebius Exp $
-*/
+ * Copyright (c) 1999 Seigo Tanimura
+ * All rights reserved.
+ *
+ * Portions of this source are based on hwdefs.h in cwcealdr1.zip, the
+ * sample source by Crystal Semiconductor.
+ * Copyright (c) 1996-1998 Crystal Semiconductor Corp.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD: src/sys/dev/sound/pci/csareg.h,v 1.4 2005/06/27 07:43:57 glebius Exp $
+ */
#ifndef _CSA_REG_H
#define _CSA_REG_H
/*
-* The following constats are orginally in the sample by Crystal Semiconductor.
-* Copyright (c) 1996-1998 Crystal Semiconductor Corp.
-*/
+ * The following constats are orginally in the sample by Crystal Semiconductor.
+ * Copyright (c) 1996-1998 Crystal Semiconductor Corp.
+ */
/*****************************************************************************
-*
-* The following define the offsets of the registers accessed via base address
-* register zero on the CS461x part.
-*
-*****************************************************************************/
+ *
+ * The following define the offsets of the registers accessed via base address
+ * register zero on the CS461x part.
+ *
+ *****************************************************************************/
#define BA0_HISR 0x00000000L
#define BA0_HSR0 0x00000004L
#define BA0_HICR 0x00000008L
@@ -170,11 +169,11 @@
#endif
/*****************************************************************************
-*
-* The following define the offsets of the AC97 shadow registers, which appear
-* as a virtual extension to the base address register zero memory range.
-*
-*****************************************************************************/
+ *
+ * The following define the offsets of the AC97 shadow registers, which appear
+ * as a virtual extension to the base address register zero memory range.
+ *
+ *****************************************************************************/
#define BA0_AC97_RESET 0x00001000L
#define BA0_AC97_MASTER_VOLUME 0x00001002L
#define BA0_AC97_HEADPHONE_VOLUME 0x00001004L
@@ -241,11 +240,11 @@
#define BA0_AC97_VENDOR_ID2 0x0000107EL
/*****************************************************************************
-*
-* The following define the offsets of the registers and memories accessed via
-* base address register one on the CS461x part.
-*
-*****************************************************************************/
+ *
+ * The following define the offsets of the registers and memories accessed via
+ * base address register one on the CS461x part.
+ *
+ *****************************************************************************/
#define BA1_SP_DMEM0 0x00000000L
#define BA1_SP_DMEM1 0x00010000L
#define BA1_SP_PMEM 0x00020000L
@@ -264,10 +263,10 @@
#define BA1_OMNI_MEM 0x000E0000L
/*****************************************************************************
-*
-* The following defines are for the flags in the PCI interrupt register.
-*
-*****************************************************************************/
+ *
+ * The following defines are for the flags in the PCI interrupt register.
+ *
+ *****************************************************************************/
#define PI_LINE_MASK 0x000000FFL
#define PI_PIN_MASK 0x0000FF00L
#define PI_MIN_GRANT_MASK 0x00FF0000L
@@ -278,11 +277,11 @@
#define PI_MAX_LATENCY_SHIFT 24L
/*****************************************************************************
-*
-* The following defines are for the flags in the host interrupt status
-* register.
-*
-*****************************************************************************/
+ *
+ * The following defines are for the flags in the host interrupt status
+ * register.
+ *
+ *****************************************************************************/
#define HISR_VC_MASK 0x0000FFFFL
#define HISR_VC0 0x00000001L
#define HISR_VC1 0x00000002L
@@ -315,10 +314,10 @@
#define HISR_INTENA 0x80000000L
/*****************************************************************************
-*
-* The following defines are for the flags in the host signal register 0.
-*
-*****************************************************************************/
+ *
+ * The following defines are for the flags in the host signal register 0.
+ *
+ *****************************************************************************/
#define HSR0_VC_MASK 0xFFFFFFFFL
#define HSR0_VC16 0x00000001L
#define HSR0_VC17 0x00000002L
@@ -354,30 +353,30 @@
#define HSR0_VC47 0x80000000L
/*****************************************************************************
-*
-* The following defines are for the flags in the host interrupt control
-* register.
-*
-*****************************************************************************/
+ *
+ * The following defines are for the flags in the host interrupt control
+ * register.
+ *
+ *****************************************************************************/
#define HICR_IEV 0x00000001L
#define HICR_CHGM 0x00000002L
/*****************************************************************************
-*
-* The following defines are for the flags in the DMA status register.
-*
-*****************************************************************************/
+ *
+ * The following defines are for the flags in the DMA status register.
+ *
+ *****************************************************************************/
#define DMSR_HP 0x00000001L
#define DMSR_HR 0x00000002L
#define DMSR_SP 0x00000004L
#define DMSR_SR 0x00000008L
/*****************************************************************************
-*
-* The following defines are for the flags in the host DMA source address
-* register.
-*
-*****************************************************************************/
+ *
+ * The following defines are for the flags in the host DMA source address
+ * register.
+ *
+ *****************************************************************************/
#define HSAR_HOST_ADDR_MASK 0xFFFFFFFFL
#define HSAR_DSP_ADDR_MASK 0x0000FFFFL
#define HSAR_MEMID_MASK 0x000F0000L
@@ -390,11 +389,11 @@
#define HSAR_ERR 0x80000000L
/*****************************************************************************
-*
-* The following defines are for the flags in the host DMA destination address
-* register.
-*
-*****************************************************************************/
+ *
+ * The following defines are for the flags in the host DMA destination address
+ * register.
+ *
+ *****************************************************************************/
#define HDAR_HOST_ADDR_MASK 0xFFFFFFFFL
#define HDAR_DSP_ADDR_MASK 0x0000FFFFL
#define HDAR_MEMID_MASK 0x000F0000L
@@ -407,10 +406,10 @@
#define HDAR_ERR 0x80000000L
/*****************************************************************************
-*
-* The following defines are for the flags in the host DMA control register.
-*
-*****************************************************************************/
+ *
+ * The following defines are for the flags in the host DMA control register.
+ *
+ *****************************************************************************/
#define HDMR_AC_MASK 0x0000F000L
#define HDMR_AC_8_16 0x00001000L
#define HDMR_AC_M_S 0x00002000L
@@ -418,10 +417,10 @@
#define HDMR_AC_S_U 0x00008000L
/*****************************************************************************
-*
-* The following defines are for the flags in the host DMA control register.
-*
-*****************************************************************************/
+ *
+ * The following defines are for the flags in the host DMA control register.
+ *
+ *****************************************************************************/
#define HDCR_COUNT_MASK 0x000003FFL
#define HDCR_DONE 0x00004000L
#define HDCR_OPT 0x00008000L
@@ -450,11 +449,11 @@
#define HDCR_COUNT_SHIFT 0L
/*****************************************************************************
-*
-* The following defines are for the flags in the performance monitor control
-* register.
-*
-*****************************************************************************/
+ *
+ * The following defines are for the flags in the performance monitor control
+ * register.
+ *
+ *****************************************************************************/
#define PFMC_C1SS_MASK 0x0000001FL
#define PFMC_C1EV 0x00000020L
#define PFMC_C1RS 0x00008000L
@@ -479,28 +478,28 @@
#define PFMC_SP_CLOCK 13L
/*****************************************************************************
-*
-* The following defines are for the flags in the performance counter value 1
-* register.
-*
-*****************************************************************************/
+ *
+ * The following defines are for the flags in the performance counter value 1
+ * register.
+ *
+ *****************************************************************************/
#define PFCV1_PC1V_MASK 0xFFFFFFFFL
#define PFCV1_PC1V_SHIFT 0L
/*****************************************************************************
-*
-* The following defines are for the flags in the performance counter value 2
-* register.
-*
-*****************************************************************************/
+ *
+ * The following defines are for the flags in the performance counter value 2
+ * register.
+ *
+ *****************************************************************************/
#define PFCV2_PC2V_MASK 0xFFFFFFFFL
#define PFCV2_PC2V_SHIFT 0L
/*****************************************************************************
-*
-* The following defines are for the flags in the clock control register 1.
-*
-*****************************************************************************/
+ *
+ * The following defines are for the flags in the clock control register 1.
+ *
+ *****************************************************************************/
#define CLKCR1_OSCS 0x00000001L
#define CLKCR1_OSCP 0x00000002L
#define CLKCR1_PLLSS_MASK 0x0000000CL
@@ -513,10 +512,10 @@
#define CLKCR1_PLLOS 0x00000040L
/*****************************************************************************
-*
-* The following defines are for the flags in the clock control register 2.
-*
-*****************************************************************************/
+ *
+ * The following defines are for the flags in the clock control register 2.
+ *
+ *****************************************************************************/
#define CLKCR2_PDIVS_MASK 0x0000000FL
#define CLKCR2_PDIVS_1 0x00000001L
#define CLKCR2_PDIVS_2 0x00000002L
@@ -526,19 +525,19 @@
#define CLKCR2_PDIVS_16 0x00000000L
/*****************************************************************************
-*
-* The following defines are for the flags in the PLL multiplier register.
-*
-*****************************************************************************/
+ *
+ * The following defines are for the flags in the PLL multiplier register.
+ *
+ *****************************************************************************/
#define PLLM_MASK 0x000000FFL
#define PLLM_SHIFT 0L
/*****************************************************************************
-*
-* The following defines are for the flags in the PLL capacitor coefficient
-* register.
-*
-*****************************************************************************/
+ *
+ * The following defines are for the flags in the PLL capacitor coefficient
+ * register.
+ *
+ *****************************************************************************/
#define PLLCC_CDR_MASK 0x00000007L
#ifndef NO_CS4610
#define PLLCC_CDR_240_350_MHZ 0x00000000L
@@ -579,10 +578,10 @@
#endif
/*****************************************************************************
-*
-* The following defines are for the flags in the feature reporting register.
-*
-*****************************************************************************/
+ *
+ * The following defines are for the flags in the feature reporting register.
+ *
+ *****************************************************************************/
#define FRR_FAB_MASK 0x00000003L
#define FRR_MASK_MASK 0x0000001CL
#ifdef NO_CS4612
@@ -601,11 +600,11 @@
#define FRR_CFOP_SHIFT 5L
/*****************************************************************************
-*
-* The following defines are for the flags in the configuration load 1
-* register.
-*
-*****************************************************************************/
+ *
+ * The following defines are for the flags in the configuration load 1
+ * register.
+ *
+ *****************************************************************************/
#define CFL1_CLOCK_SOURCE_MASK 0x00000003L
#define CFL1_CLOCK_SOURCE_CS423X 0x00000000L
#define CFL1_CLOCK_SOURCE_AC97 0x00000001L
@@ -614,19 +613,19 @@
#define CFL1_VALID_DATA_MASK 0x000000FFL
/*****************************************************************************
-*
-* The following defines are for the flags in the configuration load 2
-* register.
-*
-*****************************************************************************/
+ *
+ * The following defines are for the flags in the configuration load 2
+ * register.
+ *
+ *****************************************************************************/
#define CFL2_VALID_DATA_MASK 0x000000FFL
/*****************************************************************************
-*
-* The following defines are for the flags in the serial port master control
-* register 1.
-*
-*****************************************************************************/
+ *
+ * The following defines are for the flags in the serial port master control
+ * register 1.
+ *
+ *****************************************************************************/
#define SERMC1_MSPE 0x00000001L
#define SERMC1_PTC_MASK 0x0000000EL
#define SERMC1_PTC_CS423X 0x00000000L
@@ -636,21 +635,21 @@
#define SERMC1_XLB 0x00000020L
/*****************************************************************************
-*
-* The following defines are for the flags in the serial port master control
-* register 2.
-*
-*****************************************************************************/
+ *
+ * The following defines are for the flags in the serial port master control
+ * register 2.
+ *
+ *****************************************************************************/
#define SERMC2_LROE 0x00000001L
#define SERMC2_MCOE 0x00000002L
#define SERMC2_MCDIV 0x00000004L
/*****************************************************************************
-*
-* The following defines are for the flags in the serial port 1 configuration
-* register.
-*
-*****************************************************************************/
+ *
+ * The following defines are for the flags in the serial port 1 configuration
+ * register.
+ *
+ *****************************************************************************/
#define SERC1_SO1EN 0x00000001L
#define SERC1_SO1F_MASK 0x0000000EL
#define SERC1_SO1F_CS423X 0x00000000L
@@ -659,11 +658,11 @@
#define SERC1_SO1F_SPDIF 0x00000006L
/*****************************************************************************
-*
-* The following defines are for the flags in the serial port 2 configuration
-* register.
-*
-*****************************************************************************/
+ *
+ * The following defines are for the flags in the serial port 2 configuration
+ * register.
+ *
+ *****************************************************************************/
#define SERC2_SI1EN 0x00000001L
#define SERC2_SI1F_MASK 0x0000000EL
#define SERC2_SI1F_CS423X 0x00000000L
@@ -672,71 +671,71 @@
#define SERC2_SI1F_SPDIF 0x00000006L
/*****************************************************************************
-*
-* The following defines are for the flags in the serial port 3 configuration
-* register.
-*
-*****************************************************************************/
+ *
+ * The following defines are for the flags in the serial port 3 configuration
+ * register.
+ *
+ *****************************************************************************/
#define SERC3_SO2EN 0x00000001L
#define SERC3_SO2F_MASK 0x00000006L
#define SERC3_SO2F_DAC 0x00000000L
#define SERC3_SO2F_SPDIF 0x00000002L
/*****************************************************************************
-*
-* The following defines are for the flags in the serial port 4 configuration
-* register.
-*
-*****************************************************************************/
+ *
+ * The following defines are for the flags in the serial port 4 configuration
+ * register.
+ *
+ *****************************************************************************/
#define SERC4_SO3EN 0x00000001L
#define SERC4_SO3F_MASK 0x00000006L
#define SERC4_SO3F_DAC 0x00000000L
#define SERC4_SO3F_SPDIF 0x00000002L
/*****************************************************************************
-*
-* The following defines are for the flags in the serial port 5 configuration
-* register.
-*
-*****************************************************************************/
+ *
+ * The following defines are for the flags in the serial port 5 configuration
+ * register.
+ *
+ *****************************************************************************/
#define SERC5_SI2EN 0x00000001L
#define SERC5_SI2F_MASK 0x00000006L
#define SERC5_SI2F_ADC 0x00000000L
#define SERC5_SI2F_SPDIF 0x00000002L
/*****************************************************************************
-*
-* The following defines are for the flags in the serial port backdoor sample
-* pointer register.
-*
-*****************************************************************************/
+ *
+ * The following defines are for the flags in the serial port backdoor sample
+ * pointer register.
+ *
+ *****************************************************************************/
#define SERBSP_FSP_MASK 0x0000000FL
#define SERBSP_FSP_SHIFT 0L
/*****************************************************************************
-*
-* The following defines are for the flags in the serial port backdoor status
-* register.
-*
-*****************************************************************************/
+ *
+ * The following defines are for the flags in the serial port backdoor status
+ * register.
+ *
+ *****************************************************************************/
#define SERBST_RRDY 0x00000001L
#define SERBST_WBSY 0x00000002L
/*****************************************************************************
-*
-* The following defines are for the flags in the serial port backdoor command
-* register.
-*
-*****************************************************************************/
+ *
+ * The following defines are for the flags in the serial port backdoor command
+ * register.
+ *
+ *****************************************************************************/
#define SERBCM_RDC 0x00000001L
#define SERBCM_WRC 0x00000002L
/*****************************************************************************
-*
-* The following defines are for the flags in the serial port backdoor address
-* register.
-*
-*****************************************************************************/
+ *
+ * The following defines are for the flags in the serial port backdoor address
+ * register.
+ *
+ *****************************************************************************/
#ifdef NO_CS4612
#define SERBAD_FAD_MASK 0x000000FFL
#else
@@ -745,36 +744,36 @@
#define SERBAD_FAD_SHIFT 0L
/*****************************************************************************
-*
-* The following defines are for the flags in the serial port backdoor
-* configuration register.
-*
-*****************************************************************************/
+ *
+ * The following defines are for the flags in the serial port backdoor
+ * configuration register.
+ *
+ *****************************************************************************/
#define SERBCF_HBP 0x00000001L
/*****************************************************************************
-*
-* The following defines are for the flags in the serial port backdoor write
-* port register.
-*
-*****************************************************************************/
+ *
+ * The following defines are for the flags in the serial port backdoor write
+ * port register.
+ *
+ *****************************************************************************/
#define SERBWP_FWD_MASK 0x000FFFFFL
#define SERBWP_FWD_SHIFT 0L
/*****************************************************************************
-*
-* The following defines are for the flags in the serial port backdoor read
-* port register.
-*
-*****************************************************************************/
+ *
+ * The following defines are for the flags in the serial port backdoor read
+ * port register.
+ *
+ *****************************************************************************/
#define SERBRP_FRD_MASK 0x000FFFFFL
#define SERBRP_FRD_SHIFT 0L
/*****************************************************************************
-*
-* The following defines are for the flags in the async FIFO address register.
-*
-*****************************************************************************/
+ *
+ * The following defines are for the flags in the async FIFO address register.
+ *
+ *****************************************************************************/
#ifndef NO_CS4612
#define ASER_FADDR_A1_MASK 0x000001FFL
#define ASER_FADDR_EN1 0x00008000L
@@ -785,10 +784,10 @@
#endif
/*****************************************************************************
-*
-* The following defines are for the flags in the AC97 control register.
-*
-*****************************************************************************/
+ *
+ * The following defines are for the flags in the AC97 control register.
+ *
+ *****************************************************************************/
#define ACCTL_RSTN 0x00000001L
#define ACCTL_ESYN 0x00000002L
#define ACCTL_VFRM 0x00000004L
@@ -800,10 +799,10 @@
#endif
/*****************************************************************************
-*
-* The following defines are for the flags in the AC97 status register.
-*
-*****************************************************************************/
+ *
+ * The following defines are for the flags in the AC97 status register.
+ *
+ *****************************************************************************/
#define ACSTS_CRDY 0x00000001L
#define ACSTS_VSTS 0x00000002L
#ifndef NO_CS4612
@@ -811,11 +810,11 @@
#endif
/*****************************************************************************
-*
-* The following defines are for the flags in the AC97 output slot valid
-* register.
-*
-*****************************************************************************/
+ *
+ * The following defines are for the flags in the AC97 output slot valid
+ * register.
+ *
+ *****************************************************************************/
#define ACOSV_SLV3 0x00000001L
#define ACOSV_SLV4 0x00000002L
#define ACOSV_SLV5 0x00000004L
@@ -828,28 +827,28 @@
#define ACOSV_SLV12 0x00000200L
/*****************************************************************************
-*
-* The following defines are for the flags in the AC97 command address
-* register.
-*
-*****************************************************************************/
+ *
+ * The following defines are for the flags in the AC97 command address
+ * register.
+ *
+ *****************************************************************************/
#define ACCAD_CI_MASK 0x0000007FL
#define ACCAD_CI_SHIFT 0L
/*****************************************************************************
-*
-* The following defines are for the flags in the AC97 command data register.
-*
-*****************************************************************************/
+ *
+ * The following defines are for the flags in the AC97 command data register.
+ *
+ *****************************************************************************/
#define ACCDA_CD_MASK 0x0000FFFFL
#define ACCDA_CD_SHIFT 0L
/*****************************************************************************
-*
-* The following defines are for the flags in the AC97 input slot valid
-* register.
-*
-*****************************************************************************/
+ *
+ * The following defines are for the flags in the AC97 input slot valid
+ * register.
+ *
+ *****************************************************************************/
#define ACISV_ISV3 0x00000001L
#define ACISV_ISV4 0x00000002L
#define ACISV_ISV5 0x00000004L
@@ -862,28 +861,28 @@
#define ACISV_ISV12 0x00000200L
/*****************************************************************************
-*
-* The following defines are for the flags in the AC97 status address
-* register.
-*
-*****************************************************************************/
+ *
+ * The following defines are for the flags in the AC97 status address
+ * register.
+ *
+ *****************************************************************************/
#define ACSAD_SI_MASK 0x0000007FL
#define ACSAD_SI_SHIFT 0L
/*****************************************************************************
-*
-* The following defines are for the flags in the AC97 status data register.
-*
-*****************************************************************************/
+ *
+ * The following defines are for the flags in the AC97 status data register.
+ *
+ *****************************************************************************/
#define ACSDA_SD_MASK 0x0000FFFFL
#define ACSDA_SD_SHIFT 0L
/*****************************************************************************
-*
-* The following defines are for the flags in the joystick poll/trigger
-* register.
-*
-*****************************************************************************/
+ *
+ * The following defines are for the flags in the joystick poll/trigger
+ * register.
+ *
+ *****************************************************************************/
#define JSPT_CAX 0x00000001L
#define JSPT_CAY 0x00000002L
#define JSPT_CBX 0x00000004L
@@ -894,10 +893,10 @@
#define JSPT_BB2 0x00000080L
/*****************************************************************************
-*
-* The following defines are for the flags in the joystick control register.
-*
-*****************************************************************************/
+ *
+ * The following defines are for the flags in the joystick control register.
+ *
+ *****************************************************************************/
#define JSCTL_SP_MASK 0x00000003L
#define JSCTL_SP_SLOW 0x00000000L
#define JSCTL_SP_MEDIUM_SLOW 0x00000001L
@@ -906,32 +905,32 @@
#define JSCTL_ARE 0x00000004L
/*****************************************************************************
-*
-* The following defines are for the flags in the joystick coordinate pair 1
-* readback register.
-*
-*****************************************************************************/
+ *
+ * The following defines are for the flags in the joystick coordinate pair 1
+ * readback register.
+ *
+ *****************************************************************************/
#define JSC1_Y1V_MASK 0x0000FFFFL
#define JSC1_X1V_MASK 0xFFFF0000L
#define JSC1_Y1V_SHIFT 0L
#define JSC1_X1V_SHIFT 16L
/*****************************************************************************
-*
-* The following defines are for the flags in the joystick coordinate pair 2
-* readback register.
-*
-*****************************************************************************/
+ *
+ * The following defines are for the flags in the joystick coordinate pair 2
+ * readback register.
+ *
+ *****************************************************************************/
#define JSC2_Y2V_MASK 0x0000FFFFL
#define JSC2_X2V_MASK 0xFFFF0000L
#define JSC2_Y2V_SHIFT 0L
#define JSC2_X2V_SHIFT 16L
/*****************************************************************************
-*
-* The following defines are for the flags in the MIDI control register.
-*
-*****************************************************************************/
+ *
+ * The following defines are for the flags in the MIDI control register.
+ *
+ *****************************************************************************/
#define MIDCR_TXE 0x00000001L
#define MIDCR_RXE 0x00000002L
#define MIDCR_RIE 0x00000004L
@@ -940,34 +939,34 @@
#define MIDCR_MRST 0x00000020L
/*****************************************************************************
-*
-* The following defines are for the flags in the MIDI status register.
-*
-*****************************************************************************/
+ *
+ * The following defines are for the flags in the MIDI status register.
+ *
+ *****************************************************************************/
#define MIDSR_TBF 0x00000001L
#define MIDSR_RBE 0x00000002L
/*****************************************************************************
-*
-* The following defines are for the flags in the MIDI write port register.
-*
-*****************************************************************************/
+ *
+ * The following defines are for the flags in the MIDI write port register.
+ *
+ *****************************************************************************/
#define MIDWP_MWD_MASK 0x000000FFL
#define MIDWP_MWD_SHIFT 0L
/*****************************************************************************
-*
-* The following defines are for the flags in the MIDI read port register.
-*
-*****************************************************************************/
+ *
+ * The following defines are for the flags in the MIDI read port register.
+ *
+ *****************************************************************************/
#define MIDRP_MRD_MASK 0x000000FFL
#define MIDRP_MRD_SHIFT 0L
/*****************************************************************************
-*
-* The following defines are for the flags in the joystick GPIO register.
-*
-*****************************************************************************/
+ *
+ * The following defines are for the flags in the joystick GPIO register.
+ *
+ *****************************************************************************/
#define JSIO_DAX 0x00000001L
#define JSIO_DAY 0x00000002L
#define JSIO_DBX 0x00000004L
@@ -978,53 +977,53 @@
#define JSIO_BYOE 0x00000080L
/*****************************************************************************
-*
-* The following defines are for the flags in the master async/sync serial
-* port enable register.
-*
-*****************************************************************************/
+ *
+ * The following defines are for the flags in the master async/sync serial
+ * port enable register.
+ *
+ *****************************************************************************/
#ifndef NO_CS4612
#define ASER_MASTER_ME 0x00000001L
#endif
/*****************************************************************************
-*
-* The following defines are for the flags in the configuration interface
-* register.
-*
-*****************************************************************************/
+ *
+ * The following defines are for the flags in the configuration interface
+ * register.
+ *
+ *****************************************************************************/
#define CFGI_CLK 0x00000001L
#define CFGI_DOUT 0x00000002L
#define CFGI_DIN_EEN 0x00000004L
#define CFGI_EELD 0x00000008L
/*****************************************************************************
-*
-* The following defines are for the flags in the subsystem ID and vendor ID
-* register.
-*
-*****************************************************************************/
+ *
+ * The following defines are for the flags in the subsystem ID and vendor ID
+ * register.
+ *
+ *****************************************************************************/
#define SSVID_VID_MASK 0x0000FFFFL
#define SSVID_SID_MASK 0xFFFF0000L
#define SSVID_VID_SHIFT 0L
#define SSVID_SID_SHIFT 16L
/*****************************************************************************
-*
-* The following defines are for the flags in the GPIO pin interface register.
-*
-*****************************************************************************/
+ *
+ * The following defines are for the flags in the GPIO pin interface register.
+ *
+ *****************************************************************************/
#define GPIOR_VOLDN 0x00000001L
#define GPIOR_VOLUP 0x00000002L
#define GPIOR_SI2D 0x00000004L
#define GPIOR_SI2OE 0x00000008L
/*****************************************************************************
-*
-* The following defines are for the flags in the extended GPIO pin direction
-* register.
-*
-*****************************************************************************/
+ *
+ * The following defines are for the flags in the extended GPIO pin direction
+ * register.
+ *
+ *****************************************************************************/
#ifndef NO_CS4612
#define EGPIODR_GPOE0 0x00000001L
#define EGPIODR_GPOE1 0x00000002L
@@ -1038,11 +1037,11 @@
#endif
/*****************************************************************************
-*
-* The following defines are for the flags in the extended GPIO pin polarity/
-* type register.
-*
-*****************************************************************************/
+ *
+ * The following defines are for the flags in the extended GPIO pin polarity/
+ * type register.
+ *
+ *****************************************************************************/
#ifndef NO_CS4612
#define EGPIOPTR_GPPT0 0x00000001L
#define EGPIOPTR_GPPT1 0x00000002L
@@ -1056,11 +1055,11 @@
#endif
/*****************************************************************************
-*
-* The following defines are for the flags in the extended GPIO pin sticky
-* register.
-*
-*****************************************************************************/
+ *
+ * The following defines are for the flags in the extended GPIO pin sticky
+ * register.
+ *
+ *****************************************************************************/
#ifndef NO_CS4612
#define EGPIOTR_GPS0 0x00000001L
#define EGPIOTR_GPS1 0x00000002L
@@ -1074,11 +1073,11 @@
#endif
/*****************************************************************************
-*
-* The following defines are for the flags in the extended GPIO ping wakeup
-* register.
-*
-*****************************************************************************/
+ *
+ * The following defines are for the flags in the extended GPIO ping wakeup
+ * register.
+ *
+ *****************************************************************************/
#ifndef NO_CS4612
#define EGPIOWR_GPW0 0x00000001L
#define EGPIOWR_GPW1 0x00000002L
@@ -1092,11 +1091,11 @@
#endif
/*****************************************************************************
-*
-* The following defines are for the flags in the extended GPIO pin status
-* register.
-*
-*****************************************************************************/
+ *
+ * The following defines are for the flags in the extended GPIO pin status
+ * register.
+ *
+ *****************************************************************************/
#ifndef NO_CS4612
#define EGPIOSR_GPS0 0x00000001L
#define EGPIOSR_GPS1 0x00000002L
@@ -1110,21 +1109,21 @@
#endif
/*****************************************************************************
-*
-* The following defines are for the flags in the serial port 6 configuration
-* register.
-*
-*****************************************************************************/
+ *
+ * The following defines are for the flags in the serial port 6 configuration
+ * register.
+ *
+ *****************************************************************************/
#ifndef NO_CS4612
#define SERC6_ASDO2EN 0x00000001L
#endif
/*****************************************************************************
-*
-* The following defines are for the flags in the serial port 7 configuration
-* register.
-*
-*****************************************************************************/
+ *
+ * The following defines are for the flags in the serial port 7 configuration
+ * register.
+ *
+ *****************************************************************************/
#ifndef NO_CS4612
#define SERC7_ASDI2EN 0x00000001L
#define SERC7_POSILB 0x00000002L
@@ -1134,11 +1133,11 @@
#endif
/*****************************************************************************
-*
-* The following defines are for the flags in the serial port AC link
-* configuration register.
-*
-*****************************************************************************/
+ *
+ * The following defines are for the flags in the serial port AC link
+ * configuration register.
+ *
+ *****************************************************************************/
#ifndef NO_CS4612
#define SERACC_CODEC_TYPE_MASK 0x00000001L
#define SERACC_CODEC_TYPE_1_03 0x00000000L
@@ -1149,10 +1148,10 @@
#endif
/*****************************************************************************
-*
-* The following defines are for the flags in the AC97 control register 2.
-*
-*****************************************************************************/
+ *
+ * The following defines are for the flags in the AC97 control register 2.
+ *
+ *****************************************************************************/
#ifndef NO_CS4612
#define ACCTL2_RSTN 0x00000001L
#define ACCTL2_ESYN 0x00000002L
@@ -1163,21 +1162,21 @@
#endif
/*****************************************************************************
-*
-* The following defines are for the flags in the AC97 status register 2.
-*
-*****************************************************************************/
+ *
+ * The following defines are for the flags in the AC97 status register 2.
+ *
+ *****************************************************************************/
#ifndef NO_CS4612
#define ACSTS2_CRDY 0x00000001L
#define ACSTS2_VSTS 0x00000002L
#endif
/*****************************************************************************
-*
-* The following defines are for the flags in the AC97 output slot valid
-* register 2.
-*
-*****************************************************************************/
+ *
+ * The following defines are for the flags in the AC97 output slot valid
+ * register 2.
+ *
+ *****************************************************************************/
#ifndef NO_CS4612
#define ACOSV2_SLV3 0x00000001L
#define ACOSV2_SLV4 0x00000002L
@@ -1192,33 +1191,33 @@
#endif
/*****************************************************************************
-*
-* The following defines are for the flags in the AC97 command address
-* register 2.
-*
-*****************************************************************************/
+ *
+ * The following defines are for the flags in the AC97 command address
+ * register 2.
+ *
+ *****************************************************************************/
#ifndef NO_CS4612
#define ACCAD2_CI_MASK 0x0000007FL
#define ACCAD2_CI_SHIFT 0L
#endif
/*****************************************************************************
-*
-* The following defines are for the flags in the AC97 command data register
-* 2.
-*
-*****************************************************************************/
+ *
+ * The following defines are for the flags in the AC97 command data register
+ * 2.
+ *
+ *****************************************************************************/
#ifndef NO_CS4612
#define ACCDA2_CD_MASK 0x0000FFFFL
#define ACCDA2_CD_SHIFT 0L
#endif
/*****************************************************************************
-*
-* The following defines are for the flags in the AC97 input slot valid
-* register 2.
-*
-*****************************************************************************/
+ *
+ * The following defines are for the flags in the AC97 input slot valid
+ * register 2.
+ *
+ *****************************************************************************/
#ifndef NO_CS4612
#define ACISV2_ISV3 0x00000001L
#define ACISV2_ISV4 0x00000002L
@@ -1233,32 +1232,32 @@
#endif
/*****************************************************************************
-*
-* The following defines are for the flags in the AC97 status address
-* register 2.
-*
-*****************************************************************************/
+ *
+ * The following defines are for the flags in the AC97 status address
+ * register 2.
+ *
+ *****************************************************************************/
#ifndef NO_CS4612
#define ACSAD2_SI_MASK 0x0000007FL
#define ACSAD2_SI_SHIFT 0L
#endif
/*****************************************************************************
-*
-* The following defines are for the flags in the AC97 status data register 2.
-*
-*****************************************************************************/
+ *
+ * The following defines are for the flags in the AC97 status data register 2.
+ *
+ *****************************************************************************/
#ifndef NO_CS4612
#define ACSDA2_SD_MASK 0x0000FFFFL
#define ACSDA2_SD_SHIFT 0L
#endif
/*****************************************************************************
-*
-* The following defines are for the flags in the I/O trap address and control
-* registers (all 12).
-*
-*****************************************************************************/
+ *
+ * The following defines are for the flags in the I/O trap address and control
+ * registers (all 12).
+ *
+ *****************************************************************************/
#ifndef NO_CS4612
#define IOTAC_SA_MASK 0x0000FFFFL
#define IOTAC_MSK_MASK 0x000F0000L
@@ -1276,11 +1275,11 @@
#endif
/*****************************************************************************
-*
-* The following defines are for the flags in the I/O trap fast read registers
-* (all 8).
-*
-*****************************************************************************/
+ *
+ * The following defines are for the flags in the I/O trap fast read registers
+ * (all 8).
+ *
+ *****************************************************************************/
#ifndef NO_CS4612
#define IOTFR_D_MASK 0x0000FFFFL
#define IOTFR_A_MASK 0x000F0000L
@@ -1293,10 +1292,10 @@
#endif
/*****************************************************************************
-*
-* The following defines are for the flags in the I/O trap FIFO register.
-*
-*****************************************************************************/
+ *
+ * The following defines are for the flags in the I/O trap FIFO register.
+ *
+ *****************************************************************************/
#ifndef NO_CS4612
#define IOTFIFO_BA_MASK 0x00003FFFL
#define IOTFIFO_S_MASK 0x00FF0000L
@@ -1307,11 +1306,11 @@
#endif
/*****************************************************************************
-*
-* The following defines are for the flags in the I/O trap retry read data
-* register.
-*
-*****************************************************************************/
+ *
+ * The following defines are for the flags in the I/O trap retry read data
+ * register.
+ *
+ *****************************************************************************/
#ifndef NO_CS4612
#define IOTRRD_D_MASK 0x0000FFFFL
#define IOTRRD_RDV 0x80000000L
@@ -1319,11 +1318,11 @@
#endif
/*****************************************************************************
-*
-* The following defines are for the flags in the I/O trap FIFO pointer
-* register.
-*
-*****************************************************************************/
+ *
+ * The following defines are for the flags in the I/O trap FIFO pointer
+ * register.
+ *
+ *****************************************************************************/
#ifndef NO_CS4612
#define IOTFP_CA_MASK 0x00003FFFL
#define IOTFP_PA_MASK 0x3FFF0000L
@@ -1332,10 +1331,10 @@
#endif
/*****************************************************************************
-*
-* The following defines are for the flags in the I/O trap control register.
-*
-*****************************************************************************/
+ *
+ * The following defines are for the flags in the I/O trap control register.
+ *
+ *****************************************************************************/
#ifndef NO_CS4612
#define IOTCR_ITD 0x00000001L
#define IOTCR_HRV 0x00000002L
@@ -1348,30 +1347,30 @@
#endif
/*****************************************************************************
-*
-* The following defines are for the flags in the direct PCI data register.
-*
-*****************************************************************************/
+ *
+ * The following defines are for the flags in the direct PCI data register.
+ *
+ *****************************************************************************/
#ifndef NO_CS4612
#define DPCID_D_MASK 0xFFFFFFFFL
#define DPCID_D_SHIFT 0L
#endif
/*****************************************************************************
-*
-* The following defines are for the flags in the direct PCI address register.
-*
-*****************************************************************************/
+ *
+ * The following defines are for the flags in the direct PCI address register.
+ *
+ *****************************************************************************/
#ifndef NO_CS4612
#define DPCIA_A_MASK 0xFFFFFFFFL
#define DPCIA_A_SHIFT 0L
#endif
/*****************************************************************************
-*
-* The following defines are for the flags in the direct PCI command register.
-*
-*****************************************************************************/
+ *
+ * The following defines are for the flags in the direct PCI command register.
+ *
+ *****************************************************************************/
#ifndef NO_CS4612
#define DPCIC_C_MASK 0x0000000FL
#define DPCIC_C_IOREAD 0x00000002L
@@ -1380,10 +1379,10 @@
#endif
/*****************************************************************************
-*
-* The following defines are for the flags in the PC/PCI request register.
-*
-*****************************************************************************/
+ *
+ * The following defines are for the flags in the PC/PCI request register.
+ *
+ *****************************************************************************/
#ifndef NO_CS4612
#define PCPCIR_RDC_MASK 0x00000007L
#define PCPCIR_C_MASK 0x00007000L
@@ -1393,10 +1392,10 @@
#endif
/*****************************************************************************
-*
-* The following defines are for the flags in the PC/PCI grant register.
-*
-*****************************************************************************/
+ *
+ * The following defines are for the flags in the PC/PCI grant register.
+ *
+ *****************************************************************************/
#ifndef NO_CS4612
#define PCPCIG_GDC_MASK 0x00000007L
#define PCPCIG_VL 0x00008000L
@@ -1404,31 +1403,31 @@
#endif
/*****************************************************************************
-*
-* The following defines are for the flags in the PC/PCI master enable
-* register.
-*
-*****************************************************************************/
+ *
+ * The following defines are for the flags in the PC/PCI master enable
+ * register.
+ *
+ *****************************************************************************/
#ifndef NO_CS4612
#define PCPCIEN_EN 0x00000001L
#endif
/*****************************************************************************
-*
-* The following defines are for the flags in the extended PCI power
-* management control register.
-*
-*****************************************************************************/
+ *
+ * The following defines are for the flags in the extended PCI power
+ * management control register.
+ *
+ *****************************************************************************/
#ifndef NO_CS4612
#define EPCIPMC_GWU 0x00000001L
#define EPCIPMC_FSPC 0x00000002L
#endif
/*****************************************************************************
-*
-* The following defines are for the flags in the SP control register.
-*
-*****************************************************************************/
+ *
+ * The following defines are for the flags in the SP control register.
+ *
+ *****************************************************************************/
#define SPCR_RUN 0x00000001L
#define SPCR_STPFR 0x00000002L
#define SPCR_RUNFR 0x00000004L
@@ -1443,10 +1442,10 @@
#endif
/*****************************************************************************
-*
-* The following defines are for the flags in the debug index register.
-*
-*****************************************************************************/
+ *
+ * The following defines are for the flags in the debug index register.
+ *
+ *****************************************************************************/
#define DREG_REGID_MASK 0x0000007FL
#define DREG_DEBUG 0x00000080L
#define DREG_RGBK_MASK 0x00000700L
@@ -1626,11 +1625,11 @@
#define DREG_REGID_RSHOUT_HIGH 0x00000630L
/*****************************************************************************
-*
-* The following defines are for the flags in the DMA stream requestor write
-* port register.
-*
-*****************************************************************************/
+ *
+ * The following defines are for the flags in the DMA stream requestor write
+ * port register.
+ *
+ *****************************************************************************/
#define DSRWP_DSR_MASK 0x0000000FL
#define DSRWP_DSR_BG_RQ 0x00000001L
#define DSRWP_DSR_PRIORITY_MASK 0x00000006L
@@ -1641,27 +1640,27 @@
#define DSRWP_DSR_RQ_PENDING 0x00000008L
/*****************************************************************************
-*
-* The following defines are for the flags in the trap write port register.
-*
-*****************************************************************************/
+ *
+ * The following defines are for the flags in the trap write port register.
+ *
+ *****************************************************************************/
#define TWPR_TW_MASK 0x0000FFFFL
#define TWPR_TW_SHIFT 0L
/*****************************************************************************
-*
-* The following defines are for the flags in the stack pointer write
-* register.
-*
-*****************************************************************************/
+ *
+ * The following defines are for the flags in the stack pointer write
+ * register.
+ *
+ *****************************************************************************/
#define SPWR_STKP_MASK 0x0000000FL
#define SPWR_STKP_SHIFT 0L
/*****************************************************************************
-*
-* The following defines are for the flags in the SP interrupt register.
-*
-*****************************************************************************/
+ *
+ * The following defines are for the flags in the SP interrupt register.
+ *
+ *****************************************************************************/
#define SPIR_FRI 0x00000001L
#define SPIR_DOI 0x00000002L
#define SPIR_GPI2 0x00000004L
@@ -1672,18 +1671,18 @@
#define SPIR_IP3 0x00000080L
/*****************************************************************************
-*
-* The following defines are for the flags in the functional group 1 register.
-*
-*****************************************************************************/
+ *
+ * The following defines are for the flags in the functional group 1 register.
+ *
+ *****************************************************************************/
#define FGR1_F1S_MASK 0x0000FFFFL
#define FGR1_F1S_SHIFT 0L
/*****************************************************************************
-*
-* The following defines are for the flags in the SP clock status register.
-*
-*****************************************************************************/
+ *
+ * The following defines are for the flags in the SP clock status register.
+ *
+ *****************************************************************************/
#define SPCS_FRI 0x00000001L
#define SPCS_DOI 0x00000002L
#define SPCS_GPI2 0x00000004L
@@ -1701,47 +1700,47 @@
#define SPCS_FGN_SHIFT 13L
/*****************************************************************************
-*
-* The following defines are for the flags in the SP DMA requestor status
-* register.
-*
-*****************************************************************************/
+ *
+ * The following defines are for the flags in the SP DMA requestor status
+ * register.
+ *
+ *****************************************************************************/
#define SDSR_DCS_MASK 0x000000FFL
#define SDSR_DCS_SHIFT 0L
#define SDSR_DCS_NONE 0x00000007L
/*****************************************************************************
-*
-* The following defines are for the flags in the frame timer register.
-*
-*****************************************************************************/
+ *
+ * The following defines are for the flags in the frame timer register.
+ *
+ *****************************************************************************/
#define FRMT_FTV_MASK 0x0000FFFFL
#define FRMT_FTV_SHIFT 0L
/*****************************************************************************
-*
-* The following defines are for the flags in the frame timer current count
-* register.
-*
-*****************************************************************************/
+ *
+ * The following defines are for the flags in the frame timer current count
+ * register.
+ *
+ *****************************************************************************/
#define FRCC_FCC_MASK 0x0000FFFFL
#define FRCC_FCC_SHIFT 0L
/*****************************************************************************
-*
-* The following defines are for the flags in the frame timer save count
-* register.
-*
-*****************************************************************************/
+ *
+ * The following defines are for the flags in the frame timer save count
+ * register.
+ *
+ *****************************************************************************/
#define FRSC_FCS_MASK 0x0000FFFFL
#define FRSC_FCS_SHIFT 0L
/*****************************************************************************
-*
-* The following define the various flags stored in the scatter/gather
-* descriptors.
-*
-*****************************************************************************/
+ *
+ * The following define the various flags stored in the scatter/gather
+ * descriptors.
+ *
+ *****************************************************************************/
#define DMA_SG_NEXT_ENTRY_MASK 0x00000FF8L
#define DMA_SG_SAMPLE_END_MASK 0x0FFF0000L
#define DMA_SG_SAMPLE_END_FLAG 0x10000000L
@@ -1752,11 +1751,11 @@
#define DMA_SG_SAMPLE_END_SHIFT 16L
/*****************************************************************************
-*
-* The following define the offsets of the fields within the on-chip generic
-* DMA requestor.
-*
-*****************************************************************************/
+ *
+ * The following define the offsets of the fields within the on-chip generic
+ * DMA requestor.
+ *
+ *****************************************************************************/
#define DMA_RQ_CONTROL1 0x00000000L
#define DMA_RQ_CONTROL2 0x00000004L
#define DMA_RQ_SOURCE_ADDR 0x00000008L
@@ -1768,11 +1767,11 @@
#define DMA_RQ_PAGE_MAP_ADDR 0x00000020L
/*****************************************************************************
-*
-* The following defines are for the flags in the first control word of the
-* on-chip generic DMA requestor.
-*
-*****************************************************************************/
+ *
+ * The following defines are for the flags in the first control word of the
+ * on-chip generic DMA requestor.
+ *
+ *****************************************************************************/
#define DMA_RQ_C1_COUNT_MASK 0x000003FFL
#define DMA_RQ_C1_DESTINATION_SCATTER 0x00001000L
#define DMA_RQ_C1_SOURCE_GATHER 0x00002000L
@@ -1818,11 +1817,11 @@
#define DMA_RQ_C1_COUNT_SHIFT 0L
/*****************************************************************************
-*
-* The following defines are for the flags in the second control word of the
-* on-chip generic DMA requestor.
-*
-*****************************************************************************/
+ *
+ * The following defines are for the flags in the second control word of the
+ * on-chip generic DMA requestor.
+ *
+ *****************************************************************************/
#define DMA_RQ_C2_VIRTUAL_CHANNEL_MASK 0x0000003FL
#define DMA_RQ_C2_VIRTUAL_SIGNAL_MASK 0x00000300L
#define DMA_RQ_C2_NO_VIRTUAL_SIGNAL 0x00000000L
@@ -1847,11 +1846,11 @@
#define DMA_RQ_C2_LOOP_END_SHIFT 16L
/*****************************************************************************
-*
-* The following defines are for the flags in the source and destination words
-* of the on-chip generic DMA requestor.
-*
-*****************************************************************************/
+ *
+ * The following defines are for the flags in the source and destination words
+ * of the on-chip generic DMA requestor.
+ *
+ *****************************************************************************/
#define DMA_RQ_SD_ADDRESS_MASK 0x0000FFFFL
#define DMA_RQ_SD_MEMORY_ID_MASK 0x000F0000L
#define DMA_RQ_SD_SP_PARAM_ADDR 0x00000000L
@@ -1864,22 +1863,22 @@
#define DMA_RQ_SD_ADDRESS_SHIFT 0L
/*****************************************************************************
-*
-* The following defines are for the flags in the page map address word of the
-* on-chip generic DMA requestor.
-*
-*****************************************************************************/
+ *
+ * The following defines are for the flags in the page map address word of the
+ * on-chip generic DMA requestor.
+ *
+ *****************************************************************************/
#define DMA_RQ_PMA_LOOP_THIRD_PAGE_ENTRY_MASK 0x00000FF8L
#define DMA_RQ_PMA_PAGE_TABLE_MASK 0xFFFFF000L
#define DMA_RQ_PMA_LOOP_THIRD_PAGE_ENTRY_SHIFT 3L
#define DMA_RQ_PMA_PAGE_TABLE_SHIFT 12L
/*****************************************************************************
-*
-* The following defines are for the flags in the rsConfig01/23 registers of
-* the SP.
-*
-*****************************************************************************/
+ *
+ * The following defines are for the flags in the rsConfig01/23 registers of
+ * the SP.
+ *
+ *****************************************************************************/
#define RSCONFIG_MODULO_SIZE_MASK 0x0000000FL
#define RSCONFIG_MODULO_16 0x00000001L
#define RSCONFIG_MODULO_32 0x00000002L
@@ -1953,21 +1952,21 @@
/* The following struct holds the initialization array. */
/*
-* this is 3*1024 for parameter, 3.5*1024 for sample and 2*3.5*1024 for code since
-* each instruction is 40 bits and takes two dwords
-*/
+ * this is 3*1024 for parameter, 3.5*1024 for sample and 2*3.5*1024 for code since
+ * each instruction is 40 bits and takes two dwords
+ */
#define INKY_BA1_DWORD_SIZE (13 * 1024 + 512)
#define INKY_MEMORY_COUNT 3
struct BA1struct
{
-struct
-{
-u_long ulDestByteOffset,
-ulSourceByteSize;
-} MemoryStat[INKY_MEMORY_COUNT];
+ struct
+ {
+ u_long ulDestByteOffset,
+ ulSourceByteSize;
+ } MemoryStat[INKY_MEMORY_COUNT];
-u_long BA1Array[INKY_BA1_DWORD_SIZE];
+ u_long BA1Array[INKY_BA1_DWORD_SIZE];
};
#endif /* _CSA_REG_H */
--- /dev/null
+++ sys/dev/sound/pci/emu10kx-pcm.c
@@ -0,0 +1,1533 @@
+/*-
+ * Copyright (c) 1999 Cameron Grant <gandalf at vilnya.demon.co.uk>
+ * Copyright (c) 2003-2007 Yuriy Tsibizov <yuriy.tsibizov at gfk.ru>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHERIN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD: src/sys/dev/sound/pci/emu10kx-pcm.c,v 1.11 2007/09/12 07:43:42 ariff Exp $
+ */
+
+#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/bus.h>
+#include <machine/bus.h>
+#include <sys/rman.h>
+#include <sys/systm.h>
+#include <sys/sbuf.h>
+#include <sys/queue.h>
+#include <sys/systm.h>
+#include <sys/lock.h>
+#include <sys/mutex.h>
+
+#include <dev/sound/chip.h>
+#include <dev/sound/pcm/sound.h>
+#include <dev/sound/pcm/ac97.h>
+
+#include "mixer_if.h"
+
+#include <dev/sound/pci/emu10kx.h>
+#include "emu10k1-alsa%diked.h"
+
+struct emu_pcm_pchinfo {
+ int spd;
+ int fmt;
+ unsigned int blksz;
+ int run;
+ struct emu_voice *master;
+ struct emu_voice *slave;
+ struct snd_dbuf *buffer;
+ struct pcm_channel *channel;
+ struct emu_pcm_info *pcm;
+ int timer;
+};
+
+struct emu_pcm_rchinfo {
+ int spd;
+ int fmt;
+ unsigned int blksz;
+ int run;
+ uint32_t idxreg;
+ uint32_t basereg;
+ uint32_t sizereg;
+ uint32_t setupreg;
+ uint32_t irqmask;
+ uint32_t iprmask;
+ int ihandle;
+ struct snd_dbuf *buffer;
+ struct pcm_channel *channel;
+ struct emu_pcm_info *pcm;
+ int timer;
+};
+
+/* XXX Hardware playback channels */
+#define MAX_CHANNELS 4
+
+#if MAX_CHANNELS > 13
+#error Too many hardware channels defined. 13 is the maximum
+#endif
+
+struct emu_pcm_info {
+ struct mtx *lock;
+ device_t dev; /* device information */
+ struct emu_sc_info *card;
+ struct emu_pcm_pchinfo pch[MAX_CHANNELS]; /* hardware channels */
+ int pnum; /* next free channel number */
+ struct emu_pcm_rchinfo rch_adc;
+ struct emu_pcm_rchinfo rch_efx;
+ struct emu_route rt;
+ struct emu_route rt_mono;
+ int route;
+ int ihandle; /* interrupt handler */
+ unsigned int bufsz;
+ int is_emu10k1;
+ struct ac97_info *codec;
+ uint32_t ac97_state[0x7F];
+ kobj_class_t ac97_mixerclass;
+ uint32_t ac97_recdevs;
+ uint32_t ac97_playdevs;
+ struct snd_mixer *sm;
+ int mch_disabled;
+ unsigned int emu10k1_volcache[2][2];
+};
+
+
+static uint32_t emu_rfmt_adc[] = {
+ AFMT_S16_LE,
+ AFMT_STEREO | AFMT_S16_LE,
+ 0
+};
+static struct pcmchan_caps emu_reccaps_adc = {
+ 8000, 48000, emu_rfmt_adc, 0
+};
+
+static uint32_t emu_rfmt_efx[] = {
+ AFMT_S16_LE,
+ 0
+};
+
+static struct pcmchan_caps emu_reccaps_efx_live = {
+ 48000*32, 48000*32, emu_rfmt_efx, 0
+};
+
+static struct pcmchan_caps emu_reccaps_efx_audigy = {
+ 48000*64, 48000*64, emu_rfmt_efx, 0
+};
+
+static int emu_rates_live[] = {
+ 48000*32
+};
+
+static int emu_rates_audigy[] = {
+ 48000*64
+};
+
+static uint32_t emu_pfmt[] = {
+ AFMT_U8,
+ AFMT_STEREO | AFMT_U8,
+ AFMT_S16_LE,
+ AFMT_STEREO | AFMT_S16_LE,
+ 0
+};
+static uint32_t emu_pfmt_mono[] = {
+ AFMT_U8,
+ AFMT_S16_LE,
+ 0
+};
+
+static struct pcmchan_caps emu_playcaps = {4000, 48000, emu_pfmt, 0};
+static struct pcmchan_caps emu_playcaps_mono = {4000, 48000, emu_pfmt_mono, 0};
+
+static int emu10k1_adcspeed[8] = {48000, 44100, 32000, 24000, 22050, 16000, 11025, 8000};
+/* audigy supports 12kHz. */
+static int emu10k2_adcspeed[9] = {48000, 44100, 32000, 24000, 22050, 16000, 12000, 11025, 8000};
+
+static uint32_t emu_pcm_intr(void *pcm, uint32_t stat);
+
+static const struct emu_dspmix_props_k1 {
+ uint8_t present;
+ uint8_t recdev;
+ int8_t input;
+} dspmix_k1 [SOUND_MIXER_NRDEVICES] = {
+ /* no mixer device for ac97 */ /* in0 AC97 */
+ [SOUND_MIXER_DIGITAL1] = {1, 1, 1}, /* in1 CD SPDIF */
+ /* not connected */ /* in2 (zoom) */
+ [SOUND_MIXER_DIGITAL2] = {1, 1, 3}, /* in3 toslink */
+ [SOUND_MIXER_LINE2] = {1, 1, 4}, /* in4 Line-In2 */
+ [SOUND_MIXER_DIGITAL3] = {1, 1, 5}, /* in5 on-card SPDIF */
+ [SOUND_MIXER_LINE3] = {1, 1, 6}, /* in6 AUX2 */
+ /* not connected */ /* in7 */
+};
+static const struct emu_dspmix_props_k2 {
+ uint8_t present;
+ uint8_t recdev;
+ int8_t input;
+} dspmix_k2 [SOUND_MIXER_NRDEVICES] = {
+ [SOUND_MIXER_VOLUME] = {1, 0, (-1)},
+ [SOUND_MIXER_PCM] = {1, 0, (-1)},
+
+ /* no mixer device */ /* in0 AC97 */
+ [SOUND_MIXER_DIGITAL1] = {1, 1, 1}, /* in1 CD SPDIF */
+ [SOUND_MIXER_DIGITAL2] = {1, 1, 2}, /* in2 COAX SPDIF */
+ /* not connected */ /* in3 */
+ [SOUND_MIXER_LINE2] = {1, 1, 4}, /* in4 Line-In2 */
+ [SOUND_MIXER_DIGITAL3] = {1, 1, 5}, /* in5 on-card SPDIF */
+ [SOUND_MIXER_LINE3] = {1, 1, 6}, /* in6 AUX2 */
+ /* not connected */ /* in7 */
+};
+
+static int
+emu_dspmixer_init(struct snd_mixer *m)
+{
+ struct emu_pcm_info *sc;
+ int i;
+ int p, r;
+
+ p = 0;
+ r = 0;
+
+ sc = mix_getdevinfo(m);
+
+ if (sc->route == RT_FRONT) {
+ /* create submixer for AC97 codec */
+ if ((sc->ac97_mixerclass != NULL) && (sc->codec != NULL)) {
+ sc->sm = mixer_create(sc->dev, sc->ac97_mixerclass, sc->codec, "ac97");
+ if (sc->sm != NULL) {
+ p = mix_getdevs(sc->sm);
+ r = mix_getrecdevs(sc->sm);
+ }
+ }
+
+ sc->ac97_playdevs = p;
+ sc->ac97_recdevs = r;
+ }
+
+ /* This two are always here */
+ p |= (1 << SOUND_MIXER_PCM);
+ p |= (1 << SOUND_MIXER_VOLUME);
+
+ if (sc->route == RT_FRONT) {
+ if (sc->is_emu10k1) {
+ for (i = 0; i < SOUND_MIXER_NRDEVICES; i++) {
+ if (dspmix_k1[i].present)
+ p |= (1 << i);
+ if (dspmix_k1[i].recdev)
+ r |= (1 << i);
+ }
+ } else {
+ for (i = 0; i < SOUND_MIXER_NRDEVICES; i++) {
+ if (dspmix_k2[i].present)
+ p |= (1 << i);
+ if (dspmix_k2[i].recdev)
+ r |= (1 << i);
+ }
+ }
+ }
+
+ mix_setdevs(m, p);
+ mix_setrecdevs(m, r);
+
+ return (0);
+}
+
+static int
+emu_dspmixer_uninit(struct snd_mixer *m)
+{
+ struct emu_pcm_info *sc;
+ int err = 0;
+
+ /* drop submixer for AC97 codec */
+ sc = mix_getdevinfo(m);
+ if (sc->sm != NULL)
+ err = mixer_delete(sc->sm);
+ if (err)
+ return (err);
+ sc->sm = NULL;
+ return (0);
+}
+
+static int
+emu_dspmixer_set(struct snd_mixer *m, unsigned dev, unsigned left, unsigned right)
+{
+ struct emu_pcm_info *sc;
+
+ sc = mix_getdevinfo(m);
+
+ switch (dev) {
+ case SOUND_MIXER_VOLUME:
+ switch (sc->route) {
+ case RT_FRONT:
+ if (sc->sm != NULL)
+ mix_set(sc->sm, dev, left, right);
+ if (sc->mch_disabled) {
+ /* In emu10k1 case PCM volume does not affect
+ sound routed to rear & center/sub (it is connected
+ to AC97 codec). Calculate it manually. */
+ /* This really should belong to emu10kx.c */
+ if (sc->is_emu10k1) {
+ sc->emu10k1_volcache[0][0] = left;
+ left = left * sc->emu10k1_volcache[1][0] / 100;
+ sc->emu10k1_volcache[0][1] = right;
+ right = right * sc->emu10k1_volcache[1][1] / 100;
+ }
+
+ emumix_set_volume(sc->card, M_MASTER_REAR_L, left);
+ emumix_set_volume(sc->card, M_MASTER_REAR_R, right);
+ if (!sc->is_emu10k1) {
+ emumix_set_volume(sc->card, M_MASTER_CENTER, (left+right)/2);
+ emumix_set_volume(sc->card, M_MASTER_SUBWOOFER, (left+right)/2);
+ /* XXX side */
+ }
+ } /* mch disabled */
+ break;
+ case RT_REAR:
+ emumix_set_volume(sc->card, M_MASTER_REAR_L, left);
+ emumix_set_volume(sc->card, M_MASTER_REAR_R, right);
+ break;
+ case RT_CENTER:
+ emumix_set_volume(sc->card, M_MASTER_CENTER, (left+right)/2);
+ break;
+ case RT_SUB:
+ emumix_set_volume(sc->card, M_MASTER_SUBWOOFER, (left+right)/2);
+ break;
+ }
+ break;
+ case SOUND_MIXER_PCM:
+ switch (sc->route) {
+ case RT_FRONT:
+ if (sc->sm != NULL)
+ mix_set(sc->sm, dev, left, right);
+ if (sc->mch_disabled) {
+ /* See SOUND_MIXER_VOLUME case */
+ if (sc->is_emu10k1) {
+ sc->emu10k1_volcache[1][0] = left;
+ left = left * sc->emu10k1_volcache[0][0] / 100;
+ sc->emu10k1_volcache[1][1] = right;
+ right = right * sc->emu10k1_volcache[0][1] / 100;
+ }
+ emumix_set_volume(sc->card, M_MASTER_REAR_L, left);
+ emumix_set_volume(sc->card, M_MASTER_REAR_R, right);
+
+ if (!sc->is_emu10k1) {
+ emumix_set_volume(sc->card, M_MASTER_CENTER, (left+right)/2);
+ emumix_set_volume(sc->card, M_MASTER_SUBWOOFER, (left+right)/2);
+ /* XXX side */
+ }
+ } /* mch_disabled */
+ break;
+ case RT_REAR:
+ emumix_set_volume(sc->card, M_FX2_REAR_L, left);
+ emumix_set_volume(sc->card, M_FX3_REAR_R, right);
+ break;
+ case RT_CENTER:
+ emumix_set_volume(sc->card, M_FX4_CENTER, (left+right)/2);
+ break;
+ case RT_SUB:
+ emumix_set_volume(sc->card, M_FX5_SUBWOOFER, (left+right)/2);
+ break;
+ }
+ break;
+ case SOUND_MIXER_DIGITAL1: /* CD SPDIF, in1 */
+ emumix_set_volume(sc->card, M_IN1_FRONT_L, left);
+ emumix_set_volume(sc->card, M_IN1_FRONT_R, right);
+ break;
+ case SOUND_MIXER_DIGITAL2:
+ if (sc->is_emu10k1) {
+ /* TOSLink, in3 */
+ emumix_set_volume(sc->card, M_IN3_FRONT_L, left);
+ emumix_set_volume(sc->card, M_IN3_FRONT_R, right);
+ } else {
+ /* COAX SPDIF, in2 */
+ emumix_set_volume(sc->card, M_IN2_FRONT_L, left);
+ emumix_set_volume(sc->card, M_IN2_FRONT_R, right);
+ }
+ break;
+ case SOUND_MIXER_LINE2: /* Line-In2, in4 */
+ emumix_set_volume(sc->card, M_IN4_FRONT_L, left);
+ emumix_set_volume(sc->card, M_IN4_FRONT_R, right);
+ break;
+ case SOUND_MIXER_DIGITAL3: /* on-card SPDIF, in5 */
+ emumix_set_volume(sc->card, M_IN5_FRONT_L, left);
+ emumix_set_volume(sc->card, M_IN5_FRONT_R, right);
+ break;
+ case SOUND_MIXER_LINE3: /* AUX2, in6 */
+ emumix_set_volume(sc->card, M_IN6_FRONT_L, left);
+ emumix_set_volume(sc->card, M_IN6_FRONT_R, right);
+ break;
+ default:
+ if (sc->sm != NULL) {
+ /* XXX emumix_set_volume is not required here */
+ emumix_set_volume(sc->card, M_IN0_FRONT_L, 100);
+ emumix_set_volume(sc->card, M_IN0_FRONT_R, 100);
+ mix_set(sc->sm, dev, left, right);
+ } else
+ device_printf(sc->dev, "mixer error: unknown device %d\n", dev);
+ }
+ return (0);
+}
+
+static int
+emu_dspmixer_setrecsrc(struct snd_mixer *m, u_int32_t src)
+{
+ struct emu_pcm_info *sc;
+ int i;
+ u_int32_t recmask;
+ int input[8];
+
+ sc = mix_getdevinfo(m);
+ recmask = 0;
+ for (i=0; i < 8; i++)
+ input[i]=0;
+
+ if (sc->sm != NULL)
+ if ((src & sc->ac97_recdevs) !=0)
+ if (mix_setrecsrc(sc->sm, src & sc->ac97_recdevs) == 0) {
+ recmask |= (src & sc->ac97_recdevs);
+ /* Recording from AC97 codec.
+ Enable AC97 route to rec on DSP */
+ input[0] = 1;
+ }
+ if (sc->is_emu10k1) {
+ for (i = 0; i < SOUND_MIXER_NRDEVICES; i++) {
+ if (dspmix_k1[i].recdev)
+ if ((src & (1 << i)) == ((uint32_t)1 << i)) {
+ recmask |= (1 << i);
+ /* enable device i */
+ input[dspmix_k1[i].input] = 1;
+ }
+ }
+ } else {
+ for (i = 0; i < SOUND_MIXER_NRDEVICES; i++) {
+ if (dspmix_k2[i].recdev)
+ if ((src & (1 << i)) == ((uint32_t)1 << i)) {
+ recmask |= (1 << i);
+ /* enable device i */
+ input[dspmix_k2[i].input] = 1;
+ }
+ }
+ }
+ emumix_set_volume(sc->card, M_IN0_REC_L, input[0] == 1 ? 100 : 0);
+ emumix_set_volume(sc->card, M_IN0_REC_R, input[0] == 1 ? 100 : 0);
+
+ emumix_set_volume(sc->card, M_IN1_REC_L, input[1] == 1 ? 100 : 0);
+ emumix_set_volume(sc->card, M_IN1_REC_R, input[1] == 1 ? 100 : 0);
+
+ if (!sc->is_emu10k1) {
+ emumix_set_volume(sc->card, M_IN2_REC_L, input[2] == 1 ? 100 : 0);
+ emumix_set_volume(sc->card, M_IN2_REC_R, input[2] == 1 ? 100 : 0);
+ }
+
+ if (sc->is_emu10k1) {
+ emumix_set_volume(sc->card, M_IN3_REC_L, input[3] == 1 ? 100 : 0);
+ emumix_set_volume(sc->card, M_IN3_REC_R, input[3] == 1 ? 100 : 0);
+ }
+
+ emumix_set_volume(sc->card, M_IN4_REC_L, input[4] == 1 ? 100 : 0);
+ emumix_set_volume(sc->card, M_IN4_REC_R, input[4] == 1 ? 100 : 0);
+
+ emumix_set_volume(sc->card, M_IN5_REC_L, input[5] == 1 ? 100 : 0);
+ emumix_set_volume(sc->card, M_IN5_REC_R, input[5] == 1 ? 100 : 0);
+
+ emumix_set_volume(sc->card, M_IN6_REC_L, input[6] == 1 ? 100 : 0);
+ emumix_set_volume(sc->card, M_IN6_REC_R, input[6] == 1 ? 100 : 0);
+
+ /* XXX check for K1/k2 differences? */
+ if ((src & (1 << SOUND_MIXER_PCM)) == (1 << SOUND_MIXER_PCM)) {
+ emumix_set_volume(sc->card, M_FX0_REC_L, emumix_get_volume(sc->card, M_FX0_FRONT_L));
+ emumix_set_volume(sc->card, M_FX1_REC_R, emumix_get_volume(sc->card, M_FX1_FRONT_R));
+ } else {
+ emumix_set_volume(sc->card, M_FX0_REC_L, 0);
+ emumix_set_volume(sc->card, M_FX1_REC_R, 0);
+ }
+
+ return (recmask);
+}
+
+static kobj_method_t emudspmixer_methods[] = {
+ KOBJMETHOD(mixer_init, emu_dspmixer_init),
+ KOBJMETHOD(mixer_uninit, emu_dspmixer_uninit),
+ KOBJMETHOD(mixer_set, emu_dspmixer_set),
+ KOBJMETHOD(mixer_setrecsrc, emu_dspmixer_setrecsrc),
+ { 0, 0 }
+};
+MIXER_DECLARE(emudspmixer);
+
+static int
+emu_efxmixer_init(struct snd_mixer *m)
+{
+ mix_setdevs(m, SOUND_MASK_VOLUME);
+ mix_setrecdevs(m, SOUND_MASK_MONITOR);
+ return (0);
+}
+
+static int
+emu_efxmixer_set(struct snd_mixer *m, unsigned dev, unsigned left, unsigned right)
+{
+ if (left + right == 200) return (0);
+ return (0);
+}
+
+static int
+emu_efxmixer_setrecsrc(struct snd_mixer *m __unused, u_int32_t src __unused)
+{
+ return (SOUND_MASK_MONITOR);
+}
+
+static kobj_method_t emuefxmixer_methods[] = {
+ KOBJMETHOD(mixer_init, emu_efxmixer_init),
+ KOBJMETHOD(mixer_set, emu_efxmixer_set),
+ KOBJMETHOD(mixer_setrecsrc, emu_efxmixer_setrecsrc),
+ { 0, 0 }
+};
+MIXER_DECLARE(emuefxmixer);
+
+/*
+ * AC97 emulation code for Audigy and later cards.
+ * Some parts of AC97 codec are not used by hardware, but can be used
+ * to change some DSP controls via AC97 mixer interface. This includes:
+ * - master volume controls MASTER_FRONT_[R|L]
+ * - pcm volume controls FX[0|1]_FRONT_[R|L]
+ * - rec volume controls MASTER_REC_[R|L]
+ * We do it because we need to put it under user control....
+ * We also keep some parts of AC97 disabled to get better sound quality
+ */
+
+#define AC97LEFT(x) ((x & 0x7F00)>>8)
+#define AC97RIGHT(x) (x & 0x007F)
+#define AC97MUTE(x) ((x & 0x8000)>>15)
+#define BIT4_TO100(x) (100-(x)*100/(0x0f))
+#define BIT6_TO100(x) (100-(x)*100/(0x3f))
+#define BIT4_TO255(x) (255-(x)*255/(0x0f))
+#define BIT6_TO255(x) (255-(x)*255/(0x3f))
+#define V100_TOBIT6(x) (0x3f*(100-x)/100)
+#define V100_TOBIT4(x) (0x0f*(100-x)/100)
+#define AC97ENCODE(x_muted, x_left, x_right) (((x_muted & 1)<<15) | ((x_left & 0x3f)<<8) | (x_right & 0x3f))
+
+static int
+emu_ac97_read_emulation(struct emu_pcm_info *sc, int regno)
+{
+ int use_ac97;
+ int emulated;
+ int tmp;
+
+ use_ac97 = 1;
+ emulated = 0;
+
+ switch (regno) {
+ case AC97_MIX_MASTER:
+ emulated = sc->ac97_state[AC97_MIX_MASTER];
+ use_ac97 = 0;
+ break;
+ case AC97_MIX_PCM:
+ emulated = sc->ac97_state[AC97_MIX_PCM];
+ use_ac97 = 0;
+ break;
+ case AC97_REG_RECSEL:
+ emulated = 0x0505;
+ use_ac97 = 0;
+ break;
+ case AC97_MIX_RGAIN:
+ emulated = sc->ac97_state[AC97_MIX_RGAIN];
+ use_ac97 = 0;
+ break;
+ }
+
+ emu_wr(sc->card, AC97ADDRESS, regno, 1);
+ tmp = emu_rd(sc->card, AC97DATA, 2);
+
+ if (use_ac97)
+ emulated = tmp;
+
+ return (emulated);
+}
+
+static void
+emu_ac97_write_emulation(struct emu_pcm_info *sc, int regno, uint32_t data)
+{
+ int write_ac97;
+ int left, right;
+ uint32_t emu_left, emu_right;
+ int is_mute;
+
+ write_ac97 = 1;
+
+ left = AC97LEFT(data);
+ emu_left = BIT6_TO100(left); /* We show us as 6-bit AC97 mixer */
+ right = AC97RIGHT(data);
+ emu_right = BIT6_TO100(right);
+ is_mute = AC97MUTE(data);
+ if (is_mute)
+ emu_left = emu_right = 0;
+
+ switch (regno) {
+ /* TODO: reset emulator on AC97_RESET */
+ case AC97_MIX_MASTER:
+ emumix_set_volume(sc->card, M_MASTER_FRONT_L, emu_left);
+ emumix_set_volume(sc->card, M_MASTER_FRONT_R, emu_right);
+ sc->ac97_state[AC97_MIX_MASTER] = data & (0x8000 | 0x3f3f);
+ data = 0x8000; /* Mute AC97 main out */
+ break;
+ case AC97_MIX_PCM: /* PCM OUT VOL */
+ emumix_set_volume(sc->card, M_FX0_FRONT_L, emu_left);
+ emumix_set_volume(sc->card, M_FX1_FRONT_R, emu_right);
+ sc->ac97_state[AC97_MIX_PCM] = data & (0x8000 | 0x3f3f);
+ data = 0x8000; /* Mute AC97 PCM out */
+ break;
+ case AC97_REG_RECSEL:
+ /*
+ * PCM recording source is set to "stereo mix" (labeled "vol"
+ * in mixer). There is no 'playback' from AC97 codec -
+ * if you want to hear anything from AC97 you have to _record_
+ * it. Keep things simple and record "stereo mix".
+ */
+ data = 0x0505;
+ break;
+ case AC97_MIX_RGAIN: /* RECORD GAIN */
+ emu_left = BIT4_TO100(left); /* rgain is 4-bit */
+ emu_right = BIT4_TO100(right);
+ emumix_set_volume(sc->card, M_MASTER_REC_L, 100-emu_left);
+ emumix_set_volume(sc->card, M_MASTER_REC_R, 100-emu_right);
+ /*
+ * Record gain on AC97 should stay zero to get AC97 sound on
+ * AC97_[RL] connectors on EMU10K2 chip. AC97 on Audigy is not
+ * directly connected to any output, only to EMU10K2 chip Use
+ * this control to set AC97 mix volume inside EMU10K2 chip
+ */
+ sc->ac97_state[AC97_MIX_RGAIN] = data & (0x8000 | 0x0f0f);
+ data = 0x0000;
+ break;
+ }
+ if (write_ac97) {
+ emu_wr(sc->card, AC97ADDRESS, regno, 1);
+ emu_wr(sc->card, AC97DATA, data, 2);
+ }
+}
+
+static int
+emu_erdcd(kobj_t obj __unused, void *devinfo, int regno)
+{
+ struct emu_pcm_info *sc = (struct emu_pcm_info *)devinfo;
+
+ return (emu_ac97_read_emulation(sc, regno));
+}
+
+static int
+emu_ewrcd(kobj_t obj __unused, void *devinfo, int regno, uint32_t data)
+{
+ struct emu_pcm_info *sc = (struct emu_pcm_info *)devinfo;
+
+ emu_ac97_write_emulation(sc, regno, data);
+ return (0);
+}
+
+static kobj_method_t emu_eac97_methods[] = {
+ KOBJMETHOD(ac97_read, emu_erdcd),
+ KOBJMETHOD(ac97_write, emu_ewrcd),
+ {0, 0}
+};
+AC97_DECLARE(emu_eac97);
+
+/* real ac97 codec */
+static int
+emu_rdcd(kobj_t obj __unused, void *devinfo, int regno)
+{
+ int rd;
+ struct emu_pcm_info *sc = (struct emu_pcm_info *)devinfo;
+
+ KASSERT(sc->card != NULL, ("emu_rdcd: no soundcard"));
+ emu_wr(sc->card, AC97ADDRESS, regno, 1);
+ rd = emu_rd(sc->card, AC97DATA, 2);
+ return (rd);
+}
+
+static int
+emu_wrcd(kobj_t obj __unused, void *devinfo, int regno, uint32_t data)
+{
+ struct emu_pcm_info *sc = (struct emu_pcm_info *)devinfo;
+
+ KASSERT(sc->card != NULL, ("emu_wrcd: no soundcard"));
+ emu_wr(sc->card, AC97ADDRESS, regno, 1);
+ emu_wr(sc->card, AC97DATA, data, 2);
+ return (0);
+}
+
+static kobj_method_t emu_ac97_methods[] = {
+ KOBJMETHOD(ac97_read, emu_rdcd),
+ KOBJMETHOD(ac97_write, emu_wrcd),
+ {0, 0}
+};
+AC97_DECLARE(emu_ac97);
+
+
+static int
+emu_k1_recval(int speed)
+{
+ int val;
+
+ val = 0;
+ while ((val < 7) && (speed < emu10k1_adcspeed[val]))
+ val++;
+ return (val);
+}
+
+static int
+emu_k2_recval(int speed)
+{
+ int val;
+
+ val = 0;
+ while ((val < 8) && (speed < emu10k2_adcspeed[val]))
+ val++;
+ return (val);
+}
+
+static void *
+emupchan_init(kobj_t obj __unused, void *devinfo, struct snd_dbuf *b, struct pcm_channel *c, int dir __unused)
+{
+ struct emu_pcm_info *sc = devinfo;
+ struct emu_pcm_pchinfo *ch;
+ void *r;
+
+ KASSERT(dir == PCMDIR_PLAY, ("emupchan_init: bad direction"));
+ KASSERT(sc->card != NULL, ("empchan_init: no soundcard"));
+
+
+ if (sc->pnum >= MAX_CHANNELS)
+ return (NULL);
+ ch = &(sc->pch[sc->pnum++]);
+ ch->buffer = b;
+ ch->pcm = sc;
+ ch->channel = c;
+ ch->blksz = sc->bufsz;
+ ch->fmt = AFMT_U8;
+ ch->spd = 8000;
+ ch->master = emu_valloc(sc->card);
+ /*
+ * XXX we have to allocate slave even for mono channel until we
+ * fix emu_vfree to handle this case.
+ */
+ ch->slave = emu_valloc(sc->card);
+ ch->timer = emu_timer_create(sc->card);
+ r = (emu_vinit(sc->card, ch->master, ch->slave, EMU_PLAY_BUFSZ, ch->buffer)) ? NULL : ch;
+ return (r);
+}
+
+static int
+emupchan_free(kobj_t obj __unused, void *c_devinfo)
+{
+ struct emu_pcm_pchinfo *ch = c_devinfo;
+ struct emu_pcm_info *sc = ch->pcm;
+
+ emu_timer_clear(sc->card, ch->timer);
+ if (ch->slave != NULL)
+ emu_vfree(sc->card, ch->slave);
+ emu_vfree(sc->card, ch->master);
+ return (0);
+}
+
+static int
+emupchan_setformat(kobj_t obj __unused, void *c_devinfo, uint32_t format)
+{
+ struct emu_pcm_pchinfo *ch = c_devinfo;
+
+ ch->fmt = format;
+ return (0);
+}
+
+static int
+emupchan_setspeed(kobj_t obj __unused, void *c_devinfo, uint32_t speed)
+{
+ struct emu_pcm_pchinfo *ch = c_devinfo;
+
+ ch->spd = speed;
+ return (ch->spd);
+}
+
+static int
+emupchan_setblocksize(kobj_t obj __unused, void *c_devinfo, uint32_t blocksize)
+{
+ struct emu_pcm_pchinfo *ch = c_devinfo;
+ struct emu_pcm_info *sc = ch->pcm;
+
+ if (blocksize > ch->pcm->bufsz)
+ blocksize = ch->pcm->bufsz;
+ snd_mtxlock(sc->lock);
+ ch->blksz = blocksize;
+ emu_timer_set(sc->card, ch->timer, ch->blksz / sndbuf_getbps(ch->buffer));
+ snd_mtxunlock(sc->lock);
+ return (ch->blksz);
+}
+
+static int
+emupchan_trigger(kobj_t obj __unused, void *c_devinfo, int go)
+{
+ struct emu_pcm_pchinfo *ch = c_devinfo;
+ struct emu_pcm_info *sc = ch->pcm;
+
+ if (!PCMTRIG_COMMON(go))
+ return (0);
+
+ snd_mtxlock(sc->lock); /* XXX can we trigger on parallel threads ? */
+ if (go == PCMTRIG_START) {
+ emu_vsetup(ch->master, ch->fmt, ch->spd);
+ if ((ch->fmt & AFMT_STEREO) == AFMT_STEREO)
+ emu_vroute(sc->card, &(sc->rt), ch->master);
+ else
+ emu_vroute(sc->card, &(sc->rt_mono), ch->master);
+ emu_vwrite(sc->card, ch->master);
+ emu_timer_set(sc->card, ch->timer, ch->blksz / sndbuf_getbps(ch->buffer));
+ emu_timer_enable(sc->card, ch->timer, 1);
+ }
+ /* PCM interrupt handler will handle PCMTRIG_STOP event */
+ ch->run = (go == PCMTRIG_START) ? 1 : 0;
+ emu_vtrigger(sc->card, ch->master, ch->run);
+ snd_mtxunlock(sc->lock);
+ return (0);
+}
+
+static int
+emupchan_getptr(kobj_t obj __unused, void *c_devinfo)
+{
+ struct emu_pcm_pchinfo *ch = c_devinfo;
+ struct emu_pcm_info *sc = ch->pcm;
+ int r;
+
+ r = emu_vpos(sc->card, ch->master);
+
+ return (r);
+}
+
+static struct pcmchan_caps *
+emupchan_getcaps(kobj_t obj __unused, void *c_devinfo __unused)
+{
+ struct emu_pcm_pchinfo *ch = c_devinfo;
+ struct emu_pcm_info *sc = ch->pcm;
+
+ switch (sc->route) {
+ case RT_FRONT:
+ /* FALLTHROUGH */
+ case RT_REAR:
+ /* FALLTHROUGH */
+ case RT_SIDE:
+ return (&emu_playcaps);
+ break;
+ case RT_CENTER:
+ /* FALLTHROUGH */
+ case RT_SUB:
+ return (&emu_playcaps_mono);
+ break;
+ }
+ return (NULL);
+}
+
+static kobj_method_t emupchan_methods[] = {
+ KOBJMETHOD(channel_init, emupchan_init),
+ KOBJMETHOD(channel_free, emupchan_free),
+ KOBJMETHOD(channel_setformat, emupchan_setformat),
+ KOBJMETHOD(channel_setspeed, emupchan_setspeed),
+ KOBJMETHOD(channel_setblocksize, emupchan_setblocksize),
+ KOBJMETHOD(channel_trigger, emupchan_trigger),
+ KOBJMETHOD(channel_getptr, emupchan_getptr),
+ KOBJMETHOD(channel_getcaps, emupchan_getcaps),
+ {0, 0}
+};
+CHANNEL_DECLARE(emupchan);
+
+static void *
+emurchan_init(kobj_t obj __unused, void *devinfo, struct snd_dbuf *b, struct pcm_channel *c, int dir __unused)
+{
+ struct emu_pcm_info *sc = devinfo;
+ struct emu_pcm_rchinfo *ch;
+
+ KASSERT(dir == PCMDIR_REC, ("emurchan_init: bad direction"));
+ ch = &sc->rch_adc;
+ ch->buffer = b;
+ ch->pcm = sc;
+ ch->channel = c;
+ ch->blksz = sc->bufsz / 2; /* We rise interrupt for half-full buffer */
+ ch->fmt = AFMT_U8;
+ ch->spd = 8000;
+ ch->idxreg = sc->is_emu10k1 ? ADCIDX : A_ADCIDX;
+ ch->basereg = ADCBA;
+ ch->sizereg = ADCBS;
+ ch->setupreg = ADCCR;
+ ch->irqmask = INTE_ADCBUFENABLE;
+ ch->iprmask = IPR_ADCBUFFULL | IPR_ADCBUFHALFFULL;
+
+ if (sndbuf_alloc(ch->buffer, emu_gettag(sc->card), 0, sc->bufsz) != 0)
+ return (NULL);
+ else {
+ ch->timer = emu_timer_create(sc->card);
+ emu_wrptr(sc->card, 0, ch->basereg, sndbuf_getbufaddr(ch->buffer));
+ emu_wrptr(sc->card, 0, ch->sizereg, 0); /* off */
+ return (ch);
+ }
+}
+
+static int
+emurchan_free(kobj_t obj __unused, void *c_devinfo)
+{
+ struct emu_pcm_rchinfo *ch = c_devinfo;
+ struct emu_pcm_info *sc = ch->pcm;
+
+ emu_timer_clear(sc->card, ch->timer);
+ return (0);
+}
+
+static int
+emurchan_setformat(kobj_t obj __unused, void *c_devinfo, uint32_t format)
+{
+ struct emu_pcm_rchinfo *ch = c_devinfo;
+
+ ch->fmt = format;
+ return (0);
+}
+
+static int
+emurchan_setspeed(kobj_t obj __unused, void *c_devinfo, uint32_t speed)
+{
+ struct emu_pcm_rchinfo *ch = c_devinfo;
+
+ if (ch->pcm->is_emu10k1) {
+ speed = emu10k1_adcspeed[emu_k1_recval(speed)];
+ } else {
+ speed = emu10k2_adcspeed[emu_k2_recval(speed)];
+ }
+ ch->spd = speed;
+ return (ch->spd);
+}
+
+static int
+emurchan_setblocksize(kobj_t obj __unused, void *c_devinfo, uint32_t blocksize)
+{
+ struct emu_pcm_rchinfo *ch = c_devinfo;
+ struct emu_pcm_info *sc = ch->pcm;
+
+ ch->blksz = blocksize;
+ /*
+ * If blocksize is less than half of buffer size we will not get
+ * BUFHALFFULL interrupt in time and channel will need to generate
+ * (and use) timer interrupts. Otherwise channel will be marked dead.
+ */
+ if (ch->blksz < (ch->pcm->bufsz / 2)) {
+ emu_timer_set(sc->card, ch->timer, ch->blksz / sndbuf_getbps(ch->buffer));
+ emu_timer_enable(sc->card, ch->timer, 1);
+ } else {
+ emu_timer_enable(sc->card, ch->timer, 0);
+ }
+ return (ch->blksz);
+}
+
+static int
+emurchan_trigger(kobj_t obj __unused, void *c_devinfo, int go)
+{
+ struct emu_pcm_rchinfo *ch = c_devinfo;
+ struct emu_pcm_info *sc = ch->pcm;
+ uint32_t val, sz;
+
+ if (!PCMTRIG_COMMON(go))
+ return (0);
+
+ switch (sc->bufsz) {
+ case 4096:
+ sz = ADCBS_BUFSIZE_4096;
+ break;
+ case 8192:
+ sz = ADCBS_BUFSIZE_8192;
+ break;
+ case 16384:
+ sz = ADCBS_BUFSIZE_16384;
+ break;
+ case 32768:
+ sz = ADCBS_BUFSIZE_32768;
+ break;
+ case 65536:
+ sz = ADCBS_BUFSIZE_65536;
+ break;
+ default:
+ sz = ADCBS_BUFSIZE_4096;
+ }
+
+ snd_mtxlock(sc->lock);
+ switch (go) {
+ case PCMTRIG_START:
+ ch->run = 1;
+ emu_wrptr(sc->card, 0, ch->sizereg, sz);
+ val = sc->is_emu10k1 ? ADCCR_LCHANENABLE : A_ADCCR_LCHANENABLE;
+ if (ch->fmt & AFMT_STEREO)
+ val |= sc->is_emu10k1 ? ADCCR_RCHANENABLE : A_ADCCR_RCHANENABLE;
+ val |= sc->is_emu10k1 ? emu_k1_recval(ch->spd) : emu_k2_recval(ch->spd);
+ emu_wrptr(sc->card, 0, ch->setupreg, 0);
+ emu_wrptr(sc->card, 0, ch->setupreg, val);
+ ch->ihandle = emu_intr_register(sc->card, ch->irqmask, ch->iprmask, &emu_pcm_intr, sc);
+ break;
+ case PCMTRIG_STOP:
+ /* FALLTHROUGH */
+ case PCMTRIG_ABORT:
+ ch->run = 0;
+ emu_wrptr(sc->card, 0, ch->sizereg, 0);
+ if (ch->setupreg)
+ emu_wrptr(sc->card, 0, ch->setupreg, 0);
+ (void)emu_intr_unregister(sc->card, ch->ihandle);
+ break;
+ case PCMTRIG_EMLDMAWR:
+ /* FALLTHROUGH */
+ case PCMTRIG_EMLDMARD:
+ /* FALLTHROUGH */
+ default:
+ break;
+ }
+ snd_mtxunlock(sc->lock);
+
+ return (0);
+}
+
+static int
+emurchan_getptr(kobj_t obj __unused, void *c_devinfo)
+{
+ struct emu_pcm_rchinfo *ch = c_devinfo;
+ struct emu_pcm_info *sc = ch->pcm;
+ int r;
+
+ r = emu_rdptr(sc->card, 0, ch->idxreg) & 0x0000ffff;
+
+ return (r);
+}
+
+static struct pcmchan_caps *
+emurchan_getcaps(kobj_t obj __unused, void *c_devinfo __unused)
+{
+ return (&emu_reccaps_adc);
+}
+
+static kobj_method_t emurchan_methods[] = {
+ KOBJMETHOD(channel_init, emurchan_init),
+ KOBJMETHOD(channel_free, emurchan_free),
+ KOBJMETHOD(channel_setformat, emurchan_setformat),
+ KOBJMETHOD(channel_setspeed, emurchan_setspeed),
+ KOBJMETHOD(channel_setblocksize, emurchan_setblocksize),
+ KOBJMETHOD(channel_trigger, emurchan_trigger),
+ KOBJMETHOD(channel_getptr, emurchan_getptr),
+ KOBJMETHOD(channel_getcaps, emurchan_getcaps),
+ {0, 0}
+};
+CHANNEL_DECLARE(emurchan);
+
+static void *
+emufxrchan_init(kobj_t obj __unused, void *devinfo, struct snd_dbuf *b, struct pcm_channel *c, int dir __unused)
+{
+ struct emu_pcm_info *sc = devinfo;
+ struct emu_pcm_rchinfo *ch;
+
+ KASSERT(dir == PCMDIR_REC, ("emurchan_init: bad direction"));
+
+ if (sc == NULL) return (NULL);
+
+ ch = &(sc->rch_efx);
+ ch->fmt = AFMT_S16_LE;
+ ch->spd = sc->is_emu10k1 ? 48000*32 : 48000 * 64;
+ ch->idxreg = FXIDX;
+ ch->basereg = FXBA;
+ ch->sizereg = FXBS;
+ ch->irqmask = INTE_EFXBUFENABLE;
+ ch->iprmask = IPR_EFXBUFFULL | IPR_EFXBUFHALFFULL;
+ ch->buffer = b;
+ ch->pcm = sc;
+ ch->channel = c;
+ ch->blksz = sc->bufsz / 2;
+
+ if (sndbuf_alloc(ch->buffer, emu_gettag(sc->card), 0, sc->bufsz) != 0)
+ return (NULL);
+ else {
+ emu_wrptr(sc->card, 0, ch->basereg, sndbuf_getbufaddr(ch->buffer));
+ emu_wrptr(sc->card, 0, ch->sizereg, 0); /* off */
+ return (ch);
+ }
+}
+
+static int
+emufxrchan_setformat(kobj_t obj __unused, void *c_devinfo __unused, uint32_t format)
+{
+ if (format == AFMT_S16_LE) return (0);
+ return (EINVAL);
+}
+
+static int
+emufxrchan_setspeed(kobj_t obj __unused, void *c_devinfo, uint32_t speed)
+{
+ struct emu_pcm_rchinfo *ch = c_devinfo;
+
+ /* FIXED RATE CHANNEL */
+ return (ch->spd);
+}
+
+static int
+emufxrchan_setblocksize(kobj_t obj __unused, void *c_devinfo, uint32_t blocksize)
+{
+ struct emu_pcm_rchinfo *ch = c_devinfo;
+
+ ch->blksz = blocksize;
+ /*
+ * XXX If blocksize is less than half of buffer size we will not get
+ * interrupt in time and channel will die due to interrupt timeout.
+ * This should not happen with FX rchan, because it will fill buffer
+ * very fast (64K buffer is 0.021seconds on Audigy).
+ */
+ if (ch->blksz < (ch->pcm->bufsz / 2))
+ ch->blksz = ch->pcm->bufsz / 2;
+ return (ch->blksz);
+}
+
+static int
+emufxrchan_trigger(kobj_t obj __unused, void *c_devinfo, int go)
+{
+ struct emu_pcm_rchinfo *ch = c_devinfo;
+ struct emu_pcm_info *sc = ch->pcm;
+ uint32_t sz;
+
+ if (!PCMTRIG_COMMON(go))
+ return (0);
+
+ switch (sc->bufsz) {
+ case 4096:
+ sz = ADCBS_BUFSIZE_4096;
+ break;
+ case 8192:
+ sz = ADCBS_BUFSIZE_8192;
+ break;
+ case 16384:
+ sz = ADCBS_BUFSIZE_16384;
+ break;
+ case 32768:
+ sz = ADCBS_BUFSIZE_32768;
+ break;
+ case 65536:
+ sz = ADCBS_BUFSIZE_65536;
+ break;
+ default:
+ sz = ADCBS_BUFSIZE_4096;
+ }
+
+ snd_mtxlock(sc->lock);
+ switch (go) {
+ case PCMTRIG_START:
+ ch->run = 1;
+ emu_wrptr(sc->card, 0, ch->sizereg, sz);
+ ch->ihandle = emu_intr_register(sc->card, ch->irqmask, ch->iprmask, &emu_pcm_intr, sc);
+ /*
+ * SB Live! is limited to 32 mono channels. Audigy
+ * has 64 mono channels. Channels are enabled
+ * by setting a bit in A_FXWC[1|2] registers.
+ */
+ /* XXX there is no way to demultiplex this streams for now */
+ if (sc->is_emu10k1) {
+ emu_wrptr(sc->card, 0, FXWC, 0xffffffff);
+ } else {
+ emu_wrptr(sc->card, 0, A_FXWC1, 0xffffffff);
+ emu_wrptr(sc->card, 0, A_FXWC2, 0xffffffff);
+ }
+ break;
+ case PCMTRIG_STOP:
+ /* FALLTHROUGH */
+ case PCMTRIG_ABORT:
+ ch->run = 0;
+ if (sc->is_emu10k1) {
+ emu_wrptr(sc->card, 0, FXWC, 0x0);
+ } else {
+ emu_wrptr(sc->card, 0, A_FXWC1, 0x0);
+ emu_wrptr(sc->card, 0, A_FXWC2, 0x0);
+ }
+ emu_wrptr(sc->card, 0, ch->sizereg, 0);
+ (void)emu_intr_unregister(sc->card, ch->ihandle);
+ break;
+ case PCMTRIG_EMLDMAWR:
+ /* FALLTHROUGH */
+ case PCMTRIG_EMLDMARD:
+ /* FALLTHROUGH */
+ default:
+ break;
+ }
+ snd_mtxunlock(sc->lock);
+
+ return (0);
+}
+
+static int
+emufxrchan_getptr(kobj_t obj __unused, void *c_devinfo)
+{
+ struct emu_pcm_rchinfo *ch = c_devinfo;
+ struct emu_pcm_info *sc = ch->pcm;
+ int r;
+
+ r = emu_rdptr(sc->card, 0, ch->idxreg) & 0x0000ffff;
+
+ return (r);
+}
+
+static struct pcmchan_caps *
+emufxrchan_getcaps(kobj_t obj __unused, void *c_devinfo)
+{
+ struct emu_pcm_rchinfo *ch = c_devinfo;
+ struct emu_pcm_info *sc = ch->pcm;
+
+ if (sc->is_emu10k1)
+ return (&emu_reccaps_efx_live);
+ return (&emu_reccaps_efx_audigy);
+
+}
+
+static int
+emufxrchan_getrates(kobj_t obj __unused, void *c_devinfo, int **rates)
+{
+ struct emu_pcm_rchinfo *ch = c_devinfo;
+ struct emu_pcm_info *sc = ch->pcm;
+
+ if (sc->is_emu10k1)
+ *rates = emu_rates_live;
+ else
+ *rates = emu_rates_audigy;
+
+ return 1;
+}
+
+static kobj_method_t emufxrchan_methods[] = {
+ KOBJMETHOD(channel_init, emufxrchan_init),
+ KOBJMETHOD(channel_setformat, emufxrchan_setformat),
+ KOBJMETHOD(channel_setspeed, emufxrchan_setspeed),
+ KOBJMETHOD(channel_setblocksize, emufxrchan_setblocksize),
+ KOBJMETHOD(channel_trigger, emufxrchan_trigger),
+ KOBJMETHOD(channel_getptr, emufxrchan_getptr),
+ KOBJMETHOD(channel_getcaps, emufxrchan_getcaps),
+ KOBJMETHOD(channel_getrates, emufxrchan_getrates),
+ {0, 0}
+};
+CHANNEL_DECLARE(emufxrchan);
+
+
+static uint32_t
+emu_pcm_intr(void *pcm, uint32_t stat)
+{
+ struct emu_pcm_info *sc = (struct emu_pcm_info *)pcm;
+ uint32_t ack;
+ int i;
+
+ ack = 0;
+
+ snd_mtxlock(sc->lock);
+
+ if (stat & IPR_INTERVALTIMER) {
+ ack |= IPR_INTERVALTIMER;
+ for (i = 0; i < MAX_CHANNELS; i++)
+ if (sc->pch[i].channel) {
+ if (sc->pch[i].run == 1) {
+ snd_mtxunlock(sc->lock);
+ chn_intr(sc->pch[i].channel);
+ snd_mtxlock(sc->lock);
+ } else
+ emu_timer_enable(sc->card, sc->pch[i].timer, 0);
+ }
+ /* ADC may install timer to get low-latency interrupts */
+ if ((sc->rch_adc.channel) && (sc->rch_adc.run)) {
+ snd_mtxunlock(sc->lock);
+ chn_intr(sc->rch_adc.channel);
+ snd_mtxlock(sc->lock);
+ }
+ /*
+ * EFX does not use timer, because it will fill
+ * buffer at least 32x times faster than ADC.
+ */
+ }
+
+
+ if (stat & (IPR_ADCBUFFULL | IPR_ADCBUFHALFFULL)) {
+ ack |= stat & (IPR_ADCBUFFULL | IPR_ADCBUFHALFFULL);
+ if (sc->rch_adc.channel) {
+ snd_mtxunlock(sc->lock);
+ chn_intr(sc->rch_adc.channel);
+ snd_mtxlock(sc->lock);
+ }
+ }
+
+ if (stat & (IPR_EFXBUFFULL | IPR_EFXBUFHALFFULL)) {
+ ack |= stat & (IPR_EFXBUFFULL | IPR_EFXBUFHALFFULL);
+ if (sc->rch_efx.channel) {
+ snd_mtxunlock(sc->lock);
+ chn_intr(sc->rch_efx.channel);
+ snd_mtxlock(sc->lock);
+ }
+ }
+ snd_mtxunlock(sc->lock);
+
+ return (ack);
+}
+
+static int
+emu_pcm_init(struct emu_pcm_info *sc)
+{
+ sc->bufsz = pcm_getbuffersize(sc->dev, EMUPAGESIZE, EMU_REC_BUFSZ, EMU_MAX_BUFSZ);
+ return (0);
+}
+
+static int
+emu_pcm_uninit(struct emu_pcm_info *sc __unused)
+{
+ return (0);
+}
+
+static int
+emu_pcm_probe(device_t dev)
+{
+ uintptr_t func, route, r;
+ const char *rt;
+ char buffer[255];
+
+ r = BUS_READ_IVAR(device_get_parent(dev), dev, EMU_VAR_FUNC, &func);
+
+ if (func != SCF_PCM)
+ return (ENXIO);
+
+ rt = "UNKNOWN";
+ r = BUS_READ_IVAR(device_get_parent(dev), dev, EMU_VAR_ROUTE, &route);
+ switch (route) {
+ case RT_FRONT:
+ rt = "front";
+ break;
+ case RT_REAR:
+ rt = "rear";
+ break;
+ case RT_CENTER:
+ rt = "center";
+ break;
+ case RT_SUB:
+ rt = "subwoofer";
+ break;
+ case RT_SIDE:
+ rt = "side";
+ break;
+ case RT_MCHRECORD:
+ rt = "multichannel recording";
+ break;
+ }
+
+ snprintf(buffer, 255, "EMU10Kx DSP %s PCM interface", rt);
+ device_set_desc_copy(dev, buffer);
+ return (0);
+}
+
+static int
+emu_pcm_attach(device_t dev)
+{
+ struct emu_pcm_info *sc;
+ unsigned int i;
+ char status[SND_STATUSLEN];
+ uint32_t inte, ipr;
+ uintptr_t route, r, ivar;
+
+ sc = malloc(sizeof(*sc), M_DEVBUF, M_WAITOK | M_ZERO);
+ sc->card = (struct emu_sc_info *)(device_get_softc(device_get_parent(dev)));
+ if (sc->card == NULL) {
+ device_printf(dev, "cannot get bridge conf\n");
+ free(sc, M_DEVBUF);
+ return (ENXIO);
+ }
+
+ sc->lock = snd_mtxcreate(device_get_nameunit(dev), "snd_emu10kx pcm softc");
+ sc->dev = dev;
+
+ r = BUS_READ_IVAR(device_get_parent(dev), dev, EMU_VAR_ISEMU10K1, &ivar);
+ sc->is_emu10k1 = ivar ? 1 : 0;
+
+ r = BUS_READ_IVAR(device_get_parent(dev), dev, EMU_VAR_MCH_DISABLED, &ivar);
+ sc->mch_disabled = ivar ? 1 : 0;
+
+ sc->codec = NULL;
+
+ for (i = 0; i < 8; i++) {
+ sc->rt.routing_left[i] = i;
+ sc->rt.amounts_left[i] = 0x00;
+ sc->rt.routing_right[i] = i;
+ sc->rt.amounts_right[i] = 0x00;
+ }
+
+ for (i = 0; i < 8; i++) {
+ sc->rt_mono.routing_left[i] = i;
+ sc->rt_mono.amounts_left[i] = 0x00;
+ sc->rt_mono.routing_right[i] = i;
+ sc->rt_mono.amounts_right[i] = 0x00;
+ }
+
+ sc->emu10k1_volcache[0][0] = 75;
+ sc->emu10k1_volcache[1][0] = 75;
+ sc->emu10k1_volcache[0][1] = 75;
+ sc->emu10k1_volcache[1][1] = 75;
+ r = BUS_READ_IVAR(device_get_parent(dev), dev, EMU_VAR_ROUTE, &route);
+ sc->route = route;
+ switch (route) {
+ case RT_FRONT:
+ sc->rt.amounts_left[0] = 0xff;
+ sc->rt.amounts_right[1] = 0xff;
+ sc->rt_mono.amounts_left[0] = 0xff;
+ sc->rt_mono.amounts_left[1] = 0xff;
+ if (sc->is_emu10k1)
+ sc->codec = AC97_CREATE(dev, sc, emu_ac97);
+ else
+ sc->codec = AC97_CREATE(dev, sc, emu_eac97);
+ sc->ac97_mixerclass = NULL;
+ if (sc->codec != NULL)
+ sc->ac97_mixerclass = ac97_getmixerclass();
+ if (mixer_init(dev, &emudspmixer_class, sc)) {
+ device_printf(dev, "failed to initialize DSP mixer\n");
+ goto bad;
+ }
+ break;
+ case RT_REAR:
+ sc->rt.amounts_left[2] = 0xff;
+ sc->rt.amounts_right[3] = 0xff;
+ sc->rt_mono.amounts_left[2] = 0xff;
+ sc->rt_mono.amounts_left[3] = 0xff;
+ if (mixer_init(dev, &emudspmixer_class, sc)) {
+ device_printf(dev, "failed to initialize mixer\n");
+ goto bad;
+ }
+ break;
+ case RT_CENTER:
+ sc->rt.amounts_left[4] = 0xff;
+ sc->rt_mono.amounts_left[4] = 0xff;
+ if (mixer_init(dev, &emudspmixer_class, sc)) {
+ device_printf(dev, "failed to initialize mixer\n");
+ goto bad;
+ }
+ break;
+ case RT_SUB:
+ sc->rt.amounts_left[5] = 0xff;
+ sc->rt_mono.amounts_left[5] = 0xff;
+ if (mixer_init(dev, &emudspmixer_class, sc)) {
+ device_printf(dev, "failed to initialize mixer\n");
+ goto bad;
+ }
+ break;
+ case RT_SIDE:
+ sc->rt.amounts_left[6] = 0xff;
+ sc->rt.amounts_right[7] = 0xff;
+ sc->rt_mono.amounts_left[6] = 0xff;
+ sc->rt_mono.amounts_left[7] = 0xff;
+ if (mixer_init(dev, &emudspmixer_class, sc)) {
+ device_printf(dev, "failed to initialize mixer\n");
+ goto bad;
+ }
+ break;
+ case RT_MCHRECORD:
+ if (mixer_init(dev, &emuefxmixer_class, sc)) {
+ device_printf(dev, "failed to initialize EFX mixer\n");
+ goto bad;
+ }
+ break;
+ default:
+ device_printf(dev, "invalid default route\n");
+ goto bad;
+ }
+
+ inte = INTE_INTERVALTIMERENB;
+ ipr = IPR_INTERVALTIMER; /* Used by playback & ADC */
+ sc->ihandle = emu_intr_register(sc->card, inte, ipr, &emu_pcm_intr, sc);
+
+ if (emu_pcm_init(sc) == -1) {
+ device_printf(dev, "unable to initialize PCM part of the card\n");
+ goto bad;
+ }
+
+ /*
+ * We don't register interrupt handler with snd_setup_intr
+ * in pcm device. Mark pcm device as MPSAFE manually.
+ */
+ pcm_setflags(dev, pcm_getflags(dev) | SD_F_MPSAFE);
+
+ /* XXX we should better get number of available channels from parent */
+ if (pcm_register(dev, sc, (route == RT_FRONT) ? MAX_CHANNELS : 1, (route == RT_FRONT) ? 1 : 0)) {
+ device_printf(dev, "can't register PCM channels!\n");
+ goto bad;
+ }
+ sc->pnum = 0;
+ if (route != RT_MCHRECORD)
+ pcm_addchan(dev, PCMDIR_PLAY, &emupchan_class, sc);
+ if (route == RT_FRONT) {
+ for (i = 1; i < MAX_CHANNELS; i++)
+ pcm_addchan(dev, PCMDIR_PLAY, &emupchan_class, sc);
+ pcm_addchan(dev, PCMDIR_REC, &emurchan_class, sc);
+ }
+ if (route == RT_MCHRECORD)
+ pcm_addchan(dev, PCMDIR_REC, &emufxrchan_class, sc);
+
+ snprintf(status, SND_STATUSLEN, "on %s", device_get_nameunit(device_get_parent(dev)));
+ pcm_setstatus(dev, status);
+
+ return (0);
+
+bad:
+ if (sc->codec)
+ ac97_destroy(sc->codec);
+ if (sc->lock)
+ snd_mtxfree(sc->lock);
+ free(sc, M_DEVBUF);
+ return (ENXIO);
+}
+
+static int
+emu_pcm_detach(device_t dev)
+{
+ int r;
+ struct emu_pcm_info *sc;
+
+ sc = pcm_getdevinfo(dev);
+
+ r = pcm_unregister(dev);
+
+ if (r) return (r);
+
+ emu_pcm_uninit(sc);
+
+ if (sc->lock)
+ snd_mtxfree(sc->lock);
+ free(sc, M_DEVBUF);
+
+ return (0);
+}
+
+static device_method_t emu_pcm_methods[] = {
+ DEVMETHOD(device_probe, emu_pcm_probe),
+ DEVMETHOD(device_attach, emu_pcm_attach),
+ DEVMETHOD(device_detach, emu_pcm_detach),
+ {0, 0}
+};
+
+static driver_t emu_pcm_driver = {
+ "pcm",
+ emu_pcm_methods,
+ PCM_SOFTC_SIZE,
+ NULL,
+ 0,
+ NULL
+};
+DRIVER_MODULE(snd_emu10kx_pcm, emu10kx, emu_pcm_driver, pcm_devclass, 0, 0);
+MODULE_DEPEND(snd_emu10kx_pcm, snd_emu10kx, SND_EMU10KX_MINVER, SND_EMU10KX_PREFVER, SND_EMU10KX_MAXVER);
+MODULE_DEPEND(snd_emu10kx_pcm, sound, SOUND_MINVER, SOUND_PREFVER, SOUND_MAXVER);
+MODULE_VERSION(snd_emu10kx_pcm, SND_EMU10KX_PREFVER);
Index: ich.h
===================================================================
RCS file: /home/cvs/src/sys/dev/sound/pci/ich.h,v
retrieving revision 1.2
retrieving revision 1.3
diff -L sys/dev/sound/pci/ich.h -L sys/dev/sound/pci/ich.h -u -r1.2 -r1.3
--- sys/dev/sound/pci/ich.h
+++ sys/dev/sound/pci/ich.h
@@ -1,32 +1,31 @@
/*-
-* Copyright (c) 2000 Katsurajima Naoto <raven at katsurajima.seya.yokohama.jp>
-* Copyright (c) 2001 Cameron Grant <cg at freebsd.org>
-* All rights reserved.
-*
-* Redistribution and use in source and binary forms, with or without
-* modification, are permitted provided that the following conditions
-* are met:
-* 1. Redistributions of source code must retain the above copyright
-* notice, this list of conditions and the following disclaimer.
-* 2. Redistributions in binary form must reproduce the above copyright
-* notice, this list of conditions and the following disclaimer in the
-* documentation and/or other materials provided with the distribution.
-*
-* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
-* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
-* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
-* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
-* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHERIN CONTRACT, STRICT
-* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
-* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THEPOSSIBILITY OF
-* SUCH DAMAGE.
-*
-* $MidnightBSD$
-* $FreeBSD: src/sys/dev/sound/pci/ich.h,v 1.4 2005/01/06 01:43:19 imp Exp $
-*/
+ * Copyright (c) 2000 Katsurajima Naoto <raven at katsurajima.seya.yokohama.jp>
+ * Copyright (c) 2001 Cameron Grant <cg at freebsd.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHERIN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THEPOSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD: src/sys/dev/sound/pci/ich.h,v 1.4 2005/01/06 01:43:19 imp Exp $
+ */
#define PCIR_NAMBAR 0x10
#define PCIR_NABMBAR 0x14
Index: au88x0.h
===================================================================
RCS file: /home/cvs/src/sys/dev/sound/pci/au88x0.h,v
retrieving revision 1.2
retrieving revision 1.3
diff -L sys/dev/sound/pci/au88x0.h -L sys/dev/sound/pci/au88x0.h -u -r1.2 -r1.3
--- sys/dev/sound/pci/au88x0.h
+++ sys/dev/sound/pci/au88x0.h
@@ -1,52 +1,51 @@
/*-
-* Copyright (c) 2003 Dag-Erling Coïdan Smørgrav
-* All rights reserved.
-*
-* Redistribution and use in source and binary forms, with or without
-* modification, are permitted provided that the following conditions
-* are met:
-* 1. Redistributions of source code must retain the above copyright
-* notice, this list of conditions and the following disclaimer
-* in this position and unchanged.
-* 2. Redistributions in binary form must reproduce the above copyright
-* notice, this list of conditions and the following disclaimer in the
-* documentation and/or other materials provided with the distribution.
-* 3. The name of the author may not be used to endorse or promote products
-* derived from this software without specific prior written permission.
-*
-* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
-* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
-* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
-* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
-* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
-* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
-* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-*
-* $MidnightBSD$
-* $FreeBSD: src/sys/dev/sound/pci/au88x0.h,v 1.2 2003/10/12 11:33:39 des Exp $
-*/
+ * Copyright (c) 2003 Dag-Erling Coïdan Smørgrav
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer
+ * in this position and unchanged.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD: src/sys/dev/sound/pci/au88x0.h,v 1.2 2003/10/12 11:33:39 des Exp $
+ */
#ifndef _AU88X0_H_INCLUDED
#define _AU88X0_H_INCLUDED
/*
-* Chipset parameters
-*/
+ * Chipset parameters
+ */
struct au88x0_chipset {
-const char *auc_name;
-uint32_t auc_pci_id;
+ const char *auc_name;
+ uint32_t auc_pci_id;
-/* General control register */
-uint32_t auc_control;
+ /* General control register */
+ uint32_t auc_control;
#define AU88X0_CTL_MIDI_ENABLE 0x0001
#define AU88X0_CTL_GAME_ENABLE 0x0008
#define AU88X0_CTL_IRQ_ENABLE 0x4000
-/* IRQ control register */
-uint32_t auc_irq_source;
+ /* IRQ control register */
+ uint32_t auc_irq_source;
#define AU88X0_IRQ_FATAL_ERR 0x0001
#define AU88X0_IRQ_PARITY_ERR 0x0002
#define AU88X0_IRQ_REG_ERR 0x0004
@@ -56,88 +55,88 @@
#define AU88X0_IRQ_TIMER 0x1000
#define AU88X0_IRQ_MIDI 0x2000
#define AU88X0_IRQ_MODEM 0x4000
-uint32_t auc_irq_mask;
-uint32_t auc_irq_control;
+ uint32_t auc_irq_mask;
+ uint32_t auc_irq_control;
#define AU88X0_IRQ_PENDING_BIT 0x0001
-uint32_t auc_irq_status;
+ uint32_t auc_irq_status;
-/* DMA control registers */
-uint32_t auc_dma_control;
+ /* DMA control registers */
+ uint32_t auc_dma_control;
-/* FIFOs */
-int auc_fifo_size;
-int auc_wt_fifos;
-uint32_t auc_wt_fifo_base;
-uint32_t auc_wt_fifo_ctl;
-uint32_t auc_wt_dma_ctl;
-int auc_adb_fifos;
-uint32_t auc_adb_fifo_base;
-uint32_t auc_adb_fifo_ctl;
-uint32_t auc_adb_dma_ctl;
-
-/* Routing */
-uint32_t auc_adb_route_base;
-int auc_adb_route_bits;
-int auc_adb_codec_in;
-int auc_adb_codec_out;
+ /* FIFOs */
+ int auc_fifo_size;
+ int auc_wt_fifos;
+ uint32_t auc_wt_fifo_base;
+ uint32_t auc_wt_fifo_ctl;
+ uint32_t auc_wt_dma_ctl;
+ int auc_adb_fifos;
+ uint32_t auc_adb_fifo_base;
+ uint32_t auc_adb_fifo_ctl;
+ uint32_t auc_adb_dma_ctl;
+
+ /* Routing */
+ uint32_t auc_adb_route_base;
+ int auc_adb_route_bits;
+ int auc_adb_codec_in;
+ int auc_adb_codec_out;
};
/*
-* Channel information
-*/
+ * Channel information
+ */
struct au88x0_chan_info {
-struct au88x0_info *auci_aui;
-struct pcm_channel *auci_pcmchan;
-struct snd_dbuf *auci_buf;
-int auci_dir;
+ struct au88x0_info *auci_aui;
+ struct pcm_channel *auci_pcmchan;
+ struct snd_dbuf *auci_buf;
+ int auci_dir;
};
/*
-* Device information
-*/
+ * Device information
+ */
struct au88x0_info {
-/* the device we're associated with */
-device_t aui_dev;
-uint32_t aui_model;
-struct au88x0_chipset *aui_chipset;
-
-/* parameters */
-bus_size_t aui_bufsize;
-int aui_wt_fifos;
-int aui_wt_fifo_ctl;
-int aui_adb_fifos;
-int aui_adb_fifo_ctl;
-int aui_fifo_size;
-uint32_t aui_chanbase;
-
-/* bus_space tag and handle */
-bus_space_tag_t aui_spct;
-bus_space_handle_t aui_spch;
-
-/* register space */
-int aui_regtype;
-int aui_regid;
-struct resource *aui_reg;
-
-/* irq */
-int aui_irqtype;
-int aui_irqid;
-struct resource *aui_irq;
-void *aui_irqh;
+ /* the device we're associated with */
+ device_t aui_dev;
+ uint32_t aui_model;
+ struct au88x0_chipset *aui_chipset;
+
+ /* parameters */
+ bus_size_t aui_bufsize;
+ int aui_wt_fifos;
+ int aui_wt_fifo_ctl;
+ int aui_adb_fifos;
+ int aui_adb_fifo_ctl;
+ int aui_fifo_size;
+ uint32_t aui_chanbase;
+
+ /* bus_space tag and handle */
+ bus_space_tag_t aui_spct;
+ bus_space_handle_t aui_spch;
+
+ /* register space */
+ int aui_regtype;
+ int aui_regid;
+ struct resource *aui_reg;
+
+ /* irq */
+ int aui_irqtype;
+ int aui_irqid;
+ struct resource *aui_irq;
+ void *aui_irqh;
-/* dma */
-bus_dma_tag_t aui_dmat;
+ /* dma */
+ bus_dma_tag_t aui_dmat;
-/* codec */
-struct ac97_info *aui_ac97i;
+ /* codec */
+ struct ac97_info *aui_ac97i;
-/* channels */
-struct au88x0_chan_info aui_chan[2];
+ /* channels */
+ struct au88x0_chan_info aui_chan[2];
};
/*
-* Common parameters
-*/
+ * Common parameters
+ */
#define AU88X0_SETTLE_DELAY 1000
#define AU88X0_RETRY_COUNT 10
#define AU88X0_BUFSIZE_MIN 0x1000
@@ -145,20 +144,20 @@
#define AU88X0_BUFSIZE_MAX 0x4000
/*
-* Codec control registers
-*
-* AU88X0_CODEC_CHANNEL array of 32 32-bit words
-*
-* AU88X0_CODEC_CONTROL control register
-*
-* bit 16 ready
-*
-* AU88X0_CODEC_IO I/O register
-*
-* bits 0-15 contents of codec register
-* bits 16-22 address of codec register
-* bit 23 0 for read, 1 for write
-*/
+ * Codec control registers
+ *
+ * AU88X0_CODEC_CHANNEL array of 32 32-bit words
+ *
+ * AU88X0_CODEC_CONTROL control register
+ *
+ * bit 16 ready
+ *
+ * AU88X0_CODEC_IO I/O register
+ *
+ * bits 0-15 contents of codec register
+ * bits 16-22 address of codec register
+ * bit 23 0 for read, 1 for write
+ */
#define AU88X0_CODEC_CHANNEL 0x29080
#define AU88X0_CODEC_CONTROL 0x29184
#define AU88X0_CDCTL_WROK 0x00000100
@@ -169,8 +168,11 @@
#define AU88X0_CDIO_ADDR_MASK 0x007f0000
#define AU88X0_CDIO_RDBIT 0x00000000
#define AU88X0_CDIO_WRBIT 0x00800000
-#define AU88X0_CDIO_READ(a) (AU88X0_CDIO_RDBIT | (((a) << AU88X0_CDIO_ADDR_SHIFT) & AU88X0_CDIO_ADDR_MASK))
-#define AU88X0_CDIO_WRITE(a, d) (AU88X0_CDIO_WRBIT | (((a) << AU88X0_CDIO_ADDR_SHIFT) & AU88X0_CDIO_ADDR_MASK) | (((d) << AU88X0_CDIO_DATA_SHIFT) & AU88X0_CDIO_DATA_MASK))
+#define AU88X0_CDIO_READ(a) (AU88X0_CDIO_RDBIT | \
+ (((a) << AU88X0_CDIO_ADDR_SHIFT) & AU88X0_CDIO_ADDR_MASK))
+#define AU88X0_CDIO_WRITE(a, d) (AU88X0_CDIO_WRBIT | \
+ (((a) << AU88X0_CDIO_ADDR_SHIFT) & AU88X0_CDIO_ADDR_MASK) | \
+ (((d) << AU88X0_CDIO_DATA_SHIFT) & AU88X0_CDIO_DATA_MASK))
#define AU88X0_CODEC_ENABLE 0x29190
#endif
Index: neomagic.h
===================================================================
RCS file: /home/cvs/src/sys/dev/sound/pci/neomagic.h,v
retrieving revision 1.2
retrieving revision 1.3
diff -L sys/dev/sound/pci/neomagic.h -L sys/dev/sound/pci/neomagic.h -u -r1.2 -r1.3
--- sys/dev/sound/pci/neomagic.h
+++ sys/dev/sound/pci/neomagic.h
@@ -1,33 +1,32 @@
/*-
-* Copyright (c) 1999 Cameron Grant <cg at freebsd.org>
-* All rights reserved.
-*
-* Derived from the public domain Linux driver
-*
-* Redistribution and use in source and binary forms, with or without
-* modification, are permitted provided that the following conditions
-* are met:
-* 1. Redistributions of source code must retain the above copyright
-* notice, this list of conditions and the following disclaimer.
-* 2. Redistributions in binary form must reproduce the above copyright
-* notice, this list of conditions and the following disclaimer in the
-* documentation and/or other materials provided with the distribution.
-*
-* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
-* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
-* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
-* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
-* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHERIN CONTRACT, STRICT
-* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
-* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THEPOSSIBILITY OF
-* SUCH DAMAGE.
-*
-* $MidnightBSD$
-* $FreeBSD: src/sys/dev/sound/pci/neomagic.h,v 1.4 2005/01/06 01:43:19 imp Exp $
-*/
+ * Copyright (c) 1999 Cameron Grant <cg at freebsd.org>
+ * All rights reserved.
+ *
+ * Derived from the public domain Linux driver
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHERIN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THEPOSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD: src/sys/dev/sound/pci/neomagic.h,v 1.4 2005/01/06 01:43:19 imp Exp $
+ */
#ifndef _NM256_H_
#define _NM256_H_
@@ -64,9 +63,9 @@
#define NM_MIXER_READY_MASK 0x0800
/*
-* For the ZX. It uses the same interrupt register, but it holds 32
-* bits instead of 16.
-*/
+ * For the ZX. It uses the same interrupt register, but it holds 32
+ * bits instead of 16.
+ */
#define NM2_PLAYBACK_INT 0x10000
#define NM2_RECORD_INT 0x80000
#define NM2_MISC_INT_1 0x8
Index: via8233.h
===================================================================
RCS file: /home/cvs/src/sys/dev/sound/pci/via8233.h,v
retrieving revision 1.2
retrieving revision 1.3
diff -L sys/dev/sound/pci/via8233.h -L sys/dev/sound/pci/via8233.h -u -r1.2 -r1.3
--- sys/dev/sound/pci/via8233.h
+++ sys/dev/sound/pci/via8233.h
@@ -1,44 +1,43 @@
/*-
-* Copyright (c) 2002 Orion Hodson <orion at freebsd.org>
-* All rights reserved.
-*
-* Redistribution and use in source and binary forms, with or without
-* modification, are permitted provided that the following conditions
-* are met:
-* 1. Redistributions of source code must retain the above copyright
-* notice, this list of conditions and the following disclaimer.
-* 2. Redistributions in binary form must reproduce the above copyright
-* notice, this list of conditions and the following disclaimer in the
-* documentation and/or other materials provided with the distribution.
-*
-* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
-* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
-* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
-* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
-* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHERIN CONTRACT, STRICT
-* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
-* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THEPOSSIBILITY OF
-* SUCH DAMAGE.
-*
-* $MidnightBSD$
-* $FreeBSD: src/sys/dev/sound/pci/via8233.h,v 1.4 2005/01/06 01:43:19 imp Exp $
-*/
+ * Copyright (c) 2002 Orion Hodson <orion at freebsd.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHERIN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THEPOSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD: src/sys/dev/sound/pci/via8233.h,v 1.4 2005/01/06 01:43:19 imp Exp $
+ */
#ifndef _SYS_SOUND_PCI_VIA8233_H_
#define _SYS_SOUND_PCI_VIA8233_H_
/*
-* VIA Technologies VT8233 Southbridge Audio Driver
-*
-* Documentation sources:
-*
-* o V8233C specs. from VIA, gratefully received under NDA.
-* o AC97 R2.2 specs.
-* o ALSA driver (very useful comments)
-*/
+ * VIA Technologies VT8233 Southbridge Audio Driver
+ *
+ * Documentation sources:
+ *
+ * o V8233C specs. from VIA, gratefully received under NDA.
+ * o AC97 R2.2 specs.
+ * o ALSA driver (very useful comments)
+ */
#define VIA_PCI_SPDIF 0x49
#define VIA_SPDIF_EN 0x08
@@ -73,7 +72,10 @@
# define VIA_PCI_ACLINK_SERIAL 0x10
# define VIA_PCI_ACLINK_VRATE 0x08
# define VIA_PCI_ACLINK_SGD 0x04
-# define VIA_PCI_ACLINK_DESIRED (VIA_PCI_ACLINK_EN | VIA_PCI_ACLINK_NRST | VIA_PCI_ACLINK_VRATE | VIA_PCI_ACLINK_SGD)
+# define VIA_PCI_ACLINK_DESIRED (VIA_PCI_ACLINK_EN | \
+ VIA_PCI_ACLINK_NRST | \
+ VIA_PCI_ACLINK_VRATE | \
+ VIA_PCI_ACLINK_SGD)
#define VIA_MC_SGD_STATUS 0x40
#define VIA_WR0_SGD_STATUS 0x60
Index: cmireg.h
===================================================================
RCS file: /home/cvs/src/sys/dev/sound/pci/cmireg.h,v
retrieving revision 1.2
retrieving revision 1.3
diff -L sys/dev/sound/pci/cmireg.h -L sys/dev/sound/pci/cmireg.h -u -r1.2 -r1.3
--- sys/dev/sound/pci/cmireg.h
+++ sys/dev/sound/pci/cmireg.h
@@ -1,34 +1,33 @@
/*-
-* Copyright (c) 2000 The NetBSD Foundation, Inc.
-* All rights reserved.
-*
-* This code is derived from software contributed to The NetBSD Foundation
-* by Takuya SHIOZAKI <AoiMoe at imou.to> .
-*
-* Redistribution and use in source and binary forms, with or without
-* modification, are permitted provided that the following conditions
-* are met:
-* 1. Redistributions of source code must retain the above copyright
-* notice, this list of conditions and the following disclaimer.
-* 2. Redistributions in binary form must reproduce the above copyright
-* notice, this list of conditions and the following disclaimer in the
-* documentation and/or other materials provided with the distribution.
-*
-* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
-* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
-* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
-* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
-* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
-* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
-* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
-* SUCH DAMAGE.
-*
-* $MidnightBSD$
-* $FreeBSD: src/sys/dev/sound/pci/cmireg.h,v 1.3 2005/01/06 01:43:19 imp Exp $
-*/
+ * Copyright (c) 2000 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Takuya SHIOZAKI <AoiMoe at imou.to> .
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD: src/sys/dev/sound/pci/cmireg.h,v 1.3 2005/01/06 01:43:19 imp Exp $
+ */
/* C-Media CMI8x38 Audio Chip Support */
@@ -36,14 +35,14 @@
#define _DEV_PCI_CMPCIREG_H_ (1)
/*
-* PCI Configuration Registers
-*/
+ * PCI Configuration Registers
+ */
#define CMPCI_PCI_IOBASEREG (PCI_MAPREG_START)
/*
-* I/O Space
-*/
+ * I/O Space
+ */
#define CMPCI_REG_FUNC_0 0x00
# define CMPCI_REG_CH0_DIR 0x00000001
Index: vibes.c
===================================================================
RCS file: /home/cvs/src/sys/dev/sound/pci/vibes.c,v
retrieving revision 1.2
retrieving revision 1.3
diff -L sys/dev/sound/pci/vibes.c -L sys/dev/sound/pci/vibes.c -u -r1.2 -r1.3
--- sys/dev/sound/pci/vibes.c
+++ sys/dev/sound/pci/vibes.c
@@ -1,32 +1,32 @@
/*-
-* Copyright (c) 2001 Orion Hodson <O.Hodson at cs.ucl.ac.uk>
-* All rights reserved.
-*
-* Redistribution and use in source and binary forms, with or without
-* modification, are permitted provided that the following conditions
-* are met:
-* 1. Redistributions of source code must retain the above copyright
-* notice, this list of conditions and the following disclaimer.
-* 2. Redistributions in binary form must reproduce the above copyright
-* notice, this list of conditions and the following disclaimer in the
-* documentation and/or other materials provided with the distribution.
-*
-* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
-* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
-* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
-* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
-* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
-* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
-* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
-* SUCH DAMAGE.
-*
-* This card has the annoying habit of "clicking" when attached and
-* detached, haven't been able to remedy this with any combination of
-* muting.
-*/
+ * Copyright (c) 2001 Orion Hodson <O.Hodson at cs.ucl.ac.uk>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * This card has the annoying habit of "clicking" when attached and
+ * detached, haven't been able to remedy this with any combination of
+ * muting.
+ */
#include <dev/sound/pcm/sound.h>
#include <dev/sound/pci/vibes.h>
@@ -36,7 +36,7 @@
#include "mixer_if.h"
-SND_DECLARE_FILE("$MidnightBSD$");
+SND_DECLARE_FILE("$FreeBSD: src/sys/dev/sound/pci/vibes.c,v 1.26 2007/06/17 06:10:42 ariff Exp $");
/* ------------------------------------------------------------------------- */
/* Constants */
@@ -56,52 +56,52 @@
struct sc_info;
struct sc_chinfo {
-struct sc_info *parent;
-struct pcm_channel *channel;
-struct snd_dbuf *buffer;
-u_int32_t fmt, spd;
-int dir;
-int dma_active, dma_was_active;
+ struct sc_info *parent;
+ struct pcm_channel *channel;
+ struct snd_dbuf *buffer;
+ u_int32_t fmt, spd;
+ int dir;
+ int dma_active, dma_was_active;
};
struct sc_info {
-device_t dev;
+ device_t dev;
-/* DMA buffer allocator */
-bus_dma_tag_t parent_dmat;
+ /* DMA buffer allocator */
+ bus_dma_tag_t parent_dmat;
-/* Enhanced register resources */
-struct resource *enh_reg;
-bus_space_tag_t enh_st;
-bus_space_handle_t enh_sh;
-int enh_type;
-int enh_rid;
-
-/* DMA configuration */
-struct resource *dmaa_reg, *dmac_reg;
-bus_space_tag_t dmaa_st, dmac_st;
-bus_space_handle_t dmaa_sh, dmac_sh;
-int dmaa_type, dmac_type;
-int dmaa_rid, dmac_rid;
-
-/* Interrupt resources */
-struct resource *irq;
-int irqid;
-void *ih;
+ /* Enhanced register resources */
+ struct resource *enh_reg;
+ bus_space_tag_t enh_st;
+ bus_space_handle_t enh_sh;
+ int enh_type;
+ int enh_rid;
+
+ /* DMA configuration */
+ struct resource *dmaa_reg, *dmac_reg;
+ bus_space_tag_t dmaa_st, dmac_st;
+ bus_space_handle_t dmaa_sh, dmac_sh;
+ int dmaa_type, dmac_type;
+ int dmaa_rid, dmac_rid;
+
+ /* Interrupt resources */
+ struct resource *irq;
+ int irqid;
+ void *ih;
-/* User configurable buffer size */
-unsigned int bufsz;
+ /* User configurable buffer size */
+ unsigned int bufsz;
-struct sc_chinfo rch, pch;
-u_int8_t rev;
+ struct sc_chinfo rch, pch;
+ u_int8_t rev;
};
static u_int32_t sc_fmt[] = {
-AFMT_U8,
-AFMT_U8 | AFMT_STEREO,
-AFMT_S16_LE,
-AFMT_S16_LE | AFMT_STEREO,
-0
+ AFMT_U8,
+ AFMT_U8 | AFMT_STEREO,
+ AFMT_S16_LE,
+ AFMT_S16_LE | AFMT_STEREO,
+ 0
};
static struct pcmchan_caps sc_caps = {8000, 48000, sc_fmt, 0};
@@ -114,29 +114,29 @@
static u_int8_t
sv_direct_get(struct sc_info *sc, u_int8_t reg)
{
-return bus_space_read_1(sc->enh_st, sc->enh_sh, reg);
+ return bus_space_read_1(sc->enh_st, sc->enh_sh, reg);
}
static void
_sv_direct_set(struct sc_info *sc, u_int8_t reg, u_int8_t val, int line)
{
-u_int8_t n;
-bus_space_write_1(sc->enh_st, sc->enh_sh, reg, val);
+ u_int8_t n;
+ bus_space_write_1(sc->enh_st, sc->enh_sh, reg, val);
-n = sv_direct_get(sc, reg);
-if (n != val) {
-device_printf(sc->dev, "sv_direct_set register 0x%02x %d != %d from line %dn", reg, n, val, line);
-}
+ n = sv_direct_get(sc, reg);
+ if (n != val) {
+ device_printf(sc->dev, "sv_direct_set register 0x%02x %d != %d from line %d\n", reg, n, val, line);
+ }
}
static u_int8_t
sv_indirect_get(struct sc_info *sc, u_int8_t reg)
{
-if (reg == SV_REG_FORMAT || reg == SV_REG_ANALOG_PWR)
-reg |= SV_CM_INDEX_MCE;
+ if (reg == SV_REG_FORMAT || reg == SV_REG_ANALOG_PWR)
+ reg |= SV_CM_INDEX_MCE;
-bus_space_write_1(sc->enh_st, sc->enh_sh, SV_CM_INDEX, reg);
-return bus_space_read_1(sc->enh_st, sc->enh_sh, SV_CM_DATA);
+ bus_space_write_1(sc->enh_st, sc->enh_sh, SV_CM_INDEX, reg);
+ return bus_space_read_1(sc->enh_st, sc->enh_sh, SV_CM_DATA);
}
#define sv_indirect_set(x, y, z) _sv_indirect_set(x, y, z, __LINE__)
@@ -144,38 +144,38 @@
static void
_sv_indirect_set(struct sc_info *sc, u_int8_t reg, u_int8_t val, int line)
{
-if (reg == SV_REG_FORMAT || reg == SV_REG_ANALOG_PWR)
-reg |= SV_CM_INDEX_MCE;
+ if (reg == SV_REG_FORMAT || reg == SV_REG_ANALOG_PWR)
+ reg |= SV_CM_INDEX_MCE;
-bus_space_write_1(sc->enh_st, sc->enh_sh, SV_CM_INDEX, reg);
-bus_space_write_1(sc->enh_st, sc->enh_sh, SV_CM_DATA, val);
+ bus_space_write_1(sc->enh_st, sc->enh_sh, SV_CM_INDEX, reg);
+ bus_space_write_1(sc->enh_st, sc->enh_sh, SV_CM_DATA, val);
-reg &= ~SV_CM_INDEX_MCE;
-if (reg != SV_REG_ADC_PLLM) {
-u_int8_t n;
-n = sv_indirect_get(sc, reg);
-if (n != val) {
-device_printf(sc->dev, "sv_indirect_set register 0x%02x %d != %d line %dn", reg, n, val, line);
-}
-}
+ reg &= ~SV_CM_INDEX_MCE;
+ if (reg != SV_REG_ADC_PLLM) {
+ u_int8_t n;
+ n = sv_indirect_get(sc, reg);
+ if (n != val) {
+ device_printf(sc->dev, "sv_indirect_set register 0x%02x %d != %d line %d\n", reg, n, val, line);
+ }
+ }
}
static void
sv_dma_set_config(bus_space_tag_t st, bus_space_handle_t sh,
-u_int32_t base, u_int32_t count, u_int8_t mode)
+ u_int32_t base, u_int32_t count, u_int8_t mode)
{
-bus_space_write_4(st, sh, SV_DMA_ADDR, base);
-bus_space_write_4(st, sh, SV_DMA_COUNT, count & 0xffffff);
-bus_space_write_1(st, sh, SV_DMA_MODE, mode);
+ bus_space_write_4(st, sh, SV_DMA_ADDR, base);
+ bus_space_write_4(st, sh, SV_DMA_COUNT, count & 0xffffff);
+ bus_space_write_1(st, sh, SV_DMA_MODE, mode);
-DEB(printf("base 0x%08x count %5d mode 0x%02xn",
-base, count, mode));
+ DEB(printf("base 0x%08x count %5d mode 0x%02x\n",
+ base, count, mode));
}
static u_int32_t
sv_dma_get_count(bus_space_tag_t st, bus_space_handle_t sh)
{
-return bus_space_read_4(st, sh, SV_DMA_COUNT) & 0xffffff;
+ return bus_space_read_4(st, sh, SV_DMA_COUNT) & 0xffffff;
}
/* ------------------------------------------------------------------------- */
@@ -184,63 +184,63 @@
static void *
svchan_init(kobj_t obj, void *devinfo, struct snd_dbuf *b, struct pcm_channel *c, int dir)
{
-struct sc_info *sc = devinfo;
-struct sc_chinfo *ch;
-ch = (dir == PCMDIR_PLAY) ? &sc->pch : &sc->rch;
-
-ch->parent = sc;
-ch->channel = c;
-ch->dir = dir;
-
-if (sndbuf_alloc(b, sc->parent_dmat, sc->bufsz) != 0) {
-DEB(printf("svchan_init failedn"));
-return NULL;
-}
-ch->buffer = b;
-ch->fmt = AFMT_U8;
-ch->spd = DSP_DEFAULT_SPEED;
-ch->dma_active = ch->dma_was_active = 0;
+ struct sc_info *sc = devinfo;
+ struct sc_chinfo *ch;
+ ch = (dir == PCMDIR_PLAY) ? &sc->pch : &sc->rch;
+
+ ch->parent = sc;
+ ch->channel = c;
+ ch->dir = dir;
+
+ if (sndbuf_alloc(b, sc->parent_dmat, 0, sc->bufsz) != 0) {
+ DEB(printf("svchan_init failed\n"));
+ return NULL;
+ }
+ ch->buffer = b;
+ ch->fmt = AFMT_U8;
+ ch->spd = DSP_DEFAULT_SPEED;
+ ch->dma_active = ch->dma_was_active = 0;
-return ch;
+ return ch;
}
static struct pcmchan_caps *
svchan_getcaps(kobj_t obj, void *data)
{
-return &sc_caps;
+ return &sc_caps;
}
static int
svchan_setblocksize(kobj_t obj, void *data, u_int32_t blocksize)
{
-struct sc_chinfo *ch = data;
-struct sc_info *sc = ch->parent;
+ struct sc_chinfo *ch = data;
+ struct sc_info *sc = ch->parent;
-/* user has requested interrupts every blocksize bytes */
-RANGE(blocksize, SV_MIN_BLKSZ, sc->bufsz / SV_INTR_PER_BUFFER);
-sndbuf_resize(ch->buffer, SV_INTR_PER_BUFFER, blocksize);
-DEB(printf("svchan_setblocksize: %dn", blocksize));
-return blocksize;
+ /* user has requested interrupts every blocksize bytes */
+ RANGE(blocksize, SV_MIN_BLKSZ, sc->bufsz / SV_INTR_PER_BUFFER);
+ sndbuf_resize(ch->buffer, SV_INTR_PER_BUFFER, blocksize);
+ DEB(printf("svchan_setblocksize: %d\n", blocksize));
+ return blocksize;
}
static int
svchan_setformat(kobj_t obj, void *data, u_int32_t format)
{
-struct sc_chinfo *ch = data;
-/* NB Just note format here as setting format register
-* generates noise if dma channel is inactive. */
-ch->fmt = (format & AFMT_STEREO) ? SV_AFMT_STEREO : SV_AFMT_MONO;
-ch->fmt |= (format & AFMT_16BIT) ? SV_AFMT_S16 : SV_AFMT_U8;
-return 0;
+ struct sc_chinfo *ch = data;
+ /* NB Just note format here as setting format register
+ * generates noise if dma channel is inactive. */
+ ch->fmt = (format & AFMT_STEREO) ? SV_AFMT_STEREO : SV_AFMT_MONO;
+ ch->fmt |= (format & AFMT_16BIT) ? SV_AFMT_S16 : SV_AFMT_U8;
+ return 0;
}
static int
svchan_setspeed(kobj_t obj, void *data, u_int32_t speed)
{
-struct sc_chinfo *ch = data;
-RANGE(speed, 8000, 48000);
-ch->spd = speed;
-return speed;
+ struct sc_chinfo *ch = data;
+ RANGE(speed, 8000, 48000);
+ ch->spd = speed;
+ return speed;
}
/* ------------------------------------------------------------------------- */
@@ -249,125 +249,126 @@
static int
sv_set_recspeed(struct sc_info *sc, u_int32_t speed)
{
-u_int32_t f_out, f_actual;
-u_int32_t rs, re, r, best_r = 0, r2, t, n, best_n = 0;
-int32_t m, best_m = 0, ms, me, err, min_err;
-
-/* This algorithm is a variant described in sonicvibes.pdf
-* appendix A. This search is marginally more extensive and
-* results in (nominally) better sample rate matching. */
-
-f_out = SV_F_SCALE * speed;
-min_err = 0x7fffffff;
-
-/* Find bounds of r to examine, rs <= r <= re */
-t = 80000000 / f_out;
-for (rs = 1; (1 << rs) < t; rs++);
-
-t = 150000000 / f_out;
-for (re = 1; (2 << re) < t; re++);
-if (re > 7) re = 7;
-
-/* Search over r, n, m */
-for (r = rs; r <= re; r++) {
-r2 = (1 << r);
-for (n = 3; n < 34; n++) {
-m = f_out * n / (SV_F_REF / r2);
-ms = (m > 3) ? (m - 1) : 3;
-me = (m < 129) ? (m + 1) : 129;
-for (m = ms; m <= me; m++) {
-f_actual = m * SV_F_REF / (n * r2);
-if (f_actual > f_out) {
-err = f_actual - f_out;
-} else {
-err = f_out - f_actual;
-}
-if (err < min_err) {
-best_r = r;
-best_m = m - 2;
-best_n = n - 2;
-min_err = err;
-if (err == 0) break;
-}
-}
-}
-}
-
-sv_indirect_set(sc, SV_REG_ADC_PLLM, best_m);
-sv_indirect_set(sc, SV_REG_ADC_PLLN,
-SV_ADC_PLLN(best_n) | SV_ADC_PLLR(best_r));
-DEB(printf("svrchan_setspeed: %d -> PLLM 0x%02x PLLNR 0x%08xn",
-speed,
-sv_indirect_get(sc, SV_REG_ADC_PLLM),
-sv_indirect_get(sc, SV_REG_ADC_PLLN)));
-return 0;
+ u_int32_t f_out, f_actual;
+ u_int32_t rs, re, r, best_r = 0, r2, t, n, best_n = 0;
+ int32_t m, best_m = 0, ms, me, err, min_err;
+
+ /* This algorithm is a variant described in sonicvibes.pdf
+ * appendix A. This search is marginally more extensive and
+ * results in (nominally) better sample rate matching. */
+
+ f_out = SV_F_SCALE * speed;
+ min_err = 0x7fffffff;
+
+ /* Find bounds of r to examine, rs <= r <= re */
+ t = 80000000 / f_out;
+ for (rs = 1; (1 << rs) < t; rs++);
+
+ t = 150000000 / f_out;
+ for (re = 1; (2 << re) < t; re++);
+ if (re > 7) re = 7;
+
+ /* Search over r, n, m */
+ for (r = rs; r <= re; r++) {
+ r2 = (1 << r);
+ for (n = 3; n < 34; n++) {
+ m = f_out * n / (SV_F_REF / r2);
+ ms = (m > 3) ? (m - 1) : 3;
+ me = (m < 129) ? (m + 1) : 129;
+ for (m = ms; m <= me; m++) {
+ f_actual = m * SV_F_REF / (n * r2);
+ if (f_actual > f_out) {
+ err = f_actual - f_out;
+ } else {
+ err = f_out - f_actual;
+ }
+ if (err < min_err) {
+ best_r = r;
+ best_m = m - 2;
+ best_n = n - 2;
+ min_err = err;
+ if (err == 0) break;
+ }
+ }
+ }
+ }
+
+ sv_indirect_set(sc, SV_REG_ADC_PLLM, best_m);
+ sv_indirect_set(sc, SV_REG_ADC_PLLN,
+ SV_ADC_PLLN(best_n) | SV_ADC_PLLR(best_r));
+ DEB(printf("svrchan_setspeed: %d -> PLLM 0x%02x PLLNR 0x%08x\n",
+ speed,
+ sv_indirect_get(sc, SV_REG_ADC_PLLM),
+ sv_indirect_get(sc, SV_REG_ADC_PLLN)));
+ return 0;
}
static int
svrchan_trigger(kobj_t obj, void *data, int go)
{
-struct sc_chinfo *ch = data;
-struct sc_info *sc = ch->parent;
-u_int32_t count, enable;
-u_int8_t v;
-
-switch(go) {
-case PCMTRIG_START:
-/* Set speed */
-sv_set_recspeed(sc, ch->spd);
-
-/* Set format */
-v = sv_indirect_get(sc, SV_REG_FORMAT) & ~SV_AFMT_DMAC_MSK;
-v |= SV_AFMT_DMAC(ch->fmt);
-sv_indirect_set(sc, SV_REG_FORMAT, v);
-
-/* Program DMA */
-count = sndbuf_getsize(ch->buffer) / 2; /* DMAC uses words */
-sv_dma_set_config(sc->dmac_st, sc->dmac_sh,
-sndbuf_getbufaddr(ch->buffer),
-count - 1,
-SV_DMA_MODE_AUTO | SV_DMA_MODE_RD);
-count = count / SV_INTR_PER_BUFFER - 1;
-sv_indirect_set(sc, SV_REG_DMAC_COUNT_HI, count >> 8);
-sv_indirect_set(sc, SV_REG_DMAC_COUNT_LO, count & 0xff);
-
-/* Enable DMA */
-enable = sv_indirect_get(sc, SV_REG_ENABLE) | SV_RECORD_ENABLE;
-sv_indirect_set(sc, SV_REG_ENABLE, enable);
-ch->dma_active = 1;
-break;
-case PCMTRIG_ABORT:
-enable = sv_indirect_get(sc, SV_REG_ENABLE) & ~SV_RECORD_ENABLE;
-sv_indirect_set(sc, SV_REG_ENABLE, enable);
-ch->dma_active = 0;
-break;
-}
+ struct sc_chinfo *ch = data;
+ struct sc_info *sc = ch->parent;
+ u_int32_t count, enable;
+ u_int8_t v;
+
+ switch(go) {
+ case PCMTRIG_START:
+ /* Set speed */
+ sv_set_recspeed(sc, ch->spd);
+
+ /* Set format */
+ v = sv_indirect_get(sc, SV_REG_FORMAT) & ~SV_AFMT_DMAC_MSK;
+ v |= SV_AFMT_DMAC(ch->fmt);
+ sv_indirect_set(sc, SV_REG_FORMAT, v);
+
+ /* Program DMA */
+ count = sndbuf_getsize(ch->buffer) / 2; /* DMAC uses words */
+ sv_dma_set_config(sc->dmac_st, sc->dmac_sh,
+ sndbuf_getbufaddr(ch->buffer),
+ count - 1,
+ SV_DMA_MODE_AUTO | SV_DMA_MODE_RD);
+ count = count / SV_INTR_PER_BUFFER - 1;
+ sv_indirect_set(sc, SV_REG_DMAC_COUNT_HI, count >> 8);
+ sv_indirect_set(sc, SV_REG_DMAC_COUNT_LO, count & 0xff);
+
+ /* Enable DMA */
+ enable = sv_indirect_get(sc, SV_REG_ENABLE) | SV_RECORD_ENABLE;
+ sv_indirect_set(sc, SV_REG_ENABLE, enable);
+ ch->dma_active = 1;
+ break;
+ case PCMTRIG_STOP:
+ case PCMTRIG_ABORT:
+ enable = sv_indirect_get(sc, SV_REG_ENABLE) & ~SV_RECORD_ENABLE;
+ sv_indirect_set(sc, SV_REG_ENABLE, enable);
+ ch->dma_active = 0;
+ break;
+ }
-return 0;
+ return 0;
}
static int
svrchan_getptr(kobj_t obj, void *data)
{
-struct sc_chinfo *ch = data;
-struct sc_info *sc = ch->parent;
-u_int32_t sz, remain;
-
-sz = sndbuf_getsize(ch->buffer);
-/* DMAC uses words */
-remain = (sv_dma_get_count(sc->dmac_st, sc->dmac_sh) + 1) * 2;
-return sz - remain;
+ struct sc_chinfo *ch = data;
+ struct sc_info *sc = ch->parent;
+ u_int32_t sz, remain;
+
+ sz = sndbuf_getsize(ch->buffer);
+ /* DMAC uses words */
+ remain = (sv_dma_get_count(sc->dmac_st, sc->dmac_sh) + 1) * 2;
+ return sz - remain;
}
static kobj_method_t svrchan_methods[] = {
-KOBJMETHOD(channel_init, svchan_init),
-KOBJMETHOD(channel_setformat, svchan_setformat),
-KOBJMETHOD(channel_setspeed, svchan_setspeed),
-KOBJMETHOD(channel_setblocksize, svchan_setblocksize),
-KOBJMETHOD(channel_trigger, svrchan_trigger),
-KOBJMETHOD(channel_getptr, svrchan_getptr),
-KOBJMETHOD(channel_getcaps, svchan_getcaps),
-{ 0, 0 }
+ KOBJMETHOD(channel_init, svchan_init),
+ KOBJMETHOD(channel_setformat, svchan_setformat),
+ KOBJMETHOD(channel_setspeed, svchan_setspeed),
+ KOBJMETHOD(channel_setblocksize, svchan_setblocksize),
+ KOBJMETHOD(channel_trigger, svrchan_trigger),
+ KOBJMETHOD(channel_getptr, svrchan_getptr),
+ KOBJMETHOD(channel_getcaps, svchan_getcaps),
+ { 0, 0 }
};
CHANNEL_DECLARE(svrchan);
@@ -377,73 +378,74 @@
static int
svpchan_trigger(kobj_t obj, void *data, int go)
{
-struct sc_chinfo *ch = data;
-struct sc_info *sc = ch->parent;
-u_int32_t count, enable, speed;
-u_int8_t v;
-
-switch(go) {
-case PCMTRIG_START:
-/* Set speed */
-speed = (ch->spd * 65536) / 48000;
-if (speed > 65535)
-speed = 65535;
-sv_indirect_set(sc, SV_REG_PCM_SAMPLING_HI, speed >> 8);
-sv_indirect_set(sc, SV_REG_PCM_SAMPLING_LO, speed & 0xff);
-
-/* Set format */
-v = sv_indirect_get(sc, SV_REG_FORMAT) & ~SV_AFMT_DMAA_MSK;
-v |= SV_AFMT_DMAA(ch->fmt);
-sv_indirect_set(sc, SV_REG_FORMAT, v);
-
-/* Program DMA */
-count = sndbuf_getsize(ch->buffer);
-sv_dma_set_config(sc->dmaa_st, sc->dmaa_sh,
-sndbuf_getbufaddr(ch->buffer),
-count - 1,
-SV_DMA_MODE_AUTO | SV_DMA_MODE_WR);
-count = count / SV_INTR_PER_BUFFER - 1;
-sv_indirect_set(sc, SV_REG_DMAA_COUNT_HI, count >> 8);
-sv_indirect_set(sc, SV_REG_DMAA_COUNT_LO, count & 0xff);
-
-/* Enable DMA */
-enable = sv_indirect_get(sc, SV_REG_ENABLE);
-enable = (enable | SV_PLAY_ENABLE) & ~SV_PLAYBACK_PAUSE;
-sv_indirect_set(sc, SV_REG_ENABLE, enable);
-ch->dma_active = 1;
-break;
-case PCMTRIG_ABORT:
-enable = sv_indirect_get(sc, SV_REG_ENABLE) & ~SV_PLAY_ENABLE;
-sv_indirect_set(sc, SV_REG_ENABLE, enable);
-ch->dma_active = 0;
-break;
-}
+ struct sc_chinfo *ch = data;
+ struct sc_info *sc = ch->parent;
+ u_int32_t count, enable, speed;
+ u_int8_t v;
+
+ switch(go) {
+ case PCMTRIG_START:
+ /* Set speed */
+ speed = (ch->spd * 65536) / 48000;
+ if (speed > 65535)
+ speed = 65535;
+ sv_indirect_set(sc, SV_REG_PCM_SAMPLING_HI, speed >> 8);
+ sv_indirect_set(sc, SV_REG_PCM_SAMPLING_LO, speed & 0xff);
+
+ /* Set format */
+ v = sv_indirect_get(sc, SV_REG_FORMAT) & ~SV_AFMT_DMAA_MSK;
+ v |= SV_AFMT_DMAA(ch->fmt);
+ sv_indirect_set(sc, SV_REG_FORMAT, v);
+
+ /* Program DMA */
+ count = sndbuf_getsize(ch->buffer);
+ sv_dma_set_config(sc->dmaa_st, sc->dmaa_sh,
+ sndbuf_getbufaddr(ch->buffer),
+ count - 1,
+ SV_DMA_MODE_AUTO | SV_DMA_MODE_WR);
+ count = count / SV_INTR_PER_BUFFER - 1;
+ sv_indirect_set(sc, SV_REG_DMAA_COUNT_HI, count >> 8);
+ sv_indirect_set(sc, SV_REG_DMAA_COUNT_LO, count & 0xff);
+
+ /* Enable DMA */
+ enable = sv_indirect_get(sc, SV_REG_ENABLE);
+ enable = (enable | SV_PLAY_ENABLE) & ~SV_PLAYBACK_PAUSE;
+ sv_indirect_set(sc, SV_REG_ENABLE, enable);
+ ch->dma_active = 1;
+ break;
+ case PCMTRIG_STOP:
+ case PCMTRIG_ABORT:
+ enable = sv_indirect_get(sc, SV_REG_ENABLE) & ~SV_PLAY_ENABLE;
+ sv_indirect_set(sc, SV_REG_ENABLE, enable);
+ ch->dma_active = 0;
+ break;
+ }
-return 0;
+ return 0;
}
static int
svpchan_getptr(kobj_t obj, void *data)
{
-struct sc_chinfo *ch = data;
-struct sc_info *sc = ch->parent;
-u_int32_t sz, remain;
-
-sz = sndbuf_getsize(ch->buffer);
-/* DMAA uses bytes */
-remain = sv_dma_get_count(sc->dmaa_st, sc->dmaa_sh) + 1;
-return (sz - remain);
+ struct sc_chinfo *ch = data;
+ struct sc_info *sc = ch->parent;
+ u_int32_t sz, remain;
+
+ sz = sndbuf_getsize(ch->buffer);
+ /* DMAA uses bytes */
+ remain = sv_dma_get_count(sc->dmaa_st, sc->dmaa_sh) + 1;
+ return (sz - remain);
}
static kobj_method_t svpchan_methods[] = {
-KOBJMETHOD(channel_init, svchan_init),
-KOBJMETHOD(channel_setformat, svchan_setformat),
-KOBJMETHOD(channel_setspeed, svchan_setspeed),
-KOBJMETHOD(channel_setblocksize, svchan_setblocksize),
-KOBJMETHOD(channel_trigger, svpchan_trigger),
-KOBJMETHOD(channel_getptr, svpchan_getptr),
-KOBJMETHOD(channel_getcaps, svchan_getcaps),
-{ 0, 0 }
+ KOBJMETHOD(channel_init, svchan_init),
+ KOBJMETHOD(channel_setformat, svchan_setformat),
+ KOBJMETHOD(channel_setspeed, svchan_setspeed),
+ KOBJMETHOD(channel_setblocksize, svchan_setblocksize),
+ KOBJMETHOD(channel_trigger, svpchan_trigger),
+ KOBJMETHOD(channel_getptr, svpchan_getptr),
+ KOBJMETHOD(channel_getcaps, svchan_getcaps),
+ { 0, 0 }
};
CHANNEL_DECLARE(svpchan);
@@ -451,111 +453,111 @@
/* Mixer support */
struct sv_mix_props {
-u_int8_t reg; /* Register */
-u_int8_t stereo:1; /* Supports 2 channels */
-u_int8_t mute:1; /* Supports muting */
-u_int8_t neg:1; /* Negative gain */
-u_int8_t max; /* Max gain */
-u_int8_t iselect; /* Input selector */
+ u_int8_t reg; /* Register */
+ u_int8_t stereo:1; /* Supports 2 channels */
+ u_int8_t mute:1; /* Supports muting */
+ u_int8_t neg:1; /* Negative gain */
+ u_int8_t max; /* Max gain */
+ u_int8_t iselect; /* Input selector */
} static const mt [SOUND_MIXER_NRDEVICES] = {
-[SOUND_MIXER_LINE1] = {SV_REG_AUX1, 1, 1, 1, SV_DEFAULT_MAX, SV_INPUT_AUX1},
-[SOUND_MIXER_CD] = {SV_REG_CD, 1, 1, 1, SV_DEFAULT_MAX, SV_INPUT_CD},
-[SOUND_MIXER_LINE] = {SV_REG_LINE, 1, 1, 1, SV_DEFAULT_MAX, SV_INPUT_LINE},
-[SOUND_MIXER_MIC] = {SV_REG_MIC, 0, 1, 1, SV_MIC_MAX, SV_INPUT_MIC},
-[SOUND_MIXER_SYNTH] = {SV_REG_SYNTH, 0, 1, 1, SV_DEFAULT_MAX, 0},
-[SOUND_MIXER_LINE2] = {SV_REG_AUX2, 1, 1, 1, SV_DEFAULT_MAX, SV_INPUT_AUX2},
-[SOUND_MIXER_VOLUME] = {SV_REG_MIX, 1, 1, 1, SV_DEFAULT_MAX, 0},
-[SOUND_MIXER_PCM] = {SV_REG_PCM, 1, 1, 1, SV_PCM_MAX, 0},
-[SOUND_MIXER_RECLEV] = {SV_REG_ADC_INPUT, 1, 0, 0, SV_ADC_MAX, 0},
+ [SOUND_MIXER_LINE1] = {SV_REG_AUX1, 1, 1, 1, SV_DEFAULT_MAX, SV_INPUT_AUX1},
+ [SOUND_MIXER_CD] = {SV_REG_CD, 1, 1, 1, SV_DEFAULT_MAX, SV_INPUT_CD},
+ [SOUND_MIXER_LINE] = {SV_REG_LINE, 1, 1, 1, SV_DEFAULT_MAX, SV_INPUT_LINE},
+ [SOUND_MIXER_MIC] = {SV_REG_MIC, 0, 1, 1, SV_MIC_MAX, SV_INPUT_MIC},
+ [SOUND_MIXER_SYNTH] = {SV_REG_SYNTH, 0, 1, 1, SV_DEFAULT_MAX, 0},
+ [SOUND_MIXER_LINE2] = {SV_REG_AUX2, 1, 1, 1, SV_DEFAULT_MAX, SV_INPUT_AUX2},
+ [SOUND_MIXER_VOLUME] = {SV_REG_MIX, 1, 1, 1, SV_DEFAULT_MAX, 0},
+ [SOUND_MIXER_PCM] = {SV_REG_PCM, 1, 1, 1, SV_PCM_MAX, 0},
+ [SOUND_MIXER_RECLEV] = {SV_REG_ADC_INPUT, 1, 0, 0, SV_ADC_MAX, 0},
};
static void
sv_channel_gain(struct sc_info *sc, u_int32_t dev, u_int32_t gain, u_int32_t channel)
{
-u_int8_t v;
-int32_t g;
+ u_int8_t v;
+ int32_t g;
-g = mt[dev].max * gain / 100;
-if (mt[dev].neg)
-g = mt[dev].max - g;
-v = sv_indirect_get(sc, mt[dev].reg + channel) & ~mt[dev].max;
-v |= g;
-
-if (mt[dev].mute) {
-if (gain == 0) {
-v |= SV_MUTE;
-} else {
-v &= ~SV_MUTE;
-}
-}
-sv_indirect_set(sc, mt[dev].reg + channel, v);
+ g = mt[dev].max * gain / 100;
+ if (mt[dev].neg)
+ g = mt[dev].max - g;
+ v = sv_indirect_get(sc, mt[dev].reg + channel) & ~mt[dev].max;
+ v |= g;
+
+ if (mt[dev].mute) {
+ if (gain == 0) {
+ v |= SV_MUTE;
+ } else {
+ v &= ~SV_MUTE;
+ }
+ }
+ sv_indirect_set(sc, mt[dev].reg + channel, v);
}
static int
sv_gain(struct sc_info *sc, u_int32_t dev, u_int32_t left, u_int32_t right)
{
-sv_channel_gain(sc, dev, left, 0);
-if (mt[dev].stereo)
-sv_channel_gain(sc, dev, right, 1);
-return 0;
+ sv_channel_gain(sc, dev, left, 0);
+ if (mt[dev].stereo)
+ sv_channel_gain(sc, dev, right, 1);
+ return 0;
}
static void
sv_mix_mute_all(struct sc_info *sc)
{
-int32_t i;
-for (i = 0; i < SOUND_MIXER_NRDEVICES; i++) {
-if (mt[i].reg) sv_gain(sc, i, 0, 0);
-}
+ int32_t i;
+ for (i = 0; i < SOUND_MIXER_NRDEVICES; i++) {
+ if (mt[i].reg) sv_gain(sc, i, 0, 0);
+ }
}
static int
sv_mix_init(struct snd_mixer *m)
{
-u_int32_t i, v;
-
-for(i = v = 0; i < SOUND_MIXER_NRDEVICES; i++) {
-if (mt[i].max) v |= (1 << i);
-}
-mix_setdevs(m, v);
+ u_int32_t i, v;
-for(i = v = 0; i < SOUND_MIXER_NRDEVICES; i++) {
-if (mt[i].iselect) v |= (1 << i);
-}
-mix_setrecdevs(m, v);
+ for(i = v = 0; i < SOUND_MIXER_NRDEVICES; i++) {
+ if (mt[i].max) v |= (1 << i);
+ }
+ mix_setdevs(m, v);
+
+ for(i = v = 0; i < SOUND_MIXER_NRDEVICES; i++) {
+ if (mt[i].iselect) v |= (1 << i);
+ }
+ mix_setrecdevs(m, v);
-return 0;
+ return 0;
}
static int
sv_mix_set(struct snd_mixer *m, u_int32_t dev, u_int32_t left, u_int32_t right)
{
-struct sc_info *sc = mix_getdevinfo(m);
-return sv_gain(sc, dev, left, right);
+ struct sc_info *sc = mix_getdevinfo(m);
+ return sv_gain(sc, dev, left, right);
}
static int
sv_mix_setrecsrc(struct snd_mixer *m, u_int32_t mask)
{
-struct sc_info *sc = mix_getdevinfo(m);
-u_int32_t i, v;
+ struct sc_info *sc = mix_getdevinfo(m);
+ u_int32_t i, v;
-v = sv_indirect_get(sc, SV_REG_ADC_INPUT) & SV_INPUT_GAIN_MASK;
-for(i = 0; i < SOUND_MIXER_NRDEVICES; i++) {
-if ((1 << i) & mask) {
-v |= mt[i].iselect;
-}
-}
-DEB(printf("sv_mix_setrecsrc: mask 0x%08x adc_input 0x%02xn", mask, v));
-sv_indirect_set(sc, SV_REG_ADC_INPUT, v);
-return mask;
+ v = sv_indirect_get(sc, SV_REG_ADC_INPUT) & SV_INPUT_GAIN_MASK;
+ for(i = 0; i < SOUND_MIXER_NRDEVICES; i++) {
+ if ((1 << i) & mask) {
+ v |= mt[i].iselect;
+ }
+ }
+ DEB(printf("sv_mix_setrecsrc: mask 0x%08x adc_input 0x%02x\n", mask, v));
+ sv_indirect_set(sc, SV_REG_ADC_INPUT, v);
+ return mask;
}
static kobj_method_t sv_mixer_methods[] = {
-KOBJMETHOD(mixer_init, sv_mix_init),
-KOBJMETHOD(mixer_set, sv_mix_set),
-KOBJMETHOD(mixer_setrecsrc, sv_mix_setrecsrc),
-{ 0, 0 }
+ KOBJMETHOD(mixer_init, sv_mix_init),
+ KOBJMETHOD(mixer_set, sv_mix_set),
+ KOBJMETHOD(mixer_setrecsrc, sv_mix_setrecsrc),
+ { 0, 0 }
};
MIXER_DECLARE(sv_mixer);
@@ -565,115 +567,115 @@
static void
sv_power(struct sc_info *sc, int state)
{
-u_int8_t v;
+ u_int8_t v;
-switch (state) {
-case 0:
-/* power on */
-v = sv_indirect_get(sc, SV_REG_ANALOG_PWR) &~ SV_ANALOG_OFF;
-v |= SV_ANALOG_OFF_SRS | SV_ANALOG_OFF_SPLL;
-sv_indirect_set(sc, SV_REG_ANALOG_PWR, v);
-v = sv_indirect_get(sc, SV_REG_DIGITAL_PWR) &~ SV_DIGITAL_OFF;
-v |= SV_DIGITAL_OFF_SYN | SV_DIGITAL_OFF_MU | SV_DIGITAL_OFF_GP;
-sv_indirect_set(sc, SV_REG_DIGITAL_PWR, v);
-break;
-default:
-/* power off */
-v = sv_indirect_get(sc, SV_REG_ANALOG_PWR) | SV_ANALOG_OFF;
-sv_indirect_set(sc, SV_REG_ANALOG_PWR, v);
-v = sv_indirect_get(sc, SV_REG_DIGITAL_PWR) | SV_DIGITAL_OFF;
-sv_indirect_set(sc, SV_REG_DIGITAL_PWR, SV_DIGITAL_OFF);
-break;
-}
-DEB(printf("Power state %dn", state));
+ switch (state) {
+ case 0:
+ /* power on */
+ v = sv_indirect_get(sc, SV_REG_ANALOG_PWR) &~ SV_ANALOG_OFF;
+ v |= SV_ANALOG_OFF_SRS | SV_ANALOG_OFF_SPLL;
+ sv_indirect_set(sc, SV_REG_ANALOG_PWR, v);
+ v = sv_indirect_get(sc, SV_REG_DIGITAL_PWR) &~ SV_DIGITAL_OFF;
+ v |= SV_DIGITAL_OFF_SYN | SV_DIGITAL_OFF_MU | SV_DIGITAL_OFF_GP;
+ sv_indirect_set(sc, SV_REG_DIGITAL_PWR, v);
+ break;
+ default:
+ /* power off */
+ v = sv_indirect_get(sc, SV_REG_ANALOG_PWR) | SV_ANALOG_OFF;
+ sv_indirect_set(sc, SV_REG_ANALOG_PWR, v);
+ v = sv_indirect_get(sc, SV_REG_DIGITAL_PWR) | SV_DIGITAL_OFF;
+ sv_indirect_set(sc, SV_REG_DIGITAL_PWR, SV_DIGITAL_OFF);
+ break;
+ }
+ DEB(printf("Power state %d\n", state));
}
static int
sv_init(struct sc_info *sc)
{
-u_int8_t v;
+ u_int8_t v;
-/* Effect reset */
-v = sv_direct_get(sc, SV_CM_CONTROL) & ~SV_CM_CONTROL_ENHANCED;
-v |= SV_CM_CONTROL_RESET;
-sv_direct_set(sc, SV_CM_CONTROL, v);
-DELAY(50);
-
-v = sv_direct_get(sc, SV_CM_CONTROL) & ~SV_CM_CONTROL_RESET;
-sv_direct_set(sc, SV_CM_CONTROL, v);
-DELAY(50);
-
-/* Set in enhanced mode */
-v = sv_direct_get(sc, SV_CM_CONTROL);
-v |= SV_CM_CONTROL_ENHANCED;
-sv_direct_set(sc, SV_CM_CONTROL, v);
-
-/* Enable interrupts (UDM and MIDM are superfluous) */
-v = sv_direct_get(sc, SV_CM_IMR);
-v &= ~(SV_CM_IMR_AMSK | SV_CM_IMR_CMSK | SV_CM_IMR_SMSK);
-sv_direct_set(sc, SV_CM_IMR, v);
-
-/* Select ADC PLL for ADC clock */
-v = sv_indirect_get(sc, SV_REG_CLOCK_SOURCE) & ~SV_CLOCK_ALTERNATE;
-sv_indirect_set(sc, SV_REG_CLOCK_SOURCE, v);
-
-/* Disable loopback - binds ADC and DAC rates */
-v = sv_indirect_get(sc, SV_REG_LOOPBACK) & ~SV_LOOPBACK_ENABLE;
-sv_indirect_set(sc, SV_REG_LOOPBACK, v);
-
-/* Disable SRS */
-v = sv_indirect_get(sc, SV_REG_SRS_SPACE) | SV_SRS_DISABLED;
-sv_indirect_set(sc, SV_REG_SRS_SPACE, v);
+ /* Effect reset */
+ v = sv_direct_get(sc, SV_CM_CONTROL) & ~SV_CM_CONTROL_ENHANCED;
+ v |= SV_CM_CONTROL_RESET;
+ sv_direct_set(sc, SV_CM_CONTROL, v);
+ DELAY(50);
+
+ v = sv_direct_get(sc, SV_CM_CONTROL) & ~SV_CM_CONTROL_RESET;
+ sv_direct_set(sc, SV_CM_CONTROL, v);
+ DELAY(50);
+
+ /* Set in enhanced mode */
+ v = sv_direct_get(sc, SV_CM_CONTROL);
+ v |= SV_CM_CONTROL_ENHANCED;
+ sv_direct_set(sc, SV_CM_CONTROL, v);
+
+ /* Enable interrupts (UDM and MIDM are superfluous) */
+ v = sv_direct_get(sc, SV_CM_IMR);
+ v &= ~(SV_CM_IMR_AMSK | SV_CM_IMR_CMSK | SV_CM_IMR_SMSK);
+ sv_direct_set(sc, SV_CM_IMR, v);
+
+ /* Select ADC PLL for ADC clock */
+ v = sv_indirect_get(sc, SV_REG_CLOCK_SOURCE) & ~SV_CLOCK_ALTERNATE;
+ sv_indirect_set(sc, SV_REG_CLOCK_SOURCE, v);
+
+ /* Disable loopback - binds ADC and DAC rates */
+ v = sv_indirect_get(sc, SV_REG_LOOPBACK) & ~SV_LOOPBACK_ENABLE;
+ sv_indirect_set(sc, SV_REG_LOOPBACK, v);
+
+ /* Disable SRS */
+ v = sv_indirect_get(sc, SV_REG_SRS_SPACE) | SV_SRS_DISABLED;
+ sv_indirect_set(sc, SV_REG_SRS_SPACE, v);
-/* Get revision */
-sc->rev = sv_indirect_get(sc, SV_REG_REVISION);
+ /* Get revision */
+ sc->rev = sv_indirect_get(sc, SV_REG_REVISION);
-return 0;
+ return 0;
}
static int
sv_suspend(device_t dev)
{
-struct sc_info *sc = pcm_getdevinfo(dev);
+ struct sc_info *sc = pcm_getdevinfo(dev);
-sc->rch.dma_was_active = sc->rch.dma_active;
-svrchan_trigger(NULL, &sc->rch, PCMTRIG_ABORT);
+ sc->rch.dma_was_active = sc->rch.dma_active;
+ svrchan_trigger(NULL, &sc->rch, PCMTRIG_ABORT);
-sc->pch.dma_was_active = sc->pch.dma_active;
-svrchan_trigger(NULL, &sc->pch, PCMTRIG_ABORT);
+ sc->pch.dma_was_active = sc->pch.dma_active;
+ svrchan_trigger(NULL, &sc->pch, PCMTRIG_ABORT);
-sv_mix_mute_all(sc);
-sv_power(sc, 3);
+ sv_mix_mute_all(sc);
+ sv_power(sc, 3);
-return 0;
+ return 0;
}
static int
sv_resume(device_t dev)
{
-struct sc_info *sc = pcm_getdevinfo(dev);
-
-sv_mix_mute_all(sc);
-sv_power(sc, 0);
-if (sv_init(sc) == -1) {
-device_printf(dev, "unable to reinitialize the cardn");
-return ENXIO;
-}
+ struct sc_info *sc = pcm_getdevinfo(dev);
-if (mixer_reinit(dev) == -1) {
-device_printf(dev, "unable to reinitialize the mixern");
-return ENXIO;
-}
-
-if (sc->rch.dma_was_active) {
-svrchan_trigger(0, &sc->rch, PCMTRIG_START);
-}
+ sv_mix_mute_all(sc);
+ sv_power(sc, 0);
+ if (sv_init(sc) == -1) {
+ device_printf(dev, "unable to reinitialize the card\n");
+ return ENXIO;
+ }
+
+ if (mixer_reinit(dev) == -1) {
+ device_printf(dev, "unable to reinitialize the mixer\n");
+ return ENXIO;
+ }
+
+ if (sc->rch.dma_was_active) {
+ svrchan_trigger(0, &sc->rch, PCMTRIG_START);
+ }
+
+ if (sc->pch.dma_was_active) {
+ svpchan_trigger(0, &sc->pch, PCMTRIG_START);
+ }
-if (sc->pch.dma_was_active) {
-svpchan_trigger(0, &sc->pch, PCMTRIG_START);
-}
-
-return 0;
+ return 0;
}
/* ------------------------------------------------------------------------- */
@@ -682,261 +684,258 @@
static void
sv_intr(void *data)
{
-struct sc_info *sc = data;
-u_int8_t status;
+ struct sc_info *sc = data;
+ u_int8_t status;
-status = sv_direct_get(sc, SV_CM_STATUS);
-if (status & SV_CM_STATUS_AINT)
-chn_intr(sc->pch.channel);
+ status = sv_direct_get(sc, SV_CM_STATUS);
+ if (status & SV_CM_STATUS_AINT)
+ chn_intr(sc->pch.channel);
-if (status & SV_CM_STATUS_CINT)
-chn_intr(sc->rch.channel);
+ if (status & SV_CM_STATUS_CINT)
+ chn_intr(sc->rch.channel);
-status &= ~(SV_CM_STATUS_AINT|SV_CM_STATUS_CINT);
-DEB(if (status) printf("intr 0x%02x ?n", status));
+ status &= ~(SV_CM_STATUS_AINT|SV_CM_STATUS_CINT);
+ DEB(if (status) printf("intr 0x%02x ?\n", status));
-return;
+ return;
}
static int
sv_probe(device_t dev)
{
-switch(pci_get_devid(dev)) {
-case SV_PCI_ID:
-device_set_desc(dev, "S3 Sonicvibes");
-return BUS_PROBE_DEFAULT;
-default:
-return ENXIO;
-}
+ switch(pci_get_devid(dev)) {
+ case SV_PCI_ID:
+ device_set_desc(dev, "S3 Sonicvibes");
+ return BUS_PROBE_DEFAULT;
+ default:
+ return ENXIO;
+ }
}
static int
sv_attach(device_t dev) {
-struct sc_info *sc;
-u_int32_t data;
-char status[SND_STATUSLEN];
-u_long midi_start, games_start, count, sdmaa, sdmac, ml, mu;
-
-sc = malloc(sizeof(struct sc_info), M_DEVBUF, M_NOWAIT | M_ZERO);
-if (sc == NULL) {
-device_printf(dev, "cannot allocate softc");
-return ENXIO;
-}
-sc->dev = dev;
-
-data = pci_read_config(dev, PCIR_COMMAND, 2);
-data |= (PCIM_CMD_PORTEN|PCIM_CMD_BUSMASTEREN);
-pci_write_config(dev, PCIR_COMMAND, data, 2);
-data = pci_read_config(dev, PCIR_COMMAND, 2);
+ struct sc_info *sc;
+ u_int32_t data;
+ char status[SND_STATUSLEN];
+ u_long midi_start, games_start, count, sdmaa, sdmac, ml, mu;
+
+ sc = malloc(sizeof(*sc), M_DEVBUF, M_WAITOK | M_ZERO);
+ sc->dev = dev;
+
+ data = pci_read_config(dev, PCIR_COMMAND, 2);
+ data |= (PCIM_CMD_PORTEN|PCIM_CMD_BUSMASTEREN);
+ pci_write_config(dev, PCIR_COMMAND, data, 2);
+ data = pci_read_config(dev, PCIR_COMMAND, 2);
#if __FreeBSD_version > 500000
-if (pci_get_powerstate(dev) != PCI_POWERSTATE_D0) {
-device_printf(dev, "chip is in D%d power mode "
-"-- setting to D0n", pci_get_powerstate(dev));
-pci_set_powerstate(dev, PCI_POWERSTATE_D0);
-}
+ if (pci_get_powerstate(dev) != PCI_POWERSTATE_D0) {
+ device_printf(dev, "chip is in D%d power mode "
+ "-- setting to D0\n", pci_get_powerstate(dev));
+ pci_set_powerstate(dev, PCI_POWERSTATE_D0);
+ }
#endif
-sc->enh_rid = SV_PCI_ENHANCED;
-sc->enh_type = SYS_RES_IOPORT;
-sc->enh_reg = bus_alloc_resource(dev, sc->enh_type,
-&sc->enh_rid, 0, ~0,
-SV_PCI_ENHANCED_SIZE, RF_ACTIVE);
-if (sc->enh_reg == NULL) {
-device_printf(dev, "sv_attach: cannot allocate enhn");
-return ENXIO;
-}
-sc->enh_st = rman_get_bustag(sc->enh_reg);
-sc->enh_sh = rman_get_bushandle(sc->enh_reg);
-
-data = pci_read_config(dev, SV_PCI_DMAA, 4);
-DEB(printf("sv_attach: initial dmaa 0x%08xn", data));
-data = pci_read_config(dev, SV_PCI_DMAC, 4);
-DEB(printf("sv_attach: initial dmac 0x%08xn", data));
-
-/* Initialize DMA_A and DMA_C */
-pci_write_config(dev, SV_PCI_DMAA, SV_PCI_DMA_EXTENDED, 4);
-pci_write_config(dev, SV_PCI_DMAC, 0, 4);
-
-/* Register IRQ handler */
-sc->irqid = 0;
-sc->irq = bus_alloc_resource(dev, SYS_RES_IRQ, &sc->irqid,
-0, ~0, 1, RF_ACTIVE | RF_SHAREABLE);
-if (!sc->irq ||
-bus_setup_intr(dev, sc->irq, INTR_TYPE_AV, sv_intr, sc, &sc->ih)) {
-device_printf(dev, "sv_attach: Unable to map interruptn");
-goto fail;
-}
-
-sc->bufsz = pcm_getbuffersize(dev, 4096, SV_DEFAULT_BUFSZ, 65536);
-if (bus_dma_tag_create(/*parent*/NULL, /*alignment*/2, /*boundary*/0,
-/*lowaddr*/BUS_SPACE_MAXADDR_24BIT,
-/*highaddr*/BUS_SPACE_MAXADDR,
-/*filter*/NULL, /*filterarg*/NULL,
-/*maxsize*/sc->bufsz, /*nsegments*/1,
-/*maxsegz*/0x3ffff, /*flags*/0,
-/*lockfunc*/busdma_lock_mutex,
-/*lockarg*/&Giant, &sc->parent_dmat) != 0) {
-device_printf(dev, "sv_attach: Unable to create dma tagn");
-goto fail;
-}
-
-/* Power up and initialize */
-sv_mix_mute_all(sc);
-sv_power(sc, 0);
-sv_init(sc);
-
-if (mixer_init(dev, &sv_mixer_class, sc) != 0) {
-device_printf(dev, "sv_attach: Mixer failed to initializen");
-goto fail;
-}
-
-/* XXX This is a hack, and it's ugly. Okay, the deal is this
-* card has two more io regions that available for automatic
-* configuration by the pci code. These need to be allocated
-* to used as control registers for the DMA engines.
-* Unfortunately FBSD has no bus_space_foo() functions so we
-* have to grab port space in region of existing resources. Go
-* for space between midi and game ports.
-*/
-bus_get_resource(dev, SYS_RES_IOPORT, SV_PCI_MIDI, &midi_start, &count);
-bus_get_resource(dev, SYS_RES_IOPORT, SV_PCI_GAMES, &games_start, &count);
-
-if (games_start < midi_start) {
-ml = games_start;
-mu = midi_start;
-} else {
-ml = midi_start;
-mu = games_start;
-}
-/* Check assumptions about space availability and
-alignment. How driver loaded can determine whether
-games_start > midi_start or vice versa */
-if ((mu - ml >= 0x800) ||
-((mu - ml) % 0x200)) {
-device_printf(dev, "sv_attach: resource assumptions not met "
-"(midi 0x%08lx, games 0x%08lx)n",
-midi_start, games_start);
-goto fail;
-}
-
-sdmaa = ml + 0x40;
-sdmac = sdmaa + 0x40;
-
-/* Add resources to list of pci resources for this device - from here on
-* they look like normal pci resources. */
-bus_set_resource(dev, SYS_RES_IOPORT, SV_PCI_DMAA, sdmaa, SV_PCI_DMAA_SIZE);
-bus_set_resource(dev, SYS_RES_IOPORT, SV_PCI_DMAC, sdmac, SV_PCI_DMAC_SIZE);
-
-/* Cache resource short-cuts for dma_a */
-sc->dmaa_rid = SV_PCI_DMAA;
-sc->dmaa_type = SYS_RES_IOPORT;
-sc->dmaa_reg = bus_alloc_resource(dev, sc->dmaa_type,
-&sc->dmaa_rid, 0, ~0,
-SV_PCI_ENHANCED_SIZE, RF_ACTIVE);
-if (sc->dmaa_reg == NULL) {
-device_printf(dev, "sv_attach: cannot allocate dmaan");
-goto fail;
-}
-sc->dmaa_st = rman_get_bustag(sc->dmaa_reg);
-sc->dmaa_sh = rman_get_bushandle(sc->dmaa_reg);
-
-/* Poke port into dma_a configuration, nb bit flags to enable dma */
-data = pci_read_config(dev, SV_PCI_DMAA, 4) | SV_PCI_DMA_ENABLE | SV_PCI_DMA_EXTENDED;
-data = ((u_int32_t)sdmaa & 0xfffffff0) | (data & 0x0f);
-pci_write_config(dev, SV_PCI_DMAA, data, 4);
-DEB(printf("dmaa: 0x%x 0x%xn", data, pci_read_config(dev, SV_PCI_DMAA, 4)));
-
-/* Cache resource short-cuts for dma_c */
-sc->dmac_rid = SV_PCI_DMAC;
-sc->dmac_type = SYS_RES_IOPORT;
-sc->dmac_reg = bus_alloc_resource(dev, sc->dmac_type,
-&sc->dmac_rid, 0, ~0,
-SV_PCI_ENHANCED_SIZE, RF_ACTIVE);
-if (sc->dmac_reg == NULL) {
-device_printf(dev, "sv_attach: cannot allocate dmacn");
-goto fail;
-}
-sc->dmac_st = rman_get_bustag(sc->dmac_reg);
-sc->dmac_sh = rman_get_bushandle(sc->dmac_reg);
-
-/* Poke port into dma_c configuration, nb bit flags to enable dma */
-data = pci_read_config(dev, SV_PCI_DMAC, 4) | SV_PCI_DMA_ENABLE | SV_PCI_DMA_EXTENDED;
-data = ((u_int32_t)sdmac & 0xfffffff0) | (data & 0x0f);
-pci_write_config(dev, SV_PCI_DMAC, data, 4);
-DEB(printf("dmac: 0x%x 0x%xn", data, pci_read_config(dev, SV_PCI_DMAC, 4)));
-
-if (bootverbose)
-printf("Sonicvibes: revision %d.n", sc->rev);
-
-if (pcm_register(dev, sc, 1, 1)) {
-device_printf(dev, "sv_attach: pcm_register failn");
-goto fail;
-}
-
-pcm_addchan(dev, PCMDIR_PLAY, &svpchan_class, sc);
-pcm_addchan(dev, PCMDIR_REC, &svrchan_class, sc);
-
-snprintf(status, SND_STATUSLEN, "at io 0x%lx irq %ld %s",
-rman_get_start(sc->enh_reg), rman_get_start(sc->irq),PCM_KLDSTRING(snd_vibes));
-pcm_setstatus(dev, status);
-
-DEB(printf("sv_attach: succeededn"));
-
-return 0;
-
-fail:
-if (sc->parent_dmat)
-bus_dma_tag_destroy(sc->parent_dmat);
-if (sc->ih)
-bus_teardown_intr(dev, sc->irq, sc->ih);
-if (sc->irq)
-bus_release_resource(dev, SYS_RES_IRQ, sc->irqid, sc->irq);
-if (sc->enh_reg)
-bus_release_resource(dev, sc->enh_type, sc->enh_rid, sc->enh_reg);
-if (sc->dmaa_reg)
-bus_release_resource(dev, sc->dmaa_type, sc->dmaa_rid, sc->dmaa_reg);
-if (sc->dmac_reg)
-bus_release_resource(dev, sc->dmac_type, sc->dmac_rid, sc->dmac_reg);
-return ENXIO;
+ sc->enh_rid = SV_PCI_ENHANCED;
+ sc->enh_type = SYS_RES_IOPORT;
+ sc->enh_reg = bus_alloc_resource(dev, sc->enh_type,
+ &sc->enh_rid, 0, ~0,
+ SV_PCI_ENHANCED_SIZE, RF_ACTIVE);
+ if (sc->enh_reg == NULL) {
+ device_printf(dev, "sv_attach: cannot allocate enh\n");
+ return ENXIO;
+ }
+ sc->enh_st = rman_get_bustag(sc->enh_reg);
+ sc->enh_sh = rman_get_bushandle(sc->enh_reg);
+
+ data = pci_read_config(dev, SV_PCI_DMAA, 4);
+ DEB(printf("sv_attach: initial dmaa 0x%08x\n", data));
+ data = pci_read_config(dev, SV_PCI_DMAC, 4);
+ DEB(printf("sv_attach: initial dmac 0x%08x\n", data));
+
+ /* Initialize DMA_A and DMA_C */
+ pci_write_config(dev, SV_PCI_DMAA, SV_PCI_DMA_EXTENDED, 4);
+ pci_write_config(dev, SV_PCI_DMAC, 0, 4);
+
+ /* Register IRQ handler */
+ sc->irqid = 0;
+ sc->irq = bus_alloc_resource(dev, SYS_RES_IRQ, &sc->irqid,
+ 0, ~0, 1, RF_ACTIVE | RF_SHAREABLE);
+ if (!sc->irq ||
+ snd_setup_intr(dev, sc->irq, 0, sv_intr, sc, &sc->ih)) {
+ device_printf(dev, "sv_attach: Unable to map interrupt\n");
+ goto fail;
+ }
+
+ sc->bufsz = pcm_getbuffersize(dev, 4096, SV_DEFAULT_BUFSZ, 65536);
+ if (bus_dma_tag_create(/*parent*/bus_get_dma_tag(dev), /*alignment*/2,
+ /*boundary*/0,
+ /*lowaddr*/BUS_SPACE_MAXADDR_24BIT,
+ /*highaddr*/BUS_SPACE_MAXADDR,
+ /*filter*/NULL, /*filterarg*/NULL,
+ /*maxsize*/sc->bufsz, /*nsegments*/1,
+ /*maxsegz*/0x3ffff, /*flags*/0,
+ /*lockfunc*/busdma_lock_mutex,
+ /*lockarg*/&Giant, &sc->parent_dmat) != 0) {
+ device_printf(dev, "sv_attach: Unable to create dma tag\n");
+ goto fail;
+ }
+
+ /* Power up and initialize */
+ sv_mix_mute_all(sc);
+ sv_power(sc, 0);
+ sv_init(sc);
+
+ if (mixer_init(dev, &sv_mixer_class, sc) != 0) {
+ device_printf(dev, "sv_attach: Mixer failed to initialize\n");
+ goto fail;
+ }
+
+ /* XXX This is a hack, and it's ugly. Okay, the deal is this
+ * card has two more io regions that available for automatic
+ * configuration by the pci code. These need to be allocated
+ * to used as control registers for the DMA engines.
+ * Unfortunately FBSD has no bus_space_foo() functions so we
+ * have to grab port space in region of existing resources. Go
+ * for space between midi and game ports.
+ */
+ bus_get_resource(dev, SYS_RES_IOPORT, SV_PCI_MIDI, &midi_start, &count);
+ bus_get_resource(dev, SYS_RES_IOPORT, SV_PCI_GAMES, &games_start, &count);
+
+ if (games_start < midi_start) {
+ ml = games_start;
+ mu = midi_start;
+ } else {
+ ml = midi_start;
+ mu = games_start;
+ }
+ /* Check assumptions about space availability and
+ alignment. How driver loaded can determine whether
+ games_start > midi_start or vice versa */
+ if ((mu - ml >= 0x800) ||
+ ((mu - ml) % 0x200)) {
+ device_printf(dev, "sv_attach: resource assumptions not met "
+ "(midi 0x%08lx, games 0x%08lx)\n",
+ midi_start, games_start);
+ goto fail;
+ }
+
+ sdmaa = ml + 0x40;
+ sdmac = sdmaa + 0x40;
+
+ /* Add resources to list of pci resources for this device - from here on
+ * they look like normal pci resources. */
+ bus_set_resource(dev, SYS_RES_IOPORT, SV_PCI_DMAA, sdmaa, SV_PCI_DMAA_SIZE);
+ bus_set_resource(dev, SYS_RES_IOPORT, SV_PCI_DMAC, sdmac, SV_PCI_DMAC_SIZE);
+
+ /* Cache resource short-cuts for dma_a */
+ sc->dmaa_rid = SV_PCI_DMAA;
+ sc->dmaa_type = SYS_RES_IOPORT;
+ sc->dmaa_reg = bus_alloc_resource(dev, sc->dmaa_type,
+ &sc->dmaa_rid, 0, ~0,
+ SV_PCI_ENHANCED_SIZE, RF_ACTIVE);
+ if (sc->dmaa_reg == NULL) {
+ device_printf(dev, "sv_attach: cannot allocate dmaa\n");
+ goto fail;
+ }
+ sc->dmaa_st = rman_get_bustag(sc->dmaa_reg);
+ sc->dmaa_sh = rman_get_bushandle(sc->dmaa_reg);
+
+ /* Poke port into dma_a configuration, nb bit flags to enable dma */
+ data = pci_read_config(dev, SV_PCI_DMAA, 4) | SV_PCI_DMA_ENABLE | SV_PCI_DMA_EXTENDED;
+ data = ((u_int32_t)sdmaa & 0xfffffff0) | (data & 0x0f);
+ pci_write_config(dev, SV_PCI_DMAA, data, 4);
+ DEB(printf("dmaa: 0x%x 0x%x\n", data, pci_read_config(dev, SV_PCI_DMAA, 4)));
+
+ /* Cache resource short-cuts for dma_c */
+ sc->dmac_rid = SV_PCI_DMAC;
+ sc->dmac_type = SYS_RES_IOPORT;
+ sc->dmac_reg = bus_alloc_resource(dev, sc->dmac_type,
+ &sc->dmac_rid, 0, ~0,
+ SV_PCI_ENHANCED_SIZE, RF_ACTIVE);
+ if (sc->dmac_reg == NULL) {
+ device_printf(dev, "sv_attach: cannot allocate dmac\n");
+ goto fail;
+ }
+ sc->dmac_st = rman_get_bustag(sc->dmac_reg);
+ sc->dmac_sh = rman_get_bushandle(sc->dmac_reg);
+
+ /* Poke port into dma_c configuration, nb bit flags to enable dma */
+ data = pci_read_config(dev, SV_PCI_DMAC, 4) | SV_PCI_DMA_ENABLE | SV_PCI_DMA_EXTENDED;
+ data = ((u_int32_t)sdmac & 0xfffffff0) | (data & 0x0f);
+ pci_write_config(dev, SV_PCI_DMAC, data, 4);
+ DEB(printf("dmac: 0x%x 0x%x\n", data, pci_read_config(dev, SV_PCI_DMAC, 4)));
+
+ if (bootverbose)
+ printf("Sonicvibes: revision %d.\n", sc->rev);
+
+ if (pcm_register(dev, sc, 1, 1)) {
+ device_printf(dev, "sv_attach: pcm_register fail\n");
+ goto fail;
+ }
+
+ pcm_addchan(dev, PCMDIR_PLAY, &svpchan_class, sc);
+ pcm_addchan(dev, PCMDIR_REC, &svrchan_class, sc);
+
+ snprintf(status, SND_STATUSLEN, "at io 0x%lx irq %ld %s",
+ rman_get_start(sc->enh_reg), rman_get_start(sc->irq),PCM_KLDSTRING(snd_vibes));
+ pcm_setstatus(dev, status);
+
+ DEB(printf("sv_attach: succeeded\n"));
+
+ return 0;
+
+ fail:
+ if (sc->parent_dmat)
+ bus_dma_tag_destroy(sc->parent_dmat);
+ if (sc->ih)
+ bus_teardown_intr(dev, sc->irq, sc->ih);
+ if (sc->irq)
+ bus_release_resource(dev, SYS_RES_IRQ, sc->irqid, sc->irq);
+ if (sc->enh_reg)
+ bus_release_resource(dev, sc->enh_type, sc->enh_rid, sc->enh_reg);
+ if (sc->dmaa_reg)
+ bus_release_resource(dev, sc->dmaa_type, sc->dmaa_rid, sc->dmaa_reg);
+ if (sc->dmac_reg)
+ bus_release_resource(dev, sc->dmac_type, sc->dmac_rid, sc->dmac_reg);
+ return ENXIO;
}
static int
sv_detach(device_t dev) {
-struct sc_info *sc;
-int r;
+ struct sc_info *sc;
+ int r;
-r = pcm_unregister(dev);
-if (r) return r;
+ r = pcm_unregister(dev);
+ if (r) return r;
-sc = pcm_getdevinfo(dev);
-sv_mix_mute_all(sc);
-sv_power(sc, 3);
-
-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);
-bus_release_resource(dev, sc->enh_type, sc->enh_rid, sc->enh_reg);
-bus_release_resource(dev, sc->dmaa_type, sc->dmaa_rid, sc->dmaa_reg);
-bus_release_resource(dev, sc->dmac_type, sc->dmac_rid, sc->dmac_reg);
+ sc = pcm_getdevinfo(dev);
+ sv_mix_mute_all(sc);
+ sv_power(sc, 3);
+
+ 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);
+ bus_release_resource(dev, sc->enh_type, sc->enh_rid, sc->enh_reg);
+ bus_release_resource(dev, sc->dmaa_type, sc->dmaa_rid, sc->dmaa_reg);
+ bus_release_resource(dev, sc->dmac_type, sc->dmac_rid, sc->dmac_reg);
-free(sc, M_DEVBUF);
+ free(sc, M_DEVBUF);
-return 0;
+ return 0;
}
static device_method_t sc_methods[] = {
-DEVMETHOD(device_probe, sv_probe),
-DEVMETHOD(device_attach, sv_attach),
-DEVMETHOD(device_detach, sv_detach),
-DEVMETHOD(device_resume, sv_resume),
-DEVMETHOD(device_suspend, sv_suspend),
-{ 0, 0 }
+ DEVMETHOD(device_probe, sv_probe),
+ DEVMETHOD(device_attach, sv_attach),
+ DEVMETHOD(device_detach, sv_detach),
+ DEVMETHOD(device_resume, sv_resume),
+ DEVMETHOD(device_suspend, sv_suspend),
+ { 0, 0 }
};
static driver_t sonicvibes_driver = {
-"pcm",
-sc_methods,
-PCM_SOFTC_SIZE
+ "pcm",
+ sc_methods,
+ PCM_SOFTC_SIZE
};
DRIVER_MODULE(snd_vibes, pci, sonicvibes_driver, pcm_devclass, 0, 0);
Index: via82c686.c
===================================================================
RCS file: /home/cvs/src/sys/dev/sound/pci/via82c686.c,v
retrieving revision 1.2
retrieving revision 1.3
diff -L sys/dev/sound/pci/via82c686.c -L sys/dev/sound/pci/via82c686.c -u -r1.2 -r1.3
--- sys/dev/sound/pci/via82c686.c
+++ sys/dev/sound/pci/via82c686.c
@@ -1,28 +1,28 @@
/*-
-* Copyright (c) 2000 David Jones <dej at ox.org>
-* All rights reserved.
-*
-* Redistribution and use in source and binary forms, with or without
-* modification, are permitted provided that the following conditions
-* are met:
-* 1. Redistributions of source code must retain the above copyright
-* notice, this list of conditions and the following disclaimer.
-* 2. Redistributions in binary form must reproduce the above copyright
-* notice, this list of conditions and the following disclaimer in the
-* documentation and/or other materials provided with the distribution.
-*
-* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
-* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
-* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
-* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
-* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
-* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
-* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
-* SUCH DAMAGE.
-*/
+ * Copyright (c) 2000 David Jones <dej at ox.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
#include <dev/sound/pcm/sound.h>
#include <dev/sound/pcm/ac97.h>
@@ -33,7 +33,7 @@
#include <dev/sound/pci/via82c686.h>
-SND_DECLARE_FILE("$MidnightBSD$");
+SND_DECLARE_FILE("$FreeBSD: src/sys/dev/sound/pci/via82c686.c,v 1.43 2007/06/17 06:10:42 ariff Exp $");
#define VIA_PCI_ID 0x30581106
#define NSEGS 4 /* Number of segments in SGD table */
@@ -48,8 +48,8 @@
/* we rely on this struct being packed to 64 bits */
struct via_dma_op {
-u_int32_t ptr;
-u_int32_t flags;
+ u_int32_t ptr;
+ u_int32_t flags;
#define VIA_DMAOP_EOL 0x80000000
#define VIA_DMAOP_FLAG 0x40000000
#define VIA_DMAOP_STOP 0x20000000
@@ -59,42 +59,42 @@
struct via_info;
struct via_chinfo {
-struct via_info *parent;
-struct pcm_channel *channel;
-struct snd_dbuf *buffer;
-struct via_dma_op *sgd_table;
-bus_addr_t sgd_addr;
-int dir, blksz;
-int base, count, mode, ctrl;
+ struct via_info *parent;
+ struct pcm_channel *channel;
+ struct snd_dbuf *buffer;
+ struct via_dma_op *sgd_table;
+ bus_addr_t sgd_addr;
+ int dir, blksz;
+ int base, count, mode, ctrl;
};
struct via_info {
-bus_space_tag_t st;
-bus_space_handle_t sh;
-bus_dma_tag_t parent_dmat;
-bus_dma_tag_t sgd_dmat;
-bus_dmamap_t sgd_dmamap;
-bus_addr_t sgd_addr;
-
-struct resource *reg, *irq;
-int regid, irqid;
-void *ih;
-struct ac97_info *codec;
-
-unsigned int bufsz;
-
-struct via_chinfo pch, rch;
-struct via_dma_op *sgd_table;
-u_int16_t codec_caps;
-struct mtx *lock;
+ bus_space_tag_t st;
+ bus_space_handle_t sh;
+ bus_dma_tag_t parent_dmat;
+ bus_dma_tag_t sgd_dmat;
+ bus_dmamap_t sgd_dmamap;
+ bus_addr_t sgd_addr;
+
+ struct resource *reg, *irq;
+ int regid, irqid;
+ void *ih;
+ struct ac97_info *codec;
+
+ unsigned int bufsz;
+
+ struct via_chinfo pch, rch;
+ struct via_dma_op *sgd_table;
+ u_int16_t codec_caps;
+ struct mtx *lock;
};
static u_int32_t via_fmt[] = {
-AFMT_U8,
-AFMT_STEREO | AFMT_U8,
-AFMT_S16_LE,
-AFMT_STEREO | AFMT_S16_LE,
-0
+ AFMT_U8,
+ AFMT_STEREO | AFMT_U8,
+ AFMT_S16_LE,
+ AFMT_STEREO | AFMT_S16_LE,
+ 0
};
static struct pcmchan_caps via_vracaps = {4000, 48000, via_fmt, 0};
static struct pcmchan_caps via_caps = {48000, 48000, via_fmt, 0};
@@ -103,16 +103,16 @@
via_rd(struct via_info *via, int regno, int size)
{
-switch (size) {
-case 1:
-return bus_space_read_1(via->st, via->sh, regno);
-case 2:
-return bus_space_read_2(via->st, via->sh, regno);
-case 4:
-return bus_space_read_4(via->st, via->sh, regno);
-default:
-return 0xFFFFFFFF;
-}
+ switch (size) {
+ case 1:
+ return bus_space_read_1(via->st, via->sh, regno);
+ case 2:
+ return bus_space_read_2(via->st, via->sh, regno);
+ case 4:
+ return bus_space_read_4(via->st, via->sh, regno);
+ default:
+ return 0xFFFFFFFF;
+ }
}
@@ -120,17 +120,17 @@
via_wr(struct via_info *via, int regno, u_int32_t data, int size)
{
-switch (size) {
-case 1:
-bus_space_write_1(via->st, via->sh, regno, data);
-break;
-case 2:
-bus_space_write_2(via->st, via->sh, regno, data);
-break;
-case 4:
-bus_space_write_4(via->st, via->sh, regno, data);
-break;
-}
+ switch (size) {
+ case 1:
+ bus_space_write_1(via->st, via->sh, regno, data);
+ break;
+ case 2:
+ bus_space_write_2(via->st, via->sh, regno, data);
+ break;
+ case 4:
+ bus_space_write_4(via->st, via->sh, regno, data);
+ break;
+ }
}
/* -------------------------------------------------------------------- */
@@ -139,75 +139,75 @@
static int
via_waitready_codec(struct via_info *via)
{
-int i;
+ int i;
-/* poll until codec not busy */
-for (i = 0; (i < TIMEOUT) &&
-(via_rd(via, VIA_CODEC_CTL, 4) & VIA_CODEC_BUSY); i++)
-DELAY(1);
-if (i >= TIMEOUT) {
-printf("via: codec busyn");
-return 1;
-}
+ /* poll until codec not busy */
+ for (i = 0; (i < TIMEOUT) &&
+ (via_rd(via, VIA_CODEC_CTL, 4) & VIA_CODEC_BUSY); i++)
+ DELAY(1);
+ if (i >= TIMEOUT) {
+ printf("via: codec busy\n");
+ return 1;
+ }
-return 0;
+ return 0;
}
static int
via_waitvalid_codec(struct via_info *via)
{
-int i;
+ int i;
-/* poll until codec valid */
-for (i = 0; (i < TIMEOUT) &&
-!(via_rd(via, VIA_CODEC_CTL, 4) & VIA_CODEC_PRIVALID); i++)
-DELAY(1);
-if (i >= TIMEOUT) {
-printf("via: codec invalidn");
-return 1;
-}
+ /* poll until codec valid */
+ for (i = 0; (i < TIMEOUT) &&
+ !(via_rd(via, VIA_CODEC_CTL, 4) & VIA_CODEC_PRIVALID); i++)
+ DELAY(1);
+ if (i >= TIMEOUT) {
+ printf("via: codec invalid\n");
+ return 1;
+ }
-return 0;
+ return 0;
}
static int
via_write_codec(kobj_t obj, void *addr, int reg, u_int32_t val)
{
-struct via_info *via = addr;
+ struct via_info *via = addr;
-if (via_waitready_codec(via)) return -1;
+ if (via_waitready_codec(via)) return -1;
-via_wr(via, VIA_CODEC_CTL, VIA_CODEC_PRIVALID | VIA_CODEC_INDEX(reg) | val, 4);
+ via_wr(via, VIA_CODEC_CTL, VIA_CODEC_PRIVALID | VIA_CODEC_INDEX(reg) | val, 4);
-return 0;
+ return 0;
}
static int
via_read_codec(kobj_t obj, void *addr, int reg)
{
-struct via_info *via = addr;
+ struct via_info *via = addr;
-if (via_waitready_codec(via))
-return -1;
+ if (via_waitready_codec(via))
+ return -1;
-via_wr(via, VIA_CODEC_CTL, VIA_CODEC_PRIVALID | VIA_CODEC_READ | VIA_CODEC_INDEX(reg),4);
+ via_wr(via, VIA_CODEC_CTL, VIA_CODEC_PRIVALID | VIA_CODEC_READ | VIA_CODEC_INDEX(reg),4);
-if (via_waitready_codec(via))
-return -1;
+ if (via_waitready_codec(via))
+ return -1;
-if (via_waitvalid_codec(via))
-return -1;
+ if (via_waitvalid_codec(via))
+ return -1;
-return via_rd(via, VIA_CODEC_CTL, 2);
+ return via_rd(via, VIA_CODEC_CTL, 2);
}
static kobj_method_t via_ac97_methods[] = {
-KOBJMETHOD(ac97_read, via_read_codec),
-KOBJMETHOD(ac97_write, via_write_codec),
-{ 0, 0 }
+ KOBJMETHOD(ac97_read, via_read_codec),
+ KOBJMETHOD(ac97_write, via_write_codec),
+ { 0, 0 }
};
AC97_DECLARE(via_ac97);
@@ -216,208 +216,208 @@
static int
via_buildsgdt(struct via_chinfo *ch)
{
-u_int32_t phys_addr, flag;
-int i, segs, seg_size;
+ u_int32_t phys_addr, flag;
+ int i, segs, seg_size;
-/*
-* Build the scatter/gather DMA (SGD) table.
-* There are four slots in the table: two for play, two for record.
-* This creates two half-buffers, one of which is playing; the other
-* is feeding.
-*/
-seg_size = ch->blksz;
-segs = sndbuf_getsize(ch->buffer) / seg_size;
-phys_addr = sndbuf_getbufaddr(ch->buffer);
-
-for (i = 0; i < segs; i++) {
-flag = (i == segs - 1)? VIA_DMAOP_EOL : VIA_DMAOP_FLAG;
-ch->sgd_table[i].ptr = phys_addr + (i * seg_size);
-ch->sgd_table[i].flags = flag | seg_size;
-}
+ /*
+ * Build the scatter/gather DMA (SGD) table.
+ * There are four slots in the table: two for play, two for record.
+ * This creates two half-buffers, one of which is playing; the other
+ * is feeding.
+ */
+ seg_size = ch->blksz;
+ segs = sndbuf_getsize(ch->buffer) / seg_size;
+ phys_addr = sndbuf_getbufaddr(ch->buffer);
+
+ for (i = 0; i < segs; i++) {
+ flag = (i == segs - 1)? VIA_DMAOP_EOL : VIA_DMAOP_FLAG;
+ ch->sgd_table[i].ptr = phys_addr + (i * seg_size);
+ ch->sgd_table[i].flags = flag | seg_size;
+ }
-return 0;
+ return 0;
}
/* channel interface */
static void *
viachan_init(kobj_t obj, void *devinfo, struct snd_dbuf *b, struct pcm_channel *c, int dir)
{
-struct via_info *via = devinfo;
-struct via_chinfo *ch;
+ struct via_info *via = devinfo;
+ struct via_chinfo *ch;
-snd_mtxlock(via->lock);
-if (dir == PCMDIR_PLAY) {
-ch = &via->pch;
-ch->base = VIA_PLAY_DMAOPS_BASE;
-ch->count = VIA_PLAY_DMAOPS_COUNT;
-ch->ctrl = VIA_PLAY_CONTROL;
-ch->mode = VIA_PLAY_MODE;
-ch->sgd_addr = via->sgd_addr;
-ch->sgd_table = &via->sgd_table[0];
-} else {
-ch = &via->rch;
-ch->base = VIA_RECORD_DMAOPS_BASE;
-ch->count = VIA_RECORD_DMAOPS_COUNT;
-ch->ctrl = VIA_RECORD_CONTROL;
-ch->mode = VIA_RECORD_MODE;
-ch->sgd_addr = via->sgd_addr + sizeof(struct via_dma_op) * SEGS_PER_CHAN;
-ch->sgd_table = &via->sgd_table[SEGS_PER_CHAN];
-}
-
-ch->parent = via;
-ch->channel = c;
-ch->buffer = b;
-ch->dir = dir;
-snd_mtxunlock(via->lock);
+ snd_mtxlock(via->lock);
+ if (dir == PCMDIR_PLAY) {
+ ch = &via->pch;
+ ch->base = VIA_PLAY_DMAOPS_BASE;
+ ch->count = VIA_PLAY_DMAOPS_COUNT;
+ ch->ctrl = VIA_PLAY_CONTROL;
+ ch->mode = VIA_PLAY_MODE;
+ ch->sgd_addr = via->sgd_addr;
+ ch->sgd_table = &via->sgd_table[0];
+ } else {
+ ch = &via->rch;
+ ch->base = VIA_RECORD_DMAOPS_BASE;
+ ch->count = VIA_RECORD_DMAOPS_COUNT;
+ ch->ctrl = VIA_RECORD_CONTROL;
+ ch->mode = VIA_RECORD_MODE;
+ ch->sgd_addr = via->sgd_addr + sizeof(struct via_dma_op) * SEGS_PER_CHAN;
+ ch->sgd_table = &via->sgd_table[SEGS_PER_CHAN];
+ }
+
+ ch->parent = via;
+ ch->channel = c;
+ ch->buffer = b;
+ ch->dir = dir;
+ snd_mtxunlock(via->lock);
-if (sndbuf_alloc(ch->buffer, via->parent_dmat, via->bufsz) != 0)
-return NULL;
+ if (sndbuf_alloc(ch->buffer, via->parent_dmat, 0, via->bufsz) != 0)
+ return NULL;
-return ch;
+ return ch;
}
static int
viachan_setformat(kobj_t obj, void *data, u_int32_t format)
{
-struct via_chinfo *ch = data;
-struct via_info *via = ch->parent;
-int mode, mode_set;
-
-mode_set = 0;
-if (format & AFMT_STEREO)
-mode_set |= VIA_RPMODE_STEREO;
-if (format & AFMT_S16_LE)
-mode_set |= VIA_RPMODE_16BIT;
-
-DEB(printf("set format: dir = %d, format=%xn", ch->dir, format));
-snd_mtxlock(via->lock);
-mode = via_rd(via, ch->mode, 1);
-mode &= ~(VIA_RPMODE_16BIT | VIA_RPMODE_STEREO);
-mode |= mode_set;
-via_wr(via, ch->mode, mode, 1);
-snd_mtxunlock(via->lock);
+ struct via_chinfo *ch = data;
+ struct via_info *via = ch->parent;
+ int mode, mode_set;
+
+ mode_set = 0;
+ if (format & AFMT_STEREO)
+ mode_set |= VIA_RPMODE_STEREO;
+ if (format & AFMT_S16_LE)
+ mode_set |= VIA_RPMODE_16BIT;
+
+ DEB(printf("set format: dir = %d, format=%x\n", ch->dir, format));
+ snd_mtxlock(via->lock);
+ mode = via_rd(via, ch->mode, 1);
+ mode &= ~(VIA_RPMODE_16BIT | VIA_RPMODE_STEREO);
+ mode |= mode_set;
+ via_wr(via, ch->mode, mode, 1);
+ snd_mtxunlock(via->lock);
-return 0;
+ return 0;
}
static int
viachan_setspeed(kobj_t obj, void *data, u_int32_t speed)
{
-struct via_chinfo *ch = data;
-struct via_info *via = ch->parent;
-int reg;
-
-/*
-* Basic AC'97 defines a 48 kHz sample rate only. For other rates,
-* upsampling is required.
-*
-* The VT82C686A does not perform upsampling, and neither do we.
-* If the codec supports variable-rate audio (i.e. does the upsampling
-* itself), then negotiate the rate with the codec. Otherwise,
-* return 48 kHz cuz that's all you got.
-*/
-if (via->codec_caps & AC97_EXTCAP_VRA) {
-reg = (ch->dir == PCMDIR_PLAY)? AC97_REGEXT_FDACRATE : AC97_REGEXT_LADCRATE;
-return ac97_setrate(via->codec, reg, speed);
-} else
-return 48000;
+ struct via_chinfo *ch = data;
+ struct via_info *via = ch->parent;
+ int reg;
+
+ /*
+ * Basic AC'97 defines a 48 kHz sample rate only. For other rates,
+ * upsampling is required.
+ *
+ * The VT82C686A does not perform upsampling, and neither do we.
+ * If the codec supports variable-rate audio (i.e. does the upsampling
+ * itself), then negotiate the rate with the codec. Otherwise,
+ * return 48 kHz cuz that's all you got.
+ */
+ if (via->codec_caps & AC97_EXTCAP_VRA) {
+ reg = (ch->dir == PCMDIR_PLAY)? AC97_REGEXT_FDACRATE : AC97_REGEXT_LADCRATE;
+ return ac97_setrate(via->codec, reg, speed);
+ } else
+ return 48000;
}
static int
viachan_setblocksize(kobj_t obj, void *data, u_int32_t blocksize)
{
-struct via_chinfo *ch = data;
+ struct via_chinfo *ch = data;
-ch->blksz = blocksize;
-sndbuf_resize(ch->buffer, SEGS_PER_CHAN, ch->blksz);
+ ch->blksz = blocksize;
+ sndbuf_resize(ch->buffer, SEGS_PER_CHAN, ch->blksz);
-return ch->blksz;
+ return ch->blksz;
}
static int
viachan_trigger(kobj_t obj, void *data, int go)
{
-struct via_chinfo *ch = data;
-struct via_info *via = ch->parent;
-struct via_dma_op *ado;
-bus_addr_t sgd_addr = ch->sgd_addr;
-
-if (go == PCMTRIG_EMLDMAWR || go == PCMTRIG_EMLDMARD)
-return 0;
-
-ado = ch->sgd_table;
-DEB(printf("ado located at va=%p pa=%xn", ado, sgd_addr));
-
-snd_mtxlock(via->lock);
-if (go == PCMTRIG_START) {
-via_buildsgdt(ch);
-via_wr(via, ch->base, sgd_addr, 4);
-via_wr(via, ch->ctrl, VIA_RPCTRL_START, 1);
-} else
-via_wr(via, ch->ctrl, VIA_RPCTRL_TERMINATE, 1);
-snd_mtxunlock(via->lock);
+ struct via_chinfo *ch = data;
+ struct via_info *via = ch->parent;
+ struct via_dma_op *ado;
+ bus_addr_t sgd_addr = ch->sgd_addr;
+
+ if (!PCMTRIG_COMMON(go))
+ return 0;
+
+ ado = ch->sgd_table;
+ DEB(printf("ado located at va=%p pa=%x\n", ado, sgd_addr));
+
+ snd_mtxlock(via->lock);
+ if (go == PCMTRIG_START) {
+ via_buildsgdt(ch);
+ via_wr(via, ch->base, sgd_addr, 4);
+ via_wr(via, ch->ctrl, VIA_RPCTRL_START, 1);
+ } else
+ via_wr(via, ch->ctrl, VIA_RPCTRL_TERMINATE, 1);
+ snd_mtxunlock(via->lock);
-DEB(printf("viachan_trigger: go=%dn", go));
-return 0;
+ DEB(printf("viachan_trigger: go=%d\n", go));
+ return 0;
}
static int
viachan_getptr(kobj_t obj, void *data)
{
-struct via_chinfo *ch = data;
-struct via_info *via = ch->parent;
-struct via_dma_op *ado;
-bus_addr_t sgd_addr = ch->sgd_addr;
-int ptr, base, base1, len, seg;
-
-ado = ch->sgd_table;
-snd_mtxlock(via->lock);
-base1 = via_rd(via, ch->base, 4);
-len = via_rd(via, ch->count, 4);
-base = via_rd(via, ch->base, 4);
-if (base != base1) /* Avoid race hazard */
-len = via_rd(via, ch->count, 4);
-snd_mtxunlock(via->lock);
-
-DEB(printf("viachan_getptr: len / base = %x / %xn", len, base));
-
-/* Base points to SGD segment to do, one past current */
-
-/* Determine how many segments have been done */
-seg = (base - sgd_addr) / sizeof(struct via_dma_op);
-if (seg == 0)
-seg = SEGS_PER_CHAN;
-
-/* Now work out offset: seg less count */
-ptr = (seg * sndbuf_getsize(ch->buffer) / SEGS_PER_CHAN) - len;
-if (ch->dir == PCMDIR_REC) {
-/* DMA appears to operate on memory 'lines' of 32 bytes */
-/* so don't return any part line - it isn't in RAM yet */
-ptr = ptr & ~0x1f;
-}
+ struct via_chinfo *ch = data;
+ struct via_info *via = ch->parent;
+ struct via_dma_op *ado;
+ bus_addr_t sgd_addr = ch->sgd_addr;
+ int ptr, base, base1, len, seg;
+
+ ado = ch->sgd_table;
+ snd_mtxlock(via->lock);
+ base1 = via_rd(via, ch->base, 4);
+ len = via_rd(via, ch->count, 4);
+ base = via_rd(via, ch->base, 4);
+ if (base != base1) /* Avoid race hazard */
+ len = via_rd(via, ch->count, 4);
+ snd_mtxunlock(via->lock);
+
+ DEB(printf("viachan_getptr: len / base = %x / %x\n", len, base));
+
+ /* Base points to SGD segment to do, one past current */
+
+ /* Determine how many segments have been done */
+ seg = (base - sgd_addr) / sizeof(struct via_dma_op);
+ if (seg == 0)
+ seg = SEGS_PER_CHAN;
+
+ /* Now work out offset: seg less count */
+ ptr = (seg * sndbuf_getsize(ch->buffer) / SEGS_PER_CHAN) - len;
+ if (ch->dir == PCMDIR_REC) {
+ /* DMA appears to operate on memory 'lines' of 32 bytes */
+ /* so don't return any part line - it isn't in RAM yet */
+ ptr = ptr & ~0x1f;
+ }
-DEB(printf("return ptr=%dn", ptr));
-return ptr;
+ DEB(printf("return ptr=%d\n", ptr));
+ return ptr;
}
static struct pcmchan_caps *
viachan_getcaps(kobj_t obj, void *data)
{
-struct via_chinfo *ch = data;
-struct via_info *via = ch->parent;
+ struct via_chinfo *ch = data;
+ struct via_info *via = ch->parent;
-return (via->codec_caps & AC97_EXTCAP_VRA)? &via_vracaps : &via_caps;
+ return (via->codec_caps & AC97_EXTCAP_VRA)? &via_vracaps : &via_caps;
}
static kobj_method_t viachan_methods[] = {
-KOBJMETHOD(channel_init, viachan_init),
-KOBJMETHOD(channel_setformat, viachan_setformat),
-KOBJMETHOD(channel_setspeed, viachan_setspeed),
-KOBJMETHOD(channel_setblocksize, viachan_setblocksize),
-KOBJMETHOD(channel_trigger, viachan_trigger),
-KOBJMETHOD(channel_getptr, viachan_getptr),
-KOBJMETHOD(channel_getcaps, viachan_getcaps),
-{ 0, 0 }
+ KOBJMETHOD(channel_init, viachan_init),
+ KOBJMETHOD(channel_setformat, viachan_setformat),
+ KOBJMETHOD(channel_setspeed, viachan_setspeed),
+ KOBJMETHOD(channel_setblocksize, viachan_setblocksize),
+ KOBJMETHOD(channel_trigger, viachan_trigger),
+ KOBJMETHOD(channel_getptr, viachan_getptr),
+ KOBJMETHOD(channel_getcaps, viachan_getcaps),
+ { 0, 0 }
};
CHANNEL_DECLARE(viachan);
@@ -426,227 +426,229 @@
static void
via_intr(void *p)
{
-struct via_info *via = p;
+ struct via_info *via = p;
-/* DEB(printf("viachan_intrn")); */
-/* Read channel */
-snd_mtxlock(via->lock);
-if (via_rd(via, VIA_PLAY_STAT, 1) & VIA_RPSTAT_INTR) {
-via_wr(via, VIA_PLAY_STAT, VIA_RPSTAT_INTR, 1);
-snd_mtxunlock(via->lock);
-chn_intr(via->pch.channel);
-snd_mtxlock(via->lock);
-}
-
-/* Write channel */
-if (via_rd(via, VIA_RECORD_STAT, 1) & VIA_RPSTAT_INTR) {
-via_wr(via, VIA_RECORD_STAT, VIA_RPSTAT_INTR, 1);
-snd_mtxunlock(via->lock);
-chn_intr(via->rch.channel);
-return;
-}
-snd_mtxunlock(via->lock);
+ /* DEB(printf("viachan_intr\n")); */
+ /* Read channel */
+ snd_mtxlock(via->lock);
+ if (via_rd(via, VIA_PLAY_STAT, 1) & VIA_RPSTAT_INTR) {
+ via_wr(via, VIA_PLAY_STAT, VIA_RPSTAT_INTR, 1);
+ snd_mtxunlock(via->lock);
+ chn_intr(via->pch.channel);
+ snd_mtxlock(via->lock);
+ }
+
+ /* Write channel */
+ if (via_rd(via, VIA_RECORD_STAT, 1) & VIA_RPSTAT_INTR) {
+ via_wr(via, VIA_RECORD_STAT, VIA_RPSTAT_INTR, 1);
+ snd_mtxunlock(via->lock);
+ chn_intr(via->rch.channel);
+ return;
+ }
+ snd_mtxunlock(via->lock);
}
/*
-* Probe and attach the card
-*/
+ * Probe and attach the card
+ */
static int
via_probe(device_t dev)
{
-if (pci_get_devid(dev) == VIA_PCI_ID) {
-device_set_desc(dev, "VIA VT82C686A");
-return BUS_PROBE_DEFAULT;
-}
-return ENXIO;
+ if (pci_get_devid(dev) == VIA_PCI_ID) {
+ device_set_desc(dev, "VIA VT82C686A");
+ return BUS_PROBE_DEFAULT;
+ }
+ return ENXIO;
}
static void
dma_cb(void *p, bus_dma_segment_t *bds, int a, int b)
{
-struct via_info *via = (struct via_info *)p;
-via->sgd_addr = bds->ds_addr;
+ struct via_info *via = (struct via_info *)p;
+ via->sgd_addr = bds->ds_addr;
}
static int
via_attach(device_t dev)
{
-struct via_info *via = 0;
-char status[SND_STATUSLEN];
-u_int32_t data, cnt;
-
-if ((via = malloc(sizeof *via, M_DEVBUF, M_NOWAIT | M_ZERO)) == NULL) {
-device_printf(dev, "cannot allocate softcn");
-return ENXIO;
-}
-via->lock = snd_mtxcreate(device_get_nameunit(dev), "sound softc");
-
-/* Get resources */
-data = pci_read_config(dev, PCIR_COMMAND, 2);
-data |= (PCIM_CMD_PORTEN | PCIM_CMD_BUSMASTEREN);
-pci_write_config(dev, PCIR_COMMAND, data, 2);
-data = pci_read_config(dev, PCIR_COMMAND, 2);
-
-/* Wake up and reset AC97 if necessary */
-data = pci_read_config(dev, VIA_AC97STATUS, 1);
-
-if ((data & VIA_AC97STATUS_RDY) == 0) {
-/* Cold reset per ac97r2.3 spec (page 95) */
-pci_write_config(dev, VIA_ACLINKCTRL, VIA_ACLINK_EN, 1); /* Assert low */
-DELAY(100); /* Wait T_rst_low */
-pci_write_config(dev, VIA_ACLINKCTRL, VIA_ACLINK_EN | VIA_ACLINK_NRST, 1); /* Assert high */
-DELAY(5); /* Wait T_rst2clk */
-pci_write_config(dev, VIA_ACLINKCTRL, VIA_ACLINK_EN, 1); /* Assert low */
-} else {
-/* Warm reset */
-pci_write_config(dev, VIA_ACLINKCTRL, VIA_ACLINK_EN, 1); /* Force no sync */
-DELAY(100);
-pci_write_config(dev, VIA_ACLINKCTRL, VIA_ACLINK_EN | VIA_ACLINK_SYNC, 1); /* Sync */
-DELAY(5); /* Wait T_sync_high */
-pci_write_config(dev, VIA_ACLINKCTRL, VIA_ACLINK_EN, 1); /* Force no sync */
-DELAY(5); /* Wait T_sync2clk */
-}
-
-/* Power everything up */
-pci_write_config(dev, VIA_ACLINKCTRL, VIA_ACLINK_DESIRED, 1);
-
-/* Wait for codec to become ready (largest reported delay here 310ms) */
-for (cnt = 0; cnt < 2000; cnt++) {
-data = pci_read_config(dev, VIA_AC97STATUS, 1);
-if (data & VIA_AC97STATUS_RDY)
-break;
-DELAY(5000);
-}
-
-via->regid = PCIR_BAR(0);
-via->reg = bus_alloc_resource_any(dev, SYS_RES_IOPORT,
-&via->regid, RF_ACTIVE);
-if (!via->reg) {
-device_printf(dev, "cannot allocate bus resource.");
-goto bad;
-}
-via->st = rman_get_bustag(via->reg);
-via->sh = rman_get_bushandle(via->reg);
-
-via->bufsz = pcm_getbuffersize(dev, 4096, VIA_DEFAULT_BUFSZ, 65536);
-
-via->irqid = 0;
-via->irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &via->irqid,
-RF_ACTIVE | RF_SHAREABLE);
-if (!via->irq || snd_setup_intr(dev, via->irq, INTR_MPSAFE, via_intr, via, &via->ih)) {
-device_printf(dev, "unable to map interruptn");
-goto bad;
-}
-
-via_wr(via, VIA_PLAY_MODE, VIA_RPMODE_AUTOSTART | VIA_RPMODE_INTR_FLAG | VIA_RPMODE_INTR_EOL, 1);
-via_wr(via, VIA_RECORD_MODE, VIA_RPMODE_AUTOSTART | VIA_RPMODE_INTR_FLAG | VIA_RPMODE_INTR_EOL, 1);
-
-via->codec = AC97_CREATE(dev, via, via_ac97);
-if (!via->codec)
-goto bad;
-
-if (mixer_init(dev, ac97_getmixerclass(), via->codec))
-goto bad;
-
-via->codec_caps = ac97_getextcaps(via->codec);
-ac97_setextmode(via->codec,
-via->codec_caps & (AC97_EXTCAP_VRA | AC97_EXTCAP_VRM));
-
-/* DMA tag for buffers */
-if (bus_dma_tag_create(/*parent*/NULL, /*alignment*/2, /*boundary*/0,
-/*lowaddr*/BUS_SPACE_MAXADDR_32BIT,
-/*highaddr*/BUS_SPACE_MAXADDR,
-/*filter*/NULL, /*filterarg*/NULL,
-/*maxsize*/via->bufsz, /*nsegments*/1, /*maxsegz*/0x3ffff,
-/*flags*/0, /*lockfunc*/NULL,
-/*lockarg*/NULL, &via->parent_dmat) != 0) {
-device_printf(dev, "unable to create dma tagn");
-goto bad;
-}
-
-/*
-* DMA tag for SGD table. The 686 uses scatter/gather DMA and
-* requires a list in memory of work to do. We need only 16 bytes
-* for this list, and it is wasteful to allocate 16K.
-*/
-if (bus_dma_tag_create(/*parent*/NULL, /*alignment*/2, /*boundary*/0,
-/*lowaddr*/BUS_SPACE_MAXADDR_32BIT,
-/*highaddr*/BUS_SPACE_MAXADDR,
-/*filter*/NULL, /*filterarg*/NULL,
-/*maxsize*/NSEGS * sizeof(struct via_dma_op),
-/*nsegments*/1, /*maxsegz*/0x3ffff,
-/*flags*/0, /*lockfunc*/NULL,
-/*lockarg*/NULL, &via->sgd_dmat) != 0) {
-device_printf(dev, "unable to create dma tagn");
-goto bad;
-}
-
-if (bus_dmamem_alloc(via->sgd_dmat, (void **)&via->sgd_table,
-BUS_DMA_NOWAIT, &via->sgd_dmamap) != 0)
-goto bad;
-if (bus_dmamap_load(via->sgd_dmat, via->sgd_dmamap, via->sgd_table,
-NSEGS * sizeof(struct via_dma_op), dma_cb, via, 0) != 0)
-goto bad;
-
-snprintf(status, SND_STATUSLEN, "at io 0x%lx irq %ld %s",
-rman_get_start(via->reg), rman_get_start(via->irq),
-PCM_KLDSTRING(snd_via82c686));
-
-/* Register */
-if (pcm_register(dev, via, 1, 1)) goto bad;
-pcm_addchan(dev, PCMDIR_PLAY, &viachan_class, via);
-pcm_addchan(dev, PCMDIR_REC, &viachan_class, via);
-pcm_setstatus(dev, status);
-return 0;
+ struct via_info *via = 0;
+ char status[SND_STATUSLEN];
+ u_int32_t data, cnt;
+
+ via = malloc(sizeof(*via), M_DEVBUF, M_WAITOK | M_ZERO);
+ via->lock = snd_mtxcreate(device_get_nameunit(dev),
+ "snd_via82c686 softc");
+
+ /* Get resources */
+ data = pci_read_config(dev, PCIR_COMMAND, 2);
+ data |= (PCIM_CMD_PORTEN | PCIM_CMD_BUSMASTEREN);
+ pci_write_config(dev, PCIR_COMMAND, data, 2);
+ data = pci_read_config(dev, PCIR_COMMAND, 2);
+
+ /* Wake up and reset AC97 if necessary */
+ data = pci_read_config(dev, VIA_AC97STATUS, 1);
+
+ if ((data & VIA_AC97STATUS_RDY) == 0) {
+ /* Cold reset per ac97r2.3 spec (page 95) */
+ pci_write_config(dev, VIA_ACLINKCTRL, VIA_ACLINK_EN, 1); /* Assert low */
+ DELAY(100); /* Wait T_rst_low */
+ pci_write_config(dev, VIA_ACLINKCTRL, VIA_ACLINK_EN | VIA_ACLINK_NRST, 1); /* Assert high */
+ DELAY(5); /* Wait T_rst2clk */
+ pci_write_config(dev, VIA_ACLINKCTRL, VIA_ACLINK_EN, 1); /* Assert low */
+ } else {
+ /* Warm reset */
+ pci_write_config(dev, VIA_ACLINKCTRL, VIA_ACLINK_EN, 1); /* Force no sync */
+ DELAY(100);
+ pci_write_config(dev, VIA_ACLINKCTRL, VIA_ACLINK_EN | VIA_ACLINK_SYNC, 1); /* Sync */
+ DELAY(5); /* Wait T_sync_high */
+ pci_write_config(dev, VIA_ACLINKCTRL, VIA_ACLINK_EN, 1); /* Force no sync */
+ DELAY(5); /* Wait T_sync2clk */
+ }
+
+ /* Power everything up */
+ pci_write_config(dev, VIA_ACLINKCTRL, VIA_ACLINK_DESIRED, 1);
+
+ /* Wait for codec to become ready (largest reported delay here 310ms) */
+ for (cnt = 0; cnt < 2000; cnt++) {
+ data = pci_read_config(dev, VIA_AC97STATUS, 1);
+ if (data & VIA_AC97STATUS_RDY)
+ break;
+ DELAY(5000);
+ }
+
+ via->regid = PCIR_BAR(0);
+ via->reg = bus_alloc_resource_any(dev, SYS_RES_IOPORT,
+ &via->regid, RF_ACTIVE);
+ if (!via->reg) {
+ device_printf(dev, "cannot allocate bus resource.");
+ goto bad;
+ }
+ via->st = rman_get_bustag(via->reg);
+ via->sh = rman_get_bushandle(via->reg);
+
+ via->bufsz = pcm_getbuffersize(dev, 4096, VIA_DEFAULT_BUFSZ, 65536);
+
+ via->irqid = 0;
+ via->irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &via->irqid,
+ RF_ACTIVE | RF_SHAREABLE);
+ if (!via->irq || snd_setup_intr(dev, via->irq, INTR_MPSAFE, via_intr, via, &via->ih)) {
+ device_printf(dev, "unable to map interrupt\n");
+ goto bad;
+ }
+
+ via_wr(via, VIA_PLAY_MODE, VIA_RPMODE_AUTOSTART | VIA_RPMODE_INTR_FLAG | VIA_RPMODE_INTR_EOL, 1);
+ via_wr(via, VIA_RECORD_MODE, VIA_RPMODE_AUTOSTART | VIA_RPMODE_INTR_FLAG | VIA_RPMODE_INTR_EOL, 1);
+
+ via->codec = AC97_CREATE(dev, via, via_ac97);
+ if (!via->codec)
+ goto bad;
+
+ if (mixer_init(dev, ac97_getmixerclass(), via->codec))
+ goto bad;
+
+ via->codec_caps = ac97_getextcaps(via->codec);
+ ac97_setextmode(via->codec,
+ via->codec_caps & (AC97_EXTCAP_VRA | AC97_EXTCAP_VRM));
+
+ /* DMA tag for buffers */
+ if (bus_dma_tag_create(/*parent*/bus_get_dma_tag(dev), /*alignment*/2,
+ /*boundary*/0,
+ /*lowaddr*/BUS_SPACE_MAXADDR_32BIT,
+ /*highaddr*/BUS_SPACE_MAXADDR,
+ /*filter*/NULL, /*filterarg*/NULL,
+ /*maxsize*/via->bufsz, /*nsegments*/1, /*maxsegz*/0x3ffff,
+ /*flags*/0, /*lockfunc*/NULL,
+ /*lockarg*/NULL, &via->parent_dmat) != 0) {
+ device_printf(dev, "unable to create dma tag\n");
+ goto bad;
+ }
+
+ /*
+ * DMA tag for SGD table. The 686 uses scatter/gather DMA and
+ * requires a list in memory of work to do. We need only 16 bytes
+ * for this list, and it is wasteful to allocate 16K.
+ */
+ if (bus_dma_tag_create(/*parent*/bus_get_dma_tag(dev), /*alignment*/2,
+ /*boundary*/0,
+ /*lowaddr*/BUS_SPACE_MAXADDR_32BIT,
+ /*highaddr*/BUS_SPACE_MAXADDR,
+ /*filter*/NULL, /*filterarg*/NULL,
+ /*maxsize*/NSEGS * sizeof(struct via_dma_op),
+ /*nsegments*/1, /*maxsegz*/0x3ffff,
+ /*flags*/0, /*lockfunc*/NULL,
+ /*lockarg*/NULL, &via->sgd_dmat) != 0) {
+ device_printf(dev, "unable to create dma tag\n");
+ goto bad;
+ }
+
+ if (bus_dmamem_alloc(via->sgd_dmat, (void **)&via->sgd_table,
+ BUS_DMA_NOWAIT, &via->sgd_dmamap) != 0)
+ goto bad;
+ if (bus_dmamap_load(via->sgd_dmat, via->sgd_dmamap, via->sgd_table,
+ NSEGS * sizeof(struct via_dma_op), dma_cb, via, 0) != 0)
+ goto bad;
+
+ snprintf(status, SND_STATUSLEN, "at io 0x%lx irq %ld %s",
+ rman_get_start(via->reg), rman_get_start(via->irq),
+ PCM_KLDSTRING(snd_via82c686));
+
+ /* Register */
+ if (pcm_register(dev, via, 1, 1)) goto bad;
+ pcm_addchan(dev, PCMDIR_PLAY, &viachan_class, via);
+ pcm_addchan(dev, PCMDIR_REC, &viachan_class, via);
+ pcm_setstatus(dev, status);
+ return 0;
bad:
-if (via->codec) ac97_destroy(via->codec);
-if (via->reg) bus_release_resource(dev, SYS_RES_IOPORT, via->regid, via->reg);
-if (via->ih) bus_teardown_intr(dev, via->irq, via->ih);
-if (via->irq) bus_release_resource(dev, SYS_RES_IRQ, via->irqid, via->irq);
-if (via->parent_dmat) bus_dma_tag_destroy(via->parent_dmat);
-if (via->sgd_dmamap) bus_dmamap_unload(via->sgd_dmat, via->sgd_dmamap);
-if (via->sgd_dmat) bus_dma_tag_destroy(via->sgd_dmat);
-if (via->lock) snd_mtxfree(via->lock);
-if (via) free(via, M_DEVBUF);
-return ENXIO;
+ if (via->codec) ac97_destroy(via->codec);
+ if (via->reg) bus_release_resource(dev, SYS_RES_IOPORT, via->regid, via->reg);
+ if (via->ih) bus_teardown_intr(dev, via->irq, via->ih);
+ if (via->irq) bus_release_resource(dev, SYS_RES_IRQ, via->irqid, via->irq);
+ if (via->parent_dmat) bus_dma_tag_destroy(via->parent_dmat);
+ if (via->sgd_dmamap) bus_dmamap_unload(via->sgd_dmat, via->sgd_dmamap);
+ if (via->sgd_table) bus_dmamem_free(via->sgd_dmat, via->sgd_table, via->sgd_dmamap);
+ if (via->sgd_dmat) bus_dma_tag_destroy(via->sgd_dmat);
+ if (via->lock) snd_mtxfree(via->lock);
+ if (via) free(via, M_DEVBUF);
+ return ENXIO;
}
static int
via_detach(device_t dev)
{
-int r;
-struct via_info *via = 0;
+ int r;
+ struct via_info *via = 0;
-r = pcm_unregister(dev);
-if (r)
-return r;
-
-via = pcm_getdevinfo(dev);
-bus_release_resource(dev, SYS_RES_IOPORT, via->regid, via->reg);
-bus_teardown_intr(dev, via->irq, via->ih);
-bus_release_resource(dev, SYS_RES_IRQ, via->irqid, via->irq);
-bus_dma_tag_destroy(via->parent_dmat);
-bus_dmamap_unload(via->sgd_dmat, via->sgd_dmamap);
-bus_dma_tag_destroy(via->sgd_dmat);
-snd_mtxfree(via->lock);
-free(via, M_DEVBUF);
-return 0;
+ r = pcm_unregister(dev);
+ if (r)
+ return r;
+
+ via = pcm_getdevinfo(dev);
+ bus_release_resource(dev, SYS_RES_IOPORT, via->regid, via->reg);
+ bus_teardown_intr(dev, via->irq, via->ih);
+ bus_release_resource(dev, SYS_RES_IRQ, via->irqid, via->irq);
+ bus_dma_tag_destroy(via->parent_dmat);
+ bus_dmamap_unload(via->sgd_dmat, via->sgd_dmamap);
+ bus_dmamem_free(via->sgd_dmat, via->sgd_table, via->sgd_dmamap);
+ bus_dma_tag_destroy(via->sgd_dmat);
+ snd_mtxfree(via->lock);
+ free(via, M_DEVBUF);
+ return 0;
}
static device_method_t via_methods[] = {
-DEVMETHOD(device_probe, via_probe),
-DEVMETHOD(device_attach, via_attach),
-DEVMETHOD(device_detach, via_detach),
-{ 0, 0}
+ DEVMETHOD(device_probe, via_probe),
+ DEVMETHOD(device_attach, via_attach),
+ DEVMETHOD(device_detach, via_detach),
+ { 0, 0}
};
static driver_t via_driver = {
-"pcm",
-via_methods,
-PCM_SOFTC_SIZE,
+ "pcm",
+ via_methods,
+ PCM_SOFTC_SIZE,
};
DRIVER_MODULE(snd_via82c686, pci, via_driver, pcm_devclass, 0, 0);
Index: als4000.h
===================================================================
RCS file: /home/cvs/src/sys/dev/sound/pci/als4000.h,v
retrieving revision 1.2
retrieving revision 1.3
diff -L sys/dev/sound/pci/als4000.h -L sys/dev/sound/pci/als4000.h -u -r1.2 -r1.3
--- sys/dev/sound/pci/als4000.h
+++ sys/dev/sound/pci/als4000.h
@@ -1,31 +1,30 @@
/*-
-* Copyright (c) 2001 Orion Hodson <O.Hodson at cs.ucl.ac.uk>
-* All rights reserved.
-*
-* Redistribution and use in source and binary forms, with or without
-* modification, are permitted provided that the following conditions
-* are met:
-* 1. Redistributions of source code must retain the above copyright
-* notice, this list of conditions and the following disclaimer.
-* 2. Redistributions in binary form must reproduce the above copyright
-* notice, this list of conditions and the following disclaimer in the
-* documentation and/or other materials provided with the distribution.
-*
-* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
-* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
-* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
-* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
-* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHERIN CONTRACT, STRICT
-* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
-* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THEPOSSIBILITY OF
-* SUCH DAMAGE.
-*
-* $MidnightBSD$
-* $FreeBSD: src/sys/dev/sound/pci/als4000.h,v 1.3 2005/01/06 01:43:18 imp Exp $
-*/
+ * Copyright (c) 2001 Orion Hodson <O.Hodson at cs.ucl.ac.uk>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHERIN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THEPOSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD: src/sys/dev/sound/pci/als4000.h,v 1.3 2005/01/06 01:43:18 imp Exp $
+ */
#define ALS_PCI_ID0 0x40004005
#define ALS_PCI_POWERREG 0xe0
Index: ds1.h
===================================================================
RCS file: /home/cvs/src/sys/dev/sound/pci/ds1.h,v
retrieving revision 1.2
retrieving revision 1.3
diff -L sys/dev/sound/pci/ds1.h -L sys/dev/sound/pci/ds1.h -u -r1.2 -r1.3
--- sys/dev/sound/pci/ds1.h
+++ sys/dev/sound/pci/ds1.h
@@ -1,13 +1,12 @@
/*
-* =======================================================================
-* title : define
-* company : YAMAHA
-* author : Taichi Sugiyama
-* create Data : 28/Sep/99
-* =======================================================================
-* $MidnightBSD$
-* $FreeBSD: src/sys/dev/sound/pci/ds1.h,v 1.1 2000/05/31 03:21:36 cg Exp $
-*/
+ * =======================================================================
+ * title : define
+ * company : YAMAHA
+ * author : Taichi Sugiyama
+ * create Data : 28/Sep/99
+ * =======================================================================
+ * $FreeBSD: src/sys/dev/sound/pci/ds1.h,v 1.1 2000/05/31 03:21:36 cg Exp $
+ */
/* ----- YAMAHA DS-XG Devices -------------------------------------------- */
Index: atiixp.c
===================================================================
RCS file: /home/cvs/src/sys/dev/sound/pci/atiixp.c,v
retrieving revision 1.3
retrieving revision 1.4
diff -L sys/dev/sound/pci/atiixp.c -L sys/dev/sound/pci/atiixp.c -u -r1.3 -r1.4
--- sys/dev/sound/pci/atiixp.c
+++ sys/dev/sound/pci/atiixp.c
@@ -1,57 +1,57 @@
/*-
-* Copyright (c) 2005 Ariff Abdullah <ariff at FreeBSD.org>
-* All rights reserved.
-*
-* Redistribution and use in source and binary forms, with or without
-* modification, are permitted provided that the following conditions
-* are met:
-* 1. Redistributions of source code must retain the above copyright
-* notice, this list of conditions and the following disclaimer.
-* 2. Redistributions in binary form must reproduce the above copyright
-* notice, this list of conditions and the following disclaimer in the
-* documentation and/or other materials provided with the distribution.
-*
-* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
-* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
-* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
-* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
-* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHERIN CONTRACT, STRICT
-* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
-* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THEPOSSIBILITY OF
-* SUCH DAMAGE.
-*/
+ * Copyright (c) 2005 Ariff Abdullah <ariff at FreeBSD.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHERIN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THEPOSSIBILITY OF
+ * SUCH DAMAGE.
+ */
/*
-* FreeBSD pcm driver for ATI IXP 150/200/250/300 AC97 controllers
-*
-* Features
-* * 16bit playback / recording
-* * 32bit native playback - yay!
-* * 32bit native recording (seems broken on few hardwares)
-*
-* Issues / TODO:
-* * SPDIF
-* * Support for more than 2 channels.
-* * VRA ? VRM ? DRA ?
-* * 32bit native recording seems broken on few hardwares, most
-* probably because of incomplete VRA/DRA cleanup.
-*
-*
-* Thanks goes to:
-*
-* Shaharil @ SCAN Associates whom relentlessly providing me the
-* mind blowing Acer Ferrari 4002 WLMi with this ATI IXP hardware.
-*
-* Reinoud Zandijk <reinoud at NetBSD.org> (auixp), which this driver is
-* largely based upon although large part of it has been reworked. His
-* driver is the primary reference and pretty much well documented.
-*
-* Takashi Iwai (ALSA snd-atiixp), for register definitions and some
-* random ninja hackery.
-*/
+ * FreeBSD pcm driver for ATI IXP 150/200/250/300 AC97 controllers
+ *
+ * Features
+ * * 16bit playback / recording
+ * * 32bit native playback - yay!
+ * * 32bit native recording (seems broken on few hardwares)
+ *
+ * Issues / TODO:
+ * * SPDIF
+ * * Support for more than 2 channels.
+ * * VRA ? VRM ? DRA ?
+ * * 32bit native recording seems broken on few hardwares, most
+ * probably because of incomplete VRA/DRA cleanup.
+ *
+ *
+ * Thanks goes to:
+ *
+ * Shaharil @ SCAN Associates whom relentlessly providing me the
+ * mind blowing Acer Ferrari 4002 WLMi with this ATI IXP hardware.
+ *
+ * Reinoud Zandijk <reinoud at NetBSD.org> (auixp), which this driver is
+ * largely based upon although large part of it has been reworked. His
+ * driver is the primary reference and pretty much well documented.
+ *
+ * Takashi Iwai (ALSA snd-atiixp), for register definitions and some
+ * random ninja hackery.
+ */
#include <dev/sound/pcm/sound.h>
#include <dev/sound/pcm/ac97.h>
@@ -63,115 +63,136 @@
#include <dev/sound/pci/atiixp.h>
-SND_DECLARE_FILE("$MidnightBSD$");
+SND_DECLARE_FILE("$FreeBSD: src/sys/dev/sound/pci/atiixp.c,v 1.19.2.1 2007/11/06 02:07:56 ariff Exp $");
+
+#define ATI_IXP_DMA_RETRY_MAX 100
+
+#define ATI_IXP_BUFSZ_MIN 4096
+#define ATI_IXP_BUFSZ_MAX 65536
+#define ATI_IXP_BUFSZ_DEFAULT 16384
+
+#define ATI_IXP_BLK_MIN 32
+#define ATI_IXP_BLK_ALIGN (~(ATI_IXP_BLK_MIN - 1))
+
+#define ATI_IXP_CHN_RUNNING 0x00000001
+#define ATI_IXP_CHN_SUSPEND 0x00000002
struct atiixp_dma_op {
-volatile uint32_t addr;
-volatile uint16_t status;
-volatile uint16_t size;
-volatile uint32_t next;
+ volatile uint32_t addr;
+ volatile uint16_t status;
+ volatile uint16_t size;
+ volatile uint32_t next;
};
struct atiixp_info;
struct atiixp_chinfo {
-struct snd_dbuf *buffer;
-struct pcm_channel *channel;
-struct atiixp_info *parent;
-struct atiixp_dma_op *sgd_table;
-bus_addr_t sgd_addr;
-uint32_t enable_bit, flush_bit, linkptr_bit, dma_dt_cur_bit;
-uint32_t dma_segs;
-uint32_t fmt;
-int caps_32bit, dir, active;
+ struct snd_dbuf *buffer;
+ struct pcm_channel *channel;
+ struct atiixp_info *parent;
+ struct atiixp_dma_op *sgd_table;
+ bus_addr_t sgd_addr;
+ uint32_t enable_bit, flush_bit, linkptr_bit, dt_cur_bit;
+ uint32_t blksz, blkcnt;
+ uint32_t ptr, prevptr;
+ uint32_t fmt;
+ uint32_t flags;
+ int caps_32bit, dir;
};
struct atiixp_info {
-device_t dev;
+ device_t dev;
-bus_space_tag_t st;
-bus_space_handle_t sh;
-bus_dma_tag_t parent_dmat;
-bus_dma_tag_t sgd_dmat;
-bus_dmamap_t sgd_dmamap;
-bus_addr_t sgd_addr;
-
-struct resource *reg, *irq;
-int regtype, regid, irqid;
-void *ih;
-struct ac97_info *codec;
-
-struct atiixp_chinfo pch;
-struct atiixp_chinfo rch;
-struct atiixp_dma_op *sgd_table;
-struct intr_config_hook delayed_attach;
-
-uint32_t bufsz;
-uint32_t codec_not_ready_bits, codec_idx, codec_found;
-uint32_t dma_segs;
-int registered_channels;
-
-struct mtx *lock;
+ bus_space_tag_t st;
+ bus_space_handle_t sh;
+ bus_dma_tag_t parent_dmat;
+ bus_dma_tag_t sgd_dmat;
+ bus_dmamap_t sgd_dmamap;
+ bus_addr_t sgd_addr;
+
+ struct resource *reg, *irq;
+ int regtype, regid, irqid;
+ void *ih;
+ struct ac97_info *codec;
+
+ struct atiixp_chinfo pch;
+ struct atiixp_chinfo rch;
+ struct atiixp_dma_op *sgd_table;
+ struct intr_config_hook delayed_attach;
+
+ uint32_t bufsz;
+ uint32_t codec_not_ready_bits, codec_idx, codec_found;
+ uint32_t blkcnt;
+ int registered_channels;
+
+ struct mtx *lock;
+ struct callout poll_timer;
+ int poll_ticks, polling;
};
-#define atiixp_rd(_sc, _reg) bus_space_read_4((_sc)->st, (_sc)->sh, _reg)
-#define atiixp_wr(_sc, _reg, _val) bus_space_write_4((_sc)->st, (_sc)->sh, _reg, _val)
+#define atiixp_rd(_sc, _reg) \
+ bus_space_read_4((_sc)->st, (_sc)->sh, _reg)
+#define atiixp_wr(_sc, _reg, _val) \
+ bus_space_write_4((_sc)->st, (_sc)->sh, _reg, _val)
#define atiixp_lock(_sc) snd_mtxlock((_sc)->lock)
#define atiixp_unlock(_sc) snd_mtxunlock((_sc)->lock)
#define atiixp_assert(_sc) snd_mtxassert((_sc)->lock)
static uint32_t atiixp_fmt_32bit[] = {
-AFMT_STEREO | AFMT_S16_LE,
-AFMT_STEREO | AFMT_S32_LE,
-0
+ AFMT_STEREO | AFMT_S16_LE,
+ AFMT_STEREO | AFMT_S32_LE,
+ 0
};
static uint32_t atiixp_fmt[] = {
-AFMT_STEREO | AFMT_S16_LE,
-0
+ AFMT_STEREO | AFMT_S16_LE,
+ 0
};
static struct pcmchan_caps atiixp_caps_32bit = {
-ATI_IXP_BASE_RATE,
-ATI_IXP_BASE_RATE,
-atiixp_fmt_32bit, 0
+ ATI_IXP_BASE_RATE,
+ ATI_IXP_BASE_RATE,
+ atiixp_fmt_32bit, 0
};
static struct pcmchan_caps atiixp_caps = {
-ATI_IXP_BASE_RATE,
-ATI_IXP_BASE_RATE,
-atiixp_fmt, 0
+ ATI_IXP_BASE_RATE,
+ ATI_IXP_BASE_RATE,
+ atiixp_fmt, 0
};
static const struct {
-uint16_t vendor;
-uint16_t devid;
-char *desc;
+ uint16_t vendor;
+ uint16_t devid;
+ char *desc;
} atiixp_hw[] = {
-{ ATI_VENDOR_ID, ATI_IXP_200_ID, "ATI IXP 200" },
-{ ATI_VENDOR_ID, ATI_IXP_300_ID, "ATI IXP 300" },
-{ ATI_VENDOR_ID, ATI_IXP_400_ID, "ATI IXP 400" },
+ { ATI_VENDOR_ID, ATI_IXP_200_ID, "ATI IXP 200" },
+ { ATI_VENDOR_ID, ATI_IXP_300_ID, "ATI IXP 300" },
+ { ATI_VENDOR_ID, ATI_IXP_400_ID, "ATI IXP 400" },
+ { ATI_VENDOR_ID, ATI_IXP_SB600_ID, "ATI IXP SB600" },
};
static void atiixp_enable_interrupts(struct atiixp_info *);
static void atiixp_disable_interrupts(struct atiixp_info *);
static void atiixp_reset_aclink(struct atiixp_info *);
-static void atiixp_flush_dma(struct atiixp_info *, struct atiixp_chinfo *);
-static void atiixp_enable_dma(struct atiixp_info *, struct atiixp_chinfo *);
-static void atiixp_disable_dma(struct atiixp_info *, struct atiixp_chinfo *);
+static void atiixp_flush_dma(struct atiixp_chinfo *);
+static void atiixp_enable_dma(struct atiixp_chinfo *);
+static void atiixp_disable_dma(struct atiixp_chinfo *);
static int atiixp_waitready_codec(struct atiixp_info *);
static int atiixp_rdcd(kobj_t, void *, int);
static int atiixp_wrcd(kobj_t, void *, int, uint32_t);
static void *atiixp_chan_init(kobj_t, void *, struct snd_dbuf *,
-struct pcm_channel *, int);
+ struct pcm_channel *, int);
static int atiixp_chan_setformat(kobj_t, void *, uint32_t);
static int atiixp_chan_setspeed(kobj_t, void *, uint32_t);
+static int atiixp_chan_setfragments(kobj_t, void *, uint32_t, uint32_t);
static int atiixp_chan_setblocksize(kobj_t, void *, uint32_t);
static void atiixp_buildsgdt(struct atiixp_chinfo *);
static int atiixp_chan_trigger(kobj_t, void *, int);
+static __inline uint32_t atiixp_dmapos(struct atiixp_chinfo *);
static int atiixp_chan_getptr(kobj_t, void *);
static struct pcmchan_caps *atiixp_chan_getcaps(kobj_t, void *);
@@ -187,941 +208,1220 @@
static int atiixp_pci_resume(device_t);
/*
-* ATI IXP helper functions
-*/
+ * ATI IXP helper functions
+ */
static void
atiixp_enable_interrupts(struct atiixp_info *sc)
{
-uint32_t value;
-
-/* clear all pending */
-atiixp_wr(sc, ATI_REG_ISR, 0xffffffff);
+ uint32_t value;
-/* enable all relevant interrupt sources we can handle */
-value = atiixp_rd(sc, ATI_REG_IER);
+ /* clear all pending */
+ atiixp_wr(sc, ATI_REG_ISR, 0xffffffff);
-value |= ATI_REG_IER_IO_STATUS_EN;
+ /* enable all relevant interrupt sources we can handle */
+ value = atiixp_rd(sc, ATI_REG_IER);
-/*
-* Disable / ignore internal xrun/spdf interrupt flags
-* since it doesn't interest us (for now).
-*/
-#if 0
-value |= ATI_REG_IER_IN_XRUN_EN;
-value |= ATI_REG_IER_OUT_XRUN_EN;
+ value |= ATI_REG_IER_IO_STATUS_EN;
+
+ /*
+ * Disable / ignore internal xrun/spdf interrupt flags
+ * since it doesn't interest us (for now).
+ */
+#if 1
+ value &= ~(ATI_REG_IER_IN_XRUN_EN | ATI_REG_IER_OUT_XRUN_EN |
+ ATI_REG_IER_SPDF_XRUN_EN | ATI_REG_IER_SPDF_STATUS_EN);
+#else
+ value |= ATI_REG_IER_IN_XRUN_EN;
+ value |= ATI_REG_IER_OUT_XRUN_EN;
-value |= ATI_REG_IER_SPDF_XRUN_EN;
-value |= ATI_REG_IER_SPDF_STATUS_EN;
+ value |= ATI_REG_IER_SPDF_XRUN_EN;
+ value |= ATI_REG_IER_SPDF_STATUS_EN;
#endif
-atiixp_wr(sc, ATI_REG_IER, value);
+ atiixp_wr(sc, ATI_REG_IER, value);
}
static void
atiixp_disable_interrupts(struct atiixp_info *sc)
{
-/* disable all interrupt sources */
-atiixp_wr(sc, ATI_REG_IER, 0);
+ /* disable all interrupt sources */
+ atiixp_wr(sc, ATI_REG_IER, 0);
-/* clear all pending */
-atiixp_wr(sc, ATI_REG_ISR, 0xffffffff);
+ /* clear all pending */
+ atiixp_wr(sc, ATI_REG_ISR, 0xffffffff);
}
static void
atiixp_reset_aclink(struct atiixp_info *sc)
{
-uint32_t value, timeout;
+ uint32_t value, timeout;
-/* if power is down, power it up */
-value = atiixp_rd(sc, ATI_REG_CMD);
-if (value & ATI_REG_CMD_POWERDOWN) {
-/* explicitly enable power */
-value &= ~ATI_REG_CMD_POWERDOWN;
-atiixp_wr(sc, ATI_REG_CMD, value);
-
-/* have to wait at least 10 usec for it to initialise */
-DELAY(20);
-};
-
-/* perform a soft reset */
-value = atiixp_rd(sc, ATI_REG_CMD);
-value |= ATI_REG_CMD_AC_SOFT_RESET;
-atiixp_wr(sc, ATI_REG_CMD, value);
-
-/* need to read the CMD reg and wait aprox. 10 usec to init */
-value = atiixp_rd(sc, ATI_REG_CMD);
-DELAY(20);
-
-/* clear soft reset flag again */
-value = atiixp_rd(sc, ATI_REG_CMD);
-value &= ~ATI_REG_CMD_AC_SOFT_RESET;
-atiixp_wr(sc, ATI_REG_CMD, value);
-
-/* check if the ac-link is working; reset device otherwise */
-timeout = 10;
-value = atiixp_rd(sc, ATI_REG_CMD);
-while (!(value & ATI_REG_CMD_ACLINK_ACTIVE)
-&& --timeout) {
+ /* if power is down, power it up */
+ value = atiixp_rd(sc, ATI_REG_CMD);
+ if (value & ATI_REG_CMD_POWERDOWN) {
+ /* explicitly enable power */
+ value &= ~ATI_REG_CMD_POWERDOWN;
+ atiixp_wr(sc, ATI_REG_CMD, value);
+
+ /* have to wait at least 10 usec for it to initialise */
+ DELAY(20);
+ }
+
+ /* perform a soft reset */
+ value = atiixp_rd(sc, ATI_REG_CMD);
+ value |= ATI_REG_CMD_AC_SOFT_RESET;
+ atiixp_wr(sc, ATI_REG_CMD, value);
+
+ /* need to read the CMD reg and wait aprox. 10 usec to init */
+ value = atiixp_rd(sc, ATI_REG_CMD);
+ DELAY(20);
+
+ /* clear soft reset flag again */
+ value = atiixp_rd(sc, ATI_REG_CMD);
+ value &= ~ATI_REG_CMD_AC_SOFT_RESET;
+ atiixp_wr(sc, ATI_REG_CMD, value);
+
+ /* check if the ac-link is working; reset device otherwise */
+ timeout = 10;
+ value = atiixp_rd(sc, ATI_REG_CMD);
+ while (!(value & ATI_REG_CMD_ACLINK_ACTIVE) && --timeout) {
#if 0
-device_printf(sc->dev, "not up; resetting aclink hardwaren");
+ device_printf(sc->dev, "not up; resetting aclink hardware\n");
#endif
-/* dip aclink reset but keep the acsync */
-value &= ~ATI_REG_CMD_AC_RESET;
-value |= ATI_REG_CMD_AC_SYNC;
-atiixp_wr(sc, ATI_REG_CMD, value);
-
-/* need to read CMD again and wait again (clocking in issue?) */
-value = atiixp_rd(sc, ATI_REG_CMD);
-DELAY(20);
-
-/* assert aclink reset again */
-value = atiixp_rd(sc, ATI_REG_CMD);
-value |= ATI_REG_CMD_AC_RESET;
-atiixp_wr(sc, ATI_REG_CMD, value);
+ /* dip aclink reset but keep the acsync */
+ value &= ~ATI_REG_CMD_AC_RESET;
+ value |= ATI_REG_CMD_AC_SYNC;
+ atiixp_wr(sc, ATI_REG_CMD, value);
+
+ /* need to read CMD again and wait again (clocking in issue?) */
+ value = atiixp_rd(sc, ATI_REG_CMD);
+ DELAY(20);
+
+ /* assert aclink reset again */
+ value = atiixp_rd(sc, ATI_REG_CMD);
+ value |= ATI_REG_CMD_AC_RESET;
+ atiixp_wr(sc, ATI_REG_CMD, value);
+
+ /* check if its active now */
+ value = atiixp_rd(sc, ATI_REG_CMD);
+ }
-/* check if its active now */
-value = atiixp_rd(sc, ATI_REG_CMD);
-};
-
-if (timeout == 0)
-device_printf(sc->dev, "giving up aclink resetn");
+ if (timeout == 0)
+ device_printf(sc->dev, "giving up aclink reset\n");
#if 0
-if (timeout != 10)
-device_printf(sc->dev, "aclink hardware reset successfuln");
+ if (timeout != 10)
+ device_printf(sc->dev, "aclink hardware reset successful\n");
#endif
-/* assert reset and sync for safety */
-value = atiixp_rd(sc, ATI_REG_CMD);
-value |= ATI_REG_CMD_AC_SYNC | ATI_REG_CMD_AC_RESET;
-atiixp_wr(sc, ATI_REG_CMD, value);
+ /* assert reset and sync for safety */
+ value = atiixp_rd(sc, ATI_REG_CMD);
+ value |= ATI_REG_CMD_AC_SYNC | ATI_REG_CMD_AC_RESET;
+ atiixp_wr(sc, ATI_REG_CMD, value);
}
static void
-atiixp_flush_dma(struct atiixp_info *sc, struct atiixp_chinfo *ch)
+atiixp_flush_dma(struct atiixp_chinfo *ch)
{
-atiixp_wr(sc, ATI_REG_FIFO_FLUSH, ch->flush_bit);
+ atiixp_wr(ch->parent, ATI_REG_FIFO_FLUSH, ch->flush_bit);
}
static void
-atiixp_enable_dma(struct atiixp_info *sc, struct atiixp_chinfo *ch)
+atiixp_enable_dma(struct atiixp_chinfo *ch)
{
-uint32_t value;
+ uint32_t value;
-value = atiixp_rd(sc, ATI_REG_CMD);
-if (!(value & ch->enable_bit)) {
-value |= ch->enable_bit;
-atiixp_wr(sc, ATI_REG_CMD, value);
-}
+ value = atiixp_rd(ch->parent, ATI_REG_CMD);
+ if (!(value & ch->enable_bit)) {
+ value |= ch->enable_bit;
+ atiixp_wr(ch->parent, ATI_REG_CMD, value);
+ }
}
-static void
-atiixp_disable_dma(struct atiixp_info *sc, struct atiixp_chinfo *ch)
+static void
+atiixp_disable_dma(struct atiixp_chinfo *ch)
{
-uint32_t value;
+ uint32_t value;
-value = atiixp_rd(sc, ATI_REG_CMD);
-if (value & ch->enable_bit) {
-value &= ~ch->enable_bit;
-atiixp_wr(sc, ATI_REG_CMD, value);
-}
+ value = atiixp_rd(ch->parent, ATI_REG_CMD);
+ if (value & ch->enable_bit) {
+ value &= ~ch->enable_bit;
+ atiixp_wr(ch->parent, ATI_REG_CMD, value);
+ }
}
/*
-* AC97 interface
-*/
+ * AC97 interface
+ */
static int
atiixp_waitready_codec(struct atiixp_info *sc)
{
-int timeout = 500;
+ int timeout = 500;
-do {
-if ((atiixp_rd(sc, ATI_REG_PHYS_OUT_ADDR) &
-ATI_REG_PHYS_OUT_ADDR_EN) == 0)
-return 0;
-DELAY(1);
-} while (timeout--);
+ do {
+ if ((atiixp_rd(sc, ATI_REG_PHYS_OUT_ADDR) &
+ ATI_REG_PHYS_OUT_ADDR_EN) == 0)
+ return (0);
+ DELAY(1);
+ } while (--timeout);
-return -1;
+ return (-1);
}
static int
atiixp_rdcd(kobj_t obj, void *devinfo, int reg)
{
-struct atiixp_info *sc = devinfo;
-uint32_t data;
-int timeout;
-
-if (atiixp_waitready_codec(sc))
-return -1;
-
-data = (reg << ATI_REG_PHYS_OUT_ADDR_SHIFT) |
-ATI_REG_PHYS_OUT_ADDR_EN |
-ATI_REG_PHYS_OUT_RW | sc->codec_idx;
-
-atiixp_wr(sc, ATI_REG_PHYS_OUT_ADDR, data);
-
-if (atiixp_waitready_codec(sc))
-return -1;
-
-timeout = 500;
-do {
-data = atiixp_rd(sc, ATI_REG_PHYS_IN_ADDR);
-if (data & ATI_REG_PHYS_IN_READ_FLAG)
-return data >> ATI_REG_PHYS_IN_DATA_SHIFT;
-DELAY(1);
-} while (timeout--);
+ struct atiixp_info *sc = devinfo;
+ uint32_t data;
+ int timeout;
+
+ if (atiixp_waitready_codec(sc))
+ return (-1);
+
+ data = (reg << ATI_REG_PHYS_OUT_ADDR_SHIFT) |
+ ATI_REG_PHYS_OUT_ADDR_EN | ATI_REG_PHYS_OUT_RW | sc->codec_idx;
+
+ atiixp_wr(sc, ATI_REG_PHYS_OUT_ADDR, data);
-if (reg < 0x7c)
-device_printf(sc->dev, "codec read timeout! (reg 0x%x)n", reg);
+ if (atiixp_waitready_codec(sc))
+ return (-1);
-return -1;
+ timeout = 500;
+ do {
+ data = atiixp_rd(sc, ATI_REG_PHYS_IN_ADDR);
+ if (data & ATI_REG_PHYS_IN_READ_FLAG)
+ return (data >> ATI_REG_PHYS_IN_DATA_SHIFT);
+ DELAY(1);
+ } while (--timeout);
+
+ if (reg < 0x7c)
+ device_printf(sc->dev, "codec read timeout! (reg 0x%x)\n", reg);
+
+ return (-1);
}
static int
atiixp_wrcd(kobj_t obj, void *devinfo, int reg, uint32_t data)
{
-struct atiixp_info *sc = devinfo;
+ struct atiixp_info *sc = devinfo;
-if (atiixp_waitready_codec(sc))
-return -1;
+ if (atiixp_waitready_codec(sc))
+ return (-1);
-data = (data << ATI_REG_PHYS_OUT_DATA_SHIFT) |
-(((uint32_t)reg) << ATI_REG_PHYS_OUT_ADDR_SHIFT) |
-ATI_REG_PHYS_OUT_ADDR_EN | sc->codec_idx;
+ data = (data << ATI_REG_PHYS_OUT_DATA_SHIFT) |
+ (((uint32_t)reg) << ATI_REG_PHYS_OUT_ADDR_SHIFT) |
+ ATI_REG_PHYS_OUT_ADDR_EN | sc->codec_idx;
-atiixp_wr(sc, ATI_REG_PHYS_OUT_ADDR, data);
+ atiixp_wr(sc, ATI_REG_PHYS_OUT_ADDR, data);
-return 0;
+ return (0);
}
static kobj_method_t atiixp_ac97_methods[] = {
-KOBJMETHOD(ac97_read, atiixp_rdcd),
-KOBJMETHOD(ac97_write, atiixp_wrcd),
-{ 0, 0 }
+ KOBJMETHOD(ac97_read, atiixp_rdcd),
+ KOBJMETHOD(ac97_write, atiixp_wrcd),
+ { 0, 0 }
};
AC97_DECLARE(atiixp_ac97);
/*
-* Playback / Record channel interface
-*/
+ * Playback / Record channel interface
+ */
static void *
atiixp_chan_init(kobj_t obj, void *devinfo, struct snd_dbuf *b,
-struct pcm_channel *c, int dir)
+ struct pcm_channel *c, int dir)
{
-struct atiixp_info *sc = devinfo;
-struct atiixp_chinfo *ch;
-int num;
-
-atiixp_lock(sc);
-
-if (dir == PCMDIR_PLAY) {
-ch = &sc->pch;
-ch->linkptr_bit = ATI_REG_OUT_DMA_LINKPTR;
-ch->enable_bit = ATI_REG_CMD_OUT_DMA_EN | ATI_REG_CMD_SEND_EN;
-ch->flush_bit = ATI_REG_FIFO_OUT_FLUSH;
-ch->dma_dt_cur_bit = ATI_REG_OUT_DMA_DT_CUR;
-/* Native 32bit playback working properly */
-ch->caps_32bit = 1;
-} else {
-ch = &sc->rch;
-ch->linkptr_bit = ATI_REG_IN_DMA_LINKPTR;
-ch->enable_bit = ATI_REG_CMD_IN_DMA_EN | ATI_REG_CMD_RECEIVE_EN;
-ch->flush_bit = ATI_REG_FIFO_IN_FLUSH;
-ch->dma_dt_cur_bit = ATI_REG_IN_DMA_DT_CUR;
-/* XXX Native 32bit recording appear to be broken */
-ch->caps_32bit = 1;
-}
-
-ch->buffer = b;
-ch->parent = sc;
-ch->channel = c;
-ch->dir = dir;
-ch->dma_segs = sc->dma_segs;
-
-atiixp_unlock(sc);
-
-if (sndbuf_alloc(ch->buffer, sc->parent_dmat, sc->bufsz) == -1)
-return NULL;
-
-atiixp_lock(sc);
-num = sc->registered_channels++;
-ch->sgd_table = &sc->sgd_table[num * ch->dma_segs];
-ch->sgd_addr = sc->sgd_addr +
-(num * ch->dma_segs * sizeof(struct atiixp_dma_op));
-atiixp_disable_dma(sc, ch);
-atiixp_unlock(sc);
+ struct atiixp_info *sc = devinfo;
+ struct atiixp_chinfo *ch;
+ int num;
+
+ atiixp_lock(sc);
+
+ if (dir == PCMDIR_PLAY) {
+ ch = &sc->pch;
+ ch->linkptr_bit = ATI_REG_OUT_DMA_LINKPTR;
+ ch->enable_bit = ATI_REG_CMD_OUT_DMA_EN | ATI_REG_CMD_SEND_EN;
+ ch->flush_bit = ATI_REG_FIFO_OUT_FLUSH;
+ ch->dt_cur_bit = ATI_REG_OUT_DMA_DT_CUR;
+ /* Native 32bit playback working properly */
+ ch->caps_32bit = 1;
+ } else {
+ ch = &sc->rch;
+ ch->linkptr_bit = ATI_REG_IN_DMA_LINKPTR;
+ ch->enable_bit = ATI_REG_CMD_IN_DMA_EN | ATI_REG_CMD_RECEIVE_EN;
+ ch->flush_bit = ATI_REG_FIFO_IN_FLUSH;
+ ch->dt_cur_bit = ATI_REG_IN_DMA_DT_CUR;
+ /* XXX Native 32bit recording appear to be broken */
+ ch->caps_32bit = 1;
+ }
+
+ ch->buffer = b;
+ ch->parent = sc;
+ ch->channel = c;
+ ch->dir = dir;
+ ch->blkcnt = sc->blkcnt;
+ ch->blksz = sc->bufsz / ch->blkcnt;
+
+ atiixp_unlock(sc);
+
+ if (sndbuf_alloc(ch->buffer, sc->parent_dmat, 0, sc->bufsz) == -1)
+ return (NULL);
+
+ atiixp_lock(sc);
+ num = sc->registered_channels++;
+ ch->sgd_table = &sc->sgd_table[num * ATI_IXP_DMA_CHSEGS_MAX];
+ ch->sgd_addr = sc->sgd_addr + (num * ATI_IXP_DMA_CHSEGS_MAX *
+ sizeof(struct atiixp_dma_op));
+ atiixp_disable_dma(ch);
+ atiixp_unlock(sc);
-return ch;
+ return (ch);
}
static int
atiixp_chan_setformat(kobj_t obj, void *data, uint32_t format)
{
-struct atiixp_chinfo *ch = data;
-struct atiixp_info *sc = ch->parent;
-uint32_t value;
-
-atiixp_lock(sc);
-if (ch->dir == PCMDIR_REC) {
-value = atiixp_rd(sc, ATI_REG_CMD);
-value &= ~ATI_REG_CMD_INTERLEAVE_IN;
-if ((format & AFMT_32BIT) == 0)
-value |= ATI_REG_CMD_INTERLEAVE_IN;
-atiixp_wr(sc, ATI_REG_CMD, value);
-} else {
-value = atiixp_rd(sc, ATI_REG_OUT_DMA_SLOT);
-value &= ~ATI_REG_OUT_DMA_SLOT_MASK;
-/* We do not have support for more than 2 channels, _yet_. */
-value |= ATI_REG_OUT_DMA_SLOT_BIT(3) |
-ATI_REG_OUT_DMA_SLOT_BIT(4);
-value |= 0x04 << ATI_REG_OUT_DMA_THRESHOLD_SHIFT;
-atiixp_wr(sc, ATI_REG_OUT_DMA_SLOT, value);
-value = atiixp_rd(sc, ATI_REG_CMD);
-value &= ~ATI_REG_CMD_INTERLEAVE_OUT;
-if ((format & AFMT_32BIT) == 0)
-value |= ATI_REG_CMD_INTERLEAVE_OUT;
-atiixp_wr(sc, ATI_REG_CMD, value);
-value = atiixp_rd(sc, ATI_REG_6CH_REORDER);
-value &= ~ATI_REG_6CH_REORDER_EN;
-atiixp_wr(sc, ATI_REG_6CH_REORDER, value);
-}
-ch->fmt = format;
-atiixp_unlock(sc);
+ struct atiixp_chinfo *ch = data;
+ struct atiixp_info *sc = ch->parent;
+ uint32_t value;
+
+ atiixp_lock(sc);
+ if (ch->dir == PCMDIR_REC) {
+ value = atiixp_rd(sc, ATI_REG_CMD);
+ value &= ~ATI_REG_CMD_INTERLEAVE_IN;
+ if ((format & AFMT_32BIT) == 0)
+ value |= ATI_REG_CMD_INTERLEAVE_IN;
+ atiixp_wr(sc, ATI_REG_CMD, value);
+ } else {
+ value = atiixp_rd(sc, ATI_REG_OUT_DMA_SLOT);
+ value &= ~ATI_REG_OUT_DMA_SLOT_MASK;
+ /* We do not have support for more than 2 channels, _yet_. */
+ value |= ATI_REG_OUT_DMA_SLOT_BIT(3) |
+ ATI_REG_OUT_DMA_SLOT_BIT(4);
+ value |= 0x04 << ATI_REG_OUT_DMA_THRESHOLD_SHIFT;
+ atiixp_wr(sc, ATI_REG_OUT_DMA_SLOT, value);
+ value = atiixp_rd(sc, ATI_REG_CMD);
+ value &= ~ATI_REG_CMD_INTERLEAVE_OUT;
+ if ((format & AFMT_32BIT) == 0)
+ value |= ATI_REG_CMD_INTERLEAVE_OUT;
+ atiixp_wr(sc, ATI_REG_CMD, value);
+ value = atiixp_rd(sc, ATI_REG_6CH_REORDER);
+ value &= ~ATI_REG_6CH_REORDER_EN;
+ atiixp_wr(sc, ATI_REG_6CH_REORDER, value);
+ }
+ ch->fmt = format;
+ atiixp_unlock(sc);
-return 0;
+ return (0);
}
static int
atiixp_chan_setspeed(kobj_t obj, void *data, uint32_t spd)
{
-/* XXX We're supposed to do VRA/DRA processing right here */
-return ATI_IXP_BASE_RATE;
+ /* XXX We're supposed to do VRA/DRA processing right here */
+ return (ATI_IXP_BASE_RATE);
}
static int
-atiixp_chan_setblocksize(kobj_t obj, void *data, uint32_t blksz)
+atiixp_chan_setfragments(kobj_t obj, void *data,
+ uint32_t blksz, uint32_t blkcnt)
{
-struct atiixp_chinfo *ch = data;
-struct atiixp_info *sc = ch->parent;
+ struct atiixp_chinfo *ch = data;
+ struct atiixp_info *sc = ch->parent;
+
+ blksz &= ATI_IXP_BLK_ALIGN;
-if (blksz > (sc->bufsz / ch->dma_segs))
-blksz = sc->bufsz / ch->dma_segs;
+ if (blksz > (sndbuf_getmaxsize(ch->buffer) / ATI_IXP_DMA_CHSEGS_MIN))
+ blksz = sndbuf_getmaxsize(ch->buffer) / ATI_IXP_DMA_CHSEGS_MIN;
+ if (blksz < ATI_IXP_BLK_MIN)
+ blksz = ATI_IXP_BLK_MIN;
+ if (blkcnt > ATI_IXP_DMA_CHSEGS_MAX)
+ blkcnt = ATI_IXP_DMA_CHSEGS_MAX;
+ if (blkcnt < ATI_IXP_DMA_CHSEGS_MIN)
+ blkcnt = ATI_IXP_DMA_CHSEGS_MIN;
+
+ while ((blksz * blkcnt) > sndbuf_getmaxsize(ch->buffer)) {
+ if ((blkcnt >> 1) >= ATI_IXP_DMA_CHSEGS_MIN)
+ blkcnt >>= 1;
+ else if ((blksz >> 1) >= ATI_IXP_BLK_MIN)
+ blksz >>= 1;
+ else
+ break;
+ }
+
+ if ((sndbuf_getblksz(ch->buffer) != blksz ||
+ sndbuf_getblkcnt(ch->buffer) != blkcnt) &&
+ sndbuf_resize(ch->buffer, blkcnt, blksz) != 0)
+ device_printf(sc->dev, "%s: failed blksz=%u blkcnt=%u\n",
+ __func__, blksz, blkcnt);
-sndbuf_resize(ch->buffer, ch->dma_segs, blksz);
+ ch->blksz = sndbuf_getblksz(ch->buffer);
+ ch->blkcnt = sndbuf_getblkcnt(ch->buffer);
-return sndbuf_getblksz(ch->buffer);
+ return (1);
+}
+
+static int
+atiixp_chan_setblocksize(kobj_t obj, void *data, uint32_t blksz)
+{
+ struct atiixp_chinfo *ch = data;
+ struct atiixp_info *sc = ch->parent;
+
+ atiixp_chan_setfragments(obj, data, blksz, sc->blkcnt);
+
+ return (ch->blksz);
}
static void
atiixp_buildsgdt(struct atiixp_chinfo *ch)
{
-uint32_t addr, blksz;
-int i;
+ struct atiixp_info *sc = ch->parent;
+ uint32_t addr, blksz, blkcnt;
+ int i;
+
+ addr = sndbuf_getbufaddr(ch->buffer);
+
+ if (sc->polling != 0) {
+ blksz = ch->blksz * ch->blkcnt;
+ blkcnt = 1;
+ } else {
+ blksz = ch->blksz;
+ blkcnt = ch->blkcnt;
+ }
+
+ for (i = 0; i < blkcnt; i++) {
+ ch->sgd_table[i].addr = htole32(addr + (i * blksz));
+ ch->sgd_table[i].status = htole16(0);
+ ch->sgd_table[i].size = htole16(blksz >> 2);
+ ch->sgd_table[i].next = htole32((uint32_t)ch->sgd_addr +
+ (((i + 1) % blkcnt) * sizeof(struct atiixp_dma_op)));
+ }
+}
+
+static __inline uint32_t
+atiixp_dmapos(struct atiixp_chinfo *ch)
+{
+ struct atiixp_info *sc = ch->parent;
+ uint32_t reg, addr, sz, retry;
+ volatile uint32_t ptr;
+
+ reg = ch->dt_cur_bit;
+ addr = sndbuf_getbufaddr(ch->buffer);
+ sz = ch->blkcnt * ch->blksz;
+ retry = ATI_IXP_DMA_RETRY_MAX;
+
+ do {
+ ptr = atiixp_rd(sc, reg);
+ if (ptr < addr)
+ continue;
+ ptr -= addr;
+ if (ptr < sz) {
+#if 0
+#ifdef ATI_IXP_DEBUG
+ if ((ptr & ~(ch->blksz - 1)) != ch->ptr) {
+ uint32_t delta;
+
+ delta = (sz + ptr - ch->prevptr) % sz;
+#ifndef ATI_IXP_DEBUG_VERBOSE
+ if (delta < ch->blksz)
+#endif
+ device_printf(sc->dev,
+ "PCMDIR_%s: incoherent DMA "
+ "prevptr=%u ptr=%u "
+ "ptr=%u blkcnt=%u "
+ "[delta=%u != blksz=%u] "
+ "(%s)\n",
+ (ch->dir == PCMDIR_PLAY) ?
+ "PLAY" : "REC",
+ ch->prevptr, ptr,
+ ch->ptr, ch->blkcnt,
+ delta, ch->blksz,
+ (delta < ch->blksz) ?
+ "OVERLAPPED!" : "Ok");
+ ch->ptr = ptr & ~(ch->blksz - 1);
+ }
+ ch->prevptr = ptr;
+#endif
+#endif
+ return (ptr);
+ }
+ } while (--retry);
+
+ device_printf(sc->dev, "PCMDIR_%s: invalid DMA pointer ptr=%u\n",
+ (ch->dir == PCMDIR_PLAY) ? "PLAY" : "REC", ptr);
+
+ return (0);
+}
+
+static __inline int
+atiixp_poll_channel(struct atiixp_chinfo *ch)
+{
+ uint32_t sz, delta;
+ volatile uint32_t ptr;
+
+ if (!(ch->flags & ATI_IXP_CHN_RUNNING))
+ return (0);
+
+ sz = ch->blksz * ch->blkcnt;
+ ptr = atiixp_dmapos(ch);
+ ch->ptr = ptr;
+ ptr %= sz;
+ ptr &= ~(ch->blksz - 1);
+ delta = (sz + ptr - ch->prevptr) % sz;
+
+ if (delta < ch->blksz)
+ return (0);
-addr = sndbuf_getbufaddr(ch->buffer);
-blksz = sndbuf_getblksz(ch->buffer);
+ ch->prevptr = ptr;
-for (i = 0; i < ch->dma_segs; i++) {
-ch->sgd_table[i].addr = htole32(addr + (i * blksz));
-ch->sgd_table[i].status = htole16(0);
-ch->sgd_table[i].size = htole16(blksz >> 2);
-ch->sgd_table[i].next = htole32((uint32_t)ch->sgd_addr +
-(((i + 1) % ch->dma_segs) *
-sizeof(struct atiixp_dma_op)));
+ return (1);
}
+
+#define atiixp_chan_active(sc) (((sc)->pch.flags | (sc)->rch.flags) & \
+ ATI_IXP_CHN_RUNNING)
+
+static void
+atiixp_poll_callback(void *arg)
+{
+ struct atiixp_info *sc = arg;
+ uint32_t trigger = 0;
+
+ if (sc == NULL)
+ return;
+
+ atiixp_lock(sc);
+ if (sc->polling == 0 || atiixp_chan_active(sc) == 0) {
+ atiixp_unlock(sc);
+ return;
+ }
+
+ trigger |= (atiixp_poll_channel(&sc->pch) != 0) ? 1 : 0;
+ trigger |= (atiixp_poll_channel(&sc->rch) != 0) ? 2 : 0;
+
+ /* XXX */
+ callout_reset(&sc->poll_timer, 1/*sc->poll_ticks*/,
+ atiixp_poll_callback, sc);
+
+ atiixp_unlock(sc);
+
+ if (trigger & 1)
+ chn_intr(sc->pch.channel);
+ if (trigger & 2)
+ chn_intr(sc->rch.channel);
}
static int
atiixp_chan_trigger(kobj_t obj, void *data, int go)
{
-struct atiixp_chinfo *ch = data;
-struct atiixp_info *sc = ch->parent;
-uint32_t value;
-
-atiixp_lock(sc);
-
-switch (go) {
-case PCMTRIG_START:
-atiixp_flush_dma(sc, ch);
-atiixp_buildsgdt(ch);
-atiixp_wr(sc, ch->linkptr_bit, 0);
-atiixp_enable_dma(sc, ch);
-atiixp_wr(sc, ch->linkptr_bit,
-(uint32_t)ch->sgd_addr | ATI_REG_LINKPTR_EN);
-break;
-case PCMTRIG_STOP:
-case PCMTRIG_ABORT:
-atiixp_disable_dma(sc, ch);
-atiixp_flush_dma(sc, ch);
-break;
-default:
-atiixp_unlock(sc);
-return 0;
-break;
-}
-
-/* Update bus busy status */
-value = atiixp_rd(sc, ATI_REG_IER);
-if (atiixp_rd(sc, ATI_REG_CMD) & (
-ATI_REG_CMD_SEND_EN | ATI_REG_CMD_RECEIVE_EN |
-ATI_REG_CMD_SPDF_OUT_EN))
-value |= ATI_REG_IER_SET_BUS_BUSY;
-else
-value &= ~ATI_REG_IER_SET_BUS_BUSY;
-atiixp_wr(sc, ATI_REG_IER, value);
+ struct atiixp_chinfo *ch = data;
+ struct atiixp_info *sc = ch->parent;
+ uint32_t value;
+ int pollticks;
+
+ if (!PCMTRIG_COMMON(go))
+ return (0);
+
+ atiixp_lock(sc);
+
+ switch (go) {
+ case PCMTRIG_START:
+ atiixp_flush_dma(ch);
+ atiixp_buildsgdt(ch);
+ atiixp_wr(sc, ch->linkptr_bit, 0);
+ atiixp_enable_dma(ch);
+ atiixp_wr(sc, ch->linkptr_bit,
+ (uint32_t)ch->sgd_addr | ATI_REG_LINKPTR_EN);
+ if (sc->polling != 0) {
+ ch->ptr = 0;
+ ch->prevptr = 0;
+ pollticks = ((uint64_t)hz * ch->blksz) /
+ ((uint64_t)sndbuf_getbps(ch->buffer) *
+ sndbuf_getspd(ch->buffer));
+ pollticks >>= 2;
+ if (pollticks > hz)
+ pollticks = hz;
+ if (pollticks < 1)
+ pollticks = 1;
+ if (atiixp_chan_active(sc) == 0 ||
+ pollticks < sc->poll_ticks) {
+ if (bootverbose) {
+ if (atiixp_chan_active(sc) == 0)
+ device_printf(sc->dev,
+ "%s: pollticks=%d\n",
+ __func__, pollticks);
+ else
+ device_printf(sc->dev,
+ "%s: pollticks %d -> %d\n",
+ __func__, sc->poll_ticks,
+ pollticks);
+ }
+ sc->poll_ticks = pollticks;
+ callout_reset(&sc->poll_timer, 1,
+ atiixp_poll_callback, sc);
+ }
+ }
+ ch->flags |= ATI_IXP_CHN_RUNNING;
+ break;
+ case PCMTRIG_STOP:
+ case PCMTRIG_ABORT:
+ atiixp_disable_dma(ch);
+ atiixp_flush_dma(ch);
+ ch->flags &= ~ATI_IXP_CHN_RUNNING;
+ if (sc->polling != 0) {
+ if (atiixp_chan_active(sc) == 0) {
+ callout_stop(&sc->poll_timer);
+ sc->poll_ticks = 1;
+ } else {
+ if (sc->pch.flags & ATI_IXP_CHN_RUNNING)
+ ch = &sc->pch;
+ else
+ ch = &sc->rch;
+ pollticks = ((uint64_t)hz * ch->blksz) /
+ ((uint64_t)sndbuf_getbps(ch->buffer) *
+ sndbuf_getspd(ch->buffer));
+ pollticks >>= 2;
+ if (pollticks > hz)
+ pollticks = hz;
+ if (pollticks < 1)
+ pollticks = 1;
+ if (pollticks > sc->poll_ticks) {
+ if (bootverbose)
+ device_printf(sc->dev,
+ "%s: pollticks %d -> %d\n",
+ __func__, sc->poll_ticks,
+ pollticks);
+ sc->poll_ticks = pollticks;
+ callout_reset(&sc->poll_timer,
+ 1, atiixp_poll_callback,
+ sc);
+ }
+ }
+ }
+ break;
+ default:
+ atiixp_unlock(sc);
+ return (0);
+ break;
+ }
+
+ /* Update bus busy status */
+ value = atiixp_rd(sc, ATI_REG_IER);
+ if (atiixp_rd(sc, ATI_REG_CMD) & (ATI_REG_CMD_SEND_EN |
+ ATI_REG_CMD_RECEIVE_EN | ATI_REG_CMD_SPDF_OUT_EN))
+ value |= ATI_REG_IER_SET_BUS_BUSY;
+ else
+ value &= ~ATI_REG_IER_SET_BUS_BUSY;
+ atiixp_wr(sc, ATI_REG_IER, value);
-atiixp_unlock(sc);
+ atiixp_unlock(sc);
-return 0;
+ return (0);
}
static int
atiixp_chan_getptr(kobj_t obj, void *data)
{
-struct atiixp_chinfo *ch = data;
-struct atiixp_info *sc = ch->parent;
-uint32_t addr, align, retry, sz;
-volatile uint32_t ptr;
-
-addr = sndbuf_getbufaddr(ch->buffer);
-align = (ch->fmt & AFMT_32BIT) ? 7 : 3;
-retry = 100;
-sz = sndbuf_getblksz(ch->buffer) * ch->dma_segs;
-
-atiixp_lock(sc);
-do {
-ptr = atiixp_rd(sc, ch->dma_dt_cur_bit);
-if (ptr < addr)
-continue;
-ptr -= addr;
-if (ptr < sz && !(ptr & align))
-break;
-} while (--retry);
-atiixp_unlock(sc);
-
-#if 0
-if (retry != 100) {
-device_printf(sc->dev,
-"%saligned hwptr: dir=PCMDIR_%s ptr=%u fmt=0x%08x retry=%dn",
-(ptr & align) ? "un" : "",
-(ch->dir == PCMDIR_PLAY) ? "PLAY" : "REC", ptr,
-ch->fmt, 100 - retry);
-}
-#endif
+ struct atiixp_chinfo *ch = data;
+ struct atiixp_info *sc = ch->parent;
+ uint32_t ptr;
+
+ atiixp_lock(sc);
+ if (sc->polling != 0)
+ ptr = ch->ptr;
+ else
+ ptr = atiixp_dmapos(ch);
+ atiixp_unlock(sc);
-return (retry > 0) ? ptr : 0;
+ return (ptr);
}
static struct pcmchan_caps *
atiixp_chan_getcaps(kobj_t obj, void *data)
{
-struct atiixp_chinfo *ch = data;
+ struct atiixp_chinfo *ch = data;
-if (ch->caps_32bit)
-return &atiixp_caps_32bit;
-return &atiixp_caps;
+ if (ch->caps_32bit)
+ return (&atiixp_caps_32bit);
+ return (&atiixp_caps);
}
static kobj_method_t atiixp_chan_methods[] = {
-KOBJMETHOD(channel_init, atiixp_chan_init),
-KOBJMETHOD(channel_setformat, atiixp_chan_setformat),
-KOBJMETHOD(channel_setspeed, atiixp_chan_setspeed),
-KOBJMETHOD(channel_setblocksize, atiixp_chan_setblocksize),
-KOBJMETHOD(channel_trigger, atiixp_chan_trigger),
-KOBJMETHOD(channel_getptr, atiixp_chan_getptr),
-KOBJMETHOD(channel_getcaps, atiixp_chan_getcaps),
-{ 0, 0 }
+ KOBJMETHOD(channel_init, atiixp_chan_init),
+ KOBJMETHOD(channel_setformat, atiixp_chan_setformat),
+ KOBJMETHOD(channel_setspeed, atiixp_chan_setspeed),
+ KOBJMETHOD(channel_setblocksize, atiixp_chan_setblocksize),
+ KOBJMETHOD(channel_setfragments, atiixp_chan_setfragments),
+ KOBJMETHOD(channel_trigger, atiixp_chan_trigger),
+ KOBJMETHOD(channel_getptr, atiixp_chan_getptr),
+ KOBJMETHOD(channel_getcaps, atiixp_chan_getcaps),
+ { 0, 0 }
};
CHANNEL_DECLARE(atiixp_chan);
/*
-* PCI driver interface
-*/
+ * PCI driver interface
+ */
static void
atiixp_intr(void *p)
{
-struct atiixp_info *sc = p;
-uint32_t status, enable, detected_codecs;
-
-atiixp_lock(sc);
-status = atiixp_rd(sc, ATI_REG_ISR);
-
-if (status == 0) {
-atiixp_unlock(sc);
-return;
-}
-
-if ((status & ATI_REG_ISR_IN_STATUS) && sc->rch.channel) {
-atiixp_unlock(sc);
-chn_intr(sc->rch.channel);
-atiixp_lock(sc);
-}
-if ((status & ATI_REG_ISR_OUT_STATUS) && sc->pch.channel) {
-atiixp_unlock(sc);
-chn_intr(sc->pch.channel);
-atiixp_lock(sc);
-}
+ struct atiixp_info *sc = p;
+ uint32_t status, enable, detected_codecs;
+ uint32_t trigger = 0;
+
+ atiixp_lock(sc);
+ if (sc->polling != 0) {
+ atiixp_unlock(sc);
+ return;
+ }
+ status = atiixp_rd(sc, ATI_REG_ISR);
+
+ if (status == 0) {
+ atiixp_unlock(sc);
+ return;
+ }
+
+ if ((status & ATI_REG_ISR_OUT_STATUS) &&
+ (sc->pch.flags & ATI_IXP_CHN_RUNNING))
+ trigger |= 1;
+ if ((status & ATI_REG_ISR_IN_STATUS) &&
+ (sc->rch.flags & ATI_IXP_CHN_RUNNING))
+ trigger |= 2;
#if 0
-if (status & ATI_REG_ISR_IN_XRUN) {
-device_printf(sc->dev,
-"Recieve IN XRUN interruptn");
-}
-if (status & ATI_REG_ISR_OUT_XRUN) {
-device_printf(sc->dev,
-"Recieve OUT XRUN interruptn");
-}
+ if (status & ATI_REG_ISR_IN_XRUN) {
+ device_printf(sc->dev,
+ "Recieve IN XRUN interrupt\n");
+ }
+ if (status & ATI_REG_ISR_OUT_XRUN) {
+ device_printf(sc->dev,
+ "Recieve OUT XRUN interrupt\n");
+ }
#endif
-if (status & CODEC_CHECK_BITS) {
-/* mark missing codecs as not ready */
-detected_codecs = status & CODEC_CHECK_BITS;
-sc->codec_not_ready_bits |= detected_codecs;
-
-/* disable detected interupt sources */
-enable = atiixp_rd(sc, ATI_REG_IER);
-enable &= ~detected_codecs;
-atiixp_wr(sc, ATI_REG_IER, enable);
-}
-
-/* acknowledge */
-atiixp_wr(sc, ATI_REG_ISR, status);
-atiixp_unlock(sc);
+ if (status & CODEC_CHECK_BITS) {
+ /* mark missing codecs as not ready */
+ detected_codecs = status & CODEC_CHECK_BITS;
+ sc->codec_not_ready_bits |= detected_codecs;
+
+ /* disable detected interrupt sources */
+ enable = atiixp_rd(sc, ATI_REG_IER);
+ enable &= ~detected_codecs;
+ atiixp_wr(sc, ATI_REG_IER, enable);
+ wakeup(sc);
+ }
+
+ /* acknowledge */
+ atiixp_wr(sc, ATI_REG_ISR, status);
+ atiixp_unlock(sc);
+
+ if (trigger & 1)
+ chn_intr(sc->pch.channel);
+ if (trigger & 2)
+ chn_intr(sc->rch.channel);
}
static void
atiixp_dma_cb(void *p, bus_dma_segment_t *bds, int a, int b)
{
-struct atiixp_info *sc = (struct atiixp_info *)p;
-sc->sgd_addr = bds->ds_addr;
+ struct atiixp_info *sc = (struct atiixp_info *)p;
+ sc->sgd_addr = bds->ds_addr;
}
static void
atiixp_chip_pre_init(struct atiixp_info *sc)
{
-uint32_t value;
+ uint32_t value;
-atiixp_lock(sc);
+ atiixp_lock(sc);
-/* disable interrupts */
-atiixp_disable_interrupts(sc);
+ /* disable interrupts */
+ atiixp_disable_interrupts(sc);
-/* clear all DMA enables (preserving rest of settings) */
-value = atiixp_rd(sc, ATI_REG_CMD);
-value &= ~(ATI_REG_CMD_IN_DMA_EN | ATI_REG_CMD_OUT_DMA_EN |
-ATI_REG_CMD_SPDF_OUT_EN );
-atiixp_wr(sc, ATI_REG_CMD, value);
+ /* clear all DMA enables (preserving rest of settings) */
+ value = atiixp_rd(sc, ATI_REG_CMD);
+ value &= ~(ATI_REG_CMD_IN_DMA_EN | ATI_REG_CMD_OUT_DMA_EN |
+ ATI_REG_CMD_SPDF_OUT_EN );
+ atiixp_wr(sc, ATI_REG_CMD, value);
-/* reset aclink */
-atiixp_reset_aclink(sc);
+ /* reset aclink */
+ atiixp_reset_aclink(sc);
-sc->codec_not_ready_bits = 0;
+ sc->codec_not_ready_bits = 0;
-/* enable all codecs to interrupt as well as the new frame interrupt */
-atiixp_wr(sc, ATI_REG_IER, CODEC_CHECK_BITS);
+ /* enable all codecs to interrupt as well as the new frame interrupt */
+ atiixp_wr(sc, ATI_REG_IER, CODEC_CHECK_BITS);
-atiixp_unlock(sc);
+ atiixp_unlock(sc);
}
-static void
-atiixp_chip_post_init(void *arg)
+#ifdef SND_DYNSYSCTL
+static int
+sysctl_atiixp_polling(SYSCTL_HANDLER_ARGS)
{
-struct atiixp_info *sc = (struct atiixp_info *)arg;
-uint32_t subdev;
-int i, timeout, found;
-char status[SND_STATUSLEN];
-
-atiixp_lock(sc);
-
-if (sc->delayed_attach.ich_func) {
-config_intrhook_disestablish(&sc->delayed_attach);
-sc->delayed_attach.ich_func = NULL;
-}
-
-/* wait for the interrupts to happen */
-timeout = 100;
-while (--timeout) {
-msleep(sc, sc->lock, PWAIT, "ixpslp", 1);
-if (sc->codec_not_ready_bits)
-break;
-}
-
-atiixp_disable_interrupts(sc);
-
-if (timeout == 0) {
-device_printf(sc->dev,
-"WARNING: timeout during codec detection; "
-"codecs might be present but haven't interruptedn");
-atiixp_unlock(sc);
-goto postinitbad;
-}
-
-found = 0;
-
-/*
-* ATI IXP can have upto 3 codecs, but single codec should be
-* suffice for now.
-*/
-if (!(sc->codec_not_ready_bits &
-ATI_REG_ISR_CODEC0_NOT_READY)) {
-/* codec 0 present */
-sc->codec_found++;
-sc->codec_idx = 0;
-found++;
-}
-
-if (!(sc->codec_not_ready_bits &
-ATI_REG_ISR_CODEC1_NOT_READY)) {
-/* codec 1 present */
-sc->codec_found++;
-}
-
-if (!(sc->codec_not_ready_bits &
-ATI_REG_ISR_CODEC2_NOT_READY)) {
-/* codec 2 present */
-sc->codec_found++;
-}
-
-atiixp_unlock(sc);
-
-if (found == 0)
-goto postinitbad;
-
-/* create/init mixer */
-sc->codec = AC97_CREATE(sc->dev, sc, atiixp_ac97);
-if (sc->codec == NULL)
-goto postinitbad;
+ struct atiixp_info *sc;
+ device_t dev;
+ int err, val;
+
+ dev = oidp->oid_arg1;
+ sc = pcm_getdevinfo(dev);
+ if (sc == NULL)
+ return (EINVAL);
+ atiixp_lock(sc);
+ val = sc->polling;
+ atiixp_unlock(sc);
+ err = sysctl_handle_int(oidp, &val, 0, req);
+
+ if (err || req->newptr == NULL)
+ return (err);
+ if (val < 0 || val > 1)
+ return (EINVAL);
+
+ atiixp_lock(sc);
+ if (val != sc->polling) {
+ if (atiixp_chan_active(sc) != 0)
+ err = EBUSY;
+ else if (val == 0) {
+ atiixp_enable_interrupts(sc);
+ sc->polling = 0;
+ DELAY(1000);
+ } else {
+ atiixp_disable_interrupts(sc);
+ sc->polling = 1;
+ DELAY(1000);
+ }
+ }
+ atiixp_unlock(sc);
-subdev = (pci_get_subdevice(sc->dev) << 16) | pci_get_subvendor(sc->dev);
-switch (subdev) {
-case 0x11831043: /* ASUS A6R */
-case 0x2043161f: /* Maxselect x710s - http://maxselect.ru/ */
-ac97_setflags(sc->codec, ac97_getflags(sc->codec) | AC97_F_EAPD_INV);
-break;
-default:
-break;
+ return (err);
}
+#endif
-mixer_init(sc->dev, ac97_getmixerclass(), sc->codec);
-
-if (pcm_register(sc->dev, sc, ATI_IXP_NPCHAN, ATI_IXP_NRCHAN))
-goto postinitbad;
-
-for (i = 0; i < ATI_IXP_NPCHAN; i++)
-pcm_addchan(sc->dev, PCMDIR_PLAY, &atiixp_chan_class, sc);
-for (i = 0; i < ATI_IXP_NRCHAN; i++)
-pcm_addchan(sc->dev, PCMDIR_REC, &atiixp_chan_class, sc);
-
-snprintf(status, SND_STATUSLEN, "at memory 0x%lx irq %ld %s",
-rman_get_start(sc->reg), rman_get_start(sc->irq),
-PCM_KLDSTRING(snd_atiixp));
-
-pcm_setstatus(sc->dev, status);
+static void
+atiixp_chip_post_init(void *arg)
+{
+ struct atiixp_info *sc = (struct atiixp_info *)arg;
+ uint32_t subdev;
+ int i, timeout, found, polling;
+ char status[SND_STATUSLEN];
+
+ atiixp_lock(sc);
+
+ if (sc->delayed_attach.ich_func) {
+ config_intrhook_disestablish(&sc->delayed_attach);
+ sc->delayed_attach.ich_func = NULL;
+ }
+
+ polling = sc->polling;
+ sc->polling = 0;
+
+ timeout = 10;
+ if (sc->codec_not_ready_bits == 0) {
+ /* wait for the interrupts to happen */
+ do {
+ msleep(sc, sc->lock, PWAIT, "ixpslp", max(hz / 10, 1));
+ if (sc->codec_not_ready_bits != 0)
+ break;
+ } while (--timeout);
+ }
+
+ sc->polling = polling;
+ atiixp_disable_interrupts(sc);
+
+ if (sc->codec_not_ready_bits == 0 && timeout == 0) {
+ device_printf(sc->dev,
+ "WARNING: timeout during codec detection; "
+ "codecs might be present but haven't interrupted\n");
+ atiixp_unlock(sc);
+ goto postinitbad;
+ }
+
+ found = 0;
+
+ /*
+ * ATI IXP can have upto 3 codecs, but single codec should be
+ * suffice for now.
+ */
+ if (!(sc->codec_not_ready_bits & ATI_REG_ISR_CODEC0_NOT_READY)) {
+ /* codec 0 present */
+ sc->codec_found++;
+ sc->codec_idx = 0;
+ found++;
+ }
+
+ if (!(sc->codec_not_ready_bits & ATI_REG_ISR_CODEC1_NOT_READY)) {
+ /* codec 1 present */
+ sc->codec_found++;
+ }
+
+ if (!(sc->codec_not_ready_bits & ATI_REG_ISR_CODEC2_NOT_READY)) {
+ /* codec 2 present */
+ sc->codec_found++;
+ }
+
+ atiixp_unlock(sc);
+
+ if (found == 0)
+ goto postinitbad;
+
+ /* create/init mixer */
+ sc->codec = AC97_CREATE(sc->dev, sc, atiixp_ac97);
+ if (sc->codec == NULL)
+ goto postinitbad;
+
+ subdev = (pci_get_subdevice(sc->dev) << 16) |
+ pci_get_subvendor(sc->dev);
+ switch (subdev) {
+ case 0x11831043: /* ASUS A6R */
+ case 0x2043161f: /* Maxselect x710s - http://maxselect.ru/ */
+ ac97_setflags(sc->codec, ac97_getflags(sc->codec) |
+ AC97_F_EAPD_INV);
+ break;
+ default:
+ break;
+ }
+
+ mixer_init(sc->dev, ac97_getmixerclass(), sc->codec);
+
+ if (pcm_register(sc->dev, sc, ATI_IXP_NPCHAN, ATI_IXP_NRCHAN))
+ goto postinitbad;
+
+ for (i = 0; i < ATI_IXP_NPCHAN; i++)
+ pcm_addchan(sc->dev, PCMDIR_PLAY, &atiixp_chan_class, sc);
+ for (i = 0; i < ATI_IXP_NRCHAN; i++)
+ pcm_addchan(sc->dev, PCMDIR_REC, &atiixp_chan_class, sc);
+
+#ifdef SND_DYNSYSCTL
+ SYSCTL_ADD_PROC(device_get_sysctl_ctx(sc->dev),
+ SYSCTL_CHILDREN(device_get_sysctl_tree(sc->dev)), OID_AUTO,
+ "polling", CTLTYPE_INT | CTLFLAG_RW, sc->dev, sizeof(sc->dev),
+ sysctl_atiixp_polling, "I", "Enable polling mode");
+#endif
-atiixp_lock(sc);
-atiixp_enable_interrupts(sc);
-atiixp_unlock(sc);
+ snprintf(status, SND_STATUSLEN, "at memory 0x%lx irq %ld %s",
+ rman_get_start(sc->reg), rman_get_start(sc->irq),
+ PCM_KLDSTRING(snd_atiixp));
+
+ pcm_setstatus(sc->dev, status);
+
+ atiixp_lock(sc);
+ if (sc->polling == 0)
+ atiixp_enable_interrupts(sc);
+ atiixp_unlock(sc);
-return;
+ return;
postinitbad:
-atiixp_release_resource(sc);
+ atiixp_release_resource(sc);
}
static void
atiixp_release_resource(struct atiixp_info *sc)
{
-if (sc == NULL)
-return;
-if (sc->codec) {
-ac97_destroy(sc->codec);
-sc->codec = NULL;
-}
-if (sc->ih) {
-bus_teardown_intr(sc->dev, sc->irq, sc->ih);
-sc->ih = 0;
-}
-if (sc->reg) {
-bus_release_resource(sc->dev, sc->regtype, sc->regid, sc->reg);
-sc->reg = 0;
-}
-if (sc->irq) {
-bus_release_resource(sc->dev, SYS_RES_IRQ, sc->irqid, sc->irq);
-sc->irq = 0;
-}
-if (sc->parent_dmat) {
-bus_dma_tag_destroy(sc->parent_dmat);
-sc->parent_dmat = 0;
-}
-if (sc->sgd_dmamap) {
-bus_dmamap_unload(sc->sgd_dmat, sc->sgd_dmamap);
-sc->sgd_dmamap = 0;
-}
-if (sc->sgd_dmat) {
-bus_dma_tag_destroy(sc->sgd_dmat);
-sc->sgd_dmat = 0;
-}
-if (sc->lock) {
-snd_mtxfree(sc->lock);
-sc->lock = NULL;
-}
+ if (sc == NULL)
+ return;
+ if (sc->registered_channels != 0) {
+ atiixp_lock(sc);
+ sc->polling = 0;
+ callout_stop(&sc->poll_timer);
+ atiixp_unlock(sc);
+ callout_drain(&sc->poll_timer);
+ }
+ if (sc->codec) {
+ ac97_destroy(sc->codec);
+ sc->codec = NULL;
+ }
+ if (sc->ih) {
+ bus_teardown_intr(sc->dev, sc->irq, sc->ih);
+ sc->ih = NULL;
+ }
+ if (sc->reg) {
+ bus_release_resource(sc->dev, sc->regtype, sc->regid, sc->reg);
+ sc->reg = NULL;
+ }
+ if (sc->irq) {
+ bus_release_resource(sc->dev, SYS_RES_IRQ, sc->irqid, sc->irq);
+ sc->irq = NULL;
+ }
+ if (sc->parent_dmat) {
+ bus_dma_tag_destroy(sc->parent_dmat);
+ sc->parent_dmat = NULL;
+ }
+ if (sc->sgd_dmamap)
+ bus_dmamap_unload(sc->sgd_dmat, sc->sgd_dmamap);
+ if (sc->sgd_table) {
+ bus_dmamem_free(sc->sgd_dmat, sc->sgd_table, sc->sgd_dmamap);
+ sc->sgd_table = NULL;
+ }
+ sc->sgd_dmamap = NULL;
+ if (sc->sgd_dmat) {
+ bus_dma_tag_destroy(sc->sgd_dmat);
+ sc->sgd_dmat = NULL;
+ }
+ if (sc->lock) {
+ snd_mtxfree(sc->lock);
+ sc->lock = NULL;
+ }
+ free(sc, M_DEVBUF);
}
static int
atiixp_pci_probe(device_t dev)
{
-int i;
-uint16_t devid, vendor;
+ int i;
+ uint16_t devid, vendor;
-vendor = pci_get_vendor(dev);
-devid = pci_get_device(dev);
-for (i = 0; i < sizeof(atiixp_hw)/sizeof(atiixp_hw[0]); i++) {
-if (vendor == atiixp_hw[i].vendor &&
-devid == atiixp_hw[i].devid) {
-device_set_desc(dev, atiixp_hw[i].desc);
-return BUS_PROBE_DEFAULT;
-}
-}
+ vendor = pci_get_vendor(dev);
+ devid = pci_get_device(dev);
+ for (i = 0; i < sizeof(atiixp_hw) / sizeof(atiixp_hw[0]); i++) {
+ if (vendor == atiixp_hw[i].vendor &&
+ devid == atiixp_hw[i].devid) {
+ device_set_desc(dev, atiixp_hw[i].desc);
+ return (BUS_PROBE_DEFAULT);
+ }
+ }
-return ENXIO;
+ return (ENXIO);
}
static int
atiixp_pci_attach(device_t dev)
{
-struct atiixp_info *sc;
-int i;
-
-if ((sc = malloc(sizeof(*sc), M_DEVBUF, M_NOWAIT | M_ZERO)) == NULL) {
-device_printf(dev, "cannot allocate softcn");
-return ENXIO;
-}
+ struct atiixp_info *sc;
+ int i;
-sc->lock = snd_mtxcreate(device_get_nameunit(dev), "sound softc");
-sc->dev = dev;
-/*
-* Default DMA segments per playback / recording channel
-*/
-sc->dma_segs = ATI_IXP_DMA_CHSEGS;
-
-pci_set_powerstate(dev, PCI_POWERSTATE_D0);
-pci_enable_busmaster(dev);
-
-sc->regid = PCIR_BAR(0);
-sc->regtype = SYS_RES_MEMORY;
-sc->reg = bus_alloc_resource_any(dev, sc->regtype, &sc->regid,
-RF_ACTIVE);
-
-if (!sc->reg) {
-device_printf(dev, "unable to allocate register spacen");
-goto bad;
-}
-
-sc->st = rman_get_bustag(sc->reg);
-sc->sh = rman_get_bushandle(sc->reg);
-
-sc->bufsz = pcm_getbuffersize(dev, 4096, ATI_IXP_DEFAULT_BUFSZ, 65536);
-
-sc->irqid = 0;
-sc->irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &sc->irqid,
-RF_ACTIVE | RF_SHAREABLE);
-if (!sc->irq ||
-snd_setup_intr(dev, sc->irq, INTR_MPSAFE,
-atiixp_intr, sc, &sc->ih)) {
-device_printf(dev, "unable to map interruptn");
-goto bad;
-}
-
-/*
-* Let the user choose the best DMA segments.
-*/
-if (resource_int_value(device_get_name(dev),
-device_get_unit(dev), "dma_segs",
-&i) == 0) {
-if (i < ATI_IXP_DMA_CHSEGS_MIN)
-i = ATI_IXP_DMA_CHSEGS_MIN;
-if (i > ATI_IXP_DMA_CHSEGS_MAX)
-i = ATI_IXP_DMA_CHSEGS_MAX;
-sc->dma_segs = i;
-}
-
-/*
-* round the value to the nearest ^2
-*/
-i = 0;
-while (sc->dma_segs >> i)
-i++;
-sc->dma_segs = 1 << (i - 1);
-if (sc->dma_segs < ATI_IXP_DMA_CHSEGS_MIN)
-sc->dma_segs = ATI_IXP_DMA_CHSEGS_MIN;
-else if (sc->dma_segs > ATI_IXP_DMA_CHSEGS_MAX)
-sc->dma_segs = ATI_IXP_DMA_CHSEGS_MAX;
+ sc = malloc(sizeof(*sc), M_DEVBUF, M_WAITOK | M_ZERO);
+ sc->lock = snd_mtxcreate(device_get_nameunit(dev), "snd_atiixp softc");
+ sc->dev = dev;
+
+ callout_init(&sc->poll_timer, CALLOUT_MPSAFE);
+ sc->poll_ticks = 1;
+
+ if (resource_int_value(device_get_name(sc->dev),
+ device_get_unit(sc->dev), "polling", &i) == 0 && i != 0)
+ sc->polling = 1;
+ else
+ sc->polling = 0;
+
+ pci_set_powerstate(dev, PCI_POWERSTATE_D0);
+ pci_enable_busmaster(dev);
+
+ sc->regid = PCIR_BAR(0);
+ sc->regtype = SYS_RES_MEMORY;
+ sc->reg = bus_alloc_resource_any(dev, sc->regtype,
+ &sc->regid, RF_ACTIVE);
+
+ if (!sc->reg) {
+ device_printf(dev, "unable to allocate register space\n");
+ goto bad;
+ }
+
+ sc->st = rman_get_bustag(sc->reg);
+ sc->sh = rman_get_bushandle(sc->reg);
+
+ sc->bufsz = pcm_getbuffersize(dev, ATI_IXP_BUFSZ_MIN,
+ ATI_IXP_BUFSZ_DEFAULT, ATI_IXP_BUFSZ_MAX);
+
+ sc->irqid = 0;
+ sc->irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &sc->irqid,
+ RF_ACTIVE | RF_SHAREABLE);
+ if (!sc->irq || snd_setup_intr(dev, sc->irq, INTR_MPSAFE,
+ atiixp_intr, sc, &sc->ih)) {
+ device_printf(dev, "unable to map interrupt\n");
+ goto bad;
+ }
+
+ /*
+ * Let the user choose the best DMA segments.
+ */
+ if (resource_int_value(device_get_name(dev),
+ device_get_unit(dev), "blocksize", &i) == 0 && i > 0) {
+ i &= ATI_IXP_BLK_ALIGN;
+ if (i < ATI_IXP_BLK_MIN)
+ i = ATI_IXP_BLK_MIN;
+ sc->blkcnt = sc->bufsz / i;
+ i = 0;
+ while (sc->blkcnt >> i)
+ i++;
+ sc->blkcnt = 1 << (i - 1);
+ if (sc->blkcnt < ATI_IXP_DMA_CHSEGS_MIN)
+ sc->blkcnt = ATI_IXP_DMA_CHSEGS_MIN;
+ else if (sc->blkcnt > ATI_IXP_DMA_CHSEGS_MAX)
+ sc->blkcnt = ATI_IXP_DMA_CHSEGS_MAX;
+
+ } else
+ sc->blkcnt = ATI_IXP_DMA_CHSEGS;
+
+ /*
+ * DMA tag for scatter-gather buffers and link pointers
+ */
+ if (bus_dma_tag_create(/*parent*/bus_get_dma_tag(dev), /*alignment*/2,
+ /*boundary*/0,
+ /*lowaddr*/BUS_SPACE_MAXADDR_32BIT,
+ /*highaddr*/BUS_SPACE_MAXADDR,
+ /*filter*/NULL, /*filterarg*/NULL,
+ /*maxsize*/sc->bufsz, /*nsegments*/1, /*maxsegz*/0x3ffff,
+ /*flags*/0, /*lockfunc*/NULL,
+ /*lockarg*/NULL, &sc->parent_dmat) != 0) {
+ device_printf(dev, "unable to create dma tag\n");
+ goto bad;
+ }
+
+ if (bus_dma_tag_create(/*parent*/bus_get_dma_tag(dev), /*alignment*/2,
+ /*boundary*/0,
+ /*lowaddr*/BUS_SPACE_MAXADDR_32BIT,
+ /*highaddr*/BUS_SPACE_MAXADDR,
+ /*filter*/NULL, /*filterarg*/NULL,
+ /*maxsize*/ATI_IXP_DMA_CHSEGS_MAX * ATI_IXP_NCHANS *
+ sizeof(struct atiixp_dma_op),
+ /*nsegments*/1, /*maxsegz*/0x3ffff,
+ /*flags*/0, /*lockfunc*/NULL,
+ /*lockarg*/NULL, &sc->sgd_dmat) != 0) {
+ device_printf(dev, "unable to create dma tag\n");
+ goto bad;
+ }
+
+ if (bus_dmamem_alloc(sc->sgd_dmat, (void **)&sc->sgd_table,
+ BUS_DMA_NOWAIT, &sc->sgd_dmamap) == -1)
+ goto bad;
+
+ if (bus_dmamap_load(sc->sgd_dmat, sc->sgd_dmamap, sc->sgd_table,
+ ATI_IXP_DMA_CHSEGS_MAX * ATI_IXP_NCHANS *
+ sizeof(struct atiixp_dma_op), atiixp_dma_cb, sc, 0))
+ goto bad;
+
+
+ atiixp_chip_pre_init(sc);
+
+ sc->delayed_attach.ich_func = atiixp_chip_post_init;
+ sc->delayed_attach.ich_arg = sc;
+ if (cold == 0 ||
+ config_intrhook_establish(&sc->delayed_attach) != 0) {
+ sc->delayed_attach.ich_func = NULL;
+ atiixp_chip_post_init(sc);
+ }
-/*
-* DMA tag for scatter-gather buffers and link pointers
-*/
-if (bus_dma_tag_create(/*parent*/NULL, /*alignment*/2, /*boundary*/0,
-/*lowaddr*/BUS_SPACE_MAXADDR_32BIT,
-/*highaddr*/BUS_SPACE_MAXADDR,
-/*filter*/NULL, /*filterarg*/NULL,
-/*maxsize*/sc->bufsz, /*nsegments*/1, /*maxsegz*/0x3ffff,
-/*flags*/0, /*lockfunc*/NULL,
-/*lockarg*/NULL, &sc->parent_dmat) != 0) {
-device_printf(dev, "unable to create dma tagn");
-goto bad;
-}
-
-if (bus_dma_tag_create(/*parent*/NULL, /*alignment*/2, /*boundary*/0,
-/*lowaddr*/BUS_SPACE_MAXADDR_32BIT,
-/*highaddr*/BUS_SPACE_MAXADDR,
-/*filter*/NULL, /*filterarg*/NULL,
-/*maxsize*/sc->dma_segs * ATI_IXP_NCHANS *
-sizeof(struct atiixp_dma_op),
-/*nsegments*/1, /*maxsegz*/0x3ffff,
-/*flags*/0, /*lockfunc*/NULL,
-/*lockarg*/NULL, &sc->sgd_dmat) != 0) {
-device_printf(dev, "unable to create dma tagn");
-goto bad;
-}
-
-if (bus_dmamem_alloc(sc->sgd_dmat, (void **)&sc->sgd_table,
-BUS_DMA_NOWAIT, &sc->sgd_dmamap) == -1)
-goto bad;
-
-if (bus_dmamap_load(sc->sgd_dmat, sc->sgd_dmamap, sc->sgd_table,
-sc->dma_segs * ATI_IXP_NCHANS *
-sizeof(struct atiixp_dma_op),
-atiixp_dma_cb, sc, 0))
-goto bad;
-
-
-atiixp_chip_pre_init(sc);
-
-sc->delayed_attach.ich_func = atiixp_chip_post_init;
-sc->delayed_attach.ich_arg = sc;
-if (cold == 0 ||
-config_intrhook_establish(&sc->delayed_attach) != 0) {
-sc->delayed_attach.ich_func = NULL;
-atiixp_chip_post_init(sc);
-}
-
-return 0;
+ return (0);
bad:
-atiixp_release_resource(sc);
-return ENXIO;
+ atiixp_release_resource(sc);
+ return (ENXIO);
}
static int
atiixp_pci_detach(device_t dev)
{
-int r;
-struct atiixp_info *sc;
+ int r;
+ struct atiixp_info *sc;
-sc = pcm_getdevinfo(dev);
-if (sc != NULL) {
-if (sc->codec != NULL) {
-r = pcm_unregister(dev);
-if (r)
-return r;
-}
-sc->codec = NULL;
-atiixp_disable_interrupts(sc);
-atiixp_release_resource(sc);
-free(sc, M_DEVBUF);
-}
-return 0;
+ sc = pcm_getdevinfo(dev);
+ if (sc != NULL) {
+ if (sc->codec != NULL) {
+ r = pcm_unregister(dev);
+ if (r)
+ return (r);
+ }
+ sc->codec = NULL;
+ if (sc->st != 0 && sc->sh != 0)
+ atiixp_disable_interrupts(sc);
+ atiixp_release_resource(sc);
+ }
+ return (0);
}
static int
atiixp_pci_suspend(device_t dev)
{
-struct atiixp_info *sc = pcm_getdevinfo(dev);
-uint32_t value;
+ struct atiixp_info *sc = pcm_getdevinfo(dev);
+ uint32_t value;
-/* quickly disable interrupts and save channels active state */
-atiixp_lock(sc);
-atiixp_disable_interrupts(sc);
-value = atiixp_rd(sc, ATI_REG_CMD);
-sc->pch.active = (value & ATI_REG_CMD_SEND_EN) ? 1 : 0;
-sc->rch.active = (value & ATI_REG_CMD_RECEIVE_EN) ? 1 : 0;
-atiixp_unlock(sc);
-
-/* stop everything */
-if (sc->pch.channel && sc->pch.active)
-atiixp_chan_trigger(NULL, &sc->pch, PCMTRIG_STOP);
-if (sc->rch.channel && sc->rch.active)
-atiixp_chan_trigger(NULL, &sc->rch, PCMTRIG_STOP);
-
-/* power down aclink and pci bus */
-atiixp_lock(sc);
-value = atiixp_rd(sc, ATI_REG_CMD);
-value |= ATI_REG_CMD_POWERDOWN | ATI_REG_CMD_AC_RESET;
-atiixp_wr(sc, ATI_REG_CMD, ATI_REG_CMD_POWERDOWN);
-pci_set_powerstate(dev, PCI_POWERSTATE_D3);
-atiixp_unlock(sc);
+ /* quickly disable interrupts and save channels active state */
+ atiixp_lock(sc);
+ atiixp_disable_interrupts(sc);
+ atiixp_unlock(sc);
+
+ /* stop everything */
+ if (sc->pch.flags & ATI_IXP_CHN_RUNNING) {
+ atiixp_chan_trigger(NULL, &sc->pch, PCMTRIG_STOP);
+ sc->pch.flags |= ATI_IXP_CHN_SUSPEND;
+ }
+ if (sc->rch.flags & ATI_IXP_CHN_RUNNING) {
+ atiixp_chan_trigger(NULL, &sc->rch, PCMTRIG_STOP);
+ sc->rch.flags |= ATI_IXP_CHN_SUSPEND;
+ }
+
+ /* power down aclink and pci bus */
+ atiixp_lock(sc);
+ value = atiixp_rd(sc, ATI_REG_CMD);
+ value |= ATI_REG_CMD_POWERDOWN | ATI_REG_CMD_AC_RESET;
+ atiixp_wr(sc, ATI_REG_CMD, ATI_REG_CMD_POWERDOWN);
+ pci_set_powerstate(dev, PCI_POWERSTATE_D3);
+ atiixp_unlock(sc);
-return 0;
+ return (0);
}
static int
atiixp_pci_resume(device_t dev)
{
-struct atiixp_info *sc = pcm_getdevinfo(dev);
+ struct atiixp_info *sc = pcm_getdevinfo(dev);
-atiixp_lock(sc);
-/* power up pci bus */
-pci_set_powerstate(dev, PCI_POWERSTATE_D0);
-pci_enable_io(dev, SYS_RES_MEMORY);
-pci_enable_busmaster(dev);
-/* reset / power up aclink */
-atiixp_reset_aclink(sc);
-atiixp_unlock(sc);
-
-if (mixer_reinit(dev) == -1) {
-device_printf(dev, "unable to reinitialize the mixern");
-return ENXIO;
-}
-
-/*
-* Resume channel activities. Reset channel format regardless
-* of its previous state.
-*/
-if (sc->pch.channel) {
-if (sc->pch.fmt)
-atiixp_chan_setformat(NULL, &sc->pch, sc->pch.fmt);
-if (sc->pch.active)
-atiixp_chan_trigger(NULL, &sc->pch, PCMTRIG_START);
-}
-if (sc->rch.channel) {
-if (sc->rch.fmt)
-atiixp_chan_setformat(NULL, &sc->rch, sc->rch.fmt);
-if (sc->rch.active)
-atiixp_chan_trigger(NULL, &sc->rch, PCMTRIG_START);
-}
-
-/* enable interrupts */
-atiixp_lock(sc);
-atiixp_enable_interrupts(sc);
-atiixp_unlock(sc);
+ atiixp_lock(sc);
+ /* power up pci bus */
+ pci_set_powerstate(dev, PCI_POWERSTATE_D0);
+ pci_enable_io(dev, SYS_RES_MEMORY);
+ pci_enable_busmaster(dev);
+ /* reset / power up aclink */
+ atiixp_reset_aclink(sc);
+ atiixp_unlock(sc);
+
+ if (mixer_reinit(dev) == -1) {
+ device_printf(dev, "unable to reinitialize the mixer\n");
+ return (ENXIO);
+ }
+
+ /*
+ * Resume channel activities. Reset channel format regardless
+ * of its previous state.
+ */
+ if (sc->pch.channel != NULL) {
+ if (sc->pch.fmt != 0)
+ atiixp_chan_setformat(NULL, &sc->pch, sc->pch.fmt);
+ if (sc->pch.flags & ATI_IXP_CHN_SUSPEND) {
+ sc->pch.flags &= ~ATI_IXP_CHN_SUSPEND;
+ atiixp_chan_trigger(NULL, &sc->pch, PCMTRIG_START);
+ }
+ }
+ if (sc->rch.channel != NULL) {
+ if (sc->rch.fmt != 0)
+ atiixp_chan_setformat(NULL, &sc->rch, sc->rch.fmt);
+ if (sc->rch.flags & ATI_IXP_CHN_SUSPEND) {
+ sc->rch.flags &= ~ATI_IXP_CHN_SUSPEND;
+ atiixp_chan_trigger(NULL, &sc->rch, PCMTRIG_START);
+ }
+ }
+
+ /* enable interrupts */
+ atiixp_lock(sc);
+ if (sc->polling == 0)
+ atiixp_enable_interrupts(sc);
+ atiixp_unlock(sc);
-return 0;
+ return (0);
}
static device_method_t atiixp_methods[] = {
-DEVMETHOD(device_probe, atiixp_pci_probe),
-DEVMETHOD(device_attach, atiixp_pci_attach),
-DEVMETHOD(device_detach, atiixp_pci_detach),
-DEVMETHOD(device_suspend, atiixp_pci_suspend),
-DEVMETHOD(device_resume, atiixp_pci_resume),
-{ 0, 0 }
+ DEVMETHOD(device_probe, atiixp_pci_probe),
+ DEVMETHOD(device_attach, atiixp_pci_attach),
+ DEVMETHOD(device_detach, atiixp_pci_detach),
+ DEVMETHOD(device_suspend, atiixp_pci_suspend),
+ DEVMETHOD(device_resume, atiixp_pci_resume),
+ { 0, 0 }
};
static driver_t atiixp_driver = {
-"pcm",
-atiixp_methods,
-PCM_SOFTC_SIZE,
+ "pcm",
+ atiixp_methods,
+ PCM_SOFTC_SIZE,
};
DRIVER_MODULE(snd_atiixp, pci, atiixp_driver, pcm_devclass, 0, 0);
Index: hdac.h
===================================================================
RCS file: /home/cvs/src/sys/dev/sound/pci/hda/hdac.h,v
retrieving revision 1.1
retrieving revision 1.2
diff -L sys/dev/sound/pci/hda/hdac.h -L sys/dev/sound/pci/hda/hdac.h -u -r1.1 -r1.2
--- sys/dev/sound/pci/hda/hdac.h
+++ sys/dev/sound/pci/hda/hdac.h
@@ -1,31 +1,30 @@
/*-
-* Copyright (c) 2006 Stephane E. Potvin <sepotvin at videotron.ca>
-* All rights reserved.
-*
-* Redistribution and use in source and binary forms, with or without
-* modification, are permitted provided that the following conditions
-* are met:
-* 1. Redistributions of source code must retain the above copyright
-* notice, this list of conditions and the following disclaimer.
-* 2. Redistributions in binary form must reproduce the above copyright
-* notice, this list of conditions and the following disclaimer in the
-* documentation and/or other materials provided with the distribution.
-*
-* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
-* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
-* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
-* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
-* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
-* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
-* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
-* SUCH DAMAGE.
-*
-* $MidnightBSD$
-* $FreeBSD: src/sys/dev/sound/pci/hda/hdac.h,v 1.1 2006/10/01 11:12:59 ariff Exp $
-*/
+ * Copyright (c) 2006 Stephane E. Potvin <sepotvin at videotron.ca>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD: src/sys/dev/sound/pci/hda/hdac.h,v 1.1 2006/10/01 11:12:59 ariff Exp $
+ */
#ifndef _HDAC_H_
#define _HDAC_H_
@@ -33,27 +32,28 @@
#if 0
/****************************************************************************
-* Miscellanious defines
-****************************************************************************/
+ * Miscellanious defines
+ ****************************************************************************/
/****************************************************************************
-* Helper Macros
-****************************************************************************/
+ * Helper Macros
+ ****************************************************************************/
/****************************************************************************
-* Simplified Accessors for HDA devices
-****************************************************************************/
+ * Simplified Accessors for HDA devices
+ ****************************************************************************/
enum hdac_device_ivars {
-HDAC_IVAR_CODEC_ID,
-HDAC_IVAR_NODE_ID,
-HDAC_IVAR_VENDOR_ID,
-HDAC_IVAR_DEVICE_ID,
-HDAC_IVAR_REVISION_ID,
-HDAC_IVAR_STEPPING_ID,
-HDAC_IVAR_NODE_TYPE,
+ HDAC_IVAR_CODEC_ID,
+ HDAC_IVAR_NODE_ID,
+ HDAC_IVAR_VENDOR_ID,
+ HDAC_IVAR_DEVICE_ID,
+ HDAC_IVAR_REVISION_ID,
+ HDAC_IVAR_STEPPING_ID,
+ HDAC_IVAR_NODE_TYPE,
};
-#define HDAC_ACCESSOR(var, ivar, type) __BUS_ACCESSOR(hdac, var, HDAC, ivar, type)
+#define HDAC_ACCESSOR(var, ivar, type) \
+ __BUS_ACCESSOR(hdac, var, HDAC, ivar, type)
HDAC_ACCESSOR(codec_id, CODEC_ID, uint8_t);
HDAC_ACCESSOR(node_id, NODE_ID, uint8_t);
Index: hda_reg.h
===================================================================
RCS file: /home/cvs/src/sys/dev/sound/pci/hda/hda_reg.h,v
retrieving revision 1.1
retrieving revision 1.2
diff -L sys/dev/sound/pci/hda/hda_reg.h -L sys/dev/sound/pci/hda/hda_reg.h -u -r1.1 -r1.2
--- sys/dev/sound/pci/hda/hda_reg.h
+++ sys/dev/sound/pci/hda/hda_reg.h
@@ -1,38 +1,37 @@
/*-
-* Copyright (c) 2006 Stephane E. Potvin <sepotvin at videotron.ca>
-* All rights reserved.
-*
-* Redistribution and use in source and binary forms, with or without
-* modification, are permitted provided that the following conditions
-* are met:
-* 1. Redistributions of source code must retain the above copyright
-* notice, this list of conditions and the following disclaimer.
-* 2. Redistributions in binary form must reproduce the above copyright
-* notice, this list of conditions and the following disclaimer in the
-* documentation and/or other materials provided with the distribution.
-*
-* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
-* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
-* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
-* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
-* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
-* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
-* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
-* SUCH DAMAGE.
-*
-* $MidnightBSD$
-* $FreeBSD: src/sys/dev/sound/pci/hda/hda_reg.h,v 1.1 2006/10/01 11:12:59 ariff Exp $
-*/
+ * Copyright (c) 2006 Stephane E. Potvin <sepotvin at videotron.ca>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD: src/sys/dev/sound/pci/hda/hda_reg.h,v 1.2 2006/11/26 12:24:05 ariff Exp $
+ */
#ifndef _HDA_REG_H_
#define _HDA_REG_H_
/****************************************************************************
-* HDA Device Verbs
-****************************************************************************/
+ * HDA Device Verbs
+ ****************************************************************************/
/* HDA Command */
#define HDA_CMD_VERB_MASK 0x000fffff
@@ -45,28 +44,44 @@
#define HDA_CMD_VERB_4BIT_SHIFT 16
#define HDA_CMD_VERB_12BIT_SHIFT 8
-#define HDA_CMD_VERB_4BIT(verb, payload) (((verb) << HDA_CMD_VERB_4BIT_SHIFT) | (payload))
-#define HDA_CMD_4BIT(cad, nid, verb, payload) (((cad) << HDA_CMD_CAD_SHIFT) | ((nid) << HDA_CMD_NID_SHIFT) | (HDA_CMD_VERB_4BIT((verb), (payload))))
-
-#define HDA_CMD_VERB_12BIT(verb, payload) (((verb) << HDA_CMD_VERB_12BIT_SHIFT) | (payload))
-#define HDA_CMD_12BIT(cad, nid, verb, payload) (((cad) << HDA_CMD_CAD_SHIFT) | ((nid) << HDA_CMD_NID_SHIFT) | (HDA_CMD_VERB_12BIT((verb), (payload))))
+#define HDA_CMD_VERB_4BIT(verb, payload) \
+ (((verb) << HDA_CMD_VERB_4BIT_SHIFT) | (payload))
+#define HDA_CMD_4BIT(cad, nid, verb, payload) \
+ (((cad) << HDA_CMD_CAD_SHIFT) | \
+ ((nid) << HDA_CMD_NID_SHIFT) | \
+ (HDA_CMD_VERB_4BIT((verb), (payload))))
+
+#define HDA_CMD_VERB_12BIT(verb, payload) \
+ (((verb) << HDA_CMD_VERB_12BIT_SHIFT) | (payload))
+#define HDA_CMD_12BIT(cad, nid, verb, payload) \
+ (((cad) << HDA_CMD_CAD_SHIFT) | \
+ ((nid) << HDA_CMD_NID_SHIFT) | \
+ (HDA_CMD_VERB_12BIT((verb), (payload))))
/* Get Parameter */
#define HDA_CMD_VERB_GET_PARAMETER 0xf00
-#define HDA_CMD_GET_PARAMETER(cad, nid, payload) (HDA_CMD_12BIT((cad), (nid), HDA_CMD_VERB_GET_PARAMETER, (payload)))
+#define HDA_CMD_GET_PARAMETER(cad, nid, payload) \
+ (HDA_CMD_12BIT((cad), (nid), \
+ HDA_CMD_VERB_GET_PARAMETER, (payload)))
/* Connection Select Control */
#define HDA_CMD_VERB_GET_CONN_SELECT_CONTROL 0xf01
#define HDA_CMD_VERB_SET_CONN_SELECT_CONTROL 0x701
-#define HDA_CMD_GET_CONN_SELECT_CONTROL(cad, nid) (HDA_CMD_12BIT((cad), (nid), HDA_CMD_VERB_GET_CONN_SELECT_CONTROL, 0x0))
-#define HDA_CMD_SET_CONNECTION_SELECT_CONTROL(cad, nid, payload) (HDA_CMD_12BIT((cad), (nid), HDA_CMD_VERB_SET_CONN_SELECT_CONTROL, (payload)))
+#define HDA_CMD_GET_CONN_SELECT_CONTROL(cad, nid) \
+ (HDA_CMD_12BIT((cad), (nid), \
+ HDA_CMD_VERB_GET_CONN_SELECT_CONTROL, 0x0))
+#define HDA_CMD_SET_CONNECTION_SELECT_CONTROL(cad, nid, payload) \
+ (HDA_CMD_12BIT((cad), (nid), \
+ HDA_CMD_VERB_SET_CONN_SELECT_CONTROL, (payload)))
/* Connection List Entry */
#define HDA_CMD_VERB_GET_CONN_LIST_ENTRY 0xf02
-#define HDA_CMD_GET_CONN_LIST_ENTRY(cad, nid, payload) (HDA_CMD_12BIT((cad), (nid), HDA_CMD_VERB_GET_CONN_LIST_ENTRY, (payload)))
+#define HDA_CMD_GET_CONN_LIST_ENTRY(cad, nid, payload) \
+ (HDA_CMD_12BIT((cad), (nid), \
+ HDA_CMD_VERB_GET_CONN_LIST_ENTRY, (payload)))
#define HDA_CMD_GET_CONN_LIST_ENTRY_SIZE_SHORT 1
#define HDA_CMD_GET_CONN_LIST_ENTRY_SIZE_LONG 2
@@ -75,8 +90,12 @@
#define HDA_CMD_VERB_GET_PROCESSING_STATE 0xf03
#define HDA_CMD_VERB_SET_PROCESSING_STATE 0x703
-#define HDA_CMD_GET_PROCESSING_STATE(cad, nid) (HDA_CMD_12BIT((cad), (nid), HDA_CMD_VERB_GET_PROCESSING_STATE, 0x0))
-#define HDA_CMD_SET_PROCESSING_STATE(cad, nid, payload) (HDA_CMD_12BIT((cad), (nid), HDA_CMD_VERB_SET_PROCESSING_STATE, (payload)))
+#define HDA_CMD_GET_PROCESSING_STATE(cad, nid) \
+ (HDA_CMD_12BIT((cad), (nid), \
+ HDA_CMD_VERB_GET_PROCESSING_STATE, 0x0))
+#define HDA_CMD_SET_PROCESSING_STATE(cad, nid, payload) \
+ (HDA_CMD_12BIT((cad), (nid), \
+ HDA_CMD_VERB_SET_PROCESSING_STATE, (payload)))
#define HDA_CMD_GET_PROCESSING_STATE_STATE_OFF 0x00
#define HDA_CMD_GET_PROCESSING_STATE_STATE_ON 0x01
@@ -86,22 +105,34 @@
#define HDA_CMD_VERB_GET_COEFF_INDEX 0xd
#define HDA_CMD_VERB_SET_COEFF_INDEX 0x5
-#define HDA_CMD_GET_COEFF_INDEX(cad, nid) (HDA_CMD_4BIT((cad), (nid), HDA_CMD_VERB_GET_COEFF_INDEX, 0x0))
-#define HDA_CMD_SET_COEFF_INDEX(cad, nid, payload) (HDA_CMD_4BIT((cad), (nid), HDA_CMD_VERB_SET_COEFF_INDEX, (payload)))
+#define HDA_CMD_GET_COEFF_INDEX(cad, nid) \
+ (HDA_CMD_4BIT((cad), (nid), \
+ HDA_CMD_VERB_GET_COEFF_INDEX, 0x0))
+#define HDA_CMD_SET_COEFF_INDEX(cad, nid, payload) \
+ (HDA_CMD_4BIT((cad), (nid), \
+ HDA_CMD_VERB_SET_COEFF_INDEX, (payload)))
/* Processing Coefficient */
#define HDA_CMD_VERB_GET_PROCESSING_COEFF 0xc
#define HDA_CMD_VERB_SET_PROCESSING_COEFF 0x4
-#define HDA_CMD_GET_PROCESSING_COEFF(cad, nid) (HDA_CMD_4BIT((cad), (nid), HDA_CMD_VERB_GET_PROCESSING_COEFF, 0x0))
-#define HDA_CMD_SET_PROCESSING_COEFF(cad, nid, payload) (HDA_CMD_4BIT((cad), (nid), HDA_CMD_VERB_SET_PROCESSING_COEFF, (payload)))
+#define HDA_CMD_GET_PROCESSING_COEFF(cad, nid) \
+ (HDA_CMD_4BIT((cad), (nid), \
+ HDA_CMD_VERB_GET_PROCESSING_COEFF, 0x0))
+#define HDA_CMD_SET_PROCESSING_COEFF(cad, nid, payload) \
+ (HDA_CMD_4BIT((cad), (nid), \
+ HDA_CMD_VERB_SET_PROCESSING_COEFF, (payload)))
/* Amplifier Gain/Mute */
#define HDA_CMD_VERB_GET_AMP_GAIN_MUTE 0xb
#define HDA_CMD_VERB_SET_AMP_GAIN_MUTE 0x3
-#define HDA_CMD_GET_AMP_GAIN_MUTE(cad, nid, payload) (HDA_CMD_4BIT((cad), (nid), HDA_CMD_VERB_GET_AMP_GAIN_MUTE, (payload)))
-#define HDA_CMD_SET_AMP_GAIN_MUTE(cad, nid, payload) (HDA_CMD_4BIT((cad), (nid), HDA_CMD_VERB_SET_AMP_GAIN_MUTE, (payload)))
+#define HDA_CMD_GET_AMP_GAIN_MUTE(cad, nid, payload) \
+ (HDA_CMD_4BIT((cad), (nid), \
+ HDA_CMD_VERB_GET_AMP_GAIN_MUTE, (payload)))
+#define HDA_CMD_SET_AMP_GAIN_MUTE(cad, nid, payload) \
+ (HDA_CMD_4BIT((cad), (nid), \
+ HDA_CMD_VERB_SET_AMP_GAIN_MUTE, (payload)))
#define HDA_CMD_GET_AMP_GAIN_MUTE_INPUT 0x0000
#define HDA_CMD_GET_AMP_GAIN_MUTE_OUTPUT 0x8000
@@ -113,8 +144,12 @@
#define HDA_CMD_GET_AMP_GAIN_MUTE_GAIN_MASK 0x00000007
#define HDA_CMD_GET_AMP_GAIN_MUTE_GAIN_SHIFT 0
-#define HDA_CMD_GET_AMP_GAIN_MUTE_MUTE(rsp) (((rsp) & HDA_CMD_GET_AMP_GAIN_MUTE_MUTE_MASK) >> HDA_CMD_GET_AMP_GAIN_MUTE_MUTE_SHIFT)
-#define HDA_CMD_GET_AMP_GAIN_MUTE_GAIN(rsp) (((rsp) & HDA_CMD_GET_AMP_GAIN_MUTE_GAIN_MASK) >> HDA_CMD_GET_AMP_GAIN_MUTE_GAIN_SHIFT)
+#define HDA_CMD_GET_AMP_GAIN_MUTE_MUTE(rsp) \
+ (((rsp) & HDA_CMD_GET_AMP_GAIN_MUTE_MUTE_MASK) >> \
+ HDA_CMD_GET_AMP_GAIN_MUTE_MUTE_SHIFT)
+#define HDA_CMD_GET_AMP_GAIN_MUTE_GAIN(rsp) \
+ (((rsp) & HDA_CMD_GET_AMP_GAIN_MUTE_GAIN_MASK) >> \
+ HDA_CMD_GET_AMP_GAIN_MUTE_GAIN_SHIFT)
#define HDA_CMD_SET_AMP_GAIN_MUTE_OUTPUT 0x8000
#define HDA_CMD_SET_AMP_GAIN_MUTE_INPUT 0x4000
@@ -126,24 +161,38 @@
#define HDA_CMD_SET_AMP_GAIN_MUTE_GAIN_MASK 0x0007
#define HDA_CMD_SET_AMP_GAIN_MUTE_GAIN_SHIFT 0
-#define HDA_CMD_SET_AMP_GAIN_MUTE_INDEX(index) (((index) << HDA_CMD_SET_AMP_GAIN_MUTE_INDEX_SHIFT) & HDA_CMD_SET_AMP_GAIN_MUTE_INDEX_MASK)
-#define HDA_CMD_SET_AMP_GAIN_MUTE_GAIN(index) (((index) << HDA_CMD_SET_AMP_GAIN_MUTE_GAIN_SHIFT) & HDA_CMD_SET_AMP_GAIN_MUTE_GAIN_MASK)
+#define HDA_CMD_SET_AMP_GAIN_MUTE_INDEX(index) \
+ (((index) << HDA_CMD_SET_AMP_GAIN_MUTE_INDEX_SHIFT) & \
+ HDA_CMD_SET_AMP_GAIN_MUTE_INDEX_MASK)
+#define HDA_CMD_SET_AMP_GAIN_MUTE_GAIN(index) \
+ (((index) << HDA_CMD_SET_AMP_GAIN_MUTE_GAIN_SHIFT) & \
+ HDA_CMD_SET_AMP_GAIN_MUTE_GAIN_MASK)
/* Converter format */
#define HDA_CMD_VERB_GET_CONV_FMT 0xa
#define HDA_CMD_VERB_SET_CONV_FMT 0x2
-#define HDA_CMD_GET_CONV_FMT(cad, nid) (HDA_CMD_4BIT((cad), (nid), HDA_CMD_VERB_GET_CONV_FMT, 0x0))
-#define HDA_CMD_SET_CONV_FMT(cad, nid, payload) (HDA_CMD_4BIT((cad), (nid), HDA_CMD_VERB_SET_CONV_FMT, (payload)))
+#define HDA_CMD_GET_CONV_FMT(cad, nid) \
+ (HDA_CMD_4BIT((cad), (nid), \
+ HDA_CMD_VERB_GET_CONV_FMT, 0x0))
+#define HDA_CMD_SET_CONV_FMT(cad, nid, payload) \
+ (HDA_CMD_4BIT((cad), (nid), \
+ HDA_CMD_VERB_SET_CONV_FMT, (payload)))
/* Digital Converter Control */
#define HDA_CMD_VERB_GET_DIGITAL_CONV_FMT 0xf0d
#define HDA_CMD_VERB_SET_DIGITAL_CONV_FMT1 0x70d
#define HDA_CMD_VERB_SET_DIGITAL_CONV_FMT2 0x70e
-#define HDA_CMD_GET_DIGITAL_CONV_FMT(cad, nid) (HDA_CMD_12BIT((cad), (nid), HDA_CMD_VERB_GET_DIGITAL_CONV_FMTT, 0x0))
-#define HDA_CMD_SET_DIGITAL_CONV_FMT1(cad, nid, payload) (HDA_CMD_12BIT((cad), (nid), HDA_CMD_VERB_SET_DIGITAL_CONV_FMT1, (payload)))
-#define HDA_CMD_SET_DIGITAL_CONV_FMT2(cad, nid, payload) (HDA_CMD_12BIT((cad), (nid), HDA_CMD_VERB_SET_DIGITAL_CONV_FMT2, (payload)))
+#define HDA_CMD_GET_DIGITAL_CONV_FMT(cad, nid) \
+ (HDA_CMD_12BIT((cad), (nid), \
+ HDA_CMD_VERB_GET_DIGITAL_CONV_FMTT, 0x0))
+#define HDA_CMD_SET_DIGITAL_CONV_FMT1(cad, nid, payload) \
+ (HDA_CMD_12BIT((cad), (nid), \
+ HDA_CMD_VERB_SET_DIGITAL_CONV_FMT1, (payload)))
+#define HDA_CMD_SET_DIGITAL_CONV_FMT2(cad, nid, payload) \
+ (HDA_CMD_12BIT((cad), (nid), \
+ HDA_CMD_VERB_SET_DIGITAL_CONV_FMT2, (payload)))
#define HDA_CMD_GET_DIGITAL_CONV_FMT_CC_MASK 0x7f00
#define HDA_CMD_GET_DIGITAL_CONV_FMT_CC_SHIFT 8
@@ -164,15 +213,33 @@
#define HDA_CMD_GET_DIGITAL_CONV_FMT_DIGEN_MASK 0x0001
#define HDA_CMD_GET_DIGITAL_CONV_FMT_DIGEN_SHIFT 0
-#define HDA_CMD_GET_DIGITAL_CONV_FMT_CC(rsp) (((rsp) & HDA_CMD_GET_DIGITAL_CONV_FMT_CC_MASK) >> HDA_CMD_GET_DIGITAL_CONV_FMT_CC_SHIFT)
-#define HDA_CMD_GET_DIGITAL_CONV_FMT_L(rsp) (((rsp) & HDA_CMD_GET_DIGITAL_CONV_FMT_L_MASK) >> HDA_CMD_GET_DIGITAL_CONV_FMT_L_SHIFT)
-#define HDA_CMD_GET_DIGITAL_CONV_FMT_PRO(rsp) (((rsp) & HDA_CMD_GET_DIGITAL_CONV_FMT_PRO_MASK) >> HDA_CMD_GET_DIGITAL_CONV_FMT_PRO_SHIFT)
-#define HDA_CMD_GET_DIGITAL_CONV_FMT_NAUDIO(rsp) (((rsp) & HDA_CMD_GET_DIGITAL_CONV_FMT_NAUDIO_MASK) >> HDA_CMD_GET_DIGITAL_CONV_FMT_NAUDIO_SHIFT)
-#define HDA_CMD_GET_DIGITAL_CONV_FMT_COPY(rsp) (((rsp) & HDA_CMD_GET_DIGITAL_CONV_FMT_COPY_MASK) >> HDA_CMD_GET_DIGITAL_CONV_FMT_COPY_SHIFT)
-#define HDA_CMD_GET_DIGITAL_CONV_FMT_PRE(rsp) (((rsp) & HDA_CMD_GET_DIGITAL_CONV_FMT_PRE_MASK) >> HDA_CMD_GET_DIGITAL_CONV_FMT_PRE_SHIFT)
-#define HDA_CMD_GET_DIGITAL_CONV_FMT_VCFG(rsp) (((rsp) & HDA_CMD_GET_DIGITAL_CONV_FMT_VCFG_MASK) >> HDA_CMD_GET_DIGITAL_CONV_FMT_VCFG_SHIFT)
-#define HDA_CMD_GET_DIGITAL_CONV_FMT_V(rsp) (((rsp) & HDA_CMD_GET_DIGITAL_CONV_FMT_V_MASK) >> HDA_CMD_GET_DIGITAL_CONV_FMT_V_SHIFT)
-#define HDA_CMD_GET_DIGITAL_CONV_FMT_DIGEN(rsp) (((rsp) & HDA_CMD_GET_DIGITAL_CONV_FMT_DIGEN_MASK) >> HDA_CMD_GET_DIGITAL_CONV_FMT_DIGEN_SHIFT)
+#define HDA_CMD_GET_DIGITAL_CONV_FMT_CC(rsp) \
+ (((rsp) & HDA_CMD_GET_DIGITAL_CONV_FMT_CC_MASK) >> \
+ HDA_CMD_GET_DIGITAL_CONV_FMT_CC_SHIFT)
+#define HDA_CMD_GET_DIGITAL_CONV_FMT_L(rsp) \
+ (((rsp) & HDA_CMD_GET_DIGITAL_CONV_FMT_L_MASK) >> \
+ HDA_CMD_GET_DIGITAL_CONV_FMT_L_SHIFT)
+#define HDA_CMD_GET_DIGITAL_CONV_FMT_PRO(rsp) \
+ (((rsp) & HDA_CMD_GET_DIGITAL_CONV_FMT_PRO_MASK) >> \
+ HDA_CMD_GET_DIGITAL_CONV_FMT_PRO_SHIFT)
+#define HDA_CMD_GET_DIGITAL_CONV_FMT_NAUDIO(rsp) \
+ (((rsp) & HDA_CMD_GET_DIGITAL_CONV_FMT_NAUDIO_MASK) >> \
+ HDA_CMD_GET_DIGITAL_CONV_FMT_NAUDIO_SHIFT)
+#define HDA_CMD_GET_DIGITAL_CONV_FMT_COPY(rsp) \
+ (((rsp) & HDA_CMD_GET_DIGITAL_CONV_FMT_COPY_MASK) >> \
+ HDA_CMD_GET_DIGITAL_CONV_FMT_COPY_SHIFT)
+#define HDA_CMD_GET_DIGITAL_CONV_FMT_PRE(rsp) \
+ (((rsp) & HDA_CMD_GET_DIGITAL_CONV_FMT_PRE_MASK) >> \
+ HDA_CMD_GET_DIGITAL_CONV_FMT_PRE_SHIFT)
+#define HDA_CMD_GET_DIGITAL_CONV_FMT_VCFG(rsp) \
+ (((rsp) & HDA_CMD_GET_DIGITAL_CONV_FMT_VCFG_MASK) >> \
+ HDA_CMD_GET_DIGITAL_CONV_FMT_VCFG_SHIFT)
+#define HDA_CMD_GET_DIGITAL_CONV_FMT_V(rsp) \
+ (((rsp) & HDA_CMD_GET_DIGITAL_CONV_FMT_V_MASK) >> \
+ HDA_CMD_GET_DIGITAL_CONV_FMT_V_SHIFT)
+#define HDA_CMD_GET_DIGITAL_CONV_FMT_DIGEN(rsp) \
+ (((rsp) & HDA_CMD_GET_DIGITAL_CONV_FMT_DIGEN_MASK) >> \
+ HDA_CMD_GET_DIGITAL_CONV_FMT_DIGEN_SHIFT)
#define HDA_CMD_SET_DIGITAL_CONV_FMT1_L 0x80
#define HDA_CMD_SET_DIGITAL_CONV_FMT1_PRO 0x40
@@ -187,8 +254,12 @@
#define HDA_CMD_VERB_GET_POWER_STATE 0xf05
#define HDA_CMD_VERB_SET_POWER_STATE 0x705
-#define HDA_CMD_GET_POWER_STATE(cad, nid) (HDA_CMD_12BIT((cad), (nid), HDA_CMD_VERB_GET_POWER_STATE, 0x0))
-#define HDA_CMD_SET_POWER_STATE(cad, nid, payload) (HDA_CMD_12BIT((cad), (nid), HDA_CMD_VERB_SET_POWER_STATE, (payload)))
+#define HDA_CMD_GET_POWER_STATE(cad, nid) \
+ (HDA_CMD_12BIT((cad), (nid), \
+ HDA_CMD_VERB_GET_POWER_STATE, 0x0))
+#define HDA_CMD_SET_POWER_STATE(cad, nid, payload) \
+ (HDA_CMD_12BIT((cad), (nid), \
+ HDA_CMD_VERB_SET_POWER_STATE, (payload)))
#define HDA_CMD_POWER_STATE_D0 0x00
#define HDA_CMD_POWER_STATE_D1 0x01
@@ -200,43 +271,71 @@
#define HDA_CMD_POWER_STATE_SET_MASK 0x0000000f
#define HDA_CMD_POWER_STATE_SET_SHIFT 0
-#define HDA_CMD_GET_POWER_STATE_ACT(rsp) (((rsp) & HDA_CMD_POWER_STATE_ACT_MASK) >> HDA_CMD_POWER_STATE_ACT_SHIFT)
-#define HDA_CMD_GET_POWER_STATE_SET(rsp) (((rsp) & HDA_CMD_POWER_STATE_SET_MASK) >> HDA_CMD_POWER_STATE_SET_SHIFT)
-
-#define HDA_CMD_SET_POWER_STATE_ACT(ps) (((ps) << HDA_CMD_POWER_STATE_ACT_SHIFT) & HDA_CMD_POWER_STATE_ACT_MASK)
-#define HDA_CMD_SET_POWER_STATE_SET(ps) (((ps) << HDA_CMD_POWER_STATE_SET_SHIFT) & HDA_CMD_POWER_STATE_ACT_MASK)
+#define HDA_CMD_GET_POWER_STATE_ACT(rsp) \
+ (((rsp) & HDA_CMD_POWER_STATE_ACT_MASK) >> \
+ HDA_CMD_POWER_STATE_ACT_SHIFT)
+#define HDA_CMD_GET_POWER_STATE_SET(rsp) \
+ (((rsp) & HDA_CMD_POWER_STATE_SET_MASK) >> \
+ HDA_CMD_POWER_STATE_SET_SHIFT)
+
+#define HDA_CMD_SET_POWER_STATE_ACT(ps) \
+ (((ps) << HDA_CMD_POWER_STATE_ACT_SHIFT) & \
+ HDA_CMD_POWER_STATE_ACT_MASK)
+#define HDA_CMD_SET_POWER_STATE_SET(ps) \
+ (((ps) << HDA_CMD_POWER_STATE_SET_SHIFT) & \
+ HDA_CMD_POWER_STATE_ACT_MASK)
/* Converter Stream, Channel */
#define HDA_CMD_VERB_GET_CONV_STREAM_CHAN 0xf06
#define HDA_CMD_VERB_SET_CONV_STREAM_CHAN 0x706
-#define HDA_CMD_GET_CONV_STREAM_CHAN(cad, nid) (HDA_CMD_12BIT((cad), (nid), HDA_CMD_VERB_GET_CONV_STREAM_CHAN, 0x0))
-#define HDA_CMD_SET_CONV_STREAM_CHAN(cad, nid, payload) (HDA_CMD_12BIT((cad), (nid), HDA_CMD_VERB_SET_CONV_STREAM_CHAN, (payload)))
+#define HDA_CMD_GET_CONV_STREAM_CHAN(cad, nid) \
+ (HDA_CMD_12BIT((cad), (nid), \
+ HDA_CMD_VERB_GET_CONV_STREAM_CHAN, 0x0))
+#define HDA_CMD_SET_CONV_STREAM_CHAN(cad, nid, payload) \
+ (HDA_CMD_12BIT((cad), (nid), \
+ HDA_CMD_VERB_SET_CONV_STREAM_CHAN, (payload)))
#define HDA_CMD_CONV_STREAM_CHAN_STREAM_MASK 0x000000f0
#define HDA_CMD_CONV_STREAM_CHAN_STREAM_SHIFT 4
#define HDA_CMD_CONV_STREAM_CHAN_CHAN_MASK 0x0000000f
#define HDA_CMD_CONV_STREAM_CHAN_CHAN_SHIFT 0
-#define HDA_CMD_GET_CONV_STREAM_CHAN_STREAM(rsp) (((rsp) & HDA_CMD_CONV_STREAM_CHAN_STREAM_MASK) >> HDA_CMD_CONV_STREAM_CHAN_STREAM_SHIFT)
-#define HDA_CMD_GET_CONV_STREAM_CHAN_CHAN(rsp) (((rsp) & HDA_CMD_CONV_STREAM_CHAN_CHAN_MASK) >> HDA_CMD_CONV_STREAM_CHAN_CHAN_SHIFT)
-
-#define HDA_CMD_SET_CONV_STREAM_CHAN_STREAM(param) (((param) << HDA_CMD_CONV_STREAM_CHAN_STREAM_SHIFT) & HDA_CMD_CONV_STREAM_CHAN_STREAM_MASK)
-#define HDA_CMD_SET_CONV_STREAM_CHAN_CHAN(param) (((param) << HDA_CMD_CONV_STREAM_CHAN_CHAN_SHIFT) & HDA_CMD_CONV_STREAM_CHAN_CHAN_MASK)
+#define HDA_CMD_GET_CONV_STREAM_CHAN_STREAM(rsp) \
+ (((rsp) & HDA_CMD_CONV_STREAM_CHAN_STREAM_MASK) >> \
+ HDA_CMD_CONV_STREAM_CHAN_STREAM_SHIFT)
+#define HDA_CMD_GET_CONV_STREAM_CHAN_CHAN(rsp) \
+ (((rsp) & HDA_CMD_CONV_STREAM_CHAN_CHAN_MASK) >> \
+ HDA_CMD_CONV_STREAM_CHAN_CHAN_SHIFT)
+
+#define HDA_CMD_SET_CONV_STREAM_CHAN_STREAM(param) \
+ (((param) << HDA_CMD_CONV_STREAM_CHAN_STREAM_SHIFT) & \
+ HDA_CMD_CONV_STREAM_CHAN_STREAM_MASK)
+#define HDA_CMD_SET_CONV_STREAM_CHAN_CHAN(param) \
+ (((param) << HDA_CMD_CONV_STREAM_CHAN_CHAN_SHIFT) & \
+ HDA_CMD_CONV_STREAM_CHAN_CHAN_MASK)
/* Input Converter SDI Select */
#define HDA_CMD_VERB_GET_INPUT_CONVERTER_SDI_SELECT 0xf04
#define HDA_CMD_VERB_SET_INPUT_CONVERTER_SDI_SELECT 0x704
-#define HDA_CMD_GET_INPUT_CONVERTER_SDI_SELECT(cad, nid) (HDA_CMD_12BIT((cad), (nid), HDA_CMD_VERB_GET_INPUT_CONVERTER_SDI_SELECT, 0x0))
-#define HDA_CMD_SET_INPUT_CONVERTER_SDI_SELECT(cad, nid, payload) (HDA_CMD_12BIT((cad), (nid), HDA_CMD_VERB_SET_INPUT_CONVERTER_SDI_SELECT, (payload)))
+#define HDA_CMD_GET_INPUT_CONVERTER_SDI_SELECT(cad, nid) \
+ (HDA_CMD_12BIT((cad), (nid), \
+ HDA_CMD_VERB_GET_INPUT_CONVERTER_SDI_SELECT, 0x0))
+#define HDA_CMD_SET_INPUT_CONVERTER_SDI_SELECT(cad, nid, payload) \
+ (HDA_CMD_12BIT((cad), (nid), \
+ HDA_CMD_VERB_SET_INPUT_CONVERTER_SDI_SELECT, (payload)))
/* Pin Widget Control */
#define HDA_CMD_VERB_GET_PIN_WIDGET_CTRL 0xf07
#define HDA_CMD_VERB_SET_PIN_WIDGET_CTRL 0x707
-#define HDA_CMD_GET_PIN_WIDGET_CTRL(cad, nid) (HDA_CMD_12BIT((cad), (nid), HDA_CMD_VERB_GET_PIN_WIDGET_CTRL, 0x0))
-#define HDA_CMD_SET_PIN_WIDGET_CTRL(cad, nid, payload) (HDA_CMD_12BIT((cad), (nid), HDA_CMD_VERB_SET_PIN_WIDGET_CTRL, (payload)))
+#define HDA_CMD_GET_PIN_WIDGET_CTRL(cad, nid) \
+ (HDA_CMD_12BIT((cad), (nid), \
+ HDA_CMD_VERB_GET_PIN_WIDGET_CTRL, 0x0))
+#define HDA_CMD_SET_PIN_WIDGET_CTRL(cad, nid, payload) \
+ (HDA_CMD_12BIT((cad), (nid), \
+ HDA_CMD_VERB_SET_PIN_WIDGET_CTRL, (payload)))
#define HDA_CMD_GET_PIN_WIDGET_CTRL_HPHN_ENABLE_MASK 0x00000080
#define HDA_CMD_GET_PIN_WIDGET_CTRL_HPHN_ENABLE_SHIFT 7
@@ -247,10 +346,18 @@
#define HDA_CMD_GET_PIN_WIDGET_CTRL_VREF_ENABLE_MASK 0x00000007
#define HDA_CMD_GET_PIN_WIDGET_CTRL_VREF_ENABLE_SHIFT 0
-#define HDA_CMD_GET_PIN_WIDGET_CTRL_HPHN_ENABLE(rsp) (((rsp) & HDA_CMD_GET_PIN_WIDGET_CTRL_HPHN_ENABLE_MASK) >> HDA_CMD_GET_PIN_WIDGET_CTRL_HPHN_ENABLE_SHIFT)
-#define HDA_CMD_GET_PIN_WIDGET_CTRL_OUT_ENABLE(rsp) (((rsp) & HDA_CMD_GET_PIN_WIDGET_CTRL_OUT_ENABLE_MASK) >> HDA_GET_CMD_PIN_WIDGET_CTRL_OUT_ENABLE_SHIFT)
-#define HDA_CMD_GET_PIN_WIDGET_CTRL_IN_ENABLE(rsp) (((rsp) & HDA_CMD_GET_PIN_WIDGET_CTRL_IN_ENABLE_MASK) >> HDA_CMD_GET_PIN_WIDGET_CTRL_IN_ENABLE_SHIFT)
-#define HDA_CMD_GET_PIN_WIDGET_CTRL_VREF_ENABLE(rsp) (((rsp) & HDA_CMD_GET_PIN_WIDGET_CTRL_VREF_ENABLE_MASK) >> HDA_CMD_GET_PIN_WIDGET_CTRL_VREF_ENABLE_SHIFT)
+#define HDA_CMD_GET_PIN_WIDGET_CTRL_HPHN_ENABLE(rsp) \
+ (((rsp) & HDA_CMD_GET_PIN_WIDGET_CTRL_HPHN_ENABLE_MASK) >> \
+ HDA_CMD_GET_PIN_WIDGET_CTRL_HPHN_ENABLE_SHIFT)
+#define HDA_CMD_GET_PIN_WIDGET_CTRL_OUT_ENABLE(rsp) \
+ (((rsp) & HDA_CMD_GET_PIN_WIDGET_CTRL_OUT_ENABLE_MASK) >> \
+ HDA_GET_CMD_PIN_WIDGET_CTRL_OUT_ENABLE_SHIFT)
+#define HDA_CMD_GET_PIN_WIDGET_CTRL_IN_ENABLE(rsp) \
+ (((rsp) & HDA_CMD_GET_PIN_WIDGET_CTRL_IN_ENABLE_MASK) >> \
+ HDA_CMD_GET_PIN_WIDGET_CTRL_IN_ENABLE_SHIFT)
+#define HDA_CMD_GET_PIN_WIDGET_CTRL_VREF_ENABLE(rsp) \
+ (((rsp) & HDA_CMD_GET_PIN_WIDGET_CTRL_VREF_ENABLE_MASK) >> \
+ HDA_CMD_GET_PIN_WIDGET_CTRL_VREF_ENABLE_SHIFT)
#define HDA_CMD_SET_PIN_WIDGET_CTRL_HPHN_ENABLE 0x80
#define HDA_CMD_SET_PIN_WIDGET_CTRL_OUT_ENABLE 0x40
@@ -258,7 +365,9 @@
#define HDA_CMD_SET_PIN_WIDGET_CTRL_VREF_ENABLE_MASK 0x07
#define HDA_CMD_SET_PIN_WIDGET_CTRL_VREF_ENABLE_SHIFT 0
-#define HDA_CMD_SET_PIN_WIDGET_CTRL_VREF_ENABLE(param) (((param) << HDA_CMD_SET_PIN_WIDGET_CTRL_VREF_ENABLE_SHIFT) & HDA_CMD_SET_PIN_WIDGET_CTRL_VREF_ENABLE_MASK)
+#define HDA_CMD_SET_PIN_WIDGET_CTRL_VREF_ENABLE(param) \
+ (((param) << HDA_CMD_SET_PIN_WIDGET_CTRL_VREF_ENABLE_SHIFT) & \
+ HDA_CMD_SET_PIN_WIDGET_CTRL_VREF_ENABLE_MASK)
#define HDA_CMD_PIN_WIDGET_CTRL_VREF_ENABLE_HIZ 0
#define HDA_CMD_PIN_WIDGET_CTRL_VREF_ENABLE_50 1
@@ -270,37 +379,55 @@
#define HDA_CMD_VERB_GET_UNSOLICITED_RESPONSE 0xf08
#define HDA_CMD_VERB_SET_UNSOLICITED_RESPONSE 0x708
-#define HDA_CMD_GET_UNSOLICITED_RESPONSE(cad, nid) (HDA_CMD_12BIT((cad), (nid), HDA_CMD_VERB_GET_UNSOLICITED_RESPONSE, 0x0))
-#define HDA_CMD_SET_UNSOLICITED_RESPONSE(cad, nid, payload) (HDA_CMD_12BIT((cad), (nid), HDA_CMD_VERB_SET_UNSOLICITED_RESPONSE, (payload)))
+#define HDA_CMD_GET_UNSOLICITED_RESPONSE(cad, nid) \
+ (HDA_CMD_12BIT((cad), (nid), \
+ HDA_CMD_VERB_GET_UNSOLICITED_RESPONSE, 0x0))
+#define HDA_CMD_SET_UNSOLICITED_RESPONSE(cad, nid, payload) \
+ (HDA_CMD_12BIT((cad), (nid), \
+ HDA_CMD_VERB_SET_UNSOLICITED_RESPONSE, (payload)))
#define HDA_CMD_GET_UNSOLICITED_RESPONSE_ENABLE_MASK 0x00000080
#define HDA_CMD_GET_UNSOLICITED_RESPONSE_ENABLE_SHIFT 7
#define HDA_CMD_GET_UNSOLICITED_RESPONSE_TAG_MASK 0x0000001f
#define HDA_CMD_GET_UNSOLICITED_RESPONSE_TAG_SHIFT 0
-#define HDA_CMD_GET_UNSOLICITED_RESPONSE_ENABLE(rsp) (((rsp) & HDA_CMD_GET_UNSOLICITED_RESPONSE_ENABLE_MASK) >> HDA_CMD_GET_UNSOLICITED_RESPONSE_ENABLE_SHIFT)
-#define HDA_CMD_GET_UNSOLICITED_RESPONSE_TAG(rsp) (((rsp) & HDA_CMD_GET_UNSOLICITED_RESPONSE_TAG_MASK) >> HDA_CMD_GET_UNSOLICITED_RESPONSE_TAG_SHIFT)
+#define HDA_CMD_GET_UNSOLICITED_RESPONSE_ENABLE(rsp) \
+ (((rsp) & HDA_CMD_GET_UNSOLICITED_RESPONSE_ENABLE_MASK) >> \
+ HDA_CMD_GET_UNSOLICITED_RESPONSE_ENABLE_SHIFT)
+#define HDA_CMD_GET_UNSOLICITED_RESPONSE_TAG(rsp) \
+ (((rsp) & HDA_CMD_GET_UNSOLICITED_RESPONSE_TAG_MASK) >> \
+ HDA_CMD_GET_UNSOLICITED_RESPONSE_TAG_SHIFT)
#define HDA_CMD_SET_UNSOLICITED_RESPONSE_ENABLE 0x80
#define HDA_CMD_SET_UNSOLICITED_RESPONSE_TAG_MASK 0x1f
#define HDA_CMD_SET_UNSOLICITED_RESPONSE_TAG_SHIFT 0
-#define HDA_CMD_SET_UNSOLICITED_RESPONSE_TAG(param) (((param) << HDA_CMD_SET_UNSOLICITED_RESPONSE_TAG_SHIFT) & HDA_CMD_SET_UNSOLICITED_RESPONSE_TAG_MASK)
+#define HDA_CMD_SET_UNSOLICITED_RESPONSE_TAG(param) \
+ (((param) << HDA_CMD_SET_UNSOLICITED_RESPONSE_TAG_SHIFT) & \
+ HDA_CMD_SET_UNSOLICITED_RESPONSE_TAG_MASK)
/* Pin Sense */
#define HDA_CMD_VERB_GET_PIN_SENSE 0xf09
#define HDA_CMD_VERB_SET_PIN_SENSE 0x709
-#define HDA_CMD_GET_PIN_SENSE(cad, nid) (HDA_CMD_12BIT((cad), (nid), HDA_CMD_VERB_GET_PIN_SENSE, 0x0))
-#define HDA_CMD_SET_PIN_SENSE(cad, nid, payload) (HDA_CMD_12BIT((cad), (nid), HDA_CMD_VERB_SET_PIN_SENSE, (payload)))
+#define HDA_CMD_GET_PIN_SENSE(cad, nid) \
+ (HDA_CMD_12BIT((cad), (nid), \
+ HDA_CMD_VERB_GET_PIN_SENSE, 0x0))
+#define HDA_CMD_SET_PIN_SENSE(cad, nid, payload) \
+ (HDA_CMD_12BIT((cad), (nid), \
+ HDA_CMD_VERB_SET_PIN_SENSE, (payload)))
#define HDA_CMD_GET_PIN_SENSE_PRESENCE_DETECT_MASK 0x80000000
#define HDA_CMD_GET_PIN_SENSE_PRESENCE_DETECT_SHIFT 31
#define HDA_CMD_GET_PIN_SENSE_IMP_SENSE_MASK 0x7fffffff
#define HDA_CMD_GET_PIN_SENSE_IMP_SENSE_SHIFT 0
-#define HDA_CMD_GET_PIN_SENSE_PRESENCE_DETECT(rsp) (((rsp) & HDA_CMD_GET_PIN_SENSE_PRESENCE_DETECT_MASK) >> HDA_CMD_GET_PIN_SENSE_PRESENCE_DETECT_SHIFT)
-#define HDA_CMD_GET_PIN_SENSE_IMP_SENSE(rsp) (((rsp) & HDA_CMD_GET_PIN_SENSE_IMP_SENSE_MASK) >> HDA_CMD_GET_PIN_SENSE_IMP_SENSE_SHIFT)
+#define HDA_CMD_GET_PIN_SENSE_PRESENCE_DETECT(rsp) \
+ (((rsp) & HDA_CMD_GET_PIN_SENSE_PRESENCE_DETECT_MASK) >> \
+ HDA_CMD_GET_PIN_SENSE_PRESENCE_DETECT_SHIFT)
+#define HDA_CMD_GET_PIN_SENSE_IMP_SENSE(rsp) \
+ (((rsp) & HDA_CMD_GET_PIN_SENSE_IMP_SENSE_MASK) >> \
+ HDA_CMD_GET_PIN_SENSE_IMP_SENSE_SHIFT)
#define HDA_CMD_GET_PIN_SENSE_IMP_SENSE_INVALID 0x7fffffff
@@ -311,8 +438,12 @@
#define HDA_CMD_VERB_GET_EAPD_BTL_ENABLE 0xf0c
#define HDA_CMD_VERB_SET_EAPD_BTL_ENABLE 0x70c
-#define HDA_CMD_GET_EAPD_BTL_ENABLE(cad, nid) (HDA_CMD_12BIT((cad), (nid), HDA_CMD_VERB_GET_EAPD_BTL_ENABLE, 0x0))
-#define HDA_CMD_SET_EAPD_BTL_ENABLE(cad, nid, payload) (HDA_CMD_12BIT((cad), (nid), HDA_CMD_VERB_SET_EAPD_BTL_ENABLE, (payload)))
+#define HDA_CMD_GET_EAPD_BTL_ENABLE(cad, nid) \
+ (HDA_CMD_12BIT((cad), (nid), \
+ HDA_CMD_VERB_GET_EAPD_BTL_ENABLE, 0x0))
+#define HDA_CMD_SET_EAPD_BTL_ENABLE(cad, nid, payload) \
+ (HDA_CMD_12BIT((cad), (nid), \
+ HDA_CMD_VERB_SET_EAPD_BTL_ENABLE, (payload)))
#define HDA_CMD_GET_EAPD_BTL_ENABLE_LR_SWAP_MASK 0x00000004
#define HDA_CMD_GET_EAPD_BTL_ENABLE_LR_SWAP_SHIFT 2
@@ -321,9 +452,15 @@
#define HDA_CMD_GET_EAPD_BTL_ENABLE_BTL_MASK 0x00000001
#define HDA_CMD_GET_EAPD_BTL_ENABLE_BTL_SHIFT 0
-#define HDA_CMD_GET_EAPD_BTL_ENABLE_LR_SWAP(rsp) (((rsp) & HDA_CMD_GET_EAPD_BTL_ENABLE_LR_SWAP_MASK) >> HDA_CMD_GET_EAPD_BTL_ENABLE_LR_SWAP_SHIFT)
-#define HDA_CMD_GET_EAPD_BTL_ENABLE_EAPD(rsp) (((rsp) & HDA_CMD_GET_EAPD_BTL_ENABLE_EAPD_MASK) >> HDA_CMD_GET_EAPD_BTL_ENABLE_EAPD_SHIFT)
-#define HDA_CMD_GET_EAPD_BTL_ENABLE_BTL(rsp) (((rsp) & HDA_CMD_GET_EAPD_BTL_ENABLE_BTL_MASK) >> HDA_CMD_GET_EAPD_BTL_ENABLE_BTL_SHIFT)
+#define HDA_CMD_GET_EAPD_BTL_ENABLE_LR_SWAP(rsp) \
+ (((rsp) & HDA_CMD_GET_EAPD_BTL_ENABLE_LR_SWAP_MASK) >> \
+ HDA_CMD_GET_EAPD_BTL_ENABLE_LR_SWAP_SHIFT)
+#define HDA_CMD_GET_EAPD_BTL_ENABLE_EAPD(rsp) \
+ (((rsp) & HDA_CMD_GET_EAPD_BTL_ENABLE_EAPD_MASK) >> \
+ HDA_CMD_GET_EAPD_BTL_ENABLE_EAPD_SHIFT)
+#define HDA_CMD_GET_EAPD_BTL_ENABLE_BTL(rsp) \
+ (((rsp) & HDA_CMD_GET_EAPD_BTL_ENABLE_BTL_MASK) >> \
+ HDA_CMD_GET_EAPD_BTL_ENABLE_BTL_SHIFT)
#define HDA_CMD_SET_EAPD_BTL_ENABLE_LR_SWAP 0x04
#define HDA_CMD_SET_EAPD_BTL_ENABLE_EAPD 0x02
@@ -333,92 +470,144 @@
#define HDA_CMD_VERB_GET_GPI_DATA 0xf10
#define HDA_CMD_VERB_SET_GPI_DATA 0x710
-#define HDA_CMD_GET_GPI_DATA(cad, nid) (HDA_CMD_12BIT((cad), (nid), HDA_CMD_VERB_GET_GPI_DATA, 0x0))
-#define HDA_CMD_SET_GPI_DATA(cad, nid) (HDA_CMD_12BIT((cad), (nid), HDA_CMD_VERB_SET_GPI_DATA, (payload)))
+#define HDA_CMD_GET_GPI_DATA(cad, nid) \
+ (HDA_CMD_12BIT((cad), (nid), \
+ HDA_CMD_VERB_GET_GPI_DATA, 0x0))
+#define HDA_CMD_SET_GPI_DATA(cad, nid) \
+ (HDA_CMD_12BIT((cad), (nid), \
+ HDA_CMD_VERB_SET_GPI_DATA, (payload)))
/* GPI Wake Enable Mask */
#define HDA_CMD_VERB_GET_GPI_WAKE_ENABLE_MASK 0xf11
#define HDA_CMD_VERB_SET_GPI_WAKE_ENABLE_MASK 0x711
-#define HDA_CMD_GET_GPI_WAKE_ENABLE_MASK(cad, nid) (HDA_CMD_12BIT((cad), (nid), HDA_CMD_VERB_GET_GPI_WAKE_ENABLE_MASK, 0x0))
-#define HDA_CMD_SET_GPI_WAKE_ENABLE_MASK(cad, nid, payload) (HDA_CMD_12BIT((cad), (nid), HDA_CMD_VERB_SET_GPI_WAKE_ENABLE_MASK, (payload)))
+#define HDA_CMD_GET_GPI_WAKE_ENABLE_MASK(cad, nid) \
+ (HDA_CMD_12BIT((cad), (nid), \
+ HDA_CMD_VERB_GET_GPI_WAKE_ENABLE_MASK, 0x0))
+#define HDA_CMD_SET_GPI_WAKE_ENABLE_MASK(cad, nid, payload) \
+ (HDA_CMD_12BIT((cad), (nid), \
+ HDA_CMD_VERB_SET_GPI_WAKE_ENABLE_MASK, (payload)))
/* GPI Unsolicited Enable Mask */
#define HDA_CMD_VERB_GET_GPI_UNSOLICITED_ENABLE_MASK 0xf12
#define HDA_CMD_VERB_SET_GPI_UNSOLICITED_ENABLE_MASK 0x712
-#define HDA_CMD_GET_GPI_UNSOLICITED_ENABLE_MASK(cad, nid) (HDA_CMD_12BIT((cad), (nid), HDA_CMD_VERB_GET_GPI_UNSOLICITED_ENABLE_MASK, 0x0))
-#define HDA_CMD_SET_GPI_UNSOLICITED_ENABLE_MASK(cad, nid, payload) (HDA_CMD_12BIT((cad), (nid), HDA_CMD_VERB_SET_GPI_UNSOLICITED_ENABLE_MASK, (payload)))
+#define HDA_CMD_GET_GPI_UNSOLICITED_ENABLE_MASK(cad, nid) \
+ (HDA_CMD_12BIT((cad), (nid), \
+ HDA_CMD_VERB_GET_GPI_UNSOLICITED_ENABLE_MASK, 0x0))
+#define HDA_CMD_SET_GPI_UNSOLICITED_ENABLE_MASK(cad, nid, payload) \
+ (HDA_CMD_12BIT((cad), (nid), \
+ HDA_CMD_VERB_SET_GPI_UNSOLICITED_ENABLE_MASK, (payload)))
/* GPI Sticky Mask */
#define HDA_CMD_VERB_GET_GPI_STICKY_MASK 0xf13
#define HDA_CMD_VERB_SET_GPI_STICKY_MASK 0x713
-#define HDA_CMD_GET_GPI_STICKY_MASK(cad, nid) (HDA_CMD_12BIT((cad), (nid), HDA_CMD_VERB_GET_GPI_STICKY_MASK, 0x0))
-#define HDA_CMD_SET_GPI_STICKY_MASK(cad, nid, payload) (HDA_CMD_12BIT((cad), (nid), HDA_CMD_VERB_SET_GPI_STICKY_MASK, (payload)))
+#define HDA_CMD_GET_GPI_STICKY_MASK(cad, nid) \
+ (HDA_CMD_12BIT((cad), (nid), \
+ HDA_CMD_VERB_GET_GPI_STICKY_MASK, 0x0))
+#define HDA_CMD_SET_GPI_STICKY_MASK(cad, nid, payload) \
+ (HDA_CMD_12BIT((cad), (nid), \
+ HDA_CMD_VERB_SET_GPI_STICKY_MASK, (payload)))
/* GPO Data */
#define HDA_CMD_VERB_GET_GPO_DATA 0xf14
#define HDA_CMD_VERB_SET_GPO_DATA 0x714
-#define HDA_CMD_GET_GPO_DATA(cad, nid) (HDA_CMD_12BIT((cad), (nid), HDA_CMD_VERB_GET_GPO_DATA, 0x0))
-#define HDA_CMD_SET_GPO_DATA(cad, nid, payload) (HDA_CMD_12BIT((cad), (nid), HDA_CMD_VERB_SET_GPO_DATA, (payload)))
+#define HDA_CMD_GET_GPO_DATA(cad, nid) \
+ (HDA_CMD_12BIT((cad), (nid), \
+ HDA_CMD_VERB_GET_GPO_DATA, 0x0))
+#define HDA_CMD_SET_GPO_DATA(cad, nid, payload) \
+ (HDA_CMD_12BIT((cad), (nid), \
+ HDA_CMD_VERB_SET_GPO_DATA, (payload)))
/* GPIO Data */
#define HDA_CMD_VERB_GET_GPIO_DATA 0xf15
#define HDA_CMD_VERB_SET_GPIO_DATA 0x715
-#define HDA_CMD_GET_GPIO_DATA(cad, nid) (HDA_CMD_12BIT((cad), (nid), HDA_CMD_VERB_GET_GPIO_DATA, 0x0))
-#define HDA_CMD_SET_GPIO_DATA(cad, nid, payload) (HDA_CMD_12BIT((cad), (nid), HDA_CMD_VERB_SET_GPIO_DATA, (payload)))
+#define HDA_CMD_GET_GPIO_DATA(cad, nid) \
+ (HDA_CMD_12BIT((cad), (nid), \
+ HDA_CMD_VERB_GET_GPIO_DATA, 0x0))
+#define HDA_CMD_SET_GPIO_DATA(cad, nid, payload) \
+ (HDA_CMD_12BIT((cad), (nid), \
+ HDA_CMD_VERB_SET_GPIO_DATA, (payload)))
/* GPIO Enable Mask */
#define HDA_CMD_VERB_GET_GPIO_ENABLE_MASK 0xf16
#define HDA_CMD_VERB_SET_GPIO_ENABLE_MASK 0x716
-#define HDA_CMD_GET_GPIO_ENABLE_MASK(cad, nid) (HDA_CMD_12BIT((cad), (nid), HDA_CMD_VERB_GET_GPIO_ENABLE_MASK, 0x0))
-#define HDA_CMD_SET_GPIO_ENABLE_MASK(cad, nid, payload) (HDA_CMD_12BIT((cad), (nid), HDA_CMD_VERB_SET_GPIO_ENABLE_MASK, (payload)))
+#define HDA_CMD_GET_GPIO_ENABLE_MASK(cad, nid) \
+ (HDA_CMD_12BIT((cad), (nid), \
+ HDA_CMD_VERB_GET_GPIO_ENABLE_MASK, 0x0))
+#define HDA_CMD_SET_GPIO_ENABLE_MASK(cad, nid, payload) \
+ (HDA_CMD_12BIT((cad), (nid), \
+ HDA_CMD_VERB_SET_GPIO_ENABLE_MASK, (payload)))
/* GPIO Direction */
#define HDA_CMD_VERB_GET_GPIO_DIRECTION 0xf17
#define HDA_CMD_VERB_SET_GPIO_DIRECTION 0x717
-#define HDA_CMD_GET_GPIO_DIRECTION(cad, nid) (HDA_CMD_12BIT((cad), (nid), HDA_CMD_VERB_GET_GPIO_DIRECTION, 0x0))
-#define HDA_CMD_SET_GPIO_DIRECTION(cad, nid, payload) (HDA_CMD_12BIT((cad), (nid), HDA_CMD_VERB_SET_GPIO_DIRECTION, (payload)))
+#define HDA_CMD_GET_GPIO_DIRECTION(cad, nid) \
+ (HDA_CMD_12BIT((cad), (nid), \
+ HDA_CMD_VERB_GET_GPIO_DIRECTION, 0x0))
+#define HDA_CMD_SET_GPIO_DIRECTION(cad, nid, payload) \
+ (HDA_CMD_12BIT((cad), (nid), \
+ HDA_CMD_VERB_SET_GPIO_DIRECTION, (payload)))
/* GPIO Wake Enable Mask */
#define HDA_CMD_VERB_GET_GPIO_WAKE_ENABLE_MASK 0xf18
#define HDA_CMD_VERB_SET_GPIO_WAKE_ENABLE_MASK 0x718
-#define HDA_CMD_GET_GPIO_WAKE_ENABLE_MASK(cad, nid) (HDA_CMD_12BIT((cad), (nid), HDA_CMD_VERB_GET_GPIO_WAKE_ENABLE_MASK, 0x0))
-#define HDA_CMD_SET_GPIO_WAKE_ENABLE_MASK(cad, nid, payload) (HDA_CMD_12BIT((cad), (nid), HDA_CMD_VERB_SET_GPIO_WAKE_ENABLE_MASK, (payload)))
+#define HDA_CMD_GET_GPIO_WAKE_ENABLE_MASK(cad, nid) \
+ (HDA_CMD_12BIT((cad), (nid), \
+ HDA_CMD_VERB_GET_GPIO_WAKE_ENABLE_MASK, 0x0))
+#define HDA_CMD_SET_GPIO_WAKE_ENABLE_MASK(cad, nid, payload) \
+ (HDA_CMD_12BIT((cad), (nid), \
+ HDA_CMD_VERB_SET_GPIO_WAKE_ENABLE_MASK, (payload)))
/* GPIO Unsolicited Enable Mask */
#define HDA_CMD_VERB_GET_GPIO_UNSOLICITED_ENABLE_MASK 0xf19
#define HDA_CMD_VERB_SET_GPIO_UNSOLICITED_ENABLE_MASK 0x719
-#define HDA_CMD_GET_GPIO_UNSOLICITED_ENABLE_MASK(cad, nid) (HDA_CMD_12BIT((cad), (nid), HDA_CMD_VERB_GET_GPIO_UNSOLICITED_ENABLE_MASK, 0x0))
-#define HDA_CMD_SET_GPIO_UNSOLICITED_ENABLE_MASK(cad, nid, payload) (HDA_CMD_12BIT((cad), (nid), HDA_CMD_VERB_SET_GPIO_UNSOLICITED_ENABLE_MASK, (payload)))
+#define HDA_CMD_GET_GPIO_UNSOLICITED_ENABLE_MASK(cad, nid) \
+ (HDA_CMD_12BIT((cad), (nid), \
+ HDA_CMD_VERB_GET_GPIO_UNSOLICITED_ENABLE_MASK, 0x0))
+#define HDA_CMD_SET_GPIO_UNSOLICITED_ENABLE_MASK(cad, nid, payload) \
+ (HDA_CMD_12BIT((cad), (nid), \
+ HDA_CMD_VERB_SET_GPIO_UNSOLICITED_ENABLE_MASK, (payload)))
/* GPIO_STICKY_MASK */
#define HDA_CMD_VERB_GET_GPIO_STICKY_MASK 0xf1a
#define HDA_CMD_VERB_SET_GPIO_STICKY_MASK 0x71a
-#define HDA_CMD_GET_GPIO_STICKY_MASK(cad, nid) (HDA_CMD_12BIT((cad), (nid), HDA_CMD_VERB_GET_GPIO_STICKY_MASK, 0x0))
-#define HDA_CMD_SET_GPIO_STICKY_MASK(cad, nid, payload) (HDA_CMD_12BIT((cad), (nid), HDA_CMD_VERB_SET_GPIO_STICKY_MASK, (payload)))
+#define HDA_CMD_GET_GPIO_STICKY_MASK(cad, nid) \
+ (HDA_CMD_12BIT((cad), (nid), \
+ HDA_CMD_VERB_GET_GPIO_STICKY_MASK, 0x0))
+#define HDA_CMD_SET_GPIO_STICKY_MASK(cad, nid, payload) \
+ (HDA_CMD_12BIT((cad), (nid), \
+ HDA_CMD_VERB_SET_GPIO_STICKY_MASK, (payload)))
/* Beep Generation */
#define HDA_CMD_VERB_GET_BEEP_GENERATION 0xf0a
#define HDA_CMD_VERB_SET_BEEP_GENERATION 0x70a
-#define HDA_CMD_GET_BEEP_GENERATION(cad, nid) (HDA_CMD_12BIT((cad), (nid), HDA_CMD_VERB_GET_BEEP_GENERATION, 0x0))
-#define HDA_CMD_SET_BEEP_GENERATION(cad, nid, payload) (HDA_CMD_12BIT((cad), (nid), HDA_CMD_VERB_SET_BEEP_GENERATION, (payload)))
+#define HDA_CMD_GET_BEEP_GENERATION(cad, nid) \
+ (HDA_CMD_12BIT((cad), (nid), \
+ HDA_CMD_VERB_GET_BEEP_GENERATION, 0x0))
+#define HDA_CMD_SET_BEEP_GENERATION(cad, nid, payload) \
+ (HDA_CMD_12BIT((cad), (nid), \
+ HDA_CMD_VERB_SET_BEEP_GENERATION, (payload)))
/* Volume Knob */
#define HDA_CMD_VERB_GET_VOLUME_KNOB 0xf0f
#define HDA_CMD_VERB_SET_VOLUME_KNOB 0x70f
-#define HDA_CMD_GET_VOLUME_KNOB(cad, nid) (HDA_CMD_12BIT((cad), (nid), HDA_CMD_VERB_GET_VOLUME_KNOB, 0x0))
-#define HDA_CMD_SET_VOLUME_KNOB(cad, nid, payload) (HDA_CMD_12BIT((cad), (nid), HDA_CMD_VERB_SET_VOLUME_KNOB, (payload)))
+#define HDA_CMD_GET_VOLUME_KNOB(cad, nid) \
+ (HDA_CMD_12BIT((cad), (nid), \
+ HDA_CMD_VERB_GET_VOLUME_KNOB, 0x0))
+#define HDA_CMD_SET_VOLUME_KNOB(cad, nid, payload) \
+ (HDA_CMD_12BIT((cad), (nid), \
+ HDA_CMD_VERB_SET_VOLUME_KNOB, (payload)))
/* Subsystem ID */
#define HDA_CMD_VERB_GET_SUBSYSTEM_ID 0xf20
@@ -427,11 +616,21 @@
#define HDA_CMD_VERB_SET_SUBSYSTEM_ID3 0x722
#define HDA_CMD_VERB_SET_SUBSYSTEM_ID4 0x723
-#define HDA_CMD_GET_SUBSYSTEM_ID(cad, nid) (HDA_CMD_12BIT((cad), (nid), HDA_CMD_VERB_GET_SUBSYSTEM_ID, 0x0))
-#define HDA_CMD_SET_SUBSYSTEM_ID1(cad, nid, payload) (HDA_CMD_12BIT((cad), (nid), HDA_CMD_VERB_SET_SUSBYSTEM_ID1, (payload)))
-#define HDA_CMD_SET_SUBSYSTEM_ID2(cad, nid, payload) (HDA_CMD_12BIT((cad), (nid), HDA_CMD_VERB_SET_SUSBYSTEM_ID2, (payload)))
-#define HDA_CMD_SET_SUBSYSTEM_ID3(cad, nid, payload) (HDA_CMD_12BIT((cad), (nid), HDA_CMD_VERB_SET_SUSBYSTEM_ID3, (payload)))
-#define HDA_CMD_SET_SUBSYSTEM_ID4(cad, nid, payload) (HDA_CMD_12BIT((cad), (nid), HDA_CMD_VERB_SET_SUSBYSTEM_ID4, (payload)))
+#define HDA_CMD_GET_SUBSYSTEM_ID(cad, nid) \
+ (HDA_CMD_12BIT((cad), (nid), \
+ HDA_CMD_VERB_GET_SUBSYSTEM_ID, 0x0))
+#define HDA_CMD_SET_SUBSYSTEM_ID1(cad, nid, payload) \
+ (HDA_CMD_12BIT((cad), (nid), \
+ HDA_CMD_VERB_SET_SUSBYSTEM_ID1, (payload)))
+#define HDA_CMD_SET_SUBSYSTEM_ID2(cad, nid, payload) \
+ (HDA_CMD_12BIT((cad), (nid), \
+ HDA_CMD_VERB_SET_SUSBYSTEM_ID2, (payload)))
+#define HDA_CMD_SET_SUBSYSTEM_ID3(cad, nid, payload) \
+ (HDA_CMD_12BIT((cad), (nid), \
+ HDA_CMD_VERB_SET_SUSBYSTEM_ID3, (payload)))
+#define HDA_CMD_SET_SUBSYSTEM_ID4(cad, nid, payload) \
+ (HDA_CMD_12BIT((cad), (nid), \
+ HDA_CMD_VERB_SET_SUSBYSTEM_ID4, (payload)))
/* Configuration Default */
#define HDA_CMD_VERB_GET_CONFIGURATION_DEFAULT 0xf1c
@@ -440,28 +639,44 @@
#define HDA_CMD_VERB_SET_CONFIGURATION_DEFAULT3 0x71e
#define HDA_CMD_VERB_SET_CONFIGURATION_DEFAULT4 0x71f
-#define HDA_CMD_GET_CONFIGURATION_DEFAULT(cad, nid) (HDA_CMD_12BIT((cad), (nid), HDA_CMD_VERB_GET_CONFIGURATION_DEFAULT, 0x0))
-#define HDA_CMD_SET_CONFIGURATION_DEFAULT1(cad, nid, payload) (HDA_CMD_12BIT((cad), (nid), HDA_CMD_VERB_SET_CONFIGURATION_DEFAULT1, (payload)))
-#define HDA_CMD_SET_CONFIGURATION_DEFAULT2(cad, nid, payload) (HDA_CMD_12BIT((cad), (nid), HDA_CMD_VERB_SET_CONFIGURATION_DEFAULT2, (payload)))
-#define HDA_CMD_SET_CONFIGURATION_DEFAULT3(cad, nid, payload) (HDA_CMD_12BIT((cad), (nid), HDA_CMD_VERB_SET_CONFIGURATION_DEFAULT3, (payload)))
-#define HDA_CMD_SET_CONFIGURATION_DEFAULT4(cad, nid, payload) (HDA_CMD_12BIT((cad), (nid), HDA_CMD_VERB_SET_CONFIGURATION_DEFAULT4, (payload)))
+#define HDA_CMD_GET_CONFIGURATION_DEFAULT(cad, nid) \
+ (HDA_CMD_12BIT((cad), (nid), \
+ HDA_CMD_VERB_GET_CONFIGURATION_DEFAULT, 0x0))
+#define HDA_CMD_SET_CONFIGURATION_DEFAULT1(cad, nid, payload) \
+ (HDA_CMD_12BIT((cad), (nid), \
+ HDA_CMD_VERB_SET_CONFIGURATION_DEFAULT1, (payload)))
+#define HDA_CMD_SET_CONFIGURATION_DEFAULT2(cad, nid, payload) \
+ (HDA_CMD_12BIT((cad), (nid), \
+ HDA_CMD_VERB_SET_CONFIGURATION_DEFAULT2, (payload)))
+#define HDA_CMD_SET_CONFIGURATION_DEFAULT3(cad, nid, payload) \
+ (HDA_CMD_12BIT((cad), (nid), \
+ HDA_CMD_VERB_SET_CONFIGURATION_DEFAULT3, (payload)))
+#define HDA_CMD_SET_CONFIGURATION_DEFAULT4(cad, nid, payload) \
+ (HDA_CMD_12BIT((cad), (nid), \
+ HDA_CMD_VERB_SET_CONFIGURATION_DEFAULT4, (payload)))
/* Stripe Control */
#define HDA_CMD_VERB_GET_STRIPE_CONTROL 0xf24
#define HDA_CMD_VERB_SET_STRIPE_CONTROL 0x724
-#define HDA_CMD_SET_STRIPE_CONTROL(cad, nid) (HDA_CMD_12BIT((cad), (nid), HDA_CMD_VERB_GET_STRIPE_CONTROL, 0x0))
-#define HDA_CMD_GET_STRIPE_CONTROL(cad, nid, payload) (HDA_CMD_12BIT((cad), (nid), HDA_CMD_VERB_SET_STRIPE_CONTROL, (payload)))
+#define HDA_CMD_SET_STRIPE_CONTROL(cad, nid) \
+ (HDA_CMD_12BIT((cad), (nid), \
+ HDA_CMD_VERB_GET_STRIPE_CONTROL, 0x0))
+#define HDA_CMD_GET_STRIPE_CONTROL(cad, nid, payload) \
+ (HDA_CMD_12BIT((cad), (nid), \
+ HDA_CMD_VERB_SET_STRIPE_CONTROL, (payload)))
/* Function Reset */
#define HDA_CMD_VERB_FUNCTION_RESET 0x7ff
-#define HDA_CMD_FUNCTION_RESET(cad, nid) (HDA_CMD_12BIT((cad), (nid), HDA_CMD_VERB_FUNCTION_RESET, 0x0))
+#define HDA_CMD_FUNCTION_RESET(cad, nid) \
+ (HDA_CMD_12BIT((cad), (nid), \
+ HDA_CMD_VERB_FUNCTION_RESET, 0x0))
/****************************************************************************
-* HDA Device Parameters
-****************************************************************************/
+ * HDA Device Parameters
+ ****************************************************************************/
/* Vendor ID */
#define HDA_PARAM_VENDOR_ID 0x00
@@ -471,8 +686,12 @@
#define HDA_PARAM_VENDOR_ID_DEVICE_ID_MASK 0x0000ffff
#define HDA_PARAM_VENDOR_ID_DEVICE_ID_SHIFT 0
-#define HDA_PARAM_VENDOR_ID_VENDOR_ID(param) (((param) & HDA_PARAM_VENDOR_ID_VENDOR_ID_MASK) >> HDA_PARAM_VENDOR_ID_VENDOR_ID_SHIFT)
-#define HDA_PARAM_VENDOR_ID_DEVICE_ID(param) (((param) & HDA_PARAM_VENDOR_ID_DEVICE_ID_MASK) >> HDA_PARAM_VENDOR_ID_DEVICE_ID_SHIFT)
+#define HDA_PARAM_VENDOR_ID_VENDOR_ID(param) \
+ (((param) & HDA_PARAM_VENDOR_ID_VENDOR_ID_MASK) >> \
+ HDA_PARAM_VENDOR_ID_VENDOR_ID_SHIFT)
+#define HDA_PARAM_VENDOR_ID_DEVICE_ID(param) \
+ (((param) & HDA_PARAM_VENDOR_ID_DEVICE_ID_MASK) >> \
+ HDA_PARAM_VENDOR_ID_DEVICE_ID_SHIFT)
/* Revision ID */
#define HDA_PARAM_REVISION_ID 0x02
@@ -486,10 +705,18 @@
#define HDA_PARAM_REVISION_ID_STEPPING_ID_MASK 0x000000ff
#define HDA_PARAM_REVISION_ID_STEPPING_ID_SHIFT 0
-#define HDA_PARAM_REVISION_ID_MAJREV(param) (((param) & HDA_PARAM_REVISION_ID_MAJREV_MASK) >> HDA_PARAM_REVISION_ID_MAJREV_SHIFT)
-#define HDA_PARAM_REVISION_ID_MINREV(param) (((param) & HDA_PARAM_REVISION_ID_MINREV_MASK) >> HDA_PARAM_REVISION_ID_MINREV_SHIFT)
-#define HDA_PARAM_REVISION_ID_REVISION_ID(param) (((param) & HDA_PARAM_REVISION_ID_REVISION_ID_MASK) >> HDA_PARAM_REVISION_ID_REVISION_ID_SHIFT)
-#define HDA_PARAM_REVISION_ID_STEPPING_ID(param) (((param) & HDA_PARAM_REVISION_ID_STEPPING_ID_MASK) >> HDA_PARAM_REVISION_ID_STEPPING_ID_SHIFT)
+#define HDA_PARAM_REVISION_ID_MAJREV(param) \
+ (((param) & HDA_PARAM_REVISION_ID_MAJREV_MASK) >> \
+ HDA_PARAM_REVISION_ID_MAJREV_SHIFT)
+#define HDA_PARAM_REVISION_ID_MINREV(param) \
+ (((param) & HDA_PARAM_REVISION_ID_MINREV_MASK) >> \
+ HDA_PARAM_REVISION_ID_MINREV_SHIFT)
+#define HDA_PARAM_REVISION_ID_REVISION_ID(param) \
+ (((param) & HDA_PARAM_REVISION_ID_REVISION_ID_MASK) >> \
+ HDA_PARAM_REVISION_ID_REVISION_ID_SHIFT)
+#define HDA_PARAM_REVISION_ID_STEPPING_ID(param) \
+ (((param) & HDA_PARAM_REVISION_ID_STEPPING_ID_MASK) >> \
+ HDA_PARAM_REVISION_ID_STEPPING_ID_SHIFT)
/* Subordinate Node Cound */
#define HDA_PARAM_SUB_NODE_COUNT 0x04
@@ -499,8 +726,12 @@
#define HDA_PARAM_SUB_NODE_COUNT_TOTAL_MASK 0x000000ff
#define HDA_PARAM_SUB_NODE_COUNT_TOTAL_SHIFT 0
-#define HDA_PARAM_SUB_NODE_COUNT_START(param) (((param) & HDA_PARAM_SUB_NODE_COUNT_START_MASK) >> HDA_PARAM_SUB_NODE_COUNT_START_SHIFT)
-#define HDA_PARAM_SUB_NODE_COUNT_TOTAL(param) (((param) & HDA_PARAM_SUB_NODE_COUNT_TOTAL_MASK) >> HDA_PARAM_SUB_NODE_COUNT_TOTAL_SHIFT)
+#define HDA_PARAM_SUB_NODE_COUNT_START(param) \
+ (((param) & HDA_PARAM_SUB_NODE_COUNT_START_MASK) >> \
+ HDA_PARAM_SUB_NODE_COUNT_START_SHIFT)
+#define HDA_PARAM_SUB_NODE_COUNT_TOTAL(param) \
+ (((param) & HDA_PARAM_SUB_NODE_COUNT_TOTAL_MASK) >> \
+ HDA_PARAM_SUB_NODE_COUNT_TOTAL_SHIFT)
/* Function Group Type */
#define HDA_PARAM_FCT_GRP_TYPE 0x05
@@ -510,8 +741,12 @@
#define HDA_PARAM_FCT_GRP_TYPE_NODE_TYPE_MASK 0x000000ff
#define HDA_PARAM_FCT_GRP_TYPE_NODE_TYPE_SHIFT 0
-#define HDA_PARAM_FCT_GRP_TYPE_UNSOL(param) (((param) & HDA_PARAM_FCT_GRP_TYPE_UNSOL_MASK) >> HDA_PARAM_FCT_GROUP_TYPE_UNSOL_SHIFT)
-#define HDA_PARAM_FCT_GRP_TYPE_NODE_TYPE(param) (((param) & HDA_PARAM_FCT_GRP_TYPE_NODE_TYPE_MASK) >> HDA_PARAM_FCT_GRP_TYPE_NODE_TYPE_SHIFT)
+#define HDA_PARAM_FCT_GRP_TYPE_UNSOL(param) \
+ (((param) & HDA_PARAM_FCT_GRP_TYPE_UNSOL_MASK) >> \
+ HDA_PARAM_FCT_GROUP_TYPE_UNSOL_SHIFT)
+#define HDA_PARAM_FCT_GRP_TYPE_NODE_TYPE(param) \
+ (((param) & HDA_PARAM_FCT_GRP_TYPE_NODE_TYPE_MASK) >> \
+ HDA_PARAM_FCT_GRP_TYPE_NODE_TYPE_SHIFT)
#define HDA_PARAM_FCT_GRP_TYPE_NODE_TYPE_AUDIO 0x01
#define HDA_PARAM_FCT_GRP_TYPE_NODE_TYPE_MODEM 0x02
@@ -526,9 +761,15 @@
#define HDA_PARAM_AUDIO_FCT_GRP_CAP_OUTPUT_DELAY_MASK 0x0000000f
#define HDA_PARAM_AUDIO_FCT_GRP_CAP_OUTPUT_DELAY_SHIFT 0
-#define HDA_PARAM_AUDIO_FCT_GRP_CAP_BEEP_GEN(param) (((param) & HDA_PARAM_AUDIO_FCT_GRP_CAP_BEEP_GEN_MASK) >> HDA_PARAM_AUDIO_FCT_GRP_CAP_BEEP_GEN_SHIFT)
-#define HDA_PARAM_AUDIO_FCT_GRP_CAP_INPUT_DELAY(param) (((param) & HDA_PARAM_AUDIO_FCT_GRP_CAP_INPUT_DELAY_MASK) >> HDA_PARAM_AUDIO_FCT_GRP_CAP_INPUT_DELAY_SHIFT)
-#define HDA_PARAM_AUDIO_FCT_GRP_CAP_OUTPUT_DELAY(param) (((param) & HDA_PARAM_AUDIO_FCT_GRP_CAP_OUTPUT_DELAY_MASK) >> HDA_PARAM_AUDIO_FCT_GRP_CAP_OUTPUT_DELAY_SHIFT)
+#define HDA_PARAM_AUDIO_FCT_GRP_CAP_BEEP_GEN(param) \
+ (((param) & HDA_PARAM_AUDIO_FCT_GRP_CAP_BEEP_GEN_MASK) >> \
+ HDA_PARAM_AUDIO_FCT_GRP_CAP_BEEP_GEN_SHIFT)
+#define HDA_PARAM_AUDIO_FCT_GRP_CAP_INPUT_DELAY(param) \
+ (((param) & HDA_PARAM_AUDIO_FCT_GRP_CAP_INPUT_DELAY_MASK) >> \
+ HDA_PARAM_AUDIO_FCT_GRP_CAP_INPUT_DELAY_SHIFT)
+#define HDA_PARAM_AUDIO_FCT_GRP_CAP_OUTPUT_DELAY(param) \
+ (((param) & HDA_PARAM_AUDIO_FCT_GRP_CAP_OUTPUT_DELAY_MASK) >> \
+ HDA_PARAM_AUDIO_FCT_GRP_CAP_OUTPUT_DELAY_SHIFT)
/* Audio Widget Capabilities */
#define HDA_PARAM_AUDIO_WIDGET_CAP 0x09
@@ -562,20 +803,48 @@
#define HDA_PARAM_AUDIO_WIDGET_CAP_STEREO_MASK 0x00000001
#define HDA_PARAM_AUDIO_WIDGET_CAP_STEREO_SHIFT 0
-#define HDA_PARAM_AUDIO_WIDGET_CAP_TYPE(param) (((param) & HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_MASK) >> HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_SHIFT)
-#define HDA_PARAM_AUDIO_WIDGET_CAP_DELAY(param) (((param) & HDA_PARAM_AUDIO_WIDGET_CAP_DELAY_MASK) >> HDA_PARAM_AUDIO_WIDGET_CAP_DELAY_SHIFT)
-#define HDA_PARAM_AUDIO_WIDGET_CAP_LR_SWAP(param) (((param) & HDA_PARAM_AUDIO_WIDGET_CAP_LR_SWAP_MASK) >> HDA_PARAM_AUDIO_WIDGET_CAP_LR_SWAP_SHIFT)
-#define HDA_PARAM_AUDIO_WIDGET_CAP_POWER_CTRL(param) (((param) & HDA_PARAM_AUDIO_WIDGET_CAP_POWER_CTRL_MASK) >> HDA_PARAM_AUDIO_WIDGET_CAP_POWER_CTRL_SHIFT)
-#define HDA_PARAM_AUDIO_WIDGET_CAP_DIGITAL(param) (((param) & HDA_PARAM_AUDIO_WIDGET_CAP_DIGITAL_MASK) >> HDA_PARAM_AUDIO_WIDGET_CAP_DIGITAL_SHIFT)
-#define HDA_PARAM_AUDIO_WIDGET_CAP_CONN_LIST(param) (((param) & HDA_PARAM_AUDIO_WIDGET_CAP_CONN_LIST_MASK) >> HDA_PARAM_AUDIO_WIDGET_CAP_CONN_LIST_SHIFT)
-#define HDA_PARAM_AUDIO_WIDGET_CAP_UNSOL_CAP(param) (((param) & HDA_PARAM_AUDIO_WIDGET_CAP_UNSOL_CAP_MASK) >> HDA_PARAM_AUDIO_WIDGET_CAP_UNSOL_CAP_SHIFT)
-#define HDA_PARAM_AUDIO_WIDGET_CAP_PROC_WIDGET(param) (((param) & HDA_PARAM_AUDIO_WIDGET_CAP_PROC_WIDGET_MASK) >> HDA_PARAM_AUDIO_WIDGET_CAP_PROC_WIDGET_SHIFT)
-#define HDA_PARAM_AUDIO_WIDGET_CAP_STRIPE(param) (((param) & HDA_PARAM_AUDIO_WIDGET_CAP_STRIPE_MASK) >> HDA_PARAM_AUDIO_WIDGET_CAP_STRIPE_SHIFT)
-#define HDA_PARAM_AUDIO_WIDGET_CAP_FORMAT_OVR(param) (((param) & HDA_PARAM_AUDIO_WIDGET_CAP_FORMAT_OVR_MASK) >> HDA_PARAM_AUDIO_WIDGET_CAP_FORMAT_OVR_SHIFT)
-#define HDA_PARAM_AUDIO_WIDGET_CAP_AMP_OVR(param) (((param) & HDA_PARAM_AUDIO_WIDGET_CAP_AMP_OVR_MASK) >> HDA_PARAM_AUDIO_WIDGET_CAP_AMP_OVR_SHIFT)
-#define HDA_PARAM_AUDIO_WIDGET_CAP_OUT_AMP(param) (((param) & HDA_PARAM_AUDIO_WIDGET_CAP_OUT_AMP_MASK) >> HDA_PARAM_AUDIO_WIDGET_CAP_OUT_AMP_SHIFT)
-#define HDA_PARAM_AUDIO_WIDGET_CAP_IN_AMP(param) (((param) & HDA_PARAM_AUDIO_WIDGET_CAP_IN_AMP_MASK) >> HDA_PARAM_AUDIO_WIDGET_CAP_IN_AMP_SHIFT)
-#define HDA_PARAM_AUDIO_WIDGET_CAP_STEREO(param) (((param) & HDA_PARAM_AUDIO_WIDGET_CAP_STEREO_MASK) >> HDA_PARAM_AUDIO_WIDGET_CAP_STEREO_SHIFT)
+#define HDA_PARAM_AUDIO_WIDGET_CAP_TYPE(param) \
+ (((param) & HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_MASK) >> \
+ HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_SHIFT)
+#define HDA_PARAM_AUDIO_WIDGET_CAP_DELAY(param) \
+ (((param) & HDA_PARAM_AUDIO_WIDGET_CAP_DELAY_MASK) >> \
+ HDA_PARAM_AUDIO_WIDGET_CAP_DELAY_SHIFT)
+#define HDA_PARAM_AUDIO_WIDGET_CAP_LR_SWAP(param) \
+ (((param) & HDA_PARAM_AUDIO_WIDGET_CAP_LR_SWAP_MASK) >> \
+ HDA_PARAM_AUDIO_WIDGET_CAP_LR_SWAP_SHIFT)
+#define HDA_PARAM_AUDIO_WIDGET_CAP_POWER_CTRL(param) \
+ (((param) & HDA_PARAM_AUDIO_WIDGET_CAP_POWER_CTRL_MASK) >> \
+ HDA_PARAM_AUDIO_WIDGET_CAP_POWER_CTRL_SHIFT)
+#define HDA_PARAM_AUDIO_WIDGET_CAP_DIGITAL(param) \
+ (((param) & HDA_PARAM_AUDIO_WIDGET_CAP_DIGITAL_MASK) >> \
+ HDA_PARAM_AUDIO_WIDGET_CAP_DIGITAL_SHIFT)
+#define HDA_PARAM_AUDIO_WIDGET_CAP_CONN_LIST(param) \
+ (((param) & HDA_PARAM_AUDIO_WIDGET_CAP_CONN_LIST_MASK) >> \
+ HDA_PARAM_AUDIO_WIDGET_CAP_CONN_LIST_SHIFT)
+#define HDA_PARAM_AUDIO_WIDGET_CAP_UNSOL_CAP(param) \
+ (((param) & HDA_PARAM_AUDIO_WIDGET_CAP_UNSOL_CAP_MASK) >> \
+ HDA_PARAM_AUDIO_WIDGET_CAP_UNSOL_CAP_SHIFT)
+#define HDA_PARAM_AUDIO_WIDGET_CAP_PROC_WIDGET(param) \
+ (((param) & HDA_PARAM_AUDIO_WIDGET_CAP_PROC_WIDGET_MASK) >> \
+ HDA_PARAM_AUDIO_WIDGET_CAP_PROC_WIDGET_SHIFT)
+#define HDA_PARAM_AUDIO_WIDGET_CAP_STRIPE(param) \
+ (((param) & HDA_PARAM_AUDIO_WIDGET_CAP_STRIPE_MASK) >> \
+ HDA_PARAM_AUDIO_WIDGET_CAP_STRIPE_SHIFT)
+#define HDA_PARAM_AUDIO_WIDGET_CAP_FORMAT_OVR(param) \
+ (((param) & HDA_PARAM_AUDIO_WIDGET_CAP_FORMAT_OVR_MASK) >> \
+ HDA_PARAM_AUDIO_WIDGET_CAP_FORMAT_OVR_SHIFT)
+#define HDA_PARAM_AUDIO_WIDGET_CAP_AMP_OVR(param) \
+ (((param) & HDA_PARAM_AUDIO_WIDGET_CAP_AMP_OVR_MASK) >> \
+ HDA_PARAM_AUDIO_WIDGET_CAP_AMP_OVR_SHIFT)
+#define HDA_PARAM_AUDIO_WIDGET_CAP_OUT_AMP(param) \
+ (((param) & HDA_PARAM_AUDIO_WIDGET_CAP_OUT_AMP_MASK) >> \
+ HDA_PARAM_AUDIO_WIDGET_CAP_OUT_AMP_SHIFT)
+#define HDA_PARAM_AUDIO_WIDGET_CAP_IN_AMP(param) \
+ (((param) & HDA_PARAM_AUDIO_WIDGET_CAP_IN_AMP_MASK) >> \
+ HDA_PARAM_AUDIO_WIDGET_CAP_IN_AMP_SHIFT)
+#define HDA_PARAM_AUDIO_WIDGET_CAP_STEREO(param) \
+ (((param) & HDA_PARAM_AUDIO_WIDGET_CAP_STEREO_MASK) >> \
+ HDA_PARAM_AUDIO_WIDGET_CAP_STEREO_SHIFT)
#define HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_OUTPUT 0x0
#define HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_INPUT 0x1
@@ -601,48 +870,82 @@
#define HDA_PARAM_SUPP_PCM_SIZE_RATE_16BIT_SHIFT 17
#define HDA_PARAM_SUPP_PCM_SIZE_RATE_8BIT_MASK 0x00010000
#define HDA_PARAM_SUPP_PCM_SIZE_RATE_8BIT_SHIFT 16
-#define HDA_PARAM_SUPP_PCM_SIZE_RATE_8KHZ_MASK 0x00000800
-#define HDA_PARAM_SUPP_PCM_SIZE_RATE_8KHZ_SHIFT 11
-#define HDA_PARAM_SUPP_PCM_SIZE_RATE_11KHZ_MASK 0x00000400
-#define HDA_PARAM_SUPP_PCM_SIZE_RATE_11KHZ_SHIFT 10
-#define HDA_PARAM_SUPP_PCM_SIZE_RATE_16KHZ_MASK 0x00000200
-#define HDA_PARAM_SUPP_PCM_SIZE_RATE_16KHZ_SHIFT 9
-#define HDA_PARAM_SUPP_PCM_SIZE_RATE_22KHZ_MASK 0x00000100
-#define HDA_PARAM_SUPP_PCM_SIZE_RATE_22KHZ_SHIFT 8
-#define HDA_PARAM_SUPP_PCM_SIZE_RATE_32KHZ_MASK 0x00000080
-#define HDA_PARAM_SUPP_PCM_SIZE_RATE_32KHZ_SHIFT 7
-#define HDA_PARAM_SUPP_PCM_SIZE_RATE_44KHZ_MASK 0x00000040
-#define HDA_PARAM_SUPP_PCM_SIZE_RATE_44KHZ_SHIFT 6
-#define HDA_PARAM_SUPP_PCM_SIZE_RATE_48KHZ_MASK 0x00000020
-#define HDA_PARAM_SUPP_PCM_SIZE_RATE_48KHZ_SHIFT 5
-#define HDA_PARAM_SUPP_PCM_SIZE_RATE_88KHZ_MASK 0x00000010
-#define HDA_PARAM_SUPP_PCM_SIZE_RATE_88KHZ_SHIFT 4
-#define HDA_PARAM_SUPP_PCM_SIZE_RATE_96KHZ_MASK 0x00000008
-#define HDA_PARAM_SUPP_PCM_SIZE_RATE_96KHZ_SHIFT 3
-#define HDA_PARAM_SUPP_PCM_SIZE_RATE_176KHZ_MASK 0x000000004
-#define HDA_PARAM_SUPP_PCM_SIZE_RATE_176KHZ_SHIFT 2
-#define HDA_PARAM_SUPP_PCM_SIZE_RATE_192KHZ_MASK 0x000000002
-#define HDA_PARAM_SUPP_PCM_SIZE_RATE_192KHZ_SHIFT 1
-#define HDA_PARAM_SUPP_PCM_SIZE_RATE_384KHZ_MASK 0x000000001
-#define HDA_PARAM_SUPP_PCM_SIZE_RATE_384KHZ_SHIFT 0
-
-#define HDA_PARAM_SUPP_PCM_SIZE_RATE_32BIT(param) (((param) & HDA_PARAM_SUPP_PCM_SIZE_RATE_32BIT_MASK) >> HDA_PARAM_SUPP_PCM_SIZE_RATE_32BIT_SHIFT)
-#define HDA_PARAM_SUPP_PCM_SIZE_RATE_24BIT(param) (((param) & HDA_PARAM_SUPP_PCM_SIZE_RATE_24BIT_MASK) >> HDA_PARAM_SUPP_PCM_SIZE_RATE_24BIT_SHIFT)
-#define HDA_PARAM_SUPP_PCM_SIZE_RATE_20BIT(param) (((param) & HDA_PARAM_SUPP_PCM_SIZE_RATE_20BIT_MASK) >> HDA_PARAM_SUPP_PCM_SIZE_RATE_20BIT_SHIFT)
-#define HDA_PARAM_SUPP_PCM_SIZE_RATE_16BIT(param) (((param) & HDA_PARAM_SUPP_PCM_SIZE_RATE_16BIT_MASK) >> HDA_PARAM_SUPP_PCM_SIZE_RATE_16BIT_SHIFT)
-#define HDA_PARAM_SUPP_PCM_SIZE_RATE_8BIT(param) (((param) & HDA_PARAM_SUPP_PCM_SIZE_RATE_8BIT_MASK) >> HDA_PARAM_SUPP_PCM_SIZE_RATE_8BIT_SHIFT)
-#define HDA_PARAM_SUPP_PCM_SIZE_RATE_8KHZ(param) (((param) & HDA_PARAM_SUPP_PCM_SIZE_RATE_8KHZ_MASK) >> HDA_PARAM_SUPP_PCM_SIZE_RATE_8KHZ_SHIFT)
-#define HDA_PARAM_SUPP_PCM_SIZE_RATE_11KHZ(param) (((param) & HDA_PARAM_SUPP_PCM_SIZE_RATE_11KHZ_MASK) >> HDA_PARAM_SUPP_PCM_SIZE_RATE_11KHZ_SHIFT)
-#define HDA_PARAM_SUPP_PCM_SIZE_RATE_16KHZ(param) (((param) & HDA_PARAM_SUPP_PCM_SIZE_RATE_16KHZ_MASK) >> HDA_PARAM_SUPP_PCM_SIZE_RATE_16KHZ_SHIFT)
-#define HDA_PARAM_SUPP_PCM_SIZE_RATE_22KHZ(param) (((param) & HDA_PARAM_SUPP_PCM_SIZE_RATE_22KHZ_MASK) >> HDA_PARAM_SUPP_PCM_SIZE_RATE_22KHZ_SHIFT)
-#define HDA_PARAM_SUPP_PCM_SIZE_RATE_32KHZ(param) (((param) & HDA_PARAM_SUPP_PCM_SIZE_RATE_32KHZ_MASK) >> HDA_PARAM_SUPP_PCM_SIZE_RATE_32KHZ_SHIFT)
-#define HDA_PARAM_SUPP_PCM_SIZE_RATE_44KHZ(param) (((param) & HDA_PARAM_SUPP_PCM_SIZE_RATE_44KHZ_MASK) >> HDA_PARAM_SUPP_PCM_SIZE_RATE_44KHZ_SHIFT)
-#define HDA_PARAM_SUPP_PCM_SIZE_RATE_48KHZ(param) (((param) & HDA_PARAM_SUPP_PCM_SIZE_RATE_48KHZ_MASK) >> HDA_PARAM_SUPP_PCM_SIZE_RATE_48KHZ_SHIFT)
-#define HDA_PARAM_SUPP_PCM_SIZE_RATE_88KHZ(param) (((param) & HDA_PARAM_SUPP_PCM_SIZE_RATE_88KHZ_MASK) >> HDA_PARAM_SUPP_PCM_SIZE_RATE_88KHZ_SHIFT)
-#define HDA_PARAM_SUPP_PCM_SIZE_RATE_96KHZ(param) (((param) & HDA_PARAM_SUPP_PCM_SIZE_RATE_96KHZ_MASK) >> HDA_PARAM_SUPP_PCM_SIZE_RATE_96KHZ_SHIFT)
-#define HDA_PARAM_SUPP_PCM_SIZE_RATE_176KHZ(param) (((param) & HDA_PARAM_SUPP_PCM_SIZE_RATE_176KHZ_MASK) >> HDA_PARAM_SUPP_PCM_SIZE_RATE_176KHZ_SHIFT)
-#define HDA_PARAM_SUPP_PCM_SIZE_RATE_192KHZ(param) (((param) & HDA_PARAM_SUPP_PCM_SIZE_RATE_192KHZ_MASK) >> HDA_PARAM_SUPP_PCM_SIZE_RATE_192KHZ_SHIFT)
-#define HDA_PARAM_SUPP_PCM_SIZE_RATE_384KHZ(param) (((param) & HDA_PARAM_SUPP_PCM_SIZE_RATE_384KHZ_MASK) >> HDA_PARAM_SUPP_PCM_SIZE_RATE_384KHZ_SHIFT)
+#define HDA_PARAM_SUPP_PCM_SIZE_RATE_8KHZ_MASK 0x00000001
+#define HDA_PARAM_SUPP_PCM_SIZE_RATE_8KHZ_SHIFT 0
+#define HDA_PARAM_SUPP_PCM_SIZE_RATE_11KHZ_MASK 0x00000002
+#define HDA_PARAM_SUPP_PCM_SIZE_RATE_11KHZ_SHIFT 1
+#define HDA_PARAM_SUPP_PCM_SIZE_RATE_16KHZ_MASK 0x00000004
+#define HDA_PARAM_SUPP_PCM_SIZE_RATE_16KHZ_SHIFT 2
+#define HDA_PARAM_SUPP_PCM_SIZE_RATE_22KHZ_MASK 0x00000008
+#define HDA_PARAM_SUPP_PCM_SIZE_RATE_22KHZ_SHIFT 3
+#define HDA_PARAM_SUPP_PCM_SIZE_RATE_32KHZ_MASK 0x00000010
+#define HDA_PARAM_SUPP_PCM_SIZE_RATE_32KHZ_SHIFT 4
+#define HDA_PARAM_SUPP_PCM_SIZE_RATE_44KHZ_MASK 0x00000020
+#define HDA_PARAM_SUPP_PCM_SIZE_RATE_44KHZ_SHIFT 5
+#define HDA_PARAM_SUPP_PCM_SIZE_RATE_48KHZ_MASK 0x00000040
+#define HDA_PARAM_SUPP_PCM_SIZE_RATE_48KHZ_SHIFT 6
+#define HDA_PARAM_SUPP_PCM_SIZE_RATE_88KHZ_MASK 0x00000080
+#define HDA_PARAM_SUPP_PCM_SIZE_RATE_88KHZ_SHIFT 7
+#define HDA_PARAM_SUPP_PCM_SIZE_RATE_96KHZ_MASK 0x00000100
+#define HDA_PARAM_SUPP_PCM_SIZE_RATE_96KHZ_SHIFT 8
+#define HDA_PARAM_SUPP_PCM_SIZE_RATE_176KHZ_MASK 0x00000200
+#define HDA_PARAM_SUPP_PCM_SIZE_RATE_176KHZ_SHIFT 9
+#define HDA_PARAM_SUPP_PCM_SIZE_RATE_192KHZ_MASK 0x00000400
+#define HDA_PARAM_SUPP_PCM_SIZE_RATE_192KHZ_SHIFT 10
+#define HDA_PARAM_SUPP_PCM_SIZE_RATE_384KHZ_MASK 0x00000800
+#define HDA_PARAM_SUPP_PCM_SIZE_RATE_384KHZ_SHIFT 11
+
+#define HDA_PARAM_SUPP_PCM_SIZE_RATE_32BIT(param) \
+ (((param) & HDA_PARAM_SUPP_PCM_SIZE_RATE_32BIT_MASK) >> \
+ HDA_PARAM_SUPP_PCM_SIZE_RATE_32BIT_SHIFT)
+#define HDA_PARAM_SUPP_PCM_SIZE_RATE_24BIT(param) \
+ (((param) & HDA_PARAM_SUPP_PCM_SIZE_RATE_24BIT_MASK) >> \
+ HDA_PARAM_SUPP_PCM_SIZE_RATE_24BIT_SHIFT)
+#define HDA_PARAM_SUPP_PCM_SIZE_RATE_20BIT(param) \
+ (((param) & HDA_PARAM_SUPP_PCM_SIZE_RATE_20BIT_MASK) >> \
+ HDA_PARAM_SUPP_PCM_SIZE_RATE_20BIT_SHIFT)
+#define HDA_PARAM_SUPP_PCM_SIZE_RATE_16BIT(param) \
+ (((param) & HDA_PARAM_SUPP_PCM_SIZE_RATE_16BIT_MASK) >> \
+ HDA_PARAM_SUPP_PCM_SIZE_RATE_16BIT_SHIFT)
+#define HDA_PARAM_SUPP_PCM_SIZE_RATE_8BIT(param) \
+ (((param) & HDA_PARAM_SUPP_PCM_SIZE_RATE_8BIT_MASK) >> \
+ HDA_PARAM_SUPP_PCM_SIZE_RATE_8BIT_SHIFT)
+#define HDA_PARAM_SUPP_PCM_SIZE_RATE_8KHZ(param) \
+ (((param) & HDA_PARAM_SUPP_PCM_SIZE_RATE_8KHZ_MASK) >> \
+ HDA_PARAM_SUPP_PCM_SIZE_RATE_8KHZ_SHIFT)
+#define HDA_PARAM_SUPP_PCM_SIZE_RATE_11KHZ(param) \
+ (((param) & HDA_PARAM_SUPP_PCM_SIZE_RATE_11KHZ_MASK) >> \
+ HDA_PARAM_SUPP_PCM_SIZE_RATE_11KHZ_SHIFT)
+#define HDA_PARAM_SUPP_PCM_SIZE_RATE_16KHZ(param) \
+ (((param) & HDA_PARAM_SUPP_PCM_SIZE_RATE_16KHZ_MASK) >> \
+ HDA_PARAM_SUPP_PCM_SIZE_RATE_16KHZ_SHIFT)
+#define HDA_PARAM_SUPP_PCM_SIZE_RATE_22KHZ(param) \
+ (((param) & HDA_PARAM_SUPP_PCM_SIZE_RATE_22KHZ_MASK) >> \
+ HDA_PARAM_SUPP_PCM_SIZE_RATE_22KHZ_SHIFT)
+#define HDA_PARAM_SUPP_PCM_SIZE_RATE_32KHZ(param) \
+ (((param) & HDA_PARAM_SUPP_PCM_SIZE_RATE_32KHZ_MASK) >> \
+ HDA_PARAM_SUPP_PCM_SIZE_RATE_32KHZ_SHIFT)
+#define HDA_PARAM_SUPP_PCM_SIZE_RATE_44KHZ(param) \
+ (((param) & HDA_PARAM_SUPP_PCM_SIZE_RATE_44KHZ_MASK) >> \
+ HDA_PARAM_SUPP_PCM_SIZE_RATE_44KHZ_SHIFT)
+#define HDA_PARAM_SUPP_PCM_SIZE_RATE_48KHZ(param) \
+ (((param) & HDA_PARAM_SUPP_PCM_SIZE_RATE_48KHZ_MASK) >> \
+ HDA_PARAM_SUPP_PCM_SIZE_RATE_48KHZ_SHIFT)
+#define HDA_PARAM_SUPP_PCM_SIZE_RATE_88KHZ(param) \
+ (((param) & HDA_PARAM_SUPP_PCM_SIZE_RATE_88KHZ_MASK) >> \
+ HDA_PARAM_SUPP_PCM_SIZE_RATE_88KHZ_SHIFT)
+#define HDA_PARAM_SUPP_PCM_SIZE_RATE_96KHZ(param) \
+ (((param) & HDA_PARAM_SUPP_PCM_SIZE_RATE_96KHZ_MASK) >> \
+ HDA_PARAM_SUPP_PCM_SIZE_RATE_96KHZ_SHIFT)
+#define HDA_PARAM_SUPP_PCM_SIZE_RATE_176KHZ(param) \
+ (((param) & HDA_PARAM_SUPP_PCM_SIZE_RATE_176KHZ_MASK) >> \
+ HDA_PARAM_SUPP_PCM_SIZE_RATE_176KHZ_SHIFT)
+#define HDA_PARAM_SUPP_PCM_SIZE_RATE_192KHZ(param) \
+ (((param) & HDA_PARAM_SUPP_PCM_SIZE_RATE_192KHZ_MASK) >> \
+ HDA_PARAM_SUPP_PCM_SIZE_RATE_192KHZ_SHIFT)
+#define HDA_PARAM_SUPP_PCM_SIZE_RATE_384KHZ(param) \
+ (((param) & HDA_PARAM_SUPP_PCM_SIZE_RATE_384KHZ_MASK) >> \
+ HDA_PARAM_SUPP_PCM_SIZE_RATE_384KHZ_SHIFT)
/* Supported Stream Formats */
#define HDA_PARAM_SUPP_STREAM_FORMATS 0x0b
@@ -654,9 +957,15 @@
#define HDA_PARAM_SUPP_STREAM_FORMATS_PCM_MASK 0x00000001
#define HDA_PARAM_SUPP_STREAM_FORMATS_PCM_SHIFT 0
-#define HDA_PARAM_SUPP_STREAM_FORMATS_AC3(param) (((param) & HDA_PARAM_SUPP_STREAM_FORMATS_AC3_MASK) >> HDA_PARAM_SUPP_STREAM_FORMATS_AC3_SHIFT)
-#define HDA_PARAM_SUPP_STREAM_FORMATS_FLOAT32(param) (((param) & HDA_PARAM_SUPP_STREAM_FORMATS_FLOAT32_MASK) >> HDA_PARAM_SUPP_STREAM_FORMATS_FLOAT32_SHIFT)
-#define HDA_PARAM_SUPP_STREAM_FORMATS_PCM(param) (((param) & HDA_PARAM_SUPP_STREAM_FORMATS_PCM_MASK) >> HDA_PARAM_SUPP_STREAM_FORMATS_PCM_SHIFT)
+#define HDA_PARAM_SUPP_STREAM_FORMATS_AC3(param) \
+ (((param) & HDA_PARAM_SUPP_STREAM_FORMATS_AC3_MASK) >> \
+ HDA_PARAM_SUPP_STREAM_FORMATS_AC3_SHIFT)
+#define HDA_PARAM_SUPP_STREAM_FORMATS_FLOAT32(param) \
+ (((param) & HDA_PARAM_SUPP_STREAM_FORMATS_FLOAT32_MASK) >> \
+ HDA_PARAM_SUPP_STREAM_FORMATS_FLOAT32_SHIFT)
+#define HDA_PARAM_SUPP_STREAM_FORMATS_PCM(param) \
+ (((param) & HDA_PARAM_SUPP_STREAM_FORMATS_PCM_MASK) >> \
+ HDA_PARAM_SUPP_STREAM_FORMATS_PCM_SHIFT)
/* Pin Capabilities */
#define HDA_PARAM_PIN_CAP 0x0c
@@ -690,20 +999,48 @@
#define HDA_PARAM_PIN_CAP_IMP_SENSE_CAP_MASK 0x00000001
#define HDA_PARAM_PIN_CAP_IMP_SENSE_CAP_SHIFT 0
-#define HDA_PARAM_PIN_CAP_EAPD_CAP(param) (((param) & HDA_PARAM_PIN_CAP_EAPD_CAP_MASK) >> HDA_PARAM_PIN_CAP_EAPD_CAP_SHIFT)
-#define HDA_PARAM_PIN_CAP_VREF_CTRL(param) (((param) & HDA_PARAM_PIN_CAP_VREF_CTRL_MASK) >> HDA_PARAM_PIN_CAP_VREF_CTRL_SHIFT)
-#define HDA_PARAM_PIN_CAP_VREF_CTRL_100(param) (((param) & HDA_PARAM_PIN_CAP_VREF_CTRL_100_MASK) >> HDA_PARAM_PIN_CAP_VREF_CTRL_100_SHIFT)
-#define HDA_PARAM_PIN_CAP_VREF_CTRL_80(param) (((param) & HDA_PARAM_PIN_CAP_VREF_CTRL_80_MASK) >> HDA_PARAM_PIN_CAP_VREF_CTRL_80_SHIFT)
-#define HDA_PARAM_PIN_CAP_VREF_CTRL_GROUND(param) (((param) & HDA_PARAM_PIN_CAP_VREF_CTRL_GROUND_MASK) >> HDA_PARAM_PIN_CAP_VREF_CTRL_GROUND_SHIFT)
-#define HDA_PARAM_PIN_CAP_VREF_CTRL_50(param) (((param) & HDA_PARAM_PIN_CAP_VREF_CTRL_50_MASK) >> HDA_PARAM_PIN_CAP_VREF_CTRL_50_SHIFT)
-#define HDA_PARAM_PIN_CAP_VREF_CTRL_HIZ(param) (((param) & HDA_PARAM_PIN_CAP_VREF_CTRL_HIZ_MASK) >> HDA_PARAM_PIN_CAP_VREF_CTRL_HIZ_SHIFT)
-#define HDA_PARAM_PIN_CAP_BALANCED_IO_PINS(param) (((param) & HDA_PARAM_PIN_CAP_BALANCED_IO_PINS_MASK) >> HDA_PARAM_PIN_CAP_BALANCED_IO_PINS_SHIFT)
-#define HDA_PARAM_PIN_CAP_INPUT_CAP(param) (((param) & HDA_PARAM_PIN_CAP_INPUT_CAP_MASK) >> HDA_PARAM_PIN_CAP_INPUT_CAP_SHIFT)
-#define HDA_PARAM_PIN_CAP_OUTPUT_CAP(param) (((param) & HDA_PARAM_PIN_CAP_OUTPUT_CAP_MASK) >> HDA_PARAM_PIN_CAP_OUTPUT_CAP_SHIFT)
-#define HDA_PARAM_PIN_CAP_HEADPHONE_CAP(param) (((param) & HDA_PARAM_PIN_CAP_HEADPHONE_CAP_MASK) >> HDA_PARAM_PIN_CAP_HEADPHONE_CAP_SHIFT)
-#define HDA_PARAM_PIN_CAP_PRESENCE_DETECT_CAP(param) (((param) & HDA_PARAM_PIN_CAP_PRESENCE_DETECT_CAP_MASK) >> HDA_PARAM_PIN_CAP_PRESENCE_DETECT_CAP_MASK)
-#define HDA_PARAM_PIN_CAP_TRIGGER_REQD(param) (((param) & HDA_PARAM_PIN_CAP_TRIGGER_REQD_MASK) >> HDA_PARAM_PIN_CAP_TRIGGER_REQD_SHIFT)
-#define HDA_PARAM_PIN_CAP_IMP_SENSE_CAP(param) (((param) & HDA_PARAM_PIN_CAP_IMP_SENSE_CAP_MASK) >> HDA_PARAM_PIN_CAP_IMP_SENSE_CAP_SHIFT)
+#define HDA_PARAM_PIN_CAP_EAPD_CAP(param) \
+ (((param) & HDA_PARAM_PIN_CAP_EAPD_CAP_MASK) >> \
+ HDA_PARAM_PIN_CAP_EAPD_CAP_SHIFT)
+#define HDA_PARAM_PIN_CAP_VREF_CTRL(param) \
+ (((param) & HDA_PARAM_PIN_CAP_VREF_CTRL_MASK) >> \
+ HDA_PARAM_PIN_CAP_VREF_CTRL_SHIFT)
+#define HDA_PARAM_PIN_CAP_VREF_CTRL_100(param) \
+ (((param) & HDA_PARAM_PIN_CAP_VREF_CTRL_100_MASK) >> \
+ HDA_PARAM_PIN_CAP_VREF_CTRL_100_SHIFT)
+#define HDA_PARAM_PIN_CAP_VREF_CTRL_80(param) \
+ (((param) & HDA_PARAM_PIN_CAP_VREF_CTRL_80_MASK) >> \
+ HDA_PARAM_PIN_CAP_VREF_CTRL_80_SHIFT)
+#define HDA_PARAM_PIN_CAP_VREF_CTRL_GROUND(param) \
+ (((param) & HDA_PARAM_PIN_CAP_VREF_CTRL_GROUND_MASK) >> \
+ HDA_PARAM_PIN_CAP_VREF_CTRL_GROUND_SHIFT)
+#define HDA_PARAM_PIN_CAP_VREF_CTRL_50(param) \
+ (((param) & HDA_PARAM_PIN_CAP_VREF_CTRL_50_MASK) >> \
+ HDA_PARAM_PIN_CAP_VREF_CTRL_50_SHIFT)
+#define HDA_PARAM_PIN_CAP_VREF_CTRL_HIZ(param) \
+ (((param) & HDA_PARAM_PIN_CAP_VREF_CTRL_HIZ_MASK) >> \
+ HDA_PARAM_PIN_CAP_VREF_CTRL_HIZ_SHIFT)
+#define HDA_PARAM_PIN_CAP_BALANCED_IO_PINS(param) \
+ (((param) & HDA_PARAM_PIN_CAP_BALANCED_IO_PINS_MASK) >> \
+ HDA_PARAM_PIN_CAP_BALANCED_IO_PINS_SHIFT)
+#define HDA_PARAM_PIN_CAP_INPUT_CAP(param) \
+ (((param) & HDA_PARAM_PIN_CAP_INPUT_CAP_MASK) >> \
+ HDA_PARAM_PIN_CAP_INPUT_CAP_SHIFT)
+#define HDA_PARAM_PIN_CAP_OUTPUT_CAP(param) \
+ (((param) & HDA_PARAM_PIN_CAP_OUTPUT_CAP_MASK) >> \
+ HDA_PARAM_PIN_CAP_OUTPUT_CAP_SHIFT)
+#define HDA_PARAM_PIN_CAP_HEADPHONE_CAP(param) \
+ (((param) & HDA_PARAM_PIN_CAP_HEADPHONE_CAP_MASK) >> \
+ HDA_PARAM_PIN_CAP_HEADPHONE_CAP_SHIFT)
+#define HDA_PARAM_PIN_CAP_PRESENCE_DETECT_CAP(param) \
+ (((param) & HDA_PARAM_PIN_CAP_PRESENCE_DETECT_CAP_MASK) >> \
+ HDA_PARAM_PIN_CAP_PRESENCE_DETECT_CAP_MASK)
+#define HDA_PARAM_PIN_CAP_TRIGGER_REQD(param) \
+ (((param) & HDA_PARAM_PIN_CAP_TRIGGER_REQD_MASK) >> \
+ HDA_PARAM_PIN_CAP_TRIGGER_REQD_SHIFT)
+#define HDA_PARAM_PIN_CAP_IMP_SENSE_CAP(param) \
+ (((param) & HDA_PARAM_PIN_CAP_IMP_SENSE_CAP_MASK) >> \
+ HDA_PARAM_PIN_CAP_IMP_SENSE_CAP_SHIFT)
/* Input Amplifier Capabilities */
#define HDA_PARAM_INPUT_AMP_CAP 0x0d
@@ -717,10 +1054,18 @@
#define HDA_PARAM_INPUT_AMP_CAP_OFFSET_MASK 0x0000007f
#define HDA_PARAM_INPUT_AMP_CAP_OFFSET_SHIFT 0
-#define HDA_PARAM_INPUT_AMP_CAP_MUTE_CAP(param) (((param) & HDA_PARAM_INPUT_AMP_CAP_MUTE_CAP_MASK) >> HDA_PARAM_INPUT_AMP_CAP_MUTE_CAP_SHIFT)
-#define HDA_PARAM_INPUT_AMP_CAP_STEPSIZE(param) (((param) & HDA_PARAM_INPUT_AMP_CAP_STEPSIZE_MASK) >> HDA_PARAM_INPUT_AMP_CAP_STEPSIZE_SHIFT)
-#define HDA_PARAM_INPUT_AMP_CAP_NUMSTEPS(param) (((param) & HDA_PARAM_INPUT_AMP_CAP_NUMSTEPS_MASK) >> HDA_PARAM_INPUT_AMP_CAP_NUMSTEPS_SHIFT)
-#define HDA_PARAM_INPUT_AMP_CAP_OFFSET(param) (((param) & HDA_PARAM_INPUT_AMP_CAP_OFFSET_MASK) >> HDA_PARAM_INPUT_AMP_CAP_OFFSET_SHIFT)
+#define HDA_PARAM_INPUT_AMP_CAP_MUTE_CAP(param) \
+ (((param) & HDA_PARAM_INPUT_AMP_CAP_MUTE_CAP_MASK) >> \
+ HDA_PARAM_INPUT_AMP_CAP_MUTE_CAP_SHIFT)
+#define HDA_PARAM_INPUT_AMP_CAP_STEPSIZE(param) \
+ (((param) & HDA_PARAM_INPUT_AMP_CAP_STEPSIZE_MASK) >> \
+ HDA_PARAM_INPUT_AMP_CAP_STEPSIZE_SHIFT)
+#define HDA_PARAM_INPUT_AMP_CAP_NUMSTEPS(param) \
+ (((param) & HDA_PARAM_INPUT_AMP_CAP_NUMSTEPS_MASK) >> \
+ HDA_PARAM_INPUT_AMP_CAP_NUMSTEPS_SHIFT)
+#define HDA_PARAM_INPUT_AMP_CAP_OFFSET(param) \
+ (((param) & HDA_PARAM_INPUT_AMP_CAP_OFFSET_MASK) >> \
+ HDA_PARAM_INPUT_AMP_CAP_OFFSET_SHIFT)
/* Output Amplifier Capabilities */
#define HDA_PARAM_OUTPUT_AMP_CAP 0x12
@@ -734,10 +1079,18 @@
#define HDA_PARAM_OUTPUT_AMP_CAP_OFFSET_MASK 0x0000007f
#define HDA_PARAM_OUTPUT_AMP_CAP_OFFSET_SHIFT 0
-#define HDA_PARAM_OUTPUT_AMP_CAP_MUTE_CAP(param) (((param) & HDA_PARAM_OUTPUT_AMP_CAP_MUTE_CAP_MASK) >> HDA_PARAM_OUTPUT_AMP_CAP_MUTE_CAP_SHIFT)
-#define HDA_PARAM_OUTPUT_AMP_CAP_STEPSIZE(param) (((param) & HDA_PARAM_OUTPUT_AMP_CAP_STEPSIZE_MASK) >> HDA_PARAM_OUTPUT_AMP_CAP_STEPSIZE_SHIFT)
-#define HDA_PARAM_OUTPUT_AMP_CAP_NUMSTEPS(param) (((param) & HDA_PARAM_OUTPUT_AMP_CAP_NUMSTEPS_MASK) >> HDA_PARAM_OUTPUT_AMP_CAP_NUMSTEPS_SHIFT)
-#define HDA_PARAM_OUTPUT_AMP_CAP_OFFSET(param) (((param) & HDA_PARAM_OUTPUT_AMP_CAP_OFFSET_MASK) >> HDA_PARAM_OUTPUT_AMP_CAP_OFFSET_SHIFT)
+#define HDA_PARAM_OUTPUT_AMP_CAP_MUTE_CAP(param) \
+ (((param) & HDA_PARAM_OUTPUT_AMP_CAP_MUTE_CAP_MASK) >> \
+ HDA_PARAM_OUTPUT_AMP_CAP_MUTE_CAP_SHIFT)
+#define HDA_PARAM_OUTPUT_AMP_CAP_STEPSIZE(param) \
+ (((param) & HDA_PARAM_OUTPUT_AMP_CAP_STEPSIZE_MASK) >> \
+ HDA_PARAM_OUTPUT_AMP_CAP_STEPSIZE_SHIFT)
+#define HDA_PARAM_OUTPUT_AMP_CAP_NUMSTEPS(param) \
+ (((param) & HDA_PARAM_OUTPUT_AMP_CAP_NUMSTEPS_MASK) >> \
+ HDA_PARAM_OUTPUT_AMP_CAP_NUMSTEPS_SHIFT)
+#define HDA_PARAM_OUTPUT_AMP_CAP_OFFSET(param) \
+ (((param) & HDA_PARAM_OUTPUT_AMP_CAP_OFFSET_MASK) >> \
+ HDA_PARAM_OUTPUT_AMP_CAP_OFFSET_SHIFT)
/* Connection List Length */
#define HDA_PARAM_CONN_LIST_LENGTH 0x0e
@@ -747,8 +1100,12 @@
#define HDA_PARAM_CONN_LIST_LENGTH_LIST_LENGTH_MASK 0x0000007f
#define HDA_PARAM_CONN_LIST_LENGTH_LIST_LENGTH_SHIFT 0
-#define HDA_PARAM_CONN_LIST_LENGTH_LONG_FORM(param) (((param) & HDA_PARAM_CONN_LIST_LENGTH_LONG_FORM_MASK) >> HDA_PARAM_CONN_LIST_LENGTH_LONG_FORM_SHIFT)
-#define HDA_PARAM_CONN_LIST_LENGTH_LIST_LENGTH(param) (((param) & HDA_PARAM_CONN_LIST_LENGTH_LIST_LENGTH_MASK) >> HDA_PARAM_CONN_LIST_LENGTH_LIST_LENGTH_SHIFT)
+#define HDA_PARAM_CONN_LIST_LENGTH_LONG_FORM(param) \
+ (((param) & HDA_PARAM_CONN_LIST_LENGTH_LONG_FORM_MASK) >> \
+ HDA_PARAM_CONN_LIST_LENGTH_LONG_FORM_SHIFT)
+#define HDA_PARAM_CONN_LIST_LENGTH_LIST_LENGTH(param) \
+ (((param) & HDA_PARAM_CONN_LIST_LENGTH_LIST_LENGTH_MASK) >> \
+ HDA_PARAM_CONN_LIST_LENGTH_LIST_LENGTH_SHIFT)
/* Supported Power States */
#define HDA_PARAM_SUPP_POWER_STATES 0x0f
@@ -762,10 +1119,18 @@
#define HDA_PARAM_SUPP_POWER_STATES_D0_MASK 0x00000001
#define HDA_PARAM_SUPP_POWER_STATES_D0_SHIFT 0
-#define HDA_PARAM_SUPP_POWER_STATES_D3(param) (((param) & HDA_PARAM_SUPP_POWER_STATES_D3_MASK) >> HDA_PARAM_SUPP_POWER_STATES_D3_SHIFT)
-#define HDA_PARAM_SUPP_POWER_STATES_D2(param) (((param) & HDA_PARAM_SUPP_POWER_STATES_D2_MASK) >> HDA_PARAM_SUPP_POWER_STATES_D2_SHIFT)
-#define HDA_PARAM_SUPP_POWER_STATES_D1(param) (((param) & HDA_PARAM_SUPP_POWER_STATES_D1_MASK) >> HDA_PARAM_SUPP_POWER_STATES_D1_SHIFT)
-#define HDA_PARAM_SUPP_POWER_STATES_D0(param) (((param) & HDA_PARAM_SUPP_POWER_STATES_D0_MASK) >> HDA_PARAM_SUPP_POWER_STATES_D0_SHIFT)
+#define HDA_PARAM_SUPP_POWER_STATES_D3(param) \
+ (((param) & HDA_PARAM_SUPP_POWER_STATES_D3_MASK) >> \
+ HDA_PARAM_SUPP_POWER_STATES_D3_SHIFT)
+#define HDA_PARAM_SUPP_POWER_STATES_D2(param) \
+ (((param) & HDA_PARAM_SUPP_POWER_STATES_D2_MASK) >> \
+ HDA_PARAM_SUPP_POWER_STATES_D2_SHIFT)
+#define HDA_PARAM_SUPP_POWER_STATES_D1(param) \
+ (((param) & HDA_PARAM_SUPP_POWER_STATES_D1_MASK) >> \
+ HDA_PARAM_SUPP_POWER_STATES_D1_SHIFT)
+#define HDA_PARAM_SUPP_POWER_STATES_D0(param) \
+ (((param) & HDA_PARAM_SUPP_POWER_STATES_D0_MASK) >> \
+ HDA_PARAM_SUPP_POWER_STATES_D0_SHIFT)
/* Processing Capabilities */
#define HDA_PARAM_PROCESSING_CAP 0x10
@@ -775,8 +1140,12 @@
#define HDA_PARAM_PROCESSING_CAP_BENIGN_MASK 0x00000001
#define HDA_PARAM_PROCESSING_CAP_BENIGN_SHIFT 0
-#define HDA_PARAM_PROCESSING_CAP_NUMCOEFF(param) (((param) & HDA_PARAM_PROCESSING_CAP_NUMCOEFF_MASK) >> HDA_PARAM_PROCESSING_CAP_NUMCOEFF_SHIFT)
-#define HDA_PARAM_PROCESSING_CAP_BENIGN(param) (((param) & HDA_PARAM_PROCESSING_CAP_BENIGN_MASK) >> HDA_PARAM_PROCESSING_CAP_BENIGN_SHIFT)
+#define HDA_PARAM_PROCESSING_CAP_NUMCOEFF(param) \
+ (((param) & HDA_PARAM_PROCESSING_CAP_NUMCOEFF_MASK) >> \
+ HDA_PARAM_PROCESSING_CAP_NUMCOEFF_SHIFT)
+#define HDA_PARAM_PROCESSING_CAP_BENIGN(param) \
+ (((param) & HDA_PARAM_PROCESSING_CAP_BENIGN_MASK) >> \
+ HDA_PARAM_PROCESSING_CAP_BENIGN_SHIFT)
/* GPIO Count */
#define HDA_PARAM_GPIO_COUNT 0x11
@@ -792,11 +1161,21 @@
#define HDA_PARAM_GPIO_COUNT_NUM_GPIO_MASK 0x000000ff
#define HDA_PARAM_GPIO_COUNT_NUM_GPIO_SHIFT 0
-#define HDA_PARAM_GPIO_COUNT_GPI_WAKE(param) (((param) & HDA_PARAM_GPIO_COUNT_GPI_WAKE_MASK) >> HDA_PARAM_GPIO_COUNT_GPI_WAKE_SHIFT)
-#define HDA_PARAM_GPIO_COUNT_GPI_UNSOL(param) (((param) & HDA_PARAM_GPIO_COUNT_GPI_UNSOL_MASK) >> HDA_PARAM_GPIO_COUNT_GPI_UNSOL_SHIFT)
-#define HDA_PARAM_GPIO_COUNT_NUM_GPI(param) (((param) & HDA_PARAM_GPIO_COUNT_NUM_GPI_MASK) >> HDA_PARAM_GPIO_COUNT_NUM_GPI_SHIFT)
-#define HDA_PARAM_GPIO_COUNT_NUM_GPO(param) (((param) & HDA_PARAM_GPIO_COUNT_NUM_GPO_MASK) >> HDA_PARAM_GPIO_COUNT_NUM_GPO_SHIFT)
-#define HDA_PARAM_GPIO_COUNT_NUM_GPIO(param) (((param) & HDA_PARAM_GPIO_COUNT_NUM_GPIO_MASK) >> HDA_PARAM_GPIO_COUNT_NUM_GPIO_SHIFT)
+#define HDA_PARAM_GPIO_COUNT_GPI_WAKE(param) \
+ (((param) & HDA_PARAM_GPIO_COUNT_GPI_WAKE_MASK) >> \
+ HDA_PARAM_GPIO_COUNT_GPI_WAKE_SHIFT)
+#define HDA_PARAM_GPIO_COUNT_GPI_UNSOL(param) \
+ (((param) & HDA_PARAM_GPIO_COUNT_GPI_UNSOL_MASK) >> \
+ HDA_PARAM_GPIO_COUNT_GPI_UNSOL_SHIFT)
+#define HDA_PARAM_GPIO_COUNT_NUM_GPI(param) \
+ (((param) & HDA_PARAM_GPIO_COUNT_NUM_GPI_MASK) >> \
+ HDA_PARAM_GPIO_COUNT_NUM_GPI_SHIFT)
+#define HDA_PARAM_GPIO_COUNT_NUM_GPO(param) \
+ (((param) & HDA_PARAM_GPIO_COUNT_NUM_GPO_MASK) >> \
+ HDA_PARAM_GPIO_COUNT_NUM_GPO_SHIFT)
+#define HDA_PARAM_GPIO_COUNT_NUM_GPIO(param) \
+ (((param) & HDA_PARAM_GPIO_COUNT_NUM_GPIO_MASK) >> \
+ HDA_PARAM_GPIO_COUNT_NUM_GPIO_SHIFT)
/* Volume Knob Capabilities */
#define HDA_PARAM_VOLUME_KNOB_CAP 0x13
@@ -806,8 +1185,12 @@
#define HDA_PARAM_VOLUME_KNOB_CAP_NUM_STEPS_MASK 0x0000007f
#define HDA_PARAM_VOLUME_KNOB_CAP_NUM_STEPS_SHIFT 0
-#define HDA_PARAM_VOLUME_KNOB_CAP_DELTA(param) (((param) & HDA_PARAM_VOLUME_KNOB_CAP_DELTA_MASK) >> HDA_PARAM_VOLUME_KNOB_CAP_DELTA_SHIFT)
-#define HDA_PARAM_VOLUME_KNOB_CAP_NUM_STEPS(param) (((param) & HDA_PARAM_VOLUME_KNOB_CAP_NUM_STEPS_MASK) >> HDA_PARAM_VOLUME_KNOB_CAP_NUM_STEPS_SHIFT)
+#define HDA_PARAM_VOLUME_KNOB_CAP_DELTA(param) \
+ (((param) & HDA_PARAM_VOLUME_KNOB_CAP_DELTA_MASK) >> \
+ HDA_PARAM_VOLUME_KNOB_CAP_DELTA_SHIFT)
+#define HDA_PARAM_VOLUME_KNOB_CAP_NUM_STEPS(param) \
+ (((param) & HDA_PARAM_VOLUME_KNOB_CAP_NUM_STEPS_MASK) >> \
+ HDA_PARAM_VOLUME_KNOB_CAP_NUM_STEPS_SHIFT)
#define HDA_CONFIG_DEFAULTCONF_SEQUENCE_MASK 0x00000000f
Index: hdac_reg.h
===================================================================
RCS file: /home/cvs/src/sys/dev/sound/pci/hda/hdac_reg.h,v
retrieving revision 1.1
retrieving revision 1.2
diff -L sys/dev/sound/pci/hda/hdac_reg.h -L sys/dev/sound/pci/hda/hdac_reg.h -u -r1.1 -r1.2
--- sys/dev/sound/pci/hda/hdac_reg.h
+++ sys/dev/sound/pci/hda/hdac_reg.h
@@ -1,38 +1,37 @@
/*-
-* Copyright (c) 2006 Stephane E. Potvin <sepotvin at videotron.ca>
-* All rights reserved.
-*
-* Redistribution and use in source and binary forms, with or without
-* modification, are permitted provided that the following conditions
-* are met:
-* 1. Redistributions of source code must retain the above copyright
-* notice, this list of conditions and the following disclaimer.
-* 2. Redistributions in binary form must reproduce the above copyright
-* notice, this list of conditions and the following disclaimer in the
-* documentation and/or other materials provided with the distribution.
-*
-* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
-* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
-* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
-* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
-* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
-* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
-* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
-* SUCH DAMAGE.
-*
-* $MidnightBSD$
-* $FreeBSD: src/sys/dev/sound/pci/hda/hdac_reg.h,v 1.1 2006/10/01 11:12:59 ariff Exp $
-*/
+ * Copyright (c) 2006 Stephane E. Potvin <sepotvin at videotron.ca>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD: src/sys/dev/sound/pci/hda/hdac_reg.h,v 1.1 2006/10/01 11:12:59 ariff Exp $
+ */
#ifndef _HDAC_REG_H_
#define _HDAC_REG_H_
/****************************************************************************
-* HDA Controller Register Set
-****************************************************************************/
+ * HDA Controller Register Set
+ ****************************************************************************/
#define HDAC_GCAP 0x00 /* 2 - Global Capabilities*/
#define HDAC_VMIN 0x02 /* 1 - Minor Version */
#define HDAC_VMAJ 0x03 /* 1 - Major Version */
@@ -113,8 +112,8 @@
#define _HDAC_BSDBDBU(n, iss, oss) (0x1c + _HDAC_BSDOFFSET(n, iss, oss))
/****************************************************************************
-* HDA Controller Register Fields
-****************************************************************************/
+ * HDA Controller Register Fields
+ ****************************************************************************/
/* GCAP - Global Capabilities */
#define HDAC_GCAP_64OK 0x0001
@@ -131,9 +130,12 @@
#define HDAC_GCAP_NSDO_2SDO 0x02
#define HDAC_GCAP_NSDO_4SDO 0x04
-#define HDAC_GCAP_BSS(gcap) (((gcap) & HDAC_GCAP_BSS_MASK) >> HDAC_GCAP_BSS_SHIFT)
-#define HDAC_GCAP_ISS(gcap) (((gcap) & HDAC_GCAP_ISS_MASK) >> HDAC_GCAP_ISS_SHIFT)
-#define HDAC_GCAP_OSS(gcap) (((gcap) & HDAC_GCAP_OSS_MASK) >> HDAC_GCAP_OSS_SHIFT)
+#define HDAC_GCAP_BSS(gcap) \
+ (((gcap) & HDAC_GCAP_BSS_MASK) >> HDAC_GCAP_BSS_SHIFT)
+#define HDAC_GCAP_ISS(gcap) \
+ (((gcap) & HDAC_GCAP_ISS_MASK) >> HDAC_GCAP_ISS_SHIFT)
+#define HDAC_GCAP_OSS(gcap) \
+ (((gcap) & HDAC_GCAP_OSS_MASK) >> HDAC_GCAP_OSS_SHIFT)
/* GCTL - Global Control */
#define HDAC_GCTL_CRST 0x00000001
@@ -148,7 +150,9 @@
#define HDAC_STATESTS_SDIWAKE_MASK 0x7fff
#define HDAC_STATESTS_SDIWAKE_SHIFT 0
-#define HDAC_STATESTS_SDIWAKE(statests, n) (((((statests) & HDAC_STATESTS_SDIWAKE_MASK) >> HDAC_STATESTS_SDIWAKE_SHIFT) >> (n)) & 0x0001)
+#define HDAC_STATESTS_SDIWAKE(statests, n) \
+ (((((statests) & HDAC_STATESTS_SDIWAKE_MASK) >> \
+ HDAC_STATESTS_SDIWAKE_SHIFT) >> (n)) & 0x0001)
/* GSTS - Global Status */
#define HDAC_GSTS_FSTS 0x0002
@@ -199,7 +203,8 @@
#define HDAC_CORBSIZE_CORBSZCAP_16 0x20
#define HDAC_CORBSIZE_CORBSZCAP_256 0x40
-#define HDAC_CORBSIZE_CORBSIZE(corbsize) (((corbsize) & HDAC_CORBSIZE_CORBSIZE_MASK) >> HDAC_CORBSIZE_CORBSIZE_SHIFT)
+#define HDAC_CORBSIZE_CORBSIZE(corbsize) \
+ (((corbsize) & HDAC_CORBSIZE_CORBSIZE_MASK) >> HDAC_CORBSIZE_CORBSIZE_SHIFT)
/* RIRBWP - RIRB Write Pointer */
#define HDAC_RIRBWP_RIRBWP_MASK 0x00ff
@@ -233,7 +238,8 @@
#define HDAC_RIRBSIZE_RIRBSZCAP_16 0x20
#define HDAC_RIRBSIZE_RIRBSZCAP_256 0x40
-#define HDAC_RIRBSIZE_RIRBSIZE(rirbsize) (((rirbsize) & HDAC_RIRBSIZE_RIRBSIZE_MASK) >> HDAC_RIRBSIZE_RIRBSIZE_SHIFT)
+#define HDAC_RIRBSIZE_RIRBSIZE(rirbsize) \
+ (((rirbsize) & HDAC_RIRBSIZE_RIRBSIZE_MASK) >> HDAC_RIRBSIZE_RIRBSIZE_SHIFT)
/* DPLBASE - DMA Position Lower Base Address */
#define HDAC_DPLBASE_DPLBASE_MASK 0xffffff80
Index: hdac.c
===================================================================
RCS file: /home/cvs/src/sys/dev/sound/pci/hda/hdac.c,v
retrieving revision 1.1
retrieving revision 1.2
diff -L sys/dev/sound/pci/hda/hdac.c -L sys/dev/sound/pci/hda/hdac.c -u -r1.1 -r1.2
--- sys/dev/sound/pci/hda/hdac.c
+++ sys/dev/sound/pci/hda/hdac.c
@@ -1,78 +1,79 @@
/*-
-* Copyright (c) 2006 Stephane E. Potvin <sepotvin at videotron.ca>
-* Copyright (c) 2006 Ariff Abdullah <ariff at FreeBSD.org>
-* All rights reserved.
-*
-* Redistribution and use in source and binary forms, with or without
-* modification, are permitted provided that the following conditions
-* are met:
-* 1. Redistributions of source code must retain the above copyright
-* notice, this list of conditions and the following disclaimer.
-* 2. Redistributions in binary form must reproduce the above copyright
-* notice, this list of conditions and the following disclaimer in the
-* documentation and/or other materials provided with the distribution.
-*
-* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
-* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
-* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
-* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
-* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
-* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
-* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
-* SUCH DAMAGE.
-*/
+ * Copyright (c) 2006 Stephane E. Potvin <sepotvin at videotron.ca>
+ * Copyright (c) 2006 Ariff Abdullah <ariff at FreeBSD.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
/*
-* Intel High Definition Audio (Controller) driver for FreeBSD. Be advised
-* that this driver still in its early stage, and possible of rewrite are
-* pretty much guaranteed. There are supposedly several distinct parent/child
-* busses to make this "perfect", but as for now and for the sake of
-* simplicity, everything is gobble up within single source.
-*
-* List of subsys:
-* 1) HDA Controller support
-* 2) HDA Codecs support, which may include
-* - HDA
-* - Modem
-* - HDMI
-* 3) Widget parser - the real magic of why this driver works on so
-* many hardwares with minimal vendor specific quirk. The original
-* parser was written using Ruby and can be found at
-* http://people.freebsd.org/~ariff/HDA/parser.rb . This crude
-* ruby parser take the verbose dmesg dump as its input. Refer to
-* http://www.microsoft.com/whdc/device/audio/default.mspx for various
-* interesting documents, especiall UAA (Universal Audio Architecture).
-* 4) Possible vendor specific support.
-* (snd_hda_intel, snd_hda_ati, etc..)
-*
-* Thanks to Ahmad Ubaidah Omar @ Defenxis Sdn. Bhd. for the
-* Compaq V3000 with Conexant HDA.
-*
-* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
-* * *
-* * This driver is a collaborative effort made by: *
-* * *
-* * Stephane E. Potvin <sepotvin at videotron.ca> *
-* * Andrea Bittau <a.bittau at cs.ucl.ac.uk> *
-* * Wesley Morgan <morganw at chemikals.org> *
-* * Daniel Eischen <deischen at FreeBSD.org> *
-* * Maxime Guillaud <bsd-ports at mguillaud.net> *
-* * Ariff Abdullah <ariff at FreeBSD.org> *
-* * *
-* * ....and various people from freebsd-multimedia at FreeBSD.org *
-* * *
-* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
-*/
-
-#include <sys/ctype.h>
+ * Intel High Definition Audio (Controller) driver for FreeBSD. Be advised
+ * that this driver still in its early stage, and possible of rewrite are
+ * pretty much guaranteed. There are supposedly several distinct parent/child
+ * busses to make this "perfect", but as for now and for the sake of
+ * simplicity, everything is gobble up within single source.
+ *
+ * List of subsys:
+ * 1) HDA Controller support
+ * 2) HDA Codecs support, which may include
+ * - HDA
+ * - Modem
+ * - HDMI
+ * 3) Widget parser - the real magic of why this driver works on so
+ * many hardwares with minimal vendor specific quirk. The original
+ * parser was written using Ruby and can be found at
+ * http://people.freebsd.org/~ariff/HDA/parser.rb . This crude
+ * ruby parser take the verbose dmesg dump as its input. Refer to
+ * http://www.microsoft.com/whdc/device/audio/default.mspx for various
+ * interesting documents, especially UAA (Universal Audio Architecture).
+ * 4) Possible vendor specific support.
+ * (snd_hda_intel, snd_hda_ati, etc..)
+ *
+ * Thanks to Ahmad Ubaidah Omar @ Defenxis Sdn. Bhd. for the
+ * Compaq V3000 with Conexant HDA.
+ *
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * * *
+ * * This driver is a collaborative effort made by: *
+ * * *
+ * * Stephane E. Potvin <sepotvin at videotron.ca> *
+ * * Andrea Bittau <a.bittau at cs.ucl.ac.uk> *
+ * * Wesley Morgan <morganw at chemikals.org> *
+ * * Daniel Eischen <deischen at FreeBSD.org> *
+ * * Maxime Guillaud <bsd-ports at mguillaud.net> *
+ * * Ariff Abdullah <ariff at FreeBSD.org> *
+ * * *
+ * * ....and various people from freebsd-multimedia at FreeBSD.org *
+ * * *
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ */
#include <dev/sound/pcm/sound.h>
#include <dev/pci/pcireg.h>
#include <dev/pci/pcivar.h>
+#include <sys/ctype.h>
+#include <sys/taskqueue.h>
+
#include <dev/sound/pci/hda/hdac_private.h>
#include <dev/sound/pci/hda/hdac_reg.h>
#include <dev/sound/pci/hda/hda_reg.h>
@@ -80,21 +81,16 @@
#include "mixer_if.h"
-#define HDA_DRV_TEST_REV "20061017_0033"
+#define HDA_DRV_TEST_REV "20071129_0050"
#define HDA_WIDGET_PARSER_REV 1
-SND_DECLARE_FILE("$MidnightBSD$");
+SND_DECLARE_FILE("$FreeBSD: src/sys/dev/sound/pci/hda/hdac.c,v 1.44.2.5 2007/12/15 04:06:12 ariff Exp $");
-#undef HDA_DEBUG_ENABLED
-#define HDA_DEBUG_ENABLED 1
-
-#ifdef HDA_DEBUG_ENABLED
-#define HDA_DEBUG(stmt) do { stmt } while(0)
-#else
-#define HDA_DEBUG(stmt)
-#endif
-
-#define HDA_BOOTVERBOSE(stmt) do { if (bootverbose) { stmt } } while(0)
+#define HDA_BOOTVERBOSE(stmt) do { \
+ if (bootverbose != 0 || snd_verbose > 3) { \
+ stmt \
+ } \
+} while(0)
#if 1
#undef HDAC_INTR_EXTRA
@@ -107,30 +103,50 @@
#define hdac_lockowned(sc) mtx_owned((sc)->lock)
#define HDA_FLAG_MATCH(fl, v) (((fl) & (v)) == (v))
-#define HDA_DEV_MATCH(fl, v) ((fl) == (v) || (fl) == 0xffffffff || (((fl) & 0xffff0000) == 0xffff0000 && ((fl) & 0x0000ffff) == ((v) & 0x0000ffff)) || (((fl) & 0x0000ffff) == 0x0000ffff && ((fl) & 0xffff0000) == ((v) & 0xffff0000)))
+#define HDA_DEV_MATCH(fl, v) ((fl) == (v) || \
+ (fl) == 0xffffffff || \
+ (((fl) & 0xffff0000) == 0xffff0000 && \
+ ((fl) & 0x0000ffff) == ((v) & 0x0000ffff)) || \
+ (((fl) & 0x0000ffff) == 0x0000ffff && \
+ ((fl) & 0xffff0000) == ((v) & 0xffff0000)))
#define HDA_MATCH_ALL 0xffffffff
#define HDAC_INVALID 0xffffffff
-#define HDA_MODEL_CONSTRUCT(vendor, model) (((uint32_t)(model) << 16) | ((vendor##_VENDORID) & 0xffff))
+/* Default controller / jack sense poll: 250ms */
+#define HDAC_POLL_INTERVAL max(hz >> 2, 1)
+
+/*
+ * Make room for possible 4096 playback/record channels, in 100 years to come.
+ */
+#define HDAC_TRIGGER_NONE 0x00000000
+#define HDAC_TRIGGER_PLAY 0x00000fff
+#define HDAC_TRIGGER_REC 0x00fff000
+#define HDAC_TRIGGER_UNSOL 0x80000000
+
+#define HDA_MODEL_CONSTRUCT(vendor, model) \
+ (((uint32_t)(model) << 16) | ((vendor##_VENDORID) & 0xffff))
/* Controller models */
/* Intel */
#define INTEL_VENDORID 0x8086
#define HDA_INTEL_82801F HDA_MODEL_CONSTRUCT(INTEL, 0x2668)
+#define HDA_INTEL_63XXESB HDA_MODEL_CONSTRUCT(INTEL, 0x269a)
#define HDA_INTEL_82801G HDA_MODEL_CONSTRUCT(INTEL, 0x27d8)
#define HDA_INTEL_82801H HDA_MODEL_CONSTRUCT(INTEL, 0x284b)
-#define HDA_INTEL_63XXESB HDA_MODEL_CONSTRUCT(INTEL, 0x269a)
+#define HDA_INTEL_82801I HDA_MODEL_CONSTRUCT(INTEL, 0x293e)
#define HDA_INTEL_ALL HDA_MODEL_CONSTRUCT(INTEL, 0xffff)
/* Nvidia */
#define NVIDIA_VENDORID 0x10de
#define HDA_NVIDIA_MCP51 HDA_MODEL_CONSTRUCT(NVIDIA, 0x026c)
#define HDA_NVIDIA_MCP55 HDA_MODEL_CONSTRUCT(NVIDIA, 0x0371)
-#define HDA_NVIDIA_MCP61A HDA_MODEL_CONSTRUCT(NVIDIA, 0x03e4)
-#define HDA_NVIDIA_MCP61B HDA_MODEL_CONSTRUCT(NVIDIA, 0x03f0)
-#define HDA_NVIDIA_MCP65A HDA_MODEL_CONSTRUCT(NVIDIA, 0x044a)
-#define HDA_NVIDIA_MCP65B HDA_MODEL_CONSTRUCT(NVIDIA, 0x044b)
+#define HDA_NVIDIA_MCP61_1 HDA_MODEL_CONSTRUCT(NVIDIA, 0x03e4)
+#define HDA_NVIDIA_MCP61_2 HDA_MODEL_CONSTRUCT(NVIDIA, 0x03f0)
+#define HDA_NVIDIA_MCP65_1 HDA_MODEL_CONSTRUCT(NVIDIA, 0x044a)
+#define HDA_NVIDIA_MCP65_2 HDA_MODEL_CONSTRUCT(NVIDIA, 0x044b)
+#define HDA_NVIDIA_MCP67_1 HDA_MODEL_CONSTRUCT(NVIDIA, 0x055c)
+#define HDA_NVIDIA_MCP67_2 HDA_MODEL_CONSTRUCT(NVIDIA, 0x055d)
#define HDA_NVIDIA_ALL HDA_MODEL_CONSTRUCT(NVIDIA, 0xffff)
/* ATI */
@@ -151,17 +167,30 @@
/* OEM/subvendors */
+/* Intel */
+#define INTEL_D101GGC_SUBVENDOR HDA_MODEL_CONSTRUCT(INTEL, 0xd600)
+
/* HP/Compaq */
#define HP_VENDORID 0x103c
#define HP_V3000_SUBVENDOR HDA_MODEL_CONSTRUCT(HP, 0x30b5)
#define HP_NX7400_SUBVENDOR HDA_MODEL_CONSTRUCT(HP, 0x30a2)
#define HP_NX6310_SUBVENDOR HDA_MODEL_CONSTRUCT(HP, 0x30aa)
+#define HP_NX6325_SUBVENDOR HDA_MODEL_CONSTRUCT(HP, 0x30b0)
+#define HP_XW4300_SUBVENDOR HDA_MODEL_CONSTRUCT(HP, 0x3013)
+#define HP_3010_SUBVENDOR HDA_MODEL_CONSTRUCT(HP, 0x3010)
+#define HP_DV5000_SUBVENDOR HDA_MODEL_CONSTRUCT(HP, 0x30a5)
+#define HP_DC7700S_SUBVENDOR HDA_MODEL_CONSTRUCT(HP, 0x2801)
+#define HP_DC7700_SUBVENDOR HDA_MODEL_CONSTRUCT(HP, 0x2802)
#define HP_ALL_SUBVENDOR HDA_MODEL_CONSTRUCT(HP, 0xffff)
+/* What is wrong with XN 2563 anyway? (Got the picture ?) */
+#define HP_NX6325_SUBVENDORX 0x103c30b0
/* Dell */
#define DELL_VENDORID 0x1028
#define DELL_D820_SUBVENDOR HDA_MODEL_CONSTRUCT(DELL, 0x01cc)
#define DELL_I1300_SUBVENDOR HDA_MODEL_CONSTRUCT(DELL, 0x01c9)
+#define DELL_XPSM1210_SUBVENDOR HDA_MODEL_CONSTRUCT(DELL, 0x01d7)
+#define DELL_OPLX745_SUBVENDOR HDA_MODEL_CONSTRUCT(DELL, 0x01da)
#define DELL_ALL_SUBVENDOR HDA_MODEL_CONSTRUCT(DELL, 0xffff)
/* Clevo */
@@ -171,6 +200,10 @@
/* Acer */
#define ACER_VENDORID 0x1025
+#define ACER_A5050_SUBVENDOR HDA_MODEL_CONSTRUCT(ACER, 0x010f)
+#define ACER_A4520_SUBVENDOR HDA_MODEL_CONSTRUCT(ACER, 0x0127)
+#define ACER_A4710_SUBVENDOR HDA_MODEL_CONSTRUCT(ACER, 0x012f)
+#define ACER_3681WXM_SUBVENDOR HDA_MODEL_CONSTRUCT(ACER, 0x0110)
#define ACER_ALL_SUBVENDOR HDA_MODEL_CONSTRUCT(ACER, 0xffff)
/* Asus */
@@ -178,6 +211,17 @@
#define ASUS_M5200_SUBVENDOR HDA_MODEL_CONSTRUCT(ASUS, 0x1993)
#define ASUS_U5F_SUBVENDOR HDA_MODEL_CONSTRUCT(ASUS, 0x1263)
#define ASUS_A8JC_SUBVENDOR HDA_MODEL_CONSTRUCT(ASUS, 0x1153)
+#define ASUS_P1AH2_SUBVENDOR HDA_MODEL_CONSTRUCT(ASUS, 0x81cb)
+#define ASUS_A7M_SUBVENDOR HDA_MODEL_CONSTRUCT(ASUS, 0x1323)
+#define ASUS_A7T_SUBVENDOR HDA_MODEL_CONSTRUCT(ASUS, 0x13c2)
+#define ASUS_W6F_SUBVENDOR HDA_MODEL_CONSTRUCT(ASUS, 0x1263)
+#define ASUS_W2J_SUBVENDOR HDA_MODEL_CONSTRUCT(ASUS, 0x1971)
+#define ASUS_F3JC_SUBVENDOR HDA_MODEL_CONSTRUCT(ASUS, 0x1338)
+#define ASUS_M2V_SUBVENDOR HDA_MODEL_CONSTRUCT(ASUS, 0x81e7)
+#define ASUS_M2N_SUBVENDOR HDA_MODEL_CONSTRUCT(ASUS, 0x8234)
+#define ASUS_M2NPVMX_SUBVENDOR HDA_MODEL_CONSTRUCT(ASUS, 0x81cb)
+#define ASUS_P5BWD_SUBVENDOR HDA_MODEL_CONSTRUCT(ASUS, 0x81ec)
+#define ASUS_A8NVMCSM_SUBVENDOR HDA_MODEL_CONSTRUCT(NVIDIA, 0xcb84)
#define ASUS_ALL_SUBVENDOR HDA_MODEL_CONSTRUCT(ASUS, 0xffff)
/* IBM / Lenovo */
@@ -185,6 +229,71 @@
#define IBM_M52_SUBVENDOR HDA_MODEL_CONSTRUCT(IBM, 0x02f6)
#define IBM_ALL_SUBVENDOR HDA_MODEL_CONSTRUCT(IBM, 0xffff)
+/* Lenovo */
+#define LENOVO_VENDORID 0x17aa
+#define LENOVO_3KN100_SUBVENDOR HDA_MODEL_CONSTRUCT(LENOVO, 0x2066)
+#define LENOVO_TCA55_SUBVENDOR HDA_MODEL_CONSTRUCT(LENOVO, 0x1015)
+#define LENOVO_ALL_SUBVENDOR HDA_MODEL_CONSTRUCT(LENOVO, 0xffff)
+
+/* Samsung */
+#define SAMSUNG_VENDORID 0x144d
+#define SAMSUNG_Q1_SUBVENDOR HDA_MODEL_CONSTRUCT(SAMSUNG, 0xc027)
+#define SAMSUNG_ALL_SUBVENDOR HDA_MODEL_CONSTRUCT(SAMSUNG, 0xffff)
+
+/* Medion ? */
+#define MEDION_VENDORID 0x161f
+#define MEDION_MD95257_SUBVENDOR HDA_MODEL_CONSTRUCT(MEDION, 0x203d)
+#define MEDION_ALL_SUBVENDOR HDA_MODEL_CONSTRUCT(MEDION, 0xffff)
+
+/* Apple Computer Inc. */
+#define APPLE_VENDORID 0x106b
+#define APPLE_MB3_SUBVENDOR HDA_MODEL_CONSTRUCT(APPLE, 0x00a1)
+
+/*
+ * Apple Intel MacXXXX seems using Sigmatel codec/vendor id
+ * instead of their own, which is beyond my comprehension
+ * (see HDA_CODEC_STAC9221 below).
+ */
+#define APPLE_INTEL_MAC 0x76808384
+
+/* LG Electronics */
+#define LG_VENDORID 0x1854
+#define LG_LW20_SUBVENDOR HDA_MODEL_CONSTRUCT(LG, 0x0018)
+#define LG_ALL_SUBVENDOR HDA_MODEL_CONSTRUCT(LG, 0xffff)
+
+/* Fujitsu Siemens */
+#define FS_VENDORID 0x1734
+#define FS_PA1510_SUBVENDOR HDA_MODEL_CONSTRUCT(FS, 0x10b8)
+#define FS_SI1848_SUBVENDOR HDA_MODEL_CONSTRUCT(FS, 0x10cd)
+#define FS_ALL_SUBVENDOR HDA_MODEL_CONSTRUCT(FS, 0xffff)
+
+/* Fujitsu Limited */
+#define FL_VENDORID 0x10cf
+#define FL_S7020D_SUBVENDOR HDA_MODEL_CONSTRUCT(FL, 0x1326)
+#define FL_ALL_SUBVENDOR HDA_MODEL_CONSTRUCT(FL, 0xffff)
+
+/* Toshiba */
+#define TOSHIBA_VENDORID 0x1179
+#define TOSHIBA_U200_SUBVENDOR HDA_MODEL_CONSTRUCT(TOSHIBA, 0x0001)
+#define TOSHIBA_A135_SUBVENDOR HDA_MODEL_CONSTRUCT(TOSHIBA, 0xff01)
+#define TOSHIBA_ALL_SUBVENDOR HDA_MODEL_CONSTRUCT(TOSHIBA, 0xffff)
+
+/* Micro-Star International (MSI) */
+#define MSI_VENDORID 0x1462
+#define MSI_MS1034_SUBVENDOR HDA_MODEL_CONSTRUCT(MSI, 0x0349)
+#define MSI_MS034A_SUBVENDOR HDA_MODEL_CONSTRUCT(MSI, 0x034a)
+#define MSI_ALL_SUBVENDOR HDA_MODEL_CONSTRUCT(MSI, 0xffff)
+
+/* Giga-Byte Technology */
+#define GB_VENDORID 0x1458
+#define GB_G33S2H_SUBVENDOR HDA_MODEL_CONSTRUCT(GB, 0xa022)
+#define GP_ALL_SUBVENDOR HDA_MODEL_CONSTRUCT(GB, 0xffff)
+
+/* Uniwill ? */
+#define UNIWILL_VENDORID 0x1584
+#define UNIWILL_9075_SUBVENDOR HDA_MODEL_CONSTRUCT(UNIWILL, 0x9075)
+#define UNIWILL_9080_SUBVENDOR HDA_MODEL_CONSTRUCT(UNIWILL, 0x9080)
+
/* Misc constants.. */
#define HDA_AMP_MUTE_DEFAULT (0xffffffff)
@@ -200,151 +309,231 @@
#define HDA_ADC_PATH (1 << 1)
#define HDA_ADC_RECSEL (1 << 2)
+#define HDA_DAC_LOCKED (1 << 3)
+#define HDA_ADC_LOCKED (1 << 4)
+
#define HDA_CTL_OUT (1 << 0)
#define HDA_CTL_IN (1 << 1)
#define HDA_CTL_BOTH (HDA_CTL_IN | HDA_CTL_OUT)
-#define HDA_GPIO_MAX 15
-/* 0 - 14 = GPIO */
+#define HDA_GPIO_MAX 8
+/* 0 - 7 = GPIO , 8 = Flush */
#define HDA_QUIRK_GPIO0 (1 << 0)
#define HDA_QUIRK_GPIO1 (1 << 1)
#define HDA_QUIRK_GPIO2 (1 << 2)
-#define HDA_QUIRK_SOFTPCMVOL (1 << 15)
-#define HDA_QUIRK_FIXEDRATE (1 << 16)
-#define HDA_QUIRK_FORCESTEREO (1 << 17)
-#define HDA_QUIRK_EAPDINV (1 << 18)
+#define HDA_QUIRK_GPIO3 (1 << 3)
+#define HDA_QUIRK_GPIO4 (1 << 4)
+#define HDA_QUIRK_GPIO5 (1 << 5)
+#define HDA_QUIRK_GPIO6 (1 << 6)
+#define HDA_QUIRK_GPIO7 (1 << 7)
+#define HDA_QUIRK_GPIOFLUSH (1 << 8)
+
+/* 9 - 25 = anything else */
+#define HDA_QUIRK_SOFTPCMVOL (1 << 9)
+#define HDA_QUIRK_FIXEDRATE (1 << 10)
+#define HDA_QUIRK_FORCESTEREO (1 << 11)
+#define HDA_QUIRK_EAPDINV (1 << 12)
+#define HDA_QUIRK_DMAPOS (1 << 13)
+
+/* 26 - 31 = vrefs */
+#define HDA_QUIRK_IVREF50 (1 << 26)
+#define HDA_QUIRK_IVREF80 (1 << 27)
+#define HDA_QUIRK_IVREF100 (1 << 28)
+#define HDA_QUIRK_OVREF50 (1 << 29)
+#define HDA_QUIRK_OVREF80 (1 << 30)
+#define HDA_QUIRK_OVREF100 (1 << 31)
+
+#define HDA_QUIRK_IVREF (HDA_QUIRK_IVREF50 | HDA_QUIRK_IVREF80 | \
+ HDA_QUIRK_IVREF100)
+#define HDA_QUIRK_OVREF (HDA_QUIRK_OVREF50 | HDA_QUIRK_OVREF80 | \
+ HDA_QUIRK_OVREF100)
+#define HDA_QUIRK_VREF (HDA_QUIRK_IVREF | HDA_QUIRK_OVREF)
+
+#define SOUND_MASK_SKIP (1 << 30)
+#define SOUND_MASK_DISABLE (1 << 31)
+
+#if __FreeBSD_version < 600000
+#define taskqueue_drain(...)
+#endif
static const struct {
-char *key;
-uint32_t value;
+ char *key;
+ uint32_t value;
} hdac_quirks_tab[] = {
-{ "gpio0", HDA_QUIRK_GPIO0 },
-{ "gpio1", HDA_QUIRK_GPIO1 },
-{ "gpio2", HDA_QUIRK_GPIO2 },
-{ "softpcmvol", HDA_QUIRK_SOFTPCMVOL },
-{ "fixedrate", HDA_QUIRK_FIXEDRATE },
-{ "forcestereo", HDA_QUIRK_FORCESTEREO },
-{ "eapdinv", HDA_QUIRK_EAPDINV },
+ { "gpio0", HDA_QUIRK_GPIO0 },
+ { "gpio1", HDA_QUIRK_GPIO1 },
+ { "gpio2", HDA_QUIRK_GPIO2 },
+ { "gpio3", HDA_QUIRK_GPIO3 },
+ { "gpio4", HDA_QUIRK_GPIO4 },
+ { "gpio5", HDA_QUIRK_GPIO5 },
+ { "gpio6", HDA_QUIRK_GPIO6 },
+ { "gpio7", HDA_QUIRK_GPIO7 },
+ { "gpioflush", HDA_QUIRK_GPIOFLUSH },
+ { "softpcmvol", HDA_QUIRK_SOFTPCMVOL },
+ { "fixedrate", HDA_QUIRK_FIXEDRATE },
+ { "forcestereo", HDA_QUIRK_FORCESTEREO },
+ { "eapdinv", HDA_QUIRK_EAPDINV },
+ { "dmapos", HDA_QUIRK_DMAPOS },
+ { "ivref50", HDA_QUIRK_IVREF50 },
+ { "ivref80", HDA_QUIRK_IVREF80 },
+ { "ivref100", HDA_QUIRK_IVREF100 },
+ { "ovref50", HDA_QUIRK_OVREF50 },
+ { "ovref80", HDA_QUIRK_OVREF80 },
+ { "ovref100", HDA_QUIRK_OVREF100 },
+ { "ivref", HDA_QUIRK_IVREF },
+ { "ovref", HDA_QUIRK_OVREF },
+ { "vref", HDA_QUIRK_VREF },
};
-#define HDAC_QUIRKS_TAB_LEN (sizeof(hdac_quirks_tab) / sizeof(hdac_quirks_tab[0]))
+#define HDAC_QUIRKS_TAB_LEN \
+ (sizeof(hdac_quirks_tab) / sizeof(hdac_quirks_tab[0]))
#define HDA_BDL_MIN 2
#define HDA_BDL_MAX 256
#define HDA_BDL_DEFAULT HDA_BDL_MIN
+#define HDA_BLK_MIN HDAC_DMA_ALIGNMENT
+#define HDA_BLK_ALIGN (~(HDA_BLK_MIN - 1))
+
#define HDA_BUFSZ_MIN 4096
#define HDA_BUFSZ_MAX 65536
#define HDA_BUFSZ_DEFAULT 16384
#define HDA_PARSE_MAXDEPTH 10
-#define HDAC_UNSOLTAG_EVENT_HP 0x00
+#define HDAC_UNSOLTAG_EVENT_HP 0x00
+#define HDAC_UNSOLTAG_EVENT_TEST 0x01
-static MALLOC_DEFINE(M_HDAC, "hdac", "High Definition Audio Controller");
+MALLOC_DEFINE(M_HDAC, "hdac", "High Definition Audio Controller");
enum {
-HDA_PARSE_MIXER,
-HDA_PARSE_DIRECT
+ HDA_PARSE_MIXER,
+ HDA_PARSE_DIRECT
};
/* Default */
static uint32_t hdac_fmt[] = {
-AFMT_STEREO | AFMT_S16_LE,
-0
+ AFMT_STEREO | AFMT_S16_LE,
+ 0
};
static struct pcmchan_caps hdac_caps = {48000, 48000, hdac_fmt, 0};
static const struct {
-uint32_t model;
-char *desc;
+ uint32_t model;
+ char *desc;
} hdac_devices[] = {
-{ HDA_INTEL_82801F, "Intel 82801F" },
-{ HDA_INTEL_82801G, "Intel 82801G" },
-{ HDA_INTEL_82801H, "Intel 82801H" },
-{ HDA_INTEL_63XXESB, "Intel 631x/632xESB" },
-{ HDA_NVIDIA_MCP51, "NVidia MCP51" },
-{ HDA_NVIDIA_MCP55, "NVidia MCP55" },
-{ HDA_NVIDIA_MCP61A, "NVidia MCP61A" },
-{ HDA_NVIDIA_MCP61B, "NVidia MCP61B" },
-{ HDA_NVIDIA_MCP65A, "NVidia MCP65A" },
-{ HDA_NVIDIA_MCP65B, "NVidia MCP65B" },
-{ HDA_ATI_SB450, "ATI SB450" },
-{ HDA_ATI_SB600, "ATI SB600" },
-{ HDA_VIA_VT82XX, "VIA VT8251/8237A" },
-{ HDA_SIS_966, "SiS 966" },
-/* Unknown */
-{ HDA_INTEL_ALL, "Intel (Unknown)" },
-{ HDA_NVIDIA_ALL, "NVidia (Unknown)" },
-{ HDA_ATI_ALL, "ATI (Unknown)" },
-{ HDA_VIA_ALL, "VIA (Unknown)" },
-{ HDA_SIS_ALL, "SiS (Unknown)" },
+ { HDA_INTEL_82801F, "Intel 82801F" },
+ { HDA_INTEL_63XXESB, "Intel 631x/632xESB" },
+ { HDA_INTEL_82801G, "Intel 82801G" },
+ { HDA_INTEL_82801H, "Intel 82801H" },
+ { HDA_INTEL_82801I, "Intel 82801I" },
+ { HDA_NVIDIA_MCP51, "NVidia MCP51" },
+ { HDA_NVIDIA_MCP55, "NVidia MCP55" },
+ { HDA_NVIDIA_MCP61_1, "NVidia MCP61" },
+ { HDA_NVIDIA_MCP61_2, "NVidia MCP61" },
+ { HDA_NVIDIA_MCP65_1, "NVidia MCP65" },
+ { HDA_NVIDIA_MCP65_2, "NVidia MCP65" },
+ { HDA_NVIDIA_MCP67_1, "NVidia MCP67" },
+ { HDA_NVIDIA_MCP67_2, "NVidia MCP67" },
+ { HDA_ATI_SB450, "ATI SB450" },
+ { HDA_ATI_SB600, "ATI SB600" },
+ { HDA_VIA_VT82XX, "VIA VT8251/8237A" },
+ { HDA_SIS_966, "SiS 966" },
+ /* Unknown */
+ { HDA_INTEL_ALL, "Intel (Unknown)" },
+ { HDA_NVIDIA_ALL, "NVidia (Unknown)" },
+ { HDA_ATI_ALL, "ATI (Unknown)" },
+ { HDA_VIA_ALL, "VIA (Unknown)" },
+ { HDA_SIS_ALL, "SiS (Unknown)" },
};
#define HDAC_DEVICES_LEN (sizeof(hdac_devices) / sizeof(hdac_devices[0]))
static const struct {
-uint32_t rate;
-int valid;
-uint16_t base;
-uint16_t mul;
-uint16_t div;
+ uint16_t vendor;
+ uint8_t reg;
+ uint8_t mask;
+ uint8_t enable;
+} hdac_pcie_snoop[] = {
+ { INTEL_VENDORID, 0x00, 0x00, 0x00 },
+ { ATI_VENDORID, 0x42, 0xf8, 0x02 },
+ { NVIDIA_VENDORID, 0x4e, 0xf0, 0x0f },
+};
+#define HDAC_PCIESNOOP_LEN \
+ (sizeof(hdac_pcie_snoop) / sizeof(hdac_pcie_snoop[0]))
+
+static const struct {
+ uint32_t rate;
+ int valid;
+ uint16_t base;
+ uint16_t mul;
+ uint16_t div;
} hda_rate_tab[] = {
-{ 8000, 1, 0x0000, 0x0000, 0x0500 }, /* (48000 * 1) / 6 */
-{ 9600, 0, 0x0000, 0x0000, 0x0400 }, /* (48000 * 1) / 5 */
-{ 12000, 0, 0x0000, 0x0000, 0x0300 }, /* (48000 * 1) / 4 */
-{ 16000, 1, 0x0000, 0x0000, 0x0200 }, /* (48000 * 1) / 3 */
-{ 18000, 0, 0x0000, 0x1000, 0x0700 }, /* (48000 * 3) / 8 */
-{ 19200, 0, 0x0000, 0x0800, 0x0400 }, /* (48000 * 2) / 5 */
-{ 24000, 0, 0x0000, 0x0000, 0x0100 }, /* (48000 * 1) / 2 */
-{ 28800, 0, 0x0000, 0x1000, 0x0400 }, /* (48000 * 3) / 5 */
-{ 32000, 1, 0x0000, 0x0800, 0x0200 }, /* (48000 * 2) / 3 */
-{ 36000, 0, 0x0000, 0x1000, 0x0300 }, /* (48000 * 3) / 4 */
-{ 38400, 0, 0x0000, 0x1800, 0x0400 }, /* (48000 * 4) / 5 */
-{ 48000, 1, 0x0000, 0x0000, 0x0000 }, /* (48000 * 1) / 1 */
-{ 64000, 0, 0x0000, 0x1800, 0x0200 }, /* (48000 * 4) / 3 */
-{ 72000, 0, 0x0000, 0x1000, 0x0100 }, /* (48000 * 3) / 2 */
-{ 96000, 1, 0x0000, 0x0800, 0x0000 }, /* (48000 * 2) / 1 */
-{ 144000, 0, 0x0000, 0x1000, 0x0000 }, /* (48000 * 3) / 1 */
-{ 192000, 1, 0x0000, 0x1800, 0x0000 }, /* (48000 * 4) / 1 */
-{ 8820, 0, 0x4000, 0x0000, 0x0400 }, /* (44100 * 1) / 5 */
-{ 11025, 1, 0x4000, 0x0000, 0x0300 }, /* (44100 * 1) / 4 */
-{ 12600, 0, 0x4000, 0x0800, 0x0600 }, /* (44100 * 2) / 7 */
-{ 14700, 0, 0x4000, 0x0000, 0x0200 }, /* (44100 * 1) / 3 */
-{ 17640, 0, 0x4000, 0x0800, 0x0400 }, /* (44100 * 2) / 5 */
-{ 18900, 0, 0x4000, 0x1000, 0x0600 }, /* (44100 * 3) / 7 */
-{ 22050, 1, 0x4000, 0x0000, 0x0100 }, /* (44100 * 1) / 2 */
-{ 25200, 0, 0x4000, 0x1800, 0x0600 }, /* (44100 * 4) / 7 */
-{ 26460, 0, 0x4000, 0x1000, 0x0400 }, /* (44100 * 3) / 5 */
-{ 29400, 0, 0x4000, 0x0800, 0x0200 }, /* (44100 * 2) / 3 */
-{ 33075, 0, 0x4000, 0x1000, 0x0300 }, /* (44100 * 3) / 4 */
-{ 35280, 0, 0x4000, 0x1800, 0x0400 }, /* (44100 * 4) / 5 */
-{ 44100, 1, 0x4000, 0x0000, 0x0000 }, /* (44100 * 1) / 1 */
-{ 58800, 0, 0x4000, 0x1800, 0x0200 }, /* (44100 * 4) / 3 */
-{ 66150, 0, 0x4000, 0x1000, 0x0100 }, /* (44100 * 3) / 2 */
-{ 88200, 1, 0x4000, 0x0800, 0x0000 }, /* (44100 * 2) / 1 */
-{ 132300, 0, 0x4000, 0x1000, 0x0000 }, /* (44100 * 3) / 1 */
-{ 176400, 1, 0x4000, 0x1800, 0x0000 }, /* (44100 * 4) / 1 */
+ { 8000, 1, 0x0000, 0x0000, 0x0500 }, /* (48000 * 1) / 6 */
+ { 9600, 0, 0x0000, 0x0000, 0x0400 }, /* (48000 * 1) / 5 */
+ { 12000, 0, 0x0000, 0x0000, 0x0300 }, /* (48000 * 1) / 4 */
+ { 16000, 1, 0x0000, 0x0000, 0x0200 }, /* (48000 * 1) / 3 */
+ { 18000, 0, 0x0000, 0x1000, 0x0700 }, /* (48000 * 3) / 8 */
+ { 19200, 0, 0x0000, 0x0800, 0x0400 }, /* (48000 * 2) / 5 */
+ { 24000, 0, 0x0000, 0x0000, 0x0100 }, /* (48000 * 1) / 2 */
+ { 28800, 0, 0x0000, 0x1000, 0x0400 }, /* (48000 * 3) / 5 */
+ { 32000, 1, 0x0000, 0x0800, 0x0200 }, /* (48000 * 2) / 3 */
+ { 36000, 0, 0x0000, 0x1000, 0x0300 }, /* (48000 * 3) / 4 */
+ { 38400, 0, 0x0000, 0x1800, 0x0400 }, /* (48000 * 4) / 5 */
+ { 48000, 1, 0x0000, 0x0000, 0x0000 }, /* (48000 * 1) / 1 */
+ { 64000, 0, 0x0000, 0x1800, 0x0200 }, /* (48000 * 4) / 3 */
+ { 72000, 0, 0x0000, 0x1000, 0x0100 }, /* (48000 * 3) / 2 */
+ { 96000, 1, 0x0000, 0x0800, 0x0000 }, /* (48000 * 2) / 1 */
+ { 144000, 0, 0x0000, 0x1000, 0x0000 }, /* (48000 * 3) / 1 */
+ { 192000, 1, 0x0000, 0x1800, 0x0000 }, /* (48000 * 4) / 1 */
+ { 8820, 0, 0x4000, 0x0000, 0x0400 }, /* (44100 * 1) / 5 */
+ { 11025, 1, 0x4000, 0x0000, 0x0300 }, /* (44100 * 1) / 4 */
+ { 12600, 0, 0x4000, 0x0800, 0x0600 }, /* (44100 * 2) / 7 */
+ { 14700, 0, 0x4000, 0x0000, 0x0200 }, /* (44100 * 1) / 3 */
+ { 17640, 0, 0x4000, 0x0800, 0x0400 }, /* (44100 * 2) / 5 */
+ { 18900, 0, 0x4000, 0x1000, 0x0600 }, /* (44100 * 3) / 7 */
+ { 22050, 1, 0x4000, 0x0000, 0x0100 }, /* (44100 * 1) / 2 */
+ { 25200, 0, 0x4000, 0x1800, 0x0600 }, /* (44100 * 4) / 7 */
+ { 26460, 0, 0x4000, 0x1000, 0x0400 }, /* (44100 * 3) / 5 */
+ { 29400, 0, 0x4000, 0x0800, 0x0200 }, /* (44100 * 2) / 3 */
+ { 33075, 0, 0x4000, 0x1000, 0x0300 }, /* (44100 * 3) / 4 */
+ { 35280, 0, 0x4000, 0x1800, 0x0400 }, /* (44100 * 4) / 5 */
+ { 44100, 1, 0x4000, 0x0000, 0x0000 }, /* (44100 * 1) / 1 */
+ { 58800, 0, 0x4000, 0x1800, 0x0200 }, /* (44100 * 4) / 3 */
+ { 66150, 0, 0x4000, 0x1000, 0x0100 }, /* (44100 * 3) / 2 */
+ { 88200, 1, 0x4000, 0x0800, 0x0000 }, /* (44100 * 2) / 1 */
+ { 132300, 0, 0x4000, 0x1000, 0x0000 }, /* (44100 * 3) / 1 */
+ { 176400, 1, 0x4000, 0x1800, 0x0000 }, /* (44100 * 4) / 1 */
};
#define HDA_RATE_TAB_LEN (sizeof(hda_rate_tab) / sizeof(hda_rate_tab[0]))
/* All codecs you can eat... */
-#define HDA_CODEC_CONSTRUCT(vendor, id) (((uint32_t)(vendor##_VENDORID) << 16) | ((id) & 0xffff))
+#define HDA_CODEC_CONSTRUCT(vendor, id) \
+ (((uint32_t)(vendor##_VENDORID) << 16) | ((id) & 0xffff))
/* Realtek */
#define REALTEK_VENDORID 0x10ec
#define HDA_CODEC_ALC260 HDA_CODEC_CONSTRUCT(REALTEK, 0x0260)
+#define HDA_CODEC_ALC262 HDA_CODEC_CONSTRUCT(REALTEK, 0x0262)
+#define HDA_CODEC_ALC268 HDA_CODEC_CONSTRUCT(REALTEK, 0x0268)
+#define HDA_CODEC_ALC660 HDA_CODEC_CONSTRUCT(REALTEK, 0x0660)
#define HDA_CODEC_ALC861 HDA_CODEC_CONSTRUCT(REALTEK, 0x0861)
+#define HDA_CODEC_ALC861VD HDA_CODEC_CONSTRUCT(REALTEK, 0x0862)
#define HDA_CODEC_ALC880 HDA_CODEC_CONSTRUCT(REALTEK, 0x0880)
#define HDA_CODEC_ALC882 HDA_CODEC_CONSTRUCT(REALTEK, 0x0882)
#define HDA_CODEC_ALC883 HDA_CODEC_CONSTRUCT(REALTEK, 0x0883)
+#define HDA_CODEC_ALC885 HDA_CODEC_CONSTRUCT(REALTEK, 0x0885)
+#define HDA_CODEC_ALC888 HDA_CODEC_CONSTRUCT(REALTEK, 0x0888)
#define HDA_CODEC_ALCXXXX HDA_CODEC_CONSTRUCT(REALTEK, 0xffff)
-/* Analog Device */
-#define ANALOGDEVICE_VENDORID 0x11d4
-#define HDA_CODEC_AD1981HD HDA_CODEC_CONSTRUCT(ANALOGDEVICE, 0x1981)
-#define HDA_CODEC_AD1983 HDA_CODEC_CONSTRUCT(ANALOGDEVICE, 0x1983)
-#define HDA_CODEC_AD1986A HDA_CODEC_CONSTRUCT(ANALOGDEVICE, 0x1986)
-#define HDA_CODEC_ADXXXX HDA_CODEC_CONSTRUCT(ANALOGDEVICE, 0xffff)
+/* Analog Devices */
+#define ANALOGDEVICES_VENDORID 0x11d4
+#define HDA_CODEC_AD1981HD HDA_CODEC_CONSTRUCT(ANALOGDEVICES, 0x1981)
+#define HDA_CODEC_AD1983 HDA_CODEC_CONSTRUCT(ANALOGDEVICES, 0x1983)
+#define HDA_CODEC_AD1984 HDA_CODEC_CONSTRUCT(ANALOGDEVICES, 0x1984)
+#define HDA_CODEC_AD1986A HDA_CODEC_CONSTRUCT(ANALOGDEVICES, 0x1986)
+#define HDA_CODEC_AD1988 HDA_CODEC_CONSTRUCT(ANALOGDEVICES, 0x1988)
+#define HDA_CODEC_AD1988B HDA_CODEC_CONSTRUCT(ANALOGDEVICES, 0x198b)
+#define HDA_CODEC_ADXXXX HDA_CODEC_CONSTRUCT(ANALOGDEVICES, 0xffff)
/* CMedia */
#define CMEDIA_VENDORID 0x434d
@@ -357,112 +546,209 @@
#define HDA_CODEC_STAC9221D HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7683)
#define HDA_CODEC_STAC9220 HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7690)
#define HDA_CODEC_STAC922XD HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7681)
+#define HDA_CODEC_STAC9227 HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7618)
+#define HDA_CODEC_STAC9271D HDA_CODEC_CONSTRUCT(SIGMATEL, 0x7627)
#define HDA_CODEC_STACXXXX HDA_CODEC_CONSTRUCT(SIGMATEL, 0xffff)
/*
-* Conexant
-*
-* Ok, the truth is, I don't have any idea at all whether
-* it is "Venice" or "Waikiki" or other unnamed CXyadayada. The only
-* place that tell me it is "Venice" is from its Windows driver INF.
-*
-* Venice - CX?????
-* Waikiki - CX20551-22
-*/
+ * Conexant
+ *
+ * Ok, the truth is, I don't have any idea at all whether
+ * it is "Venice" or "Waikiki" or other unnamed CXyadayada. The only
+ * place that tell me it is "Venice" is from its Windows driver INF.
+ *
+ * Venice - CX?????
+ * Waikiki - CX20551-22
+ */
#define CONEXANT_VENDORID 0x14f1
#define HDA_CODEC_CXVENICE HDA_CODEC_CONSTRUCT(CONEXANT, 0x5045)
#define HDA_CODEC_CXWAIKIKI HDA_CODEC_CONSTRUCT(CONEXANT, 0x5047)
#define HDA_CODEC_CXXXXX HDA_CODEC_CONSTRUCT(CONEXANT, 0xffff)
+/* VIA */
+#define HDA_CODEC_VT1708_8 HDA_CODEC_CONSTRUCT(VIA, 0x1708)
+#define HDA_CODEC_VT1708_9 HDA_CODEC_CONSTRUCT(VIA, 0x1709)
+#define HDA_CODEC_VT1708_A HDA_CODEC_CONSTRUCT(VIA, 0x170a)
+#define HDA_CODEC_VT1708_B HDA_CODEC_CONSTRUCT(VIA, 0x170b)
+#define HDA_CODEC_VT1709_0 HDA_CODEC_CONSTRUCT(VIA, 0xe710)
+#define HDA_CODEC_VT1709_1 HDA_CODEC_CONSTRUCT(VIA, 0xe711)
+#define HDA_CODEC_VT1709_2 HDA_CODEC_CONSTRUCT(VIA, 0xe712)
+#define HDA_CODEC_VT1709_3 HDA_CODEC_CONSTRUCT(VIA, 0xe713)
+#define HDA_CODEC_VT1709_4 HDA_CODEC_CONSTRUCT(VIA, 0xe714)
+#define HDA_CODEC_VT1709_5 HDA_CODEC_CONSTRUCT(VIA, 0xe715)
+#define HDA_CODEC_VT1709_6 HDA_CODEC_CONSTRUCT(VIA, 0xe716)
+#define HDA_CODEC_VT1709_7 HDA_CODEC_CONSTRUCT(VIA, 0xe717)
+#define HDA_CODEC_VTXXXX HDA_CODEC_CONSTRUCT(VIA, 0xffff)
+
/* Codecs */
static const struct {
-uint32_t id;
-char *name;
+ uint32_t id;
+ char *name;
} hdac_codecs[] = {
-{ HDA_CODEC_ALC260, "Realtek ALC260" },
-{ HDA_CODEC_ALC861, "Realtek ALC861" },
-{ HDA_CODEC_ALC880, "Realtek ALC880" },
-{ HDA_CODEC_ALC882, "Realtek ALC882" },
-{ HDA_CODEC_ALC883, "Realtek ALC883" },
-{ HDA_CODEC_AD1981HD, "Analog Device AD1981HD" },
-{ HDA_CODEC_AD1983, "Analog Device AD1983" },
-{ HDA_CODEC_AD1986A, "Analog Device AD1986A" },
-{ HDA_CODEC_CMI9880, "CMedia CMI9880" },
-{ HDA_CODEC_STAC9221, "Sigmatel STAC9221" },
-{ HDA_CODEC_STAC9221D, "Sigmatel STAC9221D" },
-{ HDA_CODEC_STAC9220, "Sigmatel STAC9220" },
-{ HDA_CODEC_STAC922XD, "Sigmatel STAC9220D/9223D" },
-{ HDA_CODEC_CXVENICE, "Conexant Venice" },
-{ HDA_CODEC_CXWAIKIKI, "Conexant Waikiki" },
-/* Unknown codec */
-{ HDA_CODEC_ALCXXXX, "Realtek (Unknown)" },
-{ HDA_CODEC_ADXXXX, "Analog Device (Unknown)" },
-{ HDA_CODEC_CMIXXXX, "CMedia (Unknown)" },
-{ HDA_CODEC_STACXXXX, "Sigmatel (Unknown)" },
-{ HDA_CODEC_CXXXXX, "Conexant (Unknown)" },
+ { HDA_CODEC_ALC260, "Realtek ALC260" },
+ { HDA_CODEC_ALC262, "Realtek ALC262" },
+ { HDA_CODEC_ALC268, "Realtek ALC268" },
+ { HDA_CODEC_ALC660, "Realtek ALC660" },
+ { HDA_CODEC_ALC861, "Realtek ALC861" },
+ { HDA_CODEC_ALC861VD, "Realtek ALC861-VD" },
+ { HDA_CODEC_ALC880, "Realtek ALC880" },
+ { HDA_CODEC_ALC882, "Realtek ALC882" },
+ { HDA_CODEC_ALC883, "Realtek ALC883" },
+ { HDA_CODEC_ALC885, "Realtek ALC885" },
+ { HDA_CODEC_ALC888, "Realtek ALC888" },
+ { HDA_CODEC_AD1981HD, "Analog Devices AD1981HD" },
+ { HDA_CODEC_AD1983, "Analog Devices AD1983" },
+ { HDA_CODEC_AD1984, "Analog Devices AD1984" },
+ { HDA_CODEC_AD1986A, "Analog Devices AD1986A" },
+ { HDA_CODEC_AD1988, "Analog Devices AD1988" },
+ { HDA_CODEC_AD1988B, "Analog Devices AD1988B" },
+ { HDA_CODEC_CMI9880, "CMedia CMI9880" },
+ { HDA_CODEC_STAC9221, "Sigmatel STAC9221" },
+ { HDA_CODEC_STAC9221D, "Sigmatel STAC9221D" },
+ { HDA_CODEC_STAC9220, "Sigmatel STAC9220" },
+ { HDA_CODEC_STAC922XD, "Sigmatel STAC9220D/9223D" },
+ { HDA_CODEC_STAC9227, "Sigmatel STAC9227" },
+ { HDA_CODEC_STAC9271D, "Sigmatel STAC9271D" },
+ { HDA_CODEC_CXVENICE, "Conexant Venice" },
+ { HDA_CODEC_CXWAIKIKI, "Conexant Waikiki" },
+ { HDA_CODEC_VT1708_8, "VIA VT1708_8" },
+ { HDA_CODEC_VT1708_9, "VIA VT1708_9" },
+ { HDA_CODEC_VT1708_A, "VIA VT1708_A" },
+ { HDA_CODEC_VT1708_B, "VIA VT1708_B" },
+ { HDA_CODEC_VT1709_0, "VIA VT1709_0" },
+ { HDA_CODEC_VT1709_1, "VIA VT1709_1" },
+ { HDA_CODEC_VT1709_2, "VIA VT1709_2" },
+ { HDA_CODEC_VT1709_3, "VIA VT1709_3" },
+ { HDA_CODEC_VT1709_4, "VIA VT1709_4" },
+ { HDA_CODEC_VT1709_5, "VIA VT1709_5" },
+ { HDA_CODEC_VT1709_6, "VIA VT1709_6" },
+ { HDA_CODEC_VT1709_7, "VIA VT1709_7" },
+ /* Unknown codec */
+ { HDA_CODEC_ALCXXXX, "Realtek (Unknown)" },
+ { HDA_CODEC_ADXXXX, "Analog Devices (Unknown)" },
+ { HDA_CODEC_CMIXXXX, "CMedia (Unknown)" },
+ { HDA_CODEC_STACXXXX, "Sigmatel (Unknown)" },
+ { HDA_CODEC_CXXXXX, "Conexant (Unknown)" },
+ { HDA_CODEC_VTXXXX, "VIA (Unknown)" },
};
#define HDAC_CODECS_LEN (sizeof(hdac_codecs) / sizeof(hdac_codecs[0]))
enum {
-HDAC_HP_SWITCH_CTL,
-HDAC_HP_SWITCH_CTRL
+ HDAC_HP_SWITCH_CTL,
+ HDAC_HP_SWITCH_CTRL,
+ HDAC_HP_SWITCH_DEBUG
};
static const struct {
-uint32_t model;
-uint32_t id;
-int type;
-nid_t hpnid;
-nid_t spkrnid[8];
-nid_t eapdnid;
+ uint32_t model;
+ uint32_t id;
+ int type;
+ int inverted;
+ int polling;
+ int execsense;
+ nid_t hpnid;
+ nid_t spkrnid[8];
+ nid_t eapdnid;
} hdac_hp_switch[] = {
-/* Specific OEM models */
-{ HP_V3000_SUBVENDOR, HDA_CODEC_CXVENICE, HDAC_HP_SWITCH_CTL,
-17, { 16, -1 }, 16 },
-{ HP_NX7400_SUBVENDOR, HDA_CODEC_AD1981HD, HDAC_HP_SWITCH_CTL,
-6, { 5, -1 }, 5 },
-{ HP_NX6310_SUBVENDOR, HDA_CODEC_AD1981HD, HDAC_HP_SWITCH_CTL,
-6, { 5, -1 }, 5 },
-{ DELL_D820_SUBVENDOR, HDA_CODEC_STAC9220, HDAC_HP_SWITCH_CTRL,
-13, { 14, -1 }, -1 },
-{ DELL_I1300_SUBVENDOR, HDA_CODEC_STAC9220, HDAC_HP_SWITCH_CTRL,
-13, { 14, -1 }, -1 },
-/*
-* All models that at least come from the same vendor with
-* simmilar codec.
-*/
-{ HP_ALL_SUBVENDOR, HDA_CODEC_CXVENICE, HDAC_HP_SWITCH_CTL,
-17, { 16, -1 }, 16 },
-{ HP_ALL_SUBVENDOR, HDA_CODEC_AD1981HD, HDAC_HP_SWITCH_CTL,
-6, { 5, -1 }, 5 },
-{ DELL_ALL_SUBVENDOR, HDA_CODEC_STAC9220, HDAC_HP_SWITCH_CTRL,
-13, { 14, -1 }, -1 },
+ /* Specific OEM models */
+ { HP_V3000_SUBVENDOR, HDA_CODEC_CXVENICE, HDAC_HP_SWITCH_CTL,
+ 0, 0, -1, 17, { 16, -1 }, 16 },
+ /* { HP_XW4300_SUBVENDOR, HDA_CODEC_ALC260, HDAC_HP_SWITCH_CTL,
+ 0, 0, -1, 21, { 16, 17, -1 }, -1 } */
+ /* { HP_3010_SUBVENDOR, HDA_CODEC_ALC260, HDAC_HP_SWITCH_DEBUG,
+ 0, 1, 0, 16, { 15, 18, 19, 20, 21, -1 }, -1 }, */
+ { HP_NX7400_SUBVENDOR, HDA_CODEC_AD1981HD, HDAC_HP_SWITCH_CTL,
+ 0, 0, -1, 6, { 5, -1 }, 5 },
+ { HP_NX6310_SUBVENDOR, HDA_CODEC_AD1981HD, HDAC_HP_SWITCH_CTL,
+ 0, 0, -1, 6, { 5, -1 }, 5 },
+ { HP_NX6325_SUBVENDOR, HDA_CODEC_AD1981HD, HDAC_HP_SWITCH_CTL,
+ 0, 0, -1, 6, { 5, -1 }, 5 },
+ /* { HP_DC7700_SUBVENDOR, HDA_CODEC_ALC262, HDAC_HP_SWITCH_CTL,
+ 0, 0, -1, 21, { 22, 27, -1 }, -1 }, */
+ { TOSHIBA_U200_SUBVENDOR, HDA_CODEC_AD1981HD, HDAC_HP_SWITCH_CTL,
+ 0, 0, -1, 6, { 5, -1 }, -1 },
+ { TOSHIBA_A135_SUBVENDOR, HDA_CODEC_ALC861VD, HDAC_HP_SWITCH_CTL,
+ 0, 0, -1, 27, { 20, -1 }, -1 },
+ { DELL_D820_SUBVENDOR, HDA_CODEC_STAC9220, HDAC_HP_SWITCH_CTRL,
+ 0, 0, -1, 13, { 14, -1 }, -1 },
+ { DELL_I1300_SUBVENDOR, HDA_CODEC_STAC9220, HDAC_HP_SWITCH_CTRL,
+ 0, 0, -1, 13, { 14, -1 }, -1 },
+ { DELL_OPLX745_SUBVENDOR, HDA_CODEC_AD1983, HDAC_HP_SWITCH_CTL,
+ 0, 0, -1, 6, { 5, 7, -1 }, -1 },
+ { APPLE_MB3_SUBVENDOR, HDA_CODEC_ALC885, HDAC_HP_SWITCH_CTL,
+ 0, 0, -1, 21, { 20, 22, -1 }, -1 },
+ { APPLE_INTEL_MAC, HDA_CODEC_STAC9221, HDAC_HP_SWITCH_CTRL,
+ 0, 0, -1, 10, { 13, -1 }, -1 },
+ { LENOVO_3KN100_SUBVENDOR, HDA_CODEC_AD1986A, HDAC_HP_SWITCH_CTL,
+ 1, 0, -1, 26, { 27, -1 }, -1 },
+ /* { LENOVO_TCA55_SUBVENDOR, HDA_CODEC_AD1986A, HDAC_HP_SWITCH_CTL,
+ 0, 0, -1, 26, { 27, 28, 29, 30, -1 }, -1 }, */
+ { LG_LW20_SUBVENDOR, HDA_CODEC_ALC880, HDAC_HP_SWITCH_CTL,
+ 0, 0, -1, 27, { 20, -1 }, -1 },
+ { ACER_A5050_SUBVENDOR, HDA_CODEC_ALC883, HDAC_HP_SWITCH_CTL,
+ 0, 0, -1, 20, { 21, -1 }, -1 },
+ { ACER_3681WXM_SUBVENDOR, HDA_CODEC_ALC883, HDAC_HP_SWITCH_CTL,
+ 0, 0, -1, 20, { 21, -1 }, -1 },
+ { ACER_A4520_SUBVENDOR, HDA_CODEC_ALC268, HDAC_HP_SWITCH_CTL,
+ 0, 0, -1, 20, { 21, -1 }, -1 },
+ { ACER_A4710_SUBVENDOR, HDA_CODEC_ALC268, HDAC_HP_SWITCH_CTL,
+ 0, 0, -1, 20, { 21, -1 }, -1 },
+ { UNIWILL_9080_SUBVENDOR, HDA_CODEC_ALC883, HDAC_HP_SWITCH_CTL,
+ 0, 0, -1, 20, { 21, -1 }, -1 },
+ { MSI_MS1034_SUBVENDOR, HDA_CODEC_ALC883, HDAC_HP_SWITCH_CTL,
+ 0, 0, -1, 20, { 27, -1 }, -1 },
+ { MSI_MS034A_SUBVENDOR, HDA_CODEC_ALC883, HDAC_HP_SWITCH_CTL,
+ 0, 0, -1, 20, { 27, -1 }, -1 },
+ { FS_SI1848_SUBVENDOR, HDA_CODEC_ALC883, HDAC_HP_SWITCH_CTL,
+ 0, 0, -1, 20, { 21, -1 }, -1 },
+ { FL_S7020D_SUBVENDOR, HDA_CODEC_ALC260, HDAC_HP_SWITCH_CTL,
+ 0, 0, -1, 20, { 16, -1 }, -1 },
+ /*
+ * All models that at least come from the same vendor with
+ * simmilar codec.
+ */
+ { HP_ALL_SUBVENDOR, HDA_CODEC_CXVENICE, HDAC_HP_SWITCH_CTL,
+ 0, 0, -1, 17, { 16, -1 }, 16 },
+ { HP_ALL_SUBVENDOR, HDA_CODEC_AD1981HD, HDAC_HP_SWITCH_CTL,
+ 0, 0, -1, 6, { 5, -1 }, 5 },
+ { TOSHIBA_ALL_SUBVENDOR, HDA_CODEC_AD1981HD, HDAC_HP_SWITCH_CTL,
+ 0, 0, -1, 6, { 5, -1 }, -1 },
+ { DELL_ALL_SUBVENDOR, HDA_CODEC_STAC9220, HDAC_HP_SWITCH_CTRL,
+ 0, 0, -1, 13, { 14, -1 }, -1 },
+#if 0
+ { LENOVO_ALL_SUBVENDOR, HDA_CODEC_AD1986A, HDAC_HP_SWITCH_CTL,
+ 1, 0, -1, 26, { 27, -1 }, -1 },
+ { ACER_ALL_SUBVENDOR, HDA_CODEC_ALC883, HDAC_HP_SWITCH_CTL,
+ 0, 0, -1, 20, { 21, -1 }, -1 },
+#endif
};
-#define HDAC_HP_SWITCH_LEN (sizeof(hdac_hp_switch) / sizeof(hdac_hp_switch[0]))
+#define HDAC_HP_SWITCH_LEN \
+ (sizeof(hdac_hp_switch) / sizeof(hdac_hp_switch[0]))
static const struct {
-uint32_t model;
-uint32_t id;
-nid_t eapdnid;
-int hp_switch;
+ uint32_t model;
+ uint32_t id;
+ nid_t eapdnid;
+ int hp_switch;
} hdac_eapd_switch[] = {
-{ HP_V3000_SUBVENDOR, HDA_CODEC_CXVENICE, 16, 1 },
-{ HP_NX7400_SUBVENDOR, HDA_CODEC_AD1981HD, 5, 1 },
-{ HP_NX6310_SUBVENDOR, HDA_CODEC_AD1981HD, 5, 1 },
+ { HP_V3000_SUBVENDOR, HDA_CODEC_CXVENICE, 16, 1 },
+ { HP_NX7400_SUBVENDOR, HDA_CODEC_AD1981HD, 5, 1 },
+ { HP_NX6310_SUBVENDOR, HDA_CODEC_AD1981HD, 5, 1 },
};
-#define HDAC_EAPD_SWITCH_LEN (sizeof(hdac_eapd_switch) / sizeof(hdac_eapd_switch[0]))
+#define HDAC_EAPD_SWITCH_LEN \
+ (sizeof(hdac_eapd_switch) / sizeof(hdac_eapd_switch[0]))
/****************************************************************************
-* Function prototypes
-****************************************************************************/
+ * Function prototypes
+ ****************************************************************************/
static void hdac_intr_handler(void *);
static int hdac_reset(struct hdac_softc *);
static int hdac_get_capabilities(struct hdac_softc *);
static void hdac_dma_cb(void *, bus_dma_segment_t *, int, int);
static int hdac_dma_alloc(struct hdac_softc *,
-struct hdac_dma *, bus_size_t);
-static void hdac_dma_free(struct hdac_dma *);
+ struct hdac_dma *, bus_size_t);
+static void hdac_dma_free(struct hdac_softc *, struct hdac_dma *);
static int hdac_mem_alloc(struct hdac_softc *);
static void hdac_mem_free(struct hdac_softc *);
static int hdac_irq_alloc(struct hdac_softc *);
@@ -471,7 +757,7 @@
static void hdac_rirb_init(struct hdac_softc *);
static void hdac_corb_start(struct hdac_softc *);
static void hdac_rirb_start(struct hdac_softc *);
-static void hdac_scan_codecs(struct hdac_softc *);
+static void hdac_scan_codecs(struct hdac_softc *, int);
static int hdac_probe_codec(struct hdac_codec *);
static struct hdac_devinfo *hdac_probe_function(struct hdac_codec *, nid_t);
static void hdac_add_child(struct hdac_softc *, struct hdac_devinfo *);
@@ -479,4393 +765,5722 @@
static void hdac_attach2(void *);
static uint32_t hdac_command_sendone_internal(struct hdac_softc *,
-uint32_t, int);
+ uint32_t, int);
static void hdac_command_send_internal(struct hdac_softc *,
-struct hdac_command_list *, int);
+ struct hdac_command_list *, int);
static int hdac_probe(device_t);
static int hdac_attach(device_t);
static int hdac_detach(device_t);
static void hdac_widget_connection_select(struct hdac_widget *, uint8_t);
static void hdac_audio_ctl_amp_set(struct hdac_audio_ctl *,
-uint32_t, int, int);
+ uint32_t, int, int);
static struct hdac_audio_ctl *hdac_audio_ctl_amp_get(struct hdac_devinfo *,
-nid_t, int, int);
+ nid_t, int, int);
static void hdac_audio_ctl_amp_set_internal(struct hdac_softc *,
-nid_t, nid_t, int, int, int, int, int, int);
+ nid_t, nid_t, int, int, int, int, int, int);
static int hdac_audio_ctl_ossmixer_getnextdev(struct hdac_devinfo *);
static struct hdac_widget *hdac_widget_get(struct hdac_devinfo *, nid_t);
-#define hdac_command(a1, a2, a3) hdac_command_sendone_internal(a1, a2, a3)
+static int hdac_rirb_flush(struct hdac_softc *sc);
+static int hdac_unsolq_flush(struct hdac_softc *sc);
+
+#define hdac_command(a1, a2, a3) \
+ hdac_command_sendone_internal(a1, a2, a3)
-#define hdac_codec_id(d) ((uint32_t)((d == NULL) ? 0x00000000 : ((((uint32_t)(d)->vendor_id & 0x0000ffff) << 16) | ((uint32_t)(d)->device_id & 0x0000ffff))))
+#define hdac_codec_id(d) \
+ ((uint32_t)((d == NULL) ? 0x00000000 : \
+ ((((uint32_t)(d)->vendor_id & 0x0000ffff) << 16) | \
+ ((uint32_t)(d)->device_id & 0x0000ffff))))
static char *
hdac_codec_name(struct hdac_devinfo *devinfo)
{
-uint32_t id;
-int i;
+ uint32_t id;
+ int i;
-id = hdac_codec_id(devinfo);
+ id = hdac_codec_id(devinfo);
-for (i = 0; i < HDAC_CODECS_LEN; i++) {
-if (HDA_DEV_MATCH(hdac_codecs[i].id, id))
-return (hdac_codecs[i].name);
-}
+ for (i = 0; i < HDAC_CODECS_LEN; i++) {
+ if (HDA_DEV_MATCH(hdac_codecs[i].id, id))
+ return (hdac_codecs[i].name);
+ }
-return ((id == 0x00000000) ? "NULL Codec" : "Unknown Codec");
+ return ((id == 0x00000000) ? "NULL Codec" : "Unknown Codec");
}
static char *
hdac_audio_ctl_ossmixer_mask2name(uint32_t devmask)
{
-static char *ossname[] = SOUND_DEVICE_NAMES;
-static char *unknown = "???";
-int i;
-
-for (i = SOUND_MIXER_NRDEVICES - 1; i >= 0; i--) {
-if (devmask & (1 << i))
-return (ossname[i]);
-}
-return (unknown);
+ static char *ossname[] = SOUND_DEVICE_NAMES;
+ static char *unknown = "???";
+ int i;
+
+ for (i = SOUND_MIXER_NRDEVICES - 1; i >= 0; i--) {
+ if (devmask & (1 << i))
+ return (ossname[i]);
+ }
+ return (unknown);
}
static void
hdac_audio_ctl_ossmixer_mask2allname(uint32_t mask, char *buf, size_t len)
{
-static char *ossname[] = SOUND_DEVICE_NAMES;
-int i, first = 1;
+ static char *ossname[] = SOUND_DEVICE_NAMES;
+ int i, first = 1;
-bzero(buf, len);
-for (i = 0; i < SOUND_MIXER_NRDEVICES; i++) {
-if (mask & (1 << i)) {
-if (first == 0)
-strlcat(buf, ", ", len);
-strlcat(buf, ossname[i], len);
-first = 0;
-}
-}
+ bzero(buf, len);
+ for (i = 0; i < SOUND_MIXER_NRDEVICES; i++) {
+ if (mask & (1 << i)) {
+ if (first == 0)
+ strlcat(buf, ", ", len);
+ strlcat(buf, ossname[i], len);
+ first = 0;
+ }
+ }
}
static struct hdac_audio_ctl *
hdac_audio_ctl_each(struct hdac_devinfo *devinfo, int *index)
{
-if (devinfo == NULL ||
-devinfo->node_type != HDA_PARAM_FCT_GRP_TYPE_NODE_TYPE_AUDIO ||
-index == NULL || devinfo->function.audio.ctl == NULL ||
-devinfo->function.audio.ctlcnt < 1 ||
-*index < 0 || *index >= devinfo->function.audio.ctlcnt)
-return (NULL);
-return (&devinfo->function.audio.ctl[(*index)++]);
+ if (devinfo == NULL ||
+ devinfo->node_type != HDA_PARAM_FCT_GRP_TYPE_NODE_TYPE_AUDIO ||
+ index == NULL || devinfo->function.audio.ctl == NULL ||
+ devinfo->function.audio.ctlcnt < 1 ||
+ *index < 0 || *index >= devinfo->function.audio.ctlcnt)
+ return (NULL);
+ return (&devinfo->function.audio.ctl[(*index)++]);
}
static struct hdac_audio_ctl *
hdac_audio_ctl_amp_get(struct hdac_devinfo *devinfo, nid_t nid,
-int index, int cnt)
+ int index, int cnt)
{
-struct hdac_audio_ctl *ctl, *retctl = NULL;
-int i, at, atindex, found = 0;
+ struct hdac_audio_ctl *ctl, *retctl = NULL;
+ int i, at, atindex, found = 0;
-if (devinfo == NULL || devinfo->function.audio.ctl == NULL)
-return (NULL);
+ if (devinfo == NULL || devinfo->function.audio.ctl == NULL)
+ return (NULL);
-at = cnt;
-if (at == 0)
-at = 1;
-else if (at < 0)
-at = -1;
-atindex = index;
-if (atindex < 0)
-atindex = -1;
-
-i = 0;
-while ((ctl = hdac_audio_ctl_each(devinfo, &i)) != NULL) {
-if (ctl->enable == 0 || ctl->widget == NULL)
-continue;
-if (!(ctl->widget->nid == nid && (atindex == -1 ||
-ctl->index == atindex)))
-continue;
-found++;
-if (found == cnt)
-return (ctl);
-retctl = ctl;
-}
+ at = cnt;
+ if (at == 0)
+ at = 1;
+ else if (at < 0)
+ at = -1;
+ atindex = index;
+ if (atindex < 0)
+ atindex = -1;
+
+ i = 0;
+ while ((ctl = hdac_audio_ctl_each(devinfo, &i)) != NULL) {
+ if (ctl->enable == 0 || ctl->widget == NULL)
+ continue;
+ if (!(ctl->widget->nid == nid && (atindex == -1 ||
+ ctl->index == atindex)))
+ continue;
+ found++;
+ if (found == cnt)
+ return (ctl);
+ retctl = ctl;
+ }
-return ((at == -1) ? retctl : NULL);
+ return ((at == -1) ? retctl : NULL);
}
static void
hdac_hp_switch_handler(struct hdac_devinfo *devinfo)
{
-struct hdac_softc *sc;
-struct hdac_widget *w;
-struct hdac_audio_ctl *ctl;
-uint32_t id, res;
-int i = 0, j, forcemute;
-nid_t cad;
-
-if (devinfo == NULL || devinfo->codec == NULL ||
-devinfo->codec->sc == NULL)
-return;
-
-sc = devinfo->codec->sc;
-cad = devinfo->codec->cad;
-id = hdac_codec_id(devinfo);
-for (i = 0; i < HDAC_HP_SWITCH_LEN; i++) {
-if (HDA_DEV_MATCH(hdac_hp_switch[i].model,
-sc->pci_subvendor) &&
-hdac_hp_switch[i].id == id)
-break;
-}
-
-if (i >= HDAC_HP_SWITCH_LEN)
-return;
-
-forcemute = 0;
-if (hdac_hp_switch[i].eapdnid != -1) {
-w = hdac_widget_get(devinfo, hdac_hp_switch[i].eapdnid);
-if (w != NULL && w->param.eapdbtl != HDAC_INVALID)
-forcemute = (w->param.eapdbtl &
-HDA_CMD_SET_EAPD_BTL_ENABLE_EAPD) ? 0 : 1;
-}
-
-res = hdac_command(sc,
-HDA_CMD_GET_PIN_SENSE(cad, hdac_hp_switch[i].hpnid), cad);
-HDA_BOOTVERBOSE(
-device_printf(sc->dev,
-"HDA_DEBUG: Pin sense: nid=%d res=0x%08xn",
-hdac_hp_switch[i].hpnid, res);
-);
-res >>= 31;
-
-switch (hdac_hp_switch[i].type) {
-case HDAC_HP_SWITCH_CTL:
-ctl = hdac_audio_ctl_amp_get(devinfo,
-hdac_hp_switch[i].hpnid, 0, 1);
-if (ctl != NULL) {
-ctl->muted = (res != 0 && forcemute == 0) ?
-HDA_AMP_MUTE_NONE : HDA_AMP_MUTE_ALL;
-hdac_audio_ctl_amp_set(ctl,
-HDA_AMP_MUTE_DEFAULT, ctl->left,
-ctl->right);
-}
-for (j = 0; hdac_hp_switch[i].spkrnid[j] != -1; j++) {
-ctl = hdac_audio_ctl_amp_get(devinfo,
-hdac_hp_switch[i].spkrnid[j], 0, 1);
-if (ctl != NULL) {
-ctl->muted = (res != 0 || forcemute == 1) ?
-HDA_AMP_MUTE_ALL : HDA_AMP_MUTE_NONE;
-hdac_audio_ctl_amp_set(ctl,
-HDA_AMP_MUTE_DEFAULT, ctl->left,
-ctl->right);
-}
-}
-break;
-case HDAC_HP_SWITCH_CTRL:
-if (res != 0) {
-/* HP in */
-w = hdac_widget_get(devinfo, hdac_hp_switch[i].hpnid);
-if (w != NULL && w->type ==
-HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX) {
-if (forcemute == 0)
-w->wclass.pin.ctrl |=
-HDA_CMD_SET_PIN_WIDGET_CTRL_OUT_ENABLE;
-else
-w->wclass.pin.ctrl &=
-~HDA_CMD_SET_PIN_WIDGET_CTRL_OUT_ENABLE;
-hdac_command(sc,
-HDA_CMD_SET_PIN_WIDGET_CTRL(cad, w->nid,
-w->wclass.pin.ctrl), cad);
-}
-for (j = 0; hdac_hp_switch[i].spkrnid[j] != -1; j++) {
-w = hdac_widget_get(devinfo,
-hdac_hp_switch[i].spkrnid[j]);
-if (w != NULL && w->type ==
-HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX) {
-w->wclass.pin.ctrl &=
-~HDA_CMD_SET_PIN_WIDGET_CTRL_OUT_ENABLE;
-hdac_command(sc,
-HDA_CMD_SET_PIN_WIDGET_CTRL(cad,
-w->nid,
-w->wclass.pin.ctrl), cad);
-}
-}
-} else {
-/* HP out */
-w = hdac_widget_get(devinfo, hdac_hp_switch[i].hpnid);
-if (w != NULL && w->type ==
-HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX) {
-w->wclass.pin.ctrl &=
-~HDA_CMD_SET_PIN_WIDGET_CTRL_OUT_ENABLE;
-hdac_command(sc,
-HDA_CMD_SET_PIN_WIDGET_CTRL(cad, w->nid,
-w->wclass.pin.ctrl), cad);
-}
-for (j = 0; hdac_hp_switch[i].spkrnid[j] != -1; j++) {
-w = hdac_widget_get(devinfo,
-hdac_hp_switch[i].spkrnid[j]);
-if (w != NULL && w->type ==
-HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX) {
-if (forcemute == 0)
-w->wclass.pin.ctrl |=
-HDA_CMD_SET_PIN_WIDGET_CTRL_OUT_ENABLE;
-else
-w->wclass.pin.ctrl &=
-~HDA_CMD_SET_PIN_WIDGET_CTRL_OUT_ENABLE;
-hdac_command(sc,
-HDA_CMD_SET_PIN_WIDGET_CTRL(cad,
-w->nid,
-w->wclass.pin.ctrl), cad);
-}
-}
-}
-break;
-default:
-break;
-}
+ struct hdac_softc *sc;
+ struct hdac_widget *w;
+ struct hdac_audio_ctl *ctl;
+ uint32_t val, id, res;
+ int i = 0, j, timeout, forcemute;
+ nid_t cad;
+
+ if (devinfo == NULL || devinfo->codec == NULL ||
+ devinfo->codec->sc == NULL)
+ return;
+
+ sc = devinfo->codec->sc;
+ cad = devinfo->codec->cad;
+ id = hdac_codec_id(devinfo);
+ for (i = 0; i < HDAC_HP_SWITCH_LEN; i++) {
+ if (HDA_DEV_MATCH(hdac_hp_switch[i].model,
+ sc->pci_subvendor) &&
+ hdac_hp_switch[i].id == id)
+ break;
+ }
+
+ if (i >= HDAC_HP_SWITCH_LEN)
+ return;
+
+ forcemute = 0;
+ if (hdac_hp_switch[i].eapdnid != -1) {
+ w = hdac_widget_get(devinfo, hdac_hp_switch[i].eapdnid);
+ if (w != NULL && w->param.eapdbtl != HDAC_INVALID)
+ forcemute = (w->param.eapdbtl &
+ HDA_CMD_SET_EAPD_BTL_ENABLE_EAPD) ? 0 : 1;
+ }
+
+ if (hdac_hp_switch[i].execsense != -1)
+ hdac_command(sc,
+ HDA_CMD_SET_PIN_SENSE(cad, hdac_hp_switch[i].hpnid,
+ hdac_hp_switch[i].execsense), cad);
+
+ timeout = 10000;
+ do {
+ res = hdac_command(sc,
+ HDA_CMD_GET_PIN_SENSE(cad, hdac_hp_switch[i].hpnid),
+ cad);
+ if (hdac_hp_switch[i].execsense == -1 || res != 0x7fffffff)
+ break;
+ DELAY(10);
+ } while (--timeout != 0);
+
+ HDA_BOOTVERBOSE(
+ device_printf(sc->dev,
+ "HDA_DEBUG: Pin sense: nid=%d timeout=%d res=0x%08x\n",
+ hdac_hp_switch[i].hpnid, timeout, res);
+ );
+
+ res = HDA_CMD_GET_PIN_SENSE_PRESENCE_DETECT(res);
+ res ^= hdac_hp_switch[i].inverted;
+
+ switch (hdac_hp_switch[i].type) {
+ case HDAC_HP_SWITCH_CTL:
+ ctl = hdac_audio_ctl_amp_get(devinfo,
+ hdac_hp_switch[i].hpnid, 0, 1);
+ if (ctl != NULL) {
+ val = (res != 0 && forcemute == 0) ?
+ HDA_AMP_MUTE_NONE : HDA_AMP_MUTE_ALL;
+ if (val != ctl->muted) {
+ ctl->muted = val;
+ hdac_audio_ctl_amp_set(ctl,
+ HDA_AMP_MUTE_DEFAULT, ctl->left,
+ ctl->right);
+ }
+ }
+ for (j = 0; hdac_hp_switch[i].spkrnid[j] != -1; j++) {
+ ctl = hdac_audio_ctl_amp_get(devinfo,
+ hdac_hp_switch[i].spkrnid[j], 0, 1);
+ if (ctl == NULL)
+ continue;
+ val = (res != 0 || forcemute == 1) ?
+ HDA_AMP_MUTE_ALL : HDA_AMP_MUTE_NONE;
+ if (val == ctl->muted)
+ continue;
+ ctl->muted = val;
+ hdac_audio_ctl_amp_set(ctl, HDA_AMP_MUTE_DEFAULT,
+ ctl->left, ctl->right);
+ }
+ break;
+ case HDAC_HP_SWITCH_CTRL:
+ if (res != 0) {
+ /* HP in */
+ w = hdac_widget_get(devinfo, hdac_hp_switch[i].hpnid);
+ if (w != NULL && w->type ==
+ HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX) {
+ if (forcemute == 0)
+ val = w->wclass.pin.ctrl |
+ HDA_CMD_SET_PIN_WIDGET_CTRL_OUT_ENABLE;
+ else
+ val = w->wclass.pin.ctrl &
+ ~HDA_CMD_SET_PIN_WIDGET_CTRL_OUT_ENABLE;
+ if (val != w->wclass.pin.ctrl) {
+ w->wclass.pin.ctrl = val;
+ hdac_command(sc,
+ HDA_CMD_SET_PIN_WIDGET_CTRL(cad,
+ w->nid, w->wclass.pin.ctrl), cad);
+ }
+ }
+ for (j = 0; hdac_hp_switch[i].spkrnid[j] != -1; j++) {
+ w = hdac_widget_get(devinfo,
+ hdac_hp_switch[i].spkrnid[j]);
+ if (w == NULL || w->type !=
+ HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX)
+ continue;
+ val = w->wclass.pin.ctrl &
+ ~HDA_CMD_SET_PIN_WIDGET_CTRL_OUT_ENABLE;
+ if (val == w->wclass.pin.ctrl)
+ continue;
+ w->wclass.pin.ctrl = val;
+ hdac_command(sc, HDA_CMD_SET_PIN_WIDGET_CTRL(
+ cad, w->nid, w->wclass.pin.ctrl), cad);
+ }
+ } else {
+ /* HP out */
+ w = hdac_widget_get(devinfo, hdac_hp_switch[i].hpnid);
+ if (w != NULL && w->type ==
+ HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX) {
+ val = w->wclass.pin.ctrl &
+ ~HDA_CMD_SET_PIN_WIDGET_CTRL_OUT_ENABLE;
+ if (val != w->wclass.pin.ctrl) {
+ w->wclass.pin.ctrl = val;
+ hdac_command(sc,
+ HDA_CMD_SET_PIN_WIDGET_CTRL(cad,
+ w->nid, w->wclass.pin.ctrl), cad);
+ }
+ }
+ for (j = 0; hdac_hp_switch[i].spkrnid[j] != -1; j++) {
+ w = hdac_widget_get(devinfo,
+ hdac_hp_switch[i].spkrnid[j]);
+ if (w == NULL || w->type !=
+ HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX)
+ continue;
+ if (forcemute == 0)
+ val = w->wclass.pin.ctrl |
+ HDA_CMD_SET_PIN_WIDGET_CTRL_OUT_ENABLE;
+ else
+ val = w->wclass.pin.ctrl &
+ ~HDA_CMD_SET_PIN_WIDGET_CTRL_OUT_ENABLE;
+ if (val == w->wclass.pin.ctrl)
+ continue;
+ w->wclass.pin.ctrl = val;
+ hdac_command(sc, HDA_CMD_SET_PIN_WIDGET_CTRL(
+ cad, w->nid, w->wclass.pin.ctrl), cad);
+ }
+ }
+ break;
+ case HDAC_HP_SWITCH_DEBUG:
+ if (hdac_hp_switch[i].execsense != -1)
+ hdac_command(sc,
+ HDA_CMD_SET_PIN_SENSE(cad, hdac_hp_switch[i].hpnid,
+ hdac_hp_switch[i].execsense), cad);
+ res = hdac_command(sc,
+ HDA_CMD_GET_PIN_SENSE(cad, hdac_hp_switch[i].hpnid), cad);
+ device_printf(sc->dev,
+ "[ 0] HDA_DEBUG: Pin sense: nid=%d res=0x%08x\n",
+ hdac_hp_switch[i].hpnid, res);
+ for (j = 0; hdac_hp_switch[i].spkrnid[j] != -1; j++) {
+ w = hdac_widget_get(devinfo,
+ hdac_hp_switch[i].spkrnid[j]);
+ if (w == NULL || w->type !=
+ HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX)
+ continue;
+ if (hdac_hp_switch[i].execsense != -1)
+ hdac_command(sc,
+ HDA_CMD_SET_PIN_SENSE(cad, w->nid,
+ hdac_hp_switch[i].execsense), cad);
+ res = hdac_command(sc,
+ HDA_CMD_GET_PIN_SENSE(cad, w->nid), cad);
+ device_printf(sc->dev,
+ "[%2d] HDA_DEBUG: Pin sense: nid=%d res=0x%08x\n",
+ j + 1, w->nid, res);
+ }
+ break;
+ default:
+ break;
+ }
}
static void
hdac_unsolicited_handler(struct hdac_codec *codec, uint32_t tag)
{
-struct hdac_softc *sc;
-struct hdac_devinfo *devinfo = NULL;
-device_t *devlist = NULL;
-int devcount, i;
-
-if (codec == NULL || codec->sc == NULL)
-return;
-
-sc = codec->sc;
-
-HDA_BOOTVERBOSE(
-device_printf(sc->dev, "HDA_DEBUG: Unsol Tag: 0x%08xn", tag);
-);
-
-device_get_children(sc->dev, &devlist, &devcount);
-for (i = 0; devlist != NULL && i < devcount; i++) {
-devinfo = (struct hdac_devinfo *)device_get_ivars(devlist[i]);
-if (devinfo != NULL && devinfo->node_type ==
-HDA_PARAM_FCT_GRP_TYPE_NODE_TYPE_AUDIO &&
-devinfo->codec != NULL &&
-devinfo->codec->cad == codec->cad) {
-break;
-} else
-devinfo = NULL;
-}
-if (devlist != NULL)
-free(devlist, M_TEMP);
-
-if (devinfo == NULL)
-return;
-
-switch (tag) {
-case HDAC_UNSOLTAG_EVENT_HP:
-hdac_hp_switch_handler(devinfo);
-break;
-default:
-break;
-}
+ struct hdac_softc *sc;
+ struct hdac_devinfo *devinfo = NULL;
+ device_t *devlist = NULL;
+ int devcount, i;
+
+ if (codec == NULL || codec->sc == NULL)
+ return;
+
+ sc = codec->sc;
+
+ HDA_BOOTVERBOSE(
+ device_printf(sc->dev, "HDA_DEBUG: Unsol Tag: 0x%08x\n", tag);
+ );
+
+ device_get_children(sc->dev, &devlist, &devcount);
+ for (i = 0; devlist != NULL && i < devcount; i++) {
+ devinfo = (struct hdac_devinfo *)device_get_ivars(devlist[i]);
+ if (devinfo != NULL && devinfo->node_type ==
+ HDA_PARAM_FCT_GRP_TYPE_NODE_TYPE_AUDIO &&
+ devinfo->codec != NULL &&
+ devinfo->codec->cad == codec->cad) {
+ break;
+ } else
+ devinfo = NULL;
+ }
+ if (devlist != NULL)
+ free(devlist, M_TEMP);
+
+ if (devinfo == NULL)
+ return;
+
+ switch (tag) {
+ case HDAC_UNSOLTAG_EVENT_HP:
+ hdac_hp_switch_handler(devinfo);
+ break;
+ case HDAC_UNSOLTAG_EVENT_TEST:
+ device_printf(sc->dev, "Unsol Test!\n");
+ break;
+ default:
+ break;
+ }
}
-static void
+static int
hdac_stream_intr(struct hdac_softc *sc, struct hdac_chan *ch)
{
-/* XXX to be removed */
+ /* XXX to be removed */
#ifdef HDAC_INTR_EXTRA
-uint32_t res;
+ uint32_t res;
#endif
-if (ch->blkcnt == 0)
-return;
+ if (!(ch->flags & HDAC_CHN_RUNNING))
+ return (0);
-/* XXX to be removed */
+ /* XXX to be removed */
#ifdef HDAC_INTR_EXTRA
-res = HDAC_READ_1(&sc->mem, ch->off + HDAC_SDSTS);
+ res = HDAC_READ_1(&sc->mem, ch->off + HDAC_SDSTS);
#endif
-/* XXX to be removed */
+ /* XXX to be removed */
#ifdef HDAC_INTR_EXTRA
-HDA_BOOTVERBOSE(
-if (res & (HDAC_SDSTS_DESE | HDAC_SDSTS_FIFOE))
-device_printf(sc->dev,
-"PCMDIR_%s intr triggered beyond stream boundary:"
-"%08xn",
-(ch->dir == PCMDIR_PLAY) ? "PLAY" : "REC", res);
-);
+ HDA_BOOTVERBOSE(
+ if (res & (HDAC_SDSTS_DESE | HDAC_SDSTS_FIFOE))
+ device_printf(sc->dev,
+ "PCMDIR_%s intr triggered beyond stream boundary:"
+ "%08x\n",
+ (ch->dir == PCMDIR_PLAY) ? "PLAY" : "REC", res);
+ );
#endif
-HDAC_WRITE_1(&sc->mem, ch->off + HDAC_SDSTS,
-HDAC_SDSTS_DESE | HDAC_SDSTS_FIFOE | HDAC_SDSTS_BCIS );
+ HDAC_WRITE_1(&sc->mem, ch->off + HDAC_SDSTS,
+ HDAC_SDSTS_DESE | HDAC_SDSTS_FIFOE | HDAC_SDSTS_BCIS );
-/* XXX to be removed */
+ /* XXX to be removed */
#ifdef HDAC_INTR_EXTRA
-if (res & HDAC_SDSTS_BCIS) {
+ if (res & HDAC_SDSTS_BCIS) {
#endif
-ch->prevptr = ch->ptr;
-ch->ptr += sndbuf_getblksz(ch->b);
-ch->ptr %= sndbuf_getsize(ch->b);
-hdac_unlock(sc);
-chn_intr(ch->c);
-hdac_lock(sc);
-/* XXX to be removed */
+ return (1);
+ /* XXX to be removed */
#ifdef HDAC_INTR_EXTRA
-}
+ }
#endif
+
+ return (0);
}
/****************************************************************************
-* void hdac_intr_handler(void *)
-*
-* Interrupt handler. Processes interrupts received from the hdac.
-****************************************************************************/
+ * void hdac_intr_handler(void *)
+ *
+ * Interrupt handler. Processes interrupts received from the hdac.
+ ****************************************************************************/
static void
hdac_intr_handler(void *context)
{
-struct hdac_softc *sc;
-uint32_t intsts;
-uint8_t rirbsts;
-uint8_t rirbwp;
-struct hdac_rirb *rirb_base, *rirb;
-nid_t ucad;
-uint32_t utag;
-
-sc = (struct hdac_softc *)context;
-
-hdac_lock(sc);
-/* Do we have anything to do? */
-intsts = HDAC_READ_4(&sc->mem, HDAC_INTSTS);
-if (!HDA_FLAG_MATCH(intsts, HDAC_INTSTS_GIS)) {
-hdac_unlock(sc);
-return;
-}
-
-/* Was this a controller interrupt? */
-if (HDA_FLAG_MATCH(intsts, HDAC_INTSTS_CIS)) {
-rirb_base = (struct hdac_rirb *)sc->rirb_dma.dma_vaddr;
-rirbsts = HDAC_READ_1(&sc->mem, HDAC_RIRBSTS);
-/* Get as many responses that we can */
-while (HDA_FLAG_MATCH(rirbsts, HDAC_RIRBSTS_RINTFL)) {
-HDAC_WRITE_1(&sc->mem, HDAC_RIRBSTS, HDAC_RIRBSTS_RINTFL);
-rirbwp = HDAC_READ_1(&sc->mem, HDAC_RIRBWP);
-bus_dmamap_sync(sc->rirb_dma.dma_tag, sc->rirb_dma.dma_map,
-BUS_DMASYNC_POSTREAD);
-while (sc->rirb_rp != rirbwp) {
-sc->rirb_rp++;
-sc->rirb_rp %= sc->rirb_size;
-rirb = &rirb_base[sc->rirb_rp];
-if (rirb->response_ex & HDAC_RIRB_RESPONSE_EX_UNSOLICITED) {
-ucad = HDAC_RIRB_RESPONSE_EX_SDATA_IN(rirb->response_ex);
-utag = rirb->response >> 26;
-if (ucad > -1 && ucad < HDAC_CODEC_MAX &&
-sc->codecs[ucad] != NULL) {
-sc->unsolq[sc->unsolq_wp++] =
-(ucad << 16) |
-(utag & 0xffff);
-sc->unsolq_wp %= HDAC_UNSOLQ_MAX;
-}
-}
-}
-rirbsts = HDAC_READ_1(&sc->mem, HDAC_RIRBSTS);
-}
-/* XXX to be removed */
-/* Clear interrupt and exit */
+ struct hdac_softc *sc;
+ uint32_t intsts;
+ uint8_t rirbsts;
+ struct hdac_rirb *rirb_base;
+ uint32_t trigger;
+
+ sc = (struct hdac_softc *)context;
+
+ hdac_lock(sc);
+ if (sc->polling != 0) {
+ hdac_unlock(sc);
+ return;
+ }
+
+ /* Do we have anything to do? */
+ intsts = HDAC_READ_4(&sc->mem, HDAC_INTSTS);
+ if (!HDA_FLAG_MATCH(intsts, HDAC_INTSTS_GIS)) {
+ hdac_unlock(sc);
+ return;
+ }
+
+ trigger = 0;
+
+ /* Was this a controller interrupt? */
+ if (HDA_FLAG_MATCH(intsts, HDAC_INTSTS_CIS)) {
+ rirb_base = (struct hdac_rirb *)sc->rirb_dma.dma_vaddr;
+ rirbsts = HDAC_READ_1(&sc->mem, HDAC_RIRBSTS);
+ /* Get as many responses that we can */
+ while (HDA_FLAG_MATCH(rirbsts, HDAC_RIRBSTS_RINTFL)) {
+ HDAC_WRITE_1(&sc->mem,
+ HDAC_RIRBSTS, HDAC_RIRBSTS_RINTFL);
+ if (hdac_rirb_flush(sc) != 0)
+ trigger |= HDAC_TRIGGER_UNSOL;
+ rirbsts = HDAC_READ_1(&sc->mem, HDAC_RIRBSTS);
+ }
+ /* XXX to be removed */
+ /* Clear interrupt and exit */
#ifdef HDAC_INTR_EXTRA
-HDAC_WRITE_4(&sc->mem, HDAC_INTSTS, HDAC_INTSTS_CIS);
+ HDAC_WRITE_4(&sc->mem, HDAC_INTSTS, HDAC_INTSTS_CIS);
#endif
-}
-if (intsts & HDAC_INTSTS_SIS_MASK) {
-if (intsts & (1 << sc->num_iss))
-hdac_stream_intr(sc, &sc->play);
-if (intsts & (1 << 0))
-hdac_stream_intr(sc, &sc->rec);
-/* XXX to be removed */
+ }
+
+ if (intsts & HDAC_INTSTS_SIS_MASK) {
+ if ((intsts & (1 << sc->num_iss)) &&
+ hdac_stream_intr(sc, &sc->play) != 0)
+ trigger |= HDAC_TRIGGER_PLAY;
+ if ((intsts & (1 << 0)) &&
+ hdac_stream_intr(sc, &sc->rec) != 0)
+ trigger |= HDAC_TRIGGER_REC;
+ /* XXX to be removed */
#ifdef HDAC_INTR_EXTRA
-HDAC_WRITE_4(&sc->mem, HDAC_INTSTS, intsts & HDAC_INTSTS_SIS_MASK);
+ HDAC_WRITE_4(&sc->mem, HDAC_INTSTS, intsts &
+ HDAC_INTSTS_SIS_MASK);
#endif
-}
+ }
-if (sc->unsolq_st == HDAC_UNSOLQ_READY) {
-sc->unsolq_st = HDAC_UNSOLQ_BUSY;
-while (sc->unsolq_rp != sc->unsolq_wp) {
-ucad = sc->unsolq[sc->unsolq_rp] >> 16;
-utag = sc->unsolq[sc->unsolq_rp++] & 0xffff;
-sc->unsolq_rp %= HDAC_UNSOLQ_MAX;
-hdac_unsolicited_handler(sc->codecs[ucad], utag);
-}
-sc->unsolq_st = HDAC_UNSOLQ_READY;
-}
+ hdac_unlock(sc);
-hdac_unlock(sc);
+ if (trigger & HDAC_TRIGGER_PLAY)
+ chn_intr(sc->play.c);
+ if (trigger & HDAC_TRIGGER_REC)
+ chn_intr(sc->rec.c);
+ if (trigger & HDAC_TRIGGER_UNSOL)
+ taskqueue_enqueue(taskqueue_thread, &sc->unsolq_task);
}
/****************************************************************************
-* int hdac_reset(hdac_softc *)
-*
-* Reset the hdac to a quiescent and known state.
-****************************************************************************/
+ * int hdac_reset(hdac_softc *)
+ *
+ * Reset the hdac to a quiescent and known state.
+ ****************************************************************************/
static int
hdac_reset(struct hdac_softc *sc)
{
-uint32_t gctl;
-int count, i;
+ uint32_t gctl;
+ int count, i;
-/*
-* Stop all Streams DMA engine
-*/
-for (i = 0; i < sc->num_iss; i++)
-HDAC_WRITE_4(&sc->mem, HDAC_ISDCTL(sc, i), 0x0);
-for (i = 0; i < sc->num_oss; i++)
-HDAC_WRITE_4(&sc->mem, HDAC_OSDCTL(sc, i), 0x0);
-for (i = 0; i < sc->num_bss; i++)
-HDAC_WRITE_4(&sc->mem, HDAC_BSDCTL(sc, i), 0x0);
+ /*
+ * Stop all Streams DMA engine
+ */
+ for (i = 0; i < sc->num_iss; i++)
+ HDAC_WRITE_4(&sc->mem, HDAC_ISDCTL(sc, i), 0x0);
+ for (i = 0; i < sc->num_oss; i++)
+ HDAC_WRITE_4(&sc->mem, HDAC_OSDCTL(sc, i), 0x0);
+ for (i = 0; i < sc->num_bss; i++)
+ HDAC_WRITE_4(&sc->mem, HDAC_BSDCTL(sc, i), 0x0);
+
+ /*
+ * Stop Control DMA engines.
+ */
+ HDAC_WRITE_1(&sc->mem, HDAC_CORBCTL, 0x0);
+ HDAC_WRITE_1(&sc->mem, HDAC_RIRBCTL, 0x0);
+
+ /*
+ * Reset DMA position buffer.
+ */
+ HDAC_WRITE_4(&sc->mem, HDAC_DPIBLBASE, 0x0);
+ HDAC_WRITE_4(&sc->mem, HDAC_DPIBUBASE, 0x0);
+
+ /*
+ * Reset the controller. The reset must remain asserted for
+ * a minimum of 100us.
+ */
+ gctl = HDAC_READ_4(&sc->mem, HDAC_GCTL);
+ HDAC_WRITE_4(&sc->mem, HDAC_GCTL, gctl & ~HDAC_GCTL_CRST);
+ count = 10000;
+ do {
+ gctl = HDAC_READ_4(&sc->mem, HDAC_GCTL);
+ if (!(gctl & HDAC_GCTL_CRST))
+ break;
+ DELAY(10);
+ } while (--count);
+ if (gctl & HDAC_GCTL_CRST) {
+ device_printf(sc->dev, "Unable to put hdac in reset\n");
+ return (ENXIO);
+ }
+ DELAY(100);
+ gctl = HDAC_READ_4(&sc->mem, HDAC_GCTL);
+ HDAC_WRITE_4(&sc->mem, HDAC_GCTL, gctl | HDAC_GCTL_CRST);
+ count = 10000;
+ do {
+ gctl = HDAC_READ_4(&sc->mem, HDAC_GCTL);
+ if (gctl & HDAC_GCTL_CRST)
+ break;
+ DELAY(10);
+ } while (--count);
+ if (!(gctl & HDAC_GCTL_CRST)) {
+ device_printf(sc->dev, "Device stuck in reset\n");
+ return (ENXIO);
+ }
+
+ /*
+ * Wait for codecs to finish their own reset sequence. The delay here
+ * should be of 250us but for some reasons, on it's not enough on my
+ * computer. Let's use twice as much as necessary to make sure that
+ * it's reset properly.
+ */
+ DELAY(1000);
-/*
-* Stop Control DMA engines
-*/
-HDAC_WRITE_1(&sc->mem, HDAC_CORBCTL, 0x0);
-HDAC_WRITE_1(&sc->mem, HDAC_RIRBCTL, 0x0);
-
-/*
-* Reset the controller. The reset must remain asserted for
-* a minimum of 100us.
-*/
-gctl = HDAC_READ_4(&sc->mem, HDAC_GCTL);
-HDAC_WRITE_4(&sc->mem, HDAC_GCTL, gctl & ~HDAC_GCTL_CRST);
-count = 10000;
-do {
-gctl = HDAC_READ_4(&sc->mem, HDAC_GCTL);
-if (!(gctl & HDAC_GCTL_CRST))
-break;
-DELAY(10);
-} while (--count);
-if (gctl & HDAC_GCTL_CRST) {
-device_printf(sc->dev, "Unable to put hdac in resetn");
-return (ENXIO);
-}
-DELAY(100);
-gctl = HDAC_READ_4(&sc->mem, HDAC_GCTL);
-HDAC_WRITE_4(&sc->mem, HDAC_GCTL, gctl | HDAC_GCTL_CRST);
-count = 10000;
-do {
-gctl = HDAC_READ_4(&sc->mem, HDAC_GCTL);
-if (gctl & HDAC_GCTL_CRST)
-break;
-DELAY(10);
-} while (--count);
-if (!(gctl & HDAC_GCTL_CRST)) {
-device_printf(sc->dev, "Device stuck in resetn");
-return (ENXIO);
-}
-
-/*
-* Wait for codecs to finish their own reset sequence. The delay here
-* should be of 250us but for some reasons, on it's not enough on my
-* computer. Let's use twice as much as necessary to make sure that
-* it's reset properly.
-*/
-DELAY(1000);
-
-return (0);
+ return (0);
}
/****************************************************************************
-* int hdac_get_capabilities(struct hdac_softc *);
-*
-* Retreive the general capabilities of the hdac;
-* Number of Input Streams
-* Number of Output Streams
-* Number of bidirectional Streams
-* 64bit ready
-* CORB and RIRB sizes
-****************************************************************************/
+ * int hdac_get_capabilities(struct hdac_softc *);
+ *
+ * Retreive the general capabilities of the hdac;
+ * Number of Input Streams
+ * Number of Output Streams
+ * Number of bidirectional Streams
+ * 64bit ready
+ * CORB and RIRB sizes
+ ****************************************************************************/
static int
hdac_get_capabilities(struct hdac_softc *sc)
{
-uint16_t gcap;
-uint8_t corbsize, rirbsize;
+ uint16_t gcap;
+ uint8_t corbsize, rirbsize;
-gcap = HDAC_READ_2(&sc->mem, HDAC_GCAP);
-sc->num_iss = HDAC_GCAP_ISS(gcap);
-sc->num_oss = HDAC_GCAP_OSS(gcap);
-sc->num_bss = HDAC_GCAP_BSS(gcap);
-
-sc->support_64bit = HDA_FLAG_MATCH(gcap, HDAC_GCAP_64OK);
-
-corbsize = HDAC_READ_1(&sc->mem, HDAC_CORBSIZE);
-if ((corbsize & HDAC_CORBSIZE_CORBSZCAP_256) ==
-HDAC_CORBSIZE_CORBSZCAP_256)
-sc->corb_size = 256;
-else if ((corbsize & HDAC_CORBSIZE_CORBSZCAP_16) ==
-HDAC_CORBSIZE_CORBSZCAP_16)
-sc->corb_size = 16;
-else if ((corbsize & HDAC_CORBSIZE_CORBSZCAP_2) ==
-HDAC_CORBSIZE_CORBSZCAP_2)
-sc->corb_size = 2;
-else {
-device_printf(sc->dev, "%s: Invalid corb size (%x)n",
-__func__, corbsize);
-return (ENXIO);
-}
-
-rirbsize = HDAC_READ_1(&sc->mem, HDAC_RIRBSIZE);
-if ((rirbsize & HDAC_RIRBSIZE_RIRBSZCAP_256) ==
-HDAC_RIRBSIZE_RIRBSZCAP_256)
-sc->rirb_size = 256;
-else if ((rirbsize & HDAC_RIRBSIZE_RIRBSZCAP_16) ==
-HDAC_RIRBSIZE_RIRBSZCAP_16)
-sc->rirb_size = 16;
-else if ((rirbsize & HDAC_RIRBSIZE_RIRBSZCAP_2) ==
-HDAC_RIRBSIZE_RIRBSZCAP_2)
-sc->rirb_size = 2;
-else {
-device_printf(sc->dev, "%s: Invalid rirb size (%x)n",
-__func__, rirbsize);
-return (ENXIO);
-}
+ gcap = HDAC_READ_2(&sc->mem, HDAC_GCAP);
+ sc->num_iss = HDAC_GCAP_ISS(gcap);
+ sc->num_oss = HDAC_GCAP_OSS(gcap);
+ sc->num_bss = HDAC_GCAP_BSS(gcap);
+
+ sc->support_64bit = HDA_FLAG_MATCH(gcap, HDAC_GCAP_64OK);
+
+ corbsize = HDAC_READ_1(&sc->mem, HDAC_CORBSIZE);
+ if ((corbsize & HDAC_CORBSIZE_CORBSZCAP_256) ==
+ HDAC_CORBSIZE_CORBSZCAP_256)
+ sc->corb_size = 256;
+ else if ((corbsize & HDAC_CORBSIZE_CORBSZCAP_16) ==
+ HDAC_CORBSIZE_CORBSZCAP_16)
+ sc->corb_size = 16;
+ else if ((corbsize & HDAC_CORBSIZE_CORBSZCAP_2) ==
+ HDAC_CORBSIZE_CORBSZCAP_2)
+ sc->corb_size = 2;
+ else {
+ device_printf(sc->dev, "%s: Invalid corb size (%x)\n",
+ __func__, corbsize);
+ return (ENXIO);
+ }
+
+ rirbsize = HDAC_READ_1(&sc->mem, HDAC_RIRBSIZE);
+ if ((rirbsize & HDAC_RIRBSIZE_RIRBSZCAP_256) ==
+ HDAC_RIRBSIZE_RIRBSZCAP_256)
+ sc->rirb_size = 256;
+ else if ((rirbsize & HDAC_RIRBSIZE_RIRBSZCAP_16) ==
+ HDAC_RIRBSIZE_RIRBSZCAP_16)
+ sc->rirb_size = 16;
+ else if ((rirbsize & HDAC_RIRBSIZE_RIRBSZCAP_2) ==
+ HDAC_RIRBSIZE_RIRBSZCAP_2)
+ sc->rirb_size = 2;
+ else {
+ device_printf(sc->dev, "%s: Invalid rirb size (%x)\n",
+ __func__, rirbsize);
+ return (ENXIO);
+ }
-return (0);
+ return (0);
}
/****************************************************************************
-* void hdac_dma_cb
-*
-* This function is called by bus_dmamap_load when the mapping has been
-* established. We just record the physical address of the mapping into
-* the struct hdac_dma passed in.
-****************************************************************************/
+ * void hdac_dma_cb
+ *
+ * This function is called by bus_dmamap_load when the mapping has been
+ * established. We just record the physical address of the mapping into
+ * the struct hdac_dma passed in.
+ ****************************************************************************/
static void
hdac_dma_cb(void *callback_arg, bus_dma_segment_t *segs, int nseg, int error)
{
-struct hdac_dma *dma;
+ struct hdac_dma *dma;
-if (error == 0) {
-dma = (struct hdac_dma *)callback_arg;
-dma->dma_paddr = segs[0].ds_addr;
-}
+ if (error == 0) {
+ dma = (struct hdac_dma *)callback_arg;
+ dma->dma_paddr = segs[0].ds_addr;
+ }
}
-static void
-hdac_dma_nocache(void *ptr)
-{
-#if defined(__i386__) || defined(__amd64__)
-pt_entry_t *pte;
-vm_offset_t va;
-
-va = (vm_offset_t)ptr;
-pte = vtopte(va);
-if (pte) {
-*pte |= PG_N;
-invltlb();
-}
-#endif
-}
/****************************************************************************
-* int hdac_dma_alloc
-*
-* This function allocate and setup a dma region (struct hdac_dma).
-* It must be freed by a corresponding hdac_dma_free.
-****************************************************************************/
+ * int hdac_dma_alloc
+ *
+ * This function allocate and setup a dma region (struct hdac_dma).
+ * It must be freed by a corresponding hdac_dma_free.
+ ****************************************************************************/
static int
hdac_dma_alloc(struct hdac_softc *sc, struct hdac_dma *dma, bus_size_t size)
{
-int result;
-int lowaddr;
+ bus_size_t roundsz;
+ int result;
+ int lowaddr;
+
+ roundsz = roundup2(size, HDAC_DMA_ALIGNMENT);
+ lowaddr = (sc->support_64bit) ? BUS_SPACE_MAXADDR :
+ BUS_SPACE_MAXADDR_32BIT;
+ bzero(dma, sizeof(*dma));
+
+ /*
+ * Create a DMA tag
+ */
+ result = bus_dma_tag_create(NULL, /* parent */
+ HDAC_DMA_ALIGNMENT, /* alignment */
+ 0, /* boundary */
+ lowaddr, /* lowaddr */
+ BUS_SPACE_MAXADDR, /* highaddr */
+ NULL, /* filtfunc */
+ NULL, /* fistfuncarg */
+ roundsz, /* maxsize */
+ 1, /* nsegments */
+ roundsz, /* maxsegsz */
+ 0, /* flags */
+ NULL, /* lockfunc */
+ NULL, /* lockfuncarg */
+ &dma->dma_tag); /* dmat */
+ if (result != 0) {
+ device_printf(sc->dev, "%s: bus_dma_tag_create failed (%x)\n",
+ __func__, result);
+ goto hdac_dma_alloc_fail;
+ }
+
+ /*
+ * Allocate DMA memory
+ */
+ result = bus_dmamem_alloc(dma->dma_tag, (void **)&dma->dma_vaddr,
+ BUS_DMA_NOWAIT | BUS_DMA_ZERO |
+ ((sc->flags & HDAC_F_DMA_NOCACHE) ? BUS_DMA_NOCACHE : 0),
+ &dma->dma_map);
+ if (result != 0) {
+ device_printf(sc->dev, "%s: bus_dmamem_alloc failed (%x)\n",
+ __func__, result);
+ goto hdac_dma_alloc_fail;
+ }
+
+ dma->dma_size = roundsz;
+
+ /*
+ * Map the memory
+ */
+ result = bus_dmamap_load(dma->dma_tag, dma->dma_map,
+ (void *)dma->dma_vaddr, roundsz, hdac_dma_cb, (void *)dma, 0);
+ if (result != 0 || dma->dma_paddr == 0) {
+ if (result == 0)
+ result = ENOMEM;
+ device_printf(sc->dev, "%s: bus_dmamem_load failed (%x)\n",
+ __func__, result);
+ goto hdac_dma_alloc_fail;
+ }
+
+ HDA_BOOTVERBOSE(
+ device_printf(sc->dev, "%s: size=%ju -> roundsz=%ju\n",
+ __func__, (uintmax_t)size, (uintmax_t)roundsz);
+ );
-lowaddr = (sc->support_64bit) ? BUS_SPACE_MAXADDR :
-BUS_SPACE_MAXADDR_32BIT;
-bzero(dma, sizeof(*dma));
-
-/*
-* Create a DMA tag
-*/
-result = bus_dma_tag_create(NULL, /* parent */
-HDAC_DMA_ALIGNMENT, /* alignment */
-0, /* boundary */
-lowaddr, /* lowaddr */
-BUS_SPACE_MAXADDR, /* highaddr */
-NULL, /* filtfunc */
-NULL, /* fistfuncarg */
-size, /* maxsize */
-1, /* nsegments */
-size, /* maxsegsz */
-0, /* flags */
-NULL, /* lockfunc */
-NULL, /* lockfuncarg */
-&dma->dma_tag); /* dmat */
-if (result != 0) {
-device_printf(sc->dev, "%s: bus_dma_tag_create failed (%x)n",
-__func__, result);
-goto fail;
-}
+ return (0);
-/*
-* Allocate DMA memory
-*/
-result = bus_dmamem_alloc(dma->dma_tag, (void **)&dma->dma_vaddr,
-BUS_DMA_NOWAIT | BUS_DMA_COHERENT, &dma->dma_map);
-if (result != 0) {
-device_printf(sc->dev, "%s: bus_dmamem_alloc failed (%x)n",
-__func__, result);
-goto fail;
-}
+hdac_dma_alloc_fail:
+ hdac_dma_free(sc, dma);
-/*
-* Map the memory
-*/
-result = bus_dmamap_load(dma->dma_tag, dma->dma_map,
-(void *)dma->dma_vaddr, size, hdac_dma_cb, (void *)dma,
-BUS_DMA_NOWAIT);
-if (result != 0 || dma->dma_paddr == 0) {
-device_printf(sc->dev, "%s: bus_dmamem_load failed (%x)n",
-__func__, result);
-goto fail;
-}
-bzero((void *)dma->dma_vaddr, size);
-hdac_dma_nocache(dma->dma_vaddr);
-
-return (0);
-fail:
-if (dma->dma_map != NULL)
-bus_dmamem_free(dma->dma_tag, dma->dma_vaddr, dma->dma_map);
-if (dma->dma_tag != NULL)
-bus_dma_tag_destroy(dma->dma_tag);
-return (result);
+ return (result);
}
/****************************************************************************
-* void hdac_dma_free(struct hdac_dma *)
-*
-* Free a struct dhac_dma that has been previously allocated via the
-* hdac_dma_alloc function.
-****************************************************************************/
-static void
-hdac_dma_free(struct hdac_dma *dma)
-{
-if (dma->dma_tag != NULL) {
-/* Flush caches */
-bus_dmamap_sync(dma->dma_tag, dma->dma_map,
-BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
-bus_dmamap_unload(dma->dma_tag, dma->dma_map);
-bus_dmamem_free(dma->dma_tag, dma->dma_vaddr, dma->dma_map);
-bus_dma_tag_destroy(dma->dma_tag);
-}
+ * void hdac_dma_free(struct hdac_softc *, struct hdac_dma *)
+ *
+ * Free a struct dhac_dma that has been previously allocated via the
+ * hdac_dma_alloc function.
+ ****************************************************************************/
+static void
+hdac_dma_free(struct hdac_softc *sc, struct hdac_dma *dma)
+{
+ if (dma->dma_map != NULL) {
+#if 0
+ /* Flush caches */
+ bus_dmamap_sync(dma->dma_tag, dma->dma_map,
+ BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
+#endif
+ bus_dmamap_unload(dma->dma_tag, dma->dma_map);
+ }
+ if (dma->dma_vaddr != NULL) {
+ bus_dmamem_free(dma->dma_tag, dma->dma_vaddr, dma->dma_map);
+ dma->dma_vaddr = NULL;
+ }
+ dma->dma_map = NULL;
+ if (dma->dma_tag != NULL) {
+ bus_dma_tag_destroy(dma->dma_tag);
+ dma->dma_tag = NULL;
+ }
+ dma->dma_size = 0;
}
/****************************************************************************
-* int hdac_mem_alloc(struct hdac_softc *)
-*
-* Allocate all the bus resources necessary to speak with the physical
-* controller.
-****************************************************************************/
+ * int hdac_mem_alloc(struct hdac_softc *)
+ *
+ * Allocate all the bus resources necessary to speak with the physical
+ * controller.
+ ****************************************************************************/
static int
hdac_mem_alloc(struct hdac_softc *sc)
{
-struct hdac_mem *mem;
+ struct hdac_mem *mem;
-mem = &sc->mem;
-mem->mem_rid = PCIR_BAR(0);
-mem->mem_res = bus_alloc_resource_any(sc->dev, SYS_RES_MEMORY,
-&mem->mem_rid, RF_ACTIVE);
-if (mem->mem_res == NULL) {
-device_printf(sc->dev,
-"%s: Unable to allocate memory resourcen", __func__);
-return (ENOMEM);
-}
-mem->mem_tag = rman_get_bustag(mem->mem_res);
-mem->mem_handle = rman_get_bushandle(mem->mem_res);
+ mem = &sc->mem;
+ mem->mem_rid = PCIR_BAR(0);
+ mem->mem_res = bus_alloc_resource_any(sc->dev, SYS_RES_MEMORY,
+ &mem->mem_rid, RF_ACTIVE);
+ if (mem->mem_res == NULL) {
+ device_printf(sc->dev,
+ "%s: Unable to allocate memory resource\n", __func__);
+ return (ENOMEM);
+ }
+ mem->mem_tag = rman_get_bustag(mem->mem_res);
+ mem->mem_handle = rman_get_bushandle(mem->mem_res);
-return (0);
+ return (0);
}
/****************************************************************************
-* void hdac_mem_free(struct hdac_softc *)
-*
-* Free up resources previously allocated by hdac_mem_alloc.
-****************************************************************************/
+ * void hdac_mem_free(struct hdac_softc *)
+ *
+ * Free up resources previously allocated by hdac_mem_alloc.
+ ****************************************************************************/
static void
hdac_mem_free(struct hdac_softc *sc)
{
-struct hdac_mem *mem;
+ struct hdac_mem *mem;
-mem = &sc->mem;
-if (mem->mem_res != NULL)
-bus_release_resource(sc->dev, SYS_RES_MEMORY, mem->mem_rid,
-mem->mem_res);
+ mem = &sc->mem;
+ if (mem->mem_res != NULL)
+ bus_release_resource(sc->dev, SYS_RES_MEMORY, mem->mem_rid,
+ mem->mem_res);
+ mem->mem_res = NULL;
}
/****************************************************************************
-* int hdac_irq_alloc(struct hdac_softc *)
-*
-* Allocate and setup the resources necessary for interrupt handling.
-****************************************************************************/
+ * int hdac_irq_alloc(struct hdac_softc *)
+ *
+ * Allocate and setup the resources necessary for interrupt handling.
+ ****************************************************************************/
static int
hdac_irq_alloc(struct hdac_softc *sc)
{
-struct hdac_irq *irq;
-int result;
+ struct hdac_irq *irq;
+ int result;
+
+ irq = &sc->irq;
+ irq->irq_rid = 0x0;
+
+#if __FreeBSD_version >= 602106
+ if ((sc->flags & HDAC_F_MSI) &&
+ (result = pci_msi_count(sc->dev)) == 1 &&
+ pci_alloc_msi(sc->dev, &result) == 0)
+ irq->irq_rid = 0x1;
+ else
+#endif
+ sc->flags &= ~HDAC_F_MSI;
+
+ irq->irq_res = bus_alloc_resource_any(sc->dev, SYS_RES_IRQ,
+ &irq->irq_rid, RF_SHAREABLE | RF_ACTIVE);
+ if (irq->irq_res == NULL) {
+ device_printf(sc->dev, "%s: Unable to allocate irq\n",
+ __func__);
+ goto hdac_irq_alloc_fail;
+ }
+ result = snd_setup_intr(sc->dev, irq->irq_res, INTR_MPSAFE,
+ hdac_intr_handler, sc, &irq->irq_handle);
+ if (result != 0) {
+ device_printf(sc->dev,
+ "%s: Unable to setup interrupt handler (%x)\n",
+ __func__, result);
+ goto hdac_irq_alloc_fail;
+ }
-irq = &sc->irq;
-irq->irq_rid = 0x0;
-irq->irq_res = bus_alloc_resource_any(sc->dev, SYS_RES_IRQ,
-&irq->irq_rid, RF_SHAREABLE | RF_ACTIVE);
-if (irq->irq_res == NULL) {
-device_printf(sc->dev, "%s: Unable to allocate irqn",
-__func__);
-goto fail;
-}
-result = snd_setup_intr(sc->dev, irq->irq_res, INTR_MPSAFE,
-hdac_intr_handler, sc, &irq->irq_handle);
-if (result != 0) {
-device_printf(sc->dev,
-"%s: Unable to setup interrupt handler (%x)n",
-__func__, result);
-goto fail;
-}
-
-return (0);
-
-fail:
-if (irq->irq_res != NULL)
-bus_release_resource(sc->dev, SYS_RES_IRQ, irq->irq_rid,
-irq->irq_res);
-return (ENXIO);
+ return (0);
+
+hdac_irq_alloc_fail:
+ hdac_irq_free(sc);
+
+ return (ENXIO);
}
/****************************************************************************
-* void hdac_irq_free(struct hdac_softc *)
-*
-* Free up resources previously allocated by hdac_irq_alloc.
-****************************************************************************/
+ * void hdac_irq_free(struct hdac_softc *)
+ *
+ * Free up resources previously allocated by hdac_irq_alloc.
+ ****************************************************************************/
static void
hdac_irq_free(struct hdac_softc *sc)
{
-struct hdac_irq *irq;
+ struct hdac_irq *irq;
-irq = &sc->irq;
-if (irq->irq_handle != NULL)
-bus_teardown_intr(sc->dev, irq->irq_res, irq->irq_handle);
-if (irq->irq_res != NULL)
-bus_release_resource(sc->dev, SYS_RES_IRQ, irq->irq_rid,
-irq->irq_res);
+ irq = &sc->irq;
+ if (irq->irq_res != NULL && irq->irq_handle != NULL)
+ bus_teardown_intr(sc->dev, irq->irq_res, irq->irq_handle);
+ if (irq->irq_res != NULL)
+ bus_release_resource(sc->dev, SYS_RES_IRQ, irq->irq_rid,
+ irq->irq_res);
+#if __FreeBSD_version >= 602106
+ if ((sc->flags & HDAC_F_MSI) && irq->irq_rid == 0x1)
+ pci_release_msi(sc->dev);
+#endif
+ irq->irq_handle = NULL;
+ irq->irq_res = NULL;
+ irq->irq_rid = 0x0;
}
/****************************************************************************
-* void hdac_corb_init(struct hdac_softc *)
-*
-* Initialize the corb registers for operations but do not start it up yet.
-* The CORB engine must not be running when this function is called.
-****************************************************************************/
+ * void hdac_corb_init(struct hdac_softc *)
+ *
+ * Initialize the corb registers for operations but do not start it up yet.
+ * The CORB engine must not be running when this function is called.
+ ****************************************************************************/
static void
hdac_corb_init(struct hdac_softc *sc)
{
-uint8_t corbsize;
-uint64_t corbpaddr;
+ uint8_t corbsize;
+ uint64_t corbpaddr;
-/* Setup the CORB size. */
-switch (sc->corb_size) {
-case 256:
-corbsize = HDAC_CORBSIZE_CORBSIZE(HDAC_CORBSIZE_CORBSIZE_256);
-break;
-case 16:
-corbsize = HDAC_CORBSIZE_CORBSIZE(HDAC_CORBSIZE_CORBSIZE_16);
-break;
-case 2:
-corbsize = HDAC_CORBSIZE_CORBSIZE(HDAC_CORBSIZE_CORBSIZE_2);
-break;
-default:
-panic("%s: Invalid CORB size (%x)n", __func__, sc->corb_size);
-}
-HDAC_WRITE_1(&sc->mem, HDAC_CORBSIZE, corbsize);
-
-/* Setup the CORB Address in the hdac */
-corbpaddr = (uint64_t)sc->corb_dma.dma_paddr;
-HDAC_WRITE_4(&sc->mem, HDAC_CORBLBASE, (uint32_t)corbpaddr);
-HDAC_WRITE_4(&sc->mem, HDAC_CORBUBASE, (uint32_t)(corbpaddr >> 32));
-
-/* Set the WP and RP */
-sc->corb_wp = 0;
-HDAC_WRITE_2(&sc->mem, HDAC_CORBWP, sc->corb_wp);
-HDAC_WRITE_2(&sc->mem, HDAC_CORBRP, HDAC_CORBRP_CORBRPRST);
-/*
-* The HDA specification indicates that the CORBRPRST bit will always
-* read as zero. Unfortunately, it seems that at least the 82801G
-* doesn't reset the bit to zero, which stalls the corb engine.
-* manually reset the bit to zero before continuing.
-*/
-HDAC_WRITE_2(&sc->mem, HDAC_CORBRP, 0x0);
+ /* Setup the CORB size. */
+ switch (sc->corb_size) {
+ case 256:
+ corbsize = HDAC_CORBSIZE_CORBSIZE(HDAC_CORBSIZE_CORBSIZE_256);
+ break;
+ case 16:
+ corbsize = HDAC_CORBSIZE_CORBSIZE(HDAC_CORBSIZE_CORBSIZE_16);
+ break;
+ case 2:
+ corbsize = HDAC_CORBSIZE_CORBSIZE(HDAC_CORBSIZE_CORBSIZE_2);
+ break;
+ default:
+ panic("%s: Invalid CORB size (%x)\n", __func__, sc->corb_size);
+ }
+ HDAC_WRITE_1(&sc->mem, HDAC_CORBSIZE, corbsize);
+
+ /* Setup the CORB Address in the hdac */
+ corbpaddr = (uint64_t)sc->corb_dma.dma_paddr;
+ HDAC_WRITE_4(&sc->mem, HDAC_CORBLBASE, (uint32_t)corbpaddr);
+ HDAC_WRITE_4(&sc->mem, HDAC_CORBUBASE, (uint32_t)(corbpaddr >> 32));
+
+ /* Set the WP and RP */
+ sc->corb_wp = 0;
+ HDAC_WRITE_2(&sc->mem, HDAC_CORBWP, sc->corb_wp);
+ HDAC_WRITE_2(&sc->mem, HDAC_CORBRP, HDAC_CORBRP_CORBRPRST);
+ /*
+ * The HDA specification indicates that the CORBRPRST bit will always
+ * read as zero. Unfortunately, it seems that at least the 82801G
+ * doesn't reset the bit to zero, which stalls the corb engine.
+ * manually reset the bit to zero before continuing.
+ */
+ HDAC_WRITE_2(&sc->mem, HDAC_CORBRP, 0x0);
-/* Enable CORB error reporting */
+ /* Enable CORB error reporting */
#if 0
-HDAC_WRITE_1(&sc->mem, HDAC_CORBCTL, HDAC_CORBCTL_CMEIE);
+ HDAC_WRITE_1(&sc->mem, HDAC_CORBCTL, HDAC_CORBCTL_CMEIE);
#endif
}
/****************************************************************************
-* void hdac_rirb_init(struct hdac_softc *)
-*
-* Initialize the rirb registers for operations but do not start it up yet.
-* The RIRB engine must not be running when this function is called.
-****************************************************************************/
+ * void hdac_rirb_init(struct hdac_softc *)
+ *
+ * Initialize the rirb registers for operations but do not start it up yet.
+ * The RIRB engine must not be running when this function is called.
+ ****************************************************************************/
static void
hdac_rirb_init(struct hdac_softc *sc)
{
-uint8_t rirbsize;
-uint64_t rirbpaddr;
+ uint8_t rirbsize;
+ uint64_t rirbpaddr;
-/* Setup the RIRB size. */
-switch (sc->rirb_size) {
-case 256:
-rirbsize = HDAC_RIRBSIZE_RIRBSIZE(HDAC_RIRBSIZE_RIRBSIZE_256);
-break;
-case 16:
-rirbsize = HDAC_RIRBSIZE_RIRBSIZE(HDAC_RIRBSIZE_RIRBSIZE_16);
-break;
-case 2:
-rirbsize = HDAC_RIRBSIZE_RIRBSIZE(HDAC_RIRBSIZE_RIRBSIZE_2);
-break;
-default:
-panic("%s: Invalid RIRB size (%x)n", __func__, sc->rirb_size);
-}
-HDAC_WRITE_1(&sc->mem, HDAC_RIRBSIZE, rirbsize);
-
-/* Setup the RIRB Address in the hdac */
-rirbpaddr = (uint64_t)sc->rirb_dma.dma_paddr;
-HDAC_WRITE_4(&sc->mem, HDAC_RIRBLBASE, (uint32_t)rirbpaddr);
-HDAC_WRITE_4(&sc->mem, HDAC_RIRBUBASE, (uint32_t)(rirbpaddr >> 32));
-
-/* Setup the WP and RP */
-sc->rirb_rp = 0;
-HDAC_WRITE_2(&sc->mem, HDAC_RIRBWP, HDAC_RIRBWP_RIRBWPRST);
+ /* Setup the RIRB size. */
+ switch (sc->rirb_size) {
+ case 256:
+ rirbsize = HDAC_RIRBSIZE_RIRBSIZE(HDAC_RIRBSIZE_RIRBSIZE_256);
+ break;
+ case 16:
+ rirbsize = HDAC_RIRBSIZE_RIRBSIZE(HDAC_RIRBSIZE_RIRBSIZE_16);
+ break;
+ case 2:
+ rirbsize = HDAC_RIRBSIZE_RIRBSIZE(HDAC_RIRBSIZE_RIRBSIZE_2);
+ break;
+ default:
+ panic("%s: Invalid RIRB size (%x)\n", __func__, sc->rirb_size);
+ }
+ HDAC_WRITE_1(&sc->mem, HDAC_RIRBSIZE, rirbsize);
+
+ /* Setup the RIRB Address in the hdac */
+ rirbpaddr = (uint64_t)sc->rirb_dma.dma_paddr;
+ HDAC_WRITE_4(&sc->mem, HDAC_RIRBLBASE, (uint32_t)rirbpaddr);
+ HDAC_WRITE_4(&sc->mem, HDAC_RIRBUBASE, (uint32_t)(rirbpaddr >> 32));
+
+ /* Setup the WP and RP */
+ sc->rirb_rp = 0;
+ HDAC_WRITE_2(&sc->mem, HDAC_RIRBWP, HDAC_RIRBWP_RIRBWPRST);
+
+ if (sc->polling == 0) {
+ /* Setup the interrupt threshold */
+ HDAC_WRITE_2(&sc->mem, HDAC_RINTCNT, sc->rirb_size / 2);
-/* Setup the interrupt threshold */
-HDAC_WRITE_2(&sc->mem, HDAC_RINTCNT, sc->rirb_size / 2);
-
-/* Enable Overrun and response received reporting */
+ /* Enable Overrun and response received reporting */
#if 0
-HDAC_WRITE_1(&sc->mem, HDAC_RIRBCTL,
-HDAC_RIRBCTL_RIRBOIC | HDAC_RIRBCTL_RINTCTL);
+ HDAC_WRITE_1(&sc->mem, HDAC_RIRBCTL,
+ HDAC_RIRBCTL_RIRBOIC | HDAC_RIRBCTL_RINTCTL);
#else
-HDAC_WRITE_1(&sc->mem, HDAC_RIRBCTL, HDAC_RIRBCTL_RINTCTL);
+ HDAC_WRITE_1(&sc->mem, HDAC_RIRBCTL, HDAC_RIRBCTL_RINTCTL);
#endif
+ }
-/*
-* Make sure that the Host CPU cache doesn't contain any dirty
-* cache lines that falls in the rirb. If I understood correctly, it
-* should be sufficient to do this only once as the rirb is purely
-* read-only from now on.
-*/
-bus_dmamap_sync(sc->rirb_dma.dma_tag, sc->rirb_dma.dma_map,
-BUS_DMASYNC_PREREAD);
+#if 0
+ /*
+ * Make sure that the Host CPU cache doesn't contain any dirty
+ * cache lines that falls in the rirb. If I understood correctly, it
+ * should be sufficient to do this only once as the rirb is purely
+ * read-only from now on.
+ */
+ bus_dmamap_sync(sc->rirb_dma.dma_tag, sc->rirb_dma.dma_map,
+ BUS_DMASYNC_PREREAD);
+#endif
}
/****************************************************************************
-* void hdac_corb_start(hdac_softc *)
-*
-* Startup the corb DMA engine
-****************************************************************************/
+ * void hdac_corb_start(hdac_softc *)
+ *
+ * Startup the corb DMA engine
+ ****************************************************************************/
static void
hdac_corb_start(struct hdac_softc *sc)
{
-uint32_t corbctl;
+ uint32_t corbctl;
-corbctl = HDAC_READ_1(&sc->mem, HDAC_CORBCTL);
-corbctl |= HDAC_CORBCTL_CORBRUN;
-HDAC_WRITE_1(&sc->mem, HDAC_CORBCTL, corbctl);
+ corbctl = HDAC_READ_1(&sc->mem, HDAC_CORBCTL);
+ corbctl |= HDAC_CORBCTL_CORBRUN;
+ HDAC_WRITE_1(&sc->mem, HDAC_CORBCTL, corbctl);
}
/****************************************************************************
-* void hdac_rirb_start(hdac_softc *)
-*
-* Startup the rirb DMA engine
-****************************************************************************/
+ * void hdac_rirb_start(hdac_softc *)
+ *
+ * Startup the rirb DMA engine
+ ****************************************************************************/
static void
hdac_rirb_start(struct hdac_softc *sc)
{
-uint32_t rirbctl;
+ uint32_t rirbctl;
-rirbctl = HDAC_READ_1(&sc->mem, HDAC_RIRBCTL);
-rirbctl |= HDAC_RIRBCTL_RIRBDMAEN;
-HDAC_WRITE_1(&sc->mem, HDAC_RIRBCTL, rirbctl);
+ rirbctl = HDAC_READ_1(&sc->mem, HDAC_RIRBCTL);
+ rirbctl |= HDAC_RIRBCTL_RIRBDMAEN;
+ HDAC_WRITE_1(&sc->mem, HDAC_RIRBCTL, rirbctl);
}
/****************************************************************************
-* void hdac_scan_codecs(struct hdac_softc *)
-*
-* Scan the bus for available codecs.
-****************************************************************************/
-static void
-hdac_scan_codecs(struct hdac_softc *sc)
-{
-struct hdac_codec *codec;
-int i;
-uint16_t statests;
-
-statests = HDAC_READ_2(&sc->mem, HDAC_STATESTS);
-for (i = 0; i < HDAC_CODEC_MAX; i++) {
-if (HDAC_STATESTS_SDIWAKE(statests, i)) {
-/* We have found a codec. */
-hdac_unlock(sc);
-codec = (struct hdac_codec *)malloc(sizeof(*codec),
-M_HDAC, M_ZERO | M_NOWAIT);
-hdac_lock(sc);
-if (codec == NULL) {
-device_printf(sc->dev,
-"Unable to allocate memory for codecn");
-continue;
-}
-codec->verbs_sent = 0;
-codec->sc = sc;
-codec->cad = i;
-sc->codecs[i] = codec;
-if (hdac_probe_codec(codec) != 0)
-break;
-}
-}
-/* All codecs have been probed, now try to attach drivers to them */
-/* bus_generic_attach(sc->dev); */
+ * void hdac_scan_codecs(struct hdac_softc *, int)
+ *
+ * Scan the bus for available codecs, starting with num.
+ ****************************************************************************/
+static void
+hdac_scan_codecs(struct hdac_softc *sc, int num)
+{
+ struct hdac_codec *codec;
+ int i;
+ uint16_t statests;
+
+ if (num < 0)
+ num = 0;
+ if (num >= HDAC_CODEC_MAX)
+ num = HDAC_CODEC_MAX - 1;
+
+ statests = HDAC_READ_2(&sc->mem, HDAC_STATESTS);
+ for (i = num; i < HDAC_CODEC_MAX; i++) {
+ if (HDAC_STATESTS_SDIWAKE(statests, i)) {
+ /* We have found a codec. */
+ codec = (struct hdac_codec *)malloc(sizeof(*codec),
+ M_HDAC, M_ZERO | M_NOWAIT);
+ if (codec == NULL) {
+ device_printf(sc->dev,
+ "Unable to allocate memory for codec\n");
+ continue;
+ }
+ codec->commands = NULL;
+ codec->responses_received = 0;
+ codec->verbs_sent = 0;
+ codec->sc = sc;
+ codec->cad = i;
+ sc->codecs[i] = codec;
+ if (hdac_probe_codec(codec) != 0)
+ break;
+ }
+ }
+ /* All codecs have been probed, now try to attach drivers to them */
+ /* bus_generic_attach(sc->dev); */
}
/****************************************************************************
-* void hdac_probe_codec(struct hdac_softc *, int)
-*
-* Probe a the given codec_id for available function groups.
-****************************************************************************/
+ * void hdac_probe_codec(struct hdac_softc *, int)
+ *
+ * Probe a the given codec_id for available function groups.
+ ****************************************************************************/
static int
hdac_probe_codec(struct hdac_codec *codec)
{
-struct hdac_softc *sc = codec->sc;
-struct hdac_devinfo *devinfo;
-uint32_t vendorid, revisionid, subnode;
-int startnode;
-int endnode;
-int i;
-nid_t cad = codec->cad;
-
-HDA_BOOTVERBOSE(
-device_printf(sc->dev, "HDA_DEBUG: Probing codec: %dn", cad);
-);
-vendorid = hdac_command(sc,
-HDA_CMD_GET_PARAMETER(cad, 0x0, HDA_PARAM_VENDOR_ID),
-cad);
-revisionid = hdac_command(sc,
-HDA_CMD_GET_PARAMETER(cad, 0x0, HDA_PARAM_REVISION_ID),
-cad);
-subnode = hdac_command(sc,
-HDA_CMD_GET_PARAMETER(cad, 0x0, HDA_PARAM_SUB_NODE_COUNT),
-cad);
-startnode = HDA_PARAM_SUB_NODE_COUNT_START(subnode);
-endnode = startnode + HDA_PARAM_SUB_NODE_COUNT_TOTAL(subnode);
-
-HDA_BOOTVERBOSE(
-device_printf(sc->dev, "HDA_DEBUG: tstartnode=%d endnode=%dn",
-startnode, endnode);
-);
-for (i = startnode; i < endnode; i++) {
-devinfo = hdac_probe_function(codec, i);
-if (devinfo != NULL) {
-/* XXX Ignore other FG. */
-devinfo->vendor_id =
-HDA_PARAM_VENDOR_ID_VENDOR_ID(vendorid);
-devinfo->device_id =
-HDA_PARAM_VENDOR_ID_DEVICE_ID(vendorid);
-devinfo->revision_id =
-HDA_PARAM_REVISION_ID_REVISION_ID(revisionid);
-devinfo->stepping_id =
-HDA_PARAM_REVISION_ID_STEPPING_ID(revisionid);
-HDA_BOOTVERBOSE(
-device_printf(sc->dev,
-"HDA_DEBUG: tFound AFG nid=%d "
-"[startnode=%d endnode=%d]n",
-devinfo->nid, startnode, endnode);
-);
-return (1);
-}
-}
-
-HDA_BOOTVERBOSE(
-device_printf(sc->dev, "HDA_DEBUG: tAFG not foundn");
-);
-return (0);
+ struct hdac_softc *sc = codec->sc;
+ struct hdac_devinfo *devinfo;
+ uint32_t vendorid, revisionid, subnode;
+ int startnode;
+ int endnode;
+ int i;
+ nid_t cad = codec->cad;
+
+ HDA_BOOTVERBOSE(
+ device_printf(sc->dev, "HDA_DEBUG: Probing codec: %d\n", cad);
+ );
+ vendorid = hdac_command(sc,
+ HDA_CMD_GET_PARAMETER(cad, 0x0, HDA_PARAM_VENDOR_ID),
+ cad);
+ revisionid = hdac_command(sc,
+ HDA_CMD_GET_PARAMETER(cad, 0x0, HDA_PARAM_REVISION_ID),
+ cad);
+ subnode = hdac_command(sc,
+ HDA_CMD_GET_PARAMETER(cad, 0x0, HDA_PARAM_SUB_NODE_COUNT),
+ cad);
+ startnode = HDA_PARAM_SUB_NODE_COUNT_START(subnode);
+ endnode = startnode + HDA_PARAM_SUB_NODE_COUNT_TOTAL(subnode);
+
+ HDA_BOOTVERBOSE(
+ device_printf(sc->dev, "HDA_DEBUG: \tstartnode=%d endnode=%d\n",
+ startnode, endnode);
+ );
+ for (i = startnode; i < endnode; i++) {
+ devinfo = hdac_probe_function(codec, i);
+ if (devinfo != NULL) {
+ /* XXX Ignore other FG. */
+ devinfo->vendor_id =
+ HDA_PARAM_VENDOR_ID_VENDOR_ID(vendorid);
+ devinfo->device_id =
+ HDA_PARAM_VENDOR_ID_DEVICE_ID(vendorid);
+ devinfo->revision_id =
+ HDA_PARAM_REVISION_ID_REVISION_ID(revisionid);
+ devinfo->stepping_id =
+ HDA_PARAM_REVISION_ID_STEPPING_ID(revisionid);
+ HDA_BOOTVERBOSE(
+ device_printf(sc->dev,
+ "HDA_DEBUG: \tFound AFG nid=%d "
+ "[startnode=%d endnode=%d]\n",
+ devinfo->nid, startnode, endnode);
+ );
+ return (1);
+ }
+ }
+
+ HDA_BOOTVERBOSE(
+ device_printf(sc->dev, "HDA_DEBUG: \tAFG not found\n");
+ );
+ return (0);
}
static struct hdac_devinfo *
hdac_probe_function(struct hdac_codec *codec, nid_t nid)
{
-struct hdac_softc *sc = codec->sc;
-struct hdac_devinfo *devinfo;
-uint32_t fctgrptype;
-nid_t cad = codec->cad;
-
-fctgrptype = HDA_PARAM_FCT_GRP_TYPE_NODE_TYPE(hdac_command(sc,
-HDA_CMD_GET_PARAMETER(cad, nid, HDA_PARAM_FCT_GRP_TYPE), cad));
-
-/* XXX For now, ignore other FG. */
-if (fctgrptype != HDA_PARAM_FCT_GRP_TYPE_NODE_TYPE_AUDIO)
-return (NULL);
-
-hdac_unlock(sc);
-devinfo = (struct hdac_devinfo *)malloc(sizeof(*devinfo), M_HDAC,
-M_NOWAIT | M_ZERO);
-hdac_lock(sc);
-if (devinfo == NULL) {
-device_printf(sc->dev, "%s: Unable to allocate ivarn",
-__func__);
-return (NULL);
-}
-
-devinfo->nid = nid;
-devinfo->node_type = fctgrptype;
-devinfo->codec = codec;
+ struct hdac_softc *sc = codec->sc;
+ struct hdac_devinfo *devinfo;
+ uint32_t fctgrptype;
+ nid_t cad = codec->cad;
+
+ fctgrptype = HDA_PARAM_FCT_GRP_TYPE_NODE_TYPE(hdac_command(sc,
+ HDA_CMD_GET_PARAMETER(cad, nid, HDA_PARAM_FCT_GRP_TYPE), cad));
+
+ /* XXX For now, ignore other FG. */
+ if (fctgrptype != HDA_PARAM_FCT_GRP_TYPE_NODE_TYPE_AUDIO)
+ return (NULL);
+
+ devinfo = (struct hdac_devinfo *)malloc(sizeof(*devinfo), M_HDAC,
+ M_NOWAIT | M_ZERO);
+ if (devinfo == NULL) {
+ device_printf(sc->dev, "%s: Unable to allocate ivar\n",
+ __func__);
+ return (NULL);
+ }
+
+ devinfo->nid = nid;
+ devinfo->node_type = fctgrptype;
+ devinfo->codec = codec;
-hdac_add_child(sc, devinfo);
+ hdac_add_child(sc, devinfo);
-return (devinfo);
+ return (devinfo);
}
static void
hdac_add_child(struct hdac_softc *sc, struct hdac_devinfo *devinfo)
{
-devinfo->dev = device_add_child(sc->dev, NULL, -1);
-device_set_ivars(devinfo->dev, (void *)devinfo);
-/* XXX - Print more information when booting verbose??? */
+ devinfo->dev = device_add_child(sc->dev, NULL, -1);
+ device_set_ivars(devinfo->dev, (void *)devinfo);
+ /* XXX - Print more information when booting verbose??? */
}
static void
hdac_widget_connection_parse(struct hdac_widget *w)
{
-struct hdac_softc *sc = w->devinfo->codec->sc;
-uint32_t res;
-int i, j, max, found, entnum, cnid;
-nid_t cad = w->devinfo->codec->cad;
-nid_t nid = w->nid;
-
-res = hdac_command(sc,
-HDA_CMD_GET_PARAMETER(cad, nid, HDA_PARAM_CONN_LIST_LENGTH), cad);
-
-w->nconns = HDA_PARAM_CONN_LIST_LENGTH_LIST_LENGTH(res);
-
-if (w->nconns < 1)
-return;
-
-entnum = HDA_PARAM_CONN_LIST_LENGTH_LONG_FORM(res) ? 2 : 4;
-res = 0;
-i = 0;
-found = 0;
-max = (sizeof(w->conns) / sizeof(w->conns[0])) - 1;
-
-while (i < w->nconns) {
-res = hdac_command(sc,
-HDA_CMD_GET_CONN_LIST_ENTRY(cad, nid, i), cad);
-for (j = 0; j < entnum; j++) {
-cnid = res;
-cnid >>= (32 / entnum) * j;
-cnid &= (1 << (32 / entnum)) - 1;
-if (cnid == 0)
-continue;
-if (found > max) {
-device_printf(sc->dev,
-"node %d: Adding %d: "
-"Max connection reached!n",
-nid, cnid);
-continue;
-}
-w->conns[found++] = cnid;
-}
-i += entnum;
-}
-
-HDA_BOOTVERBOSE(
-if (w->nconns != found) {
-device_printf(sc->dev,
-"HDA_DEBUG: nid=%d WARNING!!! Connection "
-"length=%d != found=%dn",
-nid, w->nconns, found);
-}
-);
+ struct hdac_softc *sc = w->devinfo->codec->sc;
+ uint32_t res;
+ int i, j, max, ents, entnum;
+ nid_t cad = w->devinfo->codec->cad;
+ nid_t nid = w->nid;
+ nid_t cnid, addcnid, prevcnid;
+
+ w->nconns = 0;
+
+ res = hdac_command(sc,
+ HDA_CMD_GET_PARAMETER(cad, nid, HDA_PARAM_CONN_LIST_LENGTH), cad);
+
+ ents = HDA_PARAM_CONN_LIST_LENGTH_LIST_LENGTH(res);
+
+ if (ents < 1)
+ return;
+
+ entnum = HDA_PARAM_CONN_LIST_LENGTH_LONG_FORM(res) ? 2 : 4;
+ max = (sizeof(w->conns) / sizeof(w->conns[0])) - 1;
+ prevcnid = 0;
+
+#define CONN_RMASK(e) (1 << ((32 / (e)) - 1))
+#define CONN_NMASK(e) (CONN_RMASK(e) - 1)
+#define CONN_RESVAL(r, e, n) ((r) >> ((32 / (e)) * (n)))
+#define CONN_RANGE(r, e, n) (CONN_RESVAL(r, e, n) & CONN_RMASK(e))
+#define CONN_CNID(r, e, n) (CONN_RESVAL(r, e, n) & CONN_NMASK(e))
+
+ for (i = 0; i < ents; i += entnum) {
+ res = hdac_command(sc,
+ HDA_CMD_GET_CONN_LIST_ENTRY(cad, nid, i), cad);
+ for (j = 0; j < entnum; j++) {
+ cnid = CONN_CNID(res, entnum, j);
+ if (cnid == 0) {
+ if (w->nconns < ents)
+ device_printf(sc->dev,
+ "%s: nid=%d WARNING: zero cnid "
+ "entnum=%d j=%d index=%d "
+ "entries=%d found=%d res=0x%08x\n",
+ __func__, nid, entnum, j, i,
+ ents, w->nconns, res);
+ else
+ goto getconns_out;
+ }
+ if (cnid < w->devinfo->startnode ||
+ cnid >= w->devinfo->endnode) {
+ HDA_BOOTVERBOSE(
+ device_printf(sc->dev,
+ "%s: GHOST: nid=%d j=%d "
+ "entnum=%d index=%d res=0x%08x\n",
+ __func__, nid, j, entnum, i, res);
+ );
+ }
+ if (CONN_RANGE(res, entnum, j) == 0)
+ addcnid = cnid;
+ else if (prevcnid == 0 || prevcnid >= cnid) {
+ device_printf(sc->dev,
+ "%s: WARNING: Invalid child range "
+ "nid=%d index=%d j=%d entnum=%d "
+ "prevcnid=%d cnid=%d res=0x%08x\n",
+ __func__, nid, i, j, entnum, prevcnid,
+ cnid, res);
+ addcnid = cnid;
+ } else
+ addcnid = prevcnid + 1;
+ while (addcnid <= cnid) {
+ if (w->nconns > max) {
+ device_printf(sc->dev,
+ "%s: nid=%d: Adding %d: "
+ "Max connection reached! max=%d\n",
+ __func__, nid, addcnid, max + 1);
+ goto getconns_out;
+ }
+ w->conns[w->nconns++] = addcnid++;
+ }
+ prevcnid = cnid;
+ }
+ }
+
+getconns_out:
+ HDA_BOOTVERBOSE(
+ device_printf(sc->dev,
+ "HDA_DEBUG: %s: nid=%d entries=%d found=%d\n",
+ __func__, nid, ents, w->nconns);
+ );
+ return;
}
static uint32_t
hdac_widget_pin_getconfig(struct hdac_widget *w)
{
-struct hdac_softc *sc;
-uint32_t config, id;
-nid_t cad, nid;
-
-sc = w->devinfo->codec->sc;
-cad = w->devinfo->codec->cad;
-nid = w->nid;
-id = hdac_codec_id(w->devinfo);
-
-config = hdac_command(sc,
-HDA_CMD_GET_CONFIGURATION_DEFAULT(cad, nid),
-cad);
-/*
-* XXX REWRITE!!!! Don't argue!
-*/
-if (id == HDA_CODEC_ALC880 &&
-(sc->pci_subvendor == CLEVO_D900T_SUBVENDOR ||
-sc->pci_subvendor == ASUS_M5200_SUBVENDOR)) {
-/*
-* Super broken BIOS
-*/
-switch (nid) {
-case 20:
-break;
-case 21:
-break;
-case 22:
-break;
-case 23:
-break;
-case 24: /* MIC1 */
-config &= ~HDA_CONFIG_DEFAULTCONF_DEVICE_MASK;
-config |= HDA_CONFIG_DEFAULTCONF_DEVICE_MIC_IN;
-break;
-case 25: /* XXX MIC2 */
-config &= ~HDA_CONFIG_DEFAULTCONF_DEVICE_MASK;
-config |= HDA_CONFIG_DEFAULTCONF_DEVICE_MIC_IN;
-break;
-case 26: /* LINE1 */
-config &= ~HDA_CONFIG_DEFAULTCONF_DEVICE_MASK;
-config |= HDA_CONFIG_DEFAULTCONF_DEVICE_LINE_IN;
-break;
-case 27: /* XXX LINE2 */
-config &= ~HDA_CONFIG_DEFAULTCONF_DEVICE_MASK;
-config |= HDA_CONFIG_DEFAULTCONF_DEVICE_LINE_IN;
-break;
-case 28: /* CD */
-config &= ~HDA_CONFIG_DEFAULTCONF_DEVICE_MASK;
-config |= HDA_CONFIG_DEFAULTCONF_DEVICE_CD;
-break;
-case 30:
-break;
-case 31:
-break;
-default:
-break;
-}
+ struct hdac_softc *sc;
+ uint32_t config, orig, id;
+ nid_t cad, nid;
+
+ sc = w->devinfo->codec->sc;
+ cad = w->devinfo->codec->cad;
+ nid = w->nid;
+ id = hdac_codec_id(w->devinfo);
+
+ config = hdac_command(sc,
+ HDA_CMD_GET_CONFIGURATION_DEFAULT(cad, nid),
+ cad);
+ orig = config;
+
+ /*
+ * XXX REWRITE!!!! Don't argue!
+ */
+ if (id == HDA_CODEC_ALC880 && sc->pci_subvendor == LG_LW20_SUBVENDOR) {
+ switch (nid) {
+ case 26:
+ config &= ~HDA_CONFIG_DEFAULTCONF_DEVICE_MASK;
+ config |= HDA_CONFIG_DEFAULTCONF_DEVICE_LINE_IN;
+ break;
+ case 27:
+ config &= ~HDA_CONFIG_DEFAULTCONF_DEVICE_MASK;
+ config |= HDA_CONFIG_DEFAULTCONF_DEVICE_HP_OUT;
+ break;
+ default:
+ break;
+ }
+ } else if (id == HDA_CODEC_ALC880 &&
+ (sc->pci_subvendor == CLEVO_D900T_SUBVENDOR ||
+ sc->pci_subvendor == ASUS_M5200_SUBVENDOR)) {
+ /*
+ * Super broken BIOS
+ */
+ switch (nid) {
+ case 20:
+ break;
+ case 21:
+ break;
+ case 22:
+ break;
+ case 23:
+ break;
+ case 24: /* MIC1 */
+ config &= ~HDA_CONFIG_DEFAULTCONF_DEVICE_MASK;
+ config |= HDA_CONFIG_DEFAULTCONF_DEVICE_MIC_IN;
+ break;
+ case 25: /* XXX MIC2 */
+ config &= ~HDA_CONFIG_DEFAULTCONF_DEVICE_MASK;
+ config |= HDA_CONFIG_DEFAULTCONF_DEVICE_MIC_IN;
+ break;
+ case 26: /* LINE1 */
+ config &= ~HDA_CONFIG_DEFAULTCONF_DEVICE_MASK;
+ config |= HDA_CONFIG_DEFAULTCONF_DEVICE_LINE_IN;
+ break;
+ case 27: /* XXX LINE2 */
+ config &= ~HDA_CONFIG_DEFAULTCONF_DEVICE_MASK;
+ config |= HDA_CONFIG_DEFAULTCONF_DEVICE_LINE_IN;
+ break;
+ case 28: /* CD */
+ config &= ~HDA_CONFIG_DEFAULTCONF_DEVICE_MASK;
+ config |= HDA_CONFIG_DEFAULTCONF_DEVICE_CD;
+ break;
+ case 30:
+ break;
+ case 31:
+ break;
+ default:
+ break;
+ }
+ } else if (id == HDA_CODEC_ALC883 &&
+ (sc->pci_subvendor == MSI_MS034A_SUBVENDOR ||
+ HDA_DEV_MATCH(ACER_ALL_SUBVENDOR, sc->pci_subvendor))) {
+ switch (nid) {
+ case 25:
+ config &= ~(HDA_CONFIG_DEFAULTCONF_DEVICE_MASK |
+ HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK);
+ config |= (HDA_CONFIG_DEFAULTCONF_DEVICE_MIC_IN |
+ HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_FIXED);
+ break;
+ case 28:
+ config &= ~(HDA_CONFIG_DEFAULTCONF_DEVICE_MASK |
+ HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK);
+ config |= (HDA_CONFIG_DEFAULTCONF_DEVICE_CD |
+ HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_FIXED);
+ break;
+ default:
+ break;
+ }
+ } else if (id == HDA_CODEC_CXVENICE && sc->pci_subvendor ==
+ HP_V3000_SUBVENDOR) {
+ switch (nid) {
+ case 18:
+ config &= ~HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK;
+ config |= HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_NONE;
+ break;
+ case 20:
+ config &= ~(HDA_CONFIG_DEFAULTCONF_DEVICE_MASK |
+ HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK);
+ config |= (HDA_CONFIG_DEFAULTCONF_DEVICE_MIC_IN |
+ HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_FIXED);
+ break;
+ case 21:
+ config &= ~(HDA_CONFIG_DEFAULTCONF_DEVICE_MASK |
+ HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK);
+ config |= (HDA_CONFIG_DEFAULTCONF_DEVICE_CD |
+ HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_FIXED);
+ break;
+ default:
+ break;
+ }
+ } else if (id == HDA_CODEC_CXWAIKIKI && sc->pci_subvendor ==
+ HP_DV5000_SUBVENDOR) {
+ switch (nid) {
+ case 20:
+ case 21:
+ config &= ~HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK;
+ config |= HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_NONE;
+ break;
+ default:
+ break;
+ }
+ } else if (id == HDA_CODEC_ALC861 && sc->pci_subvendor ==
+ ASUS_W6F_SUBVENDOR) {
+ switch (nid) {
+ case 11:
+ config &= ~(HDA_CONFIG_DEFAULTCONF_DEVICE_MASK |
+ HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK);
+ config |= (HDA_CONFIG_DEFAULTCONF_DEVICE_LINE_OUT |
+ HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_FIXED);
+ break;
+ case 15:
+ config &= ~(HDA_CONFIG_DEFAULTCONF_DEVICE_MASK |
+ HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK);
+ config |= (HDA_CONFIG_DEFAULTCONF_DEVICE_HP_OUT |
+ HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_JACK);
+ break;
+ default:
+ break;
+ }
+ } else if (id == HDA_CODEC_ALC861 && sc->pci_subvendor ==
+ UNIWILL_9075_SUBVENDOR) {
+ switch (nid) {
+ case 15:
+ config &= ~(HDA_CONFIG_DEFAULTCONF_DEVICE_MASK |
+ HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK);
+ config |= (HDA_CONFIG_DEFAULTCONF_DEVICE_HP_OUT |
+ HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_JACK);
+ break;
+ default:
+ break;
+ }
+ } else if (id == HDA_CODEC_AD1986A &&
+ (sc->pci_subvendor == ASUS_M2NPVMX_SUBVENDOR ||
+ sc->pci_subvendor == ASUS_A8NVMCSM_SUBVENDOR)) {
+ switch (nid) {
+ case 28: /* LINE */
+ config &= ~HDA_CONFIG_DEFAULTCONF_DEVICE_MASK;
+ config |= HDA_CONFIG_DEFAULTCONF_DEVICE_LINE_IN;
+ break;
+ case 29: /* MIC */
+ config &= ~HDA_CONFIG_DEFAULTCONF_DEVICE_MASK;
+ config |= HDA_CONFIG_DEFAULTCONF_DEVICE_MIC_IN;
+ break;
+ default:
+ break;
+ }
+ } else if (id == HDA_CODEC_ALC268 &&
+ HDA_DEV_MATCH(ACER_ALL_SUBVENDOR, sc->pci_subvendor)) {
+ switch (nid) {
+ case 28:
+ config &= ~(HDA_CONFIG_DEFAULTCONF_DEVICE_MASK |
+ HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK);
+ config |= (HDA_CONFIG_DEFAULTCONF_DEVICE_CD |
+ HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_FIXED);
+ break;
+ default:
+ break;
+ }
+ }
+
+ HDA_BOOTVERBOSE(
+ if (config != orig)
+ device_printf(sc->dev,
+ "HDA_DEBUG: Pin config nid=%u 0x%08x -> 0x%08x\n",
+ nid, orig, config);
+ );
+
+ return (config);
}
-return (config);
+static uint32_t
+hdac_widget_pin_getcaps(struct hdac_widget *w)
+{
+ struct hdac_softc *sc;
+ uint32_t caps, orig, id;
+ nid_t cad, nid;
+
+ sc = w->devinfo->codec->sc;
+ cad = w->devinfo->codec->cad;
+ nid = w->nid;
+ id = hdac_codec_id(w->devinfo);
+
+ caps = hdac_command(sc,
+ HDA_CMD_GET_PARAMETER(cad, nid, HDA_PARAM_PIN_CAP), cad);
+ orig = caps;
+
+ HDA_BOOTVERBOSE(
+ if (caps != orig)
+ device_printf(sc->dev,
+ "HDA_DEBUG: Pin caps nid=%u 0x%08x -> 0x%08x\n",
+ nid, orig, caps);
+ );
+
+ return (caps);
}
static void
hdac_widget_pin_parse(struct hdac_widget *w)
{
-struct hdac_softc *sc = w->devinfo->codec->sc;
-uint32_t config, pincap;
-char *devstr, *connstr;
-nid_t cad = w->devinfo->codec->cad;
-nid_t nid = w->nid;
-
-config = hdac_widget_pin_getconfig(w);
-w->wclass.pin.config = config;
-
-pincap = hdac_command(sc,
-HDA_CMD_GET_PARAMETER(cad, nid, HDA_PARAM_PIN_CAP), cad);
-w->wclass.pin.cap = pincap;
-
-w->wclass.pin.ctrl = hdac_command(sc,
-HDA_CMD_GET_PIN_WIDGET_CTRL(cad, nid), cad) &
-~(HDA_CMD_SET_PIN_WIDGET_CTRL_HPHN_ENABLE |
-HDA_CMD_SET_PIN_WIDGET_CTRL_OUT_ENABLE |
-HDA_CMD_SET_PIN_WIDGET_CTRL_IN_ENABLE);
-
-if (HDA_PARAM_PIN_CAP_HEADPHONE_CAP(pincap))
-w->wclass.pin.ctrl |= HDA_CMD_SET_PIN_WIDGET_CTRL_HPHN_ENABLE;
-if (HDA_PARAM_PIN_CAP_OUTPUT_CAP(pincap))
-w->wclass.pin.ctrl |= HDA_CMD_SET_PIN_WIDGET_CTRL_OUT_ENABLE;
-if (HDA_PARAM_PIN_CAP_INPUT_CAP(pincap))
-w->wclass.pin.ctrl |= HDA_CMD_SET_PIN_WIDGET_CTRL_IN_ENABLE;
-if (HDA_PARAM_PIN_CAP_EAPD_CAP(pincap)) {
-w->param.eapdbtl = hdac_command(sc,
-HDA_CMD_GET_EAPD_BTL_ENABLE(cad, nid), cad);
-w->param.eapdbtl &= 0x7;
-w->param.eapdbtl |= HDA_CMD_SET_EAPD_BTL_ENABLE_EAPD;
-} else
-w->param.eapdbtl = HDAC_INVALID;
-
-switch (config & HDA_CONFIG_DEFAULTCONF_DEVICE_MASK) {
-case HDA_CONFIG_DEFAULTCONF_DEVICE_LINE_OUT:
-devstr = "line out";
-break;
-case HDA_CONFIG_DEFAULTCONF_DEVICE_SPEAKER:
-devstr = "speaker";
-break;
-case HDA_CONFIG_DEFAULTCONF_DEVICE_HP_OUT:
-devstr = "headphones out";
-break;
-case HDA_CONFIG_DEFAULTCONF_DEVICE_CD:
-devstr = "CD";
-break;
-case HDA_CONFIG_DEFAULTCONF_DEVICE_SPDIF_OUT:
-devstr = "SPDIF out";
-break;
-case HDA_CONFIG_DEFAULTCONF_DEVICE_DIGITAL_OTHER_OUT:
-devstr = "digital (other) out";
-break;
-case HDA_CONFIG_DEFAULTCONF_DEVICE_MODEM_LINE:
-devstr = "modem, line side";
-break;
-case HDA_CONFIG_DEFAULTCONF_DEVICE_MODEM_HANDSET:
-devstr = "modem, handset side";
-break;
-case HDA_CONFIG_DEFAULTCONF_DEVICE_LINE_IN:
-devstr = "line in";
-break;
-case HDA_CONFIG_DEFAULTCONF_DEVICE_AUX:
-devstr = "AUX";
-break;
-case HDA_CONFIG_DEFAULTCONF_DEVICE_MIC_IN:
-devstr = "Mic in";
-break;
-case HDA_CONFIG_DEFAULTCONF_DEVICE_TELEPHONY:
-devstr = "telephony";
-break;
-case HDA_CONFIG_DEFAULTCONF_DEVICE_SPDIF_IN:
-devstr = "SPDIF in";
-break;
-case HDA_CONFIG_DEFAULTCONF_DEVICE_DIGITAL_OTHER_IN:
-devstr = "digital (other) in";
-break;
-case HDA_CONFIG_DEFAULTCONF_DEVICE_OTHER:
-devstr = "other";
-break;
-default:
-devstr = "unknown";
-break;
-}
-
-switch (config & HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK) {
-case HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_JACK:
-connstr = "jack";
-break;
-case HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_NONE:
-connstr = "none";
-break;
-case HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_FIXED:
-connstr = "fixed";
-break;
-case HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_BOTH:
-connstr = "jack / fixed";
-break;
-default:
-connstr = "unknown";
-break;
-}
-
-strlcat(w->name, ": ", sizeof(w->name));
-strlcat(w->name, devstr, sizeof(w->name));
-strlcat(w->name, " (", sizeof(w->name));
-strlcat(w->name, connstr, sizeof(w->name));
-strlcat(w->name, ")", sizeof(w->name));
+ struct hdac_softc *sc = w->devinfo->codec->sc;
+ uint32_t config, pincap;
+ char *devstr, *connstr;
+ nid_t cad = w->devinfo->codec->cad;
+ nid_t nid = w->nid;
+
+ config = hdac_widget_pin_getconfig(w);
+ w->wclass.pin.config = config;
+
+ pincap = hdac_widget_pin_getcaps(w);
+ w->wclass.pin.cap = pincap;
+
+ w->wclass.pin.ctrl = hdac_command(sc,
+ HDA_CMD_GET_PIN_WIDGET_CTRL(cad, nid), cad) &
+ ~(HDA_CMD_SET_PIN_WIDGET_CTRL_HPHN_ENABLE |
+ HDA_CMD_SET_PIN_WIDGET_CTRL_OUT_ENABLE |
+ HDA_CMD_SET_PIN_WIDGET_CTRL_IN_ENABLE |
+ HDA_CMD_SET_PIN_WIDGET_CTRL_VREF_ENABLE_MASK);
+
+ if (HDA_PARAM_PIN_CAP_HEADPHONE_CAP(pincap))
+ w->wclass.pin.ctrl |= HDA_CMD_SET_PIN_WIDGET_CTRL_HPHN_ENABLE;
+ if (HDA_PARAM_PIN_CAP_OUTPUT_CAP(pincap))
+ w->wclass.pin.ctrl |= HDA_CMD_SET_PIN_WIDGET_CTRL_OUT_ENABLE;
+ if (HDA_PARAM_PIN_CAP_INPUT_CAP(pincap))
+ w->wclass.pin.ctrl |= HDA_CMD_SET_PIN_WIDGET_CTRL_IN_ENABLE;
+ if (HDA_PARAM_PIN_CAP_EAPD_CAP(pincap)) {
+ w->param.eapdbtl = hdac_command(sc,
+ HDA_CMD_GET_EAPD_BTL_ENABLE(cad, nid), cad);
+ w->param.eapdbtl &= 0x7;
+ w->param.eapdbtl |= HDA_CMD_SET_EAPD_BTL_ENABLE_EAPD;
+ } else
+ w->param.eapdbtl = HDAC_INVALID;
+
+ switch (config & HDA_CONFIG_DEFAULTCONF_DEVICE_MASK) {
+ case HDA_CONFIG_DEFAULTCONF_DEVICE_LINE_OUT:
+ devstr = "line out";
+ break;
+ case HDA_CONFIG_DEFAULTCONF_DEVICE_SPEAKER:
+ devstr = "speaker";
+ break;
+ case HDA_CONFIG_DEFAULTCONF_DEVICE_HP_OUT:
+ devstr = "headphones out";
+ break;
+ case HDA_CONFIG_DEFAULTCONF_DEVICE_CD:
+ devstr = "CD";
+ break;
+ case HDA_CONFIG_DEFAULTCONF_DEVICE_SPDIF_OUT:
+ devstr = "SPDIF out";
+ break;
+ case HDA_CONFIG_DEFAULTCONF_DEVICE_DIGITAL_OTHER_OUT:
+ devstr = "digital (other) out";
+ break;
+ case HDA_CONFIG_DEFAULTCONF_DEVICE_MODEM_LINE:
+ devstr = "modem, line side";
+ break;
+ case HDA_CONFIG_DEFAULTCONF_DEVICE_MODEM_HANDSET:
+ devstr = "modem, handset side";
+ break;
+ case HDA_CONFIG_DEFAULTCONF_DEVICE_LINE_IN:
+ devstr = "line in";
+ break;
+ case HDA_CONFIG_DEFAULTCONF_DEVICE_AUX:
+ devstr = "AUX";
+ break;
+ case HDA_CONFIG_DEFAULTCONF_DEVICE_MIC_IN:
+ devstr = "Mic in";
+ break;
+ case HDA_CONFIG_DEFAULTCONF_DEVICE_TELEPHONY:
+ devstr = "telephony";
+ break;
+ case HDA_CONFIG_DEFAULTCONF_DEVICE_SPDIF_IN:
+ devstr = "SPDIF in";
+ break;
+ case HDA_CONFIG_DEFAULTCONF_DEVICE_DIGITAL_OTHER_IN:
+ devstr = "digital (other) in";
+ break;
+ case HDA_CONFIG_DEFAULTCONF_DEVICE_OTHER:
+ devstr = "other";
+ break;
+ default:
+ devstr = "unknown";
+ break;
+ }
+
+ switch (config & HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK) {
+ case HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_JACK:
+ connstr = "jack";
+ break;
+ case HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_NONE:
+ connstr = "none";
+ break;
+ case HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_FIXED:
+ connstr = "fixed";
+ break;
+ case HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_BOTH:
+ connstr = "jack / fixed";
+ break;
+ default:
+ connstr = "unknown";
+ break;
+ }
+
+ strlcat(w->name, ": ", sizeof(w->name));
+ strlcat(w->name, devstr, sizeof(w->name));
+ strlcat(w->name, " (", sizeof(w->name));
+ strlcat(w->name, connstr, sizeof(w->name));
+ strlcat(w->name, ")", sizeof(w->name));
}
static void
hdac_widget_parse(struct hdac_widget *w)
{
-struct hdac_softc *sc = w->devinfo->codec->sc;
-uint32_t wcap, cap;
-char *typestr;
-nid_t cad = w->devinfo->codec->cad;
-nid_t nid = w->nid;
-
-wcap = hdac_command(sc,
-HDA_CMD_GET_PARAMETER(cad, nid, HDA_PARAM_AUDIO_WIDGET_CAP),
-cad);
-w->param.widget_cap = wcap;
-w->type = HDA_PARAM_AUDIO_WIDGET_CAP_TYPE(wcap);
-
-switch (w->type) {
-case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_OUTPUT:
-typestr = "audio output";
-break;
-case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_INPUT:
-typestr = "audio input";
-break;
-case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_MIXER:
-typestr = "audio mixer";
-break;
-case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_SELECTOR:
-typestr = "audio selector";
-break;
-case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX:
-typestr = "pin";
-break;
-case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_POWER_WIDGET:
-typestr = "power widget";
-break;
-case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_VOLUME_WIDGET:
-typestr = "volume widget";
-break;
-case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_BEEP_WIDGET:
-typestr = "beep widget";
-break;
-case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_VENDOR_WIDGET:
-typestr = "vendor widget";
-break;
-default:
-typestr = "unknown type";
-break;
-}
-
-strlcpy(w->name, typestr, sizeof(w->name));
-
-if (HDA_PARAM_AUDIO_WIDGET_CAP_POWER_CTRL(wcap)) {
-hdac_command(sc,
-HDA_CMD_SET_POWER_STATE(cad, nid, HDA_CMD_POWER_STATE_D0),
-cad);
-DELAY(1000);
-}
-
-hdac_widget_connection_parse(w);
-
-if (HDA_PARAM_AUDIO_WIDGET_CAP_OUT_AMP(wcap)) {
-if (HDA_PARAM_AUDIO_WIDGET_CAP_AMP_OVR(wcap))
-w->param.outamp_cap =
-hdac_command(sc,
-HDA_CMD_GET_PARAMETER(cad, nid,
-HDA_PARAM_OUTPUT_AMP_CAP), cad);
-else
-w->param.outamp_cap =
-w->devinfo->function.audio.outamp_cap;
-} else
-w->param.outamp_cap = 0;
-
-if (HDA_PARAM_AUDIO_WIDGET_CAP_IN_AMP(wcap)) {
-if (HDA_PARAM_AUDIO_WIDGET_CAP_AMP_OVR(wcap))
-w->param.inamp_cap =
-hdac_command(sc,
-HDA_CMD_GET_PARAMETER(cad, nid,
-HDA_PARAM_INPUT_AMP_CAP), cad);
-else
-w->param.inamp_cap =
-w->devinfo->function.audio.inamp_cap;
-} else
-w->param.inamp_cap = 0;
-
-if (w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_OUTPUT ||
-w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_INPUT) {
-if (HDA_PARAM_AUDIO_WIDGET_CAP_FORMAT_OVR(wcap)) {
-cap = hdac_command(sc,
-HDA_CMD_GET_PARAMETER(cad, nid,
-HDA_PARAM_SUPP_STREAM_FORMATS), cad);
-w->param.supp_stream_formats = (cap != 0) ? cap :
-w->devinfo->function.audio.supp_stream_formats;
-cap = hdac_command(sc,
-HDA_CMD_GET_PARAMETER(cad, nid,
-HDA_PARAM_SUPP_PCM_SIZE_RATE), cad);
-w->param.supp_pcm_size_rate = (cap != 0) ? cap :
-w->devinfo->function.audio.supp_pcm_size_rate;
-} else {
-w->param.supp_stream_formats =
-w->devinfo->function.audio.supp_stream_formats;
-w->param.supp_pcm_size_rate =
-w->devinfo->function.audio.supp_pcm_size_rate;
-}
-} else {
-w->param.supp_stream_formats = 0;
-w->param.supp_pcm_size_rate = 0;
-}
+ struct hdac_softc *sc = w->devinfo->codec->sc;
+ uint32_t wcap, cap;
+ char *typestr;
+ nid_t cad = w->devinfo->codec->cad;
+ nid_t nid = w->nid;
+
+ wcap = hdac_command(sc,
+ HDA_CMD_GET_PARAMETER(cad, nid, HDA_PARAM_AUDIO_WIDGET_CAP),
+ cad);
+ w->param.widget_cap = wcap;
+ w->type = HDA_PARAM_AUDIO_WIDGET_CAP_TYPE(wcap);
+
+ switch (w->type) {
+ case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_OUTPUT:
+ typestr = "audio output";
+ break;
+ case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_INPUT:
+ typestr = "audio input";
+ break;
+ case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_MIXER:
+ typestr = "audio mixer";
+ break;
+ case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_SELECTOR:
+ typestr = "audio selector";
+ break;
+ case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX:
+ typestr = "pin";
+ break;
+ case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_POWER_WIDGET:
+ typestr = "power widget";
+ break;
+ case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_VOLUME_WIDGET:
+ typestr = "volume widget";
+ break;
+ case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_BEEP_WIDGET:
+ typestr = "beep widget";
+ break;
+ case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_VENDOR_WIDGET:
+ typestr = "vendor widget";
+ break;
+ default:
+ typestr = "unknown type";
+ break;
+ }
+
+ strlcpy(w->name, typestr, sizeof(w->name));
+
+ if (HDA_PARAM_AUDIO_WIDGET_CAP_POWER_CTRL(wcap)) {
+ hdac_command(sc,
+ HDA_CMD_SET_POWER_STATE(cad, nid, HDA_CMD_POWER_STATE_D0),
+ cad);
+ DELAY(1000);
+ }
+
+ hdac_widget_connection_parse(w);
+
+ if (HDA_PARAM_AUDIO_WIDGET_CAP_OUT_AMP(wcap)) {
+ if (HDA_PARAM_AUDIO_WIDGET_CAP_AMP_OVR(wcap))
+ w->param.outamp_cap =
+ hdac_command(sc,
+ HDA_CMD_GET_PARAMETER(cad, nid,
+ HDA_PARAM_OUTPUT_AMP_CAP), cad);
+ else
+ w->param.outamp_cap =
+ w->devinfo->function.audio.outamp_cap;
+ } else
+ w->param.outamp_cap = 0;
+
+ if (HDA_PARAM_AUDIO_WIDGET_CAP_IN_AMP(wcap)) {
+ if (HDA_PARAM_AUDIO_WIDGET_CAP_AMP_OVR(wcap))
+ w->param.inamp_cap =
+ hdac_command(sc,
+ HDA_CMD_GET_PARAMETER(cad, nid,
+ HDA_PARAM_INPUT_AMP_CAP), cad);
+ else
+ w->param.inamp_cap =
+ w->devinfo->function.audio.inamp_cap;
+ } else
+ w->param.inamp_cap = 0;
+
+ if (w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_OUTPUT ||
+ w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_INPUT) {
+ if (HDA_PARAM_AUDIO_WIDGET_CAP_FORMAT_OVR(wcap)) {
+ cap = hdac_command(sc,
+ HDA_CMD_GET_PARAMETER(cad, nid,
+ HDA_PARAM_SUPP_STREAM_FORMATS), cad);
+ w->param.supp_stream_formats = (cap != 0) ? cap :
+ w->devinfo->function.audio.supp_stream_formats;
+ cap = hdac_command(sc,
+ HDA_CMD_GET_PARAMETER(cad, nid,
+ HDA_PARAM_SUPP_PCM_SIZE_RATE), cad);
+ w->param.supp_pcm_size_rate = (cap != 0) ? cap :
+ w->devinfo->function.audio.supp_pcm_size_rate;
+ } else {
+ w->param.supp_stream_formats =
+ w->devinfo->function.audio.supp_stream_formats;
+ w->param.supp_pcm_size_rate =
+ w->devinfo->function.audio.supp_pcm_size_rate;
+ }
+ } else {
+ w->param.supp_stream_formats = 0;
+ w->param.supp_pcm_size_rate = 0;
+ }
-if (w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX)
-hdac_widget_pin_parse(w);
+ if (w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX)
+ hdac_widget_pin_parse(w);
}
static struct hdac_widget *
hdac_widget_get(struct hdac_devinfo *devinfo, nid_t nid)
{
-if (devinfo == NULL || devinfo->widget == NULL ||
-nid < devinfo->startnode || nid >= devinfo->endnode)
-return (NULL);
-return (&devinfo->widget[nid - devinfo->startnode]);
+ if (devinfo == NULL || devinfo->widget == NULL ||
+ nid < devinfo->startnode || nid >= devinfo->endnode)
+ return (NULL);
+ return (&devinfo->widget[nid - devinfo->startnode]);
+}
+
+static __inline int
+hda_poll_channel(struct hdac_chan *ch)
+{
+ uint32_t sz, delta;
+ volatile uint32_t ptr;
+
+ if (!(ch->flags & HDAC_CHN_RUNNING))
+ return (0);
+
+ sz = ch->blksz * ch->blkcnt;
+ if (ch->dmapos != NULL)
+ ptr = *(ch->dmapos);
+ else
+ ptr = HDAC_READ_4(&ch->devinfo->codec->sc->mem,
+ ch->off + HDAC_SDLPIB);
+ ch->ptr = ptr;
+ ptr %= sz;
+ ptr &= ~(ch->blksz - 1);
+ delta = (sz + ptr - ch->prevptr) % sz;
+
+ if (delta < ch->blksz)
+ return (0);
+
+ ch->prevptr = ptr;
+
+ return (1);
+}
+
+#define hda_chan_active(sc) (((sc)->play.flags | (sc)->rec.flags) & \
+ HDAC_CHN_RUNNING)
+
+static void
+hda_poll_callback(void *arg)
+{
+ struct hdac_softc *sc = arg;
+ uint32_t trigger;
+
+ if (sc == NULL)
+ return;
+
+ hdac_lock(sc);
+ if (sc->polling == 0 || hda_chan_active(sc) == 0) {
+ hdac_unlock(sc);
+ return;
+ }
+
+ trigger = 0;
+ trigger |= (hda_poll_channel(&sc->play) != 0) ? HDAC_TRIGGER_PLAY : 0;
+ trigger |= (hda_poll_channel(&sc->rec)) != 0 ? HDAC_TRIGGER_REC : 0;
+
+ /* XXX */
+ callout_reset(&sc->poll_hda, 1/*sc->poll_ticks*/,
+ hda_poll_callback, sc);
+
+ hdac_unlock(sc);
+
+ if (trigger & HDAC_TRIGGER_PLAY)
+ chn_intr(sc->play.c);
+ if (trigger & HDAC_TRIGGER_REC)
+ chn_intr(sc->rec.c);
+}
+
+static int
+hdac_rirb_flush(struct hdac_softc *sc)
+{
+ struct hdac_rirb *rirb_base, *rirb;
+ struct hdac_codec *codec;
+ struct hdac_command_list *commands;
+ nid_t cad;
+ uint32_t resp;
+ uint8_t rirbwp;
+ int ret;
+
+ rirb_base = (struct hdac_rirb *)sc->rirb_dma.dma_vaddr;
+ rirbwp = HDAC_READ_1(&sc->mem, HDAC_RIRBWP);
+#if 0
+ bus_dmamap_sync(sc->rirb_dma.dma_tag, sc->rirb_dma.dma_map,
+ BUS_DMASYNC_POSTREAD);
+#endif
+
+ ret = 0;
+
+ while (sc->rirb_rp != rirbwp) {
+ sc->rirb_rp++;
+ sc->rirb_rp %= sc->rirb_size;
+ rirb = &rirb_base[sc->rirb_rp];
+ cad = HDAC_RIRB_RESPONSE_EX_SDATA_IN(rirb->response_ex);
+ if (cad < 0 || cad >= HDAC_CODEC_MAX ||
+ sc->codecs[cad] == NULL)
+ continue;
+ resp = rirb->response;
+ codec = sc->codecs[cad];
+ commands = codec->commands;
+ if (rirb->response_ex & HDAC_RIRB_RESPONSE_EX_UNSOLICITED) {
+ sc->unsolq[sc->unsolq_wp++] = (cad << 16) |
+ ((resp >> 26) & 0xffff);
+ sc->unsolq_wp %= HDAC_UNSOLQ_MAX;
+ } else if (commands != NULL && commands->num_commands > 0 &&
+ codec->responses_received < commands->num_commands)
+ commands->responses[codec->responses_received++] =
+ resp;
+ ret++;
+ }
+
+ return (ret);
+}
+
+static int
+hdac_unsolq_flush(struct hdac_softc *sc)
+{
+ nid_t cad;
+ uint32_t tag;
+ int ret = 0;
+
+ if (sc->unsolq_st == HDAC_UNSOLQ_READY) {
+ sc->unsolq_st = HDAC_UNSOLQ_BUSY;
+ while (sc->unsolq_rp != sc->unsolq_wp) {
+ cad = sc->unsolq[sc->unsolq_rp] >> 16;
+ tag = sc->unsolq[sc->unsolq_rp++] & 0xffff;
+ sc->unsolq_rp %= HDAC_UNSOLQ_MAX;
+ hdac_unsolicited_handler(sc->codecs[cad], tag);
+ ret++;
+ }
+ sc->unsolq_st = HDAC_UNSOLQ_READY;
+ }
+
+ return (ret);
+}
+
+static void
+hdac_poll_callback(void *arg)
+{
+ struct hdac_softc *sc = arg;
+ if (sc == NULL)
+ return;
+
+ hdac_lock(sc);
+ if (sc->polling == 0 || sc->poll_ival == 0) {
+ hdac_unlock(sc);
+ return;
+ }
+ if (hdac_rirb_flush(sc) != 0)
+ hdac_unsolq_flush(sc);
+ callout_reset(&sc->poll_hdac, sc->poll_ival, hdac_poll_callback, sc);
+ hdac_unlock(sc);
}
static void
hdac_stream_stop(struct hdac_chan *ch)
{
-struct hdac_softc *sc = ch->devinfo->codec->sc;
-uint32_t ctl;
+ struct hdac_softc *sc = ch->devinfo->codec->sc;
+ uint32_t ctl;
-ctl = HDAC_READ_1(&sc->mem, ch->off + HDAC_SDCTL0);
-ctl &= ~(HDAC_SDCTL_IOCE | HDAC_SDCTL_FEIE | HDAC_SDCTL_DEIE |
-HDAC_SDCTL_RUN);
-HDAC_WRITE_1(&sc->mem, ch->off + HDAC_SDCTL0, ctl);
-
-ctl = HDAC_READ_4(&sc->mem, HDAC_INTCTL);
-ctl &= ~(1 << (ch->off >> 5));
-HDAC_WRITE_4(&sc->mem, HDAC_INTCTL, ctl);
+ ctl = HDAC_READ_1(&sc->mem, ch->off + HDAC_SDCTL0);
+ ctl &= ~(HDAC_SDCTL_IOCE | HDAC_SDCTL_FEIE | HDAC_SDCTL_DEIE |
+ HDAC_SDCTL_RUN);
+ HDAC_WRITE_1(&sc->mem, ch->off + HDAC_SDCTL0, ctl);
+
+ ch->flags &= ~HDAC_CHN_RUNNING;
+
+ if (sc->polling != 0) {
+ int pollticks;
+
+ if (hda_chan_active(sc) == 0) {
+ callout_stop(&sc->poll_hda);
+ sc->poll_ticks = 1;
+ } else {
+ if (sc->play.flags & HDAC_CHN_RUNNING)
+ ch = &sc->play;
+ else
+ ch = &sc->rec;
+ pollticks = ((uint64_t)hz * ch->blksz) /
+ ((uint64_t)sndbuf_getbps(ch->b) *
+ sndbuf_getspd(ch->b));
+ pollticks >>= 2;
+ if (pollticks > hz)
+ pollticks = hz;
+ if (pollticks < 1) {
+ HDA_BOOTVERBOSE(
+ device_printf(sc->dev,
+ "%s: pollticks=%d < 1 !\n",
+ __func__, pollticks);
+ );
+ pollticks = 1;
+ }
+ if (pollticks > sc->poll_ticks) {
+ HDA_BOOTVERBOSE(
+ device_printf(sc->dev,
+ "%s: pollticks %d -> %d\n",
+ __func__, sc->poll_ticks,
+ pollticks);
+ );
+ sc->poll_ticks = pollticks;
+ callout_reset(&sc->poll_hda, 1,
+ hda_poll_callback, sc);
+ }
+ }
+ } else {
+ ctl = HDAC_READ_4(&sc->mem, HDAC_INTCTL);
+ ctl &= ~(1 << (ch->off >> 5));
+ HDAC_WRITE_4(&sc->mem, HDAC_INTCTL, ctl);
+ }
}
static void
hdac_stream_start(struct hdac_chan *ch)
{
-struct hdac_softc *sc = ch->devinfo->codec->sc;
-uint32_t ctl;
+ struct hdac_softc *sc = ch->devinfo->codec->sc;
+ uint32_t ctl;
+
+ if (sc->polling != 0) {
+ int pollticks;
+
+ pollticks = ((uint64_t)hz * ch->blksz) /
+ ((uint64_t)sndbuf_getbps(ch->b) * sndbuf_getspd(ch->b));
+ pollticks >>= 2;
+ if (pollticks > hz)
+ pollticks = hz;
+ if (pollticks < 1) {
+ HDA_BOOTVERBOSE(
+ device_printf(sc->dev,
+ "%s: pollticks=%d < 1 !\n",
+ __func__, pollticks);
+ );
+ pollticks = 1;
+ }
+ if (hda_chan_active(sc) == 0 || pollticks < sc->poll_ticks) {
+ HDA_BOOTVERBOSE(
+ if (hda_chan_active(sc) == 0) {
+ device_printf(sc->dev,
+ "%s: pollticks=%d\n",
+ __func__, pollticks);
+ } else {
+ device_printf(sc->dev,
+ "%s: pollticks %d -> %d\n",
+ __func__, sc->poll_ticks,
+ pollticks);
+ }
+ );
+ sc->poll_ticks = pollticks;
+ callout_reset(&sc->poll_hda, 1, hda_poll_callback,
+ sc);
+ }
+ ctl = HDAC_READ_1(&sc->mem, ch->off + HDAC_SDCTL0);
+ ctl |= HDAC_SDCTL_RUN;
+ } else {
+ ctl = HDAC_READ_4(&sc->mem, HDAC_INTCTL);
+ ctl |= 1 << (ch->off >> 5);
+ HDAC_WRITE_4(&sc->mem, HDAC_INTCTL, ctl);
+ ctl = HDAC_READ_1(&sc->mem, ch->off + HDAC_SDCTL0);
+ ctl |= HDAC_SDCTL_IOCE | HDAC_SDCTL_FEIE | HDAC_SDCTL_DEIE |
+ HDAC_SDCTL_RUN;
+ }
+ HDAC_WRITE_1(&sc->mem, ch->off + HDAC_SDCTL0, ctl);
-ctl = HDAC_READ_4(&sc->mem, HDAC_INTCTL);
-ctl |= 1 << (ch->off >> 5);
-HDAC_WRITE_4(&sc->mem, HDAC_INTCTL, ctl);
-
-ctl = HDAC_READ_1(&sc->mem, ch->off + HDAC_SDCTL0);
-ctl |= HDAC_SDCTL_IOCE | HDAC_SDCTL_FEIE | HDAC_SDCTL_DEIE |
-HDAC_SDCTL_RUN;
-HDAC_WRITE_1(&sc->mem, ch->off + HDAC_SDCTL0, ctl);
+ ch->flags |= HDAC_CHN_RUNNING;
}
static void
hdac_stream_reset(struct hdac_chan *ch)
{
-struct hdac_softc *sc = ch->devinfo->codec->sc;
-int timeout = 1000;
-int to = timeout;
-uint32_t ctl;
-
-ctl = HDAC_READ_1(&sc->mem, ch->off + HDAC_SDCTL0);
-ctl |= HDAC_SDCTL_SRST;
-HDAC_WRITE_1(&sc->mem, ch->off + HDAC_SDCTL0, ctl);
-do {
-ctl = HDAC_READ_1(&sc->mem, ch->off + HDAC_SDCTL0);
-if (ctl & HDAC_SDCTL_SRST)
-break;
-DELAY(10);
-} while (--to);
-if (!(ctl & HDAC_SDCTL_SRST)) {
-device_printf(sc->dev, "timeout in resetn");
-}
-ctl &= ~HDAC_SDCTL_SRST;
-HDAC_WRITE_1(&sc->mem, ch->off + HDAC_SDCTL0, ctl);
-to = timeout;
-do {
-ctl = HDAC_READ_1(&sc->mem, ch->off + HDAC_SDCTL0);
-if (!(ctl & HDAC_SDCTL_SRST))
-break;
-DELAY(10);
-} while (--to);
-if (ctl & HDAC_SDCTL_SRST)
-device_printf(sc->dev, "can't reset!n");
+ struct hdac_softc *sc = ch->devinfo->codec->sc;
+ int timeout = 1000;
+ int to = timeout;
+ uint32_t ctl;
+
+ ctl = HDAC_READ_1(&sc->mem, ch->off + HDAC_SDCTL0);
+ ctl |= HDAC_SDCTL_SRST;
+ HDAC_WRITE_1(&sc->mem, ch->off + HDAC_SDCTL0, ctl);
+ do {
+ ctl = HDAC_READ_1(&sc->mem, ch->off + HDAC_SDCTL0);
+ if (ctl & HDAC_SDCTL_SRST)
+ break;
+ DELAY(10);
+ } while (--to);
+ if (!(ctl & HDAC_SDCTL_SRST)) {
+ device_printf(sc->dev, "timeout in reset\n");
+ }
+ ctl &= ~HDAC_SDCTL_SRST;
+ HDAC_WRITE_1(&sc->mem, ch->off + HDAC_SDCTL0, ctl);
+ to = timeout;
+ do {
+ ctl = HDAC_READ_1(&sc->mem, ch->off + HDAC_SDCTL0);
+ if (!(ctl & HDAC_SDCTL_SRST))
+ break;
+ DELAY(10);
+ } while (--to);
+ if (ctl & HDAC_SDCTL_SRST)
+ device_printf(sc->dev, "can't reset!\n");
}
static void
hdac_stream_setid(struct hdac_chan *ch)
{
-struct hdac_softc *sc = ch->devinfo->codec->sc;
-uint32_t ctl;
+ struct hdac_softc *sc = ch->devinfo->codec->sc;
+ uint32_t ctl;
-ctl = HDAC_READ_1(&sc->mem, ch->off + HDAC_SDCTL2);
-ctl &= ~HDAC_SDCTL2_STRM_MASK;
-ctl |= ch->sid << HDAC_SDCTL2_STRM_SHIFT;
-HDAC_WRITE_1(&sc->mem, ch->off + HDAC_SDCTL2, ctl);
+ ctl = HDAC_READ_1(&sc->mem, ch->off + HDAC_SDCTL2);
+ ctl &= ~HDAC_SDCTL2_STRM_MASK;
+ ctl |= ch->sid << HDAC_SDCTL2_STRM_SHIFT;
+ HDAC_WRITE_1(&sc->mem, ch->off + HDAC_SDCTL2, ctl);
}
static void
hdac_bdl_setup(struct hdac_chan *ch)
{
-struct hdac_softc *sc = ch->devinfo->codec->sc;
-uint64_t addr;
-int blks, size, blocksize;
-struct hdac_bdle *bdle;
-int i;
-
-addr = (uint64_t)sndbuf_getbufaddr(ch->b);
-size = sndbuf_getsize(ch->b);
-blocksize = sndbuf_getblksz(ch->b);
-blks = size / blocksize;
-bdle = (struct hdac_bdle*)ch->bdl_dma.dma_vaddr;
-
-for (i = 0; i < blks; i++, bdle++) {
-bdle->addrl = (uint32_t)addr;
-bdle->addrh = (uint32_t)(addr >> 32);
-bdle->len = blocksize;
-bdle->ioc = 1;
-
-addr += blocksize;
-}
-
-HDAC_WRITE_4(&sc->mem, ch->off + HDAC_SDCBL, size);
-HDAC_WRITE_2(&sc->mem, ch->off + HDAC_SDLVI, blks - 1);
-addr = ch->bdl_dma.dma_paddr;
-HDAC_WRITE_4(&sc->mem, ch->off + HDAC_SDBDPL, (uint32_t)addr);
-HDAC_WRITE_4(&sc->mem, ch->off + HDAC_SDBDPU, (uint32_t)(addr >> 32));
+ struct hdac_softc *sc = ch->devinfo->codec->sc;
+ struct hdac_bdle *bdle;
+ uint64_t addr;
+ uint32_t blksz, blkcnt;
+ int i;
+
+ addr = (uint64_t)sndbuf_getbufaddr(ch->b);
+ bdle = (struct hdac_bdle *)ch->bdl_dma.dma_vaddr;
+
+ if (sc->polling != 0) {
+ blksz = ch->blksz * ch->blkcnt;
+ blkcnt = 1;
+ } else {
+ blksz = ch->blksz;
+ blkcnt = ch->blkcnt;
+ }
+
+ for (i = 0; i < blkcnt; i++, bdle++) {
+ bdle->addrl = (uint32_t)addr;
+ bdle->addrh = (uint32_t)(addr >> 32);
+ bdle->len = blksz;
+ bdle->ioc = 1 ^ sc->polling;
+ addr += blksz;
+ }
+
+ HDAC_WRITE_4(&sc->mem, ch->off + HDAC_SDCBL, blksz * blkcnt);
+ HDAC_WRITE_2(&sc->mem, ch->off + HDAC_SDLVI, blkcnt - 1);
+ addr = ch->bdl_dma.dma_paddr;
+ HDAC_WRITE_4(&sc->mem, ch->off + HDAC_SDBDPL, (uint32_t)addr);
+ HDAC_WRITE_4(&sc->mem, ch->off + HDAC_SDBDPU, (uint32_t)(addr >> 32));
+ if (ch->dmapos != NULL &&
+ !(HDAC_READ_4(&sc->mem, HDAC_DPIBLBASE) & 0x00000001)) {
+ addr = sc->pos_dma.dma_paddr;
+ HDAC_WRITE_4(&sc->mem, HDAC_DPIBLBASE,
+ ((uint32_t)addr & HDAC_DPLBASE_DPLBASE_MASK) | 0x00000001);
+ HDAC_WRITE_4(&sc->mem, HDAC_DPIBUBASE, (uint32_t)(addr >> 32));
+ }
}
static int
hdac_bdl_alloc(struct hdac_chan *ch)
{
-struct hdac_softc *sc = ch->devinfo->codec->sc;
-int rc;
+ struct hdac_softc *sc = ch->devinfo->codec->sc;
+ int rc;
-rc = hdac_dma_alloc(sc, &ch->bdl_dma,
-sizeof(struct hdac_bdle) * HDA_BDL_MAX);
-if (rc) {
-device_printf(sc->dev, "can't alloc bdln");
-return (rc);
-}
-hdac_dma_nocache(ch->bdl_dma.dma_vaddr);
+ rc = hdac_dma_alloc(sc, &ch->bdl_dma,
+ sizeof(struct hdac_bdle) * HDA_BDL_MAX);
+ if (rc) {
+ device_printf(sc->dev, "can't alloc bdl\n");
+ return (rc);
+ }
-return (0);
+ return (0);
}
static void
hdac_audio_ctl_amp_set_internal(struct hdac_softc *sc, nid_t cad, nid_t nid,
-int index, int lmute, int rmute,
-int left, int right, int dir)
+ int index, int lmute, int rmute,
+ int left, int right, int dir)
{
-uint16_t v = 0;
+ uint16_t v = 0;
-if (sc == NULL)
-return;
+ if (sc == NULL)
+ return;
-if (left != right || lmute != rmute) {
-v = (1 << (15 - dir)) | (1 << 13) | (index << 8) |
-(lmute << 7) | left;
-hdac_command(sc,
-HDA_CMD_SET_AMP_GAIN_MUTE(cad, nid, v), cad);
-v = (1 << (15 - dir)) | (1 << 12) | (index << 8) |
-(rmute << 7) | right;
-} else
-v = (1 << (15 - dir)) | (3 << 12) | (index << 8) |
-(lmute << 7) | left;
+ if (left != right || lmute != rmute) {
+ v = (1 << (15 - dir)) | (1 << 13) | (index << 8) |
+ (lmute << 7) | left;
+ hdac_command(sc,
+ HDA_CMD_SET_AMP_GAIN_MUTE(cad, nid, v), cad);
+ v = (1 << (15 - dir)) | (1 << 12) | (index << 8) |
+ (rmute << 7) | right;
+ } else
+ v = (1 << (15 - dir)) | (3 << 12) | (index << 8) |
+ (lmute << 7) | left;
-hdac_command(sc,
-HDA_CMD_SET_AMP_GAIN_MUTE(cad, nid, v), cad);
+ hdac_command(sc,
+ HDA_CMD_SET_AMP_GAIN_MUTE(cad, nid, v), cad);
}
static void
hdac_audio_ctl_amp_set(struct hdac_audio_ctl *ctl, uint32_t mute,
-int left, int right)
+ int left, int right)
{
-struct hdac_softc *sc;
-nid_t nid, cad;
-int lmute, rmute;
-
-if (ctl == NULL || ctl->widget == NULL ||
-ctl->widget->devinfo == NULL ||
-ctl->widget->devinfo->codec == NULL ||
-ctl->widget->devinfo->codec->sc == NULL)
-return;
-
-sc = ctl->widget->devinfo->codec->sc;
-cad = ctl->widget->devinfo->codec->cad;
-nid = ctl->widget->nid;
-
-if (mute == HDA_AMP_MUTE_DEFAULT) {
-lmute = HDA_AMP_LEFT_MUTED(ctl->muted);
-rmute = HDA_AMP_RIGHT_MUTED(ctl->muted);
-} else {
-lmute = HDA_AMP_LEFT_MUTED(mute);
-rmute = HDA_AMP_RIGHT_MUTED(mute);
-}
-
-if (ctl->dir & HDA_CTL_OUT)
-hdac_audio_ctl_amp_set_internal(sc, cad, nid, ctl->index,
-lmute, rmute, left, right, 0);
-if (ctl->dir & HDA_CTL_IN)
-hdac_audio_ctl_amp_set_internal(sc, cad, nid, ctl->index,
-lmute, rmute, left, right, 1);
-ctl->left = left;
-ctl->right = right;
+ struct hdac_softc *sc;
+ nid_t nid, cad;
+ int lmute, rmute;
+
+ if (ctl == NULL || ctl->widget == NULL ||
+ ctl->widget->devinfo == NULL ||
+ ctl->widget->devinfo->codec == NULL ||
+ ctl->widget->devinfo->codec->sc == NULL)
+ return;
+
+ sc = ctl->widget->devinfo->codec->sc;
+ cad = ctl->widget->devinfo->codec->cad;
+ nid = ctl->widget->nid;
+
+ if (mute == HDA_AMP_MUTE_DEFAULT) {
+ lmute = HDA_AMP_LEFT_MUTED(ctl->muted);
+ rmute = HDA_AMP_RIGHT_MUTED(ctl->muted);
+ } else {
+ lmute = HDA_AMP_LEFT_MUTED(mute);
+ rmute = HDA_AMP_RIGHT_MUTED(mute);
+ }
+
+ if (ctl->dir & HDA_CTL_OUT)
+ hdac_audio_ctl_amp_set_internal(sc, cad, nid, ctl->index,
+ lmute, rmute, left, right, 0);
+ if (ctl->dir & HDA_CTL_IN)
+ hdac_audio_ctl_amp_set_internal(sc, cad, nid, ctl->index,
+ lmute, rmute, left, right, 1);
+ ctl->left = left;
+ ctl->right = right;
}
static void
hdac_widget_connection_select(struct hdac_widget *w, uint8_t index)
{
-if (w == NULL || w->nconns < 1 || index > (w->nconns - 1))
-return;
-hdac_command(w->devinfo->codec->sc,
-HDA_CMD_SET_CONNECTION_SELECT_CONTROL(w->devinfo->codec->cad,
-w->nid, index), w->devinfo->codec->cad);
-w->selconn = index;
+ if (w == NULL || w->nconns < 1 || index > (w->nconns - 1))
+ return;
+ hdac_command(w->devinfo->codec->sc,
+ HDA_CMD_SET_CONNECTION_SELECT_CONTROL(w->devinfo->codec->cad,
+ w->nid, index), w->devinfo->codec->cad);
+ w->selconn = index;
}
/****************************************************************************
-* uint32_t hdac_command_sendone_internal
-*
-* Wrapper function that sends only one command to a given codec
-****************************************************************************/
+ * uint32_t hdac_command_sendone_internal
+ *
+ * Wrapper function that sends only one command to a given codec
+ ****************************************************************************/
static uint32_t
hdac_command_sendone_internal(struct hdac_softc *sc, uint32_t verb, nid_t cad)
{
-struct hdac_command_list cl;
-uint32_t response = HDAC_INVALID;
+ struct hdac_command_list cl;
+ uint32_t response = HDAC_INVALID;
-if (!hdac_lockowned(sc))
-device_printf(sc->dev, "WARNING!!!! mtx not owned!!!!n");
-cl.num_commands = 1;
-cl.verbs = &verb;
-cl.responses = &response;
+ if (!hdac_lockowned(sc))
+ device_printf(sc->dev, "WARNING!!!! mtx not owned!!!!\n");
+ cl.num_commands = 1;
+ cl.verbs = &verb;
+ cl.responses = &response;
-hdac_command_send_internal(sc, &cl, cad);
+ hdac_command_send_internal(sc, &cl, cad);
-return (response);
+ return (response);
}
/****************************************************************************
-* hdac_command_send_internal
-*
-* Send a command list to the codec via the corb. We queue as much verbs as
-* we can and msleep on the codec. When the interrupt get the responses
-* back from the rirb, it will wake us up so we can queue the remaining verbs
-* if any.
-****************************************************************************/
+ * hdac_command_send_internal
+ *
+ * Send a command list to the codec via the corb. We queue as much verbs as
+ * we can and msleep on the codec. When the interrupt get the responses
+ * back from the rirb, it will wake us up so we can queue the remaining verbs
+ * if any.
+ ****************************************************************************/
static void
hdac_command_send_internal(struct hdac_softc *sc,
-struct hdac_command_list *commands, nid_t cad)
+ struct hdac_command_list *commands, nid_t cad)
{
-struct hdac_codec *codec;
-int corbrp;
-uint32_t *corb;
-uint8_t rirbwp;
-int timeout;
-int retry = 10;
-struct hdac_rirb *rirb_base, *rirb;
-nid_t ucad;
-uint32_t utag;
-
-if (sc == NULL || sc->codecs[cad] == NULL || commands == NULL)
-return;
-
-codec = sc->codecs[cad];
-codec->commands = commands;
-codec->responses_received = 0;
-codec->verbs_sent = 0;
-corb = (uint32_t *)sc->corb_dma.dma_vaddr;
-rirb_base = (struct hdac_rirb *)sc->rirb_dma.dma_vaddr;
-
-do {
-if (codec->verbs_sent != commands->num_commands) {
-/* Queue as many verbs as possible */
-corbrp = HDAC_READ_2(&sc->mem, HDAC_CORBRP);
-bus_dmamap_sync(sc->corb_dma.dma_tag,
-sc->corb_dma.dma_map, BUS_DMASYNC_PREWRITE);
-while (codec->verbs_sent != commands->num_commands &&
-((sc->corb_wp + 1) % sc->corb_size) != corbrp) {
-sc->corb_wp++;
-sc->corb_wp %= sc->corb_size;
-corb[sc->corb_wp] =
-commands->verbs[codec->verbs_sent++];
-}
-
-/* Send the verbs to the codecs */
-bus_dmamap_sync(sc->corb_dma.dma_tag,
-sc->corb_dma.dma_map, BUS_DMASYNC_POSTWRITE);
-HDAC_WRITE_2(&sc->mem, HDAC_CORBWP, sc->corb_wp);
-}
-
-timeout = 1000;
-do {
-rirbwp = HDAC_READ_1(&sc->mem, HDAC_RIRBWP);
-bus_dmamap_sync(sc->rirb_dma.dma_tag, sc->rirb_dma.dma_map,
-BUS_DMASYNC_POSTREAD);
-if (sc->rirb_rp != rirbwp) {
-do {
-sc->rirb_rp++;
-sc->rirb_rp %= sc->rirb_size;
-rirb = &rirb_base[sc->rirb_rp];
-if (rirb->response_ex & HDAC_RIRB_RESPONSE_EX_UNSOLICITED) {
-ucad = HDAC_RIRB_RESPONSE_EX_SDATA_IN(rirb->response_ex);
-utag = rirb->response >> 26;
-if (ucad > -1 && ucad < HDAC_CODEC_MAX &&
-sc->codecs[ucad] != NULL) {
-sc->unsolq[sc->unsolq_wp++] =
-(ucad << 16) |
-(utag & 0xffff);
-sc->unsolq_wp %= HDAC_UNSOLQ_MAX;
-}
-} else if (codec->responses_received < commands->num_commands)
-codec->commands->responses[codec->responses_received++] =
-rirb->response;
-} while (sc->rirb_rp != rirbwp);
-break;
-}
-DELAY(10);
-} while (--timeout);
-} while ((codec->verbs_sent != commands->num_commands ||
-codec->responses_received != commands->num_commands) &&
---retry);
-
-if (retry == 0)
-device_printf(sc->dev,
-"%s: TIMEOUT numcmd=%d, sent=%d, received=%dn",
-__func__, commands->num_commands,
-codec->verbs_sent, codec->responses_received);
-
-codec->verbs_sent = 0;
-
-if (sc->unsolq_st == HDAC_UNSOLQ_READY) {
-sc->unsolq_st = HDAC_UNSOLQ_BUSY;
-while (sc->unsolq_rp != sc->unsolq_wp) {
-ucad = sc->unsolq[sc->unsolq_rp] >> 16;
-utag = sc->unsolq[sc->unsolq_rp++] & 0xffff;
-sc->unsolq_rp %= HDAC_UNSOLQ_MAX;
-hdac_unsolicited_handler(sc->codecs[ucad], utag);
-}
-sc->unsolq_st = HDAC_UNSOLQ_READY;
-}
+ struct hdac_codec *codec;
+ int corbrp;
+ uint32_t *corb;
+ int timeout;
+ int retry = 10;
+ struct hdac_rirb *rirb_base;
+
+ if (sc == NULL || sc->codecs[cad] == NULL || commands == NULL ||
+ commands->num_commands < 1)
+ return;
+
+ codec = sc->codecs[cad];
+ codec->commands = commands;
+ codec->responses_received = 0;
+ codec->verbs_sent = 0;
+ corb = (uint32_t *)sc->corb_dma.dma_vaddr;
+ rirb_base = (struct hdac_rirb *)sc->rirb_dma.dma_vaddr;
+
+ do {
+ if (codec->verbs_sent != commands->num_commands) {
+ /* Queue as many verbs as possible */
+ corbrp = HDAC_READ_2(&sc->mem, HDAC_CORBRP);
+#if 0
+ bus_dmamap_sync(sc->corb_dma.dma_tag,
+ sc->corb_dma.dma_map, BUS_DMASYNC_PREWRITE);
+#endif
+ while (codec->verbs_sent != commands->num_commands &&
+ ((sc->corb_wp + 1) % sc->corb_size) != corbrp) {
+ sc->corb_wp++;
+ sc->corb_wp %= sc->corb_size;
+ corb[sc->corb_wp] =
+ commands->verbs[codec->verbs_sent++];
+ }
+
+ /* Send the verbs to the codecs */
+#if 0
+ bus_dmamap_sync(sc->corb_dma.dma_tag,
+ sc->corb_dma.dma_map, BUS_DMASYNC_POSTWRITE);
+#endif
+ HDAC_WRITE_2(&sc->mem, HDAC_CORBWP, sc->corb_wp);
+ }
+
+ timeout = 1000;
+ while (hdac_rirb_flush(sc) == 0 && --timeout)
+ DELAY(10);
+ } while ((codec->verbs_sent != commands->num_commands ||
+ codec->responses_received != commands->num_commands) && --retry);
+
+ if (retry == 0)
+ device_printf(sc->dev,
+ "%s: TIMEOUT numcmd=%d, sent=%d, received=%d\n",
+ __func__, commands->num_commands, codec->verbs_sent,
+ codec->responses_received);
+
+ codec->commands = NULL;
+ codec->responses_received = 0;
+ codec->verbs_sent = 0;
+
+ hdac_unsolq_flush(sc);
}
/****************************************************************************
-* Device Methods
-****************************************************************************/
+ * Device Methods
+ ****************************************************************************/
/****************************************************************************
-* int hdac_probe(device_t)
-*
-* Probe for the presence of an hdac. If none is found, check for a generic
-* match using the subclass of the device.
-****************************************************************************/
+ * int hdac_probe(device_t)
+ *
+ * Probe for the presence of an hdac. If none is found, check for a generic
+ * match using the subclass of the device.
+ ****************************************************************************/
static int
hdac_probe(device_t dev)
{
-int i, result;
-uint32_t model;
-uint16_t class, subclass;
-char desc[64];
-
-model = (uint32_t)pci_get_device(dev) << 16;
-model |= (uint32_t)pci_get_vendor(dev) & 0x0000ffff;
-class = pci_get_class(dev);
-subclass = pci_get_subclass(dev);
-
-bzero(desc, sizeof(desc));
-result = ENXIO;
-for (i = 0; i < HDAC_DEVICES_LEN; i++) {
-if (hdac_devices[i].model == model) {
-strlcpy(desc, hdac_devices[i].desc, sizeof(desc));
-result = BUS_PROBE_DEFAULT;
-break;
-}
-if (HDA_DEV_MATCH(hdac_devices[i].model, model) &&
-class == PCIC_MULTIMEDIA &&
-subclass == PCIS_MULTIMEDIA_HDA) {
-strlcpy(desc, hdac_devices[i].desc, sizeof(desc));
-result = BUS_PROBE_GENERIC;
-break;
-}
-}
-if (result == ENXIO && class == PCIC_MULTIMEDIA &&
-subclass == PCIS_MULTIMEDIA_HDA) {
-strlcpy(desc, "Generic", sizeof(desc));
-result = BUS_PROBE_GENERIC;
-}
-if (result != ENXIO) {
-strlcat(desc, " High Definition Audio Controller",
-sizeof(desc));
-device_set_desc_copy(dev, desc);
-}
+ int i, result;
+ uint32_t model;
+ uint16_t class, subclass;
+ char desc[64];
+
+ model = (uint32_t)pci_get_device(dev) << 16;
+ model |= (uint32_t)pci_get_vendor(dev) & 0x0000ffff;
+ class = pci_get_class(dev);
+ subclass = pci_get_subclass(dev);
+
+ bzero(desc, sizeof(desc));
+ result = ENXIO;
+ for (i = 0; i < HDAC_DEVICES_LEN; i++) {
+ if (hdac_devices[i].model == model) {
+ strlcpy(desc, hdac_devices[i].desc, sizeof(desc));
+ result = BUS_PROBE_DEFAULT;
+ break;
+ }
+ if (HDA_DEV_MATCH(hdac_devices[i].model, model) &&
+ class == PCIC_MULTIMEDIA &&
+ subclass == PCIS_MULTIMEDIA_HDA) {
+ strlcpy(desc, hdac_devices[i].desc, sizeof(desc));
+ result = BUS_PROBE_GENERIC;
+ break;
+ }
+ }
+ if (result == ENXIO && class == PCIC_MULTIMEDIA &&
+ subclass == PCIS_MULTIMEDIA_HDA) {
+ strlcpy(desc, "Generic", sizeof(desc));
+ result = BUS_PROBE_GENERIC;
+ }
+ if (result != ENXIO) {
+ strlcat(desc, " High Definition Audio Controller",
+ sizeof(desc));
+ device_set_desc_copy(dev, desc);
+ }
-return (result);
+ return (result);
}
static void *
hdac_channel_init(kobj_t obj, void *data, struct snd_dbuf *b,
-struct pcm_channel *c, int dir)
+ struct pcm_channel *c, int dir)
{
-struct hdac_devinfo *devinfo = data;
-struct hdac_softc *sc = devinfo->codec->sc;
-struct hdac_chan *ch;
-
-hdac_lock(sc);
-if (dir == PCMDIR_PLAY) {
-ch = &sc->play;
-ch->off = (sc->num_iss + devinfo->function.audio.playcnt) << 5;
-ch->dir = PCMDIR_PLAY;
-ch->sid = ++sc->streamcnt;
-devinfo->function.audio.playcnt++;
-} else {
-ch = &sc->rec;
-ch->off = devinfo->function.audio.reccnt << 5;
-ch->dir = PCMDIR_REC;
-ch->sid = ++sc->streamcnt;
-devinfo->function.audio.reccnt++;
-}
-if (devinfo->function.audio.quirks & HDA_QUIRK_FIXEDRATE) {
-ch->caps.minspeed = ch->caps.maxspeed = 48000;
-ch->pcmrates[0] = 48000;
-ch->pcmrates[1] = 0;
-}
-ch->b = b;
-ch->c = c;
-ch->devinfo = devinfo;
-ch->blksz = sc->chan_size / sc->chan_blkcnt;
-ch->blkcnt = sc->chan_blkcnt;
-hdac_unlock(sc);
-
-if (hdac_bdl_alloc(ch) != 0) {
-ch->blkcnt = 0;
-return (NULL);
-}
-
-if (sndbuf_alloc(ch->b, sc->chan_dmat, sc->chan_size) != 0)
-return (NULL);
+ struct hdac_devinfo *devinfo = data;
+ struct hdac_softc *sc = devinfo->codec->sc;
+ struct hdac_chan *ch;
+
+ hdac_lock(sc);
+ if (dir == PCMDIR_PLAY) {
+ ch = &sc->play;
+ ch->off = (sc->num_iss + devinfo->function.audio.playcnt) << 5;
+ devinfo->function.audio.playcnt++;
+ } else {
+ ch = &sc->rec;
+ ch->off = devinfo->function.audio.reccnt << 5;
+ devinfo->function.audio.reccnt++;
+ }
+ if (devinfo->function.audio.quirks & HDA_QUIRK_FIXEDRATE) {
+ ch->caps.minspeed = ch->caps.maxspeed = 48000;
+ ch->pcmrates[0] = 48000;
+ ch->pcmrates[1] = 0;
+ }
+ if (sc->pos_dma.dma_vaddr != NULL)
+ ch->dmapos = (uint32_t *)(sc->pos_dma.dma_vaddr +
+ (sc->streamcnt * 8));
+ else
+ ch->dmapos = NULL;
+ ch->sid = ++sc->streamcnt;
+ ch->dir = dir;
+ ch->b = b;
+ ch->c = c;
+ ch->devinfo = devinfo;
+ ch->blksz = sc->chan_size / sc->chan_blkcnt;
+ ch->blkcnt = sc->chan_blkcnt;
+ hdac_unlock(sc);
+
+ if (hdac_bdl_alloc(ch) != 0) {
+ ch->blkcnt = 0;
+ return (NULL);
+ }
+
+ if (sndbuf_alloc(ch->b, sc->chan_dmat,
+ (sc->flags & HDAC_F_DMA_NOCACHE) ? BUS_DMA_NOCACHE : 0,
+ sc->chan_size) != 0)
+ return (NULL);
-hdac_dma_nocache(ch->b->buf);
-
-return (ch);
+ return (ch);
}
static int
hdac_channel_setformat(kobj_t obj, void *data, uint32_t format)
{
-struct hdac_chan *ch = data;
-int i;
+ struct hdac_chan *ch = data;
+ int i;
-for (i = 0; ch->caps.fmtlist[i] != 0; i++) {
-if (format == ch->caps.fmtlist[i]) {
-ch->fmt = format;
-return (0);
-}
-}
+ for (i = 0; ch->caps.fmtlist[i] != 0; i++) {
+ if (format == ch->caps.fmtlist[i]) {
+ ch->fmt = format;
+ return (0);
+ }
+ }
-return (EINVAL);
+ return (EINVAL);
}
static int
hdac_channel_setspeed(kobj_t obj, void *data, uint32_t speed)
{
-struct hdac_chan *ch = data;
-uint32_t spd = 0;
-int i;
-
-for (i = 0; ch->pcmrates[i] != 0; i++) {
-spd = ch->pcmrates[i];
-if (spd >= speed)
-break;
-}
-
-if (spd == 0)
-ch->spd = 48000;
-else
-ch->spd = spd;
+ struct hdac_chan *ch = data;
+ uint32_t spd = 0, threshold;
+ int i;
+
+ for (i = 0; ch->pcmrates[i] != 0; i++) {
+ spd = ch->pcmrates[i];
+ threshold = spd + ((ch->pcmrates[i + 1] != 0) ?
+ ((ch->pcmrates[i + 1] - spd) >> 1) : 0);
+ if (speed < threshold)
+ break;
+ }
+
+ if (spd == 0) /* impossible */
+ ch->spd = 48000;
+ else
+ ch->spd = spd;
-return (ch->spd);
+ return (ch->spd);
}
static void
hdac_stream_setup(struct hdac_chan *ch)
{
-struct hdac_softc *sc = ch->devinfo->codec->sc;
-int i;
-nid_t cad = ch->devinfo->codec->cad;
-uint16_t fmt;
-
-fmt = 0;
-if (ch->fmt & AFMT_S16_LE)
-fmt |= ch->bit16 << 4;
-else if (ch->fmt & AFMT_S32_LE)
-fmt |= ch->bit32 << 4;
-else
-fmt |= 1 << 4;
-
-for (i = 0; i < HDA_RATE_TAB_LEN; i++) {
-if (hda_rate_tab[i].valid && ch->spd == hda_rate_tab[i].rate) {
-fmt |= hda_rate_tab[i].base;
-fmt |= hda_rate_tab[i].mul;
-fmt |= hda_rate_tab[i].div;
-break;
-}
+ struct hdac_softc *sc = ch->devinfo->codec->sc;
+ struct hdac_widget *w;
+ int i, chn, totalchn;
+ nid_t cad = ch->devinfo->codec->cad;
+ uint16_t fmt;
+
+ fmt = 0;
+ if (ch->fmt & AFMT_S16_LE)
+ fmt |= ch->bit16 << 4;
+ else if (ch->fmt & AFMT_S32_LE)
+ fmt |= ch->bit32 << 4;
+ else
+ fmt |= 1 << 4;
+
+ for (i = 0; i < HDA_RATE_TAB_LEN; i++) {
+ if (hda_rate_tab[i].valid && ch->spd == hda_rate_tab[i].rate) {
+ fmt |= hda_rate_tab[i].base;
+ fmt |= hda_rate_tab[i].mul;
+ fmt |= hda_rate_tab[i].div;
+ break;
+ }
+ }
+
+ if (ch->fmt & AFMT_STEREO) {
+ fmt |= 1;
+ totalchn = 2;
+ } else
+ totalchn = 1;
+
+ HDAC_WRITE_2(&sc->mem, ch->off + HDAC_SDFMT, fmt);
+
+ chn = 0;
+ for (i = 0; ch->io[i] != -1; i++) {
+ w = hdac_widget_get(ch->devinfo, ch->io[i]);
+ if (w == NULL)
+ continue;
+ HDA_BOOTVERBOSE(
+ device_printf(sc->dev,
+ "HDA_DEBUG: PCMDIR_%s: Stream setup nid=%d "
+ "fmt=0x%08x\n",
+ (ch->dir == PCMDIR_PLAY) ? "PLAY" : "REC",
+ ch->io[i], fmt);
+ );
+ hdac_command(sc,
+ HDA_CMD_SET_CONV_FMT(cad, ch->io[i], fmt), cad);
+ if (ch->dir == PCMDIR_REC)
+ hdac_command(sc,
+ HDA_CMD_SET_CONV_STREAM_CHAN(cad, ch->io[i],
+ (chn < totalchn) ? ((ch->sid << 4) | chn) : 0),
+ cad);
+ else
+ hdac_command(sc,
+ HDA_CMD_SET_CONV_STREAM_CHAN(cad, ch->io[i],
+ ch->sid << 4), cad);
+ chn +=
+ HDA_PARAM_AUDIO_WIDGET_CAP_STEREO(w->param.widget_cap) ?
+ 2 : 1;
+ }
}
-if (ch->fmt & AFMT_STEREO)
-fmt |= 1;
-
-HDAC_WRITE_2(&sc->mem, ch->off + HDAC_SDFMT, fmt);
-
-for (i = 0; ch->io[i] != -1; i++) {
-HDA_BOOTVERBOSE(
-device_printf(sc->dev,
-"HDA_DEBUG: PCMDIR_%s: Stream setup nid=%d "
-"fmt=0x%08xn",
-(ch->dir == PCMDIR_PLAY) ? "PLAY" : "REC",
-ch->io[i], fmt);
-);
-hdac_command(sc,
-HDA_CMD_SET_CONV_FMT(cad, ch->io[i], fmt), cad);
-hdac_command(sc,
-HDA_CMD_SET_CONV_STREAM_CHAN(cad, ch->io[i],
-ch->sid << 4), cad);
-}
+static int
+hdac_channel_setfragments(kobj_t obj, void *data,
+ uint32_t blksz, uint32_t blkcnt)
+{
+ struct hdac_chan *ch = data;
+ struct hdac_softc *sc = ch->devinfo->codec->sc;
+
+ blksz &= HDA_BLK_ALIGN;
+
+ if (blksz > (sndbuf_getmaxsize(ch->b) / HDA_BDL_MIN))
+ blksz = sndbuf_getmaxsize(ch->b) / HDA_BDL_MIN;
+ if (blksz < HDA_BLK_MIN)
+ blksz = HDA_BLK_MIN;
+ if (blkcnt > HDA_BDL_MAX)
+ blkcnt = HDA_BDL_MAX;
+ if (blkcnt < HDA_BDL_MIN)
+ blkcnt = HDA_BDL_MIN;
+
+ while ((blksz * blkcnt) > sndbuf_getmaxsize(ch->b)) {
+ if ((blkcnt >> 1) >= HDA_BDL_MIN)
+ blkcnt >>= 1;
+ else if ((blksz >> 1) >= HDA_BLK_MIN)
+ blksz >>= 1;
+ else
+ break;
+ }
+
+ if ((sndbuf_getblksz(ch->b) != blksz ||
+ sndbuf_getblkcnt(ch->b) != blkcnt) &&
+ sndbuf_resize(ch->b, blkcnt, blksz) != 0)
+ device_printf(sc->dev, "%s: failed blksz=%u blkcnt=%u\n",
+ __func__, blksz, blkcnt);
+
+ ch->blksz = sndbuf_getblksz(ch->b);
+ ch->blkcnt = sndbuf_getblkcnt(ch->b);
+
+ return (1);
}
static int
-hdac_channel_setblocksize(kobj_t obj, void *data, uint32_t blocksize)
+hdac_channel_setblocksize(kobj_t obj, void *data, uint32_t blksz)
{
-struct hdac_chan *ch = data;
+ struct hdac_chan *ch = data;
+ struct hdac_softc *sc = ch->devinfo->codec->sc;
-sndbuf_resize(ch->b, ch->blkcnt, ch->blksz);
+ hdac_channel_setfragments(obj, data, blksz, sc->chan_blkcnt);
-return (ch->blksz);
+ return (ch->blksz);
}
static void
hdac_channel_stop(struct hdac_softc *sc, struct hdac_chan *ch)
{
-struct hdac_devinfo *devinfo = ch->devinfo;
-nid_t cad = devinfo->codec->cad;
-int i;
-
-hdac_stream_stop(ch);
-
-for (i = 0; ch->io[i] != -1; i++) {
-hdac_command(sc,
-HDA_CMD_SET_CONV_STREAM_CHAN(cad, ch->io[i],
-0), cad);
-}
+ struct hdac_devinfo *devinfo = ch->devinfo;
+ nid_t cad = devinfo->codec->cad;
+ int i;
+
+ hdac_stream_stop(ch);
+
+ for (i = 0; ch->io[i] != -1; i++) {
+ hdac_command(sc,
+ HDA_CMD_SET_CONV_STREAM_CHAN(cad, ch->io[i],
+ 0), cad);
+ }
}
static void
hdac_channel_start(struct hdac_softc *sc, struct hdac_chan *ch)
{
-ch->ptr = 0;
-ch->prevptr = 0;
-hdac_stream_stop(ch);
-hdac_stream_reset(ch);
-hdac_bdl_setup(ch);
-hdac_stream_setid(ch);
-hdac_stream_setup(ch);
-hdac_stream_start(ch);
+ ch->ptr = 0;
+ ch->prevptr = 0;
+ hdac_stream_stop(ch);
+ hdac_stream_reset(ch);
+ hdac_bdl_setup(ch);
+ hdac_stream_setid(ch);
+ hdac_stream_setup(ch);
+ hdac_stream_start(ch);
}
static int
hdac_channel_trigger(kobj_t obj, void *data, int go)
{
-struct hdac_chan *ch = data;
-struct hdac_softc *sc = ch->devinfo->codec->sc;
+ struct hdac_chan *ch = data;
+ struct hdac_softc *sc = ch->devinfo->codec->sc;
-hdac_lock(sc);
-switch (go) {
-case PCMTRIG_START:
-hdac_channel_start(sc, ch);
-break;
-case PCMTRIG_STOP:
-case PCMTRIG_ABORT:
-hdac_channel_stop(sc, ch);
-break;
-}
-hdac_unlock(sc);
+ if (!PCMTRIG_COMMON(go))
+ return (0);
+
+ hdac_lock(sc);
+ switch (go) {
+ case PCMTRIG_START:
+ hdac_channel_start(sc, ch);
+ break;
+ case PCMTRIG_STOP:
+ case PCMTRIG_ABORT:
+ hdac_channel_stop(sc, ch);
+ break;
+ default:
+ break;
+ }
+ hdac_unlock(sc);
-return (0);
+ return (0);
}
static int
hdac_channel_getptr(kobj_t obj, void *data)
{
-struct hdac_chan *ch = data;
-struct hdac_softc *sc = ch->devinfo->codec->sc;
-int sz, delta;
-uint32_t ptr;
-
-hdac_lock(sc);
-ptr = HDAC_READ_4(&sc->mem, ch->off + HDAC_SDLPIB);
-hdac_unlock(sc);
-
-sz = sndbuf_getsize(ch->b);
-ptr %= sz;
-
-if (ch->dir == PCMDIR_REC) {
-delta = ptr % sndbuf_getblksz(ch->b);
-if (delta != 0) {
-ptr -= delta;
-if (ptr < delta)
-ptr = sz - delta;
-else
-ptr -= delta;
-}
-}
+ struct hdac_chan *ch = data;
+ struct hdac_softc *sc = ch->devinfo->codec->sc;
+ uint32_t ptr;
+
+ hdac_lock(sc);
+ if (sc->polling != 0)
+ ptr = ch->ptr;
+ else if (ch->dmapos != NULL)
+ ptr = *(ch->dmapos);
+ else
+ ptr = HDAC_READ_4(&sc->mem, ch->off + HDAC_SDLPIB);
+ hdac_unlock(sc);
+
+ /*
+ * Round to available space and force 128 bytes aligment.
+ */
+ ptr %= ch->blksz * ch->blkcnt;
+ ptr &= HDA_BLK_ALIGN;
-return (ptr);
+ return (ptr);
}
static struct pcmchan_caps *
hdac_channel_getcaps(kobj_t obj, void *data)
{
-return (&((struct hdac_chan *)data)->caps);
+ return (&((struct hdac_chan *)data)->caps);
}
static kobj_method_t hdac_channel_methods[] = {
-KOBJMETHOD(channel_init, hdac_channel_init),
-KOBJMETHOD(channel_setformat, hdac_channel_setformat),
-KOBJMETHOD(channel_setspeed, hdac_channel_setspeed),
-KOBJMETHOD(channel_setblocksize, hdac_channel_setblocksize),
-KOBJMETHOD(channel_trigger, hdac_channel_trigger),
-KOBJMETHOD(channel_getptr, hdac_channel_getptr),
-KOBJMETHOD(channel_getcaps, hdac_channel_getcaps),
-{ 0, 0 }
+ KOBJMETHOD(channel_init, hdac_channel_init),
+ KOBJMETHOD(channel_setformat, hdac_channel_setformat),
+ KOBJMETHOD(channel_setspeed, hdac_channel_setspeed),
+ KOBJMETHOD(channel_setblocksize, hdac_channel_setblocksize),
+ KOBJMETHOD(channel_setfragments, hdac_channel_setfragments),
+ KOBJMETHOD(channel_trigger, hdac_channel_trigger),
+ KOBJMETHOD(channel_getptr, hdac_channel_getptr),
+ KOBJMETHOD(channel_getcaps, hdac_channel_getcaps),
+ { 0, 0 }
};
CHANNEL_DECLARE(hdac_channel);
-static int
-hdac_audio_ctl_ossmixer_init(struct snd_mixer *m)
+static void
+hdac_jack_poll_callback(void *arg)
{
-struct hdac_devinfo *devinfo = mix_getdevinfo(m);
-struct hdac_softc *sc = devinfo->codec->sc;
-struct hdac_widget *w, *cw;
-struct hdac_audio_ctl *ctl;
-uint32_t mask, recmask, id;
-int i, j, softpcmvol;
-nid_t cad;
-
-hdac_lock(sc);
-
-mask = 0;
-recmask = 0;
-
-id = hdac_codec_id(devinfo);
-cad = devinfo->codec->cad;
-for (i = 0; i < HDAC_HP_SWITCH_LEN; i++) {
-if (!(HDA_DEV_MATCH(hdac_hp_switch[i].model,
-sc->pci_subvendor) &&
-hdac_hp_switch[i].id == id))
-continue;
-w = hdac_widget_get(devinfo, hdac_hp_switch[i].hpnid);
-if (w != NULL && w->enable != 0
-&& w->type ==
-HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX &&
-HDA_PARAM_AUDIO_WIDGET_CAP_UNSOL_CAP(w->param.widget_cap)) {
-hdac_command(sc,
-HDA_CMD_SET_UNSOLICITED_RESPONSE(cad,
-w->nid,
-HDA_CMD_SET_UNSOLICITED_RESPONSE_ENABLE|
-HDAC_UNSOLTAG_EVENT_HP), cad);
-hdac_hp_switch_handler(devinfo);
-HDA_BOOTVERBOSE(
-device_printf(sc->dev,
-"HDA_DEBUG: Enabling headphone/speaker "
-"audio routing switching:n");
-device_printf(sc->dev,
-"HDA_DEBUG: tindex=%d nid=%d "
-"pci_subvendor=0x%08x "
-"codec=0x%08xn",
-i, w->nid, sc->pci_subvendor, id);
-);
-}
-break;
-}
-for (i = 0; i < HDAC_EAPD_SWITCH_LEN; i++) {
-if (!(HDA_DEV_MATCH(hdac_eapd_switch[i].model,
-sc->pci_subvendor) &&
-hdac_eapd_switch[i].id == id))
-continue;
-w = hdac_widget_get(devinfo, hdac_eapd_switch[i].eapdnid);
-if (w == NULL || w->enable == 0)
-break;
-if (w->type != HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX ||
-w->param.eapdbtl == HDAC_INVALID)
-break;
-mask |= SOUND_MASK_OGAIN;
-break;
-}
-
-for (i = devinfo->startnode; i < devinfo->endnode; i++) {
-w = hdac_widget_get(devinfo, i);
-if (w == NULL || w->enable == 0)
-continue;
-mask |= w->ctlflags;
-if (!(w->pflags & HDA_ADC_RECSEL))
-continue;
-for (j = 0; j < w->nconns; j++) {
-cw = hdac_widget_get(devinfo, w->conns[j]);
-if (cw == NULL || cw->enable == 0)
-continue;
-recmask |= cw->ctlflags;
-}
-}
-
-if (!(mask & SOUND_MASK_PCM)) {
-softpcmvol = 1;
-mask |= SOUND_MASK_PCM;
-} else
-softpcmvol = (devinfo->function.audio.quirks &
-HDA_QUIRK_SOFTPCMVOL) ? 1 : 0;
-
-i = 0;
-ctl = NULL;
-while ((ctl = hdac_audio_ctl_each(devinfo, &i)) != NULL) {
-if (ctl->widget == NULL || ctl->enable == 0)
-continue;
-if (!(ctl->ossmask & SOUND_MASK_PCM))
-continue;
-if (ctl->step > 0)
-break;
-}
-
-if (softpcmvol == 1 || ctl == NULL) {
-struct snddev_info *d = NULL;
-d = device_get_softc(sc->dev);
-if (d != NULL) {
-d->flags |= SD_F_SOFTPCMVOL;
-HDA_BOOTVERBOSE(
-device_printf(sc->dev,
-"HDA_DEBUG: %s Soft PCM volumen",
-(softpcmvol == 1) ?
-"Forcing" : "Enabling");
-);
-}
-i = 0;
-/*
-* XXX Temporary quirk for STAC9220, until the parser
-* become smarter.
-*/
-if (id == HDA_CODEC_STAC9220) {
-mask |= SOUND_MASK_VOLUME;
-while ((ctl = hdac_audio_ctl_each(devinfo, &i)) !=
-NULL) {
-if (ctl->widget == NULL || ctl->enable == 0)
-continue;
-if (ctl->widget->nid == 11 && ctl->index == 0) {
-ctl->ossmask = SOUND_MASK_VOLUME;
-ctl->ossval = 100 | (100 << 8);
-} else
-ctl->ossmask &= ~SOUND_MASK_VOLUME;
-}
-} else {
-mix_setparentchild(m, SOUND_MIXER_VOLUME,
-SOUND_MASK_PCM);
-if (!(mask & SOUND_MASK_VOLUME))
-mix_setrealdev(m, SOUND_MIXER_VOLUME,
-SOUND_MIXER_NONE);
-while ((ctl = hdac_audio_ctl_each(devinfo, &i)) !=
-NULL) {
-if (ctl->widget == NULL || ctl->enable == 0)
-continue;
-if (!HDA_FLAG_MATCH(ctl->ossmask,
-SOUND_MASK_VOLUME | SOUND_MASK_PCM))
-continue;
-if (!(ctl->mute == 1 && ctl->step == 0))
-ctl->enable = 0;
-}
-}
+ struct hdac_devinfo *devinfo = arg;
+ struct hdac_softc *sc;
+
+ if (devinfo == NULL || devinfo->codec == NULL ||
+ devinfo->codec->sc == NULL)
+ return;
+ sc = devinfo->codec->sc;
+ hdac_lock(sc);
+ if (sc->poll_ival == 0) {
+ hdac_unlock(sc);
+ return;
+ }
+ hdac_hp_switch_handler(devinfo);
+ callout_reset(&sc->poll_jack, sc->poll_ival,
+ hdac_jack_poll_callback, devinfo);
+ hdac_unlock(sc);
}
-recmask &= ~(SOUND_MASK_PCM | SOUND_MASK_RECLEV | SOUND_MASK_SPEAKER);
+static int
+hdac_audio_ctl_ossmixer_init(struct snd_mixer *m)
+{
+ struct hdac_devinfo *devinfo = mix_getdevinfo(m);
+ struct hdac_softc *sc = devinfo->codec->sc;
+ struct hdac_widget *w, *cw;
+ struct hdac_audio_ctl *ctl;
+ uint32_t mask, recmask, id;
+ int i, j, softpcmvol;
+ nid_t cad;
+
+ hdac_lock(sc);
+
+ mask = 0;
+ recmask = 0;
+
+ id = hdac_codec_id(devinfo);
+ cad = devinfo->codec->cad;
+ for (i = 0; i < HDAC_HP_SWITCH_LEN; i++) {
+ if (!(HDA_DEV_MATCH(hdac_hp_switch[i].model,
+ sc->pci_subvendor) && hdac_hp_switch[i].id == id))
+ continue;
+ w = hdac_widget_get(devinfo, hdac_hp_switch[i].hpnid);
+ if (w == NULL || w->enable == 0 || w->type !=
+ HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX)
+ continue;
+ if (hdac_hp_switch[i].polling != 0)
+ callout_reset(&sc->poll_jack, 1,
+ hdac_jack_poll_callback, devinfo);
+ else if (HDA_PARAM_AUDIO_WIDGET_CAP_UNSOL_CAP(w->param.widget_cap))
+ hdac_command(sc,
+ HDA_CMD_SET_UNSOLICITED_RESPONSE(cad, w->nid,
+ HDA_CMD_SET_UNSOLICITED_RESPONSE_ENABLE |
+ HDAC_UNSOLTAG_EVENT_HP), cad);
+ else
+ continue;
+ hdac_hp_switch_handler(devinfo);
+ HDA_BOOTVERBOSE(
+ device_printf(sc->dev,
+ "HDA_DEBUG: Enabling headphone/speaker "
+ "audio routing switching:\n");
+ device_printf(sc->dev,
+ "HDA_DEBUG: \tindex=%d nid=%d "
+ "pci_subvendor=0x%08x "
+ "codec=0x%08x [%s]\n",
+ i, w->nid, sc->pci_subvendor, id,
+ (hdac_hp_switch[i].polling != 0) ? "POLL" :
+ "UNSOL");
+ );
+ break;
+ }
+ for (i = 0; i < HDAC_EAPD_SWITCH_LEN; i++) {
+ if (!(HDA_DEV_MATCH(hdac_eapd_switch[i].model,
+ sc->pci_subvendor) &&
+ hdac_eapd_switch[i].id == id))
+ continue;
+ w = hdac_widget_get(devinfo, hdac_eapd_switch[i].eapdnid);
+ if (w == NULL || w->enable == 0)
+ break;
+ if (w->type != HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX ||
+ w->param.eapdbtl == HDAC_INVALID)
+ break;
+ mask |= SOUND_MASK_OGAIN;
+ break;
+ }
+
+ for (i = devinfo->startnode; i < devinfo->endnode; i++) {
+ w = hdac_widget_get(devinfo, i);
+ if (w == NULL || w->enable == 0)
+ continue;
+ mask |= w->ctlflags;
+ if (!(w->pflags & HDA_ADC_RECSEL))
+ continue;
+ for (j = 0; j < w->nconns; j++) {
+ cw = hdac_widget_get(devinfo, w->conns[j]);
+ if (cw == NULL || cw->enable == 0)
+ continue;
+ recmask |= cw->ctlflags;
+ }
+ }
+
+ if (!(mask & SOUND_MASK_PCM)) {
+ softpcmvol = 1;
+ mask |= SOUND_MASK_PCM;
+ } else
+ softpcmvol = (devinfo->function.audio.quirks &
+ HDA_QUIRK_SOFTPCMVOL) ? 1 : 0;
+
+ i = 0;
+ ctl = NULL;
+ while ((ctl = hdac_audio_ctl_each(devinfo, &i)) != NULL) {
+ if (ctl->widget == NULL || ctl->enable == 0)
+ continue;
+ if (!(ctl->ossmask & SOUND_MASK_PCM))
+ continue;
+ if (ctl->step > 0)
+ break;
+ }
+
+ if (softpcmvol == 1 || ctl == NULL) {
+ pcm_setflags(sc->dev, pcm_getflags(sc->dev) | SD_F_SOFTPCMVOL);
+ HDA_BOOTVERBOSE(
+ device_printf(sc->dev,
+ "HDA_DEBUG: %s Soft PCM volume\n",
+ (softpcmvol == 1) ?
+ "Forcing" : "Enabling");
+ );
+ i = 0;
+ /*
+ * XXX Temporary quirk for STAC9220, until the parser
+ * become smarter.
+ */
+ if (id == HDA_CODEC_STAC9220) {
+ mask |= SOUND_MASK_VOLUME;
+ while ((ctl = hdac_audio_ctl_each(devinfo, &i)) !=
+ NULL) {
+ if (ctl->widget == NULL || ctl->enable == 0)
+ continue;
+ if (ctl->widget->nid == 11 && ctl->index == 0) {
+ ctl->ossmask = SOUND_MASK_VOLUME;
+ ctl->ossval = 100 | (100 << 8);
+ } else
+ ctl->ossmask &= ~SOUND_MASK_VOLUME;
+ }
+ } else if (id == HDA_CODEC_STAC9221) {
+ mask |= SOUND_MASK_VOLUME;
+ while ((ctl = hdac_audio_ctl_each(devinfo, &i)) !=
+ NULL) {
+ if (ctl->widget == NULL)
+ continue;
+ if (ctl->widget->type ==
+ HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_OUTPUT &&
+ ctl->index == 0 && (ctl->widget->nid == 2 ||
+ ctl->widget->enable != 0)) {
+ ctl->enable = 1;
+ ctl->ossmask = SOUND_MASK_VOLUME;
+ ctl->ossval = 100 | (100 << 8);
+ } else if (ctl->enable == 0)
+ continue;
+ else
+ ctl->ossmask &= ~SOUND_MASK_VOLUME;
+ }
+ } else {
+ mix_setparentchild(m, SOUND_MIXER_VOLUME,
+ SOUND_MASK_PCM);
+ if (!(mask & SOUND_MASK_VOLUME))
+ mix_setrealdev(m, SOUND_MIXER_VOLUME,
+ SOUND_MIXER_NONE);
+ while ((ctl = hdac_audio_ctl_each(devinfo, &i)) !=
+ NULL) {
+ if (ctl->widget == NULL || ctl->enable == 0)
+ continue;
+ if (!HDA_FLAG_MATCH(ctl->ossmask,
+ SOUND_MASK_VOLUME | SOUND_MASK_PCM))
+ continue;
+ if (!(ctl->mute == 1 && ctl->step == 0))
+ ctl->enable = 0;
+ }
+ }
+ }
+
+ recmask &= ~(SOUND_MASK_PCM | SOUND_MASK_RECLEV | SOUND_MASK_SPEAKER |
+ SOUND_MASK_BASS | SOUND_MASK_TREBLE | SOUND_MASK_IGAIN |
+ SOUND_MASK_OGAIN);
+ recmask &= (1 << SOUND_MIXER_NRDEVICES) - 1;
+ mask &= (1 << SOUND_MIXER_NRDEVICES) - 1;
-mix_setrecdevs(m, recmask);
-mix_setdevs(m, mask);
+ mix_setrecdevs(m, recmask);
+ mix_setdevs(m, mask);
-hdac_unlock(sc);
+ hdac_unlock(sc);
-return (0);
+ return (0);
}
static int
hdac_audio_ctl_ossmixer_set(struct snd_mixer *m, unsigned dev,
-unsigned left, unsigned right)
+ unsigned left, unsigned right)
{
-struct hdac_devinfo *devinfo = mix_getdevinfo(m);
-struct hdac_softc *sc = devinfo->codec->sc;
-struct hdac_widget *w;
-struct hdac_audio_ctl *ctl;
-uint32_t id, mute;
-int lvol, rvol, mlvol, mrvol;
-int i = 0;
-
-hdac_lock(sc);
-if (dev == SOUND_MIXER_OGAIN) {
-uint32_t orig;
-/*if (left != right || !(left == 0 || left == 1)) {
-hdac_unlock(sc);
-return (-1);
-}*/
-id = hdac_codec_id(devinfo);
-for (i = 0; i < HDAC_EAPD_SWITCH_LEN; i++) {
-if (HDA_DEV_MATCH(hdac_eapd_switch[i].model,
-sc->pci_subvendor) &&
-hdac_eapd_switch[i].id == id)
-break;
-}
-if (i >= HDAC_EAPD_SWITCH_LEN) {
-hdac_unlock(sc);
-return (-1);
-}
-w = hdac_widget_get(devinfo, hdac_eapd_switch[i].eapdnid);
-if (w == NULL ||
-w->type != HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX ||
-w->param.eapdbtl == HDAC_INVALID) {
-hdac_unlock(sc);
-return (-1);
-}
-orig = w->param.eapdbtl;
-if (left == 0)
-w->param.eapdbtl &= ~HDA_CMD_SET_EAPD_BTL_ENABLE_EAPD;
-else
-w->param.eapdbtl |= HDA_CMD_SET_EAPD_BTL_ENABLE_EAPD;
-if (orig != w->param.eapdbtl) {
-uint32_t val;
-
-if (hdac_eapd_switch[i].hp_switch != 0)
-hdac_hp_switch_handler(devinfo);
-val = w->param.eapdbtl;
-if (devinfo->function.audio.quirks & HDA_QUIRK_EAPDINV)
-val ^= HDA_CMD_SET_EAPD_BTL_ENABLE_EAPD;
-hdac_command(sc,
-HDA_CMD_SET_EAPD_BTL_ENABLE(devinfo->codec->cad,
-w->nid, val), devinfo->codec->cad);
-}
-hdac_unlock(sc);
-return (left | (left << 8));
-}
-if (dev == SOUND_MIXER_VOLUME)
-devinfo->function.audio.mvol = left | (right << 8);
-
-mlvol = devinfo->function.audio.mvol & 0x7f;
-mrvol = (devinfo->function.audio.mvol >> 8) & 0x7f;
-lvol = 0;
-rvol = 0;
-
-i = 0;
-while ((ctl = hdac_audio_ctl_each(devinfo, &i)) != NULL) {
-if (ctl->widget == NULL || ctl->enable == 0 ||
-!(ctl->ossmask & (1 << dev)))
-continue;
-switch (dev) {
-case SOUND_MIXER_VOLUME:
-lvol = ((ctl->ossval & 0x7f) * left) / 100;
-lvol = (lvol * ctl->step) / 100;
-rvol = (((ctl->ossval >> 8) & 0x7f) * right) / 100;
-rvol = (rvol * ctl->step) / 100;
-break;
-default:
-if (ctl->ossmask & SOUND_MASK_VOLUME) {
-lvol = (left * mlvol) / 100;
-lvol = (lvol * ctl->step) / 100;
-rvol = (right * mrvol) / 100;
-rvol = (rvol * ctl->step) / 100;
-} else {
-lvol = (left * ctl->step) / 100;
-rvol = (right * ctl->step) / 100;
-}
-ctl->ossval = left | (right << 8);
-break;
-}
-mute = 0;
-if (ctl->step < 1) {
-mute |= (left == 0) ? HDA_AMP_MUTE_LEFT :
-(ctl->muted & HDA_AMP_MUTE_LEFT);
-mute |= (right == 0) ? HDA_AMP_MUTE_RIGHT :
-(ctl->muted & HDA_AMP_MUTE_RIGHT);
-} else {
-mute |= (lvol == 0) ? HDA_AMP_MUTE_LEFT :
-(ctl->muted & HDA_AMP_MUTE_LEFT);
-mute |= (rvol == 0) ? HDA_AMP_MUTE_RIGHT :
-(ctl->muted & HDA_AMP_MUTE_RIGHT);
-}
-hdac_audio_ctl_amp_set(ctl, mute, lvol, rvol);
-}
-hdac_unlock(sc);
+ struct hdac_devinfo *devinfo = mix_getdevinfo(m);
+ struct hdac_softc *sc = devinfo->codec->sc;
+ struct hdac_widget *w;
+ struct hdac_audio_ctl *ctl;
+ uint32_t id, mute;
+ int lvol, rvol, mlvol, mrvol;
+ int i = 0;
+
+ hdac_lock(sc);
+ if (dev == SOUND_MIXER_OGAIN) {
+ uint32_t orig;
+ /*if (left != right || !(left == 0 || left == 1)) {
+ hdac_unlock(sc);
+ return (-1);
+ }*/
+ id = hdac_codec_id(devinfo);
+ for (i = 0; i < HDAC_EAPD_SWITCH_LEN; i++) {
+ if (HDA_DEV_MATCH(hdac_eapd_switch[i].model,
+ sc->pci_subvendor) &&
+ hdac_eapd_switch[i].id == id)
+ break;
+ }
+ if (i >= HDAC_EAPD_SWITCH_LEN) {
+ hdac_unlock(sc);
+ return (-1);
+ }
+ w = hdac_widget_get(devinfo, hdac_eapd_switch[i].eapdnid);
+ if (w == NULL ||
+ w->type != HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX ||
+ w->param.eapdbtl == HDAC_INVALID) {
+ hdac_unlock(sc);
+ return (-1);
+ }
+ orig = w->param.eapdbtl;
+ if (left == 0)
+ w->param.eapdbtl &= ~HDA_CMD_SET_EAPD_BTL_ENABLE_EAPD;
+ else
+ w->param.eapdbtl |= HDA_CMD_SET_EAPD_BTL_ENABLE_EAPD;
+ if (orig != w->param.eapdbtl) {
+ uint32_t val;
+
+ if (hdac_eapd_switch[i].hp_switch != 0)
+ hdac_hp_switch_handler(devinfo);
+ val = w->param.eapdbtl;
+ if (devinfo->function.audio.quirks & HDA_QUIRK_EAPDINV)
+ val ^= HDA_CMD_SET_EAPD_BTL_ENABLE_EAPD;
+ hdac_command(sc,
+ HDA_CMD_SET_EAPD_BTL_ENABLE(devinfo->codec->cad,
+ w->nid, val), devinfo->codec->cad);
+ }
+ hdac_unlock(sc);
+ return (left | (left << 8));
+ }
+ if (dev == SOUND_MIXER_VOLUME)
+ devinfo->function.audio.mvol = left | (right << 8);
+
+ mlvol = devinfo->function.audio.mvol & 0x7f;
+ mrvol = (devinfo->function.audio.mvol >> 8) & 0x7f;
+ lvol = 0;
+ rvol = 0;
+
+ i = 0;
+ while ((ctl = hdac_audio_ctl_each(devinfo, &i)) != NULL) {
+ if (ctl->widget == NULL || ctl->enable == 0 ||
+ !(ctl->ossmask & (1 << dev)))
+ continue;
+ switch (dev) {
+ case SOUND_MIXER_VOLUME:
+ lvol = ((ctl->ossval & 0x7f) * left) / 100;
+ lvol = (lvol * ctl->step) / 100;
+ rvol = (((ctl->ossval >> 8) & 0x7f) * right) / 100;
+ rvol = (rvol * ctl->step) / 100;
+ break;
+ default:
+ if (ctl->ossmask & SOUND_MASK_VOLUME) {
+ lvol = (left * mlvol) / 100;
+ lvol = (lvol * ctl->step) / 100;
+ rvol = (right * mrvol) / 100;
+ rvol = (rvol * ctl->step) / 100;
+ } else {
+ lvol = (left * ctl->step) / 100;
+ rvol = (right * ctl->step) / 100;
+ }
+ ctl->ossval = left | (right << 8);
+ break;
+ }
+ mute = 0;
+ if (ctl->step < 1) {
+ mute |= (left == 0) ? HDA_AMP_MUTE_LEFT :
+ (ctl->muted & HDA_AMP_MUTE_LEFT);
+ mute |= (right == 0) ? HDA_AMP_MUTE_RIGHT :
+ (ctl->muted & HDA_AMP_MUTE_RIGHT);
+ } else {
+ mute |= (lvol == 0) ? HDA_AMP_MUTE_LEFT :
+ (ctl->muted & HDA_AMP_MUTE_LEFT);
+ mute |= (rvol == 0) ? HDA_AMP_MUTE_RIGHT :
+ (ctl->muted & HDA_AMP_MUTE_RIGHT);
+ }
+ hdac_audio_ctl_amp_set(ctl, mute, lvol, rvol);
+ }
+ hdac_unlock(sc);
-return (left | (right << 8));
+ return (left | (right << 8));
}
static int
hdac_audio_ctl_ossmixer_setrecsrc(struct snd_mixer *m, uint32_t src)
{
-struct hdac_devinfo *devinfo = mix_getdevinfo(m);
-struct hdac_widget *w, *cw;
-struct hdac_softc *sc = devinfo->codec->sc;
-uint32_t ret = src, target;
-int i, j;
-
-target = 0;
-for (i = 0; i < SOUND_MIXER_NRDEVICES; i++) {
-if (src & (1 << i)) {
-target = 1 << i;
-break;
-}
-}
+ struct hdac_devinfo *devinfo = mix_getdevinfo(m);
+ struct hdac_widget *w, *cw;
+ struct hdac_softc *sc = devinfo->codec->sc;
+ uint32_t ret = src, target;
+ int i, j;
+
+ target = 0;
+ for (i = 0; i < SOUND_MIXER_NRDEVICES; i++) {
+ if (src & (1 << i)) {
+ target = 1 << i;
+ break;
+ }
+ }
+
+ hdac_lock(sc);
+
+ for (i = devinfo->startnode; i < devinfo->endnode; i++) {
+ w = hdac_widget_get(devinfo, i);
+ if (w == NULL || w->enable == 0)
+ continue;
+ if (!(w->pflags & HDA_ADC_RECSEL))
+ continue;
+ for (j = 0; j < w->nconns; j++) {
+ cw = hdac_widget_get(devinfo, w->conns[j]);
+ if (cw == NULL || cw->enable == 0)
+ continue;
+ if ((target == SOUND_MASK_VOLUME &&
+ cw->type !=
+ HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_MIXER) ||
+ (target != SOUND_MASK_VOLUME &&
+ cw->type ==
+ HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_MIXER))
+ continue;
+ if (cw->ctlflags & target) {
+ if (!(w->pflags & HDA_ADC_LOCKED))
+ hdac_widget_connection_select(w, j);
+ ret = target;
+ j += w->nconns;
+ }
+ }
+ }
-hdac_lock(sc);
-
-for (i = devinfo->startnode; i < devinfo->endnode; i++) {
-w = hdac_widget_get(devinfo, i);
-if (w == NULL || w->enable == 0)
-continue;
-if (!(w->pflags & HDA_ADC_RECSEL))
-continue;
-for (j = 0; j < w->nconns; j++) {
-cw = hdac_widget_get(devinfo, w->conns[j]);
-if (cw == NULL || cw->enable == 0)
-continue;
-if ((target == SOUND_MASK_VOLUME &&
-cw->type !=
-HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_MIXER) ||
-(target != SOUND_MASK_VOLUME &&
-cw->type ==
-HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_MIXER))
-continue;
-if (cw->ctlflags & target) {
-hdac_widget_connection_select(w, j);
-ret = target;
-j += w->nconns;
-}
-}
-}
+ hdac_unlock(sc);
-hdac_unlock(sc);
-
-return (ret);
+ return (ret);
}
static kobj_method_t hdac_audio_ctl_ossmixer_methods[] = {
-KOBJMETHOD(mixer_init, hdac_audio_ctl_ossmixer_init),
-KOBJMETHOD(mixer_set, hdac_audio_ctl_ossmixer_set),
-KOBJMETHOD(mixer_setrecsrc, hdac_audio_ctl_ossmixer_setrecsrc),
-{ 0, 0 }
+ KOBJMETHOD(mixer_init, hdac_audio_ctl_ossmixer_init),
+ KOBJMETHOD(mixer_set, hdac_audio_ctl_ossmixer_set),
+ KOBJMETHOD(mixer_setrecsrc, hdac_audio_ctl_ossmixer_setrecsrc),
+ { 0, 0 }
};
MIXER_DECLARE(hdac_audio_ctl_ossmixer);
+static void
+hdac_unsolq_task(void *context, int pending)
+{
+ struct hdac_softc *sc;
+
+ sc = (struct hdac_softc *)context;
+
+ hdac_lock(sc);
+ hdac_unsolq_flush(sc);
+ hdac_unlock(sc);
+}
+
/****************************************************************************
-* int hdac_attach(device_t)
-*
-* Attach the device into the kernel. Interrupts usually won't be enabled
-* when this function is called. Setup everything that doesn't require
-* interrupts and defer probing of codecs until interrupts are enabled.
-****************************************************************************/
+ * int hdac_attach(device_t)
+ *
+ * Attach the device into the kernel. Interrupts usually won't be enabled
+ * when this function is called. Setup everything that doesn't require
+ * interrupts and defer probing of codecs until interrupts are enabled.
+ ****************************************************************************/
static int
hdac_attach(device_t dev)
{
-struct hdac_softc *sc;
-int result;
-int i = 0;
-
-sc = malloc(sizeof(*sc), M_DEVBUF, M_NOWAIT | M_ZERO);
-if (sc == NULL) {
-device_printf(dev, "cannot allocate softcn");
-return (ENOMEM);
-}
-
-sc->lock = snd_mtxcreate(device_get_nameunit(dev), HDAC_MTX_NAME);
-if (sc->lock == NULL) {
-device_printf(dev, "mutex creation failedn");
-free(sc, M_DEVBUF);
-return (ENOMEM);
-}
-
-sc->dev = dev;
-sc->pci_subvendor = (uint32_t)pci_get_subdevice(sc->dev) << 16;
-sc->pci_subvendor |= (uint32_t)pci_get_subvendor(sc->dev) & 0x0000ffff;
-
-sc->chan_size = pcm_getbuffersize(dev,
-HDA_BUFSZ_MIN, HDA_BUFSZ_DEFAULT, HDA_BUFSZ_DEFAULT);
-if (resource_int_value(device_get_name(sc->dev),
-device_get_unit(sc->dev), "blocksize", &i) == 0 &&
-i > 0) {
-sc->chan_blkcnt = sc->chan_size / i;
-i = 0;
-while (sc->chan_blkcnt >> i)
-i++;
-sc->chan_blkcnt = 1 << (i - 1);
-if (sc->chan_blkcnt < HDA_BDL_MIN)
-sc->chan_blkcnt = HDA_BDL_MIN;
-else if (sc->chan_blkcnt > HDA_BDL_MAX)
-sc->chan_blkcnt = HDA_BDL_MAX;
-} else
-sc->chan_blkcnt = HDA_BDL_DEFAULT;
-
-result = bus_dma_tag_create(NULL, /* parent */
-HDAC_DMA_ALIGNMENT, /* alignment */
-0, /* boundary */
-BUS_SPACE_MAXADDR_32BIT, /* lowaddr */
-BUS_SPACE_MAXADDR, /* highaddr */
-NULL, /* filtfunc */
-NULL, /* fistfuncarg */
-sc->chan_size, /* maxsize */
-1, /* nsegments */
-sc->chan_size, /* maxsegsz */
-0, /* flags */
-NULL, /* lockfunc */
-NULL, /* lockfuncarg */
-&sc->chan_dmat); /* dmat */
-if (result != 0) {
-device_printf(sc->dev, "%s: bus_dma_tag_create failed (%x)n",
-__func__, result);
-snd_mtxfree(sc->lock);
-free(sc, M_DEVBUF);
-return (ENXIO);
-}
-
-
-sc->hdabus = NULL;
-for (i = 0; i < HDAC_CODEC_MAX; i++)
-sc->codecs[i] = NULL;
-
-pci_enable_busmaster(dev);
-
-/* Allocate resources */
-result = hdac_mem_alloc(sc);
-if (result != 0)
-goto hdac_attach_fail;
-result = hdac_irq_alloc(sc);
-if (result != 0)
-goto hdac_attach_fail;
-
-/* Get Capabilities */
-result = hdac_get_capabilities(sc);
-if (result != 0)
-goto hdac_attach_fail;
-
-/* Allocate CORB and RIRB dma memory */
-result = hdac_dma_alloc(sc, &sc->corb_dma,
-sc->corb_size * sizeof(uint32_t));
-if (result != 0)
-goto hdac_attach_fail;
-result = hdac_dma_alloc(sc, &sc->rirb_dma,
-sc->rirb_size * sizeof(struct hdac_rirb));
-if (result != 0)
-goto hdac_attach_fail;
-
-/* Quiesce everything */
-hdac_reset(sc);
-
-/* Disable PCI-Express QOS */
-pci_write_config(sc->dev, 0x44,
-pci_read_config(sc->dev, 0x44, 1) & 0xf8, 1);
-
-/* Initialize the CORB and RIRB */
-hdac_corb_init(sc);
-hdac_rirb_init(sc);
-
-/* Defer remaining of initialization until interrupts are enabled */
-sc->intrhook.ich_func = hdac_attach2;
-sc->intrhook.ich_arg = (void *)sc;
-if (cold == 0 || config_intrhook_establish(&sc->intrhook) != 0) {
-sc->intrhook.ich_func = NULL;
-hdac_attach2((void *)sc);
-}
+ struct hdac_softc *sc;
+ int result;
+ int i;
+ uint16_t vendor;
+ uint8_t v;
+
+ sc = malloc(sizeof(*sc), M_DEVBUF, M_WAITOK | M_ZERO);
+ sc->lock = snd_mtxcreate(device_get_nameunit(dev), HDAC_MTX_NAME);
+ sc->dev = dev;
+ sc->pci_subvendor = (uint32_t)pci_get_subdevice(sc->dev) << 16;
+ sc->pci_subvendor |= (uint32_t)pci_get_subvendor(sc->dev) & 0x0000ffff;
+ vendor = pci_get_vendor(dev);
+
+ if (sc->pci_subvendor == HP_NX6325_SUBVENDORX) {
+ /* Screw nx6325 - subdevice/subvendor swapped */
+ sc->pci_subvendor = HP_NX6325_SUBVENDOR;
+ }
+
+ callout_init(&sc->poll_hda, CALLOUT_MPSAFE);
+ callout_init(&sc->poll_hdac, CALLOUT_MPSAFE);
+ callout_init(&sc->poll_jack, CALLOUT_MPSAFE);
+
+ TASK_INIT(&sc->unsolq_task, 0, hdac_unsolq_task, sc);
+
+ sc->poll_ticks = 1;
+ sc->poll_ival = HDAC_POLL_INTERVAL;
+ if (resource_int_value(device_get_name(dev),
+ device_get_unit(dev), "polling", &i) == 0 && i != 0)
+ sc->polling = 1;
+ else
+ sc->polling = 0;
+
+ sc->chan_size = pcm_getbuffersize(dev,
+ HDA_BUFSZ_MIN, HDA_BUFSZ_DEFAULT, HDA_BUFSZ_MAX);
+
+ if (resource_int_value(device_get_name(dev),
+ device_get_unit(dev), "blocksize", &i) == 0 && i > 0) {
+ i &= HDA_BLK_ALIGN;
+ if (i < HDA_BLK_MIN)
+ i = HDA_BLK_MIN;
+ sc->chan_blkcnt = sc->chan_size / i;
+ i = 0;
+ while (sc->chan_blkcnt >> i)
+ i++;
+ sc->chan_blkcnt = 1 << (i - 1);
+ if (sc->chan_blkcnt < HDA_BDL_MIN)
+ sc->chan_blkcnt = HDA_BDL_MIN;
+ else if (sc->chan_blkcnt > HDA_BDL_MAX)
+ sc->chan_blkcnt = HDA_BDL_MAX;
+ } else
+ sc->chan_blkcnt = HDA_BDL_DEFAULT;
+
+ result = bus_dma_tag_create(NULL, /* parent */
+ HDAC_DMA_ALIGNMENT, /* alignment */
+ 0, /* boundary */
+ BUS_SPACE_MAXADDR_32BIT, /* lowaddr */
+ BUS_SPACE_MAXADDR, /* highaddr */
+ NULL, /* filtfunc */
+ NULL, /* fistfuncarg */
+ sc->chan_size, /* maxsize */
+ 1, /* nsegments */
+ sc->chan_size, /* maxsegsz */
+ 0, /* flags */
+ NULL, /* lockfunc */
+ NULL, /* lockfuncarg */
+ &sc->chan_dmat); /* dmat */
+ if (result != 0) {
+ device_printf(dev, "%s: bus_dma_tag_create failed (%x)\n",
+ __func__, result);
+ snd_mtxfree(sc->lock);
+ free(sc, M_DEVBUF);
+ return (ENXIO);
+ }
+
+
+ sc->hdabus = NULL;
+ for (i = 0; i < HDAC_CODEC_MAX; i++)
+ sc->codecs[i] = NULL;
+
+ pci_enable_busmaster(dev);
+
+ if (vendor == INTEL_VENDORID) {
+ /* TCSEL -> TC0 */
+ v = pci_read_config(dev, 0x44, 1);
+ pci_write_config(dev, 0x44, v & 0xf8, 1);
+ HDA_BOOTVERBOSE(
+ device_printf(dev, "TCSEL: 0x%02d -> 0x%02d\n", v,
+ pci_read_config(dev, 0x44, 1));
+ );
+ }
+
+#if __FreeBSD_version >= 602106
+ if (resource_int_value(device_get_name(dev),
+ device_get_unit(dev), "msi", &i) == 0 && i != 0 &&
+ pci_msi_count(dev) == 1)
+ sc->flags |= HDAC_F_MSI;
+ else
+#endif
+ sc->flags &= ~HDAC_F_MSI;
-return (0);
+#if defined(__i386__) || defined(__amd64__)
+ sc->flags |= HDAC_F_DMA_NOCACHE;
+
+ if (resource_int_value(device_get_name(dev),
+ device_get_unit(dev), "snoop", &i) == 0 && i != 0) {
+#else
+ sc->flags &= ~HDAC_F_DMA_NOCACHE;
+#endif
+ /*
+ * Try to enable PCIe snoop to avoid messing around with
+ * uncacheable DMA attribute. Since PCIe snoop register
+ * config is pretty much vendor specific, there are no
+ * general solutions on how to enable it, forcing us (even
+ * Microsoft) to enable uncacheable or write combined DMA
+ * by default.
+ *
+ * http://msdn2.microsoft.com/en-us/library/ms790324.aspx
+ */
+ for (i = 0; i < HDAC_PCIESNOOP_LEN; i++) {
+ if (hdac_pcie_snoop[i].vendor != vendor)
+ continue;
+ sc->flags &= ~HDAC_F_DMA_NOCACHE;
+ if (hdac_pcie_snoop[i].reg == 0x00)
+ break;
+ v = pci_read_config(dev, hdac_pcie_snoop[i].reg, 1);
+ if ((v & hdac_pcie_snoop[i].enable) ==
+ hdac_pcie_snoop[i].enable)
+ break;
+ v &= hdac_pcie_snoop[i].mask;
+ v |= hdac_pcie_snoop[i].enable;
+ pci_write_config(dev, hdac_pcie_snoop[i].reg, v, 1);
+ v = pci_read_config(dev, hdac_pcie_snoop[i].reg, 1);
+ if ((v & hdac_pcie_snoop[i].enable) !=
+ hdac_pcie_snoop[i].enable) {
+ HDA_BOOTVERBOSE(
+ device_printf(dev,
+ "WARNING: Failed to enable PCIe "
+ "snoop!\n");
+ );
+#if defined(__i386__) || defined(__amd64__)
+ sc->flags |= HDAC_F_DMA_NOCACHE;
+#endif
+ }
+ break;
+ }
+#if defined(__i386__) || defined(__amd64__)
+ }
+#endif
+
+ HDA_BOOTVERBOSE(
+ device_printf(dev, "DMA Coherency: %s / vendor=0x%04x\n",
+ (sc->flags & HDAC_F_DMA_NOCACHE) ?
+ "Uncacheable" : "PCIe snoop", vendor);
+ );
+
+ /* Allocate resources */
+ result = hdac_mem_alloc(sc);
+ if (result != 0)
+ goto hdac_attach_fail;
+ result = hdac_irq_alloc(sc);
+ if (result != 0)
+ goto hdac_attach_fail;
+
+ /* Get Capabilities */
+ result = hdac_get_capabilities(sc);
+ if (result != 0)
+ goto hdac_attach_fail;
+
+ /* Allocate CORB and RIRB dma memory */
+ result = hdac_dma_alloc(sc, &sc->corb_dma,
+ sc->corb_size * sizeof(uint32_t));
+ if (result != 0)
+ goto hdac_attach_fail;
+ result = hdac_dma_alloc(sc, &sc->rirb_dma,
+ sc->rirb_size * sizeof(struct hdac_rirb));
+ if (result != 0)
+ goto hdac_attach_fail;
+
+ /* Quiesce everything */
+ hdac_reset(sc);
+
+ /* Initialize the CORB and RIRB */
+ hdac_corb_init(sc);
+ hdac_rirb_init(sc);
+
+ /* Defer remaining of initialization until interrupts are enabled */
+ sc->intrhook.ich_func = hdac_attach2;
+ sc->intrhook.ich_arg = (void *)sc;
+ if (cold == 0 || config_intrhook_establish(&sc->intrhook) != 0) {
+ sc->intrhook.ich_func = NULL;
+ hdac_attach2((void *)sc);
+ }
+
+ return (0);
hdac_attach_fail:
-hdac_dma_free(&sc->rirb_dma);
-hdac_dma_free(&sc->corb_dma);
-hdac_irq_free(sc);
-hdac_mem_free(sc);
-snd_mtxfree(sc->lock);
-free(sc, M_DEVBUF);
+ hdac_irq_free(sc);
+ hdac_dma_free(sc, &sc->rirb_dma);
+ hdac_dma_free(sc, &sc->corb_dma);
+ hdac_mem_free(sc);
+ snd_mtxfree(sc->lock);
+ free(sc, M_DEVBUF);
-return (ENXIO);
+ return (ENXIO);
}
static void
hdac_audio_parse(struct hdac_devinfo *devinfo)
{
-struct hdac_softc *sc = devinfo->codec->sc;
-struct hdac_widget *w;
-uint32_t res;
-int i;
-nid_t cad, nid;
-
-cad = devinfo->codec->cad;
-nid = devinfo->nid;
-
-hdac_command(sc,
-HDA_CMD_SET_POWER_STATE(cad, nid, HDA_CMD_POWER_STATE_D0), cad);
-
-DELAY(100);
-
-res = hdac_command(sc,
-HDA_CMD_GET_PARAMETER(cad , nid, HDA_PARAM_SUB_NODE_COUNT), cad);
-
-devinfo->nodecnt = HDA_PARAM_SUB_NODE_COUNT_TOTAL(res);
-devinfo->startnode = HDA_PARAM_SUB_NODE_COUNT_START(res);
-devinfo->endnode = devinfo->startnode + devinfo->nodecnt;
-
-HDA_BOOTVERBOSE(
-device_printf(sc->dev, " Vendor: 0x%08xn",
-devinfo->vendor_id);
-device_printf(sc->dev, " Device: 0x%08xn",
-devinfo->device_id);
-device_printf(sc->dev, " Revision: 0x%08xn",
-devinfo->revision_id);
-device_printf(sc->dev, " Stepping: 0x%08xn",
-devinfo->stepping_id);
-device_printf(sc->dev, "PCI Subvendor: 0x%08xn",
-sc->pci_subvendor);
-device_printf(sc->dev, " Nodes: start=%d "
-"endnode=%d total=%dn",
-devinfo->startnode, devinfo->endnode, devinfo->nodecnt);
-);
-
-res = hdac_command(sc,
-HDA_CMD_GET_PARAMETER(cad, nid, HDA_PARAM_SUPP_STREAM_FORMATS),
-cad);
-devinfo->function.audio.supp_stream_formats = res;
-
-res = hdac_command(sc,
-HDA_CMD_GET_PARAMETER(cad, nid, HDA_PARAM_SUPP_PCM_SIZE_RATE),
-cad);
-devinfo->function.audio.supp_pcm_size_rate = res;
-
-res = hdac_command(sc,
-HDA_CMD_GET_PARAMETER(cad, nid, HDA_PARAM_OUTPUT_AMP_CAP),
-cad);
-devinfo->function.audio.outamp_cap = res;
-
-res = hdac_command(sc,
-HDA_CMD_GET_PARAMETER(cad, nid, HDA_PARAM_INPUT_AMP_CAP),
-cad);
-devinfo->function.audio.inamp_cap = res;
-
-if (devinfo->nodecnt > 0) {
-hdac_unlock(sc);
-devinfo->widget = (struct hdac_widget *)malloc(
-sizeof(*(devinfo->widget)) * devinfo->nodecnt, M_HDAC,
-M_NOWAIT | M_ZERO);
-hdac_lock(sc);
-} else
-devinfo->widget = NULL;
-
-if (devinfo->widget == NULL) {
-device_printf(sc->dev, "unable to allocate widgets!n");
-devinfo->endnode = devinfo->startnode;
-devinfo->nodecnt = 0;
-return;
-}
-
-for (i = devinfo->startnode; i < devinfo->endnode; i++) {
-w = hdac_widget_get(devinfo, i);
-if (w == NULL)
-device_printf(sc->dev, "Ghost widget! nid=%d!n", i);
-else {
-w->devinfo = devinfo;
-w->nid = i;
-w->enable = 1;
-w->selconn = -1;
-w->pflags = 0;
-w->ctlflags = 0;
-w->param.eapdbtl = HDAC_INVALID;
-hdac_widget_parse(w);
-}
-}
+ struct hdac_softc *sc = devinfo->codec->sc;
+ struct hdac_widget *w;
+ uint32_t res;
+ int i;
+ nid_t cad, nid;
+
+ cad = devinfo->codec->cad;
+ nid = devinfo->nid;
+
+ hdac_command(sc,
+ HDA_CMD_SET_POWER_STATE(cad, nid, HDA_CMD_POWER_STATE_D0), cad);
+
+ DELAY(100);
+
+ res = hdac_command(sc,
+ HDA_CMD_GET_PARAMETER(cad , nid, HDA_PARAM_SUB_NODE_COUNT), cad);
+
+ devinfo->nodecnt = HDA_PARAM_SUB_NODE_COUNT_TOTAL(res);
+ devinfo->startnode = HDA_PARAM_SUB_NODE_COUNT_START(res);
+ devinfo->endnode = devinfo->startnode + devinfo->nodecnt;
+
+ res = hdac_command(sc,
+ HDA_CMD_GET_PARAMETER(cad , nid, HDA_PARAM_GPIO_COUNT), cad);
+ devinfo->function.audio.gpio = res;
+
+ HDA_BOOTVERBOSE(
+ device_printf(sc->dev, " Vendor: 0x%08x\n",
+ devinfo->vendor_id);
+ device_printf(sc->dev, " Device: 0x%08x\n",
+ devinfo->device_id);
+ device_printf(sc->dev, " Revision: 0x%08x\n",
+ devinfo->revision_id);
+ device_printf(sc->dev, " Stepping: 0x%08x\n",
+ devinfo->stepping_id);
+ device_printf(sc->dev, "PCI Subvendor: 0x%08x\n",
+ sc->pci_subvendor);
+ device_printf(sc->dev, " Nodes: start=%d "
+ "endnode=%d total=%d\n",
+ devinfo->startnode, devinfo->endnode, devinfo->nodecnt);
+ device_printf(sc->dev, " CORB size: %d\n", sc->corb_size);
+ device_printf(sc->dev, " RIRB size: %d\n", sc->rirb_size);
+ device_printf(sc->dev, " Streams: ISS=%d OSS=%d BSS=%d\n",
+ sc->num_iss, sc->num_oss, sc->num_bss);
+ device_printf(sc->dev, " GPIO: 0x%08x\n",
+ devinfo->function.audio.gpio);
+ device_printf(sc->dev, " NumGPIO=%d NumGPO=%d "
+ "NumGPI=%d GPIWake=%d GPIUnsol=%d\n",
+ HDA_PARAM_GPIO_COUNT_NUM_GPIO(devinfo->function.audio.gpio),
+ HDA_PARAM_GPIO_COUNT_NUM_GPO(devinfo->function.audio.gpio),
+ HDA_PARAM_GPIO_COUNT_NUM_GPI(devinfo->function.audio.gpio),
+ HDA_PARAM_GPIO_COUNT_GPI_WAKE(devinfo->function.audio.gpio),
+ HDA_PARAM_GPIO_COUNT_GPI_UNSOL(devinfo->function.audio.gpio));
+ );
+
+ res = hdac_command(sc,
+ HDA_CMD_GET_PARAMETER(cad, nid, HDA_PARAM_SUPP_STREAM_FORMATS),
+ cad);
+ devinfo->function.audio.supp_stream_formats = res;
+
+ res = hdac_command(sc,
+ HDA_CMD_GET_PARAMETER(cad, nid, HDA_PARAM_SUPP_PCM_SIZE_RATE),
+ cad);
+ devinfo->function.audio.supp_pcm_size_rate = res;
+
+ res = hdac_command(sc,
+ HDA_CMD_GET_PARAMETER(cad, nid, HDA_PARAM_OUTPUT_AMP_CAP),
+ cad);
+ devinfo->function.audio.outamp_cap = res;
+
+ res = hdac_command(sc,
+ HDA_CMD_GET_PARAMETER(cad, nid, HDA_PARAM_INPUT_AMP_CAP),
+ cad);
+ devinfo->function.audio.inamp_cap = res;
+
+ if (devinfo->nodecnt > 0)
+ devinfo->widget = (struct hdac_widget *)malloc(
+ sizeof(*(devinfo->widget)) * devinfo->nodecnt, M_HDAC,
+ M_NOWAIT | M_ZERO);
+ else
+ devinfo->widget = NULL;
+
+ if (devinfo->widget == NULL) {
+ device_printf(sc->dev, "unable to allocate widgets!\n");
+ devinfo->endnode = devinfo->startnode;
+ devinfo->nodecnt = 0;
+ return;
+ }
+
+ for (i = devinfo->startnode; i < devinfo->endnode; i++) {
+ w = hdac_widget_get(devinfo, i);
+ if (w == NULL)
+ device_printf(sc->dev, "Ghost widget! nid=%d!\n", i);
+ else {
+ w->devinfo = devinfo;
+ w->nid = i;
+ w->enable = 1;
+ w->selconn = -1;
+ w->pflags = 0;
+ w->ctlflags = 0;
+ w->param.eapdbtl = HDAC_INVALID;
+ hdac_widget_parse(w);
+ }
+ }
}
static void
hdac_audio_ctl_parse(struct hdac_devinfo *devinfo)
{
-struct hdac_softc *sc = devinfo->codec->sc;
-struct hdac_audio_ctl *ctls;
-struct hdac_widget *w, *cw;
-int i, j, cnt, max, ocap, icap;
-int mute, offset, step, size;
-
-/* XXX This is redundant */
-max = 0;
-for (i = devinfo->startnode; i < devinfo->endnode; i++) {
-w = hdac_widget_get(devinfo, i);
-if (w == NULL || w->enable == 0)
-continue;
-if (w->param.outamp_cap != 0)
-max++;
-if (w->param.inamp_cap != 0) {
-switch (w->type) {
-case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_SELECTOR:
-case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_MIXER:
-for (j = 0; j < w->nconns; j++) {
-cw = hdac_widget_get(devinfo,
-w->conns[j]);
-if (cw == NULL || cw->enable == 0)
-continue;
-max++;
-}
-break;
-default:
-max++;
-break;
-}
-}
-}
-
-devinfo->function.audio.ctlcnt = max;
-
-if (max < 1)
-return;
-
-hdac_unlock(sc);
-ctls = (struct hdac_audio_ctl *)malloc(
-sizeof(*ctls) * max, M_HDAC, M_ZERO | M_NOWAIT);
-hdac_lock(sc);
-
-if (ctls == NULL) {
-/* Blekh! */
-device_printf(sc->dev, "unable to allocate ctls!n");
-devinfo->function.audio.ctlcnt = 0;
-return;
-}
-
-cnt = 0;
-for (i = devinfo->startnode; cnt < max && i < devinfo->endnode; i++) {
-if (cnt >= max) {
-device_printf(sc->dev, "%s: Ctl overflow!n",
-__func__);
-break;
-}
-w = hdac_widget_get(devinfo, i);
-if (w == NULL || w->enable == 0)
-continue;
-ocap = w->param.outamp_cap;
-icap = w->param.inamp_cap;
-if (ocap != 0) {
-mute = HDA_PARAM_OUTPUT_AMP_CAP_MUTE_CAP(ocap);
-step = HDA_PARAM_OUTPUT_AMP_CAP_NUMSTEPS(ocap);
-size = HDA_PARAM_OUTPUT_AMP_CAP_STEPSIZE(ocap);
-offset = HDA_PARAM_OUTPUT_AMP_CAP_OFFSET(ocap);
-/*if (offset > step) {
-HDA_BOOTVERBOSE(
-device_printf(sc->dev,
-"HDA_DEBUG: BUGGY outamp: nid=%d "
-"[offset=%d > step=%d]n",
-w->nid, offset, step);
-);
-offset = step;
-}*/
-ctls[cnt].enable = 1;
-ctls[cnt].widget = w;
-ctls[cnt].mute = mute;
-ctls[cnt].step = step;
-ctls[cnt].size = size;
-ctls[cnt].offset = offset;
-ctls[cnt].left = offset;
-ctls[cnt].right = offset;
-ctls[cnt++].dir = HDA_CTL_OUT;
-}
-
-if (icap != 0) {
-mute = HDA_PARAM_OUTPUT_AMP_CAP_MUTE_CAP(icap);
-step = HDA_PARAM_OUTPUT_AMP_CAP_NUMSTEPS(icap);
-size = HDA_PARAM_OUTPUT_AMP_CAP_STEPSIZE(icap);
-offset = HDA_PARAM_OUTPUT_AMP_CAP_OFFSET(icap);
-/*if (offset > step) {
-HDA_BOOTVERBOSE(
-device_printf(sc->dev,
-"HDA_DEBUG: BUGGY inamp: nid=%d "
-"[offset=%d > step=%d]n",
-w->nid, offset, step);
-);
-offset = step;
-}*/
-switch (w->type) {
-case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_SELECTOR:
-case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_MIXER:
-for (j = 0; j < w->nconns; j++) {
-if (cnt >= max) {
-device_printf(sc->dev,
-"%s: Ctl overflow!n",
-__func__);
-break;
-}
-cw = hdac_widget_get(devinfo,
-w->conns[j]);
-if (cw == NULL || cw->enable == 0)
-continue;
-ctls[cnt].enable = 1;
-ctls[cnt].widget = w;
-ctls[cnt].childwidget = cw;
-ctls[cnt].index = j;
-ctls[cnt].mute = mute;
-ctls[cnt].step = step;
-ctls[cnt].size = size;
-ctls[cnt].offset = offset;
-ctls[cnt].left = offset;
-ctls[cnt].right = offset;
-ctls[cnt++].dir = HDA_CTL_IN;
-}
-break;
-default:
-if (cnt >= max) {
-device_printf(sc->dev,
-"%s: Ctl overflow!n",
-__func__);
-break;
-}
-ctls[cnt].enable = 1;
-ctls[cnt].widget = w;
-ctls[cnt].mute = mute;
-ctls[cnt].step = step;
-ctls[cnt].size = size;
-ctls[cnt].offset = offset;
-ctls[cnt].left = offset;
-ctls[cnt].right = offset;
-ctls[cnt++].dir = HDA_CTL_IN;
-break;
-}
-}
-}
+ struct hdac_softc *sc = devinfo->codec->sc;
+ struct hdac_audio_ctl *ctls;
+ struct hdac_widget *w, *cw;
+ int i, j, cnt, max, ocap, icap;
+ int mute, offset, step, size;
+
+ /* XXX This is redundant */
+ max = 0;
+ for (i = devinfo->startnode; i < devinfo->endnode; i++) {
+ w = hdac_widget_get(devinfo, i);
+ if (w == NULL || w->enable == 0)
+ continue;
+ if (w->param.outamp_cap != 0)
+ max++;
+ if (w->param.inamp_cap != 0) {
+ switch (w->type) {
+ case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_SELECTOR:
+ case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_MIXER:
+ for (j = 0; j < w->nconns; j++) {
+ cw = hdac_widget_get(devinfo,
+ w->conns[j]);
+ if (cw == NULL || cw->enable == 0)
+ continue;
+ max++;
+ }
+ break;
+ default:
+ max++;
+ break;
+ }
+ }
+ }
+
+ devinfo->function.audio.ctlcnt = max;
+
+ if (max < 1)
+ return;
+
+ ctls = (struct hdac_audio_ctl *)malloc(
+ sizeof(*ctls) * max, M_HDAC, M_ZERO | M_NOWAIT);
+
+ if (ctls == NULL) {
+ /* Blekh! */
+ device_printf(sc->dev, "unable to allocate ctls!\n");
+ devinfo->function.audio.ctlcnt = 0;
+ return;
+ }
+
+ cnt = 0;
+ for (i = devinfo->startnode; cnt < max && i < devinfo->endnode; i++) {
+ if (cnt >= max) {
+ device_printf(sc->dev, "%s: Ctl overflow!\n",
+ __func__);
+ break;
+ }
+ w = hdac_widget_get(devinfo, i);
+ if (w == NULL || w->enable == 0)
+ continue;
+ ocap = w->param.outamp_cap;
+ icap = w->param.inamp_cap;
+ if (ocap != 0) {
+ mute = HDA_PARAM_OUTPUT_AMP_CAP_MUTE_CAP(ocap);
+ step = HDA_PARAM_OUTPUT_AMP_CAP_NUMSTEPS(ocap);
+ size = HDA_PARAM_OUTPUT_AMP_CAP_STEPSIZE(ocap);
+ offset = HDA_PARAM_OUTPUT_AMP_CAP_OFFSET(ocap);
+ /*if (offset > step) {
+ HDA_BOOTVERBOSE(
+ device_printf(sc->dev,
+ "HDA_DEBUG: BUGGY outamp: nid=%d "
+ "[offset=%d > step=%d]\n",
+ w->nid, offset, step);
+ );
+ offset = step;
+ }*/
+ ctls[cnt].enable = 1;
+ ctls[cnt].widget = w;
+ ctls[cnt].mute = mute;
+ ctls[cnt].step = step;
+ ctls[cnt].size = size;
+ ctls[cnt].offset = offset;
+ ctls[cnt].left = offset;
+ ctls[cnt].right = offset;
+ ctls[cnt++].dir = HDA_CTL_OUT;
+ }
+
+ if (icap != 0) {
+ mute = HDA_PARAM_OUTPUT_AMP_CAP_MUTE_CAP(icap);
+ step = HDA_PARAM_OUTPUT_AMP_CAP_NUMSTEPS(icap);
+ size = HDA_PARAM_OUTPUT_AMP_CAP_STEPSIZE(icap);
+ offset = HDA_PARAM_OUTPUT_AMP_CAP_OFFSET(icap);
+ /*if (offset > step) {
+ HDA_BOOTVERBOSE(
+ device_printf(sc->dev,
+ "HDA_DEBUG: BUGGY inamp: nid=%d "
+ "[offset=%d > step=%d]\n",
+ w->nid, offset, step);
+ );
+ offset = step;
+ }*/
+ switch (w->type) {
+ case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_SELECTOR:
+ case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_MIXER:
+ for (j = 0; j < w->nconns; j++) {
+ if (cnt >= max) {
+ device_printf(sc->dev,
+ "%s: Ctl overflow!\n",
+ __func__);
+ break;
+ }
+ cw = hdac_widget_get(devinfo,
+ w->conns[j]);
+ if (cw == NULL || cw->enable == 0)
+ continue;
+ ctls[cnt].enable = 1;
+ ctls[cnt].widget = w;
+ ctls[cnt].childwidget = cw;
+ ctls[cnt].index = j;
+ ctls[cnt].mute = mute;
+ ctls[cnt].step = step;
+ ctls[cnt].size = size;
+ ctls[cnt].offset = offset;
+ ctls[cnt].left = offset;
+ ctls[cnt].right = offset;
+ ctls[cnt++].dir = HDA_CTL_IN;
+ }
+ break;
+ default:
+ if (cnt >= max) {
+ device_printf(sc->dev,
+ "%s: Ctl overflow!\n",
+ __func__);
+ break;
+ }
+ ctls[cnt].enable = 1;
+ ctls[cnt].widget = w;
+ ctls[cnt].mute = mute;
+ ctls[cnt].step = step;
+ ctls[cnt].size = size;
+ ctls[cnt].offset = offset;
+ ctls[cnt].left = offset;
+ ctls[cnt].right = offset;
+ ctls[cnt++].dir = HDA_CTL_IN;
+ break;
+ }
+ }
+ }
-devinfo->function.audio.ctl = ctls;
+ devinfo->function.audio.ctl = ctls;
}
static const struct {
-uint32_t model;
-uint32_t id;
-uint32_t set, unset;
+ uint32_t model;
+ uint32_t id;
+ uint32_t set, unset;
} hdac_quirks[] = {
-/*
-* XXX Fixed rate quirk. Other than 48000
-* sounds pretty much like train wreck.
-*
-* XXX Force stereo quirk. Monoural recording / playback
-* on few codecs (especially ALC880) seems broken or
-* perhaps unsupported.
-*/
-{ HDA_MATCH_ALL, HDA_MATCH_ALL,
-HDA_QUIRK_FIXEDRATE | HDA_QUIRK_FORCESTEREO, 0 },
-{ ACER_ALL_SUBVENDOR, HDA_MATCH_ALL,
-HDA_QUIRK_GPIO1, 0 },
-{ ASUS_M5200_SUBVENDOR, HDA_CODEC_ALC880,
-HDA_QUIRK_GPIO1, 0 },
-{ ASUS_U5F_SUBVENDOR, HDA_CODEC_AD1986A,
-HDA_QUIRK_EAPDINV, 0 },
-{ ASUS_A8JC_SUBVENDOR, HDA_CODEC_AD1986A,
-HDA_QUIRK_EAPDINV, 0 },
-{ HDA_MATCH_ALL, HDA_CODEC_CXVENICE,
-0, HDA_QUIRK_FORCESTEREO },
-{ HDA_MATCH_ALL, HDA_CODEC_STACXXXX,
-HDA_QUIRK_SOFTPCMVOL, 0 }
+ /*
+ * XXX Force stereo quirk. Monoural recording / playback
+ * on few codecs (especially ALC880) seems broken or
+ * perhaps unsupported.
+ */
+ { HDA_MATCH_ALL, HDA_MATCH_ALL,
+ HDA_QUIRK_FORCESTEREO | HDA_QUIRK_IVREF, 0 },
+ { ACER_ALL_SUBVENDOR, HDA_MATCH_ALL,
+ HDA_QUIRK_GPIO0, 0 },
+ { ASUS_M5200_SUBVENDOR, HDA_CODEC_ALC880,
+ HDA_QUIRK_GPIO0, 0 },
+ { ASUS_A7M_SUBVENDOR, HDA_CODEC_ALC880,
+ HDA_QUIRK_GPIO0, 0 },
+ { ASUS_A7T_SUBVENDOR, HDA_CODEC_ALC882,
+ HDA_QUIRK_GPIO0, 0 },
+ { ASUS_W2J_SUBVENDOR, HDA_CODEC_ALC882,
+ HDA_QUIRK_GPIO0, 0 },
+ { ASUS_U5F_SUBVENDOR, HDA_CODEC_AD1986A,
+ HDA_QUIRK_EAPDINV, 0 },
+ { ASUS_A8JC_SUBVENDOR, HDA_CODEC_AD1986A,
+ HDA_QUIRK_EAPDINV, 0 },
+ { ASUS_F3JC_SUBVENDOR, HDA_CODEC_ALC861,
+ HDA_QUIRK_OVREF, 0 },
+ { ASUS_W6F_SUBVENDOR, HDA_CODEC_ALC861,
+ HDA_QUIRK_OVREF, 0 },
+ { UNIWILL_9075_SUBVENDOR, HDA_CODEC_ALC861,
+ HDA_QUIRK_OVREF, 0 },
+ /*{ ASUS_M2N_SUBVENDOR, HDA_CODEC_AD1988,
+ HDA_QUIRK_IVREF80, HDA_QUIRK_IVREF50 | HDA_QUIRK_IVREF100 },*/
+ { MEDION_MD95257_SUBVENDOR, HDA_CODEC_ALC880,
+ HDA_QUIRK_GPIO1, 0 },
+ { LENOVO_3KN100_SUBVENDOR, HDA_CODEC_AD1986A,
+ HDA_QUIRK_EAPDINV, 0 },
+ { SAMSUNG_Q1_SUBVENDOR, HDA_CODEC_AD1986A,
+ HDA_QUIRK_EAPDINV, 0 },
+ { APPLE_MB3_SUBVENDOR, HDA_CODEC_ALC885,
+ HDA_QUIRK_GPIO0 | HDA_QUIRK_OVREF50, 0},
+ { APPLE_INTEL_MAC, HDA_CODEC_STAC9221,
+ HDA_QUIRK_GPIO0 | HDA_QUIRK_GPIO1, 0 },
+ { HDA_MATCH_ALL, HDA_CODEC_AD1988,
+ HDA_QUIRK_IVREF80, HDA_QUIRK_IVREF50 | HDA_QUIRK_IVREF100 },
+ { HDA_MATCH_ALL, HDA_CODEC_AD1988B,
+ HDA_QUIRK_IVREF80, HDA_QUIRK_IVREF50 | HDA_QUIRK_IVREF100 },
+ { HDA_MATCH_ALL, HDA_CODEC_CXVENICE,
+ 0, HDA_QUIRK_FORCESTEREO },
+ { HDA_MATCH_ALL, HDA_CODEC_STACXXXX,
+ HDA_QUIRK_SOFTPCMVOL, 0 }
};
#define HDAC_QUIRKS_LEN (sizeof(hdac_quirks) / sizeof(hdac_quirks[0]))
static void
hdac_vendor_patch_parse(struct hdac_devinfo *devinfo)
{
-struct hdac_widget *w;
-uint32_t id, subvendor;
-int i;
-
-id = hdac_codec_id(devinfo);
-subvendor = devinfo->codec->sc->pci_subvendor;
-
-/*
-* Quirks
-*/
-for (i = 0; i < HDAC_QUIRKS_LEN; i++) {
-if (!(HDA_DEV_MATCH(hdac_quirks[i].model, subvendor) &&
-HDA_DEV_MATCH(hdac_quirks[i].id, id)))
-continue;
-if (hdac_quirks[i].set != 0)
-devinfo->function.audio.quirks |=
-hdac_quirks[i].set;
-if (hdac_quirks[i].unset != 0)
-devinfo->function.audio.quirks &=
-~(hdac_quirks[i].unset);
-}
-
-switch (id) {
-case HDA_CODEC_ALC260:
-for (i = devinfo->startnode; i < devinfo->endnode; i++) {
-w = hdac_widget_get(devinfo, i);
-if (w == NULL || w->enable == 0)
-continue;
-if (w->type !=
-HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_INPUT)
-continue;
-if (w->nid != 5)
-w->enable = 0;
-}
-break;
-case HDA_CODEC_ALC880:
-for (i = devinfo->startnode; i < devinfo->endnode; i++) {
-w = hdac_widget_get(devinfo, i);
-if (w == NULL || w->enable == 0)
-continue;
-if (w->type ==
-HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_INPUT &&
-w->nid != 9 && w->nid != 29) {
-w->enable = 0;
-} else if (w->type !=
-HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_BEEP_WIDGET &&
-w->nid == 29) {
-w->type =
-HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_BEEP_WIDGET;
-w->param.widget_cap &=
-~HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_MASK;
-w->param.widget_cap |=
-HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_BEEP_WIDGET <<
-HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_SHIFT;
-strlcpy(w->name, "beep widget", sizeof(w->name));
-}
-}
-break;
-case HDA_CODEC_AD1981HD:
-w = hdac_widget_get(devinfo, 11);
-if (w != NULL && w->enable != 0 && w->nconns > 3)
-w->selconn = 3;
-if (subvendor == IBM_M52_SUBVENDOR) {
-struct hdac_audio_ctl *ctl;
-
-ctl = hdac_audio_ctl_amp_get(devinfo, 7, 0, 1);
-if (ctl != NULL)
-ctl->ossmask = SOUND_MASK_SPEAKER;
-}
-break;
-case HDA_CODEC_AD1986A:
-for (i = devinfo->startnode; i < devinfo->endnode; i++) {
-w = hdac_widget_get(devinfo, i);
-if (w == NULL || w->enable == 0)
-continue;
-if (w->type !=
-HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_OUTPUT)
-continue;
-if (w->nid != 3)
-w->enable = 0;
-}
-break;
-case HDA_CODEC_STAC9221:
-for (i = devinfo->startnode; i < devinfo->endnode; i++) {
-w = hdac_widget_get(devinfo, i);
-if (w == NULL || w->enable == 0)
-continue;
-if (w->type !=
-HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_OUTPUT)
-continue;
-if (w->nid != 2)
-w->enable = 0;
-}
-break;
-case HDA_CODEC_STAC9221D:
-for (i = devinfo->startnode; i < devinfo->endnode; i++) {
-w = hdac_widget_get(devinfo, i);
-if (w == NULL || w->enable == 0)
-continue;
-if (w->type ==
-HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_INPUT &&
-w->nid != 6)
-w->enable = 0;
-
-}
-break;
-default:
-break;
-}
+ struct hdac_widget *w;
+ struct hdac_audio_ctl *ctl;
+ uint32_t id, subvendor;
+ int i;
+
+ id = hdac_codec_id(devinfo);
+ subvendor = devinfo->codec->sc->pci_subvendor;
+
+ /*
+ * Quirks
+ */
+ for (i = 0; i < HDAC_QUIRKS_LEN; i++) {
+ if (!(HDA_DEV_MATCH(hdac_quirks[i].model, subvendor) &&
+ HDA_DEV_MATCH(hdac_quirks[i].id, id)))
+ continue;
+ if (hdac_quirks[i].set != 0)
+ devinfo->function.audio.quirks |=
+ hdac_quirks[i].set;
+ if (hdac_quirks[i].unset != 0)
+ devinfo->function.audio.quirks &=
+ ~(hdac_quirks[i].unset);
+ }
+
+ switch (id) {
+ case HDA_CODEC_ALC260:
+ for (i = devinfo->startnode; i < devinfo->endnode; i++) {
+ w = hdac_widget_get(devinfo, i);
+ if (w == NULL || w->enable == 0)
+ continue;
+ if (w->type !=
+ HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_INPUT)
+ continue;
+ if (w->nid != 5)
+ w->enable = 0;
+ }
+ if (subvendor == HP_XW4300_SUBVENDOR) {
+ ctl = hdac_audio_ctl_amp_get(devinfo, 16, 0, 1);
+ if (ctl != NULL && ctl->widget != NULL) {
+ ctl->ossmask = SOUND_MASK_SPEAKER;
+ ctl->widget->ctlflags |= SOUND_MASK_SPEAKER;
+ }
+ ctl = hdac_audio_ctl_amp_get(devinfo, 17, 0, 1);
+ if (ctl != NULL && ctl->widget != NULL) {
+ ctl->ossmask = SOUND_MASK_SPEAKER;
+ ctl->widget->ctlflags |= SOUND_MASK_SPEAKER;
+ }
+ } else if (subvendor == HP_3010_SUBVENDOR) {
+ ctl = hdac_audio_ctl_amp_get(devinfo, 17, 0, 1);
+ if (ctl != NULL && ctl->widget != NULL) {
+ ctl->ossmask = SOUND_MASK_SPEAKER;
+ ctl->widget->ctlflags |= SOUND_MASK_SPEAKER;
+ }
+ ctl = hdac_audio_ctl_amp_get(devinfo, 21, 0, 1);
+ if (ctl != NULL && ctl->widget != NULL) {
+ ctl->ossmask = SOUND_MASK_SPEAKER;
+ ctl->widget->ctlflags |= SOUND_MASK_SPEAKER;
+ }
+ }
+ break;
+ case HDA_CODEC_ALC262:
+ if (subvendor == HP_DC7700S_SUBVENDOR) {
+ ctl = hdac_audio_ctl_amp_get(devinfo, 21, 0, 1);
+ if (ctl != NULL && ctl->widget != NULL) {
+ ctl->ossmask = SOUND_MASK_PHONEOUT;
+ ctl->widget->ctlflags |= SOUND_MASK_PHONEOUT;
+ }
+ ctl = hdac_audio_ctl_amp_get(devinfo, 22, 0, 1);
+ if (ctl != NULL && ctl->widget != NULL) {
+ ctl->ossmask = SOUND_MASK_SPEAKER;
+ ctl->widget->ctlflags |= SOUND_MASK_SPEAKER;
+ }
+ } else if (subvendor == HP_DC7700_SUBVENDOR) {
+ ctl = hdac_audio_ctl_amp_get(devinfo, 22, 0, 1);
+ if (ctl != NULL && ctl->widget != NULL) {
+ ctl->ossmask = SOUND_MASK_SPEAKER;
+ ctl->widget->ctlflags |= SOUND_MASK_SPEAKER;
+ }
+ ctl = hdac_audio_ctl_amp_get(devinfo, 27, 0, 1);
+ if (ctl != NULL && ctl->widget != NULL) {
+ ctl->ossmask = SOUND_MASK_SPEAKER;
+ ctl->widget->ctlflags |= SOUND_MASK_SPEAKER;
+ }
+ }
+ break;
+ case HDA_CODEC_ALC268:
+ if (HDA_DEV_MATCH(ACER_ALL_SUBVENDOR, subvendor)) {
+ w = hdac_widget_get(devinfo, 29);
+ if (w != NULL) {
+ w->enable = 1;
+ w->type =
+ HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_BEEP_WIDGET;
+ w->param.widget_cap &=
+ ~HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_MASK;
+ w->param.widget_cap |=
+ HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_BEEP_WIDGET <<
+ HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_SHIFT;
+ strlcpy(w->name, "beep widget", sizeof(w->name));
+ }
+ }
+ break;
+ case HDA_CODEC_ALC861:
+ ctl = hdac_audio_ctl_amp_get(devinfo, 21, 2, 1);
+ if (ctl != NULL)
+ ctl->muted = HDA_AMP_MUTE_ALL;
+ break;
+ case HDA_CODEC_ALC880:
+ for (i = devinfo->startnode; i < devinfo->endnode; i++) {
+ w = hdac_widget_get(devinfo, i);
+ if (w == NULL || w->enable == 0)
+ continue;
+ if (w->type ==
+ HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_INPUT &&
+ w->nid != 9 && w->nid != 29) {
+ w->enable = 0;
+ } else if (w->type !=
+ HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_BEEP_WIDGET &&
+ w->nid == 29) {
+ w->type =
+ HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_BEEP_WIDGET;
+ w->param.widget_cap &=
+ ~HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_MASK;
+ w->param.widget_cap |=
+ HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_BEEP_WIDGET <<
+ HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_SHIFT;
+ strlcpy(w->name, "beep widget", sizeof(w->name));
+ }
+ }
+ break;
+ case HDA_CODEC_ALC883:
+ /*
+ * nid: 24/25 = External (jack) or Internal (fixed) Mic.
+ * Clear vref cap for jack connectivity.
+ */
+ w = hdac_widget_get(devinfo, 24);
+ if (w != NULL && w->enable != 0 && w->type ==
+ HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX &&
+ (w->wclass.pin.config &
+ HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK) ==
+ HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_JACK)
+ w->wclass.pin.cap &= ~(
+ HDA_PARAM_PIN_CAP_VREF_CTRL_100_MASK |
+ HDA_PARAM_PIN_CAP_VREF_CTRL_80_MASK |
+ HDA_PARAM_PIN_CAP_VREF_CTRL_50_MASK);
+ w = hdac_widget_get(devinfo, 25);
+ if (w != NULL && w->enable != 0 && w->type ==
+ HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX &&
+ (w->wclass.pin.config &
+ HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK) ==
+ HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_JACK)
+ w->wclass.pin.cap &= ~(
+ HDA_PARAM_PIN_CAP_VREF_CTRL_100_MASK |
+ HDA_PARAM_PIN_CAP_VREF_CTRL_80_MASK |
+ HDA_PARAM_PIN_CAP_VREF_CTRL_50_MASK);
+ /*
+ * nid: 26 = Line-in, leave it alone.
+ */
+ break;
+ case HDA_CODEC_AD1981HD:
+ w = hdac_widget_get(devinfo, 11);
+ if (w != NULL && w->enable != 0 && w->nconns > 3)
+ w->selconn = 3;
+ if (subvendor == IBM_M52_SUBVENDOR) {
+ ctl = hdac_audio_ctl_amp_get(devinfo, 7, 0, 1);
+ if (ctl != NULL)
+ ctl->ossmask = SOUND_MASK_SPEAKER;
+ }
+ break;
+ case HDA_CODEC_AD1986A:
+ for (i = devinfo->startnode; i < devinfo->endnode; i++) {
+ w = hdac_widget_get(devinfo, i);
+ if (w == NULL || w->enable == 0)
+ continue;
+ if (w->type !=
+ HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_OUTPUT)
+ continue;
+ if (w->nid != 3)
+ w->enable = 0;
+ }
+ if (subvendor == ASUS_M2NPVMX_SUBVENDOR ||
+ subvendor == ASUS_A8NVMCSM_SUBVENDOR) {
+ /* nid 28 is mic, nid 29 is line-in */
+ w = hdac_widget_get(devinfo, 15);
+ if (w != NULL)
+ w->selconn = 2;
+ w = hdac_widget_get(devinfo, 16);
+ if (w != NULL)
+ w->selconn = 1;
+ }
+ break;
+ case HDA_CODEC_AD1988:
+ case HDA_CODEC_AD1988B:
+ /*w = hdac_widget_get(devinfo, 12);
+ if (w != NULL) {
+ w->selconn = 1;
+ w->pflags |= HDA_ADC_LOCKED;
+ }
+ w = hdac_widget_get(devinfo, 13);
+ if (w != NULL) {
+ w->selconn = 4;
+ w->pflags |= HDA_ADC_LOCKED;
+ }
+ w = hdac_widget_get(devinfo, 14);
+ if (w != NULL) {
+ w->selconn = 2;
+ w->pflags |= HDA_ADC_LOCKED;
+ }*/
+ ctl = hdac_audio_ctl_amp_get(devinfo, 57, 0, 1);
+ if (ctl != NULL) {
+ ctl->ossmask = SOUND_MASK_IGAIN;
+ ctl->widget->ctlflags |= SOUND_MASK_IGAIN;
+ }
+ ctl = hdac_audio_ctl_amp_get(devinfo, 58, 0, 1);
+ if (ctl != NULL) {
+ ctl->ossmask = SOUND_MASK_IGAIN;
+ ctl->widget->ctlflags |= SOUND_MASK_IGAIN;
+ }
+ ctl = hdac_audio_ctl_amp_get(devinfo, 60, 0, 1);
+ if (ctl != NULL) {
+ ctl->ossmask = SOUND_MASK_IGAIN;
+ ctl->widget->ctlflags |= SOUND_MASK_IGAIN;
+ }
+ ctl = hdac_audio_ctl_amp_get(devinfo, 32, 0, 1);
+ if (ctl != NULL) {
+ ctl->ossmask = SOUND_MASK_MIC | SOUND_MASK_VOLUME;
+ ctl->widget->ctlflags |= SOUND_MASK_MIC;
+ }
+ ctl = hdac_audio_ctl_amp_get(devinfo, 32, 4, 1);
+ if (ctl != NULL) {
+ ctl->ossmask = SOUND_MASK_MIC | SOUND_MASK_VOLUME;
+ ctl->widget->ctlflags |= SOUND_MASK_MIC;
+ }
+ ctl = hdac_audio_ctl_amp_get(devinfo, 32, 1, 1);
+ if (ctl != NULL) {
+ ctl->ossmask = SOUND_MASK_LINE | SOUND_MASK_VOLUME;
+ ctl->widget->ctlflags |= SOUND_MASK_LINE;
+ }
+ ctl = hdac_audio_ctl_amp_get(devinfo, 32, 7, 1);
+ if (ctl != NULL) {
+ ctl->ossmask = SOUND_MASK_SPEAKER | SOUND_MASK_VOLUME;
+ ctl->widget->ctlflags |= SOUND_MASK_SPEAKER;
+ }
+ break;
+ case HDA_CODEC_STAC9221:
+ /*
+ * Dell XPS M1210 need all DACs for each output jacks
+ */
+ if (subvendor == DELL_XPSM1210_SUBVENDOR)
+ break;
+ for (i = devinfo->startnode; i < devinfo->endnode; i++) {
+ w = hdac_widget_get(devinfo, i);
+ if (w == NULL || w->enable == 0)
+ continue;
+ if (w->type !=
+ HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_OUTPUT)
+ continue;
+ if (w->nid != 2)
+ w->enable = 0;
+ }
+ break;
+ case HDA_CODEC_STAC9221D:
+ for (i = devinfo->startnode; i < devinfo->endnode; i++) {
+ w = hdac_widget_get(devinfo, i);
+ if (w == NULL || w->enable == 0)
+ continue;
+ if (w->type ==
+ HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_INPUT &&
+ w->nid != 6)
+ w->enable = 0;
+
+ }
+ break;
+ case HDA_CODEC_STAC9227:
+ w = hdac_widget_get(devinfo, 8);
+ if (w != NULL)
+ w->enable = 0;
+ w = hdac_widget_get(devinfo, 9);
+ if (w != NULL)
+ w->enable = 0;
+ break;
+ case HDA_CODEC_CXWAIKIKI:
+ if (subvendor == HP_DV5000_SUBVENDOR) {
+ w = hdac_widget_get(devinfo, 27);
+ if (w != NULL)
+ w->enable = 0;
+ }
+ ctl = hdac_audio_ctl_amp_get(devinfo, 16, 0, 1);
+ if (ctl != NULL)
+ ctl->ossmask = SOUND_MASK_SKIP;
+ ctl = hdac_audio_ctl_amp_get(devinfo, 25, 0, 1);
+ if (ctl != NULL && ctl->childwidget != NULL &&
+ ctl->childwidget->enable != 0) {
+ ctl->ossmask = SOUND_MASK_PCM | SOUND_MASK_VOLUME;
+ ctl->childwidget->ctlflags |= SOUND_MASK_PCM;
+ }
+ ctl = hdac_audio_ctl_amp_get(devinfo, 25, 1, 1);
+ if (ctl != NULL && ctl->childwidget != NULL &&
+ ctl->childwidget->enable != 0) {
+ ctl->ossmask = SOUND_MASK_LINE | SOUND_MASK_VOLUME;
+ ctl->childwidget->ctlflags |= SOUND_MASK_LINE;
+ }
+ ctl = hdac_audio_ctl_amp_get(devinfo, 25, 2, 1);
+ if (ctl != NULL && ctl->childwidget != NULL &&
+ ctl->childwidget->enable != 0) {
+ ctl->ossmask = SOUND_MASK_MIC | SOUND_MASK_VOLUME;
+ ctl->childwidget->ctlflags |= SOUND_MASK_MIC;
+ }
+ ctl = hdac_audio_ctl_amp_get(devinfo, 26, 0, 1);
+ if (ctl != NULL) {
+ ctl->ossmask = SOUND_MASK_SKIP;
+ /* XXX mixer \=rec mic broken.. why?!? */
+ /* ctl->widget->ctlflags |= SOUND_MASK_MIC; */
+ }
+ break;
+ default:
+ break;
+ }
}
static int
hdac_audio_ctl_ossmixer_getnextdev(struct hdac_devinfo *devinfo)
{
-int *dev = &devinfo->function.audio.ossidx;
+ int *dev = &devinfo->function.audio.ossidx;
-while (*dev < SOUND_MIXER_NRDEVICES) {
-switch (*dev) {
-case SOUND_MIXER_VOLUME:
-case SOUND_MIXER_BASS:
-case SOUND_MIXER_TREBLE:
-case SOUND_MIXER_PCM:
-case SOUND_MIXER_SPEAKER:
-case SOUND_MIXER_LINE:
-case SOUND_MIXER_MIC:
-case SOUND_MIXER_CD:
-case SOUND_MIXER_RECLEV:
-case SOUND_MIXER_OGAIN: /* reserved for EAPD switch */
-(*dev)++;
-break;
-default:
-return (*dev)++;
-break;
-}
-}
+ while (*dev < SOUND_MIXER_NRDEVICES) {
+ switch (*dev) {
+ case SOUND_MIXER_VOLUME:
+ case SOUND_MIXER_BASS:
+ case SOUND_MIXER_TREBLE:
+ case SOUND_MIXER_PCM:
+ case SOUND_MIXER_SPEAKER:
+ case SOUND_MIXER_LINE:
+ case SOUND_MIXER_MIC:
+ case SOUND_MIXER_CD:
+ case SOUND_MIXER_RECLEV:
+ case SOUND_MIXER_IGAIN:
+ case SOUND_MIXER_OGAIN: /* reserved for EAPD switch */
+ (*dev)++;
+ break;
+ default:
+ return (*dev)++;
+ break;
+ }
+ }
-return (-1);
+ return (-1);
}
static int
hdac_widget_find_dac_path(struct hdac_devinfo *devinfo, nid_t nid, int depth)
{
-struct hdac_widget *w;
-int i, ret = 0;
+ struct hdac_widget *w;
+ int i, ret = 0;
-if (depth > HDA_PARSE_MAXDEPTH)
-return (0);
-w = hdac_widget_get(devinfo, nid);
-if (w == NULL || w->enable == 0)
-return (0);
-switch (w->type) {
-case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_OUTPUT:
-w->pflags |= HDA_DAC_PATH;
-ret = 1;
-break;
-case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_MIXER:
-case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_SELECTOR:
-for (i = 0; i < w->nconns; i++) {
-if (hdac_widget_find_dac_path(devinfo,
-w->conns[i], depth + 1) != 0) {
-if (w->selconn == -1)
-w->selconn = i;
-ret = 1;
-w->pflags |= HDA_DAC_PATH;
-}
-}
-break;
-default:
-break;
-}
-return (ret);
+ if (depth > HDA_PARSE_MAXDEPTH)
+ return (0);
+ w = hdac_widget_get(devinfo, nid);
+ if (w == NULL || w->enable == 0)
+ return (0);
+ switch (w->type) {
+ case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_OUTPUT:
+ w->pflags |= HDA_DAC_PATH;
+ ret = 1;
+ break;
+ case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_MIXER:
+ case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_SELECTOR:
+ for (i = 0; i < w->nconns; i++) {
+ if (hdac_widget_find_dac_path(devinfo,
+ w->conns[i], depth + 1) != 0) {
+ if (w->selconn == -1)
+ w->selconn = i;
+ ret = 1;
+ w->pflags |= HDA_DAC_PATH;
+ }
+ }
+ break;
+ default:
+ break;
+ }
+ return (ret);
}
static int
hdac_widget_find_adc_path(struct hdac_devinfo *devinfo, nid_t nid, int depth)
{
-struct hdac_widget *w;
-int i, conndev, ret = 0;
+ struct hdac_widget *w;
+ int i, conndev, ret = 0;
-if (depth > HDA_PARSE_MAXDEPTH)
-return (0);
-w = hdac_widget_get(devinfo, nid);
-if (w == NULL || w->enable == 0)
-return (0);
-switch (w->type) {
-case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_INPUT:
-case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_SELECTOR:
-case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_MIXER:
-for (i = 0; i < w->nconns; i++) {
-if (hdac_widget_find_adc_path(devinfo, w->conns[i],
-depth + 1) != 0) {
-if (w->selconn == -1)
-w->selconn = i;
-w->pflags |= HDA_ADC_PATH;
-ret = 1;
-}
-}
-break;
-case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX:
-conndev = w->wclass.pin.config &
-HDA_CONFIG_DEFAULTCONF_DEVICE_MASK;
-if (HDA_PARAM_PIN_CAP_INPUT_CAP(w->wclass.pin.cap) &&
-(conndev == HDA_CONFIG_DEFAULTCONF_DEVICE_CD ||
-conndev == HDA_CONFIG_DEFAULTCONF_DEVICE_LINE_IN ||
-conndev == HDA_CONFIG_DEFAULTCONF_DEVICE_MIC_IN)) {
-w->pflags |= HDA_ADC_PATH;
-ret = 1;
-}
-break;
-/*case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_MIXER:
-if (w->pflags & HDA_DAC_PATH) {
-w->pflags |= HDA_ADC_PATH;
-ret = 1;
-}
-break;*/
-default:
-break;
-}
-return (ret);
+ if (depth > HDA_PARSE_MAXDEPTH)
+ return (0);
+ w = hdac_widget_get(devinfo, nid);
+ if (w == NULL || w->enable == 0)
+ return (0);
+ switch (w->type) {
+ case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_INPUT:
+ case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_SELECTOR:
+ case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_MIXER:
+ for (i = 0; i < w->nconns; i++) {
+ if (hdac_widget_find_adc_path(devinfo, w->conns[i],
+ depth + 1) != 0) {
+ if (w->selconn == -1)
+ w->selconn = i;
+ w->pflags |= HDA_ADC_PATH;
+ ret = 1;
+ }
+ }
+ break;
+ case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX:
+ conndev = w->wclass.pin.config &
+ HDA_CONFIG_DEFAULTCONF_DEVICE_MASK;
+ if (HDA_PARAM_PIN_CAP_INPUT_CAP(w->wclass.pin.cap) &&
+ (conndev == HDA_CONFIG_DEFAULTCONF_DEVICE_CD ||
+ conndev == HDA_CONFIG_DEFAULTCONF_DEVICE_LINE_IN ||
+ conndev == HDA_CONFIG_DEFAULTCONF_DEVICE_MIC_IN)) {
+ w->pflags |= HDA_ADC_PATH;
+ ret = 1;
+ }
+ break;
+ /*case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_MIXER:
+ if (w->pflags & HDA_DAC_PATH) {
+ w->pflags |= HDA_ADC_PATH;
+ ret = 1;
+ }
+ break;*/
+ default:
+ break;
+ }
+ return (ret);
}
static uint32_t
hdac_audio_ctl_outamp_build(struct hdac_devinfo *devinfo,
-nid_t nid, nid_t pnid, int index, int depth)
+ nid_t nid, nid_t pnid, int index, int depth)
{
-struct hdac_widget *w, *pw;
-struct hdac_audio_ctl *ctl;
-uint32_t fl = 0;
-int i, ossdev, conndev, strategy;
-
-if (depth > HDA_PARSE_MAXDEPTH)
-return (0);
-
-w = hdac_widget_get(devinfo, nid);
-if (w == NULL || w->enable == 0)
-return (0);
-
-pw = hdac_widget_get(devinfo, pnid);
-strategy = devinfo->function.audio.parsing_strategy;
-
-if (w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_MIXER
-|| w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_SELECTOR) {
-for (i = 0; i < w->nconns; i++) {
-fl |= hdac_audio_ctl_outamp_build(devinfo, w->conns[i],
-w->nid, i, depth + 1);
-}
-w->ctlflags |= fl;
-return (fl);
-} else if (w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_OUTPUT &&
-(w->pflags & HDA_DAC_PATH)) {
-i = 0;
-while ((ctl = hdac_audio_ctl_each(devinfo, &i)) != NULL) {
-if (ctl->enable == 0 || ctl->widget == NULL)
-continue;
-/* XXX This should be compressed! */
-if ((ctl->widget->nid == w->nid) ||
-(ctl->widget->nid == pnid && ctl->index == index &&
-(ctl->dir & HDA_CTL_IN)) ||
-(ctl->widget->nid == pnid && pw != NULL &&
-pw->type ==
-HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_SELECTOR &&
-(pw->nconns < 2 || pw->selconn == index ||
-pw->selconn == -1) &&
-(ctl->dir & HDA_CTL_OUT)) ||
-(strategy == HDA_PARSE_DIRECT &&
-ctl->widget->nid == w->nid)) {
-/*if (pw != NULL && pw->selconn == -1)
-pw->selconn = index;
-fl |= SOUND_MASK_VOLUME;
-fl |= SOUND_MASK_PCM;
-ctl->ossmask |= SOUND_MASK_VOLUME;
-ctl->ossmask |= SOUND_MASK_PCM;
-ctl->ossdev = SOUND_MIXER_PCM;*/
-if (!(w->ctlflags & SOUND_MASK_PCM) ||
-(pw != NULL &&
-!(pw->ctlflags & SOUND_MASK_PCM))) {
-fl |= SOUND_MASK_VOLUME;
-fl |= SOUND_MASK_PCM;
-ctl->ossmask |= SOUND_MASK_VOLUME;
-ctl->ossmask |= SOUND_MASK_PCM;
-ctl->ossdev = SOUND_MIXER_PCM;
-w->ctlflags |= SOUND_MASK_VOLUME;
-w->ctlflags |= SOUND_MASK_PCM;
-if (pw != NULL) {
-if (pw->selconn == -1)
-pw->selconn = index;
-pw->ctlflags |=
-SOUND_MASK_VOLUME;
-pw->ctlflags |=
-SOUND_MASK_PCM;
-}
-}
-}
-}
-w->ctlflags |= fl;
-return (fl);
-} else if (w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX
-&& HDA_PARAM_PIN_CAP_INPUT_CAP(w->wclass.pin.cap) &&
-(w->pflags & HDA_ADC_PATH)) {
-conndev = w->wclass.pin.config &
-HDA_CONFIG_DEFAULTCONF_DEVICE_MASK;
-i = 0;
-while ((ctl = hdac_audio_ctl_each(devinfo, &i)) != NULL) {
-if (ctl->enable == 0 || ctl->widget == NULL)
-continue;
-/* XXX This should be compressed! */
-if (((ctl->widget->nid == pnid && ctl->index == index &&
-(ctl->dir & HDA_CTL_IN)) ||
-(ctl->widget->nid == pnid && pw != NULL &&
-pw->type ==
-HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_SELECTOR &&
-(pw->nconns < 2 || pw->selconn == index ||
-pw->selconn == -1) &&
-(ctl->dir & HDA_CTL_OUT)) ||
-(strategy == HDA_PARSE_DIRECT &&
-ctl->widget->nid == w->nid)) &&
-!(ctl->ossmask & ~SOUND_MASK_VOLUME)) {
-if (pw != NULL && pw->selconn == -1)
-pw->selconn = index;
-ossdev = 0;
-switch (conndev) {
-case HDA_CONFIG_DEFAULTCONF_DEVICE_MIC_IN:
-ossdev = SOUND_MIXER_MIC;
-break;
-case HDA_CONFIG_DEFAULTCONF_DEVICE_LINE_IN:
-ossdev = SOUND_MIXER_LINE;
-break;
-case HDA_CONFIG_DEFAULTCONF_DEVICE_CD:
-ossdev = SOUND_MIXER_CD;
-break;
-default:
-ossdev =
-hdac_audio_ctl_ossmixer_getnextdev(
-devinfo);
-if (ossdev < 0)
-ossdev = 0;
-break;
-}
-if (strategy == HDA_PARSE_MIXER) {
-fl |= SOUND_MASK_VOLUME;
-ctl->ossmask |= SOUND_MASK_VOLUME;
-}
-fl |= 1 << ossdev;
-ctl->ossmask |= 1 << ossdev;
-ctl->ossdev = ossdev;
-}
-}
-w->ctlflags |= fl;
-return (fl);
-} else if (w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_BEEP_WIDGET) {
-i = 0;
-while ((ctl = hdac_audio_ctl_each(devinfo, &i)) != NULL) {
-if (ctl->enable == 0 || ctl->widget == NULL)
-continue;
-/* XXX This should be compressed! */
-if (((ctl->widget->nid == pnid && ctl->index == index &&
-(ctl->dir & HDA_CTL_IN)) ||
-(ctl->widget->nid == pnid && pw != NULL &&
-pw->type ==
-HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_SELECTOR &&
-(pw->nconns < 2 || pw->selconn == index ||
-pw->selconn == -1) &&
-(ctl->dir & HDA_CTL_OUT)) ||
-(strategy == HDA_PARSE_DIRECT &&
-ctl->widget->nid == w->nid)) &&
-!(ctl->ossmask & ~SOUND_MASK_VOLUME)) {
-if (pw != NULL && pw->selconn == -1)
-pw->selconn = index;
-fl |= SOUND_MASK_VOLUME;
-fl |= SOUND_MASK_SPEAKER;
-ctl->ossmask |= SOUND_MASK_VOLUME;
-ctl->ossmask |= SOUND_MASK_SPEAKER;
-ctl->ossdev = SOUND_MIXER_SPEAKER;
-}
-}
-w->ctlflags |= fl;
-return (fl);
-}
-return (0);
+ struct hdac_widget *w, *pw;
+ struct hdac_audio_ctl *ctl;
+ uint32_t fl = 0;
+ int i, ossdev, conndev, strategy;
+
+ if (depth > HDA_PARSE_MAXDEPTH)
+ return (0);
+
+ w = hdac_widget_get(devinfo, nid);
+ if (w == NULL || w->enable == 0)
+ return (0);
+
+ pw = hdac_widget_get(devinfo, pnid);
+ strategy = devinfo->function.audio.parsing_strategy;
+
+ if (w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_MIXER
+ || w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_SELECTOR) {
+ for (i = 0; i < w->nconns; i++) {
+ fl |= hdac_audio_ctl_outamp_build(devinfo, w->conns[i],
+ w->nid, i, depth + 1);
+ }
+ w->ctlflags |= fl;
+ return (fl);
+ } else if (w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_OUTPUT &&
+ (w->pflags & HDA_DAC_PATH)) {
+ i = 0;
+ while ((ctl = hdac_audio_ctl_each(devinfo, &i)) != NULL) {
+ if (ctl->enable == 0 || ctl->widget == NULL)
+ continue;
+ /* XXX This should be compressed! */
+ if (((ctl->widget->nid == w->nid) ||
+ (ctl->widget->nid == pnid && ctl->index == index &&
+ (ctl->dir & HDA_CTL_IN)) ||
+ (ctl->widget->nid == pnid && pw != NULL &&
+ pw->type ==
+ HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_SELECTOR &&
+ (pw->nconns < 2 || pw->selconn == index ||
+ pw->selconn == -1) &&
+ (ctl->dir & HDA_CTL_OUT)) ||
+ (strategy == HDA_PARSE_DIRECT &&
+ ctl->widget->nid == w->nid)) &&
+ !(ctl->ossmask & ~SOUND_MASK_VOLUME)) {
+ /*if (pw != NULL && pw->selconn == -1)
+ pw->selconn = index;
+ fl |= SOUND_MASK_VOLUME;
+ fl |= SOUND_MASK_PCM;
+ ctl->ossmask |= SOUND_MASK_VOLUME;
+ ctl->ossmask |= SOUND_MASK_PCM;
+ ctl->ossdev = SOUND_MIXER_PCM;*/
+ if (!(w->ctlflags & SOUND_MASK_PCM) ||
+ (pw != NULL &&
+ !(pw->ctlflags & SOUND_MASK_PCM))) {
+ fl |= SOUND_MASK_VOLUME;
+ fl |= SOUND_MASK_PCM;
+ ctl->ossmask |= SOUND_MASK_VOLUME;
+ ctl->ossmask |= SOUND_MASK_PCM;
+ ctl->ossdev = SOUND_MIXER_PCM;
+ w->ctlflags |= SOUND_MASK_VOLUME;
+ w->ctlflags |= SOUND_MASK_PCM;
+ if (pw != NULL) {
+ if (pw->selconn == -1)
+ pw->selconn = index;
+ pw->ctlflags |=
+ SOUND_MASK_VOLUME;
+ pw->ctlflags |=
+ SOUND_MASK_PCM;
+ }
+ }
+ }
+ }
+ w->ctlflags |= fl;
+ return (fl);
+ } else if (w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX &&
+ HDA_PARAM_PIN_CAP_INPUT_CAP(w->wclass.pin.cap) &&
+ (w->pflags & HDA_ADC_PATH)) {
+ conndev = w->wclass.pin.config &
+ HDA_CONFIG_DEFAULTCONF_DEVICE_MASK;
+ i = 0;
+ while ((ctl = hdac_audio_ctl_each(devinfo, &i)) != NULL) {
+ if (ctl->enable == 0 || ctl->widget == NULL)
+ continue;
+ /* XXX This should be compressed! */
+ if (((ctl->widget->nid == pnid && ctl->index == index &&
+ (ctl->dir & HDA_CTL_IN)) ||
+ (ctl->widget->nid == pnid && pw != NULL &&
+ pw->type ==
+ HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_SELECTOR &&
+ (pw->nconns < 2 || pw->selconn == index ||
+ pw->selconn == -1) &&
+ (ctl->dir & HDA_CTL_OUT)) ||
+ (strategy == HDA_PARSE_DIRECT &&
+ ctl->widget->nid == w->nid)) &&
+ !(ctl->ossmask & ~SOUND_MASK_VOLUME)) {
+ if (pw != NULL && pw->selconn == -1)
+ pw->selconn = index;
+ ossdev = 0;
+ switch (conndev) {
+ case HDA_CONFIG_DEFAULTCONF_DEVICE_MIC_IN:
+ ossdev = SOUND_MIXER_MIC;
+ break;
+ case HDA_CONFIG_DEFAULTCONF_DEVICE_LINE_IN:
+ ossdev = SOUND_MIXER_LINE;
+ break;
+ case HDA_CONFIG_DEFAULTCONF_DEVICE_CD:
+ ossdev = SOUND_MIXER_CD;
+ break;
+ default:
+ ossdev =
+ hdac_audio_ctl_ossmixer_getnextdev(
+ devinfo);
+ if (ossdev < 0)
+ ossdev = 0;
+ break;
+ }
+ if (strategy == HDA_PARSE_MIXER) {
+ fl |= SOUND_MASK_VOLUME;
+ ctl->ossmask |= SOUND_MASK_VOLUME;
+ }
+ fl |= 1 << ossdev;
+ ctl->ossmask |= 1 << ossdev;
+ ctl->ossdev = ossdev;
+ }
+ }
+ w->ctlflags |= fl;
+ return (fl);
+ } else if (w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_BEEP_WIDGET) {
+ i = 0;
+ while ((ctl = hdac_audio_ctl_each(devinfo, &i)) != NULL) {
+ if (ctl->enable == 0 || ctl->widget == NULL)
+ continue;
+ /* XXX This should be compressed! */
+ if (((ctl->widget->nid == pnid && ctl->index == index &&
+ (ctl->dir & HDA_CTL_IN)) ||
+ (ctl->widget->nid == pnid && pw != NULL &&
+ pw->type ==
+ HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_SELECTOR &&
+ (pw->nconns < 2 || pw->selconn == index ||
+ pw->selconn == -1) &&
+ (ctl->dir & HDA_CTL_OUT)) ||
+ (strategy == HDA_PARSE_DIRECT &&
+ ctl->widget->nid == w->nid)) &&
+ !(ctl->ossmask & ~SOUND_MASK_VOLUME)) {
+ if (pw != NULL && pw->selconn == -1)
+ pw->selconn = index;
+ fl |= SOUND_MASK_VOLUME;
+ fl |= SOUND_MASK_SPEAKER;
+ ctl->ossmask |= SOUND_MASK_VOLUME;
+ ctl->ossmask |= SOUND_MASK_SPEAKER;
+ ctl->ossdev = SOUND_MIXER_SPEAKER;
+ }
+ }
+ w->ctlflags |= fl;
+ return (fl);
+ }
+ return (0);
}
static uint32_t
hdac_audio_ctl_inamp_build(struct hdac_devinfo *devinfo, nid_t nid, int depth)
{
-struct hdac_widget *w, *cw;
-struct hdac_audio_ctl *ctl;
-uint32_t fl;
-int i;
-
-if (depth > HDA_PARSE_MAXDEPTH)
-return (0);
-
-w = hdac_widget_get(devinfo, nid);
-if (w == NULL || w->enable == 0)
-return (0);
-/*if (!(w->pflags & HDA_ADC_PATH))
-return (0);
-if (!(w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_INPUT ||
-w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_SELECTOR))
-return (0);*/
-i = 0;
-while ((ctl = hdac_audio_ctl_each(devinfo, &i)) != NULL) {
-if (ctl->enable == 0 || ctl->widget == NULL)
-continue;
-if (ctl->widget->nid == nid) {
-ctl->ossmask |= SOUND_MASK_RECLEV;
-w->ctlflags |= SOUND_MASK_RECLEV;
-return (SOUND_MASK_RECLEV);
-}
-}
-for (i = 0; i < w->nconns; i++) {
-cw = hdac_widget_get(devinfo, w->conns[i]);
-if (cw == NULL || cw->enable == 0)
-continue;
-if (cw->type != HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_SELECTOR)
-continue;
-fl = hdac_audio_ctl_inamp_build(devinfo, cw->nid, depth + 1);
-if (fl != 0) {
-cw->ctlflags |= fl;
-w->ctlflags |= fl;
-return (fl);
-}
-}
-return (0);
+ struct hdac_widget *w, *cw;
+ struct hdac_audio_ctl *ctl;
+ uint32_t fl;
+ int i;
+
+ if (depth > HDA_PARSE_MAXDEPTH)
+ return (0);
+
+ w = hdac_widget_get(devinfo, nid);
+ if (w == NULL || w->enable == 0)
+ return (0);
+ /*if (!(w->pflags & HDA_ADC_PATH))
+ return (0);
+ if (!(w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_INPUT ||
+ w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_SELECTOR))
+ return (0);*/
+ i = 0;
+ while ((ctl = hdac_audio_ctl_each(devinfo, &i)) != NULL) {
+ if (ctl->enable == 0 || ctl->widget == NULL)
+ continue;
+ if (ctl->widget->nid == nid) {
+ ctl->ossmask |= SOUND_MASK_RECLEV;
+ w->ctlflags |= SOUND_MASK_RECLEV;
+ return (SOUND_MASK_RECLEV);
+ }
+ }
+ for (i = 0; i < w->nconns; i++) {
+ cw = hdac_widget_get(devinfo, w->conns[i]);
+ if (cw == NULL || cw->enable == 0)
+ continue;
+ if (cw->type != HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_SELECTOR)
+ continue;
+ fl = hdac_audio_ctl_inamp_build(devinfo, cw->nid, depth + 1);
+ if (fl != 0) {
+ cw->ctlflags |= fl;
+ w->ctlflags |= fl;
+ return (fl);
+ }
+ }
+ return (0);
}
static int
hdac_audio_ctl_recsel_build(struct hdac_devinfo *devinfo, nid_t nid, int depth)
{
-struct hdac_widget *w, *cw;
-int i, child = 0;
+ struct hdac_widget *w, *cw;
+ int i, child = 0;
-if (depth > HDA_PARSE_MAXDEPTH)
-return (0);
+ if (depth > HDA_PARSE_MAXDEPTH)
+ return (0);
-w = hdac_widget_get(devinfo, nid);
-if (w == NULL || w->enable == 0)
-return (0);
-/*if (!(w->pflags & HDA_ADC_PATH))
-return (0);
-if (!(w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_INPUT ||
-w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_SELECTOR))
-return (0);*/
-/* XXX weak! */
-for (i = 0; i < w->nconns; i++) {
-cw = hdac_widget_get(devinfo, w->conns[i]);
-if (cw == NULL)
-continue;
-if (++child > 1) {
-w->pflags |= HDA_ADC_RECSEL;
-return (1);
-}
-}
-for (i = 0; i < w->nconns; i++) {
-if (hdac_audio_ctl_recsel_build(devinfo,
-w->conns[i], depth + 1) != 0)
-return (1);
-}
-return (0);
+ w = hdac_widget_get(devinfo, nid);
+ if (w == NULL || w->enable == 0)
+ return (0);
+ /*if (!(w->pflags & HDA_ADC_PATH))
+ return (0);
+ if (!(w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_INPUT ||
+ w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_SELECTOR))
+ return (0);*/
+ /* XXX weak! */
+ for (i = 0; i < w->nconns; i++) {
+ cw = hdac_widget_get(devinfo, w->conns[i]);
+ if (cw == NULL)
+ continue;
+ if (++child > 1) {
+ w->pflags |= HDA_ADC_RECSEL;
+ return (1);
+ }
+ }
+ for (i = 0; i < w->nconns; i++) {
+ if (hdac_audio_ctl_recsel_build(devinfo,
+ w->conns[i], depth + 1) != 0)
+ return (1);
+ }
+ return (0);
}
static int
hdac_audio_build_tree_strategy(struct hdac_devinfo *devinfo)
{
-struct hdac_widget *w, *cw;
-int i, j, conndev, found_dac = 0;
-int strategy;
-
-strategy = devinfo->function.audio.parsing_strategy;
-
-for (i = devinfo->startnode; i < devinfo->endnode; i++) {
-w = hdac_widget_get(devinfo, i);
-if (w == NULL || w->enable == 0)
-continue;
-if (w->type != HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX)
-continue;
-if (!HDA_PARAM_PIN_CAP_OUTPUT_CAP(w->wclass.pin.cap))
-continue;
-conndev = w->wclass.pin.config &
-HDA_CONFIG_DEFAULTCONF_DEVICE_MASK;
-if (!(conndev == HDA_CONFIG_DEFAULTCONF_DEVICE_HP_OUT ||
-conndev == HDA_CONFIG_DEFAULTCONF_DEVICE_SPEAKER ||
-conndev == HDA_CONFIG_DEFAULTCONF_DEVICE_LINE_OUT))
-continue;
-for (j = 0; j < w->nconns; j++) {
-cw = hdac_widget_get(devinfo, w->conns[j]);
-if (cw == NULL || cw->enable == 0)
-continue;
-if (strategy == HDA_PARSE_MIXER && !(cw->type ==
-HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_MIXER ||
-cw->type ==
-HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_SELECTOR))
-continue;
-if (hdac_widget_find_dac_path(devinfo, cw->nid, 0)
-!= 0) {
-if (w->selconn == -1)
-w->selconn = j;
-w->pflags |= HDA_DAC_PATH;
-found_dac++;
-}
-}
-}
+ struct hdac_widget *w, *cw;
+ int i, j, conndev, found_dac = 0;
+ int strategy;
+
+ strategy = devinfo->function.audio.parsing_strategy;
+
+ for (i = devinfo->startnode; i < devinfo->endnode; i++) {
+ w = hdac_widget_get(devinfo, i);
+ if (w == NULL || w->enable == 0)
+ continue;
+ if (w->type != HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX)
+ continue;
+ if (!HDA_PARAM_PIN_CAP_OUTPUT_CAP(w->wclass.pin.cap))
+ continue;
+ conndev = w->wclass.pin.config &
+ HDA_CONFIG_DEFAULTCONF_DEVICE_MASK;
+ if (!(conndev == HDA_CONFIG_DEFAULTCONF_DEVICE_HP_OUT ||
+ conndev == HDA_CONFIG_DEFAULTCONF_DEVICE_SPEAKER ||
+ conndev == HDA_CONFIG_DEFAULTCONF_DEVICE_LINE_OUT))
+ continue;
+ for (j = 0; j < w->nconns; j++) {
+ cw = hdac_widget_get(devinfo, w->conns[j]);
+ if (cw == NULL || cw->enable == 0)
+ continue;
+ if (strategy == HDA_PARSE_MIXER && !(cw->type ==
+ HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_MIXER ||
+ cw->type ==
+ HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_SELECTOR))
+ continue;
+ if (hdac_widget_find_dac_path(devinfo, cw->nid, 0)
+ != 0) {
+ if (w->selconn == -1)
+ w->selconn = j;
+ w->pflags |= HDA_DAC_PATH;
+ found_dac++;
+ }
+ }
+ }
-return (found_dac);
+ return (found_dac);
}
static void
hdac_audio_build_tree(struct hdac_devinfo *devinfo)
{
-struct hdac_widget *w;
-struct hdac_audio_ctl *ctl;
-int i, j, dacs, strategy;
-
-/* Construct DAC path */
-strategy = HDA_PARSE_MIXER;
-devinfo->function.audio.parsing_strategy = strategy;
-HDA_BOOTVERBOSE(
-device_printf(devinfo->codec->sc->dev,
-"HDA_DEBUG: HWiP: HDA Widget Parser - Revision %dn",
-HDA_WIDGET_PARSER_REV);
-);
-dacs = hdac_audio_build_tree_strategy(devinfo);
-if (dacs == 0) {
-HDA_BOOTVERBOSE(
-device_printf(devinfo->codec->sc->dev,
-"HDA_DEBUG: HWiP: 0 DAC path found! "
-"Retrying parser "
-"using HDA_PARSE_DIRECT strategy.n");
-);
-strategy = HDA_PARSE_DIRECT;
-devinfo->function.audio.parsing_strategy = strategy;
-dacs = hdac_audio_build_tree_strategy(devinfo);
-}
-
-HDA_BOOTVERBOSE(
-device_printf(devinfo->codec->sc->dev,
-"HDA_DEBUG: HWiP: Found %d DAC path using HDA_PARSE_%s "
-"strategy.n",
-dacs, (strategy == HDA_PARSE_MIXER) ? "MIXER" : "DIRECT");
-);
-
-/* Construct ADC path */
-for (i = devinfo->startnode; i < devinfo->endnode; i++) {
-w = hdac_widget_get(devinfo, i);
-if (w == NULL || w->enable == 0)
-continue;
-if (w->type != HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_INPUT)
-continue;
-(void)hdac_widget_find_adc_path(devinfo, w->nid, 0);
-}
-
-/* Output mixers */
-for (i = devinfo->startnode; i < devinfo->endnode; i++) {
-w = hdac_widget_get(devinfo, i);
-if (w == NULL || w->enable == 0)
-continue;
-if ((strategy == HDA_PARSE_MIXER &&
-(w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_MIXER ||
-w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_SELECTOR)
-&& (w->pflags & HDA_DAC_PATH)) ||
-(strategy == HDA_PARSE_DIRECT && (w->pflags &
-(HDA_DAC_PATH | HDA_ADC_PATH)))) {
-w->ctlflags |= hdac_audio_ctl_outamp_build(devinfo,
-w->nid, devinfo->startnode - 1, 0, 0);
-} else if (w->type ==
-HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_BEEP_WIDGET) {
-j = 0;
-while ((ctl = hdac_audio_ctl_each(devinfo, &j)) !=
-NULL) {
-if (ctl->enable == 0 || ctl->widget == NULL)
-continue;
-if (ctl->widget->nid != w->nid)
-continue;
-ctl->ossmask |= SOUND_MASK_VOLUME;
-ctl->ossmask |= SOUND_MASK_SPEAKER;
-ctl->ossdev = SOUND_MIXER_SPEAKER;
-w->ctlflags |= SOUND_MASK_VOLUME;
-w->ctlflags |= SOUND_MASK_SPEAKER;
-}
-}
-}
-
-/* Input mixers (rec) */
-for (i = devinfo->startnode; i < devinfo->endnode; i++) {
-w = hdac_widget_get(devinfo, i);
-if (w == NULL || w->enable == 0)
-continue;
-if (!(w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_INPUT &&
-w->pflags & HDA_ADC_PATH))
-continue;
-hdac_audio_ctl_inamp_build(devinfo, w->nid, 0);
-hdac_audio_ctl_recsel_build(devinfo, w->nid, 0);
-}
+ struct hdac_widget *w;
+ struct hdac_audio_ctl *ctl;
+ int i, j, dacs, strategy;
+
+ /* Construct DAC path */
+ strategy = HDA_PARSE_MIXER;
+ devinfo->function.audio.parsing_strategy = strategy;
+ HDA_BOOTVERBOSE(
+ device_printf(devinfo->codec->sc->dev,
+ "HDA_DEBUG: HWiP: HDA Widget Parser - Revision %d\n",
+ HDA_WIDGET_PARSER_REV);
+ );
+ dacs = hdac_audio_build_tree_strategy(devinfo);
+ if (dacs == 0) {
+ HDA_BOOTVERBOSE(
+ device_printf(devinfo->codec->sc->dev,
+ "HDA_DEBUG: HWiP: 0 DAC path found! "
+ "Retrying parser "
+ "using HDA_PARSE_DIRECT strategy.\n");
+ );
+ strategy = HDA_PARSE_DIRECT;
+ devinfo->function.audio.parsing_strategy = strategy;
+ dacs = hdac_audio_build_tree_strategy(devinfo);
+ }
+
+ HDA_BOOTVERBOSE(
+ device_printf(devinfo->codec->sc->dev,
+ "HDA_DEBUG: HWiP: Found %d DAC path using HDA_PARSE_%s "
+ "strategy.\n",
+ dacs, (strategy == HDA_PARSE_MIXER) ? "MIXER" : "DIRECT");
+ );
+
+ /* Construct ADC path */
+ for (i = devinfo->startnode; i < devinfo->endnode; i++) {
+ w = hdac_widget_get(devinfo, i);
+ if (w == NULL || w->enable == 0)
+ continue;
+ if (w->type != HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_INPUT)
+ continue;
+ (void)hdac_widget_find_adc_path(devinfo, w->nid, 0);
+ }
+
+ /* Output mixers */
+ for (i = devinfo->startnode; i < devinfo->endnode; i++) {
+ w = hdac_widget_get(devinfo, i);
+ if (w == NULL || w->enable == 0)
+ continue;
+ if ((strategy == HDA_PARSE_MIXER &&
+ (w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_MIXER ||
+ w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_SELECTOR)
+ && (w->pflags & HDA_DAC_PATH)) ||
+ (strategy == HDA_PARSE_DIRECT && (w->pflags &
+ (HDA_DAC_PATH | HDA_ADC_PATH)))) {
+ w->ctlflags |= hdac_audio_ctl_outamp_build(devinfo,
+ w->nid, devinfo->startnode - 1, 0, 0);
+ } else if (w->type ==
+ HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_BEEP_WIDGET) {
+ j = 0;
+ while ((ctl = hdac_audio_ctl_each(devinfo, &j)) !=
+ NULL) {
+ if (ctl->enable == 0 || ctl->widget == NULL)
+ continue;
+ if (ctl->widget->nid != w->nid)
+ continue;
+ ctl->ossmask |= SOUND_MASK_VOLUME;
+ ctl->ossmask |= SOUND_MASK_SPEAKER;
+ ctl->ossdev = SOUND_MIXER_SPEAKER;
+ w->ctlflags |= SOUND_MASK_VOLUME;
+ w->ctlflags |= SOUND_MASK_SPEAKER;
+ }
+ }
+ }
+
+ /* Input mixers (rec) */
+ for (i = devinfo->startnode; i < devinfo->endnode; i++) {
+ w = hdac_widget_get(devinfo, i);
+ if (w == NULL || w->enable == 0)
+ continue;
+ if (!(w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_INPUT &&
+ w->pflags & HDA_ADC_PATH))
+ continue;
+ hdac_audio_ctl_inamp_build(devinfo, w->nid, 0);
+ hdac_audio_ctl_recsel_build(devinfo, w->nid, 0);
+ }
}
#define HDA_COMMIT_CONN (1 << 0)
#define HDA_COMMIT_CTRL (1 << 1)
#define HDA_COMMIT_EAPD (1 << 2)
#define HDA_COMMIT_GPIO (1 << 3)
-#define HDA_COMMIT_ALL (HDA_COMMIT_CONN | HDA_COMMIT_CTRL | HDA_COMMIT_EAPD | HDA_COMMIT_GPIO)
+#define HDA_COMMIT_MISC (1 << 4)
+#define HDA_COMMIT_ALL (HDA_COMMIT_CONN | HDA_COMMIT_CTRL | \
+ HDA_COMMIT_EAPD | HDA_COMMIT_GPIO | HDA_COMMIT_MISC)
static void
hdac_audio_commit(struct hdac_devinfo *devinfo, uint32_t cfl)
{
-struct hdac_softc *sc = devinfo->codec->sc;
-struct hdac_widget *w;
-nid_t cad, nid;
-int i, gpioval;
-
-if (!(cfl & HDA_COMMIT_ALL))
-return;
-
-cad = devinfo->codec->cad;
-
-if (cfl & HDA_COMMIT_GPIO) {
-nid = devinfo->nid;
-for (i = 0; i < HDA_GPIO_MAX; i++) {
-if (!(devinfo->function.audio.quirks & (1 << i)))
-continue;
-gpioval = (1 << i) - 1;
-hdac_command(sc,
-HDA_CMD_SET_GPIO_ENABLE_MASK(cad, nid, gpioval),
-cad);
-hdac_command(sc,
-HDA_CMD_SET_GPIO_DIRECTION(cad, nid, gpioval),
-cad);
-hdac_command(sc,
-HDA_CMD_SET_GPIO_DATA(cad, nid, gpioval),
-cad);
-}
-}
-
-for (i = 0; i < devinfo->nodecnt; i++) {
-w = &devinfo->widget[i];
-if (w == NULL || w->enable == 0)
-continue;
-if (cfl & HDA_COMMIT_CONN) {
-if (w->selconn == -1)
-w->selconn = 0;
-if (w->nconns > 0)
-hdac_widget_connection_select(w, w->selconn);
-}
-if ((cfl & HDA_COMMIT_CTRL) &&
-w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX) {
-if ((w->pflags & (HDA_DAC_PATH | HDA_ADC_PATH)) ==
-(HDA_DAC_PATH | HDA_ADC_PATH))
-device_printf(sc->dev, "WARNING: node %d "
-"participate both for DAC/ADC!n", w->nid);
-if (w->pflags & HDA_DAC_PATH) {
-w->wclass.pin.ctrl &=
-~HDA_CMD_SET_PIN_WIDGET_CTRL_IN_ENABLE;
-if ((w->wclass.pin.config &
-HDA_CONFIG_DEFAULTCONF_DEVICE_MASK) !=
-HDA_CONFIG_DEFAULTCONF_DEVICE_HP_OUT)
-w->wclass.pin.ctrl &=
-~HDA_CMD_SET_PIN_WIDGET_CTRL_HPHN_ENABLE;
-} else if (w->pflags & HDA_ADC_PATH) {
-w->wclass.pin.ctrl &=
-~(HDA_CMD_SET_PIN_WIDGET_CTRL_OUT_ENABLE |
-HDA_CMD_SET_PIN_WIDGET_CTRL_HPHN_ENABLE);
-} else
-w->wclass.pin.ctrl &= ~(
-HDA_CMD_SET_PIN_WIDGET_CTRL_HPHN_ENABLE |
-HDA_CMD_SET_PIN_WIDGET_CTRL_OUT_ENABLE |
-HDA_CMD_SET_PIN_WIDGET_CTRL_IN_ENABLE);
-hdac_command(sc,
-HDA_CMD_SET_PIN_WIDGET_CTRL(cad, w->nid,
-w->wclass.pin.ctrl), cad);
-}
-if ((cfl & HDA_COMMIT_EAPD) &&
-w->param.eapdbtl != HDAC_INVALID) {
-uint32_t val;
-
-val = w->param.eapdbtl;
-if (devinfo->function.audio.quirks &
-HDA_QUIRK_EAPDINV)
-val ^= HDA_CMD_SET_EAPD_BTL_ENABLE_EAPD;
-hdac_command(sc,
-HDA_CMD_SET_EAPD_BTL_ENABLE(cad, w->nid,
-val), cad);
-
-}
-DELAY(1000);
-}
+ struct hdac_softc *sc = devinfo->codec->sc;
+ struct hdac_widget *w;
+ nid_t cad;
+ int i;
+
+ if (!(cfl & HDA_COMMIT_ALL))
+ return;
+
+ cad = devinfo->codec->cad;
+
+ if ((cfl & HDA_COMMIT_MISC)) {
+ if (sc->pci_subvendor == APPLE_INTEL_MAC)
+ hdac_command(sc, HDA_CMD_12BIT(cad, devinfo->nid,
+ 0x7e7, 0), cad);
+ }
+
+ if (cfl & HDA_COMMIT_GPIO) {
+ uint32_t gdata, gmask, gdir;
+ int commitgpio, numgpio;
+
+ gdata = 0;
+ gmask = 0;
+ gdir = 0;
+ commitgpio = 0;
+
+ numgpio = HDA_PARAM_GPIO_COUNT_NUM_GPIO(
+ devinfo->function.audio.gpio);
+
+ if (devinfo->function.audio.quirks & HDA_QUIRK_GPIOFLUSH)
+ commitgpio = (numgpio > 0) ? 1 : 0;
+ else {
+ for (i = 0; i < numgpio && i < HDA_GPIO_MAX; i++) {
+ if (!(devinfo->function.audio.quirks &
+ (1 << i)))
+ continue;
+ if (commitgpio == 0) {
+ commitgpio = 1;
+ HDA_BOOTVERBOSE(
+ gdata = hdac_command(sc,
+ HDA_CMD_GET_GPIO_DATA(cad,
+ devinfo->nid), cad);
+ gmask = hdac_command(sc,
+ HDA_CMD_GET_GPIO_ENABLE_MASK(cad,
+ devinfo->nid), cad);
+ gdir = hdac_command(sc,
+ HDA_CMD_GET_GPIO_DIRECTION(cad,
+ devinfo->nid), cad);
+ device_printf(sc->dev,
+ "GPIO init: data=0x%08x "
+ "mask=0x%08x dir=0x%08x\n",
+ gdata, gmask, gdir);
+ gdata = 0;
+ gmask = 0;
+ gdir = 0;
+ );
+ }
+ gdata |= 1 << i;
+ gmask |= 1 << i;
+ gdir |= 1 << i;
+ }
+ }
+
+ if (commitgpio != 0) {
+ HDA_BOOTVERBOSE(
+ device_printf(sc->dev,
+ "GPIO commit: data=0x%08x mask=0x%08x "
+ "dir=0x%08x\n",
+ gdata, gmask, gdir);
+ );
+ hdac_command(sc,
+ HDA_CMD_SET_GPIO_ENABLE_MASK(cad, devinfo->nid,
+ gmask), cad);
+ hdac_command(sc,
+ HDA_CMD_SET_GPIO_DIRECTION(cad, devinfo->nid,
+ gdir), cad);
+ hdac_command(sc,
+ HDA_CMD_SET_GPIO_DATA(cad, devinfo->nid,
+ gdata), cad);
+ }
+ }
+
+ for (i = 0; i < devinfo->nodecnt; i++) {
+ w = &devinfo->widget[i];
+ if (w == NULL || w->enable == 0)
+ continue;
+ if (cfl & HDA_COMMIT_CONN) {
+ if (w->selconn == -1)
+ w->selconn = 0;
+ if (w->nconns > 0)
+ hdac_widget_connection_select(w, w->selconn);
+ }
+ if ((cfl & HDA_COMMIT_CTRL) &&
+ w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX) {
+ uint32_t pincap;
+
+ pincap = w->wclass.pin.cap;
+
+ if ((w->pflags & (HDA_DAC_PATH | HDA_ADC_PATH)) ==
+ (HDA_DAC_PATH | HDA_ADC_PATH))
+ device_printf(sc->dev, "WARNING: node %d "
+ "participate both for DAC/ADC!\n", w->nid);
+ if (w->pflags & HDA_DAC_PATH) {
+ w->wclass.pin.ctrl &=
+ ~HDA_CMD_SET_PIN_WIDGET_CTRL_IN_ENABLE;
+ if ((w->wclass.pin.config &
+ HDA_CONFIG_DEFAULTCONF_DEVICE_MASK) !=
+ HDA_CONFIG_DEFAULTCONF_DEVICE_HP_OUT)
+ w->wclass.pin.ctrl &=
+ ~HDA_CMD_SET_PIN_WIDGET_CTRL_HPHN_ENABLE;
+ if ((devinfo->function.audio.quirks & HDA_QUIRK_OVREF100) &&
+ HDA_PARAM_PIN_CAP_VREF_CTRL_100(pincap))
+ w->wclass.pin.ctrl |=
+ HDA_CMD_SET_PIN_WIDGET_CTRL_VREF_ENABLE(
+ HDA_CMD_PIN_WIDGET_CTRL_VREF_ENABLE_100);
+ else if ((devinfo->function.audio.quirks & HDA_QUIRK_OVREF80) &&
+ HDA_PARAM_PIN_CAP_VREF_CTRL_80(pincap))
+ w->wclass.pin.ctrl |=
+ HDA_CMD_SET_PIN_WIDGET_CTRL_VREF_ENABLE(
+ HDA_CMD_PIN_WIDGET_CTRL_VREF_ENABLE_80);
+ else if ((devinfo->function.audio.quirks & HDA_QUIRK_OVREF50) &&
+ HDA_PARAM_PIN_CAP_VREF_CTRL_50(pincap))
+ w->wclass.pin.ctrl |=
+ HDA_CMD_SET_PIN_WIDGET_CTRL_VREF_ENABLE(
+ HDA_CMD_PIN_WIDGET_CTRL_VREF_ENABLE_50);
+ } else if (w->pflags & HDA_ADC_PATH) {
+ w->wclass.pin.ctrl &=
+ ~(HDA_CMD_SET_PIN_WIDGET_CTRL_OUT_ENABLE |
+ HDA_CMD_SET_PIN_WIDGET_CTRL_HPHN_ENABLE);
+ if ((devinfo->function.audio.quirks & HDA_QUIRK_IVREF100) &&
+ HDA_PARAM_PIN_CAP_VREF_CTRL_100(pincap))
+ w->wclass.pin.ctrl |=
+ HDA_CMD_SET_PIN_WIDGET_CTRL_VREF_ENABLE(
+ HDA_CMD_PIN_WIDGET_CTRL_VREF_ENABLE_100);
+ else if ((devinfo->function.audio.quirks & HDA_QUIRK_IVREF80) &&
+ HDA_PARAM_PIN_CAP_VREF_CTRL_80(pincap))
+ w->wclass.pin.ctrl |=
+ HDA_CMD_SET_PIN_WIDGET_CTRL_VREF_ENABLE(
+ HDA_CMD_PIN_WIDGET_CTRL_VREF_ENABLE_80);
+ else if ((devinfo->function.audio.quirks & HDA_QUIRK_IVREF50) &&
+ HDA_PARAM_PIN_CAP_VREF_CTRL_50(pincap))
+ w->wclass.pin.ctrl |=
+ HDA_CMD_SET_PIN_WIDGET_CTRL_VREF_ENABLE(
+ HDA_CMD_PIN_WIDGET_CTRL_VREF_ENABLE_50);
+ } else
+ w->wclass.pin.ctrl &= ~(
+ HDA_CMD_SET_PIN_WIDGET_CTRL_HPHN_ENABLE |
+ HDA_CMD_SET_PIN_WIDGET_CTRL_OUT_ENABLE |
+ HDA_CMD_SET_PIN_WIDGET_CTRL_IN_ENABLE |
+ HDA_CMD_SET_PIN_WIDGET_CTRL_VREF_ENABLE_MASK);
+ hdac_command(sc,
+ HDA_CMD_SET_PIN_WIDGET_CTRL(cad, w->nid,
+ w->wclass.pin.ctrl), cad);
+ }
+ if ((cfl & HDA_COMMIT_EAPD) &&
+ w->param.eapdbtl != HDAC_INVALID) {
+ uint32_t val;
+
+ val = w->param.eapdbtl;
+ if (devinfo->function.audio.quirks &
+ HDA_QUIRK_EAPDINV)
+ val ^= HDA_CMD_SET_EAPD_BTL_ENABLE_EAPD;
+ hdac_command(sc,
+ HDA_CMD_SET_EAPD_BTL_ENABLE(cad, w->nid,
+ val), cad);
+
+ }
+ DELAY(1000);
+ }
}
static void
hdac_audio_ctl_commit(struct hdac_devinfo *devinfo)
{
-struct hdac_softc *sc = devinfo->codec->sc;
-struct hdac_audio_ctl *ctl;
-int i;
-
-devinfo->function.audio.mvol = 100 | (100 << 8);
-i = 0;
-while ((ctl = hdac_audio_ctl_each(devinfo, &i)) != NULL) {
-if (ctl->enable == 0 || ctl->widget == NULL) {
-HDA_BOOTVERBOSE(
-device_printf(sc->dev, "[%2d] Ctl nid=%d",
-i, (ctl->widget != NULL) ?
-ctl->widget->nid : -1);
-if (ctl->childwidget != NULL)
-printf(" childnid=%d",
-ctl->childwidget->nid);
-if (ctl->widget == NULL)
-printf(" NULL WIDGET!");
-printf(" DISABLEDn");
-);
-continue;
-}
-HDA_BOOTVERBOSE(
-if (ctl->ossmask == 0) {
-device_printf(sc->dev, "[%2d] Ctl nid=%d",
-i, ctl->widget->nid);
-if (ctl->childwidget != NULL)
-printf(" childnid=%d",
-ctl->childwidget->nid);
-printf(" Bind to NONEn");
-}
-);
-if (ctl->step > 0) {
-ctl->ossval = (ctl->left * 100) / ctl->step;
-ctl->ossval |= ((ctl->right * 100) / ctl->step) << 8;
-} else
-ctl->ossval = 0;
-hdac_audio_ctl_amp_set(ctl, HDA_AMP_MUTE_DEFAULT,
-ctl->left, ctl->right);
-}
+ struct hdac_softc *sc = devinfo->codec->sc;
+ struct hdac_audio_ctl *ctl;
+ int i;
+
+ devinfo->function.audio.mvol = 100 | (100 << 8);
+ i = 0;
+ while ((ctl = hdac_audio_ctl_each(devinfo, &i)) != NULL) {
+ if (ctl->enable == 0 || ctl->widget == NULL) {
+ HDA_BOOTVERBOSE(
+ device_printf(sc->dev, "[%2d] Ctl nid=%d",
+ i, (ctl->widget != NULL) ?
+ ctl->widget->nid : -1);
+ if (ctl->childwidget != NULL)
+ printf(" childnid=%d",
+ ctl->childwidget->nid);
+ if (ctl->widget == NULL)
+ printf(" NULL WIDGET!");
+ printf(" DISABLED\n");
+ );
+ continue;
+ }
+ HDA_BOOTVERBOSE(
+ if (ctl->ossmask == 0) {
+ device_printf(sc->dev, "[%2d] Ctl nid=%d",
+ i, ctl->widget->nid);
+ if (ctl->childwidget != NULL)
+ printf(" childnid=%d",
+ ctl->childwidget->nid);
+ printf(" Bind to NONE\n");
+ }
+ );
+ if (ctl->step > 0) {
+ ctl->ossval = (ctl->left * 100) / ctl->step;
+ ctl->ossval |= ((ctl->right * 100) / ctl->step) << 8;
+ } else
+ ctl->ossval = 0;
+ hdac_audio_ctl_amp_set(ctl, HDA_AMP_MUTE_DEFAULT,
+ ctl->left, ctl->right);
+ }
}
static int
hdac_pcmchannel_setup(struct hdac_devinfo *devinfo, int dir)
{
-struct hdac_chan *ch;
-struct hdac_widget *w;
-uint32_t cap, fmtcap, pcmcap, path;
-int i, type, ret, max;
-
-if (dir == PCMDIR_PLAY) {
-type = HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_OUTPUT;
-ch = &devinfo->codec->sc->play;
-path = HDA_DAC_PATH;
-} else {
-type = HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_INPUT;
-ch = &devinfo->codec->sc->rec;
-path = HDA_ADC_PATH;
-}
-
-ch->caps = hdac_caps;
-ch->caps.fmtlist = ch->fmtlist;
-ch->bit16 = 1;
-ch->bit32 = 0;
-ch->pcmrates[0] = 48000;
-ch->pcmrates[1] = 0;
-
-ret = 0;
-fmtcap = devinfo->function.audio.supp_stream_formats;
-pcmcap = devinfo->function.audio.supp_pcm_size_rate;
-max = (sizeof(ch->io) / sizeof(ch->io[0])) - 1;
-
-for (i = devinfo->startnode; i < devinfo->endnode && ret < max; i++) {
-w = hdac_widget_get(devinfo, i);
-if (w == NULL || w->enable == 0 || w->type != type ||
-!(w->pflags & path))
-continue;
-cap = w->param.widget_cap;
-/*if (HDA_PARAM_AUDIO_WIDGET_CAP_DIGITAL(cap))
-continue;*/
-if (!HDA_PARAM_AUDIO_WIDGET_CAP_STEREO(cap))
-continue;
-cap = w->param.supp_stream_formats;
-/*if (HDA_PARAM_SUPP_STREAM_FORMATS_AC3(cap)) {
-}
-if (HDA_PARAM_SUPP_STREAM_FORMATS_FLOAT32(cap)) {
-}*/
-if (!HDA_PARAM_SUPP_STREAM_FORMATS_PCM(cap))
-continue;
-ch->io[ret++] = i;
-fmtcap &= w->param.supp_stream_formats;
-pcmcap &= w->param.supp_pcm_size_rate;
-}
-ch->io[ret] = -1;
+ struct hdac_chan *ch;
+ struct hdac_widget *w;
+ uint32_t cap, fmtcap, pcmcap, path;
+ int i, type, ret, max;
+
+ if (dir == PCMDIR_PLAY) {
+ type = HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_OUTPUT;
+ ch = &devinfo->codec->sc->play;
+ path = HDA_DAC_PATH;
+ } else {
+ type = HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_INPUT;
+ ch = &devinfo->codec->sc->rec;
+ path = HDA_ADC_PATH;
+ }
+
+ ch->caps = hdac_caps;
+ ch->caps.fmtlist = ch->fmtlist;
+ ch->bit16 = 1;
+ ch->bit32 = 0;
+ ch->pcmrates[0] = 48000;
+ ch->pcmrates[1] = 0;
+
+ ret = 0;
+ fmtcap = devinfo->function.audio.supp_stream_formats;
+ pcmcap = devinfo->function.audio.supp_pcm_size_rate;
+ max = (sizeof(ch->io) / sizeof(ch->io[0])) - 1;
+
+ for (i = devinfo->startnode; i < devinfo->endnode && ret < max; i++) {
+ w = hdac_widget_get(devinfo, i);
+ if (w == NULL || w->enable == 0 || w->type != type ||
+ !(w->pflags & path))
+ continue;
+ cap = w->param.widget_cap;
+ /*if (HDA_PARAM_AUDIO_WIDGET_CAP_DIGITAL(cap))
+ continue;*/
+ if (!HDA_PARAM_AUDIO_WIDGET_CAP_STEREO(cap))
+ continue;
+ cap = w->param.supp_stream_formats;
+ /*if (HDA_PARAM_SUPP_STREAM_FORMATS_AC3(cap)) {
+ }
+ if (HDA_PARAM_SUPP_STREAM_FORMATS_FLOAT32(cap)) {
+ }*/
+ if (!HDA_PARAM_SUPP_STREAM_FORMATS_PCM(cap))
+ continue;
+ if (ret == 0) {
+ fmtcap = w->param.supp_stream_formats;
+ pcmcap = w->param.supp_pcm_size_rate;
+ } else {
+ fmtcap &= w->param.supp_stream_formats;
+ pcmcap &= w->param.supp_pcm_size_rate;
+ }
+ ch->io[ret++] = i;
+ }
+ ch->io[ret] = -1;
+
+ ch->supp_stream_formats = fmtcap;
+ ch->supp_pcm_size_rate = pcmcap;
+
+ /*
+ * 8bit = 0
+ * 16bit = 1
+ * 20bit = 2
+ * 24bit = 3
+ * 32bit = 4
+ */
+ if (ret > 0) {
+ cap = pcmcap;
+ if (HDA_PARAM_SUPP_PCM_SIZE_RATE_16BIT(cap))
+ ch->bit16 = 1;
+ else if (HDA_PARAM_SUPP_PCM_SIZE_RATE_8BIT(cap))
+ ch->bit16 = 0;
+ if (HDA_PARAM_SUPP_PCM_SIZE_RATE_32BIT(cap))
+ ch->bit32 = 4;
+ else if (HDA_PARAM_SUPP_PCM_SIZE_RATE_24BIT(cap))
+ ch->bit32 = 3;
+ else if (HDA_PARAM_SUPP_PCM_SIZE_RATE_20BIT(cap))
+ ch->bit32 = 2;
+ i = 0;
+ if (!(devinfo->function.audio.quirks & HDA_QUIRK_FORCESTEREO))
+ ch->fmtlist[i++] = AFMT_S16_LE;
+ ch->fmtlist[i++] = AFMT_S16_LE | AFMT_STEREO;
+ if (ch->bit32 > 0) {
+ if (!(devinfo->function.audio.quirks &
+ HDA_QUIRK_FORCESTEREO))
+ ch->fmtlist[i++] = AFMT_S32_LE;
+ ch->fmtlist[i++] = AFMT_S32_LE | AFMT_STEREO;
+ }
+ ch->fmtlist[i] = 0;
+ i = 0;
+ if (HDA_PARAM_SUPP_PCM_SIZE_RATE_8KHZ(cap))
+ ch->pcmrates[i++] = 8000;
+ if (HDA_PARAM_SUPP_PCM_SIZE_RATE_11KHZ(cap))
+ ch->pcmrates[i++] = 11025;
+ if (HDA_PARAM_SUPP_PCM_SIZE_RATE_16KHZ(cap))
+ ch->pcmrates[i++] = 16000;
+ if (HDA_PARAM_SUPP_PCM_SIZE_RATE_22KHZ(cap))
+ ch->pcmrates[i++] = 22050;
+ if (HDA_PARAM_SUPP_PCM_SIZE_RATE_32KHZ(cap))
+ ch->pcmrates[i++] = 32000;
+ if (HDA_PARAM_SUPP_PCM_SIZE_RATE_44KHZ(cap))
+ ch->pcmrates[i++] = 44100;
+ /* if (HDA_PARAM_SUPP_PCM_SIZE_RATE_48KHZ(cap)) */
+ ch->pcmrates[i++] = 48000;
+ if (HDA_PARAM_SUPP_PCM_SIZE_RATE_88KHZ(cap))
+ ch->pcmrates[i++] = 88200;
+ if (HDA_PARAM_SUPP_PCM_SIZE_RATE_96KHZ(cap))
+ ch->pcmrates[i++] = 96000;
+ if (HDA_PARAM_SUPP_PCM_SIZE_RATE_176KHZ(cap))
+ ch->pcmrates[i++] = 176400;
+ if (HDA_PARAM_SUPP_PCM_SIZE_RATE_192KHZ(cap))
+ ch->pcmrates[i++] = 192000;
+ /* if (HDA_PARAM_SUPP_PCM_SIZE_RATE_384KHZ(cap)) */
+ ch->pcmrates[i] = 0;
+ if (i > 0) {
+ ch->caps.minspeed = ch->pcmrates[0];
+ ch->caps.maxspeed = ch->pcmrates[i - 1];
+ }
+ }
-ch->supp_stream_formats = fmtcap;
-ch->supp_pcm_size_rate = pcmcap;
-
-/*
-* 8bit = 0
-* 16bit = 1
-* 20bit = 2
-* 24bit = 3
-* 32bit = 4
-*/
-if (ret > 0) {
-cap = pcmcap;
-if (HDA_PARAM_SUPP_PCM_SIZE_RATE_16BIT(cap))
-ch->bit16 = 1;
-else if (HDA_PARAM_SUPP_PCM_SIZE_RATE_8BIT(cap))
-ch->bit16 = 0;
-if (HDA_PARAM_SUPP_PCM_SIZE_RATE_32BIT(cap))
-ch->bit32 = 4;
-else if (HDA_PARAM_SUPP_PCM_SIZE_RATE_24BIT(cap))
-ch->bit32 = 3;
-else if (HDA_PARAM_SUPP_PCM_SIZE_RATE_20BIT(cap))
-ch->bit32 = 2;
-i = 0;
-if (!(devinfo->function.audio.quirks & HDA_QUIRK_FORCESTEREO))
-ch->fmtlist[i++] = AFMT_S16_LE;
-ch->fmtlist[i++] = AFMT_S16_LE | AFMT_STEREO;
-if (ch->bit32 > 0) {
-if (!(devinfo->function.audio.quirks &
-HDA_QUIRK_FORCESTEREO))
-ch->fmtlist[i++] = AFMT_S32_LE;
-ch->fmtlist[i++] = AFMT_S32_LE | AFMT_STEREO;
-}
-ch->fmtlist[i] = 0;
-i = 0;
-if (HDA_PARAM_SUPP_PCM_SIZE_RATE_8KHZ(cap))
-ch->pcmrates[i++] = 8000;
-if (HDA_PARAM_SUPP_PCM_SIZE_RATE_11KHZ(cap))
-ch->pcmrates[i++] = 11025;
-if (HDA_PARAM_SUPP_PCM_SIZE_RATE_16KHZ(cap))
-ch->pcmrates[i++] = 16000;
-if (HDA_PARAM_SUPP_PCM_SIZE_RATE_22KHZ(cap))
-ch->pcmrates[i++] = 22050;
-if (HDA_PARAM_SUPP_PCM_SIZE_RATE_32KHZ(cap))
-ch->pcmrates[i++] = 32000;
-if (HDA_PARAM_SUPP_PCM_SIZE_RATE_44KHZ(cap))
-ch->pcmrates[i++] = 44100;
-/* if (HDA_PARAM_SUPP_PCM_SIZE_RATE_48KHZ(cap)) */
-ch->pcmrates[i++] = 48000;
-if (HDA_PARAM_SUPP_PCM_SIZE_RATE_88KHZ(cap))
-ch->pcmrates[i++] = 88200;
-if (HDA_PARAM_SUPP_PCM_SIZE_RATE_96KHZ(cap))
-ch->pcmrates[i++] = 96000;
-if (HDA_PARAM_SUPP_PCM_SIZE_RATE_176KHZ(cap))
-ch->pcmrates[i++] = 176400;
-if (HDA_PARAM_SUPP_PCM_SIZE_RATE_192KHZ(cap))
-ch->pcmrates[i++] = 192000;
-/* if (HDA_PARAM_SUPP_PCM_SIZE_RATE_384KHZ(cap)) */
-ch->pcmrates[i] = 0;
-if (i > 0) {
-ch->caps.minspeed = ch->pcmrates[0];
-ch->caps.maxspeed = ch->pcmrates[i - 1];
-}
-}
-
-return (ret);
+ return (ret);
}
static void
hdac_dump_ctls(struct hdac_devinfo *devinfo, const char *banner, uint32_t flag)
{
-struct hdac_audio_ctl *ctl;
-struct hdac_softc *sc = devinfo->codec->sc;
-int i;
-uint32_t fl = 0;
+ struct hdac_audio_ctl *ctl;
+ struct hdac_softc *sc = devinfo->codec->sc;
+ int i;
+ uint32_t fl = 0;
+
+
+ if (flag == 0) {
+ fl = SOUND_MASK_VOLUME | SOUND_MASK_PCM |
+ SOUND_MASK_CD | SOUND_MASK_LINE | SOUND_MASK_RECLEV |
+ SOUND_MASK_MIC | SOUND_MASK_SPEAKER | SOUND_MASK_OGAIN;
+ }
+
+ i = 0;
+ while ((ctl = hdac_audio_ctl_each(devinfo, &i)) != NULL) {
+ if (ctl->enable == 0 || ctl->widget == NULL ||
+ ctl->widget->enable == 0 || (ctl->ossmask &
+ (SOUND_MASK_SKIP | SOUND_MASK_DISABLE)))
+ continue;
+ if ((flag == 0 && (ctl->ossmask & ~fl)) ||
+ (flag != 0 && (ctl->ossmask & flag))) {
+ if (banner != NULL) {
+ device_printf(sc->dev, "\n");
+ device_printf(sc->dev, "%s\n", banner);
+ }
+ goto hdac_ctl_dump_it_all;
+ }
+ }
-
-if (flag == 0) {
-fl = SOUND_MASK_VOLUME | SOUND_MASK_PCM |
-SOUND_MASK_CD | SOUND_MASK_LINE | SOUND_MASK_RECLEV |
-SOUND_MASK_MIC | SOUND_MASK_SPEAKER | SOUND_MASK_OGAIN;
-}
-
-i = 0;
-while ((ctl = hdac_audio_ctl_each(devinfo, &i)) != NULL) {
-if (ctl->enable == 0 || ctl->widget == NULL ||
-ctl->widget->enable == 0)
-continue;
-if ((flag == 0 && (ctl->ossmask & ~fl)) ||
-(flag != 0 && (ctl->ossmask & flag))) {
-if (banner != NULL) {
-device_printf(sc->dev, "n");
-device_printf(sc->dev, "%sn", banner);
-}
-goto hdac_ctl_dump_it_all;
-}
-}
-
-return;
+ return;
hdac_ctl_dump_it_all:
-i = 0;
-while ((ctl = hdac_audio_ctl_each(devinfo, &i)) != NULL) {
-if (ctl->enable == 0 || ctl->widget == NULL ||
-ctl->widget->enable == 0)
-continue;
-if (!((flag == 0 && (ctl->ossmask & ~fl)) ||
-(flag != 0 && (ctl->ossmask & flag))))
-continue;
-if (flag == 0) {
-device_printf(sc->dev, "n");
-device_printf(sc->dev, "Unknown Ctl (OSS: %s)n",
-hdac_audio_ctl_ossmixer_mask2name(ctl->ossmask));
-}
-device_printf(sc->dev, " |n");
-device_printf(sc->dev, " +- nid: %2d index: %2d ",
-ctl->widget->nid, ctl->index);
-if (ctl->childwidget != NULL)
-printf("(nid: %2d) ", ctl->childwidget->nid);
-else
-printf(" ");
-printf("mute: %d step: %3d size: %3d off: %3d dir=0x%x ossmask=0x%08xn",
-ctl->mute, ctl->step, ctl->size, ctl->offset, ctl->dir,
-ctl->ossmask);
-}
+ i = 0;
+ while ((ctl = hdac_audio_ctl_each(devinfo, &i)) != NULL) {
+ if (ctl->enable == 0 || ctl->widget == NULL ||
+ ctl->widget->enable == 0)
+ continue;
+ if (!((flag == 0 && (ctl->ossmask & ~fl)) ||
+ (flag != 0 && (ctl->ossmask & flag))))
+ continue;
+ if (flag == 0) {
+ device_printf(sc->dev, "\n");
+ device_printf(sc->dev, "Unknown Ctl (OSS: %s)\n",
+ hdac_audio_ctl_ossmixer_mask2name(ctl->ossmask));
+ }
+ device_printf(sc->dev, " |\n");
+ device_printf(sc->dev, " +- nid: %2d index: %2d ",
+ ctl->widget->nid, ctl->index);
+ if (ctl->childwidget != NULL)
+ printf("(nid: %2d) ", ctl->childwidget->nid);
+ else
+ printf(" ");
+ printf("mute: %d step: %3d size: %3d off: %3d dir=0x%x ossmask=0x%08x\n",
+ ctl->mute, ctl->step, ctl->size, ctl->offset, ctl->dir,
+ ctl->ossmask);
+ }
}
static void
hdac_dump_audio_formats(struct hdac_softc *sc, uint32_t fcap, uint32_t pcmcap)
{
-uint32_t cap;
+ uint32_t cap;
-cap = fcap;
-if (cap != 0) {
-device_printf(sc->dev, " Stream cap: 0x%08xn", cap);
-device_printf(sc->dev, " Format:");
-if (HDA_PARAM_SUPP_STREAM_FORMATS_AC3(cap))
-printf(" AC3");
-if (HDA_PARAM_SUPP_STREAM_FORMATS_FLOAT32(cap))
-printf(" FLOAT32");
-if (HDA_PARAM_SUPP_STREAM_FORMATS_PCM(cap))
-printf(" PCM");
-printf("n");
-}
-cap = pcmcap;
-if (cap != 0) {
-device_printf(sc->dev, " PCM cap: 0x%08xn", cap);
-device_printf(sc->dev, " PCM size:");
-if (HDA_PARAM_SUPP_PCM_SIZE_RATE_8BIT(cap))
-printf(" 8");
-if (HDA_PARAM_SUPP_PCM_SIZE_RATE_16BIT(cap))
-printf(" 16");
-if (HDA_PARAM_SUPP_PCM_SIZE_RATE_20BIT(cap))
-printf(" 20");
-if (HDA_PARAM_SUPP_PCM_SIZE_RATE_24BIT(cap))
-printf(" 24");
-if (HDA_PARAM_SUPP_PCM_SIZE_RATE_32BIT(cap))
-printf(" 32");
-printf("n");
-device_printf(sc->dev, " PCM rate:");
-if (HDA_PARAM_SUPP_PCM_SIZE_RATE_8KHZ(cap))
-printf(" 8");
-if (HDA_PARAM_SUPP_PCM_SIZE_RATE_11KHZ(cap))
-printf(" 11");
-if (HDA_PARAM_SUPP_PCM_SIZE_RATE_16KHZ(cap))
-printf(" 16");
-if (HDA_PARAM_SUPP_PCM_SIZE_RATE_22KHZ(cap))
-printf(" 22");
-if (HDA_PARAM_SUPP_PCM_SIZE_RATE_32KHZ(cap))
-printf(" 32");
-if (HDA_PARAM_SUPP_PCM_SIZE_RATE_44KHZ(cap))
-printf(" 44");
-printf(" 48");
-if (HDA_PARAM_SUPP_PCM_SIZE_RATE_88KHZ(cap))
-printf(" 88");
-if (HDA_PARAM_SUPP_PCM_SIZE_RATE_96KHZ(cap))
-printf(" 96");
-if (HDA_PARAM_SUPP_PCM_SIZE_RATE_176KHZ(cap))
-printf(" 176");
-if (HDA_PARAM_SUPP_PCM_SIZE_RATE_192KHZ(cap))
-printf(" 192");
-printf("n");
-}
+ cap = fcap;
+ if (cap != 0) {
+ device_printf(sc->dev, " Stream cap: 0x%08x\n", cap);
+ device_printf(sc->dev, " Format:");
+ if (HDA_PARAM_SUPP_STREAM_FORMATS_AC3(cap))
+ printf(" AC3");
+ if (HDA_PARAM_SUPP_STREAM_FORMATS_FLOAT32(cap))
+ printf(" FLOAT32");
+ if (HDA_PARAM_SUPP_STREAM_FORMATS_PCM(cap))
+ printf(" PCM");
+ printf("\n");
+ }
+ cap = pcmcap;
+ if (cap != 0) {
+ device_printf(sc->dev, " PCM cap: 0x%08x\n", cap);
+ device_printf(sc->dev, " PCM size:");
+ if (HDA_PARAM_SUPP_PCM_SIZE_RATE_8BIT(cap))
+ printf(" 8");
+ if (HDA_PARAM_SUPP_PCM_SIZE_RATE_16BIT(cap))
+ printf(" 16");
+ if (HDA_PARAM_SUPP_PCM_SIZE_RATE_20BIT(cap))
+ printf(" 20");
+ if (HDA_PARAM_SUPP_PCM_SIZE_RATE_24BIT(cap))
+ printf(" 24");
+ if (HDA_PARAM_SUPP_PCM_SIZE_RATE_32BIT(cap))
+ printf(" 32");
+ printf("\n");
+ device_printf(sc->dev, " PCM rate:");
+ if (HDA_PARAM_SUPP_PCM_SIZE_RATE_8KHZ(cap))
+ printf(" 8");
+ if (HDA_PARAM_SUPP_PCM_SIZE_RATE_11KHZ(cap))
+ printf(" 11");
+ if (HDA_PARAM_SUPP_PCM_SIZE_RATE_16KHZ(cap))
+ printf(" 16");
+ if (HDA_PARAM_SUPP_PCM_SIZE_RATE_22KHZ(cap))
+ printf(" 22");
+ if (HDA_PARAM_SUPP_PCM_SIZE_RATE_32KHZ(cap))
+ printf(" 32");
+ if (HDA_PARAM_SUPP_PCM_SIZE_RATE_44KHZ(cap))
+ printf(" 44");
+ printf(" 48");
+ if (HDA_PARAM_SUPP_PCM_SIZE_RATE_88KHZ(cap))
+ printf(" 88");
+ if (HDA_PARAM_SUPP_PCM_SIZE_RATE_96KHZ(cap))
+ printf(" 96");
+ if (HDA_PARAM_SUPP_PCM_SIZE_RATE_176KHZ(cap))
+ printf(" 176");
+ if (HDA_PARAM_SUPP_PCM_SIZE_RATE_192KHZ(cap))
+ printf(" 192");
+ printf("\n");
+ }
}
static void
hdac_dump_pin(struct hdac_softc *sc, struct hdac_widget *w)
{
-uint32_t pincap, wcap;
+ uint32_t pincap, wcap;
-pincap = w->wclass.pin.cap;
-wcap = w->param.widget_cap;
+ pincap = w->wclass.pin.cap;
+ wcap = w->param.widget_cap;
-device_printf(sc->dev, " Pin cap: 0x%08xn", pincap);
-device_printf(sc->dev, " ");
-if (HDA_PARAM_PIN_CAP_IMP_SENSE_CAP(pincap))
-printf(" ISC");
-if (HDA_PARAM_PIN_CAP_TRIGGER_REQD(pincap))
-printf(" TRQD");
-if (HDA_PARAM_PIN_CAP_PRESENCE_DETECT_CAP(pincap))
-printf(" PDC");
-if (HDA_PARAM_PIN_CAP_HEADPHONE_CAP(pincap))
-printf(" HP");
-if (HDA_PARAM_PIN_CAP_OUTPUT_CAP(pincap))
-printf(" OUT");
-if (HDA_PARAM_PIN_CAP_INPUT_CAP(pincap))
-printf(" IN");
-if (HDA_PARAM_PIN_CAP_BALANCED_IO_PINS(pincap))
-printf(" BAL");
-if (HDA_PARAM_PIN_CAP_EAPD_CAP(pincap))
-printf(" EAPD");
-if (HDA_PARAM_AUDIO_WIDGET_CAP_UNSOL_CAP(wcap))
-printf(" : UNSOL");
-printf("n");
-device_printf(sc->dev, " Pin config: 0x%08xn",
-w->wclass.pin.config);
-device_printf(sc->dev, " Pin control: 0x%08x", w->wclass.pin.ctrl);
-if (w->wclass.pin.ctrl & HDA_CMD_SET_PIN_WIDGET_CTRL_HPHN_ENABLE)
-printf(" HP");
-if (w->wclass.pin.ctrl & HDA_CMD_SET_PIN_WIDGET_CTRL_IN_ENABLE)
-printf(" IN");
-if (w->wclass.pin.ctrl & HDA_CMD_SET_PIN_WIDGET_CTRL_OUT_ENABLE)
-printf(" OUT");
-printf("n");
+ device_printf(sc->dev, " Pin cap: 0x%08x\n", pincap);
+ device_printf(sc->dev, " ");
+ if (HDA_PARAM_PIN_CAP_IMP_SENSE_CAP(pincap))
+ printf(" ISC");
+ if (HDA_PARAM_PIN_CAP_TRIGGER_REQD(pincap))
+ printf(" TRQD");
+ if (HDA_PARAM_PIN_CAP_PRESENCE_DETECT_CAP(pincap))
+ printf(" PDC");
+ if (HDA_PARAM_PIN_CAP_HEADPHONE_CAP(pincap))
+ printf(" HP");
+ if (HDA_PARAM_PIN_CAP_OUTPUT_CAP(pincap))
+ printf(" OUT");
+ if (HDA_PARAM_PIN_CAP_INPUT_CAP(pincap))
+ printf(" IN");
+ if (HDA_PARAM_PIN_CAP_BALANCED_IO_PINS(pincap))
+ printf(" BAL");
+ if (HDA_PARAM_PIN_CAP_VREF_CTRL(pincap)) {
+ printf(" VREF[");
+ if (HDA_PARAM_PIN_CAP_VREF_CTRL_50(pincap))
+ printf(" 50");
+ if (HDA_PARAM_PIN_CAP_VREF_CTRL_80(pincap))
+ printf(" 80");
+ if (HDA_PARAM_PIN_CAP_VREF_CTRL_100(pincap))
+ printf(" 100");
+ if (HDA_PARAM_PIN_CAP_VREF_CTRL_GROUND(pincap))
+ printf(" GROUND");
+ if (HDA_PARAM_PIN_CAP_VREF_CTRL_HIZ(pincap))
+ printf(" HIZ");
+ printf(" ]");
+ }
+ if (HDA_PARAM_PIN_CAP_EAPD_CAP(pincap))
+ printf(" EAPD");
+ if (HDA_PARAM_AUDIO_WIDGET_CAP_UNSOL_CAP(wcap))
+ printf(" : UNSOL");
+ printf("\n");
+ device_printf(sc->dev, " Pin config: 0x%08x\n",
+ w->wclass.pin.config);
+ device_printf(sc->dev, " Pin control: 0x%08x", w->wclass.pin.ctrl);
+ if (w->wclass.pin.ctrl & HDA_CMD_SET_PIN_WIDGET_CTRL_HPHN_ENABLE)
+ printf(" HP");
+ if (w->wclass.pin.ctrl & HDA_CMD_SET_PIN_WIDGET_CTRL_IN_ENABLE)
+ printf(" IN");
+ if (w->wclass.pin.ctrl & HDA_CMD_SET_PIN_WIDGET_CTRL_OUT_ENABLE)
+ printf(" OUT");
+ printf("\n");
}
static void
hdac_dump_amp(struct hdac_softc *sc, uint32_t cap, char *banner)
{
-device_printf(sc->dev, " %s amp: 0x%08xn", banner, cap);
-device_printf(sc->dev, " "
-"mute=%d step=%d size=%d offset=%dn",
-HDA_PARAM_OUTPUT_AMP_CAP_MUTE_CAP(cap),
-HDA_PARAM_OUTPUT_AMP_CAP_NUMSTEPS(cap),
-HDA_PARAM_OUTPUT_AMP_CAP_STEPSIZE(cap),
-HDA_PARAM_OUTPUT_AMP_CAP_OFFSET(cap));
+ device_printf(sc->dev, " %s amp: 0x%08x\n", banner, cap);
+ device_printf(sc->dev, " "
+ "mute=%d step=%d size=%d offset=%d\n",
+ HDA_PARAM_OUTPUT_AMP_CAP_MUTE_CAP(cap),
+ HDA_PARAM_OUTPUT_AMP_CAP_NUMSTEPS(cap),
+ HDA_PARAM_OUTPUT_AMP_CAP_STEPSIZE(cap),
+ HDA_PARAM_OUTPUT_AMP_CAP_OFFSET(cap));
}
static void
hdac_dump_nodes(struct hdac_devinfo *devinfo)
{
-struct hdac_softc *sc = devinfo->codec->sc;
-struct hdac_widget *w, *cw;
-int i, j;
-
-device_printf(sc->dev, "n");
-device_printf(sc->dev, "Default Parametern");
-device_printf(sc->dev, "-----------------n");
-hdac_dump_audio_formats(sc,
-devinfo->function.audio.supp_stream_formats,
-devinfo->function.audio.supp_pcm_size_rate);
-device_printf(sc->dev, " IN amp: 0x%08xn",
-devinfo->function.audio.inamp_cap);
-device_printf(sc->dev, " OUT amp: 0x%08xn",
-devinfo->function.audio.outamp_cap);
-for (i = devinfo->startnode; i < devinfo->endnode; i++) {
-w = hdac_widget_get(devinfo, i);
-if (w == NULL) {
-device_printf(sc->dev, "Ghost widget nid=%dn", i);
-continue;
-}
-device_printf(sc->dev, "n");
-device_printf(sc->dev, " nid: %d [%s]%sn", w->nid,
-HDA_PARAM_AUDIO_WIDGET_CAP_DIGITAL(w->param.widget_cap) ?
-"DIGITAL" : "ANALOG",
-(w->enable == 0) ? " [DISABLED]" : "");
-device_printf(sc->dev, " name: %sn", w->name);
-device_printf(sc->dev, " widget_cap: 0x%08xn",
-w->param.widget_cap);
-device_printf(sc->dev, " Parse flags: 0x%08xn",
-w->pflags);
-device_printf(sc->dev, " Ctl flags: 0x%08xn",
-w->ctlflags);
-if (w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_OUTPUT ||
-w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_INPUT) {
-hdac_dump_audio_formats(sc,
-w->param.supp_stream_formats,
-w->param.supp_pcm_size_rate);
-} else if (w->type ==
-HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX)
-hdac_dump_pin(sc, w);
-if (w->param.eapdbtl != HDAC_INVALID)
-device_printf(sc->dev, " EAPD: 0x%08xn",
-w->param.eapdbtl);
-if (HDA_PARAM_AUDIO_WIDGET_CAP_OUT_AMP(w->param.widget_cap) &&
-w->param.outamp_cap != 0)
-hdac_dump_amp(sc, w->param.outamp_cap, "Output");
-if (HDA_PARAM_AUDIO_WIDGET_CAP_IN_AMP(w->param.widget_cap) &&
-w->param.inamp_cap != 0)
-hdac_dump_amp(sc, w->param.inamp_cap, " Input");
-device_printf(sc->dev, " connections: %dn", w->nconns);
-for (j = 0; j < w->nconns; j++) {
-cw = hdac_widget_get(devinfo, w->conns[j]);
-device_printf(sc->dev, " |n");
-device_printf(sc->dev, " + <- nid=%d [%s]",
-w->conns[j], (cw == NULL) ? "GHOST!" : cw->name);
-if (cw == NULL)
-printf(" [UNKNOWN]");
-else if (cw->enable == 0)
-printf(" [DISABLED]");
-if (w->nconns > 1 && w->selconn == j && w->type !=
-HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_MIXER)
-printf(" (selected)");
-printf("n");
-}
-}
+ struct hdac_softc *sc = devinfo->codec->sc;
+ struct hdac_widget *w, *cw;
+ int i, j;
+
+ device_printf(sc->dev, "\n");
+ device_printf(sc->dev, "Default Parameter\n");
+ device_printf(sc->dev, "-----------------\n");
+ hdac_dump_audio_formats(sc,
+ devinfo->function.audio.supp_stream_formats,
+ devinfo->function.audio.supp_pcm_size_rate);
+ device_printf(sc->dev, " IN amp: 0x%08x\n",
+ devinfo->function.audio.inamp_cap);
+ device_printf(sc->dev, " OUT amp: 0x%08x\n",
+ devinfo->function.audio.outamp_cap);
+ for (i = devinfo->startnode; i < devinfo->endnode; i++) {
+ w = hdac_widget_get(devinfo, i);
+ if (w == NULL) {
+ device_printf(sc->dev, "Ghost widget nid=%d\n", i);
+ continue;
+ }
+ device_printf(sc->dev, "\n");
+ device_printf(sc->dev, " nid: %d [%s]%s\n", w->nid,
+ HDA_PARAM_AUDIO_WIDGET_CAP_DIGITAL(w->param.widget_cap) ?
+ "DIGITAL" : "ANALOG",
+ (w->enable == 0) ? " [DISABLED]" : "");
+ device_printf(sc->dev, " name: %s\n", w->name);
+ device_printf(sc->dev, " widget_cap: 0x%08x\n",
+ w->param.widget_cap);
+ device_printf(sc->dev, " Parse flags: 0x%08x\n",
+ w->pflags);
+ device_printf(sc->dev, " Ctl flags: 0x%08x\n",
+ w->ctlflags);
+ if (w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_OUTPUT ||
+ w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_INPUT) {
+ hdac_dump_audio_formats(sc,
+ w->param.supp_stream_formats,
+ w->param.supp_pcm_size_rate);
+ } else if (w->type ==
+ HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX)
+ hdac_dump_pin(sc, w);
+ if (w->param.eapdbtl != HDAC_INVALID)
+ device_printf(sc->dev, " EAPD: 0x%08x\n",
+ w->param.eapdbtl);
+ if (HDA_PARAM_AUDIO_WIDGET_CAP_OUT_AMP(w->param.widget_cap) &&
+ w->param.outamp_cap != 0)
+ hdac_dump_amp(sc, w->param.outamp_cap, "Output");
+ if (HDA_PARAM_AUDIO_WIDGET_CAP_IN_AMP(w->param.widget_cap) &&
+ w->param.inamp_cap != 0)
+ hdac_dump_amp(sc, w->param.inamp_cap, " Input");
+ device_printf(sc->dev, " connections: %d\n", w->nconns);
+ for (j = 0; j < w->nconns; j++) {
+ cw = hdac_widget_get(devinfo, w->conns[j]);
+ device_printf(sc->dev, " |\n");
+ device_printf(sc->dev, " + <- nid=%d [%s]",
+ w->conns[j], (cw == NULL) ? "GHOST!" : cw->name);
+ if (cw == NULL)
+ printf(" [UNKNOWN]");
+ else if (cw->enable == 0)
+ printf(" [DISABLED]");
+ if (w->nconns > 1 && w->selconn == j && w->type !=
+ HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_MIXER)
+ printf(" (selected)");
+ printf("\n");
+ }
+ }
}
static int
hdac_dump_dac_internal(struct hdac_devinfo *devinfo, nid_t nid, int depth)
{
-struct hdac_widget *w, *cw;
-struct hdac_softc *sc = devinfo->codec->sc;
-int i;
-
-if (depth > HDA_PARSE_MAXDEPTH)
-return (0);
-
-w = hdac_widget_get(devinfo, nid);
-if (w == NULL || w->enable == 0 || !(w->pflags & HDA_DAC_PATH))
-return (0);
-
-if (w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX) {
-device_printf(sc->dev, "n");
-device_printf(sc->dev, " nid=%d [%s]n", w->nid, w->name);
-device_printf(sc->dev, " ^n");
-device_printf(sc->dev, " |n");
-device_printf(sc->dev, " +-----<------+n");
-} else {
-device_printf(sc->dev, " ^n");
-device_printf(sc->dev, " |n");
-device_printf(sc->dev, " ");
-printf(" nid=%d [%s]n", w->nid, w->name);
-}
-
-if (w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_OUTPUT) {
-return (1);
-} else if (w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_MIXER) {
-for (i = 0; i < w->nconns; i++) {
-cw = hdac_widget_get(devinfo, w->conns[i]);
-if (cw == NULL || cw->enable == 0 || cw->type ==
-HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX)
-continue;
-if (hdac_dump_dac_internal(devinfo, cw->nid,
-depth + 1) != 0)
-return (1);
-}
-} else if ((w->type ==
-HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_SELECTOR ||
-w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX) &&
-w->selconn > -1 && w->selconn < w->nconns) {
-if (hdac_dump_dac_internal(devinfo, w->conns[w->selconn],
-depth + 1) != 0)
-return (1);
-}
+ struct hdac_widget *w, *cw;
+ struct hdac_softc *sc = devinfo->codec->sc;
+ int i;
+
+ if (depth > HDA_PARSE_MAXDEPTH)
+ return (0);
+
+ w = hdac_widget_get(devinfo, nid);
+ if (w == NULL || w->enable == 0 || !(w->pflags & HDA_DAC_PATH))
+ return (0);
+
+ if (w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX) {
+ device_printf(sc->dev, "\n");
+ device_printf(sc->dev, " nid=%d [%s]\n", w->nid, w->name);
+ device_printf(sc->dev, " ^\n");
+ device_printf(sc->dev, " |\n");
+ device_printf(sc->dev, " +-----<------+\n");
+ } else {
+ device_printf(sc->dev, " ^\n");
+ device_printf(sc->dev, " |\n");
+ device_printf(sc->dev, " ");
+ printf(" nid=%d [%s]\n", w->nid, w->name);
+ }
+
+ if (w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_OUTPUT) {
+ return (1);
+ } else if (w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_MIXER) {
+ for (i = 0; i < w->nconns; i++) {
+ cw = hdac_widget_get(devinfo, w->conns[i]);
+ if (cw == NULL || cw->enable == 0 || cw->type ==
+ HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX)
+ continue;
+ if (hdac_dump_dac_internal(devinfo, cw->nid,
+ depth + 1) != 0)
+ return (1);
+ }
+ } else if ((w->type ==
+ HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_SELECTOR ||
+ w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX) &&
+ w->selconn > -1 && w->selconn < w->nconns) {
+ if (hdac_dump_dac_internal(devinfo, w->conns[w->selconn],
+ depth + 1) != 0)
+ return (1);
+ }
-return (0);
+ return (0);
}
static void
hdac_dump_dac(struct hdac_devinfo *devinfo)
{
-struct hdac_widget *w;
-struct hdac_softc *sc = devinfo->codec->sc;
-int i, printed = 0;
-
-for (i = devinfo->startnode; i < devinfo->endnode; i++) {
-w = hdac_widget_get(devinfo, i);
-if (w == NULL || w->enable == 0)
-continue;
-if (w->type != HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX ||
-!(w->pflags & HDA_DAC_PATH))
-continue;
-if (printed == 0) {
-printed = 1;
-device_printf(sc->dev, "n");
-device_printf(sc->dev, "Playback path:n");
-}
-hdac_dump_dac_internal(devinfo, w->nid, 0);
-}
+ struct hdac_widget *w;
+ struct hdac_softc *sc = devinfo->codec->sc;
+ int i, printed = 0;
+
+ for (i = devinfo->startnode; i < devinfo->endnode; i++) {
+ w = hdac_widget_get(devinfo, i);
+ if (w == NULL || w->enable == 0)
+ continue;
+ if (w->type != HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX ||
+ !(w->pflags & HDA_DAC_PATH))
+ continue;
+ if (printed == 0) {
+ printed = 1;
+ device_printf(sc->dev, "\n");
+ device_printf(sc->dev, "Playback path:\n");
+ }
+ hdac_dump_dac_internal(devinfo, w->nid, 0);
+ }
}
static void
hdac_dump_adc(struct hdac_devinfo *devinfo)
{
-struct hdac_widget *w, *cw;
-struct hdac_softc *sc = devinfo->codec->sc;
-int i, j;
-int printed = 0;
-char ossdevs[256];
-
-for (i = devinfo->startnode; i < devinfo->endnode; i++) {
-w = hdac_widget_get(devinfo, i);
-if (w == NULL || w->enable == 0)
-continue;
-if (!(w->pflags & HDA_ADC_RECSEL))
-continue;
-if (printed == 0) {
-printed = 1;
-device_printf(sc->dev, "n");
-device_printf(sc->dev, "Recording sources:n");
-}
-device_printf(sc->dev, "n");
-device_printf(sc->dev, " nid=%d [%s]n", w->nid, w->name);
-for (j = 0; j < w->nconns; j++) {
-cw = hdac_widget_get(devinfo, w->conns[j]);
-if (cw == NULL || cw->enable == 0)
-continue;
-hdac_audio_ctl_ossmixer_mask2allname(cw->ctlflags,
-ossdevs, sizeof(ossdevs));
-device_printf(sc->dev, " |n");
-device_printf(sc->dev, " + <- nid=%d [%s]",
-cw->nid, cw->name);
-if (strlen(ossdevs) > 0) {
-printf(" [recsrc: %s]", ossdevs);
-}
-printf("n");
-}
-}
+ struct hdac_widget *w, *cw;
+ struct hdac_softc *sc = devinfo->codec->sc;
+ int i, j;
+ int printed = 0;
+ char ossdevs[256];
+
+ for (i = devinfo->startnode; i < devinfo->endnode; i++) {
+ w = hdac_widget_get(devinfo, i);
+ if (w == NULL || w->enable == 0)
+ continue;
+ if (!(w->pflags & HDA_ADC_RECSEL))
+ continue;
+ if (printed == 0) {
+ printed = 1;
+ device_printf(sc->dev, "\n");
+ device_printf(sc->dev, "Recording sources:\n");
+ }
+ device_printf(sc->dev, "\n");
+ device_printf(sc->dev, " nid=%d [%s]\n", w->nid, w->name);
+ for (j = 0; j < w->nconns; j++) {
+ cw = hdac_widget_get(devinfo, w->conns[j]);
+ if (cw == NULL || cw->enable == 0)
+ continue;
+ hdac_audio_ctl_ossmixer_mask2allname(cw->ctlflags,
+ ossdevs, sizeof(ossdevs));
+ device_printf(sc->dev, " |\n");
+ device_printf(sc->dev, " + <- nid=%d [%s]",
+ cw->nid, cw->name);
+ if (strlen(ossdevs) > 0) {
+ printf(" [recsrc: %s]", ossdevs);
+ }
+ printf("\n");
+ }
+ }
}
static void
hdac_dump_pcmchannels(struct hdac_softc *sc, int pcnt, int rcnt)
{
-nid_t *nids;
+ nid_t *nids;
-if (pcnt > 0) {
-device_printf(sc->dev, "n");
-device_printf(sc->dev, " PCM Playback: %dn", pcnt);
-hdac_dump_audio_formats(sc, sc->play.supp_stream_formats,
-sc->play.supp_pcm_size_rate);
-device_printf(sc->dev, " DAC:");
-for (nids = sc->play.io; *nids != -1; nids++)
-printf(" %d", *nids);
-printf("n");
-}
-
-if (rcnt > 0) {
-device_printf(sc->dev, "n");
-device_printf(sc->dev, " PCM Record: %dn", rcnt);
-hdac_dump_audio_formats(sc, sc->play.supp_stream_formats,
-sc->rec.supp_pcm_size_rate);
-device_printf(sc->dev, " ADC:");
-for (nids = sc->rec.io; *nids != -1; nids++)
-printf(" %d", *nids);
-printf("n");
-}
+ if (pcnt > 0) {
+ device_printf(sc->dev, "\n");
+ device_printf(sc->dev, " PCM Playback: %d\n", pcnt);
+ hdac_dump_audio_formats(sc, sc->play.supp_stream_formats,
+ sc->play.supp_pcm_size_rate);
+ device_printf(sc->dev, " DAC:");
+ for (nids = sc->play.io; *nids != -1; nids++)
+ printf(" %d", *nids);
+ printf("\n");
+ }
+
+ if (rcnt > 0) {
+ device_printf(sc->dev, "\n");
+ device_printf(sc->dev, " PCM Record: %d\n", rcnt);
+ hdac_dump_audio_formats(sc, sc->play.supp_stream_formats,
+ sc->rec.supp_pcm_size_rate);
+ device_printf(sc->dev, " ADC:");
+ for (nids = sc->rec.io; *nids != -1; nids++)
+ printf(" %d", *nids);
+ printf("\n");
+ }
}
static void
hdac_release_resources(struct hdac_softc *sc)
{
-struct hdac_devinfo *devinfo = NULL;
-device_t *devlist = NULL;
-int i, devcount;
-
-if (sc == NULL)
-return;
-
-hdac_lock(sc);
-hdac_reset(sc);
-hdac_unlock(sc);
-snd_mtxfree(sc->lock);
-
-device_get_children(sc->dev, &devlist, &devcount);
-for (i = 0; devlist != NULL && i < devcount; i++) {
-devinfo = (struct hdac_devinfo *)device_get_ivars(devlist[i]);
-if (devinfo == NULL)
-continue;
-if (devinfo->widget != NULL)
-free(devinfo->widget, M_HDAC);
-if (devinfo->node_type ==
-HDA_PARAM_FCT_GRP_TYPE_NODE_TYPE_AUDIO &&
-devinfo->function.audio.ctl != NULL)
-free(devinfo->function.audio.ctl, M_HDAC);
-free(devinfo, M_HDAC);
-device_delete_child(sc->dev, devlist[i]);
-}
-if (devlist != NULL)
-free(devlist, M_TEMP);
-
-for (i = 0; i < HDAC_CODEC_MAX; i++) {
-if (sc->codecs[i] != NULL)
-free(sc->codecs[i], M_HDAC);
-sc->codecs[i] = NULL;
-}
-
-hdac_dma_free(&sc->rirb_dma);
-hdac_dma_free(&sc->corb_dma);
-if (sc->play.blkcnt > 0)
-hdac_dma_free(&sc->play.bdl_dma);
-if (sc->rec.blkcnt > 0)
-hdac_dma_free(&sc->rec.bdl_dma);
-hdac_irq_free(sc);
-hdac_mem_free(sc);
-free(sc, M_DEVBUF);
-
+ struct hdac_devinfo *devinfo = NULL;
+ device_t *devlist = NULL;
+ int i, devcount;
+
+ if (sc == NULL)
+ return;
+
+ hdac_lock(sc);
+ sc->polling = 0;
+ sc->poll_ival = 0;
+ callout_stop(&sc->poll_hda);
+ callout_stop(&sc->poll_hdac);
+ callout_stop(&sc->poll_jack);
+ hdac_reset(sc);
+ hdac_unlock(sc);
+ taskqueue_drain(taskqueue_thread, &sc->unsolq_task);
+ callout_drain(&sc->poll_hda);
+ callout_drain(&sc->poll_hdac);
+ callout_drain(&sc->poll_jack);
+
+ hdac_irq_free(sc);
+
+ device_get_children(sc->dev, &devlist, &devcount);
+ for (i = 0; devlist != NULL && i < devcount; i++) {
+ devinfo = (struct hdac_devinfo *)device_get_ivars(devlist[i]);
+ if (devinfo == NULL)
+ continue;
+ if (devinfo->widget != NULL)
+ free(devinfo->widget, M_HDAC);
+ if (devinfo->node_type ==
+ HDA_PARAM_FCT_GRP_TYPE_NODE_TYPE_AUDIO &&
+ devinfo->function.audio.ctl != NULL)
+ free(devinfo->function.audio.ctl, M_HDAC);
+ free(devinfo, M_HDAC);
+ device_delete_child(sc->dev, devlist[i]);
+ }
+ if (devlist != NULL)
+ free(devlist, M_TEMP);
+
+ for (i = 0; i < HDAC_CODEC_MAX; i++) {
+ if (sc->codecs[i] != NULL)
+ free(sc->codecs[i], M_HDAC);
+ sc->codecs[i] = NULL;
+ }
+
+ hdac_dma_free(sc, &sc->pos_dma);
+ hdac_dma_free(sc, &sc->rirb_dma);
+ hdac_dma_free(sc, &sc->corb_dma);
+ if (sc->play.blkcnt > 0)
+ hdac_dma_free(sc, &sc->play.bdl_dma);
+ if (sc->rec.blkcnt > 0)
+ hdac_dma_free(sc, &sc->rec.bdl_dma);
+ if (sc->chan_dmat != NULL) {
+ bus_dma_tag_destroy(sc->chan_dmat);
+ sc->chan_dmat = NULL;
+ }
+ hdac_mem_free(sc);
+ snd_mtxfree(sc->lock);
+ free(sc, M_DEVBUF);
}
/* This function surely going to make its way into upper level someday. */
static void
hdac_config_fetch(struct hdac_softc *sc, uint32_t *on, uint32_t *off)
{
-const char *res = NULL;
-int i = 0, j, k, len, inv;
+ const char *res = NULL;
+ int i = 0, j, k, len, inv;
-if (on != NULL)
-*on = 0;
-if (off != NULL)
-*off = 0;
-if (sc == NULL)
-return;
-if (resource_string_value(device_get_name(sc->dev),
-device_get_unit(sc->dev), "config", &res) != 0)
-return;
-if (!(res != NULL && strlen(res) > 0))
-return;
-HDA_BOOTVERBOSE(
-device_printf(sc->dev, "HDA_DEBUG: HDA Config:");
-);
-for (;;) {
-while (res[i] != '0' &&
-(res[i] == ',' || isspace(res[i]) != 0))
-i++;
-if (res[i] == '0') {
-HDA_BOOTVERBOSE(
-printf("n");
-);
-return;
-}
-j = i;
-while (res[j] != '0' &&
-!(res[j] == ',' || isspace(res[j]) != 0))
-j++;
-len = j - i;
-if (len > 2 && strncmp(res + i, "no", 2) == 0)
-inv = 2;
-else
-inv = 0;
-for (k = 0; len > inv && k < HDAC_QUIRKS_TAB_LEN; k++) {
-if (strncmp(res + i + inv,
-hdac_quirks_tab[k].key, len - inv) != 0)
-continue;
-if (len - inv != strlen(hdac_quirks_tab[k].key))
-break;
-HDA_BOOTVERBOSE(
-printf(" %s%s", (inv != 0) ? "no" : "",
-hdac_quirks_tab[k].key);
-);
-if (inv == 0 && on != NULL)
-*on |= hdac_quirks_tab[k].value;
-else if (inv != 0 && off != NULL)
-*off |= hdac_quirks_tab[k].value;
-break;
+ if (on != NULL)
+ *on = 0;
+ if (off != NULL)
+ *off = 0;
+ if (sc == NULL)
+ return;
+ if (resource_string_value(device_get_name(sc->dev),
+ device_get_unit(sc->dev), "config", &res) != 0)
+ return;
+ if (!(res != NULL && strlen(res) > 0))
+ return;
+ HDA_BOOTVERBOSE(
+ device_printf(sc->dev, "HDA_DEBUG: HDA Config:");
+ );
+ for (;;) {
+ while (res[i] != '\0' &&
+ (res[i] == ',' || isspace(res[i]) != 0))
+ i++;
+ if (res[i] == '\0') {
+ HDA_BOOTVERBOSE(
+ printf("\n");
+ );
+ return;
+ }
+ j = i;
+ while (res[j] != '\0' &&
+ !(res[j] == ',' || isspace(res[j]) != 0))
+ j++;
+ len = j - i;
+ if (len > 2 && strncmp(res + i, "no", 2) == 0)
+ inv = 2;
+ else
+ inv = 0;
+ for (k = 0; len > inv && k < HDAC_QUIRKS_TAB_LEN; k++) {
+ if (strncmp(res + i + inv,
+ hdac_quirks_tab[k].key, len - inv) != 0)
+ continue;
+ if (len - inv != strlen(hdac_quirks_tab[k].key))
+ break;
+ HDA_BOOTVERBOSE(
+ printf(" %s%s", (inv != 0) ? "no" : "",
+ hdac_quirks_tab[k].key);
+ );
+ if (inv == 0 && on != NULL)
+ *on |= hdac_quirks_tab[k].value;
+ else if (inv != 0 && off != NULL)
+ *off |= hdac_quirks_tab[k].value;
+ break;
+ }
+ i = j;
+ }
}
-i = j;
+
+#ifdef SND_DYNSYSCTL
+static int
+sysctl_hdac_polling(SYSCTL_HANDLER_ARGS)
+{
+ struct hdac_softc *sc;
+ struct hdac_devinfo *devinfo;
+ device_t dev;
+ uint32_t ctl;
+ int err, val;
+
+ dev = oidp->oid_arg1;
+ devinfo = pcm_getdevinfo(dev);
+ if (devinfo == NULL || devinfo->codec == NULL ||
+ devinfo->codec->sc == NULL)
+ return (EINVAL);
+ sc = devinfo->codec->sc;
+ hdac_lock(sc);
+ val = sc->polling;
+ hdac_unlock(sc);
+ err = sysctl_handle_int(oidp, &val, 0, req);
+
+ if (err != 0 || req->newptr == NULL)
+ return (err);
+ if (val < 0 || val > 1)
+ return (EINVAL);
+
+ hdac_lock(sc);
+ if (val != sc->polling) {
+ if (hda_chan_active(sc) != 0)
+ err = EBUSY;
+ else if (val == 0) {
+ callout_stop(&sc->poll_hdac);
+ hdac_unlock(sc);
+ callout_drain(&sc->poll_hdac);
+ hdac_lock(sc);
+ HDAC_WRITE_2(&sc->mem, HDAC_RINTCNT,
+ sc->rirb_size / 2);
+ ctl = HDAC_READ_1(&sc->mem, HDAC_RIRBCTL);
+ ctl |= HDAC_RIRBCTL_RINTCTL;
+ HDAC_WRITE_1(&sc->mem, HDAC_RIRBCTL, ctl);
+ HDAC_WRITE_4(&sc->mem, HDAC_INTCTL,
+ HDAC_INTCTL_CIE | HDAC_INTCTL_GIE);
+ sc->polling = 0;
+ DELAY(1000);
+ } else {
+ HDAC_WRITE_4(&sc->mem, HDAC_INTCTL, 0);
+ HDAC_WRITE_2(&sc->mem, HDAC_RINTCNT, 0);
+ ctl = HDAC_READ_1(&sc->mem, HDAC_RIRBCTL);
+ ctl &= ~HDAC_RIRBCTL_RINTCTL;
+ HDAC_WRITE_1(&sc->mem, HDAC_RIRBCTL, ctl);
+ hdac_unlock(sc);
+ taskqueue_drain(taskqueue_thread, &sc->unsolq_task);
+ hdac_lock(sc);
+ callout_reset(&sc->poll_hdac, 1, hdac_poll_callback,
+ sc);
+ sc->polling = 1;
+ DELAY(1000);
+ }
+ }
+ hdac_unlock(sc);
+
+ return (err);
}
+
+static int
+sysctl_hdac_polling_interval(SYSCTL_HANDLER_ARGS)
+{
+ struct hdac_softc *sc;
+ struct hdac_devinfo *devinfo;
+ device_t dev;
+ int err, val;
+
+ dev = oidp->oid_arg1;
+ devinfo = pcm_getdevinfo(dev);
+ if (devinfo == NULL || devinfo->codec == NULL ||
+ devinfo->codec->sc == NULL)
+ return (EINVAL);
+ sc = devinfo->codec->sc;
+ hdac_lock(sc);
+ val = ((uint64_t)sc->poll_ival * 1000) / hz;
+ hdac_unlock(sc);
+ err = sysctl_handle_int(oidp, &val, 0, req);
+
+ if (err != 0 || req->newptr == NULL)
+ return (err);
+
+ if (val < 1)
+ val = 1;
+ if (val > 5000)
+ val = 5000;
+ val = ((uint64_t)val * hz) / 1000;
+ if (val < 1)
+ val = 1;
+ if (val > (hz * 5))
+ val = hz * 5;
+
+ hdac_lock(sc);
+ sc->poll_ival = val;
+ hdac_unlock(sc);
+
+ return (err);
}
+#ifdef SND_DEBUG
+static int
+sysctl_hdac_pindump(SYSCTL_HANDLER_ARGS)
+{
+ struct hdac_softc *sc;
+ struct hdac_devinfo *devinfo;
+ struct hdac_widget *w;
+ device_t dev;
+ uint32_t res, pincap, timeout;
+ int i, err, val;
+ nid_t cad;
+
+ dev = oidp->oid_arg1;
+ devinfo = pcm_getdevinfo(dev);
+ if (devinfo == NULL || devinfo->codec == NULL ||
+ devinfo->codec->sc == NULL)
+ return (EINVAL);
+ val = 0;
+ err = sysctl_handle_int(oidp, &val, 0, req);
+ if (err != 0 || req->newptr == NULL || val == 0)
+ return (err);
+ sc = devinfo->codec->sc;
+ cad = devinfo->codec->cad;
+ hdac_lock(sc);
+ device_printf(dev, "HDAC Dump AFG [nid=%d]:\n", devinfo->nid);
+ for (i = devinfo->startnode; i < devinfo->endnode; i++) {
+ w = hdac_widget_get(devinfo, i);
+ if (w == NULL || w->type !=
+ HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX)
+ continue;
+ pincap = w->wclass.pin.cap;
+ if ((HDA_PARAM_PIN_CAP_IMP_SENSE_CAP(pincap) ||
+ HDA_PARAM_PIN_CAP_PRESENCE_DETECT_CAP(pincap)) &&
+ HDA_PARAM_PIN_CAP_TRIGGER_REQD(pincap)) {
+ timeout = 10000;
+ hdac_command(sc,
+ HDA_CMD_SET_PIN_SENSE(cad, w->nid, 0), cad);
+ do {
+ res = hdac_command(sc,
+ HDA_CMD_GET_PIN_SENSE(cad, w->nid), cad);
+ if (res != 0x7fffffff)
+ break;
+ DELAY(10);
+ } while (--timeout != 0);
+ } else {
+ timeout = -1;
+ res = hdac_command(sc, HDA_CMD_GET_PIN_SENSE(cad,
+ w->nid), cad);
+ }
+ device_printf(dev,
+ "PIN_SENSE: nid=%-3d timeout=%d res=0x%08x [%s]\n",
+ w->nid, timeout, res,
+ (w->enable == 0) ? "DISABLED" : "ENABLED");
+ }
+ device_printf(dev,
+ "NumGPIO=%d NumGPO=%d NumGPI=%d GPIWake=%d GPIUnsol=%d\n",
+ HDA_PARAM_GPIO_COUNT_NUM_GPIO(devinfo->function.audio.gpio),
+ HDA_PARAM_GPIO_COUNT_NUM_GPO(devinfo->function.audio.gpio),
+ HDA_PARAM_GPIO_COUNT_NUM_GPI(devinfo->function.audio.gpio),
+ HDA_PARAM_GPIO_COUNT_GPI_WAKE(devinfo->function.audio.gpio),
+ HDA_PARAM_GPIO_COUNT_GPI_UNSOL(devinfo->function.audio.gpio));
+ if (HDA_PARAM_GPIO_COUNT_NUM_GPI(devinfo->function.audio.gpio) > 0) {
+ device_printf(dev, " GPI:");
+ res = hdac_command(sc,
+ HDA_CMD_GET_GPI_DATA(cad, devinfo->nid), cad);
+ printf(" data=0x%08x", res);
+ res = hdac_command(sc,
+ HDA_CMD_GET_GPI_WAKE_ENABLE_MASK(cad, devinfo->nid),
+ cad);
+ printf(" wake=0x%08x", res);
+ res = hdac_command(sc,
+ HDA_CMD_GET_GPI_UNSOLICITED_ENABLE_MASK(cad, devinfo->nid),
+ cad);
+ printf(" unsol=0x%08x", res);
+ res = hdac_command(sc,
+ HDA_CMD_GET_GPI_STICKY_MASK(cad, devinfo->nid), cad);
+ printf(" sticky=0x%08x\n", res);
+ }
+ if (HDA_PARAM_GPIO_COUNT_NUM_GPO(devinfo->function.audio.gpio) > 0) {
+ device_printf(dev, " GPO:");
+ res = hdac_command(sc,
+ HDA_CMD_GET_GPO_DATA(cad, devinfo->nid), cad);
+ printf(" data=0x%08x\n", res);
+ }
+ if (HDA_PARAM_GPIO_COUNT_NUM_GPIO(devinfo->function.audio.gpio) > 0) {
+ device_printf(dev, "GPI0:");
+ res = hdac_command(sc,
+ HDA_CMD_GET_GPIO_DATA(cad, devinfo->nid), cad);
+ printf(" data=0x%08x", res);
+ res = hdac_command(sc,
+ HDA_CMD_GET_GPIO_ENABLE_MASK(cad, devinfo->nid), cad);
+ printf(" enable=0x%08x", res);
+ res = hdac_command(sc,
+ HDA_CMD_GET_GPIO_DIRECTION(cad, devinfo->nid), cad);
+ printf(" direction=0x%08x\n", res);
+ res = hdac_command(sc,
+ HDA_CMD_GET_GPIO_WAKE_ENABLE_MASK(cad, devinfo->nid), cad);
+ device_printf(dev, " wake=0x%08x", res);
+ res = hdac_command(sc,
+ HDA_CMD_GET_GPIO_UNSOLICITED_ENABLE_MASK(cad, devinfo->nid),
+ cad);
+ printf(" unsol=0x%08x", res);
+ res = hdac_command(sc,
+ HDA_CMD_GET_GPIO_STICKY_MASK(cad, devinfo->nid), cad);
+ printf(" sticky=0x%08x\n", res);
+ }
+ hdac_unlock(sc);
+ return (0);
+}
+#endif
+#endif
+
static void
hdac_attach2(void *arg)
{
-struct hdac_softc *sc;
-struct hdac_widget *w;
-struct hdac_audio_ctl *ctl;
-uint32_t quirks_on, quirks_off;
-int pcnt, rcnt;
-int i;
-char status[SND_STATUSLEN];
-device_t *devlist = NULL;
-int devcount;
-struct hdac_devinfo *devinfo = NULL;
-
-sc = (struct hdac_softc *)arg;
-
-hdac_config_fetch(sc, &quirks_on, &quirks_off);
-
-HDA_BOOTVERBOSE(
-device_printf(sc->dev, "HDA_DEBUG: HDA Config: on=0x%08x off=0x%08xn",
-quirks_on, quirks_off);
-);
-
-hdac_lock(sc);
-
-/* Remove ourselves from the config hooks */
-if (sc->intrhook.ich_func != NULL) {
-config_intrhook_disestablish(&sc->intrhook);
-sc->intrhook.ich_func = NULL;
-}
-
-/* Start the corb and rirb engines */
-HDA_BOOTVERBOSE(
-device_printf(sc->dev, "HDA_DEBUG: Starting CORB Engine...n");
-);
-hdac_corb_start(sc);
-HDA_BOOTVERBOSE(
-device_printf(sc->dev, "HDA_DEBUG: Starting RIRB Engine...n");
-);
-hdac_rirb_start(sc);
-
-HDA_BOOTVERBOSE(
-device_printf(sc->dev,
-"HDA_DEBUG: Enabling controller interrupt...n");
-);
-HDAC_WRITE_4(&sc->mem, HDAC_INTCTL, HDAC_INTCTL_CIE | HDAC_INTCTL_GIE);
-HDAC_WRITE_4(&sc->mem, HDAC_GCTL, HDAC_READ_4(&sc->mem, HDAC_GCTL) |
-HDAC_GCTL_UNSOL);
-
-DELAY(1000);
-
-HDA_BOOTVERBOSE(
-device_printf(sc->dev, "HDA_DEBUG: Scanning HDA codecs...n");
-);
-hdac_scan_codecs(sc);
-
-device_get_children(sc->dev, &devlist, &devcount);
-for (i = 0; devlist != NULL && i < devcount; i++) {
-devinfo = (struct hdac_devinfo *)device_get_ivars(devlist[i]);
-if (devinfo != NULL && devinfo->node_type ==
-HDA_PARAM_FCT_GRP_TYPE_NODE_TYPE_AUDIO) {
-break;
-} else
-devinfo = NULL;
-}
-if (devlist != NULL)
-free(devlist, M_TEMP);
-
-if (devinfo == NULL) {
-hdac_unlock(sc);
-device_printf(sc->dev, "Audio Function Group not found!n");
-hdac_release_resources(sc);
-return;
-}
-
-HDA_BOOTVERBOSE(
-device_printf(sc->dev,
-"HDA_DEBUG: Parsing AFG nid=%d cad=%dn",
-devinfo->nid, devinfo->codec->cad);
-);
-hdac_audio_parse(devinfo);
-HDA_BOOTVERBOSE(
-device_printf(sc->dev, "HDA_DEBUG: Parsing Ctls...n");
-);
-hdac_audio_ctl_parse(devinfo);
-HDA_BOOTVERBOSE(
-device_printf(sc->dev, "HDA_DEBUG: Parsing vendor patch...n");
-);
-hdac_vendor_patch_parse(devinfo);
-if (quirks_on != 0)
-devinfo->function.audio.quirks |= quirks_on;
-if (quirks_off != 0)
-devinfo->function.audio.quirks &= ~quirks_off;
-
-/* XXX Disable all DIGITAL path. */
-for (i = devinfo->startnode; i < devinfo->endnode; i++) {
-w = hdac_widget_get(devinfo, i);
-if (w == NULL)
-continue;
-if (HDA_PARAM_AUDIO_WIDGET_CAP_DIGITAL(w->param.widget_cap)) {
-w->enable = 0;
-continue;
-}
-/* XXX Disable useless pin ? */
-if (w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX &&
-(w->wclass.pin.config &
-HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK) ==
-HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_NONE)
-w->enable = 0;
-}
-i = 0;
-while ((ctl = hdac_audio_ctl_each(devinfo, &i)) != NULL) {
-if (ctl->widget == NULL)
-continue;
-w = ctl->widget;
-if (w->enable == 0)
-ctl->enable = 0;
-if (HDA_PARAM_AUDIO_WIDGET_CAP_DIGITAL(w->param.widget_cap))
-ctl->enable = 0;
-w = ctl->childwidget;
-if (w == NULL)
-continue;
-if (w->enable == 0 ||
-HDA_PARAM_AUDIO_WIDGET_CAP_DIGITAL(w->param.widget_cap))
-ctl->enable = 0;
-}
-
-HDA_BOOTVERBOSE(
-device_printf(sc->dev, "HDA_DEBUG: Building AFG tree...n");
-);
-hdac_audio_build_tree(devinfo);
-
-HDA_BOOTVERBOSE(
-device_printf(sc->dev, "HDA_DEBUG: AFG commit...n");
-);
-hdac_audio_commit(devinfo, HDA_COMMIT_ALL);
-HDA_BOOTVERBOSE(
-device_printf(sc->dev, "HDA_DEBUG: Ctls commit...n");
-);
-hdac_audio_ctl_commit(devinfo);
-
-HDA_BOOTVERBOSE(
-device_printf(sc->dev, "HDA_DEBUG: PCMDIR_PLAY setup...n");
-);
-pcnt = hdac_pcmchannel_setup(devinfo, PCMDIR_PLAY);
-HDA_BOOTVERBOSE(
-device_printf(sc->dev, "HDA_DEBUG: PCMDIR_REC setup...n");
-);
-rcnt = hdac_pcmchannel_setup(devinfo, PCMDIR_REC);
-
-hdac_unlock(sc);
-HDA_BOOTVERBOSE(
-device_printf(sc->dev,
-"HDA_DEBUG: OSS mixer initialization...n");
-);
+ struct hdac_softc *sc;
+ struct hdac_widget *w;
+ struct hdac_audio_ctl *ctl;
+ uint32_t quirks_on, quirks_off;
+ int pcnt, rcnt, codec_index;
+ int i;
+ char status[SND_STATUSLEN];
+ device_t *devlist = NULL;
+ int devcount;
+ struct hdac_devinfo *devinfo = NULL;
+
+ sc = (struct hdac_softc *)arg;
+
+ hdac_config_fetch(sc, &quirks_on, &quirks_off);
+
+ HDA_BOOTVERBOSE(
+ device_printf(sc->dev, "HDA_DEBUG: HDA Config: on=0x%08x off=0x%08x\n",
+ quirks_on, quirks_off);
+ );
+
+ if (resource_int_value(device_get_name(sc->dev),
+ device_get_unit(sc->dev), "codec_index", &codec_index) != 0) {
+ switch (sc->pci_subvendor) {
+ case GB_G33S2H_SUBVENDOR:
+ codec_index = 2;
+ break;
+ default:
+ codec_index = 0;
+ break;
+ }
+ }
+
+ hdac_lock(sc);
+
+ /* Remove ourselves from the config hooks */
+ if (sc->intrhook.ich_func != NULL) {
+ config_intrhook_disestablish(&sc->intrhook);
+ sc->intrhook.ich_func = NULL;
+ }
+
+ /* Start the corb and rirb engines */
+ HDA_BOOTVERBOSE(
+ device_printf(sc->dev, "HDA_DEBUG: Starting CORB Engine...\n");
+ );
+ hdac_corb_start(sc);
+ HDA_BOOTVERBOSE(
+ device_printf(sc->dev, "HDA_DEBUG: Starting RIRB Engine...\n");
+ );
+ hdac_rirb_start(sc);
+
+ HDA_BOOTVERBOSE(
+ device_printf(sc->dev,
+ "HDA_DEBUG: Enabling controller interrupt...\n");
+ );
+ if (sc->polling == 0)
+ HDAC_WRITE_4(&sc->mem, HDAC_INTCTL,
+ HDAC_INTCTL_CIE | HDAC_INTCTL_GIE);
+ HDAC_WRITE_4(&sc->mem, HDAC_GCTL, HDAC_READ_4(&sc->mem, HDAC_GCTL) |
+ HDAC_GCTL_UNSOL);
+
+ DELAY(1000);
+
+ HDA_BOOTVERBOSE(
+ device_printf(sc->dev,
+ "HDA_DEBUG: Scanning HDA codecs [start index=%d] ...\n",
+ codec_index);
+ );
+ hdac_scan_codecs(sc, codec_index);
+
+ device_get_children(sc->dev, &devlist, &devcount);
+ for (i = 0; devlist != NULL && i < devcount; i++) {
+ devinfo = (struct hdac_devinfo *)device_get_ivars(devlist[i]);
+ if (devinfo != NULL && devinfo->node_type ==
+ HDA_PARAM_FCT_GRP_TYPE_NODE_TYPE_AUDIO) {
+ break;
+ } else
+ devinfo = NULL;
+ }
+ if (devlist != NULL)
+ free(devlist, M_TEMP);
+
+ if (devinfo == NULL) {
+ hdac_unlock(sc);
+ device_printf(sc->dev, "Audio Function Group not found!\n");
+ hdac_release_resources(sc);
+ return;
+ }
+
+ HDA_BOOTVERBOSE(
+ device_printf(sc->dev,
+ "HDA_DEBUG: Parsing AFG nid=%d cad=%d\n",
+ devinfo->nid, devinfo->codec->cad);
+ );
+ hdac_audio_parse(devinfo);
+ HDA_BOOTVERBOSE(
+ device_printf(sc->dev, "HDA_DEBUG: Parsing Ctls...\n");
+ );
+ hdac_audio_ctl_parse(devinfo);
+ HDA_BOOTVERBOSE(
+ device_printf(sc->dev, "HDA_DEBUG: Parsing vendor patch...\n");
+ );
+ hdac_vendor_patch_parse(devinfo);
+ if (quirks_on != 0)
+ devinfo->function.audio.quirks |= quirks_on;
+ if (quirks_off != 0)
+ devinfo->function.audio.quirks &= ~quirks_off;
+
+ /* XXX Disable all DIGITAL path. */
+ for (i = devinfo->startnode; i < devinfo->endnode; i++) {
+ w = hdac_widget_get(devinfo, i);
+ if (w == NULL)
+ continue;
+ if (HDA_PARAM_AUDIO_WIDGET_CAP_DIGITAL(w->param.widget_cap)) {
+ w->enable = 0;
+ continue;
+ }
+ /* XXX Disable useless pin ? */
+ if (w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX &&
+ (w->wclass.pin.config &
+ HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK) ==
+ HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_NONE)
+ w->enable = 0;
+ }
+ i = 0;
+ while ((ctl = hdac_audio_ctl_each(devinfo, &i)) != NULL) {
+ if (ctl->widget == NULL)
+ continue;
+ if (ctl->ossmask & SOUND_MASK_DISABLE)
+ ctl->enable = 0;
+ w = ctl->widget;
+ if (w->enable == 0 ||
+ HDA_PARAM_AUDIO_WIDGET_CAP_DIGITAL(w->param.widget_cap))
+ ctl->enable = 0;
+ w = ctl->childwidget;
+ if (w == NULL)
+ continue;
+ if (w->enable == 0 ||
+ HDA_PARAM_AUDIO_WIDGET_CAP_DIGITAL(w->param.widget_cap))
+ ctl->enable = 0;
+ }
+
+ HDA_BOOTVERBOSE(
+ device_printf(sc->dev, "HDA_DEBUG: Building AFG tree...\n");
+ );
+ hdac_audio_build_tree(devinfo);
+
+ i = 0;
+ while ((ctl = hdac_audio_ctl_each(devinfo, &i)) != NULL) {
+ if (ctl->ossmask & (SOUND_MASK_SKIP | SOUND_MASK_DISABLE))
+ ctl->ossmask = 0;
+ }
+ HDA_BOOTVERBOSE(
+ device_printf(sc->dev, "HDA_DEBUG: AFG commit...\n");
+ );
+ hdac_audio_commit(devinfo, HDA_COMMIT_ALL);
+ HDA_BOOTVERBOSE(
+ device_printf(sc->dev, "HDA_DEBUG: Ctls commit...\n");
+ );
+ hdac_audio_ctl_commit(devinfo);
+
+ HDA_BOOTVERBOSE(
+ device_printf(sc->dev, "HDA_DEBUG: PCMDIR_PLAY setup...\n");
+ );
+ pcnt = hdac_pcmchannel_setup(devinfo, PCMDIR_PLAY);
+ HDA_BOOTVERBOSE(
+ device_printf(sc->dev, "HDA_DEBUG: PCMDIR_REC setup...\n");
+ );
+ rcnt = hdac_pcmchannel_setup(devinfo, PCMDIR_REC);
+
+ hdac_unlock(sc);
+ HDA_BOOTVERBOSE(
+ device_printf(sc->dev,
+ "HDA_DEBUG: OSS mixer initialization...\n");
+ );
+
+ /*
+ * There is no point of return after this. If the driver failed,
+ * so be it. Let the detach procedure do all the cleanup.
+ */
+ if (mixer_init(sc->dev, &hdac_audio_ctl_ossmixer_class, devinfo) != 0)
+ device_printf(sc->dev, "Can't register mixer\n");
+
+ if (pcnt > 0)
+ pcnt = 1;
+ if (rcnt > 0)
+ rcnt = 1;
+
+ HDA_BOOTVERBOSE(
+ device_printf(sc->dev,
+ "HDA_DEBUG: Registering PCM channels...\n");
+ );
+ if (pcm_register(sc->dev, devinfo, pcnt, rcnt) != 0)
+ device_printf(sc->dev, "Can't register PCM\n");
+
+ sc->registered++;
+
+ if ((devinfo->function.audio.quirks & HDA_QUIRK_DMAPOS) &&
+ hdac_dma_alloc(sc, &sc->pos_dma,
+ (sc->num_iss + sc->num_oss + sc->num_bss) * 8) != 0) {
+ HDA_BOOTVERBOSE(
+ device_printf(sc->dev,
+ "Failed to allocate DMA pos buffer (non-fatal)\n");
+ );
+ }
+
+ for (i = 0; i < pcnt; i++)
+ pcm_addchan(sc->dev, PCMDIR_PLAY, &hdac_channel_class, devinfo);
+ for (i = 0; i < rcnt; i++)
+ pcm_addchan(sc->dev, PCMDIR_REC, &hdac_channel_class, devinfo);
+
+#ifdef SND_DYNSYSCTL
+ SYSCTL_ADD_PROC(device_get_sysctl_ctx(sc->dev),
+ SYSCTL_CHILDREN(device_get_sysctl_tree(sc->dev)), OID_AUTO,
+ "polling", CTLTYPE_INT | CTLFLAG_RW, sc->dev, sizeof(sc->dev),
+ sysctl_hdac_polling, "I", "Enable polling mode");
+ SYSCTL_ADD_PROC(device_get_sysctl_ctx(sc->dev),
+ SYSCTL_CHILDREN(device_get_sysctl_tree(sc->dev)), OID_AUTO,
+ "polling_interval", CTLTYPE_INT | CTLFLAG_RW, sc->dev,
+ sizeof(sc->dev), sysctl_hdac_polling_interval, "I",
+ "Controller/Jack Sense polling interval (1-1000 ms)");
+#ifdef SND_DEBUG
+ SYSCTL_ADD_PROC(device_get_sysctl_ctx(sc->dev),
+ SYSCTL_CHILDREN(device_get_sysctl_tree(sc->dev)), OID_AUTO,
+ "pindump", CTLTYPE_INT | CTLFLAG_RW, sc->dev, sizeof(sc->dev),
+ sysctl_hdac_pindump, "I", "Dump pin states/data");
+#endif
+#endif
-/*
-* There is no point of return after this. If the driver failed,
-* so be it. Let the detach procedure do all the cleanup.
-*/
-if (mixer_init(sc->dev, &hdac_audio_ctl_ossmixer_class, devinfo) != 0)
-device_printf(sc->dev, "Can't register mixern");
-
-if (pcnt > 0)
-pcnt = 1;
-if (rcnt > 0)
-rcnt = 1;
-
-HDA_BOOTVERBOSE(
-device_printf(sc->dev,
-"HDA_DEBUG: Registering PCM channels...n");
-);
-if (pcm_register(sc->dev, devinfo, pcnt, rcnt) != 0)
-device_printf(sc->dev, "Can't register PCMn");
-
-sc->registered++;
-
-for (i = 0; i < pcnt; i++)
-pcm_addchan(sc->dev, PCMDIR_PLAY, &hdac_channel_class, devinfo);
-for (i = 0; i < rcnt; i++)
-pcm_addchan(sc->dev, PCMDIR_REC, &hdac_channel_class, devinfo);
-
-snprintf(status, SND_STATUSLEN, "at memory 0x%lx irq %ld %s [%s]",
-rman_get_start(sc->mem.mem_res),
-rman_get_start(sc->irq.irq_res),
-PCM_KLDSTRING(snd_hda), HDA_DRV_TEST_REV);
-pcm_setstatus(sc->dev, status);
-device_printf(sc->dev, "<HDA Codec: %s>n", hdac_codec_name(devinfo));
-HDA_BOOTVERBOSE(
-device_printf(sc->dev, "<HDA Codec ID: 0x%08x>n",
-hdac_codec_id(devinfo));
-);
-device_printf(sc->dev, "<HDA Driver Revision: %s>n", HDA_DRV_TEST_REV);
-
-HDA_BOOTVERBOSE(
-if (devinfo->function.audio.quirks != 0) {
-device_printf(sc->dev, "n");
-device_printf(sc->dev, "HDA config/quirks:");
-for (i = 0; i < HDAC_QUIRKS_TAB_LEN; i++) {
-if (devinfo->function.audio.quirks &
-hdac_quirks_tab[i].value)
-printf(" %s", hdac_quirks_tab[i].key);
-}
-printf("n");
-}
-device_printf(sc->dev, "n");
-device_printf(sc->dev, "+-------------------+n");
-device_printf(sc->dev, "| DUMPING HDA NODES |n");
-device_printf(sc->dev, "+-------------------+n");
-hdac_dump_nodes(devinfo);
-device_printf(sc->dev, "n");
-device_printf(sc->dev, "+------------------------+n");
-device_printf(sc->dev, "| DUMPING HDA AMPLIFIERS |n");
-device_printf(sc->dev, "+------------------------+n");
-device_printf(sc->dev, "n");
-i = 0;
-while ((ctl = hdac_audio_ctl_each(devinfo, &i)) != NULL) {
-device_printf(sc->dev, "%3d: nid=%d", i,
-(ctl->widget != NULL) ? ctl->widget->nid : -1);
-if (ctl->childwidget != NULL)
-printf(" cnid=%d", ctl->childwidget->nid);
-printf(" dir=0x%x index=%d "
-"ossmask=0x%08x ossdev=%d%sn",
-ctl->dir, ctl->index,
-ctl->ossmask, ctl->ossdev,
-(ctl->enable == 0) ? " [DISABLED]" : "");
-}
-device_printf(sc->dev, "n");
-device_printf(sc->dev, "+-----------------------------------+n");
-device_printf(sc->dev, "| DUMPING HDA AUDIO/VOLUME CONTROLS |n");
-device_printf(sc->dev, "+-----------------------------------+n");
-hdac_dump_ctls(devinfo, "Master Volume (OSS: vol)", SOUND_MASK_VOLUME);
-hdac_dump_ctls(devinfo, "PCM Volume (OSS: pcm)", SOUND_MASK_PCM);
-hdac_dump_ctls(devinfo, "CD Volume (OSS: cd)", SOUND_MASK_CD);
-hdac_dump_ctls(devinfo, "Microphone Volume (OSS: mic)", SOUND_MASK_MIC);
-hdac_dump_ctls(devinfo, "Line-in Volume (OSS: line)", SOUND_MASK_LINE);
-hdac_dump_ctls(devinfo, "Recording Level (OSS: rec)", SOUND_MASK_RECLEV);
-hdac_dump_ctls(devinfo, "Speaker/Beep (OSS: speaker)", SOUND_MASK_SPEAKER);
-hdac_dump_ctls(devinfo, NULL, 0);
-hdac_dump_dac(devinfo);
-hdac_dump_adc(devinfo);
-device_printf(sc->dev, "n");
-device_printf(sc->dev, "+--------------------------------------+n");
-device_printf(sc->dev, "| DUMPING PCM Playback/Record Channels |n");
-device_printf(sc->dev, "+--------------------------------------+n");
-hdac_dump_pcmchannels(sc, pcnt, rcnt);
-);
+ snprintf(status, SND_STATUSLEN, "at memory 0x%lx irq %ld %s [%s]",
+ rman_get_start(sc->mem.mem_res), rman_get_start(sc->irq.irq_res),
+ PCM_KLDSTRING(snd_hda), HDA_DRV_TEST_REV);
+ pcm_setstatus(sc->dev, status);
+ device_printf(sc->dev, "<HDA Codec: %s>\n", hdac_codec_name(devinfo));
+ HDA_BOOTVERBOSE(
+ device_printf(sc->dev, "<HDA Codec ID: 0x%08x>\n",
+ hdac_codec_id(devinfo));
+ );
+ device_printf(sc->dev, "<HDA Driver Revision: %s>\n",
+ HDA_DRV_TEST_REV);
+
+ HDA_BOOTVERBOSE(
+ if (devinfo->function.audio.quirks != 0) {
+ device_printf(sc->dev, "\n");
+ device_printf(sc->dev, "HDA config/quirks:");
+ for (i = 0; i < HDAC_QUIRKS_TAB_LEN; i++) {
+ if ((devinfo->function.audio.quirks &
+ hdac_quirks_tab[i].value) ==
+ hdac_quirks_tab[i].value)
+ printf(" %s", hdac_quirks_tab[i].key);
+ }
+ printf("\n");
+ }
+ device_printf(sc->dev, "\n");
+ device_printf(sc->dev, "+-------------------+\n");
+ device_printf(sc->dev, "| DUMPING HDA NODES |\n");
+ device_printf(sc->dev, "+-------------------+\n");
+ hdac_dump_nodes(devinfo);
+ device_printf(sc->dev, "\n");
+ device_printf(sc->dev, "+------------------------+\n");
+ device_printf(sc->dev, "| DUMPING HDA AMPLIFIERS |\n");
+ device_printf(sc->dev, "+------------------------+\n");
+ device_printf(sc->dev, "\n");
+ i = 0;
+ while ((ctl = hdac_audio_ctl_each(devinfo, &i)) != NULL) {
+ device_printf(sc->dev, "%3d: nid=%d", i,
+ (ctl->widget != NULL) ? ctl->widget->nid : -1);
+ if (ctl->childwidget != NULL)
+ printf(" cnid=%d", ctl->childwidget->nid);
+ printf(" dir=0x%x index=%d "
+ "ossmask=0x%08x ossdev=%d%s\n",
+ ctl->dir, ctl->index,
+ ctl->ossmask, ctl->ossdev,
+ (ctl->enable == 0) ? " [DISABLED]" : "");
+ }
+ device_printf(sc->dev, "\n");
+ device_printf(sc->dev, "+-----------------------------------+\n");
+ device_printf(sc->dev, "| DUMPING HDA AUDIO/VOLUME CONTROLS |\n");
+ device_printf(sc->dev, "+-----------------------------------+\n");
+ hdac_dump_ctls(devinfo, "Master Volume (OSS: vol)", SOUND_MASK_VOLUME);
+ hdac_dump_ctls(devinfo, "PCM Volume (OSS: pcm)", SOUND_MASK_PCM);
+ hdac_dump_ctls(devinfo, "CD Volume (OSS: cd)", SOUND_MASK_CD);
+ hdac_dump_ctls(devinfo, "Microphone Volume (OSS: mic)", SOUND_MASK_MIC);
+ hdac_dump_ctls(devinfo, "Line-in Volume (OSS: line)", SOUND_MASK_LINE);
+ hdac_dump_ctls(devinfo, "Recording Level (OSS: rec)", SOUND_MASK_RECLEV);
+ hdac_dump_ctls(devinfo, "Speaker/Beep (OSS: speaker)", SOUND_MASK_SPEAKER);
+ hdac_dump_ctls(devinfo, NULL, 0);
+ hdac_dump_dac(devinfo);
+ hdac_dump_adc(devinfo);
+ device_printf(sc->dev, "\n");
+ device_printf(sc->dev, "+--------------------------------------+\n");
+ device_printf(sc->dev, "| DUMPING PCM Playback/Record Channels |\n");
+ device_printf(sc->dev, "+--------------------------------------+\n");
+ hdac_dump_pcmchannels(sc, pcnt, rcnt);
+ );
+
+ if (sc->polling != 0) {
+ hdac_lock(sc);
+ callout_reset(&sc->poll_hdac, 1, hdac_poll_callback, sc);
+ hdac_unlock(sc);
+ }
}
/****************************************************************************
-* int hdac_detach(device_t)
-*
-* Detach and free up resources utilized by the hdac device.
-****************************************************************************/
+ * int hdac_detach(device_t)
+ *
+ * Detach and free up resources utilized by the hdac device.
+ ****************************************************************************/
static int
hdac_detach(device_t dev)
{
-struct hdac_softc *sc = NULL;
-struct hdac_devinfo *devinfo = NULL;
-int err;
-
-devinfo = (struct hdac_devinfo *)pcm_getdevinfo(dev);
-if (devinfo != NULL && devinfo->codec != NULL)
-sc = devinfo->codec->sc;
-if (sc == NULL)
-return (0);
-
-if (sc->registered > 0) {
-err = pcm_unregister(dev);
-if (err != 0)
-return (err);
-}
+ struct hdac_softc *sc = NULL;
+ struct hdac_devinfo *devinfo = NULL;
+ int err;
+
+ devinfo = (struct hdac_devinfo *)pcm_getdevinfo(dev);
+ if (devinfo != NULL && devinfo->codec != NULL)
+ sc = devinfo->codec->sc;
+ if (sc == NULL)
+ return (0);
+
+ if (sc->registered > 0) {
+ err = pcm_unregister(dev);
+ if (err != 0)
+ return (err);
+ }
-hdac_release_resources(sc);
+ hdac_release_resources(sc);
-return (0);
+ return (0);
}
static device_method_t hdac_methods[] = {
-/* device interface */
-DEVMETHOD(device_probe, hdac_probe),
-DEVMETHOD(device_attach, hdac_attach),
-DEVMETHOD(device_detach, hdac_detach),
-{ 0, 0 }
+ /* device interface */
+ DEVMETHOD(device_probe, hdac_probe),
+ DEVMETHOD(device_attach, hdac_attach),
+ DEVMETHOD(device_detach, hdac_detach),
+ { 0, 0 }
};
static driver_t hdac_driver = {
-"pcm",
-hdac_methods,
-PCM_SOFTC_SIZE,
+ "pcm",
+ hdac_methods,
+ PCM_SOFTC_SIZE,
};
DRIVER_MODULE(snd_hda, pci, hdac_driver, pcm_devclass, 0, 0);
Index: hdac_private.h
===================================================================
RCS file: /home/cvs/src/sys/dev/sound/pci/hda/hdac_private.h,v
retrieving revision 1.1
retrieving revision 1.2
diff -L sys/dev/sound/pci/hda/hdac_private.h -L sys/dev/sound/pci/hda/hdac_private.h -u -r1.1 -r1.2
--- sys/dev/sound/pci/hda/hdac_private.h
+++ sys/dev/sound/pci/hda/hdac_private.h
@@ -1,53 +1,58 @@
/*-
-* Copyright (c) 2006 Stephane E. Potvin <sepotvin at videotron.ca>
-* All rights reserved.
-*
-* Redistribution and use in source and binary forms, with or without
-* modification, are permitted provided that the following conditions
-* are met:
-* 1. Redistributions of source code must retain the above copyright
-* notice, this list of conditions and the following disclaimer.
-* 2. Redistributions in binary form must reproduce the above copyright
-* notice, this list of conditions and the following disclaimer in the
-* documentation and/or other materials provided with the distribution.
-*
-* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
-* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
-* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
-* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
-* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
-* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
-* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
-* SUCH DAMAGE.
-*
-* $MidnightBSD$
-* $FreeBSD: src/sys/dev/sound/pci/hda/hdac_private.h,v 1.2 2006/10/06 18:59:27 ariff Exp $
-*/
+ * Copyright (c) 2006 Stephane E. Potvin <sepotvin at videotron.ca>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD: src/sys/dev/sound/pci/hda/hdac_private.h,v 1.8 2007/07/09 20:42:11 ariff Exp $
+ */
#ifndef _HDAC_PRIVATE_H_
#define _HDAC_PRIVATE_H_
/****************************************************************************
-* Miscellanious defines
-****************************************************************************/
+ * Miscellaneous defines
+ ****************************************************************************/
#define HDAC_DMA_ALIGNMENT 128
#define HDAC_CODEC_MAX 16
#define HDAC_MTX_NAME "hdac driver mutex"
/****************************************************************************
-* Helper Macros
-****************************************************************************/
-#define HDAC_READ_1(mem, offset) bus_space_read_1((mem)->mem_tag, (mem)->mem_handle, (offset))
-#define HDAC_READ_2(mem, offset) bus_space_read_2((mem)->mem_tag, (mem)->mem_handle, (offset))
-#define HDAC_READ_4(mem, offset) bus_space_read_4((mem)->mem_tag, (mem)->mem_handle, (offset))
-#define HDAC_WRITE_1(mem, offset, value) bus_space_write_1((mem)->mem_tag, (mem)->mem_handle, (offset), (value))
-#define HDAC_WRITE_2(mem, offset, value) bus_space_write_2((mem)->mem_tag, (mem)->mem_handle, (offset), (value))
-#define HDAC_WRITE_4(mem, offset, value) bus_space_write_4((mem)->mem_tag, (mem)->mem_handle, (offset), (value))
+ * Helper Macros
+ ****************************************************************************/
+#define HDAC_READ_1(mem, offset) \
+ bus_space_read_1((mem)->mem_tag, (mem)->mem_handle, (offset))
+#define HDAC_READ_2(mem, offset) \
+ bus_space_read_2((mem)->mem_tag, (mem)->mem_handle, (offset))
+#define HDAC_READ_4(mem, offset) \
+ bus_space_read_4((mem)->mem_tag, (mem)->mem_handle, (offset))
+#define HDAC_WRITE_1(mem, offset, value) \
+ bus_space_write_1((mem)->mem_tag, (mem)->mem_handle, (offset), (value))
+#define HDAC_WRITE_2(mem, offset, value) \
+ bus_space_write_2((mem)->mem_tag, (mem)->mem_handle, (offset), (value))
+#define HDAC_WRITE_4(mem, offset, value) \
+ bus_space_write_4((mem)->mem_tag, (mem)->mem_handle, (offset), (value))
#define HDAC_ISDCTL(sc, n) (_HDAC_ISDCTL((n), (sc)->num_iss, (sc)->num_oss))
#define HDAC_ISDSTS(sc, n) (_HDAC_ISDSTS((n), (sc)->num_iss, (sc)->num_oss))
@@ -79,97 +84,100 @@
/****************************************************************************
-* Custom hdac malloc type
-****************************************************************************/
+ * Custom hdac malloc type
+ ****************************************************************************/
MALLOC_DECLARE(M_HDAC);
/****************************************************************************
-* struct hdac_mem
-*
-* Holds the resources necessary to describe the physical memory associated
-* with the device.
-****************************************************************************/
+ * struct hdac_mem
+ *
+ * Holds the resources necessary to describe the physical memory associated
+ * with the device.
+ ****************************************************************************/
struct hdac_mem {
-struct resource *mem_res;
-int mem_rid;
-bus_space_tag_t mem_tag;
-bus_space_handle_t mem_handle;
+ struct resource *mem_res;
+ int mem_rid;
+ bus_space_tag_t mem_tag;
+ bus_space_handle_t mem_handle;
};
/****************************************************************************
-* struct hdac_irq
-*
-* Holds the resources necessary to describe the irq associated with the
-* device.
-****************************************************************************/
+ * struct hdac_irq
+ *
+ * Holds the resources necessary to describe the irq associated with the
+ * device.
+ ****************************************************************************/
struct hdac_irq {
-struct resource *irq_res;
-int irq_rid;
-void *irq_handle;
+ struct resource *irq_res;
+ int irq_rid;
+ void *irq_handle;
};
/****************************************************************************
-* struct hdac_dma
-*
-* This structure is used to hold all the information to manage the dma
-* states.
-****************************************************************************/
+ * struct hdac_dma
+ *
+ * This structure is used to hold all the information to manage the dma
+ * states.
+ ****************************************************************************/
struct hdac_dma {
-bus_dma_tag_t dma_tag;
-bus_dmamap_t dma_map;
-bus_addr_t dma_paddr;
-caddr_t dma_vaddr;
+ bus_dma_tag_t dma_tag;
+ bus_dmamap_t dma_map;
+ bus_addr_t dma_paddr;
+ bus_size_t dma_size;
+ caddr_t dma_vaddr;
};
/****************************************************************************
-* struct hdac_rirb
-*
-* Hold a response from a verb sent to a codec received via the rirb.
-****************************************************************************/
+ * struct hdac_rirb
+ *
+ * Hold a response from a verb sent to a codec received via the rirb.
+ ****************************************************************************/
struct hdac_rirb {
-uint32_t response;
-uint32_t response_ex;
+ uint32_t response;
+ uint32_t response_ex;
};
#define HDAC_RIRB_RESPONSE_EX_SDATA_IN_MASK 0x0000000f
#define HDAC_RIRB_RESPONSE_EX_SDATA_IN_OFFSET 0
#define HDAC_RIRB_RESPONSE_EX_UNSOLICITED 0x00000010
-#define HDAC_RIRB_RESPONSE_EX_SDATA_IN(response_ex) (((response_ex) & HDAC_RIRB_RESPONSE_EX_SDATA_IN_MASK) >> HDAC_RIRB_RESPONSE_EX_SDATA_IN_OFFSET)
+#define HDAC_RIRB_RESPONSE_EX_SDATA_IN(response_ex) \
+ (((response_ex) & HDAC_RIRB_RESPONSE_EX_SDATA_IN_MASK) >> \
+ HDAC_RIRB_RESPONSE_EX_SDATA_IN_OFFSET)
/****************************************************************************
-* struct hdac_command_list
-*
-* This structure holds the list of verbs that are to be sent to the codec
-* via the corb and the responses received via the rirb. It's allocated by
-* the codec driver and is owned by it.
-****************************************************************************/
+ * struct hdac_command_list
+ *
+ * This structure holds the list of verbs that are to be sent to the codec
+ * via the corb and the responses received via the rirb. It's allocated by
+ * the codec driver and is owned by it.
+ ****************************************************************************/
struct hdac_command_list {
-int num_commands;
-uint32_t *verbs;
-uint32_t *responses;
+ int num_commands;
+ uint32_t *verbs;
+ uint32_t *responses;
};
typedef int nid_t;
struct hdac_softc;
/****************************************************************************
-* struct hdac_codec
-*
-****************************************************************************/
+ * struct hdac_codec
+ *
+ ****************************************************************************/
struct hdac_codec {
-int verbs_sent;
-int responses_received;
-nid_t cad;
-struct hdac_command_list *commands;
-struct hdac_softc *sc;
+ int verbs_sent;
+ int responses_received;
+ nid_t cad;
+ struct hdac_command_list *commands;
+ struct hdac_softc *sc;
};
struct hdac_bdle {
-volatile uint32_t addrl;
-volatile uint32_t addrh;
-volatile uint32_t len;
-volatile uint32_t ioc;
+ volatile uint32_t addrl;
+ volatile uint32_t addrh;
+ volatile uint32_t len;
+ volatile uint32_t ioc;
} __packed;
#define HDA_MAX_CONNS 32
@@ -178,147 +186,172 @@
struct hdac_devinfo;
struct hdac_widget {
-nid_t nid;
-int type;
-int enable;
-int nconns, selconn;
-uint32_t pflags, ctlflags;
-nid_t conns[HDA_MAX_CONNS];
-char name[HDA_MAX_NAMELEN];
-struct hdac_devinfo *devinfo;
-struct {
-uint32_t widget_cap;
-uint32_t outamp_cap;
-uint32_t inamp_cap;
-uint32_t supp_stream_formats;
-uint32_t supp_pcm_size_rate;
-uint32_t eapdbtl;
-int outpath;
-} param;
-union {
-struct {
-uint32_t config;
-uint32_t cap;
-uint32_t ctrl;
-} pin;
-} wclass;
+ nid_t nid;
+ int type;
+ int enable;
+ int nconns, selconn;
+ uint32_t pflags, ctlflags;
+ nid_t conns[HDA_MAX_CONNS];
+ char name[HDA_MAX_NAMELEN];
+ struct hdac_devinfo *devinfo;
+ struct {
+ uint32_t widget_cap;
+ uint32_t outamp_cap;
+ uint32_t inamp_cap;
+ uint32_t supp_stream_formats;
+ uint32_t supp_pcm_size_rate;
+ uint32_t eapdbtl;
+ int outpath;
+ } param;
+ union {
+ struct {
+ uint32_t config;
+ uint32_t cap;
+ uint32_t ctrl;
+ } pin;
+ } wclass;
};
struct hdac_audio_ctl {
-struct hdac_widget *widget, *childwidget;
-int enable;
-int index;
-int mute, step, size, offset;
-int left, right;
-uint32_t muted;
-int ossdev;
-uint32_t dir, ossmask, ossval;
+ struct hdac_widget *widget, *childwidget;
+ int enable;
+ int index;
+ int mute, step, size, offset;
+ int left, right;
+ uint32_t muted;
+ int ossdev;
+ uint32_t dir, ossmask, ossval;
};
/****************************************************************************
-* struct hdac_devinfo
-*
-* Holds all the parameters of a given codec function group. This is stored
-* in the ivar of each child of the hdac bus
-****************************************************************************/
+ * struct hdac_devinfo
+ *
+ * Holds all the parameters of a given codec function group. This is stored
+ * in the ivar of each child of the hdac bus
+ ****************************************************************************/
struct hdac_devinfo {
-device_t dev;
-uint16_t vendor_id;
-uint16_t device_id;
-uint8_t revision_id;
-uint8_t stepping_id;
-uint8_t node_type;
-nid_t nid;
-nid_t startnode, endnode;
-int nodecnt;
-struct hdac_codec *codec;
-struct hdac_widget *widget;
-union {
-struct {
-uint32_t outamp_cap;
-uint32_t inamp_cap;
-uint32_t supp_stream_formats;
-uint32_t supp_pcm_size_rate;
-int ctlcnt, pcnt, rcnt;
-struct hdac_audio_ctl *ctl;
-uint32_t mvol;
-uint32_t quirks;
-int ossidx;
-int playcnt, reccnt;
-int parsing_strategy;
-} audio;
-/* XXX undefined: modem, hdmi. */
-} function;
+ device_t dev;
+ uint16_t vendor_id;
+ uint16_t device_id;
+ uint8_t revision_id;
+ uint8_t stepping_id;
+ uint8_t node_type;
+ nid_t nid;
+ nid_t startnode, endnode;
+ int nodecnt;
+ struct hdac_codec *codec;
+ struct hdac_widget *widget;
+ union {
+ struct {
+ uint32_t outamp_cap;
+ uint32_t inamp_cap;
+ uint32_t supp_stream_formats;
+ uint32_t supp_pcm_size_rate;
+ int ctlcnt, pcnt, rcnt;
+ struct hdac_audio_ctl *ctl;
+ uint32_t mvol;
+ uint32_t quirks;
+ uint32_t gpio;
+ int ossidx;
+ int playcnt, reccnt;
+ int parsing_strategy;
+ } audio;
+ /* XXX undefined: modem, hdmi. */
+ } function;
};
+#define HDAC_CHN_RUNNING 0x00000001
+#define HDAC_CHN_SUSPEND 0x00000002
+
struct hdac_chan {
-struct snd_dbuf *b;
-struct pcm_channel *c;
-struct pcmchan_caps caps;
-struct hdac_devinfo *devinfo;
-struct hdac_dma bdl_dma;
-uint32_t spd, fmt, fmtlist[8], pcmrates[16];
-uint32_t supp_stream_formats, supp_pcm_size_rate;
-int ptr, prevptr, blkcnt, blksz;
-int dir;
-int off;
-int sid;
-int bit16, bit32;
-nid_t io[16];
+ struct snd_dbuf *b;
+ struct pcm_channel *c;
+ struct pcmchan_caps caps;
+ struct hdac_devinfo *devinfo;
+ struct hdac_dma bdl_dma;
+ uint32_t spd, fmt, fmtlist[8], pcmrates[16];
+ uint32_t supp_stream_formats, supp_pcm_size_rate;
+ uint32_t ptr, prevptr, blkcnt, blksz;
+ uint32_t *dmapos;
+ uint32_t flags;
+ int dir;
+ int off;
+ int sid;
+ int bit16, bit32;
+ nid_t io[16];
};
/****************************************************************************
-* struct hdac_softc
-*
-* This structure holds the current state of the hdac driver.
-****************************************************************************/
+ * struct hdac_softc
+ *
+ * This structure holds the current state of the hdac driver.
+ ****************************************************************************/
+
+#define HDAC_F_DMA_NOCACHE 0x00000001
+#define HDAC_F_MSI 0x00000002
+
struct hdac_softc {
-device_t dev;
-device_t hdabus;
-struct mtx *lock;
-
-struct intr_config_hook intrhook;
-
-struct hdac_mem mem;
-struct hdac_irq irq;
-uint32_t pci_subvendor;
-
-
-int num_iss;
-int num_oss;
-int num_bss;
-int support_64bit;
-int streamcnt;
-
-int corb_size;
-struct hdac_dma corb_dma;
-int corb_wp;
-
-int rirb_size;
-struct hdac_dma rirb_dma;
-int rirb_rp;
-
-struct hdac_chan play, rec;
-bus_dma_tag_t chan_dmat;
-int chan_size;
-int chan_blkcnt;
+ device_t dev;
+ device_t hdabus;
+ struct mtx *lock;
+
+ struct intr_config_hook intrhook;
+
+ struct hdac_mem mem;
+ struct hdac_irq irq;
+ uint32_t pci_subvendor;
+
+ uint32_t flags;
+
+ int num_iss;
+ int num_oss;
+ int num_bss;
+ int support_64bit;
+ int streamcnt;
+
+ int corb_size;
+ struct hdac_dma corb_dma;
+ int corb_wp;
+
+ int rirb_size;
+ struct hdac_dma rirb_dma;
+ int rirb_rp;
+
+ struct hdac_dma pos_dma;
+
+ struct hdac_chan play, rec;
+ bus_dma_tag_t chan_dmat;
+ int chan_size;
+ int chan_blkcnt;
+
+ /*
+ * Polling
+ */
+ int polling;
+ int poll_ticks;
+ int poll_ival;
+ struct callout poll_hda;
+ struct callout poll_hdac;
+ struct callout poll_jack;
+
+ struct task unsolq_task;
#define HDAC_UNSOLQ_MAX 64
#define HDAC_UNSOLQ_READY 0
#define HDAC_UNSOLQ_BUSY 1
-int unsolq_rp;
-int unsolq_wp;
-int unsolq_st;
-uint32_t unsolq[HDAC_UNSOLQ_MAX];
+ int unsolq_rp;
+ int unsolq_wp;
+ int unsolq_st;
+ uint32_t unsolq[HDAC_UNSOLQ_MAX];
-struct hdac_codec *codecs[HDAC_CODEC_MAX];
+ struct hdac_codec *codecs[HDAC_CODEC_MAX];
-int registered;
+ int registered;
};
/****************************************************************************
-* struct hdac_command flags
-****************************************************************************/
+ * struct hdac_command flags
+ ****************************************************************************/
#define HDAC_COMMAND_FLAG_WAITOK 0x0000
#define HDAC_COMMAND_FLAG_NOWAIT 0x0001
Index: gusc.c
===================================================================
RCS file: /home/cvs/src/sys/dev/sound/isa/gusc.c,v
retrieving revision 1.2
retrieving revision 1.3
diff -L sys/dev/sound/isa/gusc.c -L sys/dev/sound/isa/gusc.c -u -r1.2 -r1.3
--- sys/dev/sound/isa/gusc.c
+++ sys/dev/sound/isa/gusc.c
@@ -1,29 +1,29 @@
/*-
-* Copyright (c) 1999 Seigo Tanimura
-* Copyright (c) 1999 Ville-Pertti Keinonen
-* All rights reserved.
-*
-* Redistribution and use in source and binary forms, with or without
-* modification, are permitted provided that the following conditions
-* are met:
-* 1. Redistributions of source code must retain the above copyright
-* notice, this list of conditions and the following disclaimer.
-* 2. Redistributions in binary form must reproduce the above copyright
-* notice, this list of conditions and the following disclaimer in the
-* documentation and/or other materials provided with the distribution.
-*
-* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
-* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
-* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
-* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
-* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
-* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
-* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
-* SUCH DAMAGE.
-*/
+ * Copyright (c) 1999 Seigo Tanimura
+ * Copyright (c) 1999 Ville-Pertti Keinonen
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
#include <sys/param.h>
#include <sys/systm.h>
@@ -41,11 +41,8 @@
#include <isa/isavar.h>
#include <isa/isa_common.h>
-#ifdef __alpha__ /* XXX workaround a stupid warning */
-#include <alpha/isa/isavar.h>
-#endif
-SND_DECLARE_FILE("$MidnightBSD$");
+SND_DECLARE_FILE("$FreeBSD: src/sys/dev/sound/isa/gusc.c,v 1.19 2007/02/23 19:40:13 ariff Exp $");
#define LOGICALID_NOPNP 0
#define LOGICALID_PCM 0x0000561e
@@ -54,33 +51,33 @@
/* PnP IDs */
static struct isa_pnp_id gusc_ids[] = {
-{LOGICALID_PCM, "GRV0000 Gravis UltraSound PnP PCM"}, /* GRV0000 */
-{LOGICALID_OPL, "GRV0003 Gravis UltraSound PnP OPL"}, /* GRV0003 */
-{LOGICALID_MIDI, "GRV0004 Gravis UltraSound PnP MIDI"}, /* GRV0004 */
+ {LOGICALID_PCM, "GRV0000 Gravis UltraSound PnP PCM"}, /* GRV0000 */
+ {LOGICALID_OPL, "GRV0003 Gravis UltraSound PnP OPL"}, /* GRV0003 */
+ {LOGICALID_MIDI, "GRV0004 Gravis UltraSound PnP MIDI"}, /* GRV0004 */
};
/* Interrupt handler. */
struct gusc_ihandler {
-void (*intr)(void *);
-void *arg;
+ void (*intr)(void *);
+ void *arg;
};
/* Here is the parameter structure per a device. */
struct gusc_softc {
-device_t dev; /* device */
-int io_rid[3]; /* io port rids */
-struct resource *io[3]; /* io port resources */
-int io_alloced[3]; /* io port alloc flag */
-int irq_rid; /* irq rids */
-struct resource *irq; /* irq resources */
-int irq_alloced; /* irq alloc flag */
-int drq_rid[2]; /* drq rids */
-struct resource *drq[2]; /* drq resources */
-int drq_alloced[2]; /* drq alloc flag */
-
-/* Interrupts are shared (XXX non-PnP only?) */
-struct gusc_ihandler midi_intr;
-struct gusc_ihandler pcm_intr;
+ device_t dev; /* device */
+ int io_rid[3]; /* io port rids */
+ struct resource *io[3]; /* io port resources */
+ int io_alloced[3]; /* io port alloc flag */
+ int irq_rid; /* irq rids */
+ struct resource *irq; /* irq resources */
+ int irq_alloced; /* irq alloc flag */
+ int drq_rid[2]; /* drq rids */
+ struct resource *drq[2]; /* drq resources */
+ int drq_alloced[2]; /* drq alloc flag */
+
+ /* Interrupts are shared (XXX non-PnP only?) */
+ struct gusc_ihandler midi_intr;
+ struct gusc_ihandler pcm_intr;
};
typedef struct gusc_softc *sc_p;
@@ -90,9 +87,9 @@
static int gusisa_probe(device_t dev);
static void gusc_intr(void *);
static struct resource *gusc_alloc_resource(device_t bus, device_t child, int type, int *rid,
-u_long start, u_long end, u_long count, u_int flags);
+ u_long start, u_long end, u_long count, u_int flags);
static int gusc_release_resource(device_t bus, device_t child, int type, int rid,
-struct resource *r);
+ struct resource *r);
static device_t find_masterdev(sc_p scp);
static int alloc_resource(sc_p scp);
@@ -103,365 +100,377 @@
static int
gusc_probe(device_t dev)
{
-device_t child;
-u_int32_t logical_id;
-char *s;
-struct sndcard_func *func;
-int ret;
-
-logical_id = isa_get_logicalid(dev);
-s = NULL;
-
-/* Check isapnp ids */
-if (logical_id != 0 && (ret = ISA_PNP_PROBE(device_get_parent(dev), dev, gusc_ids)) != 0)
-return (ret);
-else {
-if (logical_id == 0)
-return gusisa_probe(dev);
-}
-
-switch (logical_id) {
-case LOGICALID_PCM:
-s = "Gravis UltraSound Plug & Play PCM";
-func = malloc(sizeof(struct sndcard_func), M_DEVBUF, M_NOWAIT | M_ZERO);
-if (func == NULL)
-return (ENOMEM);
-func->func = SCF_PCM;
-child = device_add_child(dev, "pcm", -1);
-device_set_ivars(child, func);
-break;
-case LOGICALID_OPL:
-s = "Gravis UltraSound Plug & Play OPL";
-func = malloc(sizeof(struct sndcard_func), M_DEVBUF, M_NOWAIT | M_ZERO);
-if (func == NULL)
-return (ENOMEM);
-func->func = SCF_SYNTH;
-child = device_add_child(dev, "midi", -1);
-device_set_ivars(child, func);
-break;
-case LOGICALID_MIDI:
-s = "Gravis UltraSound Plug & Play MIDI";
-func = malloc(sizeof(struct sndcard_func), M_DEVBUF, M_NOWAIT | M_ZERO);
-if (func == NULL)
-return (ENOMEM);
-func->func = SCF_MIDI;
-child = device_add_child(dev, "midi", -1);
-device_set_ivars(child, func);
-break;
-}
-
-if (s != NULL) {
-device_set_desc(dev, s);
-return (0);
-}
+ device_t child;
+ u_int32_t logical_id;
+ char *s;
+ struct sndcard_func *func;
+ int ret;
+
+ logical_id = isa_get_logicalid(dev);
+ s = NULL;
+
+ /* Check isapnp ids */
+ if (logical_id != 0 && (ret = ISA_PNP_PROBE(device_get_parent(dev), dev, gusc_ids)) != 0)
+ return (ret);
+ else {
+ if (logical_id == 0)
+ return gusisa_probe(dev);
+ }
+
+ switch (logical_id) {
+ case LOGICALID_PCM:
+ s = "Gravis UltraSound Plug & Play PCM";
+ func = malloc(sizeof(struct sndcard_func), M_DEVBUF, M_NOWAIT | M_ZERO);
+ if (func == NULL)
+ return (ENOMEM);
+ func->func = SCF_PCM;
+ child = device_add_child(dev, "pcm", -1);
+ device_set_ivars(child, func);
+ break;
+ case LOGICALID_OPL:
+ s = "Gravis UltraSound Plug & Play OPL";
+ func = malloc(sizeof(struct sndcard_func), M_DEVBUF, M_NOWAIT | M_ZERO);
+ if (func == NULL)
+ return (ENOMEM);
+ func->func = SCF_SYNTH;
+ child = device_add_child(dev, "midi", -1);
+ device_set_ivars(child, func);
+ break;
+ case LOGICALID_MIDI:
+ s = "Gravis UltraSound Plug & Play MIDI";
+ func = malloc(sizeof(struct sndcard_func), M_DEVBUF, M_NOWAIT | M_ZERO);
+ if (func == NULL)
+ return (ENOMEM);
+ func->func = SCF_MIDI;
+ child = device_add_child(dev, "midi", -1);
+ device_set_ivars(child, func);
+ break;
+ }
+
+ if (s != NULL) {
+ device_set_desc(dev, s);
+ return (0);
+ }
-return (ENXIO);
+ return (ENXIO);
}
static void
port_wr(struct resource *r, int i, unsigned char v)
{
-bus_space_write_1(rman_get_bustag(r), rman_get_bushandle(r), i, v);
+ bus_space_write_1(rman_get_bustag(r), rman_get_bushandle(r), i, v);
}
static int
port_rd(struct resource *r, int i)
{
-return bus_space_read_1(rman_get_bustag(r), rman_get_bushandle(r), i);
+ return bus_space_read_1(rman_get_bustag(r), rman_get_bushandle(r), i);
}
/*
-* Probe for an old (non-PnP) GUS card on the ISA bus.
-*/
+ * Probe for an old (non-PnP) GUS card on the ISA bus.
+ */
static int
gusisa_probe(device_t dev)
{
-device_t child;
-struct resource *res, *res2;
-int base, rid, rid2, s, flags;
-unsigned char val;
-
-base = isa_get_port(dev);
-flags = device_get_flags(dev);
-rid = 1;
-res = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid, base + 0x100,
-base + 0x107, 8, RF_ACTIVE);
-
-if (res == NULL)
-return ENXIO;
-
-res2 = NULL;
-
-/*
-* Check for the presence of some GUS card. Reset the card,
-* then see if we can access the memory on it.
-*/
-
-port_wr(res, 3, 0x4c);
-port_wr(res, 5, 0);
-DELAY(30 * 1000);
-
-port_wr(res, 3, 0x4c);
-port_wr(res, 5, 1);
-DELAY(30 * 1000);
-
-s = splhigh();
-
-/* Write to DRAM. */
-
-port_wr(res, 3, 0x43); /* Register select */
-port_wr(res, 4, 0); /* Low addr */
-port_wr(res, 5, 0); /* Med addr */
-
-port_wr(res, 3, 0x44); /* Register select */
-port_wr(res, 4, 0); /* High addr */
-port_wr(res, 7, 0x55); /* DRAM */
-
-/* Read from DRAM. */
-
-port_wr(res, 3, 0x43); /* Register select */
-port_wr(res, 4, 0); /* Low addr */
-port_wr(res, 5, 0); /* Med addr */
-
-port_wr(res, 3, 0x44); /* Register select */
-port_wr(res, 4, 0); /* High addr */
-val = port_rd(res, 7); /* DRAM */
-
-splx(s);
-
-if (val != 0x55)
-goto fail;
-
-rid2 = 0;
-res2 = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid2, base, base, 1,
-RF_ACTIVE);
-
-if (res2 == NULL)
-goto fail;
-
-s = splhigh();
-port_wr(res2, 0x0f, 0x20);
-val = port_rd(res2, 0x0f);
-splx(s);
-
-if (val == 0xff || (val & 0x06) == 0)
-val = 0;
-else {
-val = port_rd(res2, 0x506); /* XXX Out of range. */
-if (val == 0xff)
-val = 0;
-}
-
-bus_release_resource(dev, SYS_RES_IOPORT, rid2, res2);
-bus_release_resource(dev, SYS_RES_IOPORT, rid, res);
-
-if (val >= 10) {
-struct sndcard_func *func;
-
-/* Looks like a GUS MAX. Set the rest of the resources. */
-
-bus_set_resource(dev, SYS_RES_IOPORT, 2, base + 0x10c, 8);
-
-if (flags & DV_F_DUAL_DMA)
-bus_set_resource(dev, SYS_RES_DRQ, 1,
-flags & DV_F_DRQ_MASK, 1);
-
-/* We can support the CS4231 and MIDI devices. */
-
-func = malloc(sizeof(struct sndcard_func), M_DEVBUF, M_NOWAIT | M_ZERO);
-if (func == NULL)
-return ENOMEM;
-func->func = SCF_MIDI;
-child = device_add_child(dev, "midi", -1);
-device_set_ivars(child, func);
-
-func = malloc(sizeof(struct sndcard_func), M_DEVBUF, M_NOWAIT | M_ZERO);
-if (func == NULL)
-printf("xxx: gus pcm not attached, out of memoryn");
-else {
-func->func = SCF_PCM;
-child = device_add_child(dev, "pcm", -1);
-device_set_ivars(child, func);
-}
-device_set_desc(dev, "Gravis UltraSound MAX");
-return 0;
-} else {
-
-/*
-* TODO: Support even older GUS cards. MIDI should work on
-* all models.
-*/
-return ENXIO;
-}
+ device_t child;
+ struct resource *res, *res2;
+ int base, rid, rid2, s, flags;
+ unsigned char val;
+
+ base = isa_get_port(dev);
+ flags = device_get_flags(dev);
+ rid = 1;
+ res = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid, base + 0x100,
+ base + 0x107, 8, RF_ACTIVE);
+
+ if (res == NULL)
+ return ENXIO;
+
+ res2 = NULL;
+
+ /*
+ * Check for the presence of some GUS card. Reset the card,
+ * then see if we can access the memory on it.
+ */
+
+ port_wr(res, 3, 0x4c);
+ port_wr(res, 5, 0);
+ DELAY(30 * 1000);
+
+ port_wr(res, 3, 0x4c);
+ port_wr(res, 5, 1);
+ DELAY(30 * 1000);
+
+ s = splhigh();
+
+ /* Write to DRAM. */
+
+ port_wr(res, 3, 0x43); /* Register select */
+ port_wr(res, 4, 0); /* Low addr */
+ port_wr(res, 5, 0); /* Med addr */
+
+ port_wr(res, 3, 0x44); /* Register select */
+ port_wr(res, 4, 0); /* High addr */
+ port_wr(res, 7, 0x55); /* DRAM */
+
+ /* Read from DRAM. */
+
+ port_wr(res, 3, 0x43); /* Register select */
+ port_wr(res, 4, 0); /* Low addr */
+ port_wr(res, 5, 0); /* Med addr */
+
+ port_wr(res, 3, 0x44); /* Register select */
+ port_wr(res, 4, 0); /* High addr */
+ val = port_rd(res, 7); /* DRAM */
+
+ splx(s);
+
+ if (val != 0x55)
+ goto fail;
+
+ rid2 = 0;
+ res2 = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid2, base, base, 1,
+ RF_ACTIVE);
+
+ if (res2 == NULL)
+ goto fail;
+
+ s = splhigh();
+ port_wr(res2, 0x0f, 0x20);
+ val = port_rd(res2, 0x0f);
+ splx(s);
+
+ if (val == 0xff || (val & 0x06) == 0)
+ val = 0;
+ else {
+ val = port_rd(res2, 0x506); /* XXX Out of range. */
+ if (val == 0xff)
+ val = 0;
+ }
+
+ bus_release_resource(dev, SYS_RES_IOPORT, rid2, res2);
+ bus_release_resource(dev, SYS_RES_IOPORT, rid, res);
+
+ if (val >= 10) {
+ struct sndcard_func *func;
+
+ /* Looks like a GUS MAX. Set the rest of the resources. */
+
+ bus_set_resource(dev, SYS_RES_IOPORT, 2, base + 0x10c, 8);
+
+ if (flags & DV_F_DUAL_DMA)
+ bus_set_resource(dev, SYS_RES_DRQ, 1,
+ flags & DV_F_DRQ_MASK, 1);
+
+ /* We can support the CS4231 and MIDI devices. */
+
+ func = malloc(sizeof(struct sndcard_func), M_DEVBUF, M_NOWAIT | M_ZERO);
+ if (func == NULL)
+ return ENOMEM;
+ func->func = SCF_MIDI;
+ child = device_add_child(dev, "midi", -1);
+ device_set_ivars(child, func);
+
+ func = malloc(sizeof(struct sndcard_func), M_DEVBUF, M_NOWAIT | M_ZERO);
+ if (func == NULL)
+ printf("xxx: gus pcm not attached, out of memory\n");
+ else {
+ func->func = SCF_PCM;
+ child = device_add_child(dev, "pcm", -1);
+ device_set_ivars(child, func);
+ }
+ device_set_desc(dev, "Gravis UltraSound MAX");
+ return 0;
+ } else {
+
+ /*
+ * TODO: Support even older GUS cards. MIDI should work on
+ * all models.
+ */
+ return ENXIO;
+ }
fail:
-bus_release_resource(dev, SYS_RES_IOPORT, rid, res);
-return ENXIO;
+ bus_release_resource(dev, SYS_RES_IOPORT, rid, res);
+ return ENXIO;
}
static int
gusc_attach(device_t dev)
{
-sc_p scp;
-int unit;
-void *ih;
-
-scp = device_get_softc(dev);
-unit = device_get_unit(dev);
-
-bzero(scp, sizeof(*scp));
-
-scp->dev = dev;
-if (alloc_resource(scp)) {
-release_resource(scp);
-return (ENXIO);
-}
-
-if (scp->irq != NULL)
-bus_setup_intr(dev, scp->irq, INTR_TYPE_AV, gusc_intr, scp, &ih);
-bus_generic_attach(dev);
+ sc_p scp;
+ int unit;
+ void *ih;
+
+ scp = device_get_softc(dev);
+ unit = device_get_unit(dev);
+
+ bzero(scp, sizeof(*scp));
+
+ scp->dev = dev;
+ if (alloc_resource(scp)) {
+ release_resource(scp);
+ return (ENXIO);
+ }
+
+ if (scp->irq != NULL)
+ snd_setup_intr(dev, scp->irq, 0, gusc_intr, scp, &ih);
+ bus_generic_attach(dev);
-return (0);
+ return (0);
}
/*
-* Handle interrupts on GUS devices until there aren't any left.
-*/
+ * Handle interrupts on GUS devices until there aren't any left.
+ */
static void
gusc_intr(void *arg)
{
-sc_p scp = (sc_p)arg;
-int did_something;
+ sc_p scp = (sc_p)arg;
+ int did_something;
-do {
-did_something = 0;
-if (scp->pcm_intr.intr != NULL &&
-(port_rd(scp->io[2], 2) & 1)) {
-(*scp->pcm_intr.intr)(scp->pcm_intr.arg);
-did_something = 1;
-}
-if (scp->midi_intr.intr != NULL &&
-(port_rd(scp->io[1], 0) & 0x80)) {
-(*scp->midi_intr.intr)(scp->midi_intr.arg);
-did_something = 1;
-}
-} while (did_something != 0);
+ do {
+ did_something = 0;
+ if (scp->pcm_intr.intr != NULL &&
+ (port_rd(scp->io[2], 2) & 1)) {
+ (*scp->pcm_intr.intr)(scp->pcm_intr.arg);
+ did_something = 1;
+ }
+ if (scp->midi_intr.intr != NULL &&
+ (port_rd(scp->io[1], 0) & 0x80)) {
+ (*scp->midi_intr.intr)(scp->midi_intr.arg);
+ did_something = 1;
+ }
+ } while (did_something != 0);
}
static struct resource *
gusc_alloc_resource(device_t bus, device_t child, int type, int *rid,
-u_long start, u_long end, u_long count, u_int flags)
+ u_long start, u_long end, u_long count, u_int flags)
{
-sc_p scp;
-int *alloced, rid_max, alloced_max;
-struct resource **res;
-
-scp = device_get_softc(bus);
-switch (type) {
-case SYS_RES_IOPORT:
-alloced = scp->io_alloced;
-res = scp->io;
-rid_max = 2;
-alloced_max = 2; /* pcm + midi (more to include synth) */
-break;
-case SYS_RES_IRQ:
-alloced = &scp->irq_alloced;
-res = &scp->irq;
-rid_max = 0;
-alloced_max = 2; /* pcm and midi share the single irq. */
-break;
-case SYS_RES_DRQ:
-alloced = scp->drq_alloced;
-res = scp->drq;
-rid_max = 1;
-alloced_max = 1;
-break;
-default:
-return (NULL);
-}
+ sc_p scp;
+ int *alloced, rid_max, alloced_max;
+ struct resource **res;
+
+ scp = device_get_softc(bus);
+ switch (type) {
+ case SYS_RES_IOPORT:
+ alloced = scp->io_alloced;
+ res = scp->io;
+ rid_max = 2;
+ alloced_max = 2; /* pcm + midi (more to include synth) */
+ break;
+ case SYS_RES_IRQ:
+ alloced = &scp->irq_alloced;
+ res = &scp->irq;
+ rid_max = 0;
+ alloced_max = 2; /* pcm and midi share the single irq. */
+ break;
+ case SYS_RES_DRQ:
+ alloced = scp->drq_alloced;
+ res = scp->drq;
+ rid_max = 1;
+ alloced_max = 1;
+ break;
+ default:
+ return (NULL);
+ }
-if (*rid > rid_max || alloced[*rid] == alloced_max)
-return (NULL);
+ if (*rid > rid_max || alloced[*rid] == alloced_max)
+ return (NULL);
-alloced[*rid]++;
-return (res[*rid]);
+ alloced[*rid]++;
+ return (res[*rid]);
}
static int
gusc_release_resource(device_t bus, device_t child, int type, int rid,
-struct resource *r)
+ struct resource *r)
{
-sc_p scp;
-int *alloced, rid_max;
+ sc_p scp;
+ int *alloced, rid_max;
-scp = device_get_softc(bus);
-switch (type) {
-case SYS_RES_IOPORT:
-alloced = scp->io_alloced;
-rid_max = 2;
-break;
-case SYS_RES_IRQ:
-alloced = &scp->irq_alloced;
-rid_max = 0;
-break;
-case SYS_RES_DRQ:
-alloced = scp->drq_alloced;
-rid_max = 1;
-break;
-default:
-return (1);
-}
+ scp = device_get_softc(bus);
+ switch (type) {
+ case SYS_RES_IOPORT:
+ alloced = scp->io_alloced;
+ rid_max = 2;
+ break;
+ case SYS_RES_IRQ:
+ alloced = &scp->irq_alloced;
+ rid_max = 0;
+ break;
+ case SYS_RES_DRQ:
+ alloced = scp->drq_alloced;
+ rid_max = 1;
+ break;
+ default:
+ return (1);
+ }
-if (rid > rid_max || alloced[rid] == 0)
-return (1);
+ if (rid > rid_max || alloced[rid] == 0)
+ return (1);
-alloced[rid]--;
-return (0);
+ alloced[rid]--;
+ return (0);
}
static int
-gusc_setup_intr(device_t dev, device_t child, struct resource *irq,
-int flags, driver_intr_t *intr, void *arg, void **cookiep)
+gusc_setup_intr(device_t dev, device_t child, struct resource *irq, int flags,
+#if __FreeBSD_version >= 700031
+ driver_filter_t *filter,
+#endif
+ driver_intr_t *intr, void *arg, void **cookiep)
{
-sc_p scp = (sc_p)device_get_softc(dev);
-devclass_t devclass;
+ sc_p scp = (sc_p)device_get_softc(dev);
+ devclass_t devclass;
-devclass = device_get_devclass(child);
-if (strcmp(devclass_get_name(devclass), "midi") == 0) {
-scp->midi_intr.intr = intr;
-scp->midi_intr.arg = arg;
-return 0;
-} else if (strcmp(devclass_get_name(devclass), "pcm") == 0) {
-scp->pcm_intr.intr = intr;
-scp->pcm_intr.arg = arg;
-return 0;
-}
-return bus_generic_setup_intr(dev, child, irq, flags, intr,
-arg, cookiep);
+#if __FreeBSD_version >= 700031
+ if (filter != NULL) {
+ printf("gusc.c: we cannot use a filter here\n");
+ return (EINVAL);
+ }
+#endif
+ devclass = device_get_devclass(child);
+ if (strcmp(devclass_get_name(devclass), "midi") == 0) {
+ scp->midi_intr.intr = intr;
+ scp->midi_intr.arg = arg;
+ return 0;
+ } else if (strcmp(devclass_get_name(devclass), "pcm") == 0) {
+ scp->pcm_intr.intr = intr;
+ scp->pcm_intr.arg = arg;
+ return 0;
+ }
+ return bus_generic_setup_intr(dev, child, irq, flags,
+#if __FreeBSD_version >= 700031
+ filter,
+#endif
+ intr, arg, cookiep);
}
static device_t
find_masterdev(sc_p scp)
{
-int i, units;
-devclass_t devclass;
-device_t dev;
-
-devclass = device_get_devclass(scp->dev);
-units = devclass_get_maxunit(devclass);
-dev = NULL;
-for (i = 0 ; i < units ; i++) {
-dev = devclass_get_device(devclass, i);
-if (isa_get_vendorid(dev) == isa_get_vendorid(scp->dev)
-&& isa_get_logicalid(dev) == LOGICALID_PCM
-&& isa_get_serial(dev) == isa_get_serial(scp->dev))
-break;
-}
-if (i == units)
-return (NULL);
+ int i, units;
+ devclass_t devclass;
+ device_t dev;
+
+ devclass = device_get_devclass(scp->dev);
+ units = devclass_get_maxunit(devclass);
+ dev = NULL;
+ for (i = 0 ; i < units ; i++) {
+ dev = devclass_get_device(devclass, i);
+ if (isa_get_vendorid(dev) == isa_get_vendorid(scp->dev)
+ && isa_get_logicalid(dev) == LOGICALID_PCM
+ && isa_get_serial(dev) == isa_get_serial(scp->dev))
+ break;
+ }
+ if (i == units)
+ return (NULL);
-return (dev);
+ return (dev);
}
static int io_range[3] = {0x10, 0x8 , 0x4 };
@@ -469,192 +478,192 @@
static int
alloc_resource(sc_p scp)
{
-int i, base, lid, flags;
-device_t dev;
+ int i, base, lid, flags;
+ device_t dev;
-flags = 0;
-if (isa_get_vendorid(scp->dev))
-lid = isa_get_logicalid(scp->dev);
-else {
-lid = LOGICALID_NOPNP;
-flags = device_get_flags(scp->dev);
-}
-switch(lid) {
-case LOGICALID_PCM:
-case LOGICALID_NOPNP: /* XXX Non-PnP */
-if (lid == LOGICALID_NOPNP)
-base = isa_get_port(scp->dev);
-else
-base = 0;
-for (i = 0 ; i < sizeof(scp->io) / sizeof(*scp->io) ; i++) {
-if (scp->io[i] == NULL) {
-scp->io_rid[i] = i;
-if (base == 0)
-scp->io[i] = bus_alloc_resource(scp->dev, SYS_RES_IOPORT, &scp->io_rid[i],
-0, ~0, io_range[i], RF_ACTIVE);
-else
-scp->io[i] = bus_alloc_resource(scp->dev, SYS_RES_IOPORT, &scp->io_rid[i],
-base + io_offset[i],
-base + io_offset[i] + io_range[i] - 1
-, io_range[i], RF_ACTIVE);
-if (scp->io[i] == NULL)
-return (1);
-scp->io_alloced[i] = 0;
-}
-}
-if (scp->irq == NULL) {
-scp->irq_rid = 0;
-scp->irq =
-bus_alloc_resource_any(scp->dev, SYS_RES_IRQ,
-&scp->irq_rid,
-RF_ACTIVE|RF_SHAREABLE);
-if (scp->irq == NULL)
-return (1);
-scp->irq_alloced = 0;
-}
-for (i = 0 ; i < sizeof(scp->drq) / sizeof(*scp->drq) ; i++) {
-if (scp->drq[i] == NULL) {
-scp->drq_rid[i] = i;
-if (base == 0 || i == 0)
-scp->drq[i] =
-bus_alloc_resource_any(
-scp->dev, SYS_RES_DRQ,
-&scp->drq_rid[i],
-RF_ACTIVE);
-else if ((flags & DV_F_DUAL_DMA) != 0)
-/* XXX The secondary drq is specified in the flag. */
-scp->drq[i] = bus_alloc_resource(scp->dev, SYS_RES_DRQ, &scp->drq_rid[i],
-flags & DV_F_DRQ_MASK,
-flags & DV_F_DRQ_MASK, 1, RF_ACTIVE);
-if (scp->drq[i] == NULL)
-return (1);
-scp->drq_alloced[i] = 0;
-}
-}
-break;
-case LOGICALID_OPL:
-if (scp->io[0] == NULL) {
-scp->io_rid[0] = 0;
-scp->io[0] = bus_alloc_resource(scp->dev, SYS_RES_IOPORT, &scp->io_rid[0],
-0, ~0, io_range[0], RF_ACTIVE);
-if (scp->io[0] == NULL)
-return (1);
-scp->io_alloced[0] = 0;
-}
-break;
-case LOGICALID_MIDI:
-if (scp->io[0] == NULL) {
-scp->io_rid[0] = 0;
-scp->io[0] = bus_alloc_resource(scp->dev, SYS_RES_IOPORT, &scp->io_rid[0],
-0, ~0, io_range[0], RF_ACTIVE);
-if (scp->io[0] == NULL)
-return (1);
-scp->io_alloced[0] = 0;
-}
-if (scp->irq == NULL) {
-/* The irq is shared with pcm audio. */
-dev = find_masterdev(scp);
-if (dev == NULL)
-return (1);
-scp->irq_rid = 0;
-scp->irq = BUS_ALLOC_RESOURCE(dev, NULL, SYS_RES_IRQ, &scp->irq_rid,
-0, ~0, 1, RF_ACTIVE | RF_SHAREABLE);
-if (scp->irq == NULL)
-return (1);
-scp->irq_alloced = 0;
-}
-break;
-}
-return (0);
+ flags = 0;
+ if (isa_get_vendorid(scp->dev))
+ lid = isa_get_logicalid(scp->dev);
+ else {
+ lid = LOGICALID_NOPNP;
+ flags = device_get_flags(scp->dev);
+ }
+ switch(lid) {
+ case LOGICALID_PCM:
+ case LOGICALID_NOPNP: /* XXX Non-PnP */
+ if (lid == LOGICALID_NOPNP)
+ base = isa_get_port(scp->dev);
+ else
+ base = 0;
+ for (i = 0 ; i < sizeof(scp->io) / sizeof(*scp->io) ; i++) {
+ if (scp->io[i] == NULL) {
+ scp->io_rid[i] = i;
+ if (base == 0)
+ scp->io[i] = bus_alloc_resource(scp->dev, SYS_RES_IOPORT, &scp->io_rid[i],
+ 0, ~0, io_range[i], RF_ACTIVE);
+ else
+ scp->io[i] = bus_alloc_resource(scp->dev, SYS_RES_IOPORT, &scp->io_rid[i],
+ base + io_offset[i],
+ base + io_offset[i] + io_range[i] - 1
+ , io_range[i], RF_ACTIVE);
+ if (scp->io[i] == NULL)
+ return (1);
+ scp->io_alloced[i] = 0;
+ }
+ }
+ if (scp->irq == NULL) {
+ scp->irq_rid = 0;
+ scp->irq =
+ bus_alloc_resource_any(scp->dev, SYS_RES_IRQ,
+ &scp->irq_rid,
+ RF_ACTIVE|RF_SHAREABLE);
+ if (scp->irq == NULL)
+ return (1);
+ scp->irq_alloced = 0;
+ }
+ for (i = 0 ; i < sizeof(scp->drq) / sizeof(*scp->drq) ; i++) {
+ if (scp->drq[i] == NULL) {
+ scp->drq_rid[i] = i;
+ if (base == 0 || i == 0)
+ scp->drq[i] =
+ bus_alloc_resource_any(
+ scp->dev, SYS_RES_DRQ,
+ &scp->drq_rid[i],
+ RF_ACTIVE);
+ else if ((flags & DV_F_DUAL_DMA) != 0)
+ /* XXX The secondary drq is specified in the flag. */
+ scp->drq[i] = bus_alloc_resource(scp->dev, SYS_RES_DRQ, &scp->drq_rid[i],
+ flags & DV_F_DRQ_MASK,
+ flags & DV_F_DRQ_MASK, 1, RF_ACTIVE);
+ if (scp->drq[i] == NULL)
+ return (1);
+ scp->drq_alloced[i] = 0;
+ }
+ }
+ break;
+ case LOGICALID_OPL:
+ if (scp->io[0] == NULL) {
+ scp->io_rid[0] = 0;
+ scp->io[0] = bus_alloc_resource(scp->dev, SYS_RES_IOPORT, &scp->io_rid[0],
+ 0, ~0, io_range[0], RF_ACTIVE);
+ if (scp->io[0] == NULL)
+ return (1);
+ scp->io_alloced[0] = 0;
+ }
+ break;
+ case LOGICALID_MIDI:
+ if (scp->io[0] == NULL) {
+ scp->io_rid[0] = 0;
+ scp->io[0] = bus_alloc_resource(scp->dev, SYS_RES_IOPORT, &scp->io_rid[0],
+ 0, ~0, io_range[0], RF_ACTIVE);
+ if (scp->io[0] == NULL)
+ return (1);
+ scp->io_alloced[0] = 0;
+ }
+ if (scp->irq == NULL) {
+ /* The irq is shared with pcm audio. */
+ dev = find_masterdev(scp);
+ if (dev == NULL)
+ return (1);
+ scp->irq_rid = 0;
+ scp->irq = BUS_ALLOC_RESOURCE(dev, NULL, SYS_RES_IRQ, &scp->irq_rid,
+ 0, ~0, 1, RF_ACTIVE | RF_SHAREABLE);
+ if (scp->irq == NULL)
+ return (1);
+ scp->irq_alloced = 0;
+ }
+ break;
+ }
+ return (0);
}
static int
release_resource(sc_p scp)
{
-int i, lid, flags;
-device_t dev;
+ int i, lid, flags;
+ device_t dev;
-flags = 0;
-if (isa_get_vendorid(scp->dev))
-lid = isa_get_logicalid(scp->dev);
-else {
-lid = LOGICALID_NOPNP;
-flags = device_get_flags(scp->dev);
-}
-switch(lid) {
-case LOGICALID_PCM:
-case LOGICALID_NOPNP: /* XXX Non-PnP */
-for (i = 0 ; i < sizeof(scp->io) / sizeof(*scp->io) ; i++) {
-if (scp->io[i] != NULL) {
-bus_release_resource(scp->dev, SYS_RES_IOPORT, scp->io_rid[i], scp->io[i]);
-scp->io[i] = NULL;
-}
-}
-if (scp->irq != NULL) {
-bus_release_resource(scp->dev, SYS_RES_IRQ, scp->irq_rid, scp->irq);
-scp->irq = NULL;
-}
-for (i = 0 ; i < sizeof(scp->drq) / sizeof(*scp->drq) ; i++) {
-if (scp->drq[i] != NULL) {
-bus_release_resource(scp->dev, SYS_RES_DRQ, scp->drq_rid[i], scp->drq[i]);
-scp->drq[i] = NULL;
-}
-}
-break;
-case LOGICALID_OPL:
-if (scp->io[0] != NULL) {
-bus_release_resource(scp->dev, SYS_RES_IOPORT, scp->io_rid[0], scp->io[0]);
-scp->io[0] = NULL;
-}
-break;
-case LOGICALID_MIDI:
-if (scp->io[0] != NULL) {
-bus_release_resource(scp->dev, SYS_RES_IOPORT, scp->io_rid[0], scp->io[0]);
-scp->io[0] = NULL;
-}
-if (scp->irq != NULL) {
-/* The irq is shared with pcm audio. */
-dev = find_masterdev(scp);
-if (dev == NULL)
-return (1);
-BUS_RELEASE_RESOURCE(dev, NULL, SYS_RES_IOPORT, scp->irq_rid, scp->irq);
-scp->irq = NULL;
-}
-break;
-}
-return (0);
+ flags = 0;
+ if (isa_get_vendorid(scp->dev))
+ lid = isa_get_logicalid(scp->dev);
+ else {
+ lid = LOGICALID_NOPNP;
+ flags = device_get_flags(scp->dev);
+ }
+ switch(lid) {
+ case LOGICALID_PCM:
+ case LOGICALID_NOPNP: /* XXX Non-PnP */
+ for (i = 0 ; i < sizeof(scp->io) / sizeof(*scp->io) ; i++) {
+ if (scp->io[i] != NULL) {
+ bus_release_resource(scp->dev, SYS_RES_IOPORT, scp->io_rid[i], scp->io[i]);
+ scp->io[i] = NULL;
+ }
+ }
+ if (scp->irq != NULL) {
+ bus_release_resource(scp->dev, SYS_RES_IRQ, scp->irq_rid, scp->irq);
+ scp->irq = NULL;
+ }
+ for (i = 0 ; i < sizeof(scp->drq) / sizeof(*scp->drq) ; i++) {
+ if (scp->drq[i] != NULL) {
+ bus_release_resource(scp->dev, SYS_RES_DRQ, scp->drq_rid[i], scp->drq[i]);
+ scp->drq[i] = NULL;
+ }
+ }
+ break;
+ case LOGICALID_OPL:
+ if (scp->io[0] != NULL) {
+ bus_release_resource(scp->dev, SYS_RES_IOPORT, scp->io_rid[0], scp->io[0]);
+ scp->io[0] = NULL;
+ }
+ break;
+ case LOGICALID_MIDI:
+ if (scp->io[0] != NULL) {
+ bus_release_resource(scp->dev, SYS_RES_IOPORT, scp->io_rid[0], scp->io[0]);
+ scp->io[0] = NULL;
+ }
+ if (scp->irq != NULL) {
+ /* The irq is shared with pcm audio. */
+ dev = find_masterdev(scp);
+ if (dev == NULL)
+ return (1);
+ BUS_RELEASE_RESOURCE(dev, NULL, SYS_RES_IOPORT, scp->irq_rid, scp->irq);
+ scp->irq = NULL;
+ }
+ break;
+ }
+ return (0);
}
static device_method_t gusc_methods[] = {
-/* Device interface */
-DEVMETHOD(device_probe, gusc_probe),
-DEVMETHOD(device_attach, gusc_attach),
-DEVMETHOD(device_detach, bus_generic_detach),
-DEVMETHOD(device_shutdown, bus_generic_shutdown),
-DEVMETHOD(device_suspend, bus_generic_suspend),
-DEVMETHOD(device_resume, bus_generic_resume),
-
-/* Bus interface */
-DEVMETHOD(bus_print_child, bus_generic_print_child),
-DEVMETHOD(bus_alloc_resource, gusc_alloc_resource),
-DEVMETHOD(bus_release_resource, gusc_release_resource),
-DEVMETHOD(bus_activate_resource, bus_generic_activate_resource),
-DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource),
-DEVMETHOD(bus_setup_intr, gusc_setup_intr),
-DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr),
+ /* Device interface */
+ DEVMETHOD(device_probe, gusc_probe),
+ DEVMETHOD(device_attach, gusc_attach),
+ DEVMETHOD(device_detach, bus_generic_detach),
+ DEVMETHOD(device_shutdown, bus_generic_shutdown),
+ DEVMETHOD(device_suspend, bus_generic_suspend),
+ DEVMETHOD(device_resume, bus_generic_resume),
+
+ /* Bus interface */
+ DEVMETHOD(bus_print_child, bus_generic_print_child),
+ DEVMETHOD(bus_alloc_resource, gusc_alloc_resource),
+ DEVMETHOD(bus_release_resource, gusc_release_resource),
+ DEVMETHOD(bus_activate_resource, bus_generic_activate_resource),
+ DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource),
+ DEVMETHOD(bus_setup_intr, gusc_setup_intr),
+ DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr),
-{ 0, 0 }
+ { 0, 0 }
};
static driver_t gusc_driver = {
-"gusc",
-gusc_methods,
-sizeof(struct gusc_softc),
+ "gusc",
+ gusc_methods,
+ sizeof(struct gusc_softc),
};
/*
-* gusc can be attached to an isa bus.
-*/
+ * gusc can be attached to an isa bus.
+ */
DRIVER_MODULE(snd_gusc, isa, gusc_driver, gusc_devclass, 0, 0);
DRIVER_MODULE(snd_gusc, acpi, gusc_driver, gusc_devclass, 0, 0);
MODULE_DEPEND(snd_gusc, sound, SOUND_MINVER, SOUND_PREFVER, SOUND_MAXVER);
Index: ad1816.h
===================================================================
RCS file: /home/cvs/src/sys/dev/sound/isa/ad1816.h,v
retrieving revision 1.2
retrieving revision 1.3
diff -L sys/dev/sound/isa/ad1816.h -L sys/dev/sound/isa/ad1816.h -u -r1.2 -r1.3
--- sys/dev/sound/isa/ad1816.h
+++ sys/dev/sound/isa/ad1816.h
@@ -1,12 +1,35 @@
/*-
-* (C) 1997 Luigi Rizzo (luigi at iet.unipi.it)
-*
-* This file contains information and macro definitions for
-* the ad1816 chip
-*
-* $MidnightBSD$
-* $FreeBSD: src/sys/dev/sound/isa/ad1816.h,v 1.2 2005/01/06 01:43:17 imp Exp $
-*/
+ * Copyright (c) 1997 Luigi Rizzo
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD: src/sys/dev/sound/isa/ad1816.h,v 1.4 2007/02/02 13:44:09 joel Exp $
+ */
+
+/*
+ * This file contains information and macro definitions for
+ * the ad1816 chip
+ */
/* AD1816 register macros */
@@ -22,15 +45,15 @@
#endif
/* values for playback/capture config:
-bits: 0 enable/disable
-1 pio/dma
-2 stereo/mono
-3 companded/linearPCM
-4-5 format : 00 8bit linear (uncomp)
-00 8bit mulaw (comp)
-01 16bit le (uncomp)
-01 8bit alaw (comp)
-11 16bit be (uncomp)
+ bits: 0 enable/disable
+ 1 pio/dma
+ 2 stereo/mono
+ 3 companded/linearPCM
+ 4-5 format : 00 8bit linear (uncomp)
+ 00 8bit mulaw (comp)
+ 01 16bit le (uncomp)
+ 01 8bit alaw (comp)
+ 11 16bit be (uncomp)
*/
#define AD1816_PLAY 8 /* playback config */
@@ -63,7 +86,10 @@
#define AD1816_S16BE 0x30 /* 16 bit linear big endian */
#define AD1816_FORMASK 0x38 /* format mask */
-#define AD1816_REC_DEVICES (SOUND_MASK_LINE | SOUND_MASK_MIC | SOUND_MASK_CD)
+#define AD1816_REC_DEVICES \
+ (SOUND_MASK_LINE | SOUND_MASK_MIC | SOUND_MASK_CD)
-#define AD1816_MIXER_DEVICES (SOUND_MASK_VOLUME | SOUND_MASK_PCM | SOUND_MASK_SYNTH | SOUND_MASK_LINE | SOUND_MASK_MIC | SOUND_MASK_CD | SOUND_MASK_IGAIN)
+#define AD1816_MIXER_DEVICES \
+ (SOUND_MASK_VOLUME | SOUND_MASK_PCM | SOUND_MASK_SYNTH | \
+ SOUND_MASK_LINE | SOUND_MASK_MIC | SOUND_MASK_CD | SOUND_MASK_IGAIN)
Index: sbc.c
===================================================================
RCS file: /home/cvs/src/sys/dev/sound/isa/sbc.c,v
retrieving revision 1.2
retrieving revision 1.3
diff -L sys/dev/sound/isa/sbc.c -L sys/dev/sound/isa/sbc.c -u -r1.2 -r1.3
--- sys/dev/sound/isa/sbc.c
+++ sys/dev/sound/isa/sbc.c
@@ -1,28 +1,28 @@
/*-
-* Copyright (c) 1999 Seigo Tanimura
-* All rights reserved.
-*
-* Redistribution and use in source and binary forms, with or without
-* modification, are permitted provided that the following conditions
-* are met:
-* 1. Redistributions of source code must retain the above copyright
-* notice, this list of conditions and the following disclaimer.
-* 2. Redistributions in binary form must reproduce the above copyright
-* notice, this list of conditions and the following disclaimer in the
-* documentation and/or other materials provided with the distribution.
-*
-* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
-* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
-* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
-* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
-* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
-* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
-* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
-* SUCH DAMAGE.
-*/
+ * Copyright (c) 1999 Seigo Tanimura
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
#include <dev/sound/chip.h>
#include <dev/sound/pcm/sound.h>
@@ -30,7 +30,7 @@
#include <isa/isavar.h>
-SND_DECLARE_FILE("$MidnightBSD$");
+SND_DECLARE_FILE("$FreeBSD: src/sys/dev/sound/isa/sbc.c,v 1.48 2007/03/15 16:41:25 ariff Exp $");
#define IO_MAX 3
#define IRQ_MAX 1
@@ -40,35 +40,35 @@
struct sbc_softc;
struct sbc_ihl {
-driver_intr_t *intr[INTR_MAX];
-void *intr_arg[INTR_MAX];
-struct sbc_softc *parent;
+ driver_intr_t *intr[INTR_MAX];
+ void *intr_arg[INTR_MAX];
+ struct sbc_softc *parent;
};
/* Here is the parameter structure per a device. */
struct sbc_softc {
-device_t dev; /* device */
-device_t child_pcm, child_midi1, child_midi2;
+ device_t dev; /* device */
+ device_t child_pcm, child_midi1, child_midi2;
-int io_rid[IO_MAX]; /* io port rids */
-struct resource *io[IO_MAX]; /* io port resources */
-int io_alloced[IO_MAX]; /* io port alloc flag */
+ int io_rid[IO_MAX]; /* io port rids */
+ struct resource *io[IO_MAX]; /* io port resources */
+ int io_alloced[IO_MAX]; /* io port alloc flag */
-int irq_rid[IRQ_MAX]; /* irq rids */
-struct resource *irq[IRQ_MAX]; /* irq resources */
-int irq_alloced[IRQ_MAX]; /* irq alloc flag */
+ int irq_rid[IRQ_MAX]; /* irq rids */
+ struct resource *irq[IRQ_MAX]; /* irq resources */
+ int irq_alloced[IRQ_MAX]; /* irq alloc flag */
-int drq_rid[DRQ_MAX]; /* drq rids */
-struct resource *drq[DRQ_MAX]; /* drq resources */
-int drq_alloced[DRQ_MAX]; /* drq alloc flag */
+ int drq_rid[DRQ_MAX]; /* drq rids */
+ struct resource *drq[DRQ_MAX]; /* drq resources */
+ int drq_alloced[DRQ_MAX]; /* drq alloc flag */
-struct sbc_ihl ihl[IRQ_MAX];
+ struct sbc_ihl ihl[IRQ_MAX];
-void *ih[IRQ_MAX];
+ void *ih[IRQ_MAX];
-struct mtx *lock;
+ struct mtx *lock;
-u_int32_t bd_ver;
+ u_int32_t bd_ver;
};
static int sbc_probe(device_t dev);
@@ -76,14 +76,18 @@
static void sbc_intr(void *p);
static struct resource *sbc_alloc_resource(device_t bus, device_t child, int type, int *rid,
-u_long start, u_long end, u_long count, u_int flags);
+ u_long start, u_long end, u_long count, u_int flags);
static int sbc_release_resource(device_t bus, device_t child, int type, int rid,
-struct resource *r);
+ struct resource *r);
static int sbc_setup_intr(device_t dev, device_t child, struct resource *irq,
-int flags, driver_intr_t *intr, void *arg,
-void **cookiep);
+ int flags,
+#if __FreeBSD_version >= 700031
+ driver_filter_t *filter,
+#endif
+ driver_intr_t *intr,
+ void *arg, void **cookiep);
static int sbc_teardown_intr(device_t dev, device_t child, struct resource *irq,
-void *cookie);
+ void *cookie);
static int alloc_resource(struct sbc_softc *scp);
static int release_resource(struct sbc_softc *scp);
@@ -94,14 +98,14 @@
#ifdef PC98 /* I/O address table for PC98 */
static bus_addr_t pcm_iat[] = {
-0x000, 0x100, 0x200, 0x300, 0x400, 0x500, 0x600, 0x700,
-0x800, 0x900, 0xa00, 0xb00, 0xc00, 0xd00, 0xe00, 0xf00
+ 0x000, 0x100, 0x200, 0x300, 0x400, 0x500, 0x600, 0x700,
+ 0x800, 0x900, 0xa00, 0xb00, 0xc00, 0xd00, 0xe00, 0xf00
};
static bus_addr_t midi_iat[] = {
-0x000, 0x100
+ 0x000, 0x100
};
static bus_addr_t opl_iat[] = {
-0x000, 0x100, 0x200, 0x300
+ 0x000, 0x100, 0x200, 0x300
};
static bus_addr_t *sb_iat[] = { pcm_iat, midi_iat, opl_iat };
#endif
@@ -116,677 +120,687 @@
static void
sbc_lockinit(struct sbc_softc *scp)
{
-scp->lock = snd_mtxcreate(device_get_nameunit(scp->dev), "sound softc");
+ scp->lock = snd_mtxcreate(device_get_nameunit(scp->dev),
+ "snd_sbc softc");
}
static void
sbc_lockdestroy(struct sbc_softc *scp)
{
-snd_mtxfree(scp->lock);
+ snd_mtxfree(scp->lock);
}
void
sbc_lock(struct sbc_softc *scp)
{
-snd_mtxlock(scp->lock);
+ snd_mtxlock(scp->lock);
}
void
sbc_lockassert(struct sbc_softc *scp)
{
-snd_mtxassert(scp->lock);
+ snd_mtxassert(scp->lock);
}
void
sbc_unlock(struct sbc_softc *scp)
{
-snd_mtxunlock(scp->lock);
+ snd_mtxunlock(scp->lock);
}
static int
sb_rd(struct resource *io, int reg)
{
-return bus_space_read_1(rman_get_bustag(io),
-rman_get_bushandle(io),
-reg);
+ return bus_space_read_1(rman_get_bustag(io),
+ rman_get_bushandle(io),
+ reg);
}
static void
sb_wr(struct resource *io, int reg, u_int8_t val)
{
-bus_space_write_1(rman_get_bustag(io),
-rman_get_bushandle(io),
-reg, val);
+ bus_space_write_1(rman_get_bustag(io),
+ rman_get_bushandle(io),
+ reg, val);
}
static int
sb_dspready(struct resource *io)
{
-return ((sb_rd(io, SBDSP_STATUS) & 0x80) == 0);
+ return ((sb_rd(io, SBDSP_STATUS) & 0x80) == 0);
}
static int
sb_dspwr(struct resource *io, u_char val)
{
-int i;
+ int i;
-for (i = 0; i < 1000; i++) {
-if (sb_dspready(io)) {
-sb_wr(io, SBDSP_CMD, val);
-return 1;
-}
-if (i > 10) DELAY((i > 100)? 1000 : 10);
-}
-printf("sb_dspwr(0x%02x) timed out.n", val);
-return 0;
+ for (i = 0; i < 1000; i++) {
+ if (sb_dspready(io)) {
+ sb_wr(io, SBDSP_CMD, val);
+ return 1;
+ }
+ if (i > 10) DELAY((i > 100)? 1000 : 10);
+ }
+ printf("sb_dspwr(0x%02x) timed out.\n", val);
+ return 0;
}
static int
sb_cmd(struct resource *io, u_char val)
{
-return sb_dspwr(io, val);
+ return sb_dspwr(io, val);
}
static void
sb_setmixer(struct resource *io, u_int port, u_int value)
{
-u_long flags;
+ u_long flags;
-flags = spltty();
-sb_wr(io, SB_MIX_ADDR, (u_char) (port & 0xff)); /* Select register */
-DELAY(10);
-sb_wr(io, SB_MIX_DATA, (u_char) (value & 0xff));
-DELAY(10);
-splx(flags);
+ flags = spltty();
+ sb_wr(io, SB_MIX_ADDR, (u_char) (port & 0xff)); /* Select register */
+ DELAY(10);
+ sb_wr(io, SB_MIX_DATA, (u_char) (value & 0xff));
+ DELAY(10);
+ splx(flags);
}
static u_int
sb_get_byte(struct resource *io)
{
-int i;
+ int i;
-for (i = 1000; i > 0; i--) {
-if (sb_rd(io, DSP_DATA_AVAIL) & 0x80)
-return sb_rd(io, DSP_READ);
-else
-DELAY(20);
-}
-return 0xffff;
+ for (i = 1000; i > 0; i--) {
+ if (sb_rd(io, DSP_DATA_AVAIL) & 0x80)
+ return sb_rd(io, DSP_READ);
+ else
+ DELAY(20);
+ }
+ return 0xffff;
}
static int
sb_reset_dsp(struct resource *io)
{
-sb_wr(io, SBDSP_RST, 3);
-DELAY(100);
-sb_wr(io, SBDSP_RST, 0);
-return (sb_get_byte(io) == 0xAA)? 0 : ENXIO;
+ sb_wr(io, SBDSP_RST, 3);
+ DELAY(100);
+ sb_wr(io, SBDSP_RST, 0);
+ return (sb_get_byte(io) == 0xAA)? 0 : ENXIO;
}
static int
sb_identify_board(struct resource *io)
{
-int ver, essver, rev;
+ int ver, essver, rev;
-sb_cmd(io, DSP_CMD_GETVER); /* Get version */
-ver = (sb_get_byte(io) << 8) | sb_get_byte(io);
-if (ver < 0x100 || ver > 0x4ff) return 0;
-if (ver == 0x0301) {
-/* Try to detect ESS chips. */
-sb_cmd(io, DSP_CMD_GETID); /* Return ident. bytes. */
-essver = (sb_get_byte(io) << 8) | sb_get_byte(io);
-rev = essver & 0x000f;
-essver &= 0xfff0;
-if (essver == 0x4880) ver |= 0x1000;
-else if (essver == 0x6880) ver = 0x0500 | rev;
-}
-return ver;
+ sb_cmd(io, DSP_CMD_GETVER); /* Get version */
+ ver = (sb_get_byte(io) << 8) | sb_get_byte(io);
+ if (ver < 0x100 || ver > 0x4ff) return 0;
+ if (ver == 0x0301) {
+ /* Try to detect ESS chips. */
+ sb_cmd(io, DSP_CMD_GETID); /* Return ident. bytes. */
+ essver = (sb_get_byte(io) << 8) | sb_get_byte(io);
+ rev = essver & 0x000f;
+ essver &= 0xfff0;
+ if (essver == 0x4880) ver |= 0x1000;
+ else if (essver == 0x6880) ver = 0x0500 | rev;
+ }
+ return ver;
}
static struct isa_pnp_id sbc_ids[] = {
-{0x01008c0e, "Creative ViBRA16C"}, /* CTL0001 */
-{0x31008c0e, "Creative SB16/SB32"}, /* CTL0031 */
-{0x41008c0e, "Creative SB16/SB32"}, /* CTL0041 */
-{0x42008c0e, "Creative SB AWE64"}, /* CTL0042 */
-{0x43008c0e, "Creative ViBRA16X"}, /* CTL0043 */
-{0x44008c0e, "Creative SB AWE64 Gold"}, /* CTL0044 */
-{0x45008c0e, "Creative SB AWE64"}, /* CTL0045 */
-{0x46008c0e, "Creative SB AWE64"}, /* CTL0046 */
-
-{0x01000000, "Avance Logic ALS100+"}, /* @@@0001 - ViBRA16X clone */
-{0x01100000, "Avance Asound 110"}, /* @@@1001 */
-{0x01200000, "Avance Logic ALS120"}, /* @@@2001 - ViBRA16X clone */
-
-{0x81167316, "ESS ES1681"}, /* ESS1681 */
-{0x02017316, "ESS ES1688"}, /* ESS1688 */
-{0x68097316, "ESS ES1688"}, /* ESS1688 */
-{0x68187316, "ESS ES1868"}, /* ESS1868 */
-{0x03007316, "ESS ES1869"}, /* ESS1869 */
-{0x69187316, "ESS ES1869"}, /* ESS1869 */
-{0xabb0110e, "ESS ES1869 (Compaq OEM)"}, /* CPQb0ab */
-{0xacb0110e, "ESS ES1869 (Compaq OEM)"}, /* CPQb0ac */
-{0x78187316, "ESS ES1878"}, /* ESS1878 */
-{0x79187316, "ESS ES1879"}, /* ESS1879 */
-{0x88187316, "ESS ES1888"}, /* ESS1888 */
-{0x07017316, "ESS ES1888 (DEC OEM)"}, /* ESS0107 */
-{0x06017316, "ESS ES1888 (Dell OEM)"}, /* ESS0106 */
-{0}
+ {0x01008c0e, "Creative ViBRA16C"}, /* CTL0001 */
+ {0x31008c0e, "Creative SB16/SB32"}, /* CTL0031 */
+ {0x41008c0e, "Creative SB16/SB32"}, /* CTL0041 */
+ {0x42008c0e, "Creative SB AWE64"}, /* CTL0042 */
+ {0x43008c0e, "Creative ViBRA16X"}, /* CTL0043 */
+ {0x44008c0e, "Creative SB AWE64 Gold"}, /* CTL0044 */
+ {0x45008c0e, "Creative SB AWE64"}, /* CTL0045 */
+ {0x46008c0e, "Creative SB AWE64"}, /* CTL0046 */
+
+ {0x01000000, "Avance Logic ALS100+"}, /* @@@0001 - ViBRA16X clone */
+ {0x01100000, "Avance Asound 110"}, /* @@@1001 */
+ {0x01200000, "Avance Logic ALS120"}, /* @@@2001 - ViBRA16X clone */
+
+ {0x81167316, "ESS ES1681"}, /* ESS1681 */
+ {0x02017316, "ESS ES1688"}, /* ESS1688 */
+ {0x68097316, "ESS ES1688"}, /* ESS1688 */
+ {0x68187316, "ESS ES1868"}, /* ESS1868 */
+ {0x03007316, "ESS ES1869"}, /* ESS1869 */
+ {0x69187316, "ESS ES1869"}, /* ESS1869 */
+ {0xabb0110e, "ESS ES1869 (Compaq OEM)"}, /* CPQb0ab */
+ {0xacb0110e, "ESS ES1869 (Compaq OEM)"}, /* CPQb0ac */
+ {0x78187316, "ESS ES1878"}, /* ESS1878 */
+ {0x79187316, "ESS ES1879"}, /* ESS1879 */
+ {0x88187316, "ESS ES1888"}, /* ESS1888 */
+ {0x07017316, "ESS ES1888 (DEC OEM)"}, /* ESS0107 */
+ {0x06017316, "ESS ES1888 (Dell OEM)"}, /* ESS0106 */
+ {0}
};
static int
sbc_probe(device_t dev)
{
-char *s = NULL;
-u_int32_t lid, vid;
+ char *s = NULL;
+ u_int32_t lid, vid;
-lid = isa_get_logicalid(dev);
-vid = isa_get_vendorid(dev);
-if (lid) {
-if (lid == 0x01000000 && vid != 0x01009305) /* ALS0001 */
-return ENXIO;
-/* Check pnp ids */
-return ISA_PNP_PROBE(device_get_parent(dev), dev, sbc_ids);
-} else {
-int rid = 0, ver;
-struct resource *io;
+ lid = isa_get_logicalid(dev);
+ vid = isa_get_vendorid(dev);
+ if (lid) {
+ if (lid == 0x01000000 && vid != 0x01009305) /* ALS0001 */
+ return ENXIO;
+ /* Check pnp ids */
+ return ISA_PNP_PROBE(device_get_parent(dev), dev, sbc_ids);
+ } else {
+ int rid = 0, ver;
+ struct resource *io;
#ifdef PC98
-io = isa_alloc_resourcev(dev, SYS_RES_IOPORT, &rid,
-pcm_iat, 16, RF_ACTIVE);
+ io = isa_alloc_resourcev(dev, SYS_RES_IOPORT, &rid,
+ pcm_iat, 16, RF_ACTIVE);
#else
-io = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid,
-0, ~0, 16, RF_ACTIVE);
+ io = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid,
+ 0, ~0, 16, RF_ACTIVE);
#endif
-if (!io) goto bad;
+ if (!io) goto bad;
#ifdef PC98
-isa_load_resourcev(io, pcm_iat, 16);
+ isa_load_resourcev(io, pcm_iat, 16);
#endif
-if (sb_reset_dsp(io)) goto bad2;
-ver = sb_identify_board(io);
-if (ver == 0) goto bad2;
-switch ((ver & 0x00000f00) >> 8) {
-case 1:
-device_set_desc(dev, "SoundBlaster 1.0 (not supported)");
-s = NULL;
-break;
-
-case 2:
-s = "SoundBlaster 2.0";
-break;
-
-case 3:
-s = (ver & 0x0000f000)? "ESS 488" : "SoundBlaster Pro";
-break;
-
-case 4:
-s = "SoundBlaster 16";
-break;
-
-case 5:
-s = (ver & 0x00000008)? "ESS 688" : "ESS 1688";
-break;
-}
-if (s) device_set_desc(dev, s);
+ if (sb_reset_dsp(io)) goto bad2;
+ ver = sb_identify_board(io);
+ if (ver == 0) goto bad2;
+ switch ((ver & 0x00000f00) >> 8) {
+ case 1:
+ device_set_desc(dev, "SoundBlaster 1.0 (not supported)");
+ s = NULL;
+ break;
+
+ case 2:
+ s = "SoundBlaster 2.0";
+ break;
+
+ case 3:
+ s = (ver & 0x0000f000)? "ESS 488" : "SoundBlaster Pro";
+ break;
+
+ case 4:
+ s = "SoundBlaster 16";
+ break;
+
+ case 5:
+ s = (ver & 0x00000008)? "ESS 688" : "ESS 1688";
+ break;
+ }
+ if (s) device_set_desc(dev, s);
bad2: bus_release_resource(dev, SYS_RES_IOPORT, rid, io);
bad: return s? 0 : ENXIO;
-}
+ }
}
static int
sbc_attach(device_t dev)
{
-char *err = NULL;
-struct sbc_softc *scp;
-struct sndcard_func *func;
-u_int32_t logical_id = isa_get_logicalid(dev);
-int flags = device_get_flags(dev);
-int f, dh, dl, x, irq, i;
-
-if (!logical_id && (flags & DV_F_DUAL_DMA)) {
-bus_set_resource(dev, SYS_RES_DRQ, 1,
-flags & DV_F_DRQ_MASK, 1);
-}
-
-scp = device_get_softc(dev);
-bzero(scp, sizeof(*scp));
-scp->dev = dev;
-sbc_lockinit(scp);
-err = "alloc_resource";
-if (alloc_resource(scp)) goto bad;
-
-err = "sb_reset_dsp";
-if (sb_reset_dsp(scp->io[0])) goto bad;
-err = "sb_identify_board";
-scp->bd_ver = sb_identify_board(scp->io[0]) & 0x00000fff;
-if (scp->bd_ver == 0) goto bad;
-f = 0;
-if (logical_id == 0x01200000 && scp->bd_ver < 0x0400) scp->bd_ver = 0x0499;
-switch ((scp->bd_ver & 0x0f00) >> 8) {
-case 1: /* old sound blaster has nothing... */
-break;
-
-case 2:
-f |= BD_F_DUP_MIDI;
-if (scp->bd_ver > 0x200) f |= BD_F_MIX_CT1335;
-break;
-
-case 5:
-f |= BD_F_ESS;
-scp->bd_ver = 0x0301;
-case 3:
-f |= BD_F_DUP_MIDI | BD_F_MIX_CT1345;
-break;
-
-case 4:
-f |= BD_F_SB16 | BD_F_MIX_CT1745;
-if (scp->drq[0]) dl = rman_get_start(scp->drq[0]); else dl = -1;
-if (scp->drq[1]) dh = rman_get_start(scp->drq[1]); else dh = dl;
-if (!logical_id && (dh < dl)) {
-struct resource *r;
-r = scp->drq[0];
-scp->drq[0] = scp->drq[1];
-scp->drq[1] = r;
-dl = rman_get_start(scp->drq[0]);
-dh = rman_get_start(scp->drq[1]);
-}
-/* soft irq/dma configuration */
-x = -1;
-irq = rman_get_start(scp->irq[0]);
+ char *err = NULL;
+ struct sbc_softc *scp;
+ struct sndcard_func *func;
+ u_int32_t logical_id = isa_get_logicalid(dev);
+ int flags = device_get_flags(dev);
+ int f, dh, dl, x, irq, i;
+
+ if (!logical_id && (flags & DV_F_DUAL_DMA)) {
+ bus_set_resource(dev, SYS_RES_DRQ, 1,
+ flags & DV_F_DRQ_MASK, 1);
+ }
+
+ scp = device_get_softc(dev);
+ bzero(scp, sizeof(*scp));
+ scp->dev = dev;
+ sbc_lockinit(scp);
+ err = "alloc_resource";
+ if (alloc_resource(scp)) goto bad;
+
+ err = "sb_reset_dsp";
+ if (sb_reset_dsp(scp->io[0])) goto bad;
+ err = "sb_identify_board";
+ scp->bd_ver = sb_identify_board(scp->io[0]) & 0x00000fff;
+ if (scp->bd_ver == 0) goto bad;
+ f = 0;
+ if (logical_id == 0x01200000 && scp->bd_ver < 0x0400) scp->bd_ver = 0x0499;
+ switch ((scp->bd_ver & 0x0f00) >> 8) {
+ case 1: /* old sound blaster has nothing... */
+ break;
+
+ case 2:
+ f |= BD_F_DUP_MIDI;
+ if (scp->bd_ver > 0x200) f |= BD_F_MIX_CT1335;
+ break;
+
+ case 5:
+ f |= BD_F_ESS;
+ scp->bd_ver = 0x0301;
+ case 3:
+ f |= BD_F_DUP_MIDI | BD_F_MIX_CT1345;
+ break;
+
+ case 4:
+ f |= BD_F_SB16 | BD_F_MIX_CT1745;
+ if (scp->drq[0]) dl = rman_get_start(scp->drq[0]); else dl = -1;
+ if (scp->drq[1]) dh = rman_get_start(scp->drq[1]); else dh = dl;
+ if (!logical_id && (dh < dl)) {
+ struct resource *r;
+ r = scp->drq[0];
+ scp->drq[0] = scp->drq[1];
+ scp->drq[1] = r;
+ dl = rman_get_start(scp->drq[0]);
+ dh = rman_get_start(scp->drq[1]);
+ }
+ /* soft irq/dma configuration */
+ x = -1;
+ irq = rman_get_start(scp->irq[0]);
#ifdef PC98
-/* SB16 in PC98 use different IRQ table */
-if (irq == 3) x = 1;
-else if (irq == 5) x = 8;
-else if (irq == 10) x = 2;
-else if (irq == 12) x = 4;
-if (x == -1) {
-err = "bad irq (3/5/10/12 valid)";
-goto bad;
-}
-else sb_setmixer(scp->io[0], IRQ_NR, x);
-/* SB16 in PC98 use different dma setting */
-sb_setmixer(scp->io[0], DMA_NR, dh == 0 ? 1 : 2);
+ /* SB16 in PC98 use different IRQ table */
+ if (irq == 3) x = 1;
+ else if (irq == 5) x = 8;
+ else if (irq == 10) x = 2;
+ else if (irq == 12) x = 4;
+ if (x == -1) {
+ err = "bad irq (3/5/10/12 valid)";
+ goto bad;
+ }
+ else sb_setmixer(scp->io[0], IRQ_NR, x);
+ /* SB16 in PC98 use different dma setting */
+ sb_setmixer(scp->io[0], DMA_NR, dh == 0 ? 1 : 2);
#else
-if (irq == 5) x = 2;
-else if (irq == 7) x = 4;
-else if (irq == 9) x = 1;
-else if (irq == 10) x = 8;
-if (x == -1) {
-err = "bad irq (5/7/9/10 valid)";
-goto bad;
-}
-else sb_setmixer(scp->io[0], IRQ_NR, x);
-sb_setmixer(scp->io[0], DMA_NR, (1 << dh) | (1 << dl));
+ if (irq == 5) x = 2;
+ else if (irq == 7) x = 4;
+ else if (irq == 9) x = 1;
+ else if (irq == 10) x = 8;
+ if (x == -1) {
+ err = "bad irq (5/7/9/10 valid)";
+ goto bad;
+ }
+ else sb_setmixer(scp->io[0], IRQ_NR, x);
+ sb_setmixer(scp->io[0], DMA_NR, (1 << dh) | (1 << dl));
#endif
-if (bootverbose) {
-device_printf(dev, "setting card to irq %d, drq %d", irq, dl);
-if (dl != dh) printf(", %d", dh);
-printf("n");
-}
-break;
-}
-
-switch (logical_id) {
-case 0x43008c0e: /* CTL0043 */
-case 0x01200000:
-case 0x01000000:
-f |= BD_F_SB16X;
-break;
-}
-scp->bd_ver |= f << 16;
-
-err = "setup_intr";
-for (i = 0; i < IRQ_MAX; i++) {
-scp->ihl[i].parent = scp;
-if (snd_setup_intr(dev, scp->irq[i], 0, sbc_intr, &scp->ihl[i], &scp->ih[i]))
-goto bad;
-}
-
-/* PCM Audio */
-func = malloc(sizeof(struct sndcard_func), M_DEVBUF, M_NOWAIT | M_ZERO);
-if (func == NULL) goto bad;
-func->func = SCF_PCM;
-scp->child_pcm = device_add_child(dev, "pcm", -1);
-device_set_ivars(scp->child_pcm, func);
-
-/* Midi Interface */
-func = malloc(sizeof(struct sndcard_func), M_DEVBUF, M_NOWAIT | M_ZERO);
-if (func == NULL) goto bad;
-func->func = SCF_MIDI;
-scp->child_midi1 = device_add_child(dev, "midi", -1);
-device_set_ivars(scp->child_midi1, func);
-
-/* OPL FM Synthesizer */
-func = malloc(sizeof(struct sndcard_func), M_DEVBUF, M_NOWAIT | M_ZERO);
-if (func == NULL) goto bad;
-func->func = SCF_SYNTH;
-scp->child_midi2 = device_add_child(dev, "midi", -1);
-device_set_ivars(scp->child_midi2, func);
-
-/* probe/attach kids */
-bus_generic_attach(dev);
-
-return (0);
-
-bad: if (err) device_printf(dev, "%sn", err);
-release_resource(scp);
-return (ENXIO);
+ if (bootverbose) {
+ device_printf(dev, "setting card to irq %d, drq %d", irq, dl);
+ if (dl != dh) printf(", %d", dh);
+ printf("\n");
+ }
+ break;
+ }
+
+ switch (logical_id) {
+ case 0x43008c0e: /* CTL0043 */
+ case 0x01200000:
+ case 0x01000000:
+ f |= BD_F_SB16X;
+ break;
+ }
+ scp->bd_ver |= f << 16;
+
+ err = "setup_intr";
+ for (i = 0; i < IRQ_MAX; i++) {
+ scp->ihl[i].parent = scp;
+ if (snd_setup_intr(dev, scp->irq[i], 0, sbc_intr, &scp->ihl[i], &scp->ih[i]))
+ goto bad;
+ }
+
+ /* PCM Audio */
+ func = malloc(sizeof(struct sndcard_func), M_DEVBUF, M_NOWAIT | M_ZERO);
+ if (func == NULL) goto bad;
+ func->func = SCF_PCM;
+ scp->child_pcm = device_add_child(dev, "pcm", -1);
+ device_set_ivars(scp->child_pcm, func);
+
+ /* Midi Interface */
+ func = malloc(sizeof(struct sndcard_func), M_DEVBUF, M_NOWAIT | M_ZERO);
+ if (func == NULL) goto bad;
+ func->func = SCF_MIDI;
+ scp->child_midi1 = device_add_child(dev, "midi", -1);
+ device_set_ivars(scp->child_midi1, func);
+
+ /* OPL FM Synthesizer */
+ func = malloc(sizeof(struct sndcard_func), M_DEVBUF, M_NOWAIT | M_ZERO);
+ if (func == NULL) goto bad;
+ func->func = SCF_SYNTH;
+ scp->child_midi2 = device_add_child(dev, "midi", -1);
+ device_set_ivars(scp->child_midi2, func);
+
+ /* probe/attach kids */
+ bus_generic_attach(dev);
+
+ return (0);
+
+bad: if (err) device_printf(dev, "%s\n", err);
+ release_resource(scp);
+ return (ENXIO);
}
static int
sbc_detach(device_t dev)
{
-struct sbc_softc *scp = device_get_softc(dev);
+ struct sbc_softc *scp = device_get_softc(dev);
-sbc_lock(scp);
-device_delete_child(dev, scp->child_midi2);
-device_delete_child(dev, scp->child_midi1);
-device_delete_child(dev, scp->child_pcm);
-release_resource(scp);
-sbc_lockdestroy(scp);
-return bus_generic_detach(dev);
+ sbc_lock(scp);
+ device_delete_child(dev, scp->child_midi2);
+ device_delete_child(dev, scp->child_midi1);
+ device_delete_child(dev, scp->child_pcm);
+ release_resource(scp);
+ sbc_lockdestroy(scp);
+ return bus_generic_detach(dev);
}
static void
sbc_intr(void *p)
{
-struct sbc_ihl *ihl = p;
-int i;
+ struct sbc_ihl *ihl = p;
+ int i;
-/* sbc_lock(ihl->parent); */
-i = 0;
-while (i < INTR_MAX) {
-if (ihl->intr[i] != NULL) ihl->intr[i](ihl->intr_arg[i]);
-i++;
-}
-/* sbc_unlock(ihl->parent); */
+ /* sbc_lock(ihl->parent); */
+ i = 0;
+ while (i < INTR_MAX) {
+ if (ihl->intr[i] != NULL) ihl->intr[i](ihl->intr_arg[i]);
+ i++;
+ }
+ /* sbc_unlock(ihl->parent); */
}
static int
-sbc_setup_intr(device_t dev, device_t child, struct resource *irq,
-int flags, driver_intr_t *intr, void *arg,
-void **cookiep)
-{
-struct sbc_softc *scp = device_get_softc(dev);
-struct sbc_ihl *ihl = NULL;
-int i, ret;
-
-sbc_lock(scp);
-i = 0;
-while (i < IRQ_MAX) {
-if (irq == scp->irq[i]) ihl = &scp->ihl[i];
-i++;
-}
-ret = 0;
-if (ihl == NULL) ret = EINVAL;
-i = 0;
-while ((ret == 0) && (i < INTR_MAX)) {
-if (ihl->intr[i] == NULL) {
-ihl->intr[i] = intr;
-ihl->intr_arg[i] = arg;
-*cookiep = &ihl->intr[i];
-ret = -1;
-} else i++;
-}
-sbc_unlock(scp);
-return (ret > 0)? EINVAL : 0;
+sbc_setup_intr(device_t dev, device_t child, struct resource *irq, int flags,
+#if __FreeBSD_version >= 700031
+ driver_filter_t *filter,
+#endif
+ driver_intr_t *intr,
+ void *arg, void **cookiep)
+{
+ struct sbc_softc *scp = device_get_softc(dev);
+ struct sbc_ihl *ihl = NULL;
+ int i, ret;
+
+#if __FreeBSD_version >= 700031
+ if (filter != NULL) {
+ printf("sbc.c: we cannot use a filter here\n");
+ return (EINVAL);
+ }
+#endif
+ sbc_lock(scp);
+ i = 0;
+ while (i < IRQ_MAX) {
+ if (irq == scp->irq[i]) ihl = &scp->ihl[i];
+ i++;
+ }
+ ret = 0;
+ if (ihl == NULL) ret = EINVAL;
+ i = 0;
+ while ((ret == 0) && (i < INTR_MAX)) {
+ if (ihl->intr[i] == NULL) {
+ ihl->intr[i] = intr;
+ ihl->intr_arg[i] = arg;
+ *cookiep = &ihl->intr[i];
+ ret = -1;
+ } else i++;
+ }
+ sbc_unlock(scp);
+ return (ret > 0)? EINVAL : 0;
}
static int
sbc_teardown_intr(device_t dev, device_t child, struct resource *irq,
-void *cookie)
+ void *cookie)
{
-struct sbc_softc *scp = device_get_softc(dev);
-struct sbc_ihl *ihl = NULL;
-int i, ret;
-
-sbc_lock(scp);
-i = 0;
-while (i < IRQ_MAX) {
-if (irq == scp->irq[i]) ihl = &scp->ihl[i];
-i++;
-}
-ret = 0;
-if (ihl == NULL) ret = EINVAL;
-i = 0;
-while ((ret == 0) && (i < INTR_MAX)) {
-if (cookie == &ihl->intr[i]) {
-ihl->intr[i] = NULL;
-ihl->intr_arg[i] = NULL;
-return 0;
-} else i++;
-}
-sbc_unlock(scp);
-return (ret > 0)? EINVAL : 0;
+ struct sbc_softc *scp = device_get_softc(dev);
+ struct sbc_ihl *ihl = NULL;
+ int i, ret;
+
+ sbc_lock(scp);
+ i = 0;
+ while (i < IRQ_MAX) {
+ if (irq == scp->irq[i]) ihl = &scp->ihl[i];
+ i++;
+ }
+ ret = 0;
+ if (ihl == NULL) ret = EINVAL;
+ i = 0;
+ while ((ret == 0) && (i < INTR_MAX)) {
+ if (cookie == &ihl->intr[i]) {
+ ihl->intr[i] = NULL;
+ ihl->intr_arg[i] = NULL;
+ return 0;
+ } else i++;
+ }
+ sbc_unlock(scp);
+ return (ret > 0)? EINVAL : 0;
}
static struct resource *
sbc_alloc_resource(device_t bus, device_t child, int type, int *rid,
-u_long start, u_long end, u_long count, u_int flags)
+ u_long start, u_long end, u_long count, u_int flags)
{
-struct sbc_softc *scp;
-int *alloced, rid_max, alloced_max;
-struct resource **res;
+ struct sbc_softc *scp;
+ int *alloced, rid_max, alloced_max;
+ struct resource **res;
#ifdef PC98
-int i;
+ int i;
#endif
-scp = device_get_softc(bus);
-switch (type) {
-case SYS_RES_IOPORT:
-alloced = scp->io_alloced;
-res = scp->io;
+ scp = device_get_softc(bus);
+ switch (type) {
+ case SYS_RES_IOPORT:
+ alloced = scp->io_alloced;
+ res = scp->io;
#ifdef PC98
-rid_max = 0;
-for (i = 0; i < IO_MAX; i++)
-rid_max += io_range[i];
+ rid_max = 0;
+ for (i = 0; i < IO_MAX; i++)
+ rid_max += io_range[i];
#else
-rid_max = IO_MAX - 1;
+ rid_max = IO_MAX - 1;
#endif
-alloced_max = 1;
-break;
-case SYS_RES_DRQ:
-alloced = scp->drq_alloced;
-res = scp->drq;
-rid_max = DRQ_MAX - 1;
-alloced_max = 1;
-break;
-case SYS_RES_IRQ:
-alloced = scp->irq_alloced;
-res = scp->irq;
-rid_max = IRQ_MAX - 1;
-alloced_max = INTR_MAX; /* pcm and mpu may share the irq. */
-break;
-default:
-return (NULL);
-}
+ alloced_max = 1;
+ break;
+ case SYS_RES_DRQ:
+ alloced = scp->drq_alloced;
+ res = scp->drq;
+ rid_max = DRQ_MAX - 1;
+ alloced_max = 1;
+ break;
+ case SYS_RES_IRQ:
+ alloced = scp->irq_alloced;
+ res = scp->irq;
+ rid_max = IRQ_MAX - 1;
+ alloced_max = INTR_MAX; /* pcm and mpu may share the irq. */
+ break;
+ default:
+ return (NULL);
+ }
-if (*rid > rid_max || alloced[*rid] == alloced_max)
-return (NULL);
+ if (*rid > rid_max || alloced[*rid] == alloced_max)
+ return (NULL);
-alloced[*rid]++;
-return (res[*rid]);
+ alloced[*rid]++;
+ return (res[*rid]);
}
static int
sbc_release_resource(device_t bus, device_t child, int type, int rid,
-struct resource *r)
+ struct resource *r)
{
-struct sbc_softc *scp;
-int *alloced, rid_max;
+ struct sbc_softc *scp;
+ int *alloced, rid_max;
-scp = device_get_softc(bus);
-switch (type) {
-case SYS_RES_IOPORT:
-alloced = scp->io_alloced;
-rid_max = IO_MAX - 1;
-break;
-case SYS_RES_DRQ:
-alloced = scp->drq_alloced;
-rid_max = DRQ_MAX - 1;
-break;
-case SYS_RES_IRQ:
-alloced = scp->irq_alloced;
-rid_max = IRQ_MAX - 1;
-break;
-default:
-return (1);
-}
+ scp = device_get_softc(bus);
+ switch (type) {
+ case SYS_RES_IOPORT:
+ alloced = scp->io_alloced;
+ rid_max = IO_MAX - 1;
+ break;
+ case SYS_RES_DRQ:
+ alloced = scp->drq_alloced;
+ rid_max = DRQ_MAX - 1;
+ break;
+ case SYS_RES_IRQ:
+ alloced = scp->irq_alloced;
+ rid_max = IRQ_MAX - 1;
+ break;
+ default:
+ return (1);
+ }
-if (rid > rid_max || alloced[rid] == 0)
-return (1);
+ if (rid > rid_max || alloced[rid] == 0)
+ return (1);
-alloced[rid]--;
-return (0);
+ alloced[rid]--;
+ return (0);
}
static int
sbc_read_ivar(device_t bus, device_t dev, int index, uintptr_t * result)
{
-struct sbc_softc *scp = device_get_softc(bus);
-struct sndcard_func *func = device_get_ivars(dev);
-
-switch (index) {
-case 0:
-*result = func->func;
-break;
+ struct sbc_softc *scp = device_get_softc(bus);
+ struct sndcard_func *func = device_get_ivars(dev);
-case 1:
-*result = scp->bd_ver;
-break;
-
-default:
-return ENOENT;
-}
+ switch (index) {
+ case 0:
+ *result = func->func;
+ break;
+
+ case 1:
+ *result = scp->bd_ver;
+ break;
+
+ default:
+ return ENOENT;
+ }
-return 0;
+ return 0;
}
static int
sbc_write_ivar(device_t bus, device_t dev,
-int index, uintptr_t value)
+ int index, uintptr_t value)
{
-switch (index) {
-case 0:
-case 1:
-return EINVAL;
-
-default:
-return (ENOENT);
-}
+ switch (index) {
+ case 0:
+ case 1:
+ return EINVAL;
+
+ default:
+ return (ENOENT);
+ }
}
static int
alloc_resource(struct sbc_softc *scp)
{
-int i;
+ int i;
-for (i = 0 ; i < IO_MAX ; i++) {
-if (scp->io[i] == NULL) {
+ for (i = 0 ; i < IO_MAX ; i++) {
+ if (scp->io[i] == NULL) {
#ifdef PC98
-scp->io_rid[i] = i > 0 ?
-scp->io_rid[i - 1] + io_range[i - 1] : 0;
-scp->io[i] = isa_alloc_resourcev(scp->dev,
-SYS_RES_IOPORT,
-&scp->io_rid[i],
-sb_iat[i],
-io_range[i],
-RF_ACTIVE);
-if (scp->io[i] != NULL)
-isa_load_resourcev(scp->io[i], sb_iat[i],
-io_range[i]);
+ scp->io_rid[i] = i > 0 ?
+ scp->io_rid[i - 1] + io_range[i - 1] : 0;
+ scp->io[i] = isa_alloc_resourcev(scp->dev,
+ SYS_RES_IOPORT,
+ &scp->io_rid[i],
+ sb_iat[i],
+ io_range[i],
+ RF_ACTIVE);
+ if (scp->io[i] != NULL)
+ isa_load_resourcev(scp->io[i], sb_iat[i],
+ io_range[i]);
#else
-scp->io_rid[i] = i;
-scp->io[i] = bus_alloc_resource(scp->dev, SYS_RES_IOPORT, &scp->io_rid[i],
-0, ~0, io_range[i], RF_ACTIVE);
+ scp->io_rid[i] = i;
+ scp->io[i] = bus_alloc_resource(scp->dev, SYS_RES_IOPORT, &scp->io_rid[i],
+ 0, ~0, io_range[i], RF_ACTIVE);
#endif
-if (i == 0 && scp->io[i] == NULL)
-return (1);
-scp->io_alloced[i] = 0;
-}
-}
-for (i = 0 ; i < DRQ_MAX ; i++) {
-if (scp->drq[i] == NULL) {
-scp->drq_rid[i] = i;
-scp->drq[i] = bus_alloc_resource_any(scp->dev,
-SYS_RES_DRQ,
-&scp->drq_rid[i],
-RF_ACTIVE);
-if (i == 0 && scp->drq[i] == NULL)
-return (1);
-scp->drq_alloced[i] = 0;
-}
-}
-for (i = 0 ; i < IRQ_MAX ; i++) {
-if (scp->irq[i] == NULL) {
-scp->irq_rid[i] = i;
-scp->irq[i] = bus_alloc_resource_any(scp->dev,
-SYS_RES_IRQ,
-&scp->irq_rid[i],
-RF_ACTIVE);
-if (i == 0 && scp->irq[i] == NULL)
-return (1);
-scp->irq_alloced[i] = 0;
-}
-}
-return (0);
+ if (i == 0 && scp->io[i] == NULL)
+ return (1);
+ scp->io_alloced[i] = 0;
+ }
+ }
+ for (i = 0 ; i < DRQ_MAX ; i++) {
+ if (scp->drq[i] == NULL) {
+ scp->drq_rid[i] = i;
+ scp->drq[i] = bus_alloc_resource_any(scp->dev,
+ SYS_RES_DRQ,
+ &scp->drq_rid[i],
+ RF_ACTIVE);
+ if (i == 0 && scp->drq[i] == NULL)
+ return (1);
+ scp->drq_alloced[i] = 0;
+ }
+ }
+ for (i = 0 ; i < IRQ_MAX ; i++) {
+ if (scp->irq[i] == NULL) {
+ scp->irq_rid[i] = i;
+ scp->irq[i] = bus_alloc_resource_any(scp->dev,
+ SYS_RES_IRQ,
+ &scp->irq_rid[i],
+ RF_ACTIVE);
+ if (i == 0 && scp->irq[i] == NULL)
+ return (1);
+ scp->irq_alloced[i] = 0;
+ }
+ }
+ return (0);
}
static int
release_resource(struct sbc_softc *scp)
{
-int i;
+ int i;
-for (i = 0 ; i < IO_MAX ; i++) {
-if (scp->io[i] != NULL) {
-bus_release_resource(scp->dev, SYS_RES_IOPORT, scp->io_rid[i], scp->io[i]);
-scp->io[i] = NULL;
-}
-}
-for (i = 0 ; i < DRQ_MAX ; i++) {
-if (scp->drq[i] != NULL) {
-bus_release_resource(scp->dev, SYS_RES_DRQ, scp->drq_rid[i], scp->drq[i]);
-scp->drq[i] = NULL;
-}
-}
-for (i = 0 ; i < IRQ_MAX ; i++) {
-if (scp->irq[i] != NULL) {
-if (scp->ih[i] != NULL)
-bus_teardown_intr(scp->dev, scp->irq[i], scp->ih[i]);
-scp->ih[i] = NULL;
-bus_release_resource(scp->dev, SYS_RES_IRQ, scp->irq_rid[i], scp->irq[i]);
-scp->irq[i] = NULL;
-}
-}
-return (0);
+ for (i = 0 ; i < IO_MAX ; i++) {
+ if (scp->io[i] != NULL) {
+ bus_release_resource(scp->dev, SYS_RES_IOPORT, scp->io_rid[i], scp->io[i]);
+ scp->io[i] = NULL;
+ }
+ }
+ for (i = 0 ; i < DRQ_MAX ; i++) {
+ if (scp->drq[i] != NULL) {
+ bus_release_resource(scp->dev, SYS_RES_DRQ, scp->drq_rid[i], scp->drq[i]);
+ scp->drq[i] = NULL;
+ }
+ }
+ for (i = 0 ; i < IRQ_MAX ; i++) {
+ if (scp->irq[i] != NULL) {
+ if (scp->ih[i] != NULL)
+ bus_teardown_intr(scp->dev, scp->irq[i], scp->ih[i]);
+ scp->ih[i] = NULL;
+ bus_release_resource(scp->dev, SYS_RES_IRQ, scp->irq_rid[i], scp->irq[i]);
+ scp->irq[i] = NULL;
+ }
+ }
+ return (0);
}
static device_method_t sbc_methods[] = {
-/* Device interface */
-DEVMETHOD(device_probe, sbc_probe),
-DEVMETHOD(device_attach, sbc_attach),
-DEVMETHOD(device_detach, sbc_detach),
-DEVMETHOD(device_shutdown, bus_generic_shutdown),
-DEVMETHOD(device_suspend, bus_generic_suspend),
-DEVMETHOD(device_resume, bus_generic_resume),
-
-/* Bus interface */
-DEVMETHOD(bus_read_ivar, sbc_read_ivar),
-DEVMETHOD(bus_write_ivar, sbc_write_ivar),
-DEVMETHOD(bus_print_child, bus_generic_print_child),
-DEVMETHOD(bus_alloc_resource, sbc_alloc_resource),
-DEVMETHOD(bus_release_resource, sbc_release_resource),
-DEVMETHOD(bus_activate_resource, bus_generic_activate_resource),
-DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource),
-DEVMETHOD(bus_setup_intr, sbc_setup_intr),
-DEVMETHOD(bus_teardown_intr, sbc_teardown_intr),
+ /* Device interface */
+ DEVMETHOD(device_probe, sbc_probe),
+ DEVMETHOD(device_attach, sbc_attach),
+ DEVMETHOD(device_detach, sbc_detach),
+ DEVMETHOD(device_shutdown, bus_generic_shutdown),
+ DEVMETHOD(device_suspend, bus_generic_suspend),
+ DEVMETHOD(device_resume, bus_generic_resume),
+
+ /* Bus interface */
+ DEVMETHOD(bus_read_ivar, sbc_read_ivar),
+ DEVMETHOD(bus_write_ivar, sbc_write_ivar),
+ DEVMETHOD(bus_print_child, bus_generic_print_child),
+ DEVMETHOD(bus_alloc_resource, sbc_alloc_resource),
+ DEVMETHOD(bus_release_resource, sbc_release_resource),
+ DEVMETHOD(bus_activate_resource, bus_generic_activate_resource),
+ DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource),
+ DEVMETHOD(bus_setup_intr, sbc_setup_intr),
+ DEVMETHOD(bus_teardown_intr, sbc_teardown_intr),
-{ 0, 0 }
+ { 0, 0 }
};
static driver_t sbc_driver = {
-"sbc",
-sbc_methods,
-sizeof(struct sbc_softc),
+ "sbc",
+ sbc_methods,
+ sizeof(struct sbc_softc),
};
/* sbc can be attached to an isa bus. */
Index: mss.h
===================================================================
RCS file: /home/cvs/src/sys/dev/sound/isa/mss.h,v
retrieving revision 1.2
retrieving revision 1.3
diff -L sys/dev/sound/isa/mss.h -L sys/dev/sound/isa/mss.h -u -r1.2 -r1.3
--- sys/dev/sound/isa/mss.h
+++ sys/dev/sound/isa/mss.h
@@ -1,44 +1,39 @@
/*-
-* file: mss.h
-*
-* (C) 1997 Luigi Rizzo (luigi at iet.unipi.it)
-*
-* This file contains information and macro definitions for
-* AD1848-compatible devices, used in the MSS/WSS compatible boards.
-*
-*/
-
-/*-
-* Copyright (c) 1999 Doug Rabson
-* All rights reserved.
-*
-* Redistribution and use in source and binary forms, with or without
-* modification, are permitted provided that the following conditions
-* are met:
-* 1. Redistributions of source code must retain the above copyright
-* notice, this list of conditions and the following disclaimer.
-* 2. Redistributions in binary form must reproduce the above copyright
-* notice, this list of conditions and the following disclaimer in the
-* documentation and/or other materials provided with the distribution.
-*
-* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
-* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
-* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
-* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
-* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
-* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
-* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
-* SUCH DAMAGE.
-*
-* $MidnightBSD$
-* $FreeBSD: src/sys/dev/sound/isa/mss.h,v 1.12 2005/01/06 01:43:17 imp Exp $
-*/
+ * Copyright (c) 1999 Doug Rabson
+ * Copyright (c) 1997 Luigi Rizzo
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD: src/sys/dev/sound/isa/mss.h,v 1.14 2007/02/02 13:44:09 joel Exp $
+ */
+
+/*
+ * This file contains information and macro definitions for
+ * AD1848-compatible devices, used in the MSS/WSS compatible boards.
+ */
/*
-*
+ *
The codec part of the board is seen as a set of 4 registers mapped
at the base address for the board (default 0x534). Note that some
@@ -49,54 +44,56 @@
configuration file and consider MSS registers start four location
ahead.
-*
-*/
+ *
+ */
struct mixer_def {
-u_int regno:7;
-u_int polarity:1; /* 1 means reversed */
-u_int bitoffs:4;
-u_int nbits:4;
+ u_int regno:7;
+ u_int polarity:1; /* 1 means reversed */
+ u_int bitoffs:4;
+ u_int nbits:4;
};
typedef struct mixer_def mixer_ent;
typedef struct mixer_def mixer_tab[32][2];
-#define MIX_ENT(name, reg_l, pol_l, pos_l, len_l, reg_r, pol_r, pos_r, len_r) {{reg_l, pol_l, pos_l, len_l}, {reg_r, pol_r, pos_r, len_r}}
+#define MIX_ENT(name, reg_l, pol_l, pos_l, len_l, reg_r, pol_r, pos_r, len_r) \
+ {{reg_l, pol_l, pos_l, len_l}, {reg_r, pol_r, pos_r, len_r}}
-#define PMIX_ENT(name, reg_l, pos_l, len_l, reg_r, pos_r, len_r) {{reg_l, 0, pos_l, len_l}, {reg_r, 0, pos_r, len_r}}
+#define PMIX_ENT(name, reg_l, pos_l, len_l, reg_r, pos_r, len_r) \
+ {{reg_l, 0, pos_l, len_l}, {reg_r, 0, pos_r, len_r}}
#define MIX_NONE(name) MIX_ENT(name, 0,0,0,0, 0,0,0,0)
/*
-* The four visible registers of the MSS :
-*
-*/
+ * The four visible registers of the MSS :
+ *
+ */
#define MSS_INDEX (0 + 4)
#define MSS_IDXBUSY 0x80 /* readonly, set when busy */
#define MSS_MCE 0x40 /* the MCE bit. */
-/*
-* the MCE bit must be set whenever the current mode of the
-* codec is changed; this in particular is true for the
-* Data Format (I8, I28) and Interface Config(I9) registers.
-* Only exception are CEN and PEN which can be changed on the fly.
-* The DAC output is muted when MCE is set.
-*/
+ /*
+ * the MCE bit must be set whenever the current mode of the
+ * codec is changed; this in particular is true for the
+ * Data Format (I8, I28) and Interface Config(I9) registers.
+ * Only exception are CEN and PEN which can be changed on the fly.
+ * The DAC output is muted when MCE is set.
+ */
#define MSS_TRD 0x20 /* Transfer request disable */
-/*
-* When TRD is set, DMA transfers cease when the INT bit in
-* the MSS status reg is set. Must be cleared for automode
-* DMA, set otherwise.
-*/
+ /*
+ * When TRD is set, DMA transfers cease when the INT bit in
+ * the MSS status reg is set. Must be cleared for automode
+ * DMA, set otherwise.
+ */
#define MSS_IDXMASK 0x1f /* mask for indirect address */
#define MSS_IDATA (1 + 4)
-/*
-* data to be transferred to the indirect register addressed
-* by index addr. During init and sw. powerdown, cannot be
-* written to, and is always read as 0x80 (consistent with the
-* busy flag).
-*/
+ /*
+ * data to be transferred to the indirect register addressed
+ * by index addr. During init and sw. powerdown, cannot be
+ * written to, and is always read as 0x80 (consistent with the
+ * busy flag).
+ */
#define MSS_STATUS (2 + 4)
@@ -108,44 +105,44 @@
#define IS_PLR 0x04 /* playback left/right */
#define IS_PRDY 0x02 /* playback ready for programmed i/o */
#define IS_INT 0x01 /* int status (1 = active) */
-/*
-* IS_INT is clreared by any write to the status register.
-*/
+ /*
+ * IS_INT is clreared by any write to the status register.
+ */
#if 0
#define io_Polled_IO(d) ((d)->io_base+3+4)
-/*
-* this register is used in case of polled i/o
-*/
+ /*
+ * this register is used in case of polled i/o
+ */
#endif
/*
-* The MSS has a set of 16 (or 32 depending on the model) indirect
-* registers accessible through the data port by specifying the
-* appropriate address in the address register.
-*
-* The 16 low registers are uniformly handled in AD1848/CS4248 compatible
-* mode (often called MODE1). For the upper 16 registers there are
-* some differences among different products, mainly Crystal uses them
-* differently from OPTi.
-*
-*/
+ * The MSS has a set of 16 (or 32 depending on the model) indirect
+ * registers accessible through the data port by specifying the
+ * appropriate address in the address register.
+ *
+ * The 16 low registers are uniformly handled in AD1848/CS4248 compatible
+ * mode (often called MODE1). For the upper 16 registers there are
+ * some differences among different products, mainly Crystal uses them
+ * differently from OPTi.
+ *
+ */
/*
-* volume registers
-*/
+ * volume registers
+ */
#define I6_MUTE 0x80
/*
-* register I9 -- interface configuration.
-*/
+ * register I9 -- interface configuration.
+ */
#define I9_PEN 0x01 /* playback enable */
#define I9_CEN 0x02 /* capture enable */
/*
-* values used in bd_flags
-*/
+ * values used in bd_flags
+ */
#define BD_F_MCE_BIT 0x0001
#define BD_F_IRQ_OK 0x0002
#define BD_F_TMR_RUN 0x0004
@@ -154,64 +151,65 @@
#define BD_F_924PNP 0x0020 /* OPTi924 is in PNP mode */
/*
-* sound/ad1848_mixer.h
-*
-* Definitions for the mixer of AD1848 and compatible codecs.
-*
-* Copyright by Hannu Savolainen 1994
-*
-* Redistribution and use in source and binary forms, with or without
-* modification, are permitted provided that the following conditions are
-* met: 1. Redistributions of source code must retain the above copyright
-* notice, this list of conditions and the following disclaimer. 2.
-* Redistributions in binary form must reproduce the above copyright notice,
-* this list of conditions and the following disclaimer in the documentation
-* and/or other materials provided with the distribution.
-*
-* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY
-* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-* DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
-* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
-* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
-* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
-* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
-* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
-* SUCH DAMAGE.
-*/
-/*
-* The AD1848 codec has generic input lines called Line, Aux1 and Aux2.
-* Soundcard manufacturers have connected actual inputs (CD, synth, line,
-* etc) to these inputs in different order. Therefore it's difficult
-* to assign mixer channels to to these inputs correctly. The following
-* contains two alternative mappings. The first one is for GUS MAX and
-* the second is just a generic one (line1, line2 and line3).
-* (Actually this is not a mapping but rather some kind of interleaving
-* solution).
-*/
-
-#define MSS_REC_DEVICES (SOUND_MASK_LINE | SOUND_MASK_MIC | SOUND_MASK_CD|SOUND_MASK_IMIX)
+ * sound/ad1848_mixer.h
+ *
+ * Definitions for the mixer of AD1848 and compatible codecs.
+ *
+ * Copyright by Hannu Savolainen 1994
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer. 2.
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+/*
+ * The AD1848 codec has generic input lines called Line, Aux1 and Aux2.
+ * Soundcard manufacturers have connected actual inputs (CD, synth, line,
+ * etc) to these inputs in different order. Therefore it's difficult
+ * to assign mixer channels to to these inputs correctly. The following
+ * contains two alternative mappings. The first one is for GUS MAX and
+ * the second is just a generic one (line1, line2 and line3).
+ * (Actually this is not a mapping but rather some kind of interleaving
+ * solution).
+ */
+
+#define MSS_REC_DEVICES \
+ (SOUND_MASK_LINE | SOUND_MASK_MIC | SOUND_MASK_CD|SOUND_MASK_IMIX)
/*
-* Table of mixer registers. There is a default table for the
-* AD1848/CS423x clones, one for the OPTI931 and one for the
-* OPTi930. As more MSS clones come out, there ought to be
-* more tables.
-*
-* Fields in the table are : polarity, register, offset, bits
-*
-* The channel numbering used by individual soundcards is not fixed.
-* Some cards have assigned different meanings for the AUX1, AUX2
-* and LINE inputs. Some have different features...
-*
-* Following there is a macro ...MIXER_DEVICES which is a bitmap
-* of all non-zero fields in the table.
-* MODE1_MIXER_DEVICES is the basic mixer of the 1848 in mode 1
-* registers I0..I15)
-*
-*/
+ * Table of mixer registers. There is a default table for the
+ * AD1848/CS423x clones, one for the OPTI931 and one for the
+ * OPTi930. As more MSS clones come out, there ought to be
+ * more tables.
+ *
+ * Fields in the table are : polarity, register, offset, bits
+ *
+ * The channel numbering used by individual soundcards is not fixed.
+ * Some cards have assigned different meanings for the AUX1, AUX2
+ * and LINE inputs. Some have different features...
+ *
+ * Following there is a macro ...MIXER_DEVICES which is a bitmap
+ * of all non-zero fields in the table.
+ * MODE1_MIXER_DEVICES is the basic mixer of the 1848 in mode 1
+ * registers I0..I15)
+ *
+ */
mixer_ent mix_devices[32][2] = {
MIX_NONE(SOUND_MIXER_VOLUME),
@@ -241,9 +239,14 @@
MIX_NONE(SOUND_MIXER_LINE3),
};
-#define MODE2_MIXER_DEVICES (SOUND_MASK_SYNTH | SOUND_MASK_PCM | SOUND_MASK_SPEAKER | SOUND_MASK_LINE | SOUND_MASK_MIC | SOUND_MASK_CD | SOUND_MASK_IMIX | SOUND_MASK_IGAIN )
-
-#define MODE1_MIXER_DEVICES (SOUND_MASK_SYNTH | SOUND_MASK_PCM | SOUND_MASK_MIC | SOUND_MASK_CD | SOUND_MASK_IMIX | SOUND_MASK_IGAIN )
+#define MODE2_MIXER_DEVICES \
+ (SOUND_MASK_SYNTH | SOUND_MASK_PCM | SOUND_MASK_SPEAKER | \
+ SOUND_MASK_LINE | SOUND_MASK_MIC | SOUND_MASK_CD | \
+ SOUND_MASK_IMIX | SOUND_MASK_IGAIN )
+
+#define MODE1_MIXER_DEVICES \
+ (SOUND_MASK_SYNTH | SOUND_MASK_PCM | SOUND_MASK_MIC | \
+ SOUND_MASK_CD | SOUND_MASK_IMIX | SOUND_MASK_IGAIN )
mixer_ent opti930_devices[32][2] = {
@@ -266,11 +269,13 @@
MIX_NONE(SOUND_MIXER_LINE3),
};
-#define OPTI930_MIXER_DEVICES (SOUND_MASK_VOLUME | SOUND_MASK_SYNTH | SOUND_MASK_PCM | SOUND_MASK_LINE | SOUND_MASK_MIC | SOUND_MASK_CD )
+#define OPTI930_MIXER_DEVICES \
+ (SOUND_MASK_VOLUME | SOUND_MASK_SYNTH | SOUND_MASK_PCM | \
+ SOUND_MASK_LINE | SOUND_MASK_MIC | SOUND_MASK_CD )
/*
-* entries for the opti931...
-*/
+ * entries for the opti931...
+ */
mixer_ent opti931_devices[32][2] = { /* for the opti931 */
MIX_ENT(SOUND_MIXER_VOLUME, 22, 1, 1, 5, 23, 1, 1, 5),
@@ -292,11 +297,14 @@
MIX_NONE(SOUND_MIXER_LINE3),
};
-#define OPTI931_MIXER_DEVICES (SOUND_MASK_VOLUME | SOUND_MASK_SYNTH | SOUND_MASK_PCM | SOUND_MASK_LINE | SOUND_MASK_MIC | SOUND_MASK_CD | SOUND_MASK_IGAIN | SOUND_MASK_LINE1 )
+#define OPTI931_MIXER_DEVICES \
+ (SOUND_MASK_VOLUME | SOUND_MASK_SYNTH | SOUND_MASK_PCM | \
+ SOUND_MASK_LINE | SOUND_MASK_MIC | SOUND_MASK_CD | \
+ SOUND_MASK_IGAIN | SOUND_MASK_LINE1 )
/*
-* Register definitions for the Yamaha OPL3-SA[23x].
-*/
+ * Register definitions for the Yamaha OPL3-SA[23x].
+ */
#define OPL3SAx_POWER 0x01 /* Power Management (R/W) */
#define OPL3SAx_POWER_PDX 0x01 /* Set to 1 to halt oscillator */
#define OPL3SAx_POWER_PDN 0x02 /* Set to 1 to power down */
Index: sb8.c
===================================================================
RCS file: /home/cvs/src/sys/dev/sound/isa/sb8.c,v
retrieving revision 1.2
retrieving revision 1.3
diff -L sys/dev/sound/isa/sb8.c -L sys/dev/sound/isa/sb8.c -u -r1.2 -r1.3
--- sys/dev/sound/isa/sb8.c
+++ sys/dev/sound/isa/sb8.c
@@ -1,33 +1,33 @@
/*-
-* Copyright (c) 1999 Cameron Grant <cg at freebsd.org>
-* Copyright 1997,1998 Luigi Rizzo.
-*
-* Derived from files in the Voxware 3.5 distribution,
-* Copyright by Hannu Savolainen 1994, under the same copyright
-* conditions.
-* All rights reserved.
-*
-* Redistribution and use in source and binary forms, with or without
-* modification, are permitted provided that the following conditions
-* are met:
-* 1. Redistributions of source code must retain the above copyright
-* notice, this list of conditions and the following disclaimer.
-* 2. Redistributions in binary form must reproduce the above copyright
-* notice, this list of conditions and the following disclaimer in the
-* documentation and/or other materials provided with the distribution.
-*
-* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
-* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
-* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
-* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
-* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
-* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
-* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
-* SUCH DAMAGE.
-*/
+ * Copyright (c) 1999 Cameron Grant <cg at freebsd.org>
+ * Copyright (c) 1997,1998 Luigi Rizzo
+ *
+ * Derived from files in the Voxware 3.5 distribution,
+ * Copyright by Hannu Savolainen 1994, under the same copyright
+ * conditions.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
#include <dev/sound/pcm/sound.h>
@@ -38,13 +38,13 @@
#include "mixer_if.h"
-SND_DECLARE_FILE("$MidnightBSD$");
+SND_DECLARE_FILE("$FreeBSD: src/sys/dev/sound/isa/sb8.c,v 1.86 2007/06/17 06:10:41 ariff Exp $");
#define SB_DEFAULT_BUFSZ 4096
static u_int32_t sb_fmt[] = {
-AFMT_U8,
-0
+ AFMT_U8,
+ 0
};
static struct pcmchan_caps sb200_playcaps = {4000, 23000, sb_fmt, 0};
static struct pcmchan_caps sb200_reccaps = {4000, 13000, sb_fmt, 0};
@@ -52,9 +52,9 @@
static struct pcmchan_caps sb201_reccaps = {4000, 15000, sb_fmt, 0};
static u_int32_t sbpro_fmt[] = {
-AFMT_U8,
-AFMT_STEREO | AFMT_U8,
-0
+ AFMT_U8,
+ AFMT_STEREO | AFMT_U8,
+ 0
};
static struct pcmchan_caps sbpro_playcaps = {4000, 44100, sbpro_fmt, 0};
static struct pcmchan_caps sbpro_reccaps = {4000, 44100, sbpro_fmt, 0};
@@ -62,25 +62,25 @@
struct sb_info;
struct sb_chinfo {
-struct sb_info *parent;
-struct pcm_channel *channel;
-struct snd_dbuf *buffer;
-int dir;
-u_int32_t fmt, spd, blksz;
+ struct sb_info *parent;
+ struct pcm_channel *channel;
+ struct snd_dbuf *buffer;
+ int dir;
+ u_int32_t fmt, spd, blksz;
};
struct sb_info {
-device_t parent_dev;
-struct resource *io_base; /* I/O address for the board */
-struct resource *irq;
-struct resource *drq;
-void *ih;
-bus_dma_tag_t parent_dmat;
-
-unsigned int bufsize;
-int bd_id;
-u_long bd_flags; /* board-specific flags */
-struct sb_chinfo pch, rch;
+ device_t parent_dev;
+ struct resource *io_base; /* I/O address for the board */
+ struct resource *irq;
+ struct resource *drq;
+ void *ih;
+ bus_dma_tag_t parent_dmat;
+
+ unsigned int bufsize;
+ int bd_id;
+ u_long bd_flags; /* board-specific flags */
+ struct sb_chinfo pch, rch;
};
static int sb_rd(struct sb_info *sb, int reg);
@@ -100,209 +100,209 @@
static int sb_stop(struct sb_chinfo *ch);
/*
-* Common code for the midi and pcm functions
-*
-* sb_cmd write a single byte to the CMD port.
-* sb_cmd1 write a CMD + 1 byte arg
-* sb_cmd2 write a CMD + 2 byte arg
-* sb_get_byte returns a single byte from the DSP data port
-*/
+ * Common code for the midi and pcm functions
+ *
+ * sb_cmd write a single byte to the CMD port.
+ * sb_cmd1 write a CMD + 1 byte arg
+ * sb_cmd2 write a CMD + 2 byte arg
+ * sb_get_byte returns a single byte from the DSP data port
+ */
static void
sb_lock(struct sb_info *sb) {
-sbc_lock(device_get_softc(sb->parent_dev));
+ sbc_lock(device_get_softc(sb->parent_dev));
}
static void
sb_unlock(struct sb_info *sb) {
-sbc_unlock(device_get_softc(sb->parent_dev));
+ sbc_unlock(device_get_softc(sb->parent_dev));
}
static int
port_rd(struct resource *port, int off)
{
-return bus_space_read_1(rman_get_bustag(port), rman_get_bushandle(port), off);
+ return bus_space_read_1(rman_get_bustag(port), rman_get_bushandle(port), off);
}
static void
port_wr(struct resource *port, int off, u_int8_t data)
{
-bus_space_write_1(rman_get_bustag(port), rman_get_bushandle(port), off, data);
+ bus_space_write_1(rman_get_bustag(port), rman_get_bushandle(port), off, data);
}
static int
sb_rd(struct sb_info *sb, int reg)
{
-return port_rd(sb->io_base, reg);
+ return port_rd(sb->io_base, reg);
}
static void
sb_wr(struct sb_info *sb, int reg, u_int8_t val)
{
-port_wr(sb->io_base, reg, val);
+ port_wr(sb->io_base, reg, val);
}
static int
sb_dspready(struct sb_info *sb)
{
-return ((sb_rd(sb, SBDSP_STATUS) & 0x80) == 0);
+ return ((sb_rd(sb, SBDSP_STATUS) & 0x80) == 0);
}
static int
sb_dspwr(struct sb_info *sb, u_char val)
{
-int i;
+ int i;
-for (i = 0; i < 1000; i++) {
-if (sb_dspready(sb)) {
-sb_wr(sb, SBDSP_CMD, val);
-return 1;
-}
-if (i > 10) DELAY((i > 100)? 1000 : 10);
-}
-printf("sb_dspwr(0x%02x) timed out.n", val);
-return 0;
+ for (i = 0; i < 1000; i++) {
+ if (sb_dspready(sb)) {
+ sb_wr(sb, SBDSP_CMD, val);
+ return 1;
+ }
+ if (i > 10) DELAY((i > 100)? 1000 : 10);
+ }
+ printf("sb_dspwr(0x%02x) timed out.\n", val);
+ return 0;
}
static int
sb_cmd(struct sb_info *sb, u_char val)
{
#if 0
-printf("sb_cmd: %xn", val);
+ printf("sb_cmd: %x\n", val);
#endif
-return sb_dspwr(sb, val);
+ return sb_dspwr(sb, val);
}
static int
sb_cmd1(struct sb_info *sb, u_char cmd, int val)
{
#if 0
-printf("sb_cmd1: %x, %xn", cmd, val);
+ printf("sb_cmd1: %x, %x\n", cmd, val);
#endif
-if (sb_dspwr(sb, cmd)) {
-return sb_dspwr(sb, val & 0xff);
-} else return 0;
+ if (sb_dspwr(sb, cmd)) {
+ return sb_dspwr(sb, val & 0xff);
+ } else return 0;
}
static int
sb_cmd2(struct sb_info *sb, u_char cmd, int val)
{
#if 0
-printf("sb_cmd2: %x, %xn", cmd, val);
+ printf("sb_cmd2: %x, %x\n", cmd, val);
#endif
-if (sb_dspwr(sb, cmd)) {
-return sb_dspwr(sb, val & 0xff) &&
-sb_dspwr(sb, (val >> 8) & 0xff);
-} else return 0;
+ if (sb_dspwr(sb, cmd)) {
+ return sb_dspwr(sb, val & 0xff) &&
+ sb_dspwr(sb, (val >> 8) & 0xff);
+ } else return 0;
}
/*
-* in the SB, there is a set of indirect "mixer" registers with
-* address at offset 4, data at offset 5
-*
-* we don't need to interlock these, the mixer lock will suffice.
-*/
+ * in the SB, there is a set of indirect "mixer" registers with
+ * address at offset 4, data at offset 5
+ *
+ * we don't need to interlock these, the mixer lock will suffice.
+ */
static void
sb_setmixer(struct sb_info *sb, u_int port, u_int value)
{
-sb_wr(sb, SB_MIX_ADDR, (u_char) (port & 0xff)); /* Select register */
-DELAY(10);
-sb_wr(sb, SB_MIX_DATA, (u_char) (value & 0xff));
-DELAY(10);
+ sb_wr(sb, SB_MIX_ADDR, (u_char) (port & 0xff)); /* Select register */
+ DELAY(10);
+ sb_wr(sb, SB_MIX_DATA, (u_char) (value & 0xff));
+ DELAY(10);
}
static int
sb_getmixer(struct sb_info *sb, u_int port)
{
-int val;
+ int val;
-sb_wr(sb, SB_MIX_ADDR, (u_char) (port & 0xff)); /* Select register */
-DELAY(10);
-val = sb_rd(sb, SB_MIX_DATA);
-DELAY(10);
+ sb_wr(sb, SB_MIX_ADDR, (u_char) (port & 0xff)); /* Select register */
+ DELAY(10);
+ val = sb_rd(sb, SB_MIX_DATA);
+ DELAY(10);
-return val;
+ return val;
}
static u_int
sb_get_byte(struct sb_info *sb)
{
-int i;
+ int i;
-for (i = 1000; i > 0; i--) {
-if (sb_rd(sb, DSP_DATA_AVAIL) & 0x80)
-return sb_rd(sb, DSP_READ);
-else
-DELAY(20);
-}
-return 0xffff;
+ for (i = 1000; i > 0; i--) {
+ if (sb_rd(sb, DSP_DATA_AVAIL) & 0x80)
+ return sb_rd(sb, DSP_READ);
+ else
+ DELAY(20);
+ }
+ return 0xffff;
}
static int
sb_reset_dsp(struct sb_info *sb)
{
-sb_wr(sb, SBDSP_RST, 3);
-DELAY(100);
-sb_wr(sb, SBDSP_RST, 0);
-if (sb_get_byte(sb) != 0xAA) {
-DEB(printf("sb_reset_dsp 0x%lx failedn",
-rman_get_start(sb->io_base)));
-return ENXIO; /* Sorry */
-}
-return 0;
+ sb_wr(sb, SBDSP_RST, 3);
+ DELAY(100);
+ sb_wr(sb, SBDSP_RST, 0);
+ if (sb_get_byte(sb) != 0xAA) {
+ DEB(printf("sb_reset_dsp 0x%lx failed\n",
+ rman_get_start(sb->io_base)));
+ return ENXIO; /* Sorry */
+ }
+ return 0;
}
static void
sb_release_resources(struct sb_info *sb, device_t dev)
{
-if (sb->irq) {
-if (sb->ih)
-bus_teardown_intr(dev, sb->irq, sb->ih);
-bus_release_resource(dev, SYS_RES_IRQ, 0, sb->irq);
-sb->irq = 0;
-}
-if (sb->drq) {
-isa_dma_release(rman_get_start(sb->drq));
-bus_release_resource(dev, SYS_RES_DRQ, 0, sb->drq);
-sb->drq = 0;
-}
-if (sb->io_base) {
-bus_release_resource(dev, SYS_RES_IOPORT, 0, sb->io_base);
-sb->io_base = 0;
-}
-if (sb->parent_dmat) {
-bus_dma_tag_destroy(sb->parent_dmat);
-sb->parent_dmat = 0;
-}
-free(sb, M_DEVBUF);
+ if (sb->irq) {
+ if (sb->ih)
+ bus_teardown_intr(dev, sb->irq, sb->ih);
+ bus_release_resource(dev, SYS_RES_IRQ, 0, sb->irq);
+ sb->irq = 0;
+ }
+ if (sb->drq) {
+ isa_dma_release(rman_get_start(sb->drq));
+ bus_release_resource(dev, SYS_RES_DRQ, 0, sb->drq);
+ sb->drq = 0;
+ }
+ if (sb->io_base) {
+ bus_release_resource(dev, SYS_RES_IOPORT, 0, sb->io_base);
+ sb->io_base = 0;
+ }
+ if (sb->parent_dmat) {
+ bus_dma_tag_destroy(sb->parent_dmat);
+ sb->parent_dmat = 0;
+ }
+ free(sb, M_DEVBUF);
}
static int
sb_alloc_resources(struct sb_info *sb, device_t dev)
{
-int rid;
+ int rid;
-rid = 0;
-if (!sb->io_base)
-sb->io_base = bus_alloc_resource_any(dev, SYS_RES_IOPORT,
-&rid, RF_ACTIVE);
-rid = 0;
-if (!sb->irq)
-sb->irq = bus_alloc_resource_any(dev, SYS_RES_IRQ,
-&rid, RF_ACTIVE);
-rid = 0;
-if (!sb->drq)
-sb->drq = bus_alloc_resource_any(dev, SYS_RES_DRQ,
-&rid, RF_ACTIVE);
-
-if (sb->io_base && sb->drq && sb->irq) {
-isa_dma_acquire(rman_get_start(sb->drq));
-isa_dmainit(rman_get_start(sb->drq), sb->bufsize);
+ rid = 0;
+ if (!sb->io_base)
+ sb->io_base = bus_alloc_resource_any(dev, SYS_RES_IOPORT,
+ &rid, RF_ACTIVE);
+ rid = 0;
+ if (!sb->irq)
+ sb->irq = bus_alloc_resource_any(dev, SYS_RES_IRQ,
+ &rid, RF_ACTIVE);
+ rid = 0;
+ if (!sb->drq)
+ sb->drq = bus_alloc_resource_any(dev, SYS_RES_DRQ,
+ &rid, RF_ACTIVE);
+
+ if (sb->io_base && sb->drq && sb->irq) {
+ isa_dma_acquire(rman_get_start(sb->drq));
+ isa_dmainit(rman_get_start(sb->drq), sb->bufsize);
-return 0;
-} else return ENXIO;
+ return 0;
+ } else return ENXIO;
}
/************************************************************/
@@ -310,92 +310,92 @@
static int
sbpromix_init(struct snd_mixer *m)
{
-struct sb_info *sb = mix_getdevinfo(m);
+ struct sb_info *sb = mix_getdevinfo(m);
-mix_setdevs(m, SOUND_MASK_SYNTH | SOUND_MASK_PCM | SOUND_MASK_LINE |
-SOUND_MASK_MIC | SOUND_MASK_CD | SOUND_MASK_VOLUME);
+ mix_setdevs(m, SOUND_MASK_SYNTH | SOUND_MASK_PCM | SOUND_MASK_LINE |
+ SOUND_MASK_MIC | SOUND_MASK_CD | SOUND_MASK_VOLUME);
-mix_setrecdevs(m, SOUND_MASK_LINE | SOUND_MASK_MIC | SOUND_MASK_CD);
+ mix_setrecdevs(m, SOUND_MASK_LINE | SOUND_MASK_MIC | SOUND_MASK_CD);
-sb_setmixer(sb, 0, 1); /* reset mixer */
+ sb_setmixer(sb, 0, 1); /* reset mixer */
-return 0;
+ return 0;
}
static int
sbpromix_set(struct snd_mixer *m, unsigned dev, unsigned left, unsigned right)
{
-struct sb_info *sb = mix_getdevinfo(m);
-int reg, max;
-u_char val;
-
-max = 7;
-switch (dev) {
-case SOUND_MIXER_PCM:
-reg = 0x04;
-break;
+ struct sb_info *sb = mix_getdevinfo(m);
+ int reg, max;
+ u_char val;
+
+ max = 7;
+ switch (dev) {
+ case SOUND_MIXER_PCM:
+ reg = 0x04;
+ break;
+
+ case SOUND_MIXER_MIC:
+ reg = 0x0a;
+ max = 3;
+ break;
+
+ case SOUND_MIXER_VOLUME:
+ reg = 0x22;
+ break;
+
+ case SOUND_MIXER_SYNTH:
+ reg = 0x26;
+ break;
+
+ case SOUND_MIXER_CD:
+ reg = 0x28;
+ break;
+
+ case SOUND_MIXER_LINE:
+ reg = 0x2e;
+ break;
+
+ default:
+ return -1;
+ }
+
+ left = (left * max) / 100;
+ right = (dev == SOUND_MIXER_MIC)? left : ((right * max) / 100);
-case SOUND_MIXER_MIC:
-reg = 0x0a;
-max = 3;
-break;
+ val = (dev == SOUND_MIXER_MIC)? (left << 1) : (left << 5 | right << 1);
+ sb_setmixer(sb, reg, val);
-case SOUND_MIXER_VOLUME:
-reg = 0x22;
-break;
+ left = (left * 100) / max;
+ right = (right * 100) / max;
-case SOUND_MIXER_SYNTH:
-reg = 0x26;
-break;
-
-case SOUND_MIXER_CD:
-reg = 0x28;
-break;
-
-case SOUND_MIXER_LINE:
-reg = 0x2e;
-break;
-
-default:
-return -1;
-}
-
-left = (left * max) / 100;
-right = (dev == SOUND_MIXER_MIC)? left : ((right * max) / 100);
-
-val = (dev == SOUND_MIXER_MIC)? (left << 1) : (left << 5 | right << 1);
-sb_setmixer(sb, reg, val);
-
-left = (left * 100) / max;
-right = (right * 100) / max;
-
-return left | (right << 8);
+ return left | (right << 8);
}
static int
sbpromix_setrecsrc(struct snd_mixer *m, u_int32_t src)
{
-struct sb_info *sb = mix_getdevinfo(m);
-u_char recdev;
+ struct sb_info *sb = mix_getdevinfo(m);
+ u_char recdev;
-if (src == SOUND_MASK_LINE)
-recdev = 0x06;
-else if (src == SOUND_MASK_CD)
-recdev = 0x02;
-else { /* default: mic */
-src = SOUND_MASK_MIC;
-recdev = 0;
-}
-sb_setmixer(sb, RECORD_SRC, recdev | (sb_getmixer(sb, RECORD_SRC) & ~0x07));
+ if (src == SOUND_MASK_LINE)
+ recdev = 0x06;
+ else if (src == SOUND_MASK_CD)
+ recdev = 0x02;
+ else { /* default: mic */
+ src = SOUND_MASK_MIC;
+ recdev = 0;
+ }
+ sb_setmixer(sb, RECORD_SRC, recdev | (sb_getmixer(sb, RECORD_SRC) & ~0x07));
-return src;
+ return src;
}
static kobj_method_t sbpromix_mixer_methods[] = {
-KOBJMETHOD(mixer_init, sbpromix_init),
-KOBJMETHOD(mixer_set, sbpromix_set),
-KOBJMETHOD(mixer_setrecsrc, sbpromix_setrecsrc),
-{ 0, 0 }
+ KOBJMETHOD(mixer_init, sbpromix_init),
+ KOBJMETHOD(mixer_set, sbpromix_set),
+ KOBJMETHOD(mixer_setrecsrc, sbpromix_setrecsrc),
+ { 0, 0 }
};
MIXER_DECLARE(sbpromix_mixer);
@@ -404,66 +404,66 @@
static int
sbmix_init(struct snd_mixer *m)
{
-struct sb_info *sb = mix_getdevinfo(m);
+ struct sb_info *sb = mix_getdevinfo(m);
-mix_setdevs(m, SOUND_MASK_SYNTH | SOUND_MASK_PCM | SOUND_MASK_CD | SOUND_MASK_VOLUME);
+ mix_setdevs(m, SOUND_MASK_SYNTH | SOUND_MASK_PCM | SOUND_MASK_CD | SOUND_MASK_VOLUME);
-mix_setrecdevs(m, 0);
+ mix_setrecdevs(m, 0);
-sb_setmixer(sb, 0, 1); /* reset mixer */
+ sb_setmixer(sb, 0, 1); /* reset mixer */
-return 0;
+ return 0;
}
static int
sbmix_set(struct snd_mixer *m, unsigned dev, unsigned left, unsigned right)
{
-struct sb_info *sb = mix_getdevinfo(m);
-int reg, max;
+ struct sb_info *sb = mix_getdevinfo(m);
+ int reg, max;
-max = 7;
-switch (dev) {
-case SOUND_MIXER_VOLUME:
-reg = 0x2;
-break;
+ max = 7;
+ switch (dev) {
+ case SOUND_MIXER_VOLUME:
+ reg = 0x2;
+ break;
-case SOUND_MIXER_SYNTH:
-reg = 0x6;
-break;
+ case SOUND_MIXER_SYNTH:
+ reg = 0x6;
+ break;
-case SOUND_MIXER_CD:
-reg = 0x8;
-break;
+ case SOUND_MIXER_CD:
+ reg = 0x8;
+ break;
-case SOUND_MIXER_PCM:
-reg = 0x0a;
-max = 3;
-break;
+ case SOUND_MIXER_PCM:
+ reg = 0x0a;
+ max = 3;
+ break;
-default:
-return -1;
-}
+ default:
+ return -1;
+ }
-left = (left * max) / 100;
+ left = (left * max) / 100;
-sb_setmixer(sb, reg, left << 1);
+ sb_setmixer(sb, reg, left << 1);
-left = (left * 100) / max;
+ left = (left * 100) / max;
-return left | (left << 8);
+ return left | (left << 8);
}
static int
sbmix_setrecsrc(struct snd_mixer *m, u_int32_t src)
{
-return 0;
+ return 0;
}
static kobj_method_t sbmix_mixer_methods[] = {
-KOBJMETHOD(mixer_init, sbmix_init),
-KOBJMETHOD(mixer_set, sbmix_set),
-KOBJMETHOD(mixer_setrecsrc, sbmix_setrecsrc),
-{ 0, 0 }
+ KOBJMETHOD(mixer_init, sbmix_init),
+ KOBJMETHOD(mixer_set, sbmix_set),
+ KOBJMETHOD(mixer_setrecsrc, sbmix_setrecsrc),
+ { 0, 0 }
};
MIXER_DECLARE(sbmix_mixer);
@@ -472,212 +472,212 @@
static void
sb_intr(void *arg)
{
-struct sb_info *sb = (struct sb_info *)arg;
+ struct sb_info *sb = (struct sb_info *)arg;
-sb_lock(sb);
-if (sndbuf_runsz(sb->pch.buffer) > 0) {
-sb_unlock(sb);
-chn_intr(sb->pch.channel);
-sb_lock(sb);
-}
-
-if (sndbuf_runsz(sb->rch.buffer) > 0) {
-sb_unlock(sb);
-chn_intr(sb->rch.channel);
-sb_lock(sb);
-}
+ sb_lock(sb);
+ if (sndbuf_runsz(sb->pch.buffer) > 0) {
+ sb_unlock(sb);
+ chn_intr(sb->pch.channel);
+ sb_lock(sb);
+ }
+
+ if (sndbuf_runsz(sb->rch.buffer) > 0) {
+ sb_unlock(sb);
+ chn_intr(sb->rch.channel);
+ sb_lock(sb);
+ }
-sb_rd(sb, DSP_DATA_AVAIL); /* int ack */
-sb_unlock(sb);
+ sb_rd(sb, DSP_DATA_AVAIL); /* int ack */
+ sb_unlock(sb);
}
static int
sb_speed(struct sb_chinfo *ch)
{
-struct sb_info *sb = ch->parent;
-int play = (ch->dir == PCMDIR_PLAY)? 1 : 0;
-int stereo = (ch->fmt & AFMT_STEREO)? 1 : 0;
-int speed, tmp, thresh, max;
-u_char tconst;
-
-if (sb->bd_id >= 0x300) {
-thresh = stereo? 11025 : 23000;
-max = stereo? 22050 : 44100;
-} else if (sb->bd_id > 0x200) {
-thresh = play? 23000 : 13000;
-max = play? 44100 : 15000;
-} else {
-thresh = 999999;
-max = play? 23000 : 13000;
-}
-
-speed = ch->spd;
-if (speed > max)
-speed = max;
-
-sb_lock(sb);
-sb->bd_flags &= ~BD_F_HISPEED;
-if (speed > thresh)
-sb->bd_flags |= BD_F_HISPEED;
-
-tmp = 65536 - (256000000 / (speed << stereo));
-tconst = tmp >> 8;
-
-sb_cmd1(sb, 0x40, tconst); /* set time constant */
-
-speed = (256000000 / (65536 - tmp)) >> stereo;
-
-ch->spd = speed;
-sb_unlock(sb);
-return speed;
+ struct sb_info *sb = ch->parent;
+ int play = (ch->dir == PCMDIR_PLAY)? 1 : 0;
+ int stereo = (ch->fmt & AFMT_STEREO)? 1 : 0;
+ int speed, tmp, thresh, max;
+ u_char tconst;
+
+ if (sb->bd_id >= 0x300) {
+ thresh = stereo? 11025 : 23000;
+ max = stereo? 22050 : 44100;
+ } else if (sb->bd_id > 0x200) {
+ thresh = play? 23000 : 13000;
+ max = play? 44100 : 15000;
+ } else {
+ thresh = 999999;
+ max = play? 23000 : 13000;
+ }
+
+ speed = ch->spd;
+ if (speed > max)
+ speed = max;
+
+ sb_lock(sb);
+ sb->bd_flags &= ~BD_F_HISPEED;
+ if (speed > thresh)
+ sb->bd_flags |= BD_F_HISPEED;
+
+ tmp = 65536 - (256000000 / (speed << stereo));
+ tconst = tmp >> 8;
+
+ sb_cmd1(sb, 0x40, tconst); /* set time constant */
+
+ speed = (256000000 / (65536 - tmp)) >> stereo;
+
+ ch->spd = speed;
+ sb_unlock(sb);
+ return speed;
}
static int
sb_start(struct sb_chinfo *ch)
{
-struct sb_info *sb = ch->parent;
-int play = (ch->dir == PCMDIR_PLAY)? 1 : 0;
-int stereo = (ch->fmt & AFMT_STEREO)? 1 : 0;
-int l = ch->blksz;
-u_char i;
-
-l--;
-
-sb_lock(sb);
-if (play)
-sb_cmd(sb, DSP_CMD_SPKON);
-
-if (sb->bd_flags & BD_F_HISPEED)
-i = play? 0x90 : 0x98;
-else
-i = play? 0x1c : 0x2c;
-
-sb_setmixer(sb, 0x0e, stereo? 2 : 0);
-sb_cmd2(sb, 0x48, l);
-sb_cmd(sb, i);
-
-sb->bd_flags |= BD_F_DMARUN;
-sb_unlock(sb);
-return 0;
+ struct sb_info *sb = ch->parent;
+ int play = (ch->dir == PCMDIR_PLAY)? 1 : 0;
+ int stereo = (ch->fmt & AFMT_STEREO)? 1 : 0;
+ int l = ch->blksz;
+ u_char i;
+
+ l--;
+
+ sb_lock(sb);
+ if (play)
+ sb_cmd(sb, DSP_CMD_SPKON);
+
+ if (sb->bd_flags & BD_F_HISPEED)
+ i = play? 0x90 : 0x98;
+ else
+ i = play? 0x1c : 0x2c;
+
+ sb_setmixer(sb, 0x0e, stereo? 2 : 0);
+ sb_cmd2(sb, 0x48, l);
+ sb_cmd(sb, i);
+
+ sb->bd_flags |= BD_F_DMARUN;
+ sb_unlock(sb);
+ return 0;
}
static int
sb_stop(struct sb_chinfo *ch)
{
-struct sb_info *sb = ch->parent;
-int play = (ch->dir == PCMDIR_PLAY)? 1 : 0;
+ struct sb_info *sb = ch->parent;
+ int play = (ch->dir == PCMDIR_PLAY)? 1 : 0;
-sb_lock(sb);
-if (sb->bd_flags & BD_F_HISPEED)
-sb_reset_dsp(sb);
-else {
+ sb_lock(sb);
+ if (sb->bd_flags & BD_F_HISPEED)
+ sb_reset_dsp(sb);
+ else {
#if 0
-/*
-* NOTE: DSP_CMD_DMAEXIT_8 does not work with old
-* soundblaster.
-*/
-sb_cmd(sb, DSP_CMD_DMAEXIT_8);
+ /*
+ * NOTE: DSP_CMD_DMAEXIT_8 does not work with old
+ * soundblaster.
+ */
+ sb_cmd(sb, DSP_CMD_DMAEXIT_8);
#endif
-sb_reset_dsp(sb);
-}
+ sb_reset_dsp(sb);
+ }
-if (play)
-sb_cmd(sb, DSP_CMD_SPKOFF); /* speaker off */
-sb_unlock(sb);
-sb->bd_flags &= ~BD_F_DMARUN;
-return 0;
+ if (play)
+ sb_cmd(sb, DSP_CMD_SPKOFF); /* speaker off */
+ sb_unlock(sb);
+ sb->bd_flags &= ~BD_F_DMARUN;
+ return 0;
}
/* channel interface */
static void *
sbchan_init(kobj_t obj, void *devinfo, struct snd_dbuf *b, struct pcm_channel *c, int dir)
{
-struct sb_info *sb = devinfo;
-struct sb_chinfo *ch = (dir == PCMDIR_PLAY)? &sb->pch : &sb->rch;
+ struct sb_info *sb = devinfo;
+ struct sb_chinfo *ch = (dir == PCMDIR_PLAY)? &sb->pch : &sb->rch;
-ch->parent = sb;
-ch->channel = c;
-ch->dir = dir;
-ch->buffer = b;
-if (sndbuf_alloc(ch->buffer, sb->parent_dmat, sb->bufsize) != 0)
-return NULL;
-sndbuf_dmasetup(ch->buffer, sb->drq);
-return ch;
+ ch->parent = sb;
+ ch->channel = c;
+ ch->dir = dir;
+ ch->buffer = b;
+ if (sndbuf_alloc(ch->buffer, sb->parent_dmat, 0, sb->bufsize) != 0)
+ return NULL;
+ sndbuf_dmasetup(ch->buffer, sb->drq);
+ return ch;
}
static int
sbchan_setformat(kobj_t obj, void *data, u_int32_t format)
{
-struct sb_chinfo *ch = data;
+ struct sb_chinfo *ch = data;
-ch->fmt = format;
-return 0;
+ ch->fmt = format;
+ return 0;
}
static int
sbchan_setspeed(kobj_t obj, void *data, u_int32_t speed)
{
-struct sb_chinfo *ch = data;
+ struct sb_chinfo *ch = data;
-ch->spd = speed;
-return sb_speed(ch);
+ ch->spd = speed;
+ return sb_speed(ch);
}
static int
sbchan_setblocksize(kobj_t obj, void *data, u_int32_t blocksize)
{
-struct sb_chinfo *ch = data;
+ struct sb_chinfo *ch = data;
-ch->blksz = blocksize;
-return ch->blksz;
+ ch->blksz = blocksize;
+ return ch->blksz;
}
static int
sbchan_trigger(kobj_t obj, void *data, int go)
{
-struct sb_chinfo *ch = data;
+ struct sb_chinfo *ch = data;
-if (go == PCMTRIG_EMLDMAWR || go == PCMTRIG_EMLDMARD)
-return 0;
+ if (!PCMTRIG_COMMON(go))
+ return 0;
-sndbuf_dma(ch->buffer, go);
-if (go == PCMTRIG_START)
-sb_start(ch);
-else
-sb_stop(ch);
-return 0;
+ sndbuf_dma(ch->buffer, go);
+ if (go == PCMTRIG_START)
+ sb_start(ch);
+ else
+ sb_stop(ch);
+ return 0;
}
static int
sbchan_getptr(kobj_t obj, void *data)
{
-struct sb_chinfo *ch = data;
+ struct sb_chinfo *ch = data;
-return sndbuf_dmaptr(ch->buffer);
+ return sndbuf_dmaptr(ch->buffer);
}
static struct pcmchan_caps *
sbchan_getcaps(kobj_t obj, void *data)
{
-struct sb_chinfo *ch = data;
-int p = (ch->dir == PCMDIR_PLAY)? 1 : 0;
+ struct sb_chinfo *ch = data;
+ int p = (ch->dir == PCMDIR_PLAY)? 1 : 0;
-if (ch->parent->bd_id == 0x200)
-return p? &sb200_playcaps : &sb200_reccaps;
-if (ch->parent->bd_id < 0x300)
-return p? &sb201_playcaps : &sb201_reccaps;
-return p? &sbpro_playcaps : &sbpro_reccaps;
+ if (ch->parent->bd_id == 0x200)
+ return p? &sb200_playcaps : &sb200_reccaps;
+ if (ch->parent->bd_id < 0x300)
+ return p? &sb201_playcaps : &sb201_reccaps;
+ return p? &sbpro_playcaps : &sbpro_reccaps;
}
static kobj_method_t sbchan_methods[] = {
-KOBJMETHOD(channel_init, sbchan_init),
-KOBJMETHOD(channel_setformat, sbchan_setformat),
-KOBJMETHOD(channel_setspeed, sbchan_setspeed),
-KOBJMETHOD(channel_setblocksize, sbchan_setblocksize),
-KOBJMETHOD(channel_trigger, sbchan_trigger),
-KOBJMETHOD(channel_getptr, sbchan_getptr),
-KOBJMETHOD(channel_getcaps, sbchan_getcaps),
-{ 0, 0 }
+ KOBJMETHOD(channel_init, sbchan_init),
+ KOBJMETHOD(channel_setformat, sbchan_setformat),
+ KOBJMETHOD(channel_setspeed, sbchan_setspeed),
+ KOBJMETHOD(channel_setblocksize, sbchan_setblocksize),
+ KOBJMETHOD(channel_trigger, sbchan_trigger),
+ KOBJMETHOD(channel_getptr, sbchan_getptr),
+ KOBJMETHOD(channel_getcaps, sbchan_getcaps),
+ { 0, 0 }
};
CHANNEL_DECLARE(sbchan);
@@ -686,113 +686,111 @@
static int
sb_probe(device_t dev)
{
-char buf[64];
-uintptr_t func, ver, r, f;
+ char buf[64];
+ uintptr_t func, ver, r, f;
-/* The parent device has already been probed. */
-r = BUS_READ_IVAR(device_get_parent(dev), dev, 0, &func);
-if (func != SCF_PCM)
-return (ENXIO);
+ /* The parent device has already been probed. */
+ r = BUS_READ_IVAR(device_get_parent(dev), dev, 0, &func);
+ if (func != SCF_PCM)
+ return (ENXIO);
-r = BUS_READ_IVAR(device_get_parent(dev), dev, 1, &ver);
-f = (ver & 0xffff0000) >> 16;
-ver &= 0x0000ffff;
-if ((f & BD_F_ESS) || (ver >= 0x400))
-return (ENXIO);
+ r = BUS_READ_IVAR(device_get_parent(dev), dev, 1, &ver);
+ f = (ver & 0xffff0000) >> 16;
+ ver &= 0x0000ffff;
+ if ((f & BD_F_ESS) || (ver >= 0x400))
+ return (ENXIO);
-snprintf(buf, sizeof buf, "SB DSP %d.%02d", (int) ver >> 8, (int) ver & 0xff);
+ snprintf(buf, sizeof buf, "SB DSP %d.%02d", (int) ver >> 8, (int) ver & 0xff);
-device_set_desc_copy(dev, buf);
+ device_set_desc_copy(dev, buf);
-return 0;
+ return 0;
}
static int
sb_attach(device_t dev)
{
-struct sb_info *sb;
-char status[SND_STATUSLEN];
-uintptr_t ver;
-
-sb = (struct sb_info *)malloc(sizeof *sb, M_DEVBUF, M_NOWAIT | M_ZERO);
-if (!sb)
-return ENXIO;
-
-sb->parent_dev = device_get_parent(dev);
-BUS_READ_IVAR(device_get_parent(dev), dev, 1, &ver);
-sb->bd_id = ver & 0x0000ffff;
-sb->bd_flags = (ver & 0xffff0000) >> 16;
-sb->bufsize = pcm_getbuffersize(dev, 4096, SB_DEFAULT_BUFSZ, 65536);
-
-if (sb_alloc_resources(sb, dev))
-goto no;
-if (sb_reset_dsp(sb))
-goto no;
-if (mixer_init(dev, (sb->bd_id < 0x300)? &sbmix_mixer_class : &sbpromix_mixer_class, sb))
-goto no;
-if (snd_setup_intr(dev, sb->irq, 0, sb_intr, sb, &sb->ih))
-goto no;
-
-pcm_setflags(dev, pcm_getflags(dev) | SD_F_SIMPLEX);
-
-if (bus_dma_tag_create(/*parent*/NULL, /*alignment*/2, /*boundary*/0,
-/*lowaddr*/BUS_SPACE_MAXADDR_24BIT,
-/*highaddr*/BUS_SPACE_MAXADDR,
-/*filter*/NULL, /*filterarg*/NULL,
-/*maxsize*/sb->bufsize, /*nsegments*/1,
-/*maxsegz*/0x3ffff, /*flags*/0,
-/*lockfunc*/busdma_lock_mutex, /*lockarg*/&Giant,
-&sb->parent_dmat) != 0) {
-device_printf(dev, "unable to create dma tagn");
-goto no;
-}
-
-snprintf(status, SND_STATUSLEN, "at io 0x%lx irq %ld drq %ld bufsz %u %s",
-rman_get_start(sb->io_base), rman_get_start(sb->irq),
-rman_get_start(sb->drq), sb->bufsize, PCM_KLDSTRING(snd_sb8));
-
-if (pcm_register(dev, sb, 1, 1))
-goto no;
-pcm_addchan(dev, PCMDIR_REC, &sbchan_class, sb);
-pcm_addchan(dev, PCMDIR_PLAY, &sbchan_class, sb);
+ struct sb_info *sb;
+ char status[SND_STATUSLEN];
+ uintptr_t ver;
+
+ sb = malloc(sizeof(*sb), M_DEVBUF, M_WAITOK | M_ZERO);
+ sb->parent_dev = device_get_parent(dev);
+ BUS_READ_IVAR(device_get_parent(dev), dev, 1, &ver);
+ sb->bd_id = ver & 0x0000ffff;
+ sb->bd_flags = (ver & 0xffff0000) >> 16;
+ sb->bufsize = pcm_getbuffersize(dev, 4096, SB_DEFAULT_BUFSZ, 65536);
+
+ if (sb_alloc_resources(sb, dev))
+ goto no;
+ if (sb_reset_dsp(sb))
+ goto no;
+ if (mixer_init(dev, (sb->bd_id < 0x300)? &sbmix_mixer_class : &sbpromix_mixer_class, sb))
+ goto no;
+ if (snd_setup_intr(dev, sb->irq, 0, sb_intr, sb, &sb->ih))
+ goto no;
+
+ pcm_setflags(dev, pcm_getflags(dev) | SD_F_SIMPLEX);
+
+ if (bus_dma_tag_create(/*parent*/bus_get_dma_tag(dev), /*alignment*/2,
+ /*boundary*/0,
+ /*lowaddr*/BUS_SPACE_MAXADDR_24BIT,
+ /*highaddr*/BUS_SPACE_MAXADDR,
+ /*filter*/NULL, /*filterarg*/NULL,
+ /*maxsize*/sb->bufsize, /*nsegments*/1,
+ /*maxsegz*/0x3ffff, /*flags*/0,
+ /*lockfunc*/busdma_lock_mutex, /*lockarg*/&Giant,
+ &sb->parent_dmat) != 0) {
+ device_printf(dev, "unable to create dma tag\n");
+ goto no;
+ }
+
+ snprintf(status, SND_STATUSLEN, "at io 0x%lx irq %ld drq %ld bufsz %u %s",
+ rman_get_start(sb->io_base), rman_get_start(sb->irq),
+ rman_get_start(sb->drq), sb->bufsize, PCM_KLDSTRING(snd_sb8));
+
+ if (pcm_register(dev, sb, 1, 1))
+ goto no;
+ pcm_addchan(dev, PCMDIR_REC, &sbchan_class, sb);
+ pcm_addchan(dev, PCMDIR_PLAY, &sbchan_class, sb);
-pcm_setstatus(dev, status);
+ pcm_setstatus(dev, status);
-return 0;
+ return 0;
no:
-sb_release_resources(sb, dev);
-return ENXIO;
+ sb_release_resources(sb, dev);
+ return ENXIO;
}
static int
sb_detach(device_t dev)
{
-int r;
-struct sb_info *sb;
+ int r;
+ struct sb_info *sb;
-r = pcm_unregister(dev);
-if (r)
-return r;
-
-sb = pcm_getdevinfo(dev);
-sb_release_resources(sb, dev);
-return 0;
+ r = pcm_unregister(dev);
+ if (r)
+ return r;
+
+ sb = pcm_getdevinfo(dev);
+ sb_release_resources(sb, dev);
+ return 0;
}
static device_method_t sb_methods[] = {
-/* Device interface */
-DEVMETHOD(device_probe, sb_probe),
-DEVMETHOD(device_attach, sb_attach),
-DEVMETHOD(device_detach, sb_detach),
+ /* Device interface */
+ DEVMETHOD(device_probe, sb_probe),
+ DEVMETHOD(device_attach, sb_attach),
+ DEVMETHOD(device_detach, sb_detach),
-{ 0, 0 }
+ { 0, 0 }
};
static driver_t sb_driver = {
-"pcm",
-sb_methods,
-PCM_SOFTC_SIZE,
+ "pcm",
+ sb_methods,
+ PCM_SOFTC_SIZE,
};
DRIVER_MODULE(snd_sb8, sbc, sb_driver, pcm_devclass, 0, 0);
Index: ad1816.c
===================================================================
RCS file: /home/cvs/src/sys/dev/sound/isa/ad1816.c,v
retrieving revision 1.3
retrieving revision 1.4
diff -L sys/dev/sound/isa/ad1816.c -L sys/dev/sound/isa/ad1816.c -u -r1.3 -r1.4
--- sys/dev/sound/isa/ad1816.c
+++ sys/dev/sound/isa/ad1816.c
@@ -1,30 +1,30 @@
/*-
-* Copyright (c) 1999 Cameron Grant <cg at freebsd.org>
-* Copyright Luigi Rizzo, 1997,1998
-* Copyright by Hannu Savolainen 1994, 1995
-* All rights reserved.
-*
-* Redistribution and use in source and binary forms, with or without
-* modification, are permitted provided that the following conditions
-* are met:
-* 1. Redistributions of source code must retain the above copyright
-* notice, this list of conditions and the following disclaimer.
-* 2. Redistributions in binary form must reproduce the above copyright
-* notice, this list of conditions and the following disclaimer in the
-* documentation and/or other materials provided with the distribution.
-*
-* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
-* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
-* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
-* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
-* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
-* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
-* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
-* SUCH DAMAGE.
-*/
+ * Copyright (c) 1999 Cameron Grant <cg at freebsd.org>
+ * Copyright (c) 1997,1998 Luigi Rizzo
+ * Copyright (c) 1994,1995 Hannu Savolainen
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
#include <dev/sound/pcm/sound.h>
#include <dev/sound/isa/ad1816.h>
@@ -33,44 +33,44 @@
#include "mixer_if.h"
-SND_DECLARE_FILE("$MidnightBSD$");
+SND_DECLARE_FILE("$FreeBSD: src/sys/dev/sound/isa/ad1816.c,v 1.45 2007/06/17 06:10:40 ariff Exp $");
struct ad1816_info;
struct ad1816_chinfo {
-struct ad1816_info *parent;
-struct pcm_channel *channel;
-struct snd_dbuf *buffer;
-int dir, blksz;
+ struct ad1816_info *parent;
+ struct pcm_channel *channel;
+ struct snd_dbuf *buffer;
+ int dir, blksz;
};
struct ad1816_info {
-struct resource *io_base; /* primary I/O address for the board */
-int io_rid;
-struct resource *irq;
-int irq_rid;
-struct resource *drq1; /* play */
-int drq1_rid;
-struct resource *drq2; /* rec */
-int drq2_rid;
-void *ih;
-bus_dma_tag_t parent_dmat;
-struct mtx *lock;
+ struct resource *io_base; /* primary I/O address for the board */
+ int io_rid;
+ struct resource *irq;
+ int irq_rid;
+ struct resource *drq1; /* play */
+ int drq1_rid;
+ struct resource *drq2; /* rec */
+ int drq2_rid;
+ void *ih;
+ bus_dma_tag_t parent_dmat;
+ struct mtx *lock;
-unsigned int bufsize;
-struct ad1816_chinfo pch, rch;
+ unsigned int bufsize;
+ struct ad1816_chinfo pch, rch;
};
static u_int32_t ad1816_fmt[] = {
-AFMT_U8,
-AFMT_STEREO | AFMT_U8,
-AFMT_S16_LE,
-AFMT_STEREO | AFMT_S16_LE,
-AFMT_MU_LAW,
-AFMT_STEREO | AFMT_MU_LAW,
-AFMT_A_LAW,
-AFMT_STEREO | AFMT_A_LAW,
-0
+ AFMT_U8,
+ AFMT_STEREO | AFMT_U8,
+ AFMT_S16_LE,
+ AFMT_STEREO | AFMT_S16_LE,
+ AFMT_MU_LAW,
+ AFMT_STEREO | AFMT_MU_LAW,
+ AFMT_A_LAW,
+ AFMT_STEREO | AFMT_A_LAW,
+ 0
};
static struct pcmchan_caps ad1816_caps = {4000, 55200, ad1816_fmt, 0};
@@ -80,120 +80,120 @@
static void
ad1816_lock(struct ad1816_info *ad1816)
{
-snd_mtxlock(ad1816->lock);
+ snd_mtxlock(ad1816->lock);
}
static void
ad1816_unlock(struct ad1816_info *ad1816)
{
-snd_mtxunlock(ad1816->lock);
+ snd_mtxunlock(ad1816->lock);
}
static int
port_rd(struct resource *port, int off)
{
-if (port)
-return bus_space_read_1(rman_get_bustag(port),
-rman_get_bushandle(port),
-off);
-else
-return -1;
+ if (port)
+ return bus_space_read_1(rman_get_bustag(port),
+ rman_get_bushandle(port),
+ off);
+ else
+ return -1;
}
static void
port_wr(struct resource *port, int off, u_int8_t data)
{
-if (port)
-bus_space_write_1(rman_get_bustag(port),
-rman_get_bushandle(port),
-off, data);
+ if (port)
+ bus_space_write_1(rman_get_bustag(port),
+ rman_get_bushandle(port),
+ off, data);
}
static int
io_rd(struct ad1816_info *ad1816, int reg)
{
-return port_rd(ad1816->io_base, reg);
+ return port_rd(ad1816->io_base, reg);
}
static void
io_wr(struct ad1816_info *ad1816, int reg, u_int8_t data)
{
-port_wr(ad1816->io_base, reg, data);
+ port_wr(ad1816->io_base, reg, data);
}
static void
ad1816_intr(void *arg)
{
-struct ad1816_info *ad1816 = (struct ad1816_info *)arg;
-unsigned char c, served = 0;
+ struct ad1816_info *ad1816 = (struct ad1816_info *)arg;
+ unsigned char c, served = 0;
-ad1816_lock(ad1816);
-/* get interupt status */
-c = io_rd(ad1816, AD1816_INT);
-
-/* check for stray interupts */
-if (c & ~(AD1816_INTRCI | AD1816_INTRPI)) {
-printf("pcm: stray int (%x)n", c);
-c &= AD1816_INTRCI | AD1816_INTRPI;
-}
-/* check for capture interupt */
-if (sndbuf_runsz(ad1816->rch.buffer) && (c & AD1816_INTRCI)) {
-ad1816_unlock(ad1816);
-chn_intr(ad1816->rch.channel);
-ad1816_lock(ad1816);
-served |= AD1816_INTRCI; /* cp served */
-}
-/* check for playback interupt */
-if (sndbuf_runsz(ad1816->pch.buffer) && (c & AD1816_INTRPI)) {
-ad1816_unlock(ad1816);
-chn_intr(ad1816->pch.channel);
-ad1816_lock(ad1816);
-served |= AD1816_INTRPI; /* pb served */
-}
-if (served == 0) {
-/* this probably means this is not a (working) ad1816 chip, */
-/* or an error in dma handling */
-printf("pcm: int without reason (%x)n", c);
-c = 0;
-} else c &= ~served;
-io_wr(ad1816, AD1816_INT, c);
-c = io_rd(ad1816, AD1816_INT);
-if (c != 0) printf("pcm: int clear failed (%x)n", c);
-ad1816_unlock(ad1816);
+ ad1816_lock(ad1816);
+ /* get interupt status */
+ c = io_rd(ad1816, AD1816_INT);
+
+ /* check for stray interupts */
+ if (c & ~(AD1816_INTRCI | AD1816_INTRPI)) {
+ printf("pcm: stray int (%x)\n", c);
+ c &= AD1816_INTRCI | AD1816_INTRPI;
+ }
+ /* check for capture interupt */
+ if (sndbuf_runsz(ad1816->rch.buffer) && (c & AD1816_INTRCI)) {
+ ad1816_unlock(ad1816);
+ chn_intr(ad1816->rch.channel);
+ ad1816_lock(ad1816);
+ served |= AD1816_INTRCI; /* cp served */
+ }
+ /* check for playback interupt */
+ if (sndbuf_runsz(ad1816->pch.buffer) && (c & AD1816_INTRPI)) {
+ ad1816_unlock(ad1816);
+ chn_intr(ad1816->pch.channel);
+ ad1816_lock(ad1816);
+ served |= AD1816_INTRPI; /* pb served */
+ }
+ if (served == 0) {
+ /* this probably means this is not a (working) ad1816 chip, */
+ /* or an error in dma handling */
+ printf("pcm: int without reason (%x)\n", c);
+ c = 0;
+ } else c &= ~served;
+ io_wr(ad1816, AD1816_INT, c);
+ c = io_rd(ad1816, AD1816_INT);
+ if (c != 0) printf("pcm: int clear failed (%x)\n", c);
+ ad1816_unlock(ad1816);
}
static int
ad1816_wait_init(struct ad1816_info *ad1816, int x)
{
-int n = 0; /* to shut up the compiler... */
+ int n = 0; /* to shut up the compiler... */
-for (; x--;)
-if ((n = (io_rd(ad1816, AD1816_ALE) & AD1816_BUSY)) == 0) DELAY(10);
-else return n;
-printf("ad1816_wait_init failed 0x%02x.n", n);
-return -1;
+ for (; x--;)
+ if ((n = (io_rd(ad1816, AD1816_ALE) & AD1816_BUSY)) == 0) DELAY(10);
+ else return n;
+ printf("ad1816_wait_init failed 0x%02x.\n", n);
+ return -1;
}
static unsigned short
ad1816_read(struct ad1816_info *ad1816, unsigned int reg)
{
-u_short x = 0;
+ u_short x = 0;
-if (ad1816_wait_init(ad1816, 100) == -1) return 0;
-io_wr(ad1816, AD1816_ALE, 0);
-io_wr(ad1816, AD1816_ALE, (reg & AD1816_ALEMASK));
-if (ad1816_wait_init(ad1816, 100) == -1) return 0;
-x = (io_rd(ad1816, AD1816_HIGH) << 8) | io_rd(ad1816, AD1816_LOW);
-return x;
+ if (ad1816_wait_init(ad1816, 100) == -1) return 0;
+ io_wr(ad1816, AD1816_ALE, 0);
+ io_wr(ad1816, AD1816_ALE, (reg & AD1816_ALEMASK));
+ if (ad1816_wait_init(ad1816, 100) == -1) return 0;
+ x = (io_rd(ad1816, AD1816_HIGH) << 8) | io_rd(ad1816, AD1816_LOW);
+ return x;
}
static void
ad1816_write(struct ad1816_info *ad1816, unsigned int reg, unsigned short data)
{
-if (ad1816_wait_init(ad1816, 100) == -1) return;
-io_wr(ad1816, AD1816_ALE, (reg & AD1816_ALEMASK));
-io_wr(ad1816, AD1816_LOW, (data & 0x000000ff));
-io_wr(ad1816, AD1816_HIGH, (data & 0x0000ff00) >> 8);
+ if (ad1816_wait_init(ad1816, 100) == -1) return;
+ io_wr(ad1816, AD1816_ALE, (reg & AD1816_ALEMASK));
+ io_wr(ad1816, AD1816_LOW, (data & 0x000000ff));
+ io_wr(ad1816, AD1816_HIGH, (data & 0x0000ff00) >> 8);
}
/* -------------------------------------------------------------------- */
@@ -201,109 +201,109 @@
static int
ad1816mix_init(struct snd_mixer *m)
{
-mix_setdevs(m, AD1816_MIXER_DEVICES);
-mix_setrecdevs(m, AD1816_REC_DEVICES);
-return 0;
+ mix_setdevs(m, AD1816_MIXER_DEVICES);
+ mix_setrecdevs(m, AD1816_REC_DEVICES);
+ return 0;
}
static int
ad1816mix_set(struct snd_mixer *m, unsigned dev, unsigned left, unsigned right)
{
-struct ad1816_info *ad1816 = mix_getdevinfo(m);
-u_short reg = 0;
+ struct ad1816_info *ad1816 = mix_getdevinfo(m);
+ u_short reg = 0;
-/* Scale volumes */
-left = AD1816_MUTE - (AD1816_MUTE * left) / 100;
-right = AD1816_MUTE - (AD1816_MUTE * right) / 100;
-
-reg = (left << 8) | right;
-
-/* do channel selective muting if volume is zero */
-if (left == AD1816_MUTE) reg |= 0x8000;
-if (right == AD1816_MUTE) reg |= 0x0080;
-
-ad1816_lock(ad1816);
-switch (dev) {
-case SOUND_MIXER_VOLUME: /* Register 14 master volume */
-ad1816_write(ad1816, 14, reg);
-break;
-
-case SOUND_MIXER_CD: /* Register 15 cd */
-case SOUND_MIXER_LINE1:
-ad1816_write(ad1816, 15, reg);
-break;
-
-case SOUND_MIXER_SYNTH: /* Register 16 synth */
-ad1816_write(ad1816, 16, reg);
-break;
-
-case SOUND_MIXER_PCM: /* Register 4 pcm */
-ad1816_write(ad1816, 4, reg);
-break;
-
-case SOUND_MIXER_LINE:
-case SOUND_MIXER_LINE3: /* Register 18 line in */
-ad1816_write(ad1816, 18, reg);
-break;
-
-case SOUND_MIXER_MIC: /* Register 19 mic volume */
-ad1816_write(ad1816, 19, reg & ~0xff); /* mic is mono */
-break;
-
-case SOUND_MIXER_IGAIN:
-/* and now to something completely different ... */
-ad1816_write(ad1816, 20, ((ad1816_read(ad1816, 20) & ~0x0f0f)
-| (((AD1816_MUTE - left) / 2) << 8) /* four bits of adc gain */
-| ((AD1816_MUTE - right) / 2)));
-break;
-
-default:
-printf("ad1816_mixer_set(): unknown device.n");
-break;
-}
-ad1816_unlock(ad1816);
+ /* Scale volumes */
+ left = AD1816_MUTE - (AD1816_MUTE * left) / 100;
+ right = AD1816_MUTE - (AD1816_MUTE * right) / 100;
+
+ reg = (left << 8) | right;
+
+ /* do channel selective muting if volume is zero */
+ if (left == AD1816_MUTE) reg |= 0x8000;
+ if (right == AD1816_MUTE) reg |= 0x0080;
+
+ ad1816_lock(ad1816);
+ switch (dev) {
+ case SOUND_MIXER_VOLUME: /* Register 14 master volume */
+ ad1816_write(ad1816, 14, reg);
+ break;
+
+ case SOUND_MIXER_CD: /* Register 15 cd */
+ case SOUND_MIXER_LINE1:
+ ad1816_write(ad1816, 15, reg);
+ break;
+
+ case SOUND_MIXER_SYNTH: /* Register 16 synth */
+ ad1816_write(ad1816, 16, reg);
+ break;
+
+ case SOUND_MIXER_PCM: /* Register 4 pcm */
+ ad1816_write(ad1816, 4, reg);
+ break;
+
+ case SOUND_MIXER_LINE:
+ case SOUND_MIXER_LINE3: /* Register 18 line in */
+ ad1816_write(ad1816, 18, reg);
+ break;
+
+ case SOUND_MIXER_MIC: /* Register 19 mic volume */
+ ad1816_write(ad1816, 19, reg & ~0xff); /* mic is mono */
+ break;
+
+ case SOUND_MIXER_IGAIN:
+ /* and now to something completely different ... */
+ ad1816_write(ad1816, 20, ((ad1816_read(ad1816, 20) & ~0x0f0f)
+ | (((AD1816_MUTE - left) / 2) << 8) /* four bits of adc gain */
+ | ((AD1816_MUTE - right) / 2)));
+ break;
+
+ default:
+ printf("ad1816_mixer_set(): unknown device.\n");
+ break;
+ }
+ ad1816_unlock(ad1816);
-left = ((AD1816_MUTE - left) * 100) / AD1816_MUTE;
-right = ((AD1816_MUTE - right) * 100) / AD1816_MUTE;
+ left = ((AD1816_MUTE - left) * 100) / AD1816_MUTE;
+ right = ((AD1816_MUTE - right) * 100) / AD1816_MUTE;
-return left | (right << 8);
+ return left | (right << 8);
}
static int
ad1816mix_setrecsrc(struct snd_mixer *m, u_int32_t src)
{
-struct ad1816_info *ad1816 = mix_getdevinfo(m);
-int dev;
+ struct ad1816_info *ad1816 = mix_getdevinfo(m);
+ int dev;
-switch (src) {
-case SOUND_MASK_LINE:
-case SOUND_MASK_LINE3:
-dev = 0x00;
-break;
-
-case SOUND_MASK_CD:
-case SOUND_MASK_LINE1:
-dev = 0x20;
-break;
-
-case SOUND_MASK_MIC:
-default:
-dev = 0x50;
-src = SOUND_MASK_MIC;
-}
-
-dev |= dev << 8;
-ad1816_lock(ad1816);
-ad1816_write(ad1816, 20, (ad1816_read(ad1816, 20) & ~0x7070) | dev);
-ad1816_unlock(ad1816);
-return src;
+ switch (src) {
+ case SOUND_MASK_LINE:
+ case SOUND_MASK_LINE3:
+ dev = 0x00;
+ break;
+
+ case SOUND_MASK_CD:
+ case SOUND_MASK_LINE1:
+ dev = 0x20;
+ break;
+
+ case SOUND_MASK_MIC:
+ default:
+ dev = 0x50;
+ src = SOUND_MASK_MIC;
+ }
+
+ dev |= dev << 8;
+ ad1816_lock(ad1816);
+ ad1816_write(ad1816, 20, (ad1816_read(ad1816, 20) & ~0x7070) | dev);
+ ad1816_unlock(ad1816);
+ return src;
}
static kobj_method_t ad1816mixer_methods[] = {
-KOBJMETHOD(mixer_init, ad1816mix_init),
-KOBJMETHOD(mixer_set, ad1816mix_set),
-KOBJMETHOD(mixer_setrecsrc, ad1816mix_setrecsrc),
-{ 0, 0 }
+ KOBJMETHOD(mixer_init, ad1816mix_init),
+ KOBJMETHOD(mixer_set, ad1816mix_set),
+ KOBJMETHOD(mixer_setrecsrc, ad1816mix_setrecsrc),
+ { 0, 0 }
};
MIXER_DECLARE(ad1816mixer);
@@ -312,173 +312,173 @@
static void *
ad1816chan_init(kobj_t obj, void *devinfo, struct snd_dbuf *b, struct pcm_channel *c, int dir)
{
-struct ad1816_info *ad1816 = devinfo;
-struct ad1816_chinfo *ch = (dir == PCMDIR_PLAY)? &ad1816->pch : &ad1816->rch;
+ struct ad1816_info *ad1816 = devinfo;
+ struct ad1816_chinfo *ch = (dir == PCMDIR_PLAY)? &ad1816->pch : &ad1816->rch;
-ch->parent = ad1816;
-ch->channel = c;
-ch->buffer = b;
-if (sndbuf_alloc(ch->buffer, ad1816->parent_dmat, ad1816->bufsize) != 0)
-return NULL;
-return ch;
+ ch->parent = ad1816;
+ ch->channel = c;
+ ch->buffer = b;
+ if (sndbuf_alloc(ch->buffer, ad1816->parent_dmat, 0, ad1816->bufsize) != 0)
+ return NULL;
+ return ch;
}
static int
ad1816chan_setdir(kobj_t obj, void *data, int dir)
{
-struct ad1816_chinfo *ch = data;
-struct ad1816_info *ad1816 = ch->parent;
+ struct ad1816_chinfo *ch = data;
+ struct ad1816_info *ad1816 = ch->parent;
-sndbuf_dmasetup(ch->buffer, (dir == PCMDIR_PLAY)? ad1816->drq1 : ad1816->drq2);
-ch->dir = dir;
-return 0;
+ sndbuf_dmasetup(ch->buffer, (dir == PCMDIR_PLAY)? ad1816->drq1 : ad1816->drq2);
+ ch->dir = dir;
+ return 0;
}
static int
ad1816chan_setformat(kobj_t obj, void *data, u_int32_t format)
{
-struct ad1816_chinfo *ch = data;
-struct ad1816_info *ad1816 = ch->parent;
-int fmt = AD1816_U8, reg;
-
-ad1816_lock(ad1816);
-if (ch->dir == PCMDIR_PLAY) {
-reg = AD1816_PLAY;
-ad1816_write(ad1816, 8, 0x0000); /* reset base and current counter */
-ad1816_write(ad1816, 9, 0x0000); /* for playback and capture */
-} else {
-reg = AD1816_CAPT;
-ad1816_write(ad1816, 10, 0x0000);
-ad1816_write(ad1816, 11, 0x0000);
-}
-switch (format & ~AFMT_STEREO) {
-case AFMT_A_LAW:
-fmt = AD1816_ALAW;
-break;
-
-case AFMT_MU_LAW:
-fmt = AD1816_MULAW;
-break;
-
-case AFMT_S16_LE:
-fmt = AD1816_S16LE;
-break;
-
-case AFMT_S16_BE:
-fmt = AD1816_S16BE;
-break;
-
-case AFMT_U8:
-fmt = AD1816_U8;
-break;
-}
-if (format & AFMT_STEREO) fmt |= AD1816_STEREO;
-io_wr(ad1816, reg, fmt);
-ad1816_unlock(ad1816);
+ struct ad1816_chinfo *ch = data;
+ struct ad1816_info *ad1816 = ch->parent;
+ int fmt = AD1816_U8, reg;
+
+ ad1816_lock(ad1816);
+ if (ch->dir == PCMDIR_PLAY) {
+ reg = AD1816_PLAY;
+ ad1816_write(ad1816, 8, 0x0000); /* reset base and current counter */
+ ad1816_write(ad1816, 9, 0x0000); /* for playback and capture */
+ } else {
+ reg = AD1816_CAPT;
+ ad1816_write(ad1816, 10, 0x0000);
+ ad1816_write(ad1816, 11, 0x0000);
+ }
+ switch (format & ~AFMT_STEREO) {
+ case AFMT_A_LAW:
+ fmt = AD1816_ALAW;
+ break;
+
+ case AFMT_MU_LAW:
+ fmt = AD1816_MULAW;
+ break;
+
+ case AFMT_S16_LE:
+ fmt = AD1816_S16LE;
+ break;
+
+ case AFMT_S16_BE:
+ fmt = AD1816_S16BE;
+ break;
+
+ case AFMT_U8:
+ fmt = AD1816_U8;
+ break;
+ }
+ if (format & AFMT_STEREO) fmt |= AD1816_STEREO;
+ io_wr(ad1816, reg, fmt);
+ ad1816_unlock(ad1816);
#if 0
-return format;
+ return format;
#else
-return 0;
+ return 0;
#endif
}
static int
ad1816chan_setspeed(kobj_t obj, void *data, u_int32_t speed)
{
-struct ad1816_chinfo *ch = data;
-struct ad1816_info *ad1816 = ch->parent;
+ struct ad1816_chinfo *ch = data;
+ struct ad1816_info *ad1816 = ch->parent;
-RANGE(speed, 4000, 55200);
-ad1816_lock(ad1816);
-ad1816_write(ad1816, (ch->dir == PCMDIR_PLAY)? 2 : 3, speed);
-ad1816_unlock(ad1816);
-return speed;
+ RANGE(speed, 4000, 55200);
+ ad1816_lock(ad1816);
+ ad1816_write(ad1816, (ch->dir == PCMDIR_PLAY)? 2 : 3, speed);
+ ad1816_unlock(ad1816);
+ return speed;
}
static int
ad1816chan_setblocksize(kobj_t obj, void *data, u_int32_t blocksize)
{
-struct ad1816_chinfo *ch = data;
+ struct ad1816_chinfo *ch = data;
-ch->blksz = blocksize;
-return ch->blksz;
+ ch->blksz = blocksize;
+ return ch->blksz;
}
static int
ad1816chan_trigger(kobj_t obj, void *data, int go)
{
-struct ad1816_chinfo *ch = data;
-struct ad1816_info *ad1816 = ch->parent;
-int wr, reg;
-
-if (go == PCMTRIG_EMLDMAWR || go == PCMTRIG_EMLDMARD)
-return 0;
-
-sndbuf_dma(ch->buffer, go);
-wr = (ch->dir == PCMDIR_PLAY);
-reg = wr? AD1816_PLAY : AD1816_CAPT;
-ad1816_lock(ad1816);
-switch (go) {
-case PCMTRIG_START:
-/* start only if not already running */
-if (!(io_rd(ad1816, reg) & AD1816_ENABLE)) {
-int cnt = ((ch->blksz) >> 2) - 1;
-ad1816_write(ad1816, wr? 8 : 10, cnt); /* count */
-ad1816_write(ad1816, wr? 9 : 11, 0); /* reset cur cnt */
-ad1816_write(ad1816, 1, ad1816_read(ad1816, 1) |
-(wr? 0x8000 : 0x4000)); /* enable int */
-/* enable playback */
-io_wr(ad1816, reg, io_rd(ad1816, reg) | AD1816_ENABLE);
-if (!(io_rd(ad1816, reg) & AD1816_ENABLE))
-printf("ad1816: failed to start %s DMA!n",
-wr? "play" : "rec");
-}
-break;
-
-case PCMTRIG_STOP:
-case PCMTRIG_ABORT: /* XXX check this... */
-/* we don't test here if it is running... */
-if (wr) {
-ad1816_write(ad1816, 1, ad1816_read(ad1816, 1) &
-~(wr? 0x8000 : 0x4000));
-/* disable int */
-io_wr(ad1816, reg, io_rd(ad1816, reg) & ~AD1816_ENABLE);
-/* disable playback */
-if (io_rd(ad1816, reg) & AD1816_ENABLE)
-printf("ad1816: failed to stop %s DMA!n",
-wr? "play" : "rec");
-ad1816_write(ad1816, wr? 8 : 10, 0); /* reset base cnt */
-ad1816_write(ad1816, wr? 9 : 11, 0); /* reset cur cnt */
-}
-break;
-}
-ad1816_unlock(ad1816);
-return 0;
+ struct ad1816_chinfo *ch = data;
+ struct ad1816_info *ad1816 = ch->parent;
+ int wr, reg;
+
+ if (!PCMTRIG_COMMON(go))
+ return 0;
+
+ sndbuf_dma(ch->buffer, go);
+ wr = (ch->dir == PCMDIR_PLAY);
+ reg = wr? AD1816_PLAY : AD1816_CAPT;
+ ad1816_lock(ad1816);
+ switch (go) {
+ case PCMTRIG_START:
+ /* start only if not already running */
+ if (!(io_rd(ad1816, reg) & AD1816_ENABLE)) {
+ int cnt = ((ch->blksz) >> 2) - 1;
+ ad1816_write(ad1816, wr? 8 : 10, cnt); /* count */
+ ad1816_write(ad1816, wr? 9 : 11, 0); /* reset cur cnt */
+ ad1816_write(ad1816, 1, ad1816_read(ad1816, 1) |
+ (wr? 0x8000 : 0x4000)); /* enable int */
+ /* enable playback */
+ io_wr(ad1816, reg, io_rd(ad1816, reg) | AD1816_ENABLE);
+ if (!(io_rd(ad1816, reg) & AD1816_ENABLE))
+ printf("ad1816: failed to start %s DMA!\n",
+ wr? "play" : "rec");
+ }
+ break;
+
+ case PCMTRIG_STOP:
+ case PCMTRIG_ABORT: /* XXX check this... */
+ /* we don't test here if it is running... */
+ if (wr) {
+ ad1816_write(ad1816, 1, ad1816_read(ad1816, 1) &
+ ~(wr? 0x8000 : 0x4000));
+ /* disable int */
+ io_wr(ad1816, reg, io_rd(ad1816, reg) & ~AD1816_ENABLE);
+ /* disable playback */
+ if (io_rd(ad1816, reg) & AD1816_ENABLE)
+ printf("ad1816: failed to stop %s DMA!\n",
+ wr? "play" : "rec");
+ ad1816_write(ad1816, wr? 8 : 10, 0); /* reset base cnt */
+ ad1816_write(ad1816, wr? 9 : 11, 0); /* reset cur cnt */
+ }
+ break;
+ }
+ ad1816_unlock(ad1816);
+ return 0;
}
static int
ad1816chan_getptr(kobj_t obj, void *data)
{
-struct ad1816_chinfo *ch = data;
-return sndbuf_dmaptr(ch->buffer);
+ struct ad1816_chinfo *ch = data;
+ return sndbuf_dmaptr(ch->buffer);
}
static struct pcmchan_caps *
ad1816chan_getcaps(kobj_t obj, void *data)
{
-return &ad1816_caps;
+ return &ad1816_caps;
}
static kobj_method_t ad1816chan_methods[] = {
-KOBJMETHOD(channel_init, ad1816chan_init),
-KOBJMETHOD(channel_setdir, ad1816chan_setdir),
-KOBJMETHOD(channel_setformat, ad1816chan_setformat),
-KOBJMETHOD(channel_setspeed, ad1816chan_setspeed),
-KOBJMETHOD(channel_setblocksize, ad1816chan_setblocksize),
-KOBJMETHOD(channel_trigger, ad1816chan_trigger),
-KOBJMETHOD(channel_getptr, ad1816chan_getptr),
-KOBJMETHOD(channel_getcaps, ad1816chan_getcaps),
-{ 0, 0 }
+ KOBJMETHOD(channel_init, ad1816chan_init),
+ KOBJMETHOD(channel_setdir, ad1816chan_setdir),
+ KOBJMETHOD(channel_setformat, ad1816chan_setformat),
+ KOBJMETHOD(channel_setspeed, ad1816chan_setspeed),
+ KOBJMETHOD(channel_setblocksize, ad1816chan_setblocksize),
+ KOBJMETHOD(channel_trigger, ad1816chan_trigger),
+ KOBJMETHOD(channel_getptr, ad1816chan_getptr),
+ KOBJMETHOD(channel_getcaps, ad1816chan_getcaps),
+ { 0, 0 }
};
CHANNEL_DECLARE(ad1816chan);
@@ -487,197 +487,197 @@
static void
ad1816_release_resources(struct ad1816_info *ad1816, device_t dev)
{
-if (ad1816->irq) {
-if (ad1816->ih)
-bus_teardown_intr(dev, ad1816->irq, ad1816->ih);
-bus_release_resource(dev, SYS_RES_IRQ, ad1816->irq_rid, ad1816->irq);
-ad1816->irq = 0;
-}
-if (ad1816->drq1) {
-isa_dma_release(rman_get_start(ad1816->drq1));
-bus_release_resource(dev, SYS_RES_DRQ, ad1816->drq1_rid, ad1816->drq1);
-ad1816->drq1 = 0;
-}
-if (ad1816->drq2) {
-isa_dma_release(rman_get_start(ad1816->drq2));
-bus_release_resource(dev, SYS_RES_DRQ, ad1816->drq2_rid, ad1816->drq2);
-ad1816->drq2 = 0;
-}
-if (ad1816->io_base) {
-bus_release_resource(dev, SYS_RES_IOPORT, ad1816->io_rid, ad1816->io_base);
-ad1816->io_base = 0;
-}
-if (ad1816->parent_dmat) {
-bus_dma_tag_destroy(ad1816->parent_dmat);
-ad1816->parent_dmat = 0;
-}
-if (ad1816->lock)
-snd_mtxfree(ad1816->lock);
+ if (ad1816->irq) {
+ if (ad1816->ih)
+ bus_teardown_intr(dev, ad1816->irq, ad1816->ih);
+ bus_release_resource(dev, SYS_RES_IRQ, ad1816->irq_rid, ad1816->irq);
+ ad1816->irq = 0;
+ }
+ if (ad1816->drq1) {
+ isa_dma_release(rman_get_start(ad1816->drq1));
+ bus_release_resource(dev, SYS_RES_DRQ, ad1816->drq1_rid, ad1816->drq1);
+ ad1816->drq1 = 0;
+ }
+ if (ad1816->drq2) {
+ isa_dma_release(rman_get_start(ad1816->drq2));
+ bus_release_resource(dev, SYS_RES_DRQ, ad1816->drq2_rid, ad1816->drq2);
+ ad1816->drq2 = 0;
+ }
+ if (ad1816->io_base) {
+ bus_release_resource(dev, SYS_RES_IOPORT, ad1816->io_rid, ad1816->io_base);
+ ad1816->io_base = 0;
+ }
+ if (ad1816->parent_dmat) {
+ bus_dma_tag_destroy(ad1816->parent_dmat);
+ ad1816->parent_dmat = 0;
+ }
+ if (ad1816->lock)
+ snd_mtxfree(ad1816->lock);
-free(ad1816, M_DEVBUF);
+ free(ad1816, M_DEVBUF);
}
static int
ad1816_alloc_resources(struct ad1816_info *ad1816, device_t dev)
{
-int ok = 1, pdma, rdma;
+ int ok = 1, pdma, rdma;
-if (!ad1816->io_base)
-ad1816->io_base = bus_alloc_resource_any(dev,
-SYS_RES_IOPORT, &ad1816->io_rid, RF_ACTIVE);
-if (!ad1816->irq)
-ad1816->irq = bus_alloc_resource_any(dev, SYS_RES_IRQ,
-&ad1816->irq_rid, RF_ACTIVE);
-if (!ad1816->drq1)
-ad1816->drq1 = bus_alloc_resource_any(dev, SYS_RES_DRQ,
-&ad1816->drq1_rid, RF_ACTIVE);
-if (!ad1816->drq2)
-ad1816->drq2 = bus_alloc_resource_any(dev, SYS_RES_DRQ,
-&ad1816->drq2_rid, RF_ACTIVE);
-
-if (!ad1816->io_base || !ad1816->drq1 || !ad1816->irq) ok = 0;
-
-if (ok) {
-pdma = rman_get_start(ad1816->drq1);
-isa_dma_acquire(pdma);
-isa_dmainit(pdma, ad1816->bufsize);
-if (ad1816->drq2) {
-rdma = rman_get_start(ad1816->drq2);
-isa_dma_acquire(rdma);
-isa_dmainit(rdma, ad1816->bufsize);
-} else
-rdma = pdma;
-if (pdma == rdma)
-pcm_setflags(dev, pcm_getflags(dev) | SD_F_SIMPLEX);
-}
+ if (!ad1816->io_base)
+ ad1816->io_base = bus_alloc_resource_any(dev,
+ SYS_RES_IOPORT, &ad1816->io_rid, RF_ACTIVE);
+ if (!ad1816->irq)
+ ad1816->irq = bus_alloc_resource_any(dev, SYS_RES_IRQ,
+ &ad1816->irq_rid, RF_ACTIVE);
+ if (!ad1816->drq1)
+ ad1816->drq1 = bus_alloc_resource_any(dev, SYS_RES_DRQ,
+ &ad1816->drq1_rid, RF_ACTIVE);
+ if (!ad1816->drq2)
+ ad1816->drq2 = bus_alloc_resource_any(dev, SYS_RES_DRQ,
+ &ad1816->drq2_rid, RF_ACTIVE);
+
+ if (!ad1816->io_base || !ad1816->drq1 || !ad1816->irq) ok = 0;
+
+ if (ok) {
+ pdma = rman_get_start(ad1816->drq1);
+ isa_dma_acquire(pdma);
+ isa_dmainit(pdma, ad1816->bufsize);
+ if (ad1816->drq2) {
+ rdma = rman_get_start(ad1816->drq2);
+ isa_dma_acquire(rdma);
+ isa_dmainit(rdma, ad1816->bufsize);
+ } else
+ rdma = pdma;
+ if (pdma == rdma)
+ pcm_setflags(dev, pcm_getflags(dev) | SD_F_SIMPLEX);
+ }
-return ok;
+ return ok;
}
static int
ad1816_init(struct ad1816_info *ad1816, device_t dev)
{
-ad1816_write(ad1816, 1, 0x2); /* disable interrupts */
-ad1816_write(ad1816, 32, 0x90F0); /* SoundSys Mode, split fmt */
+ ad1816_write(ad1816, 1, 0x2); /* disable interrupts */
+ ad1816_write(ad1816, 32, 0x90F0); /* SoundSys Mode, split fmt */
-ad1816_write(ad1816, 5, 0x8080); /* FM volume mute */
-ad1816_write(ad1816, 6, 0x8080); /* I2S1 volume mute */
-ad1816_write(ad1816, 7, 0x8080); /* I2S0 volume mute */
-ad1816_write(ad1816, 17, 0x8888); /* VID Volume mute */
-ad1816_write(ad1816, 20, 0x5050); /* recsrc mic, agc off */
-/* adc gain is set to 0 */
+ ad1816_write(ad1816, 5, 0x8080); /* FM volume mute */
+ ad1816_write(ad1816, 6, 0x8080); /* I2S1 volume mute */
+ ad1816_write(ad1816, 7, 0x8080); /* I2S0 volume mute */
+ ad1816_write(ad1816, 17, 0x8888); /* VID Volume mute */
+ ad1816_write(ad1816, 20, 0x5050); /* recsrc mic, agc off */
+ /* adc gain is set to 0 */
-return 0;
+ return 0;
}
static int
ad1816_probe(device_t dev)
{
-char *s = NULL;
-u_int32_t logical_id = isa_get_logicalid(dev);
+ char *s = NULL;
+ u_int32_t logical_id = isa_get_logicalid(dev);
-switch (logical_id) {
-case 0x80719304: /* ADS7180 */
-s = "AD1816";
-break;
-case 0x50719304: /* ADS7150 */
-s = "AD1815";
-break;
-}
-
-if (s) {
-device_set_desc(dev, s);
-return BUS_PROBE_DEFAULT;
-}
-return ENXIO;
+ switch (logical_id) {
+ case 0x80719304: /* ADS7180 */
+ s = "AD1816";
+ break;
+ case 0x50719304: /* ADS7150 */
+ s = "AD1815";
+ break;
+ }
+
+ if (s) {
+ device_set_desc(dev, s);
+ return BUS_PROBE_DEFAULT;
+ }
+ return ENXIO;
}
static int
ad1816_attach(device_t dev)
{
-struct ad1816_info *ad1816;
-char status[SND_STATUSLEN], status2[SND_STATUSLEN];
-
-ad1816 = (struct ad1816_info *)malloc(sizeof *ad1816, M_DEVBUF, M_NOWAIT | M_ZERO);
-if (!ad1816) return ENXIO;
+ struct ad1816_info *ad1816;
+ char status[SND_STATUSLEN], status2[SND_STATUSLEN];
-ad1816->lock = snd_mtxcreate(device_get_nameunit(dev), "sound softc");
-ad1816->io_rid = 2;
-ad1816->irq_rid = 0;
-ad1816->drq1_rid = 0;
-ad1816->drq2_rid = 1;
-ad1816->bufsize = pcm_getbuffersize(dev, 4096, DSP_BUFFSIZE, 65536);
-
-if (!ad1816_alloc_resources(ad1816, dev)) goto no;
-ad1816_init(ad1816, dev);
-if (mixer_init(dev, &ad1816mixer_class, ad1816)) goto no;
-
-snd_setup_intr(dev, ad1816->irq, 0, ad1816_intr, ad1816, &ad1816->ih);
-if (bus_dma_tag_create(/*parent*/NULL, /*alignment*/2, /*boundary*/0,
-/*lowaddr*/BUS_SPACE_MAXADDR_24BIT,
-/*highaddr*/BUS_SPACE_MAXADDR,
-/*filter*/NULL, /*filterarg*/NULL,
-/*maxsize*/ad1816->bufsize, /*nsegments*/1,
-/*maxsegz*/0x3ffff,
-/*flags*/0, /*lockfunc*/busdma_lock_mutex,
-/*lockarg*/ &Giant, &ad1816->parent_dmat) != 0) {
-device_printf(dev, "unable to create dma tagn");
-goto no;
-}
-if (ad1816->drq2)
-snprintf(status2, SND_STATUSLEN, ":%ld", rman_get_start(ad1816->drq2));
-else
-status2[0] = '0';
-
-snprintf(status, SND_STATUSLEN, "at io 0x%lx irq %ld drq %ld%s bufsz %u %s",
-rman_get_start(ad1816->io_base),
-rman_get_start(ad1816->irq),
-rman_get_start(ad1816->drq1),
-status2,
-ad1816->bufsize,
-PCM_KLDSTRING(snd_ad1816));
-
-if (pcm_register(dev, ad1816, 1, 1)) goto no;
-pcm_addchan(dev, PCMDIR_REC, &ad1816chan_class, ad1816);
-pcm_addchan(dev, PCMDIR_PLAY, &ad1816chan_class, ad1816);
-pcm_setstatus(dev, status);
+ ad1816 = malloc(sizeof(*ad1816), M_DEVBUF, M_WAITOK | M_ZERO);
+ ad1816->lock = snd_mtxcreate(device_get_nameunit(dev),
+ "snd_ad1816 softc");
+ ad1816->io_rid = 2;
+ ad1816->irq_rid = 0;
+ ad1816->drq1_rid = 0;
+ ad1816->drq2_rid = 1;
+ ad1816->bufsize = pcm_getbuffersize(dev, 4096, DSP_BUFFSIZE, 65536);
+
+ if (!ad1816_alloc_resources(ad1816, dev)) goto no;
+ ad1816_init(ad1816, dev);
+ if (mixer_init(dev, &ad1816mixer_class, ad1816)) goto no;
+
+ snd_setup_intr(dev, ad1816->irq, 0, ad1816_intr, ad1816, &ad1816->ih);
+ if (bus_dma_tag_create(/*parent*/bus_get_dma_tag(dev), /*alignment*/2,
+ /*boundary*/0,
+ /*lowaddr*/BUS_SPACE_MAXADDR_24BIT,
+ /*highaddr*/BUS_SPACE_MAXADDR,
+ /*filter*/NULL, /*filterarg*/NULL,
+ /*maxsize*/ad1816->bufsize, /*nsegments*/1,
+ /*maxsegz*/0x3ffff,
+ /*flags*/0, /*lockfunc*/busdma_lock_mutex,
+ /*lockarg*/ &Giant, &ad1816->parent_dmat) != 0) {
+ device_printf(dev, "unable to create dma tag\n");
+ goto no;
+ }
+ if (ad1816->drq2)
+ snprintf(status2, SND_STATUSLEN, ":%ld", rman_get_start(ad1816->drq2));
+ else
+ status2[0] = '\0';
+
+ snprintf(status, SND_STATUSLEN, "at io 0x%lx irq %ld drq %ld%s bufsz %u %s",
+ rman_get_start(ad1816->io_base),
+ rman_get_start(ad1816->irq),
+ rman_get_start(ad1816->drq1),
+ status2,
+ ad1816->bufsize,
+ PCM_KLDSTRING(snd_ad1816));
+
+ if (pcm_register(dev, ad1816, 1, 1)) goto no;
+ pcm_addchan(dev, PCMDIR_REC, &ad1816chan_class, ad1816);
+ pcm_addchan(dev, PCMDIR_PLAY, &ad1816chan_class, ad1816);
+ pcm_setstatus(dev, status);
-return 0;
+ return 0;
no:
-ad1816_release_resources(ad1816, dev);
+ ad1816_release_resources(ad1816, dev);
-return ENXIO;
+ return ENXIO;
}
static int
ad1816_detach(device_t dev)
{
-int r;
-struct ad1816_info *ad1816;
+ int r;
+ struct ad1816_info *ad1816;
-r = pcm_unregister(dev);
-if (r)
-return r;
-
-ad1816 = pcm_getdevinfo(dev);
-ad1816_release_resources(ad1816, dev);
-return 0;
+ r = pcm_unregister(dev);
+ if (r)
+ return r;
+
+ ad1816 = pcm_getdevinfo(dev);
+ ad1816_release_resources(ad1816, dev);
+ return 0;
}
static device_method_t ad1816_methods[] = {
-/* Device interface */
-DEVMETHOD(device_probe, ad1816_probe),
-DEVMETHOD(device_attach, ad1816_attach),
-DEVMETHOD(device_detach, ad1816_detach),
+ /* Device interface */
+ DEVMETHOD(device_probe, ad1816_probe),
+ DEVMETHOD(device_attach, ad1816_attach),
+ DEVMETHOD(device_detach, ad1816_detach),
-{ 0, 0 }
+ { 0, 0 }
};
static driver_t ad1816_driver = {
-"pcm",
-ad1816_methods,
-PCM_SOFTC_SIZE,
+ "pcm",
+ ad1816_methods,
+ PCM_SOFTC_SIZE,
};
DRIVER_MODULE(snd_ad1816, isa, ad1816_driver, pcm_devclass, 0, 0);
Index: sb.h
===================================================================
RCS file: /home/cvs/src/sys/dev/sound/isa/sb.h,v
retrieving revision 1.2
retrieving revision 1.3
diff -L sys/dev/sound/isa/sb.h -L sys/dev/sound/isa/sb.h -u -r1.2 -r1.3
--- sys/dev/sound/isa/sb.h
+++ sys/dev/sound/isa/sb.h
@@ -1,8 +1,30 @@
-/*
-* file: sbcard.h
-* $MidnightBSD$
-* $FreeBSD: src/sys/dev/sound/isa/sb.h,v 1.15 2004/05/13 11:32:54 truckman Exp $
-*/
+/*-
+ * Copyright (c) 1997,1998 Luigi Rizzo
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD: src/sys/dev/sound/isa/sb.h,v 1.16 2007/02/02 13:33:35 joel Exp $
+ */
#ifndef SB_H
#define SB_H
@@ -13,8 +35,8 @@
void sbc_unlock(struct sbc_softc *);
/*
-* sound blaster registers
-*/
+ * sound blaster registers
+ */
#define SBDSP_RST 0x6
#define DSP_READ 0xA
@@ -33,8 +55,8 @@
#endif
/*
-* DSP Commands. There are many, and in many cases they are used explicitly
-*/
+ * DSP Commands. There are many, and in many cases they are used explicitly
+ */
/* these are not used except for programmed I/O (not in this driver) */
#define DSP_DAC8 0x10 /* direct DAC output */
@@ -54,7 +76,7 @@
/* SBPro commands. Some cards (JAZZ, SMW) also support 16 bits */
-/* prepare for dma input */
+ /* prepare for dma input */
#define DSP_CMD_DMAMODE(stereo, bit16) (0xA0 | (stereo ? 8:0) | (bit16 ? 4:0))
#define DSP_CMD_DAC2 0x16 /* 2-bit adpcm dma out (cont) */
@@ -98,12 +120,12 @@
#endif
/*
-* in fact, for the SB16, dma commands are as follows:
-*
-* cmd, mode, len_low, len_high.
-*
-* cmd is a combination of DSP_DMA16 or DSP_DMA8 and
-*/
+ * in fact, for the SB16, dma commands are as follows:
+ *
+ * cmd, mode, len_low, len_high.
+ *
+ * cmd is a combination of DSP_DMA16 or DSP_DMA8 and
+ */
#define DSP_DMA16 0xb0
#define DSP_DMA8 0xc0
@@ -113,8 +135,8 @@
# define DSP_F16_FIFO_ON 0x02
/*
-* mode is a combination of the following:
-*/
+ * mode is a combination of the following:
+ */
#define DSP_F16_STEREO 0x20
#define DSP_F16_SIGNED 0x10
@@ -128,8 +150,8 @@
#define UART_MIDI 1
/*
-* values used for bd_flags in SoundBlaster driver
-*/
+ * values used for bd_flags in SoundBlaster driver
+ */
#define BD_F_HISPEED 0x0001 /* doing high speed ... */
#if 0
@@ -154,8 +176,8 @@
#define BD_F_DMARUN2 0x4000
/*
-* Mixer registers of SB Pro
-*/
+ * Mixer registers of SB Pro
+ */
#define VOC_VOL 0x04
#define MIC_VOL 0x0A
#define MIC_MIX 0x0A
@@ -171,8 +193,8 @@
#define IRQ_STAT 0x82
/*
-* Additional registers on the SG NX Pro
-*/
+ * Additional registers on the SG NX Pro
+ */
#define COVOX_VOL 0x42
#define TREBLE_LVL 0x44
#define BASS_LVL 0x46
@@ -186,8 +208,8 @@
#define STEREO_DAC 0x02
/*
-* Mixer registers of SB16
-*/
+ * Mixer registers of SB16
+ */
#define SB16_IMASK_L 0x3d
#define SB16_IMASK_R 0x3e
#define SB16_OMASK 0x3c
Index: sb16.c
===================================================================
RCS file: /home/cvs/src/sys/dev/sound/isa/sb16.c,v
retrieving revision 1.2
retrieving revision 1.3
diff -L sys/dev/sound/isa/sb16.c -L sys/dev/sound/isa/sb16.c -u -r1.2 -r1.3
--- sys/dev/sound/isa/sb16.c
+++ sys/dev/sound/isa/sb16.c
@@ -1,33 +1,33 @@
/*-
-* Copyright (c) 1999 Cameron Grant <cg at freebsd.org>
-* Copyright 1997,1998 Luigi Rizzo.
-*
-* Derived from files in the Voxware 3.5 distribution,
-* Copyright by Hannu Savolainen 1994, under the same copyright
-* conditions.
-* All rights reserved.
-*
-* Redistribution and use in source and binary forms, with or without
-* modification, are permitted provided that the following conditions
-* are met:
-* 1. Redistributions of source code must retain the above copyright
-* notice, this list of conditions and the following disclaimer.
-* 2. Redistributions in binary form must reproduce the above copyright
-* notice, this list of conditions and the following disclaimer in the
-* documentation and/or other materials provided with the distribution.
-*
-* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
-* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
-* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
-* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
-* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
-* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
-* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
-* SUCH DAMAGE.
-*/
+ * Copyright (c) 1999 Cameron Grant <cg at freebsd.org>
+ * Copyright (c) 1997,1998 Luigi Rizzo
+ *
+ * Derived from files in the Voxware 3.5 distribution,
+ * Copyright by Hannu Savolainen 1994, under the same copyright
+ * conditions.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
#include <dev/sound/pcm/sound.h>
@@ -38,58 +38,58 @@
#include "mixer_if.h"
-SND_DECLARE_FILE("$MidnightBSD$");
+SND_DECLARE_FILE("$FreeBSD: src/sys/dev/sound/isa/sb16.c,v 1.97 2007/06/17 06:10:40 ariff Exp $");
#define SB16_BUFFSIZE 4096
#define PLAIN_SB16(x) ((((x)->bd_flags) & (BD_F_SB16|BD_F_SB16X)) == BD_F_SB16)
static u_int32_t sb16_fmt8[] = {
-AFMT_U8,
-AFMT_STEREO | AFMT_U8,
-0
+ AFMT_U8,
+ AFMT_STEREO | AFMT_U8,
+ 0
};
static struct pcmchan_caps sb16_caps8 = {5000, 45000, sb16_fmt8, 0};
static u_int32_t sb16_fmt16[] = {
-AFMT_S16_LE,
-AFMT_STEREO | AFMT_S16_LE,
-0
+ AFMT_S16_LE,
+ AFMT_STEREO | AFMT_S16_LE,
+ 0
};
static struct pcmchan_caps sb16_caps16 = {5000, 45000, sb16_fmt16, 0};
static u_int32_t sb16x_fmt[] = {
-AFMT_U8,
-AFMT_STEREO | AFMT_U8,
-AFMT_S16_LE,
-AFMT_STEREO | AFMT_S16_LE,
-0
+ AFMT_U8,
+ AFMT_STEREO | AFMT_U8,
+ AFMT_S16_LE,
+ AFMT_STEREO | AFMT_S16_LE,
+ 0
};
static struct pcmchan_caps sb16x_caps = {5000, 49000, sb16x_fmt, 0};
struct sb_info;
struct sb_chinfo {
-struct sb_info *parent;
-struct pcm_channel *channel;
-struct snd_dbuf *buffer;
-int dir, run, dch;
-u_int32_t fmt, spd, blksz;
+ struct sb_info *parent;
+ struct pcm_channel *channel;
+ struct snd_dbuf *buffer;
+ int dir, run, dch;
+ u_int32_t fmt, spd, blksz;
};
struct sb_info {
-struct resource *io_base; /* I/O address for the board */
-struct resource *irq;
-struct resource *drq1;
-struct resource *drq2;
-void *ih;
-bus_dma_tag_t parent_dmat;
-
-unsigned int bufsize;
-int bd_id;
-u_long bd_flags; /* board-specific flags */
-int prio, prio16;
-struct sb_chinfo pch, rch;
-device_t parent_dev;
+ struct resource *io_base; /* I/O address for the board */
+ struct resource *irq;
+ struct resource *drq1;
+ struct resource *drq2;
+ void *ih;
+ bus_dma_tag_t parent_dmat;
+
+ unsigned int bufsize;
+ int bd_id;
+ u_long bd_flags; /* board-specific flags */
+ int prio, prio16;
+ struct sb_chinfo pch, rch;
+ device_t parent_dev;
};
#if 0
@@ -109,83 +109,83 @@
#endif
/*
-* Common code for the midi and pcm functions
-*
-* sb_cmd write a single byte to the CMD port.
-* sb_cmd1 write a CMD + 1 byte arg
-* sb_cmd2 write a CMD + 2 byte arg
-* sb_get_byte returns a single byte from the DSP data port
-*/
+ * Common code for the midi and pcm functions
+ *
+ * sb_cmd write a single byte to the CMD port.
+ * sb_cmd1 write a CMD + 1 byte arg
+ * sb_cmd2 write a CMD + 2 byte arg
+ * sb_get_byte returns a single byte from the DSP data port
+ */
static void
sb_lock(struct sb_info *sb) {
-sbc_lock(device_get_softc(sb->parent_dev));
+ sbc_lock(device_get_softc(sb->parent_dev));
}
static void
sb_lockassert(struct sb_info *sb) {
-sbc_lockassert(device_get_softc(sb->parent_dev));
+ sbc_lockassert(device_get_softc(sb->parent_dev));
}
static void
sb_unlock(struct sb_info *sb) {
-sbc_unlock(device_get_softc(sb->parent_dev));
+ sbc_unlock(device_get_softc(sb->parent_dev));
}
static int
port_rd(struct resource *port, int off)
{
-return bus_space_read_1(rman_get_bustag(port), rman_get_bushandle(port), off);
+ return bus_space_read_1(rman_get_bustag(port), rman_get_bushandle(port), off);
}
static void
port_wr(struct resource *port, int off, u_int8_t data)
{
-bus_space_write_1(rman_get_bustag(port), rman_get_bushandle(port), off, data);
+ bus_space_write_1(rman_get_bustag(port), rman_get_bushandle(port), off, data);
}
static int
sb_rd(struct sb_info *sb, int reg)
{
-return port_rd(sb->io_base, reg);
+ return port_rd(sb->io_base, reg);
}
static void
sb_wr(struct sb_info *sb, int reg, u_int8_t val)
{
-port_wr(sb->io_base, reg, val);
+ port_wr(sb->io_base, reg, val);
}
static int
sb_dspwr(struct sb_info *sb, u_char val)
{
-int i;
+ int i;
-for (i = 0; i < 1000; i++) {
-if ((sb_rd(sb, SBDSP_STATUS) & 0x80))
-DELAY((i > 100)? 1000 : 10);
-else {
-sb_wr(sb, SBDSP_CMD, val);
-return 1;
-}
-}
+ for (i = 0; i < 1000; i++) {
+ if ((sb_rd(sb, SBDSP_STATUS) & 0x80))
+ DELAY((i > 100)? 1000 : 10);
+ else {
+ sb_wr(sb, SBDSP_CMD, val);
+ return 1;
+ }
+ }
#if __FreeBSD_version > 500000
-if (curthread->td_intr_nesting_level == 0)
-printf("sb_dspwr(0x%02x) timed out.n", val);
+ if (curthread->td_intr_nesting_level == 0)
+ printf("sb_dspwr(0x%02x) timed out.\n", val);
#endif
-return 0;
+ return 0;
}
static int
sb_cmd(struct sb_info *sb, u_char val)
{
#if 0
-printf("sb_cmd: %xn", val);
+ printf("sb_cmd: %x\n", val);
#endif
-return sb_dspwr(sb, val);
+ return sb_dspwr(sb, val);
}
/*
@@ -193,234 +193,234 @@
sb_cmd1(struct sb_info *sb, u_char cmd, int val)
{
#if 0
-printf("sb_cmd1: %x, %xn", cmd, val);
+ printf("sb_cmd1: %x, %x\n", cmd, val);
#endif
-if (sb_dspwr(sb, cmd)) {
-return sb_dspwr(sb, val & 0xff);
-} else return 0;
+ if (sb_dspwr(sb, cmd)) {
+ return sb_dspwr(sb, val & 0xff);
+ } else return 0;
}
*/
static int
sb_cmd2(struct sb_info *sb, u_char cmd, int val)
{
-int r;
+ int r;
#if 0
-printf("sb_cmd2: %x, %xn", cmd, val);
+ printf("sb_cmd2: %x, %x\n", cmd, val);
#endif
-sb_lockassert(sb);
-r = 0;
-if (sb_dspwr(sb, cmd)) {
-if (sb_dspwr(sb, val & 0xff)) {
-if (sb_dspwr(sb, (val >> 8) & 0xff)) {
-r = 1;
-}
-}
-}
+ sb_lockassert(sb);
+ r = 0;
+ if (sb_dspwr(sb, cmd)) {
+ if (sb_dspwr(sb, val & 0xff)) {
+ if (sb_dspwr(sb, (val >> 8) & 0xff)) {
+ r = 1;
+ }
+ }
+ }
-return r;
+ return r;
}
/*
-* in the SB, there is a set of indirect "mixer" registers with
-* address at offset 4, data at offset 5
-*/
+ * in the SB, there is a set of indirect "mixer" registers with
+ * address at offset 4, data at offset 5
+ */
static void
sb_setmixer(struct sb_info *sb, u_int port, u_int value)
{
-sb_lock(sb);
-sb_wr(sb, SB_MIX_ADDR, (u_char) (port & 0xff)); /* Select register */
-DELAY(10);
-sb_wr(sb, SB_MIX_DATA, (u_char) (value & 0xff));
-DELAY(10);
-sb_unlock(sb);
+ sb_lock(sb);
+ sb_wr(sb, SB_MIX_ADDR, (u_char) (port & 0xff)); /* Select register */
+ DELAY(10);
+ sb_wr(sb, SB_MIX_DATA, (u_char) (value & 0xff));
+ DELAY(10);
+ sb_unlock(sb);
}
static int
sb_getmixer(struct sb_info *sb, u_int port)
{
-int val;
+ int val;
-sb_lockassert(sb);
-sb_wr(sb, SB_MIX_ADDR, (u_char) (port & 0xff)); /* Select register */
-DELAY(10);
-val = sb_rd(sb, SB_MIX_DATA);
-DELAY(10);
+ sb_lockassert(sb);
+ sb_wr(sb, SB_MIX_ADDR, (u_char) (port & 0xff)); /* Select register */
+ DELAY(10);
+ val = sb_rd(sb, SB_MIX_DATA);
+ DELAY(10);
-return val;
+ return val;
}
static u_int
sb_get_byte(struct sb_info *sb)
{
-int i;
+ int i;
-for (i = 1000; i > 0; i--) {
-if (sb_rd(sb, DSP_DATA_AVAIL) & 0x80)
-return sb_rd(sb, DSP_READ);
-else
-DELAY(20);
-}
-return 0xffff;
+ for (i = 1000; i > 0; i--) {
+ if (sb_rd(sb, DSP_DATA_AVAIL) & 0x80)
+ return sb_rd(sb, DSP_READ);
+ else
+ DELAY(20);
+ }
+ return 0xffff;
}
static int
sb_reset_dsp(struct sb_info *sb)
{
-u_char b;
+ u_char b;
-sb_lockassert(sb);
-sb_wr(sb, SBDSP_RST, 3);
-DELAY(100);
-sb_wr(sb, SBDSP_RST, 0);
-b = sb_get_byte(sb);
-if (b != 0xAA) {
-DEB(printf("sb_reset_dsp 0x%lx failedn",
-rman_get_start(sb->io_base)));
-return ENXIO; /* Sorry */
-}
-return 0;
+ sb_lockassert(sb);
+ sb_wr(sb, SBDSP_RST, 3);
+ DELAY(100);
+ sb_wr(sb, SBDSP_RST, 0);
+ b = sb_get_byte(sb);
+ if (b != 0xAA) {
+ DEB(printf("sb_reset_dsp 0x%lx failed\n",
+ rman_get_start(sb->io_base)));
+ return ENXIO; /* Sorry */
+ }
+ return 0;
}
/************************************************************/
struct sb16_mixent {
-int reg;
-int bits;
-int ofs;
-int stereo;
+ int reg;
+ int bits;
+ int ofs;
+ int stereo;
};
static const struct sb16_mixent sb16_mixtab[32] = {
-[SOUND_MIXER_VOLUME] = { 0x30, 5, 3, 1 },
-[SOUND_MIXER_PCM] = { 0x32, 5, 3, 1 },
-[SOUND_MIXER_SYNTH] = { 0x34, 5, 3, 1 },
-[SOUND_MIXER_CD] = { 0x36, 5, 3, 1 },
-[SOUND_MIXER_LINE] = { 0x38, 5, 3, 1 },
-[SOUND_MIXER_MIC] = { 0x3a, 5, 3, 0 },
-[SOUND_MIXER_SPEAKER] = { 0x3b, 5, 3, 0 },
-[SOUND_MIXER_IGAIN] = { 0x3f, 2, 6, 1 },
-[SOUND_MIXER_OGAIN] = { 0x41, 2, 6, 1 },
-[SOUND_MIXER_TREBLE] = { 0x44, 4, 4, 1 },
-[SOUND_MIXER_BASS] = { 0x46, 4, 4, 1 },
-[SOUND_MIXER_LINE1] = { 0x52, 5, 3, 1 }
+ [SOUND_MIXER_VOLUME] = { 0x30, 5, 3, 1 },
+ [SOUND_MIXER_PCM] = { 0x32, 5, 3, 1 },
+ [SOUND_MIXER_SYNTH] = { 0x34, 5, 3, 1 },
+ [SOUND_MIXER_CD] = { 0x36, 5, 3, 1 },
+ [SOUND_MIXER_LINE] = { 0x38, 5, 3, 1 },
+ [SOUND_MIXER_MIC] = { 0x3a, 5, 3, 0 },
+ [SOUND_MIXER_SPEAKER] = { 0x3b, 5, 3, 0 },
+ [SOUND_MIXER_IGAIN] = { 0x3f, 2, 6, 1 },
+ [SOUND_MIXER_OGAIN] = { 0x41, 2, 6, 1 },
+ [SOUND_MIXER_TREBLE] = { 0x44, 4, 4, 1 },
+ [SOUND_MIXER_BASS] = { 0x46, 4, 4, 1 },
+ [SOUND_MIXER_LINE1] = { 0x52, 5, 3, 1 }
};
static int
sb16mix_init(struct snd_mixer *m)
{
-struct sb_info *sb = mix_getdevinfo(m);
+ struct sb_info *sb = mix_getdevinfo(m);
-mix_setdevs(m, SOUND_MASK_SYNTH | SOUND_MASK_PCM | SOUND_MASK_SPEAKER |
-SOUND_MASK_LINE | SOUND_MASK_MIC | SOUND_MASK_CD |
-SOUND_MASK_IGAIN | SOUND_MASK_OGAIN | SOUND_MASK_LINE1 |
-SOUND_MASK_VOLUME | SOUND_MASK_BASS | SOUND_MASK_TREBLE);
+ mix_setdevs(m, SOUND_MASK_SYNTH | SOUND_MASK_PCM | SOUND_MASK_SPEAKER |
+ SOUND_MASK_LINE | SOUND_MASK_MIC | SOUND_MASK_CD |
+ SOUND_MASK_IGAIN | SOUND_MASK_OGAIN | SOUND_MASK_LINE1 |
+ SOUND_MASK_VOLUME | SOUND_MASK_BASS | SOUND_MASK_TREBLE);
-mix_setrecdevs(m, SOUND_MASK_SYNTH | SOUND_MASK_LINE |
-SOUND_MASK_LINE1 | SOUND_MASK_MIC | SOUND_MASK_CD);
+ mix_setrecdevs(m, SOUND_MASK_SYNTH | SOUND_MASK_LINE |
+ SOUND_MASK_LINE1 | SOUND_MASK_MIC | SOUND_MASK_CD);
-sb_setmixer(sb, 0x3c, 0x1f); /* make all output active */
+ sb_setmixer(sb, 0x3c, 0x1f); /* make all output active */
-sb_setmixer(sb, 0x3d, 0); /* make all inputs-l off */
-sb_setmixer(sb, 0x3e, 0); /* make all inputs-r off */
+ sb_setmixer(sb, 0x3d, 0); /* make all inputs-l off */
+ sb_setmixer(sb, 0x3e, 0); /* make all inputs-r off */
-return 0;
+ return 0;
}
static int
rel2abs_volume(int x, int max)
{
-int temp;
-
-temp = ((x * max) + 50) / 100;
-if (temp > max)
-temp = max;
-else if (temp < 0)
-temp = 0;
-return (temp);
+ int temp;
+
+ temp = ((x * max) + 50) / 100;
+ if (temp > max)
+ temp = max;
+ else if (temp < 0)
+ temp = 0;
+ return (temp);
}
static int
sb16mix_set(struct snd_mixer *m, unsigned dev, unsigned left, unsigned right)
{
-struct sb_info *sb = mix_getdevinfo(m);
-const struct sb16_mixent *e;
-int max;
-
-e = &sb16_mixtab[dev];
-max = (1 << e->bits) - 1;
-
-left = rel2abs_volume(left, max);
-right = rel2abs_volume(right, max);
-
-sb_setmixer(sb, e->reg, left << e->ofs);
-if (e->stereo)
-sb_setmixer(sb, e->reg + 1, right << e->ofs);
-else
-right = left;
+ struct sb_info *sb = mix_getdevinfo(m);
+ const struct sb16_mixent *e;
+ int max;
+
+ e = &sb16_mixtab[dev];
+ max = (1 << e->bits) - 1;
+
+ left = rel2abs_volume(left, max);
+ right = rel2abs_volume(right, max);
+
+ sb_setmixer(sb, e->reg, left << e->ofs);
+ if (e->stereo)
+ sb_setmixer(sb, e->reg + 1, right << e->ofs);
+ else
+ right = left;
-left = (left * 100) / max;
-right = (right * 100) / max;
+ left = (left * 100) / max;
+ right = (right * 100) / max;
-return left | (right << 8);
+ return left | (right << 8);
}
static int
sb16mix_setrecsrc(struct snd_mixer *m, u_int32_t src)
{
-struct sb_info *sb = mix_getdevinfo(m);
-u_char recdev_l, recdev_r;
+ struct sb_info *sb = mix_getdevinfo(m);
+ u_char recdev_l, recdev_r;
-recdev_l = 0;
-recdev_r = 0;
-if (src & SOUND_MASK_MIC) {
-recdev_l |= 0x01; /* mono mic */
-recdev_r |= 0x01;
-}
-
-if (src & SOUND_MASK_CD) {
-recdev_l |= 0x04; /* l cd */
-recdev_r |= 0x02; /* r cd */
-}
+ recdev_l = 0;
+ recdev_r = 0;
+ if (src & SOUND_MASK_MIC) {
+ recdev_l |= 0x01; /* mono mic */
+ recdev_r |= 0x01;
+ }
+
+ if (src & SOUND_MASK_CD) {
+ recdev_l |= 0x04; /* l cd */
+ recdev_r |= 0x02; /* r cd */
+ }
+
+ if (src & SOUND_MASK_LINE) {
+ recdev_l |= 0x10; /* l line */
+ recdev_r |= 0x08; /* r line */
+ }
+
+ if (src & SOUND_MASK_SYNTH) {
+ recdev_l |= 0x40; /* l midi */
+ recdev_r |= 0x20; /* r midi */
+ }
+
+ sb_setmixer(sb, SB16_IMASK_L, recdev_l);
+ sb_setmixer(sb, SB16_IMASK_R, recdev_r);
+
+ /* Switch on/off FM tuner source */
+ if (src & SOUND_MASK_LINE1)
+ sb_setmixer(sb, 0x4a, 0x0c);
+ else
+ sb_setmixer(sb, 0x4a, 0x00);
+
+ /*
+ * since the same volume controls apply to the input and
+ * output sections, the best approach to have a consistent
+ * behaviour among cards would be to disable the output path
+ * on devices which are used to record.
+ * However, since users like to have feedback, we only disable
+ * the mic -- permanently.
+ */
+ sb_setmixer(sb, SB16_OMASK, 0x1f & ~1);
-if (src & SOUND_MASK_LINE) {
-recdev_l |= 0x10; /* l line */
-recdev_r |= 0x08; /* r line */
-}
-
-if (src & SOUND_MASK_SYNTH) {
-recdev_l |= 0x40; /* l midi */
-recdev_r |= 0x20; /* r midi */
-}
-
-sb_setmixer(sb, SB16_IMASK_L, recdev_l);
-sb_setmixer(sb, SB16_IMASK_R, recdev_r);
-
-/* Switch on/off FM tuner source */
-if (src & SOUND_MASK_LINE1)
-sb_setmixer(sb, 0x4a, 0x0c);
-else
-sb_setmixer(sb, 0x4a, 0x00);
-
-/*
-* since the same volume controls apply to the input and
-* output sections, the best approach to have a consistent
-* behaviour among cards would be to disable the output path
-* on devices which are used to record.
-* However, since users like to have feedback, we only disable
-* the mic -- permanently.
-*/
-sb_setmixer(sb, SB16_OMASK, 0x1f & ~1);
-
-return src;
+ return src;
}
static kobj_method_t sb16mix_mixer_methods[] = {
-KOBJMETHOD(mixer_init, sb16mix_init),
-KOBJMETHOD(mixer_set, sb16mix_set),
-KOBJMETHOD(mixer_setrecsrc, sb16mix_setrecsrc),
-{ 0, 0 }
+ KOBJMETHOD(mixer_init, sb16mix_init),
+ KOBJMETHOD(mixer_set, sb16mix_set),
+ KOBJMETHOD(mixer_setrecsrc, sb16mix_setrecsrc),
+ { 0, 0 }
};
MIXER_DECLARE(sb16mix_mixer);
@@ -429,355 +429,355 @@
static void
sb16_release_resources(struct sb_info *sb, device_t dev)
{
-if (sb->irq) {
-if (sb->ih)
-bus_teardown_intr(dev, sb->irq, sb->ih);
-bus_release_resource(dev, SYS_RES_IRQ, 0, sb->irq);
-sb->irq = 0;
-}
-if (sb->drq2) {
-if (sb->drq2 != sb->drq1) {
-isa_dma_release(rman_get_start(sb->drq2));
-bus_release_resource(dev, SYS_RES_DRQ, 1, sb->drq2);
-}
-sb->drq2 = 0;
-}
-if (sb->drq1) {
-isa_dma_release(rman_get_start(sb->drq1));
-bus_release_resource(dev, SYS_RES_DRQ, 0, sb->drq1);
-sb->drq1 = 0;
-}
-if (sb->io_base) {
-bus_release_resource(dev, SYS_RES_IOPORT, 0, sb->io_base);
-sb->io_base = 0;
-}
-if (sb->parent_dmat) {
-bus_dma_tag_destroy(sb->parent_dmat);
-sb->parent_dmat = 0;
-}
-free(sb, M_DEVBUF);
+ if (sb->irq) {
+ if (sb->ih)
+ bus_teardown_intr(dev, sb->irq, sb->ih);
+ bus_release_resource(dev, SYS_RES_IRQ, 0, sb->irq);
+ sb->irq = 0;
+ }
+ if (sb->drq2) {
+ if (sb->drq2 != sb->drq1) {
+ isa_dma_release(rman_get_start(sb->drq2));
+ bus_release_resource(dev, SYS_RES_DRQ, 1, sb->drq2);
+ }
+ sb->drq2 = 0;
+ }
+ if (sb->drq1) {
+ isa_dma_release(rman_get_start(sb->drq1));
+ bus_release_resource(dev, SYS_RES_DRQ, 0, sb->drq1);
+ sb->drq1 = 0;
+ }
+ if (sb->io_base) {
+ bus_release_resource(dev, SYS_RES_IOPORT, 0, sb->io_base);
+ sb->io_base = 0;
+ }
+ if (sb->parent_dmat) {
+ bus_dma_tag_destroy(sb->parent_dmat);
+ sb->parent_dmat = 0;
+ }
+ free(sb, M_DEVBUF);
}
static int
sb16_alloc_resources(struct sb_info *sb, device_t dev)
{
-int rid;
+ int rid;
-rid = 0;
-if (!sb->io_base)
-sb->io_base = bus_alloc_resource_any(dev, SYS_RES_IOPORT,
-&rid, RF_ACTIVE);
-
-rid = 0;
-if (!sb->irq)
-sb->irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid,
-RF_ACTIVE);
-
-rid = 0;
-if (!sb->drq1)
-sb->drq1 = bus_alloc_resource_any(dev, SYS_RES_DRQ, &rid,
-RF_ACTIVE);
-
-rid = 1;
-if (!sb->drq2)
-sb->drq2 = bus_alloc_resource_any(dev, SYS_RES_DRQ, &rid,
-RF_ACTIVE);
-
-if (sb->io_base && sb->drq1 && sb->irq) {
-isa_dma_acquire(rman_get_start(sb->drq1));
-isa_dmainit(rman_get_start(sb->drq1), sb->bufsize);
-
-if (sb->drq2) {
-isa_dma_acquire(rman_get_start(sb->drq2));
-isa_dmainit(rman_get_start(sb->drq2), sb->bufsize);
-} else {
-sb->drq2 = sb->drq1;
-pcm_setflags(dev, pcm_getflags(dev) | SD_F_SIMPLEX);
-}
-return 0;
-} else return ENXIO;
+ rid = 0;
+ if (!sb->io_base)
+ sb->io_base = bus_alloc_resource_any(dev, SYS_RES_IOPORT,
+ &rid, RF_ACTIVE);
+
+ rid = 0;
+ if (!sb->irq)
+ sb->irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid,
+ RF_ACTIVE);
+
+ rid = 0;
+ if (!sb->drq1)
+ sb->drq1 = bus_alloc_resource_any(dev, SYS_RES_DRQ, &rid,
+ RF_ACTIVE);
+
+ rid = 1;
+ if (!sb->drq2)
+ sb->drq2 = bus_alloc_resource_any(dev, SYS_RES_DRQ, &rid,
+ RF_ACTIVE);
+
+ if (sb->io_base && sb->drq1 && sb->irq) {
+ isa_dma_acquire(rman_get_start(sb->drq1));
+ isa_dmainit(rman_get_start(sb->drq1), sb->bufsize);
+
+ if (sb->drq2) {
+ isa_dma_acquire(rman_get_start(sb->drq2));
+ isa_dmainit(rman_get_start(sb->drq2), sb->bufsize);
+ } else {
+ sb->drq2 = sb->drq1;
+ pcm_setflags(dev, pcm_getflags(dev) | SD_F_SIMPLEX);
+ }
+ return 0;
+ } else return ENXIO;
}
/* sbc does locking for us */
static void
sb_intr(void *arg)
{
-struct sb_info *sb = (struct sb_info *)arg;
-int reason, c;
-
-/*
-* The Vibra16X has separate flags for 8 and 16 bit transfers, but
-* I have no idea how to tell capture from playback interrupts...
-*/
+ struct sb_info *sb = (struct sb_info *)arg;
+ int reason, c;
-reason = 0;
-sb_lock(sb);
-c = sb_getmixer(sb, IRQ_STAT);
-if (c & 1)
-sb_rd(sb, DSP_DATA_AVAIL); /* 8-bit int ack */
-
-if (c & 2)
-sb_rd(sb, DSP_DATA_AVL16); /* 16-bit int ack */
-sb_unlock(sb);
-
-/*
-* this tells us if the source is 8-bit or 16-bit dma. We
-* have to check the io channel to map it to read or write...
-*/
-
-if (sb->bd_flags & BD_F_SB16X) {
-if (c & 1) { /* 8-bit format */
-if (sb->pch.fmt & AFMT_8BIT)
-reason |= 1;
-if (sb->rch.fmt & AFMT_8BIT)
-reason |= 2;
-}
-if (c & 2) { /* 16-bit format */
-if (sb->pch.fmt & AFMT_16BIT)
-reason |= 1;
-if (sb->rch.fmt & AFMT_16BIT)
-reason |= 2;
-}
-} else {
-if (c & 1) { /* 8-bit dma */
-if (sb->pch.dch == 1)
-reason |= 1;
-if (sb->rch.dch == 1)
-reason |= 2;
-}
-if (c & 2) { /* 16-bit dma */
-if (sb->pch.dch == 2)
-reason |= 1;
-if (sb->rch.dch == 2)
-reason |= 2;
-}
-}
+ /*
+ * The Vibra16X has separate flags for 8 and 16 bit transfers, but
+ * I have no idea how to tell capture from playback interrupts...
+ */
+
+ reason = 0;
+ sb_lock(sb);
+ c = sb_getmixer(sb, IRQ_STAT);
+ if (c & 1)
+ sb_rd(sb, DSP_DATA_AVAIL); /* 8-bit int ack */
+
+ if (c & 2)
+ sb_rd(sb, DSP_DATA_AVL16); /* 16-bit int ack */
+ sb_unlock(sb);
+
+ /*
+ * this tells us if the source is 8-bit or 16-bit dma. We
+ * have to check the io channel to map it to read or write...
+ */
+
+ if (sb->bd_flags & BD_F_SB16X) {
+ if (c & 1) { /* 8-bit format */
+ if (sb->pch.fmt & AFMT_8BIT)
+ reason |= 1;
+ if (sb->rch.fmt & AFMT_8BIT)
+ reason |= 2;
+ }
+ if (c & 2) { /* 16-bit format */
+ if (sb->pch.fmt & AFMT_16BIT)
+ reason |= 1;
+ if (sb->rch.fmt & AFMT_16BIT)
+ reason |= 2;
+ }
+ } else {
+ if (c & 1) { /* 8-bit dma */
+ if (sb->pch.dch == 1)
+ reason |= 1;
+ if (sb->rch.dch == 1)
+ reason |= 2;
+ }
+ if (c & 2) { /* 16-bit dma */
+ if (sb->pch.dch == 2)
+ reason |= 1;
+ if (sb->rch.dch == 2)
+ reason |= 2;
+ }
+ }
#if 0
-printf("sb_intr: reason=%d c=0x%xn", reason, c);
+ printf("sb_intr: reason=%d c=0x%x\n", reason, c);
#endif
-if ((reason & 1) && (sb->pch.run))
-chn_intr(sb->pch.channel);
+ if ((reason & 1) && (sb->pch.run))
+ chn_intr(sb->pch.channel);
-if ((reason & 2) && (sb->rch.run))
-chn_intr(sb->rch.channel);
+ if ((reason & 2) && (sb->rch.run))
+ chn_intr(sb->rch.channel);
}
static int
sb_setup(struct sb_info *sb)
{
-struct sb_chinfo *ch;
-u_int8_t v;
-int l, pprio;
-
-sb_lock(sb);
-if (sb->bd_flags & BD_F_DMARUN)
-sndbuf_dma(sb->pch.buffer, PCMTRIG_STOP);
-if (sb->bd_flags & BD_F_DMARUN2)
-sndbuf_dma(sb->rch.buffer, PCMTRIG_STOP);
-sb->bd_flags &= ~(BD_F_DMARUN | BD_F_DMARUN2);
-
-sb_reset_dsp(sb);
-
-if (sb->bd_flags & BD_F_SB16X) {
-/* full-duplex doesn't work! */
-pprio = sb->pch.run? 1 : 0;
-sndbuf_dmasetup(sb->pch.buffer, pprio? sb->drq1 : sb->drq2);
-sb->pch.dch = pprio? 1 : 0;
-sndbuf_dmasetup(sb->rch.buffer, pprio? sb->drq2 : sb->drq1);
-sb->rch.dch = pprio? 2 : 1;
-} else {
-if (sb->pch.run && sb->rch.run) {
-pprio = (sb->rch.fmt & AFMT_16BIT)? 0 : 1;
-sndbuf_dmasetup(sb->pch.buffer, pprio? sb->drq2 : sb->drq1);
-sb->pch.dch = pprio? 2 : 1;
-sndbuf_dmasetup(sb->rch.buffer, pprio? sb->drq1 : sb->drq2);
-sb->rch.dch = pprio? 1 : 2;
-} else {
-if (sb->pch.run) {
-sndbuf_dmasetup(sb->pch.buffer, (sb->pch.fmt & AFMT_16BIT)? sb->drq2 : sb->drq1);
-sb->pch.dch = (sb->pch.fmt & AFMT_16BIT)? 2 : 1;
-sndbuf_dmasetup(sb->rch.buffer, (sb->pch.fmt & AFMT_16BIT)? sb->drq1 : sb->drq2);
-sb->rch.dch = (sb->pch.fmt & AFMT_16BIT)? 1 : 2;
-} else if (sb->rch.run) {
-sndbuf_dmasetup(sb->pch.buffer, (sb->rch.fmt & AFMT_16BIT)? sb->drq1 : sb->drq2);
-sb->pch.dch = (sb->rch.fmt & AFMT_16BIT)? 1 : 2;
-sndbuf_dmasetup(sb->rch.buffer, (sb->rch.fmt & AFMT_16BIT)? sb->drq2 : sb->drq1);
-sb->rch.dch = (sb->rch.fmt & AFMT_16BIT)? 2 : 1;
-}
-}
-}
-
-sndbuf_dmasetdir(sb->pch.buffer, PCMDIR_PLAY);
-sndbuf_dmasetdir(sb->rch.buffer, PCMDIR_REC);
-
-/*
-printf("setup: [pch = %d, pfmt = %d, pgo = %d] [rch = %d, rfmt = %d, rgo = %d]n",
-sb->pch.dch, sb->pch.fmt, sb->pch.run, sb->rch.dch, sb->rch.fmt, sb->rch.run);
-*/
-
-ch = &sb->pch;
-if (ch->run) {
-l = ch->blksz;
-if (ch->fmt & AFMT_16BIT)
-l >>= 1;
-l--;
-
-/* play speed */
-RANGE(ch->spd, 5000, 45000);
-sb_cmd(sb, DSP_CMD_OUT16);
-sb_cmd(sb, ch->spd >> 8);
-sb_cmd(sb, ch->spd & 0xff);
-
-/* play format, length */
-v = DSP_F16_AUTO | DSP_F16_FIFO_ON | DSP_F16_DAC;
-v |= (ch->fmt & AFMT_16BIT)? DSP_DMA16 : DSP_DMA8;
-sb_cmd(sb, v);
-
-v = (ch->fmt & AFMT_STEREO)? DSP_F16_STEREO : 0;
-v |= (ch->fmt & AFMT_SIGNED)? DSP_F16_SIGNED : 0;
-sb_cmd2(sb, v, l);
-sndbuf_dma(ch->buffer, PCMTRIG_START);
-sb->bd_flags |= BD_F_DMARUN;
-}
-
-ch = &sb->rch;
-if (ch->run) {
-l = ch->blksz;
-if (ch->fmt & AFMT_16BIT)
-l >>= 1;
-l--;
-
-/* record speed */
-RANGE(ch->spd, 5000, 45000);
-sb_cmd(sb, DSP_CMD_IN16);
-sb_cmd(sb, ch->spd >> 8);
-sb_cmd(sb, ch->spd & 0xff);
-
-/* record format, length */
-v = DSP_F16_AUTO | DSP_F16_FIFO_ON | DSP_F16_ADC;
-v |= (ch->fmt & AFMT_16BIT)? DSP_DMA16 : DSP_DMA8;
-sb_cmd(sb, v);
-
-v = (ch->fmt & AFMT_STEREO)? DSP_F16_STEREO : 0;
-v |= (ch->fmt & AFMT_SIGNED)? DSP_F16_SIGNED : 0;
-sb_cmd2(sb, v, l);
-sndbuf_dma(ch->buffer, PCMTRIG_START);
-sb->bd_flags |= BD_F_DMARUN2;
-}
-sb_unlock(sb);
+ struct sb_chinfo *ch;
+ u_int8_t v;
+ int l, pprio;
+
+ sb_lock(sb);
+ if (sb->bd_flags & BD_F_DMARUN)
+ sndbuf_dma(sb->pch.buffer, PCMTRIG_STOP);
+ if (sb->bd_flags & BD_F_DMARUN2)
+ sndbuf_dma(sb->rch.buffer, PCMTRIG_STOP);
+ sb->bd_flags &= ~(BD_F_DMARUN | BD_F_DMARUN2);
+
+ sb_reset_dsp(sb);
+
+ if (sb->bd_flags & BD_F_SB16X) {
+ /* full-duplex doesn't work! */
+ pprio = sb->pch.run? 1 : 0;
+ sndbuf_dmasetup(sb->pch.buffer, pprio? sb->drq1 : sb->drq2);
+ sb->pch.dch = pprio? 1 : 0;
+ sndbuf_dmasetup(sb->rch.buffer, pprio? sb->drq2 : sb->drq1);
+ sb->rch.dch = pprio? 2 : 1;
+ } else {
+ if (sb->pch.run && sb->rch.run) {
+ pprio = (sb->rch.fmt & AFMT_16BIT)? 0 : 1;
+ sndbuf_dmasetup(sb->pch.buffer, pprio? sb->drq2 : sb->drq1);
+ sb->pch.dch = pprio? 2 : 1;
+ sndbuf_dmasetup(sb->rch.buffer, pprio? sb->drq1 : sb->drq2);
+ sb->rch.dch = pprio? 1 : 2;
+ } else {
+ if (sb->pch.run) {
+ sndbuf_dmasetup(sb->pch.buffer, (sb->pch.fmt & AFMT_16BIT)? sb->drq2 : sb->drq1);
+ sb->pch.dch = (sb->pch.fmt & AFMT_16BIT)? 2 : 1;
+ sndbuf_dmasetup(sb->rch.buffer, (sb->pch.fmt & AFMT_16BIT)? sb->drq1 : sb->drq2);
+ sb->rch.dch = (sb->pch.fmt & AFMT_16BIT)? 1 : 2;
+ } else if (sb->rch.run) {
+ sndbuf_dmasetup(sb->pch.buffer, (sb->rch.fmt & AFMT_16BIT)? sb->drq1 : sb->drq2);
+ sb->pch.dch = (sb->rch.fmt & AFMT_16BIT)? 1 : 2;
+ sndbuf_dmasetup(sb->rch.buffer, (sb->rch.fmt & AFMT_16BIT)? sb->drq2 : sb->drq1);
+ sb->rch.dch = (sb->rch.fmt & AFMT_16BIT)? 2 : 1;
+ }
+ }
+ }
+
+ sndbuf_dmasetdir(sb->pch.buffer, PCMDIR_PLAY);
+ sndbuf_dmasetdir(sb->rch.buffer, PCMDIR_REC);
+
+ /*
+ printf("setup: [pch = %d, pfmt = %d, pgo = %d] [rch = %d, rfmt = %d, rgo = %d]\n",
+ sb->pch.dch, sb->pch.fmt, sb->pch.run, sb->rch.dch, sb->rch.fmt, sb->rch.run);
+ */
+
+ ch = &sb->pch;
+ if (ch->run) {
+ l = ch->blksz;
+ if (ch->fmt & AFMT_16BIT)
+ l >>= 1;
+ l--;
+
+ /* play speed */
+ RANGE(ch->spd, 5000, 45000);
+ sb_cmd(sb, DSP_CMD_OUT16);
+ sb_cmd(sb, ch->spd >> 8);
+ sb_cmd(sb, ch->spd & 0xff);
+
+ /* play format, length */
+ v = DSP_F16_AUTO | DSP_F16_FIFO_ON | DSP_F16_DAC;
+ v |= (ch->fmt & AFMT_16BIT)? DSP_DMA16 : DSP_DMA8;
+ sb_cmd(sb, v);
+
+ v = (ch->fmt & AFMT_STEREO)? DSP_F16_STEREO : 0;
+ v |= (ch->fmt & AFMT_SIGNED)? DSP_F16_SIGNED : 0;
+ sb_cmd2(sb, v, l);
+ sndbuf_dma(ch->buffer, PCMTRIG_START);
+ sb->bd_flags |= BD_F_DMARUN;
+ }
+
+ ch = &sb->rch;
+ if (ch->run) {
+ l = ch->blksz;
+ if (ch->fmt & AFMT_16BIT)
+ l >>= 1;
+ l--;
+
+ /* record speed */
+ RANGE(ch->spd, 5000, 45000);
+ sb_cmd(sb, DSP_CMD_IN16);
+ sb_cmd(sb, ch->spd >> 8);
+ sb_cmd(sb, ch->spd & 0xff);
+
+ /* record format, length */
+ v = DSP_F16_AUTO | DSP_F16_FIFO_ON | DSP_F16_ADC;
+ v |= (ch->fmt & AFMT_16BIT)? DSP_DMA16 : DSP_DMA8;
+ sb_cmd(sb, v);
+
+ v = (ch->fmt & AFMT_STEREO)? DSP_F16_STEREO : 0;
+ v |= (ch->fmt & AFMT_SIGNED)? DSP_F16_SIGNED : 0;
+ sb_cmd2(sb, v, l);
+ sndbuf_dma(ch->buffer, PCMTRIG_START);
+ sb->bd_flags |= BD_F_DMARUN2;
+ }
+ sb_unlock(sb);
-return 0;
+ return 0;
}
/* channel interface */
static void *
sb16chan_init(kobj_t obj, void *devinfo, struct snd_dbuf *b, struct pcm_channel *c, int dir)
{
-struct sb_info *sb = devinfo;
-struct sb_chinfo *ch = (dir == PCMDIR_PLAY)? &sb->pch : &sb->rch;
+ struct sb_info *sb = devinfo;
+ struct sb_chinfo *ch = (dir == PCMDIR_PLAY)? &sb->pch : &sb->rch;
-ch->parent = sb;
-ch->channel = c;
-ch->buffer = b;
-ch->dir = dir;
+ ch->parent = sb;
+ ch->channel = c;
+ ch->buffer = b;
+ ch->dir = dir;
-if (sndbuf_alloc(ch->buffer, sb->parent_dmat, sb->bufsize) != 0)
-return NULL;
+ if (sndbuf_alloc(ch->buffer, sb->parent_dmat, 0, sb->bufsize) != 0)
+ return NULL;
-return ch;
+ return ch;
}
static int
sb16chan_setformat(kobj_t obj, void *data, u_int32_t format)
{
-struct sb_chinfo *ch = data;
-struct sb_info *sb = ch->parent;
+ struct sb_chinfo *ch = data;
+ struct sb_info *sb = ch->parent;
-ch->fmt = format;
-sb->prio = ch->dir;
-sb->prio16 = (ch->fmt & AFMT_16BIT)? 1 : 0;
+ ch->fmt = format;
+ sb->prio = ch->dir;
+ sb->prio16 = (ch->fmt & AFMT_16BIT)? 1 : 0;
-return 0;
+ return 0;
}
static int
sb16chan_setspeed(kobj_t obj, void *data, u_int32_t speed)
{
-struct sb_chinfo *ch = data;
+ struct sb_chinfo *ch = data;
-ch->spd = speed;
-return speed;
+ ch->spd = speed;
+ return speed;
}
static int
sb16chan_setblocksize(kobj_t obj, void *data, u_int32_t blocksize)
{
-struct sb_chinfo *ch = data;
+ struct sb_chinfo *ch = data;
-ch->blksz = blocksize;
-return ch->blksz;
+ ch->blksz = blocksize;
+ return ch->blksz;
}
static int
sb16chan_trigger(kobj_t obj, void *data, int go)
{
-struct sb_chinfo *ch = data;
-struct sb_info *sb = ch->parent;
+ struct sb_chinfo *ch = data;
+ struct sb_info *sb = ch->parent;
-if (go == PCMTRIG_EMLDMAWR || go == PCMTRIG_EMLDMARD)
-return 0;
+ if (!PCMTRIG_COMMON(go))
+ return 0;
-if (go == PCMTRIG_START)
-ch->run = 1;
-else
-ch->run = 0;
+ if (go == PCMTRIG_START)
+ ch->run = 1;
+ else
+ ch->run = 0;
-sb_setup(sb);
+ sb_setup(sb);
-return 0;
+ return 0;
}
static int
sb16chan_getptr(kobj_t obj, void *data)
{
-struct sb_chinfo *ch = data;
+ struct sb_chinfo *ch = data;
-return sndbuf_dmaptr(ch->buffer);
+ return sndbuf_dmaptr(ch->buffer);
}
static struct pcmchan_caps *
sb16chan_getcaps(kobj_t obj, void *data)
{
-struct sb_chinfo *ch = data;
-struct sb_info *sb = ch->parent;
+ struct sb_chinfo *ch = data;
+ struct sb_info *sb = ch->parent;
-if ((sb->prio == 0) || (sb->prio == ch->dir))
-return &sb16x_caps;
-else
-return sb->prio16? &sb16_caps8 : &sb16_caps16;
+ if ((sb->prio == 0) || (sb->prio == ch->dir))
+ return &sb16x_caps;
+ else
+ return sb->prio16? &sb16_caps8 : &sb16_caps16;
}
static int
sb16chan_resetdone(kobj_t obj, void *data)
{
-struct sb_chinfo *ch = data;
-struct sb_info *sb = ch->parent;
+ struct sb_chinfo *ch = data;
+ struct sb_info *sb = ch->parent;
-sb->prio = 0;
+ sb->prio = 0;
-return 0;
+ return 0;
}
static kobj_method_t sb16chan_methods[] = {
-KOBJMETHOD(channel_init, sb16chan_init),
-KOBJMETHOD(channel_resetdone, sb16chan_resetdone),
-KOBJMETHOD(channel_setformat, sb16chan_setformat),
-KOBJMETHOD(channel_setspeed, sb16chan_setspeed),
-KOBJMETHOD(channel_setblocksize, sb16chan_setblocksize),
-KOBJMETHOD(channel_trigger, sb16chan_trigger),
-KOBJMETHOD(channel_getptr, sb16chan_getptr),
-KOBJMETHOD(channel_getcaps, sb16chan_getcaps),
-{ 0, 0 }
+ KOBJMETHOD(channel_init, sb16chan_init),
+ KOBJMETHOD(channel_resetdone, sb16chan_resetdone),
+ KOBJMETHOD(channel_setformat, sb16chan_setformat),
+ KOBJMETHOD(channel_setspeed, sb16chan_setspeed),
+ KOBJMETHOD(channel_setblocksize, sb16chan_setblocksize),
+ KOBJMETHOD(channel_trigger, sb16chan_trigger),
+ KOBJMETHOD(channel_getptr, sb16chan_getptr),
+ KOBJMETHOD(channel_getcaps, sb16chan_getcaps),
+ { 0, 0 }
};
CHANNEL_DECLARE(sb16chan);
@@ -786,125 +786,123 @@
static int
sb16_probe(device_t dev)
{
-char buf[64];
-uintptr_t func, ver, r, f;
+ char buf[64];
+ uintptr_t func, ver, r, f;
-/* The parent device has already been probed. */
-r = BUS_READ_IVAR(device_get_parent(dev), dev, 0, &func);
-if (func != SCF_PCM)
-return (ENXIO);
-
-r = BUS_READ_IVAR(device_get_parent(dev), dev, 1, &ver);
-f = (ver & 0xffff0000) >> 16;
-ver &= 0x0000ffff;
-if (f & BD_F_SB16) {
-snprintf(buf, sizeof buf, "SB16 DSP %d.%02d%s", (int) ver >> 8, (int) ver & 0xff,
-(f & BD_F_SB16X)? " (ViBRA16X)" : "");
-device_set_desc_copy(dev, buf);
-return 0;
-} else
-return (ENXIO);
+ /* The parent device has already been probed. */
+ r = BUS_READ_IVAR(device_get_parent(dev), dev, 0, &func);
+ if (func != SCF_PCM)
+ return (ENXIO);
+
+ r = BUS_READ_IVAR(device_get_parent(dev), dev, 1, &ver);
+ f = (ver & 0xffff0000) >> 16;
+ ver &= 0x0000ffff;
+ if (f & BD_F_SB16) {
+ snprintf(buf, sizeof buf, "SB16 DSP %d.%02d%s", (int) ver >> 8, (int) ver & 0xff,
+ (f & BD_F_SB16X)? " (ViBRA16X)" : "");
+ device_set_desc_copy(dev, buf);
+ return 0;
+ } else
+ return (ENXIO);
}
static int
sb16_attach(device_t dev)
{
-struct sb_info *sb;
-uintptr_t ver;
-char status[SND_STATUSLEN], status2[SND_STATUSLEN];
-
-sb = (struct sb_info *)malloc(sizeof *sb, M_DEVBUF, M_NOWAIT | M_ZERO);
-if (!sb)
-return ENXIO;
-
-sb->parent_dev = device_get_parent(dev);
-BUS_READ_IVAR(sb->parent_dev, dev, 1, &ver);
-sb->bd_id = ver & 0x0000ffff;
-sb->bd_flags = (ver & 0xffff0000) >> 16;
-sb->bufsize = pcm_getbuffersize(dev, 4096, SB16_BUFFSIZE, 65536);
-
-if (sb16_alloc_resources(sb, dev))
-goto no;
-sb_lock(sb);
-if (sb_reset_dsp(sb)) {
-sb_unlock(sb);
-goto no;
-}
-sb_unlock(sb);
-if (mixer_init(dev, &sb16mix_mixer_class, sb))
-goto no;
-if (snd_setup_intr(dev, sb->irq, 0, sb_intr, sb, &sb->ih))
-goto no;
-
-if (sb->bd_flags & BD_F_SB16X)
-pcm_setflags(dev, pcm_getflags(dev) | SD_F_SIMPLEX);
-
-sb->prio = 0;
-
-if (bus_dma_tag_create(/*parent*/NULL, /*alignment*/2, /*boundary*/0,
-/*lowaddr*/BUS_SPACE_MAXADDR_24BIT,
-/*highaddr*/BUS_SPACE_MAXADDR,
-/*filter*/NULL, /*filterarg*/NULL,
-/*maxsize*/sb->bufsize, /*nsegments*/1,
-/*maxsegz*/0x3ffff, /*flags*/0,
-/*lockfunc*/busdma_lock_mutex, /*lockarg*/&Giant,
-&sb->parent_dmat) != 0) {
-device_printf(dev, "unable to create dma tagn");
-goto no;
-}
-
-if (!(pcm_getflags(dev) & SD_F_SIMPLEX))
-snprintf(status2, SND_STATUSLEN, ":%ld", rman_get_start(sb->drq2));
-else
-status2[0] = '0';
-
-snprintf(status, SND_STATUSLEN, "at io 0x%lx irq %ld drq %ld%s bufsz %u %s",
-rman_get_start(sb->io_base), rman_get_start(sb->irq),
-rman_get_start(sb->drq1), status2, sb->bufsize,
-PCM_KLDSTRING(snd_sb16));
-
-if (pcm_register(dev, sb, 1, 1))
-goto no;
-pcm_addchan(dev, PCMDIR_REC, &sb16chan_class, sb);
-pcm_addchan(dev, PCMDIR_PLAY, &sb16chan_class, sb);
+ struct sb_info *sb;
+ uintptr_t ver;
+ char status[SND_STATUSLEN], status2[SND_STATUSLEN];
+
+ sb = malloc(sizeof(*sb), M_DEVBUF, M_WAITOK | M_ZERO);
+ sb->parent_dev = device_get_parent(dev);
+ BUS_READ_IVAR(sb->parent_dev, dev, 1, &ver);
+ sb->bd_id = ver & 0x0000ffff;
+ sb->bd_flags = (ver & 0xffff0000) >> 16;
+ sb->bufsize = pcm_getbuffersize(dev, 4096, SB16_BUFFSIZE, 65536);
+
+ if (sb16_alloc_resources(sb, dev))
+ goto no;
+ sb_lock(sb);
+ if (sb_reset_dsp(sb)) {
+ sb_unlock(sb);
+ goto no;
+ }
+ sb_unlock(sb);
+ if (mixer_init(dev, &sb16mix_mixer_class, sb))
+ goto no;
+ if (snd_setup_intr(dev, sb->irq, 0, sb_intr, sb, &sb->ih))
+ goto no;
+
+ if (sb->bd_flags & BD_F_SB16X)
+ pcm_setflags(dev, pcm_getflags(dev) | SD_F_SIMPLEX);
+
+ sb->prio = 0;
+
+ if (bus_dma_tag_create(/*parent*/bus_get_dma_tag(dev), /*alignment*/2,
+ /*boundary*/0,
+ /*lowaddr*/BUS_SPACE_MAXADDR_24BIT,
+ /*highaddr*/BUS_SPACE_MAXADDR,
+ /*filter*/NULL, /*filterarg*/NULL,
+ /*maxsize*/sb->bufsize, /*nsegments*/1,
+ /*maxsegz*/0x3ffff, /*flags*/0,
+ /*lockfunc*/busdma_lock_mutex, /*lockarg*/&Giant,
+ &sb->parent_dmat) != 0) {
+ device_printf(dev, "unable to create dma tag\n");
+ goto no;
+ }
+
+ if (!(pcm_getflags(dev) & SD_F_SIMPLEX))
+ snprintf(status2, SND_STATUSLEN, ":%ld", rman_get_start(sb->drq2));
+ else
+ status2[0] = '\0';
+
+ snprintf(status, SND_STATUSLEN, "at io 0x%lx irq %ld drq %ld%s bufsz %u %s",
+ rman_get_start(sb->io_base), rman_get_start(sb->irq),
+ rman_get_start(sb->drq1), status2, sb->bufsize,
+ PCM_KLDSTRING(snd_sb16));
+
+ if (pcm_register(dev, sb, 1, 1))
+ goto no;
+ pcm_addchan(dev, PCMDIR_REC, &sb16chan_class, sb);
+ pcm_addchan(dev, PCMDIR_PLAY, &sb16chan_class, sb);
-pcm_setstatus(dev, status);
+ pcm_setstatus(dev, status);
-return 0;
+ return 0;
no:
-sb16_release_resources(sb, dev);
-return ENXIO;
+ sb16_release_resources(sb, dev);
+ return ENXIO;
}
static int
sb16_detach(device_t dev)
{
-int r;
-struct sb_info *sb;
+ int r;
+ struct sb_info *sb;
-r = pcm_unregister(dev);
-if (r)
-return r;
-
-sb = pcm_getdevinfo(dev);
-sb16_release_resources(sb, dev);
-return 0;
+ r = pcm_unregister(dev);
+ if (r)
+ return r;
+
+ sb = pcm_getdevinfo(dev);
+ sb16_release_resources(sb, dev);
+ return 0;
}
static device_method_t sb16_methods[] = {
-/* Device interface */
-DEVMETHOD(device_probe, sb16_probe),
-DEVMETHOD(device_attach, sb16_attach),
-DEVMETHOD(device_detach, sb16_detach),
+ /* Device interface */
+ DEVMETHOD(device_probe, sb16_probe),
+ DEVMETHOD(device_attach, sb16_attach),
+ DEVMETHOD(device_detach, sb16_detach),
-{ 0, 0 }
+ { 0, 0 }
};
static driver_t sb16_driver = {
-"pcm",
-sb16_methods,
-PCM_SOFTC_SIZE,
+ "pcm",
+ sb16_methods,
+ PCM_SOFTC_SIZE,
};
DRIVER_MODULE(snd_sb16, sbc, sb16_driver, pcm_devclass, 0, 0);
Index: sndbuf_dma.c
===================================================================
RCS file: /home/cvs/src/sys/dev/sound/isa/sndbuf_dma.c,v
retrieving revision 1.2
retrieving revision 1.3
diff -L sys/dev/sound/isa/sndbuf_dma.c -L sys/dev/sound/isa/sndbuf_dma.c -u -r1.2 -r1.3
--- sys/dev/sound/isa/sndbuf_dma.c
+++ sys/dev/sound/isa/sndbuf_dma.c
@@ -1,103 +1,103 @@
/*-
-* Copyright (c) 1999 Cameron Grant <cg at freebsd.org>
-* All rights reserved.
-*
-* Redistribution and use in source and binary forms, with or without
-* modification, are permitted provided that the following conditions
-* are met:
-* 1. Redistributions of source code must retain the above copyright
-* notice, this list of conditions and the following disclaimer.
-* 2. Redistributions in binary form must reproduce the above copyright
-* notice, this list of conditions and the following disclaimer in the
-* documentation and/or other materials provided with the distribution.
-*
-* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
-* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
-* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
-* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
-* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
-* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
-* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
-* SUCH DAMAGE.
-*/
+ * Copyright (c) 1999 Cameron Grant <cg at freebsd.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
#include <dev/sound/pcm/sound.h>
#include <isa/isavar.h>
-SND_DECLARE_FILE("$MidnightBSD$");
+SND_DECLARE_FILE("$FreeBSD: src/sys/dev/sound/isa/sndbuf_dma.c,v 1.3 2005/01/06 01:43:17 imp Exp $");
int
sndbuf_dmasetup(struct snd_dbuf *b, struct resource *drq)
{
-/* should do isa_dma_acquire/isa_dma_release here */
-if (drq == NULL) {
-b->dmachan = -1;
-} else {
-sndbuf_setflags(b, SNDBUF_F_DMA, 1);
-b->dmachan = rman_get_start(drq);
-}
-return 0;
+ /* should do isa_dma_acquire/isa_dma_release here */
+ if (drq == NULL) {
+ b->dmachan = -1;
+ } else {
+ sndbuf_setflags(b, SNDBUF_F_DMA, 1);
+ b->dmachan = rman_get_start(drq);
+ }
+ return 0;
}
int
sndbuf_dmasetdir(struct snd_dbuf *b, int dir)
{
-KASSERT(b, ("sndbuf_dmasetdir called with b == NULL"));
-KASSERT(sndbuf_getflags(b) & SNDBUF_F_DMA, ("sndbuf_dmasetdir called on non-ISA buffer"));
+ KASSERT(b, ("sndbuf_dmasetdir called with b == NULL"));
+ KASSERT(sndbuf_getflags(b) & SNDBUF_F_DMA, ("sndbuf_dmasetdir called on non-ISA buffer"));
-b->dir = (dir == PCMDIR_PLAY)? ISADMA_WRITE : ISADMA_READ;
-return 0;
+ b->dir = (dir == PCMDIR_PLAY)? ISADMA_WRITE : ISADMA_READ;
+ return 0;
}
void
sndbuf_dma(struct snd_dbuf *b, int go)
{
-KASSERT(b, ("sndbuf_dma called with b == NULL"));
-KASSERT(sndbuf_getflags(b) & SNDBUF_F_DMA, ("sndbuf_dma called on non-ISA buffer"));
-
-switch (go) {
-case PCMTRIG_START:
-/* isa_dmainit(b->chan, size); */
-isa_dmastart(b->dir | ISADMA_RAW, b->buf, b->bufsize, b->dmachan);
-break;
-
-case PCMTRIG_STOP:
-case PCMTRIG_ABORT:
-isa_dmastop(b->dmachan);
-isa_dmadone(b->dir | ISADMA_RAW, b->buf, b->bufsize, b->dmachan);
-break;
-}
+ KASSERT(b, ("sndbuf_dma called with b == NULL"));
+ KASSERT(sndbuf_getflags(b) & SNDBUF_F_DMA, ("sndbuf_dma called on non-ISA buffer"));
-DEB(printf("buf 0x%p ISA DMA %s, channel %dn",
-b,
-(go == PCMTRIG_START)? "started" : "stopped",
-b->dmachan));
+ switch (go) {
+ case PCMTRIG_START:
+ /* isa_dmainit(b->chan, size); */
+ isa_dmastart(b->dir | ISADMA_RAW, b->buf, b->bufsize, b->dmachan);
+ break;
+
+ case PCMTRIG_STOP:
+ case PCMTRIG_ABORT:
+ isa_dmastop(b->dmachan);
+ isa_dmadone(b->dir | ISADMA_RAW, b->buf, b->bufsize, b->dmachan);
+ break;
+ }
+
+ DEB(printf("buf 0x%p ISA DMA %s, channel %d\n",
+ b,
+ (go == PCMTRIG_START)? "started" : "stopped",
+ b->dmachan));
}
int
sndbuf_dmaptr(struct snd_dbuf *b)
{
-int i;
+ int i;
-KASSERT(b, ("sndbuf_dmaptr called with b == NULL"));
-KASSERT(sndbuf_getflags(b) & SNDBUF_F_DMA, ("sndbuf_dmaptr called on non-ISA buffer"));
+ KASSERT(b, ("sndbuf_dmaptr called with b == NULL"));
+ KASSERT(sndbuf_getflags(b) & SNDBUF_F_DMA, ("sndbuf_dmaptr called on non-ISA buffer"));
-if (!sndbuf_runsz(b))
-return 0;
-i = isa_dmastatus(b->dmachan);
-KASSERT(i >= 0, ("isa_dmastatus returned %d", i));
-return b->bufsize - i;
+ if (!sndbuf_runsz(b))
+ return 0;
+ i = isa_dmastatus(b->dmachan);
+ KASSERT(i >= 0, ("isa_dmastatus returned %d", i));
+ return b->bufsize - i;
}
void
sndbuf_dmabounce(struct snd_dbuf *b)
{
-KASSERT(b, ("sndbuf_dmabounce called with b == NULL"));
-KASSERT(sndbuf_getflags(b) & SNDBUF_F_DMA, ("sndbuf_dmabounce called on non-ISA buffer"));
+ KASSERT(b, ("sndbuf_dmabounce called with b == NULL"));
+ KASSERT(sndbuf_getflags(b) & SNDBUF_F_DMA, ("sndbuf_dmabounce called on non-ISA buffer"));
-/* tell isa_dma to bounce data in/out */
+ /* tell isa_dma to bounce data in/out */
}
Index: ess.c
===================================================================
RCS file: /home/cvs/src/sys/dev/sound/isa/ess.c,v
retrieving revision 1.2
retrieving revision 1.3
diff -L sys/dev/sound/isa/ess.c -L sys/dev/sound/isa/ess.c -u -r1.2 -r1.3
--- sys/dev/sound/isa/ess.c
+++ sys/dev/sound/isa/ess.c
@@ -1,33 +1,33 @@
/*-
-* Copyright (c) 1999 Cameron Grant <cg at freebsd.org>
-* Copyright 1997,1998 Luigi Rizzo.
-*
-* Derived from files in the Voxware 3.5 distribution,
-* Copyright by Hannu Savolainen 1994, under the same copyright
-* conditions.
-* All rights reserved.
-*
-* Redistribution and use in source and binary forms, with or without
-* modification, are permitted provided that the following conditions
-* are met:
-* 1. Redistributions of source code must retain the above copyright
-* notice, this list of conditions and the following disclaimer.
-* 2. Redistributions in binary form must reproduce the above copyright
-* notice, this list of conditions and the following disclaimer in the
-* documentation and/or other materials provided with the distribution.
-*
-* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
-* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
-* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
-* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
-* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
-* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
-* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
-* SUCH DAMAGE.
-*/
+ * Copyright (c) 1999 Cameron Grant <cg at freebsd.org>
+ * Copyright (c) 1997,1998 Luigi Rizzo
+ *
+ * Derived from files in the Voxware 3.5 distribution,
+ * Copyright by Hannu Savolainen 1994, under the same copyright
+ * conditions.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
#include <dev/sound/pcm/sound.h>
@@ -38,7 +38,7 @@
#include "mixer_if.h"
-SND_DECLARE_FILE("$MidnightBSD$");
+SND_DECLARE_FILE("$FreeBSD: src/sys/dev/sound/isa/ess.c,v 1.42 2007/06/17 06:10:40 ariff Exp $");
#define ESS_BUFFSIZE (4096)
#define ABS(x) (((x) < 0)? -(x) : (x))
@@ -50,29 +50,29 @@
#define ESS18XX_NEWSPEED
static u_int32_t ess_pfmt[] = {
-AFMT_U8,
-AFMT_STEREO | AFMT_U8,
-AFMT_S8,
-AFMT_STEREO | AFMT_S8,
-AFMT_S16_LE,
-AFMT_STEREO | AFMT_S16_LE,
-AFMT_U16_LE,
-AFMT_STEREO | AFMT_U16_LE,
-0
+ AFMT_U8,
+ AFMT_STEREO | AFMT_U8,
+ AFMT_S8,
+ AFMT_STEREO | AFMT_S8,
+ AFMT_S16_LE,
+ AFMT_STEREO | AFMT_S16_LE,
+ AFMT_U16_LE,
+ AFMT_STEREO | AFMT_U16_LE,
+ 0
};
static struct pcmchan_caps ess_playcaps = {6000, 48000, ess_pfmt, 0};
static u_int32_t ess_rfmt[] = {
-AFMT_U8,
-AFMT_STEREO | AFMT_U8,
-AFMT_S8,
-AFMT_STEREO | AFMT_S8,
-AFMT_S16_LE,
-AFMT_STEREO | AFMT_S16_LE,
-AFMT_U16_LE,
-AFMT_STEREO | AFMT_U16_LE,
-0
+ AFMT_U8,
+ AFMT_STEREO | AFMT_U8,
+ AFMT_S8,
+ AFMT_STEREO | AFMT_S8,
+ AFMT_S16_LE,
+ AFMT_STEREO | AFMT_S16_LE,
+ AFMT_U16_LE,
+ AFMT_STEREO | AFMT_U16_LE,
+ 0
};
static struct pcmchan_caps ess_reccaps = {6000, 48000, ess_rfmt, 0};
@@ -80,26 +80,27 @@
struct ess_info;
struct ess_chinfo {
-struct ess_info *parent;
-struct pcm_channel *channel;
-struct snd_dbuf *buffer;
-int dir, hwch, stopping, run;
-u_int32_t fmt, spd, blksz;
+ struct ess_info *parent;
+ struct pcm_channel *channel;
+ struct snd_dbuf *buffer;
+ int dir, hwch, stopping, run;
+ u_int32_t fmt, spd, blksz;
};
struct ess_info {
-device_t parent_dev;
-struct resource *io_base; /* I/O address for the board */
-struct resource *irq;
-struct resource *drq1;
-struct resource *drq2;
-void *ih;
-bus_dma_tag_t parent_dmat;
-
-unsigned int bufsize;
-int type, duplex:1, newspeed:1;
-u_long bd_flags; /* board-specific flags */
-struct ess_chinfo pch, rch;
+ device_t parent_dev;
+ struct resource *io_base; /* I/O address for the board */
+ struct resource *irq;
+ struct resource *drq1;
+ struct resource *drq2;
+ void *ih;
+ bus_dma_tag_t parent_dmat;
+
+ unsigned int bufsize;
+ int type;
+ unsigned int duplex:1, newspeed:1;
+ u_long bd_flags; /* board-specific flags */
+ struct ess_chinfo pch, rch;
};
#if 0
@@ -123,433 +124,433 @@
#endif
/*
-* Common code for the midi and pcm functions
-*
-* ess_cmd write a single byte to the CMD port.
-* ess_cmd1 write a CMD + 1 byte arg
-* ess_cmd2 write a CMD + 2 byte arg
-* ess_get_byte returns a single byte from the DSP data port
-*
-* ess_write is actually ess_cmd1
-* ess_read access ext. regs via ess_cmd(0xc0, reg) followed by ess_get_byte
-*/
+ * Common code for the midi and pcm functions
+ *
+ * ess_cmd write a single byte to the CMD port.
+ * ess_cmd1 write a CMD + 1 byte arg
+ * ess_cmd2 write a CMD + 2 byte arg
+ * ess_get_byte returns a single byte from the DSP data port
+ *
+ * ess_write is actually ess_cmd1
+ * ess_read access ext. regs via ess_cmd(0xc0, reg) followed by ess_get_byte
+ */
static void
ess_lock(struct ess_info *sc) {
-sbc_lock(device_get_softc(sc->parent_dev));
+ sbc_lock(device_get_softc(sc->parent_dev));
}
static void
ess_unlock(struct ess_info *sc) {
-sbc_unlock(device_get_softc(sc->parent_dev));
+ sbc_unlock(device_get_softc(sc->parent_dev));
}
static int
port_rd(struct resource *port, int off)
{
-return bus_space_read_1(rman_get_bustag(port),
-rman_get_bushandle(port),
-off);
+ return bus_space_read_1(rman_get_bustag(port),
+ rman_get_bushandle(port),
+ off);
}
static void
port_wr(struct resource *port, int off, u_int8_t data)
{
-bus_space_write_1(rman_get_bustag(port),
-rman_get_bushandle(port),
-off, data);
+ bus_space_write_1(rman_get_bustag(port),
+ rman_get_bushandle(port),
+ off, data);
}
static int
ess_rd(struct ess_info *sc, int reg)
{
-return port_rd(sc->io_base, reg);
+ return port_rd(sc->io_base, reg);
}
static void
ess_wr(struct ess_info *sc, int reg, u_int8_t val)
{
-port_wr(sc->io_base, reg, val);
+ port_wr(sc->io_base, reg, val);
}
static int
ess_dspready(struct ess_info *sc)
{
-return ((ess_rd(sc, SBDSP_STATUS) & 0x80) == 0);
+ return ((ess_rd(sc, SBDSP_STATUS) & 0x80) == 0);
}
static int
ess_dspwr(struct ess_info *sc, u_char val)
{
-int i;
+ int i;
-for (i = 0; i < 1000; i++) {
-if (ess_dspready(sc)) {
-ess_wr(sc, SBDSP_CMD, val);
-return 1;
-}
-if (i > 10) DELAY((i > 100)? 1000 : 10);
-}
-printf("ess_dspwr(0x%02x) timed out.n", val);
-return 0;
+ for (i = 0; i < 1000; i++) {
+ if (ess_dspready(sc)) {
+ ess_wr(sc, SBDSP_CMD, val);
+ return 1;
+ }
+ if (i > 10) DELAY((i > 100)? 1000 : 10);
+ }
+ printf("ess_dspwr(0x%02x) timed out.\n", val);
+ return 0;
}
static int
ess_cmd(struct ess_info *sc, u_char val)
{
#if 0
-printf("ess_cmd: %xn", val);
+ printf("ess_cmd: %x\n", val);
#endif
-return ess_dspwr(sc, val);
+ return ess_dspwr(sc, val);
}
static int
ess_cmd1(struct ess_info *sc, u_char cmd, int val)
{
#if 0
-printf("ess_cmd1: %x, %xn", cmd, val);
+ printf("ess_cmd1: %x, %x\n", cmd, val);
#endif
-if (ess_dspwr(sc, cmd)) {
-return ess_dspwr(sc, val & 0xff);
-} else return 0;
+ if (ess_dspwr(sc, cmd)) {
+ return ess_dspwr(sc, val & 0xff);
+ } else return 0;
}
static void
ess_setmixer(struct ess_info *sc, u_int port, u_int value)
{
-DEB(printf("ess_setmixer: reg=%x, val=%xn", port, value);)
-ess_wr(sc, SB_MIX_ADDR, (u_char) (port & 0xff)); /* Select register */
-DELAY(10);
-ess_wr(sc, SB_MIX_DATA, (u_char) (value & 0xff));
-DELAY(10);
+ DEB(printf("ess_setmixer: reg=%x, val=%x\n", port, value);)
+ ess_wr(sc, SB_MIX_ADDR, (u_char) (port & 0xff)); /* Select register */
+ DELAY(10);
+ ess_wr(sc, SB_MIX_DATA, (u_char) (value & 0xff));
+ DELAY(10);
}
static int
ess_getmixer(struct ess_info *sc, u_int port)
{
-int val;
-ess_wr(sc, SB_MIX_ADDR, (u_char) (port & 0xff)); /* Select register */
-DELAY(10);
-val = ess_rd(sc, SB_MIX_DATA);
-DELAY(10);
+ int val;
+ ess_wr(sc, SB_MIX_ADDR, (u_char) (port & 0xff)); /* Select register */
+ DELAY(10);
+ val = ess_rd(sc, SB_MIX_DATA);
+ DELAY(10);
-return val;
+ return val;
}
static int
ess_get_byte(struct ess_info *sc)
{
-int i;
+ int i;
-for (i = 1000; i > 0; i--) {
-if (ess_rd(sc, DSP_DATA_AVAIL) & 0x80)
-return ess_rd(sc, DSP_READ);
-else
-DELAY(20);
-}
-return -1;
+ for (i = 1000; i > 0; i--) {
+ if (ess_rd(sc, DSP_DATA_AVAIL) & 0x80)
+ return ess_rd(sc, DSP_READ);
+ else
+ DELAY(20);
+ }
+ return -1;
}
static int
ess_write(struct ess_info *sc, u_char reg, int val)
{
-return ess_cmd1(sc, reg, val);
+ return ess_cmd1(sc, reg, val);
}
static int
ess_read(struct ess_info *sc, u_char reg)
{
-return (ess_cmd(sc, 0xc0) && ess_cmd(sc, reg))? ess_get_byte(sc) : -1;
+ return (ess_cmd(sc, 0xc0) && ess_cmd(sc, reg))? ess_get_byte(sc) : -1;
}
static int
ess_reset_dsp(struct ess_info *sc)
{
-ess_wr(sc, SBDSP_RST, 3);
-DELAY(100);
-ess_wr(sc, SBDSP_RST, 0);
-if (ess_get_byte(sc) != 0xAA) {
-DEB(printf("ess_reset_dsp 0x%lx failedn",
-rman_get_start(sc->io_base)));
-return ENXIO; /* Sorry */
-}
-ess_cmd(sc, 0xc6);
-return 0;
+ ess_wr(sc, SBDSP_RST, 3);
+ DELAY(100);
+ ess_wr(sc, SBDSP_RST, 0);
+ if (ess_get_byte(sc) != 0xAA) {
+ DEB(printf("ess_reset_dsp 0x%lx failed\n",
+ rman_get_start(sc->io_base)));
+ return ENXIO; /* Sorry */
+ }
+ ess_cmd(sc, 0xc6);
+ return 0;
}
static void
ess_release_resources(struct ess_info *sc, device_t dev)
{
-if (sc->irq) {
-if (sc->ih)
-bus_teardown_intr(dev, sc->irq, sc->ih);
-bus_release_resource(dev, SYS_RES_IRQ, 0, sc->irq);
-sc->irq = 0;
-}
-if (sc->drq1) {
-isa_dma_release(rman_get_start(sc->drq1));
-bus_release_resource(dev, SYS_RES_DRQ, 0, sc->drq1);
-sc->drq1 = 0;
-}
-if (sc->drq2) {
-isa_dma_release(rman_get_start(sc->drq2));
-bus_release_resource(dev, SYS_RES_DRQ, 1, sc->drq2);
-sc->drq2 = 0;
-}
-if (sc->io_base) {
-bus_release_resource(dev, SYS_RES_IOPORT, 0, sc->io_base);
-sc->io_base = 0;
-}
-if (sc->parent_dmat) {
-bus_dma_tag_destroy(sc->parent_dmat);
-sc->parent_dmat = 0;
-}
-free(sc, M_DEVBUF);
+ if (sc->irq) {
+ if (sc->ih)
+ bus_teardown_intr(dev, sc->irq, sc->ih);
+ bus_release_resource(dev, SYS_RES_IRQ, 0, sc->irq);
+ sc->irq = 0;
+ }
+ if (sc->drq1) {
+ isa_dma_release(rman_get_start(sc->drq1));
+ bus_release_resource(dev, SYS_RES_DRQ, 0, sc->drq1);
+ sc->drq1 = 0;
+ }
+ if (sc->drq2) {
+ isa_dma_release(rman_get_start(sc->drq2));
+ bus_release_resource(dev, SYS_RES_DRQ, 1, sc->drq2);
+ sc->drq2 = 0;
+ }
+ if (sc->io_base) {
+ bus_release_resource(dev, SYS_RES_IOPORT, 0, sc->io_base);
+ sc->io_base = 0;
+ }
+ if (sc->parent_dmat) {
+ bus_dma_tag_destroy(sc->parent_dmat);
+ sc->parent_dmat = 0;
+ }
+ free(sc, M_DEVBUF);
}
static int
ess_alloc_resources(struct ess_info *sc, device_t dev)
{
-int rid;
+ int rid;
-rid = 0;
-if (!sc->io_base)
-sc->io_base = bus_alloc_resource_any(dev, SYS_RES_IOPORT,
-&rid, RF_ACTIVE);
-rid = 0;
-if (!sc->irq)
-sc->irq = bus_alloc_resource_any(dev, SYS_RES_IRQ,
-&rid, RF_ACTIVE);
-rid = 0;
-if (!sc->drq1)
-sc->drq1 = bus_alloc_resource_any(dev, SYS_RES_DRQ,
-&rid, RF_ACTIVE);
-rid = 1;
-if (!sc->drq2)
-sc->drq2 = bus_alloc_resource_any(dev, SYS_RES_DRQ,
-&rid, RF_ACTIVE);
-
-if (sc->io_base && sc->drq1 && sc->irq) {
-isa_dma_acquire(rman_get_start(sc->drq1));
-isa_dmainit(rman_get_start(sc->drq1), sc->bufsize);
-
-if (sc->drq2) {
-isa_dma_acquire(rman_get_start(sc->drq2));
-isa_dmainit(rman_get_start(sc->drq2), sc->bufsize);
-}
+ rid = 0;
+ if (!sc->io_base)
+ sc->io_base = bus_alloc_resource_any(dev, SYS_RES_IOPORT,
+ &rid, RF_ACTIVE);
+ rid = 0;
+ if (!sc->irq)
+ sc->irq = bus_alloc_resource_any(dev, SYS_RES_IRQ,
+ &rid, RF_ACTIVE);
+ rid = 0;
+ if (!sc->drq1)
+ sc->drq1 = bus_alloc_resource_any(dev, SYS_RES_DRQ,
+ &rid, RF_ACTIVE);
+ rid = 1;
+ if (!sc->drq2)
+ sc->drq2 = bus_alloc_resource_any(dev, SYS_RES_DRQ,
+ &rid, RF_ACTIVE);
+
+ if (sc->io_base && sc->drq1 && sc->irq) {
+ isa_dma_acquire(rman_get_start(sc->drq1));
+ isa_dmainit(rman_get_start(sc->drq1), sc->bufsize);
+
+ if (sc->drq2) {
+ isa_dma_acquire(rman_get_start(sc->drq2));
+ isa_dmainit(rman_get_start(sc->drq2), sc->bufsize);
+ }
-return 0;
-} else return ENXIO;
+ return 0;
+ } else return ENXIO;
}
static void
ess_intr(void *arg)
{
-struct ess_info *sc = (struct ess_info *)arg;
-int src, pirq, rirq;
-
-ess_lock(sc);
-src = 0;
-if (ess_getmixer(sc, 0x7a) & 0x80)
-src |= 2;
-if (ess_rd(sc, 0x0c) & 0x01)
-src |= 1;
-
-pirq = (src & sc->pch.hwch)? 1 : 0;
-rirq = (src & sc->rch.hwch)? 1 : 0;
-
-if (pirq) {
-if (sc->pch.run) {
-ess_unlock(sc);
-chn_intr(sc->pch.channel);
-ess_lock(sc);
-}
-if (sc->pch.stopping) {
-sc->pch.run = 0;
-sndbuf_dma(sc->pch.buffer, PCMTRIG_STOP);
-sc->pch.stopping = 0;
-if (sc->pch.hwch == 1)
-ess_write(sc, 0xb8, ess_read(sc, 0xb8) & ~0x01);
-else
-ess_setmixer(sc, 0x78, ess_getmixer(sc, 0x78) & ~0x03);
-}
-}
-
-if (rirq) {
-if (sc->rch.run) {
-ess_unlock(sc);
-chn_intr(sc->rch.channel);
-ess_lock(sc);
-}
-if (sc->rch.stopping) {
-sc->rch.run = 0;
-sndbuf_dma(sc->rch.buffer, PCMTRIG_STOP);
-sc->rch.stopping = 0;
-/* XXX: will this stop audio2? */
-ess_write(sc, 0xb8, ess_read(sc, 0xb8) & ~0x01);
-}
-}
+ struct ess_info *sc = (struct ess_info *)arg;
+ int src, pirq, rirq;
-if (src & 2)
-ess_setmixer(sc, 0x7a, ess_getmixer(sc, 0x7a) & ~0x80);
-if (src & 1)
-ess_rd(sc, DSP_DATA_AVAIL);
-ess_unlock(sc);
+ ess_lock(sc);
+ src = 0;
+ if (ess_getmixer(sc, 0x7a) & 0x80)
+ src |= 2;
+ if (ess_rd(sc, 0x0c) & 0x01)
+ src |= 1;
+
+ pirq = (src & sc->pch.hwch)? 1 : 0;
+ rirq = (src & sc->rch.hwch)? 1 : 0;
+
+ if (pirq) {
+ if (sc->pch.run) {
+ ess_unlock(sc);
+ chn_intr(sc->pch.channel);
+ ess_lock(sc);
+ }
+ if (sc->pch.stopping) {
+ sc->pch.run = 0;
+ sndbuf_dma(sc->pch.buffer, PCMTRIG_STOP);
+ sc->pch.stopping = 0;
+ if (sc->pch.hwch == 1)
+ ess_write(sc, 0xb8, ess_read(sc, 0xb8) & ~0x01);
+ else
+ ess_setmixer(sc, 0x78, ess_getmixer(sc, 0x78) & ~0x03);
+ }
+ }
+
+ if (rirq) {
+ if (sc->rch.run) {
+ ess_unlock(sc);
+ chn_intr(sc->rch.channel);
+ ess_lock(sc);
+ }
+ if (sc->rch.stopping) {
+ sc->rch.run = 0;
+ sndbuf_dma(sc->rch.buffer, PCMTRIG_STOP);
+ sc->rch.stopping = 0;
+ /* XXX: will this stop audio2? */
+ ess_write(sc, 0xb8, ess_read(sc, 0xb8) & ~0x01);
+ }
+ }
+
+ if (src & 2)
+ ess_setmixer(sc, 0x7a, ess_getmixer(sc, 0x7a) & ~0x80);
+ if (src & 1)
+ ess_rd(sc, DSP_DATA_AVAIL);
+ ess_unlock(sc);
}
/* utility functions for ESS */
static u_int8_t
ess_calcspeed8(int *spd)
{
-int speed = *spd;
-u_int32_t t;
+ int speed = *spd;
+ u_int32_t t;
-if (speed > 22000) {
-t = (795500 + speed / 2) / speed;
-speed = (795500 + t / 2) / t;
-t = (256 - t) | 0x80;
-} else {
-t = (397700 + speed / 2) / speed;
-speed = (397700 + t / 2) / t;
-t = 128 - t;
-}
-*spd = speed;
-return t & 0x000000ff;
+ if (speed > 22000) {
+ t = (795500 + speed / 2) / speed;
+ speed = (795500 + t / 2) / t;
+ t = (256 - t) | 0x80;
+ } else {
+ t = (397700 + speed / 2) / speed;
+ speed = (397700 + t / 2) / t;
+ t = 128 - t;
+ }
+ *spd = speed;
+ return t & 0x000000ff;
}
static u_int8_t
ess_calcspeed9(int *spd)
{
-int speed, s0, s1, use0;
-u_int8_t t0, t1;
+ int speed, s0, s1, use0;
+ u_int8_t t0, t1;
-/* rate = source / (256 - divisor) */
-/* divisor = 256 - (source / rate) */
-speed = *spd;
-t0 = 128 - (793800 / speed);
-s0 = 793800 / (128 - t0);
-
-t1 = 128 - (768000 / speed);
-s1 = 768000 / (128 - t1);
-t1 |= 0x80;
+ /* rate = source / (256 - divisor) */
+ /* divisor = 256 - (source / rate) */
+ speed = *spd;
+ t0 = 128 - (793800 / speed);
+ s0 = 793800 / (128 - t0);
+
+ t1 = 128 - (768000 / speed);
+ s1 = 768000 / (128 - t1);
+ t1 |= 0x80;
-use0 = (ABS(speed - s0) < ABS(speed - s1))? 1 : 0;
+ use0 = (ABS(speed - s0) < ABS(speed - s1))? 1 : 0;
-*spd = use0? s0 : s1;
-return use0? t0 : t1;
+ *spd = use0? s0 : s1;
+ return use0? t0 : t1;
}
static u_int8_t
ess_calcfilter(int spd)
{
-int cutoff;
+ int cutoff;
-/* cutoff = 7160000 / (256 - divisor) */
-/* divisor = 256 - (7160000 / cutoff) */
-cutoff = (spd * 9 * 82) / 20;
-return (256 - (7160000 / cutoff));
+ /* cutoff = 7160000 / (256 - divisor) */
+ /* divisor = 256 - (7160000 / cutoff) */
+ cutoff = (spd * 9 * 82) / 20;
+ return (256 - (7160000 / cutoff));
}
static int
ess_setupch(struct ess_info *sc, int ch, int dir, int spd, u_int32_t fmt, int len)
{
-int play = (dir == PCMDIR_PLAY)? 1 : 0;
-int b16 = (fmt & AFMT_16BIT)? 1 : 0;
-int stereo = (fmt & AFMT_STEREO)? 1 : 0;
-int unsign = (fmt == AFMT_U8 || fmt == AFMT_U16_LE)? 1 : 0;
-u_int8_t spdval, fmtval;
-
-
-spdval = (sc->newspeed)? ess_calcspeed9(&spd) : ess_calcspeed8(&spd);
-len = -len;
-
-if (ch == 1) {
-KASSERT((dir == PCMDIR_PLAY) || (dir == PCMDIR_REC), ("ess_setupch: dir1 bad"));
-/* transfer length low */
-ess_write(sc, 0xa4, len & 0x00ff);
-/* transfer length high */
-ess_write(sc, 0xa5, (len & 0xff00) >> 8);
-/* autoinit, dma dir */
-ess_write(sc, 0xb8, 0x04 | (play? 0x00 : 0x0a));
-/* mono/stereo */
-ess_write(sc, 0xa8, (ess_read(sc, 0xa8) & ~0x03) | (stereo? 0x01 : 0x02));
-/* demand mode, 4 bytes/xfer */
-ess_write(sc, 0xb9, 0x02);
-/* sample rate */
-ess_write(sc, 0xa1, spdval);
-/* filter cutoff */
-ess_write(sc, 0xa2, ess_calcfilter(spd));
-/* setup dac/adc */
-if (play)
-ess_write(sc, 0xb6, unsign? 0x80 : 0x00);
-/* mono, b16: signed, load signal */
-ess_write(sc, 0xb7, 0x51 | (unsign? 0x00 : 0x20));
-/* setup fifo */
-ess_write(sc, 0xb7, 0x90 | (unsign? 0x00 : 0x20) |
-(b16? 0x04 : 0x00) |
-(stereo? 0x08 : 0x40));
-/* irq control */
-ess_write(sc, 0xb1, (ess_read(sc, 0xb1) & 0x0f) | 0x50);
-/* drq control */
-ess_write(sc, 0xb2, (ess_read(sc, 0xb2) & 0x0f) | 0x50);
-} else if (ch == 2) {
-KASSERT(dir == PCMDIR_PLAY, ("ess_setupch: dir2 bad"));
-/* transfer length low */
-ess_setmixer(sc, 0x74, len & 0x00ff);
-/* transfer length high */
-ess_setmixer(sc, 0x76, (len & 0xff00) >> 8);
-/* autoinit, 4 bytes/req */
-ess_setmixer(sc, 0x78, 0x90);
-fmtval = b16 | (stereo << 1) | (unsign << 2);
-/* enable irq, set format */
-ess_setmixer(sc, 0x7a, 0x40 | fmtval);
-if (sc->newspeed) {
-/* sample rate */
-ess_setmixer(sc, 0x70, spdval);
-/* filter cutoff */
-ess_setmixer(sc, 0x72, ess_calcfilter(spd));
-}
-}
+ int play = (dir == PCMDIR_PLAY)? 1 : 0;
+ int b16 = (fmt & AFMT_16BIT)? 1 : 0;
+ int stereo = (fmt & AFMT_STEREO)? 1 : 0;
+ int unsign = (fmt == AFMT_U8 || fmt == AFMT_U16_LE)? 1 : 0;
+ u_int8_t spdval, fmtval;
+
+
+ spdval = (sc->newspeed)? ess_calcspeed9(&spd) : ess_calcspeed8(&spd);
+ len = -len;
+
+ if (ch == 1) {
+ KASSERT((dir == PCMDIR_PLAY) || (dir == PCMDIR_REC), ("ess_setupch: dir1 bad"));
+ /* transfer length low */
+ ess_write(sc, 0xa4, len & 0x00ff);
+ /* transfer length high */
+ ess_write(sc, 0xa5, (len & 0xff00) >> 8);
+ /* autoinit, dma dir */
+ ess_write(sc, 0xb8, 0x04 | (play? 0x00 : 0x0a));
+ /* mono/stereo */
+ ess_write(sc, 0xa8, (ess_read(sc, 0xa8) & ~0x03) | (stereo? 0x01 : 0x02));
+ /* demand mode, 4 bytes/xfer */
+ ess_write(sc, 0xb9, 0x02);
+ /* sample rate */
+ ess_write(sc, 0xa1, spdval);
+ /* filter cutoff */
+ ess_write(sc, 0xa2, ess_calcfilter(spd));
+ /* setup dac/adc */
+ if (play)
+ ess_write(sc, 0xb6, unsign? 0x80 : 0x00);
+ /* mono, b16: signed, load signal */
+ ess_write(sc, 0xb7, 0x51 | (unsign? 0x00 : 0x20));
+ /* setup fifo */
+ ess_write(sc, 0xb7, 0x90 | (unsign? 0x00 : 0x20) |
+ (b16? 0x04 : 0x00) |
+ (stereo? 0x08 : 0x40));
+ /* irq control */
+ ess_write(sc, 0xb1, (ess_read(sc, 0xb1) & 0x0f) | 0x50);
+ /* drq control */
+ ess_write(sc, 0xb2, (ess_read(sc, 0xb2) & 0x0f) | 0x50);
+ } else if (ch == 2) {
+ KASSERT(dir == PCMDIR_PLAY, ("ess_setupch: dir2 bad"));
+ /* transfer length low */
+ ess_setmixer(sc, 0x74, len & 0x00ff);
+ /* transfer length high */
+ ess_setmixer(sc, 0x76, (len & 0xff00) >> 8);
+ /* autoinit, 4 bytes/req */
+ ess_setmixer(sc, 0x78, 0x90);
+ fmtval = b16 | (stereo << 1) | (unsign << 2);
+ /* enable irq, set format */
+ ess_setmixer(sc, 0x7a, 0x40 | fmtval);
+ if (sc->newspeed) {
+ /* sample rate */
+ ess_setmixer(sc, 0x70, spdval);
+ /* filter cutoff */
+ ess_setmixer(sc, 0x72, ess_calcfilter(spd));
+ }
+ }
-return 0;
+ return 0;
}
static int
ess_start(struct ess_chinfo *ch)
{
-struct ess_info *sc = ch->parent;
-int play = (ch->dir == PCMDIR_PLAY)? 1 : 0;
+ struct ess_info *sc = ch->parent;
+ int play = (ch->dir == PCMDIR_PLAY)? 1 : 0;
-ess_lock(sc);
-ess_setupch(sc, ch->hwch, ch->dir, ch->spd, ch->fmt, ch->blksz);
-ch->stopping = 0;
-if (ch->hwch == 1)
-ess_write(sc, 0xb8, ess_read(sc, 0xb8) | 0x01);
-else
-ess_setmixer(sc, 0x78, ess_getmixer(sc, 0x78) | 0x03);
-if (play)
-ess_cmd(sc, DSP_CMD_SPKON);
-ess_unlock(sc);
-return 0;
+ ess_lock(sc);
+ ess_setupch(sc, ch->hwch, ch->dir, ch->spd, ch->fmt, ch->blksz);
+ ch->stopping = 0;
+ if (ch->hwch == 1)
+ ess_write(sc, 0xb8, ess_read(sc, 0xb8) | 0x01);
+ else
+ ess_setmixer(sc, 0x78, ess_getmixer(sc, 0x78) | 0x03);
+ if (play)
+ ess_cmd(sc, DSP_CMD_SPKON);
+ ess_unlock(sc);
+ return 0;
}
static int
ess_stop(struct ess_chinfo *ch)
{
-struct ess_info *sc = ch->parent;
-int play = (ch->dir == PCMDIR_PLAY)? 1 : 0;
+ struct ess_info *sc = ch->parent;
+ int play = (ch->dir == PCMDIR_PLAY)? 1 : 0;
-ess_lock(sc);
-ch->stopping = 1;
-if (ch->hwch == 1)
-ess_write(sc, 0xb8, ess_read(sc, 0xb8) & ~0x04);
-else
-ess_setmixer(sc, 0x78, ess_getmixer(sc, 0x78) & ~0x10);
-if (play)
-ess_cmd(sc, DSP_CMD_SPKOFF);
-ess_unlock(sc);
-return 0;
+ ess_lock(sc);
+ ch->stopping = 1;
+ if (ch->hwch == 1)
+ ess_write(sc, 0xb8, ess_read(sc, 0xb8) & ~0x04);
+ else
+ ess_setmixer(sc, 0x78, ess_getmixer(sc, 0x78) & ~0x10);
+ if (play)
+ ess_cmd(sc, DSP_CMD_SPKOFF);
+ ess_unlock(sc);
+ return 0;
}
/* -------------------------------------------------------------------- */
@@ -557,103 +558,103 @@
static void *
esschan_init(kobj_t obj, void *devinfo, struct snd_dbuf *b, struct pcm_channel *c, int dir)
{
-struct ess_info *sc = devinfo;
-struct ess_chinfo *ch = (dir == PCMDIR_PLAY)? &sc->pch : &sc->rch;
+ struct ess_info *sc = devinfo;
+ struct ess_chinfo *ch = (dir == PCMDIR_PLAY)? &sc->pch : &sc->rch;
-ch->parent = sc;
-ch->channel = c;
-ch->buffer = b;
-if (sndbuf_alloc(ch->buffer, sc->parent_dmat, sc->bufsize) != 0)
-return NULL;
-ch->dir = dir;
-ch->hwch = 1;
-if ((dir == PCMDIR_PLAY) && (sc->duplex))
-ch->hwch = 2;
-sndbuf_dmasetup(ch->buffer, (ch->hwch == 1)? sc->drq1 : sc->drq2);
-return ch;
+ ch->parent = sc;
+ ch->channel = c;
+ ch->buffer = b;
+ if (sndbuf_alloc(ch->buffer, sc->parent_dmat, 0, sc->bufsize) != 0)
+ return NULL;
+ ch->dir = dir;
+ ch->hwch = 1;
+ if ((dir == PCMDIR_PLAY) && (sc->duplex))
+ ch->hwch = 2;
+ sndbuf_dmasetup(ch->buffer, (ch->hwch == 1)? sc->drq1 : sc->drq2);
+ return ch;
}
static int
esschan_setformat(kobj_t obj, void *data, u_int32_t format)
{
-struct ess_chinfo *ch = data;
+ struct ess_chinfo *ch = data;
-ch->fmt = format;
-return 0;
+ ch->fmt = format;
+ return 0;
}
static int
esschan_setspeed(kobj_t obj, void *data, u_int32_t speed)
{
-struct ess_chinfo *ch = data;
-struct ess_info *sc = ch->parent;
+ struct ess_chinfo *ch = data;
+ struct ess_info *sc = ch->parent;
-ch->spd = speed;
-if (sc->newspeed)
-ess_calcspeed9(&ch->spd);
-else
-ess_calcspeed8(&ch->spd);
-return ch->spd;
+ ch->spd = speed;
+ if (sc->newspeed)
+ ess_calcspeed9(&ch->spd);
+ else
+ ess_calcspeed8(&ch->spd);
+ return ch->spd;
}
static int
esschan_setblocksize(kobj_t obj, void *data, u_int32_t blocksize)
{
-struct ess_chinfo *ch = data;
+ struct ess_chinfo *ch = data;
-ch->blksz = blocksize;
-return ch->blksz;
+ ch->blksz = blocksize;
+ return ch->blksz;
}
static int
esschan_trigger(kobj_t obj, void *data, int go)
{
-struct ess_chinfo *ch = data;
+ struct ess_chinfo *ch = data;
-if (go == PCMTRIG_EMLDMAWR || go == PCMTRIG_EMLDMARD)
-return 0;
+ if (!PCMTRIG_COMMON(go))
+ return 0;
-switch (go) {
-case PCMTRIG_START:
-ch->run = 1;
-sndbuf_dma(ch->buffer, go);
-ess_start(ch);
-break;
-
-case PCMTRIG_STOP:
-case PCMTRIG_ABORT:
-default:
-ess_stop(ch);
-break;
-}
-return 0;
+ switch (go) {
+ case PCMTRIG_START:
+ ch->run = 1;
+ sndbuf_dma(ch->buffer, go);
+ ess_start(ch);
+ break;
+
+ case PCMTRIG_STOP:
+ case PCMTRIG_ABORT:
+ default:
+ ess_stop(ch);
+ break;
+ }
+ return 0;
}
static int
esschan_getptr(kobj_t obj, void *data)
{
-struct ess_chinfo *ch = data;
+ struct ess_chinfo *ch = data;
-return sndbuf_dmaptr(ch->buffer);
+ return sndbuf_dmaptr(ch->buffer);
}
static struct pcmchan_caps *
esschan_getcaps(kobj_t obj, void *data)
{
-struct ess_chinfo *ch = data;
+ struct ess_chinfo *ch = data;
-return (ch->dir == PCMDIR_PLAY)? &ess_playcaps : &ess_reccaps;
+ return (ch->dir == PCMDIR_PLAY)? &ess_playcaps : &ess_reccaps;
}
static kobj_method_t esschan_methods[] = {
-KOBJMETHOD(channel_init, esschan_init),
-KOBJMETHOD(channel_setformat, esschan_setformat),
-KOBJMETHOD(channel_setspeed, esschan_setspeed),
-KOBJMETHOD(channel_setblocksize, esschan_setblocksize),
-KOBJMETHOD(channel_trigger, esschan_trigger),
-KOBJMETHOD(channel_getptr, esschan_getptr),
-KOBJMETHOD(channel_getcaps, esschan_getcaps),
-{ 0, 0 }
+ KOBJMETHOD(channel_init, esschan_init),
+ KOBJMETHOD(channel_setformat, esschan_setformat),
+ KOBJMETHOD(channel_setspeed, esschan_setspeed),
+ KOBJMETHOD(channel_setblocksize, esschan_setblocksize),
+ KOBJMETHOD(channel_trigger, esschan_trigger),
+ KOBJMETHOD(channel_getptr, esschan_getptr),
+ KOBJMETHOD(channel_getcaps, esschan_getcaps),
+ { 0, 0 }
};
CHANNEL_DECLARE(esschan);
@@ -662,120 +663,120 @@
static int
essmix_init(struct snd_mixer *m)
{
-struct ess_info *sc = mix_getdevinfo(m);
+ struct ess_info *sc = mix_getdevinfo(m);
-mix_setrecdevs(m, SOUND_MASK_CD | SOUND_MASK_MIC | SOUND_MASK_LINE |
-SOUND_MASK_IMIX);
+ mix_setrecdevs(m, SOUND_MASK_CD | SOUND_MASK_MIC | SOUND_MASK_LINE |
+ SOUND_MASK_IMIX);
-mix_setdevs(m, SOUND_MASK_SYNTH | SOUND_MASK_PCM | SOUND_MASK_LINE |
-SOUND_MASK_MIC | SOUND_MASK_CD | SOUND_MASK_VOLUME |
-SOUND_MASK_LINE1 | SOUND_MASK_SPEAKER);
+ mix_setdevs(m, SOUND_MASK_SYNTH | SOUND_MASK_PCM | SOUND_MASK_LINE |
+ SOUND_MASK_MIC | SOUND_MASK_CD | SOUND_MASK_VOLUME |
+ SOUND_MASK_LINE1 | SOUND_MASK_SPEAKER);
-ess_setmixer(sc, 0, 0); /* reset */
+ ess_setmixer(sc, 0, 0); /* reset */
-return 0;
+ return 0;
}
static int
essmix_set(struct snd_mixer *m, unsigned dev, unsigned left, unsigned right)
{
-struct ess_info *sc = mix_getdevinfo(m);
-int preg = 0, rreg = 0, l, r;
+ struct ess_info *sc = mix_getdevinfo(m);
+ int preg = 0, rreg = 0, l, r;
-l = (left * 15) / 100;
-r = (right * 15) / 100;
-switch (dev) {
-case SOUND_MIXER_SYNTH:
-preg = 0x36;
-rreg = 0x6b;
-break;
-
-case SOUND_MIXER_PCM:
-preg = 0x14;
-rreg = 0x7c;
-break;
-
-case SOUND_MIXER_LINE:
-preg = 0x3e;
-rreg = 0x6e;
-break;
-
-case SOUND_MIXER_MIC:
-preg = 0x1a;
-rreg = 0x68;
-break;
-
-case SOUND_MIXER_LINE1:
-preg = 0x3a;
-rreg = 0x6c;
-break;
-
-case SOUND_MIXER_CD:
-preg = 0x38;
-rreg = 0x6a;
-break;
-
-case SOUND_MIXER_SPEAKER:
-preg = 0x3c;
-break;
-
-case SOUND_MIXER_VOLUME:
-l = left? (left * 63) / 100 : 64;
-r = right? (right * 63) / 100 : 64;
-ess_setmixer(sc, 0x60, l);
-ess_setmixer(sc, 0x62, r);
-left = (l == 64)? 0 : (l * 100) / 63;
-right = (r == 64)? 0 : (r * 100) / 63;
-return left | (right << 8);
-}
-
-if (preg)
-ess_setmixer(sc, preg, (l << 4) | r);
-if (rreg)
-ess_setmixer(sc, rreg, (l << 4) | r);
+ l = (left * 15) / 100;
+ r = (right * 15) / 100;
+ switch (dev) {
+ case SOUND_MIXER_SYNTH:
+ preg = 0x36;
+ rreg = 0x6b;
+ break;
+
+ case SOUND_MIXER_PCM:
+ preg = 0x14;
+ rreg = 0x7c;
+ break;
+
+ case SOUND_MIXER_LINE:
+ preg = 0x3e;
+ rreg = 0x6e;
+ break;
+
+ case SOUND_MIXER_MIC:
+ preg = 0x1a;
+ rreg = 0x68;
+ break;
+
+ case SOUND_MIXER_LINE1:
+ preg = 0x3a;
+ rreg = 0x6c;
+ break;
+
+ case SOUND_MIXER_CD:
+ preg = 0x38;
+ rreg = 0x6a;
+ break;
+
+ case SOUND_MIXER_SPEAKER:
+ preg = 0x3c;
+ break;
+
+ case SOUND_MIXER_VOLUME:
+ l = left? (left * 63) / 100 : 64;
+ r = right? (right * 63) / 100 : 64;
+ ess_setmixer(sc, 0x60, l);
+ ess_setmixer(sc, 0x62, r);
+ left = (l == 64)? 0 : (l * 100) / 63;
+ right = (r == 64)? 0 : (r * 100) / 63;
+ return left | (right << 8);
+ }
+
+ if (preg)
+ ess_setmixer(sc, preg, (l << 4) | r);
+ if (rreg)
+ ess_setmixer(sc, rreg, (l << 4) | r);
-left = (l * 100) / 15;
-right = (r * 100) / 15;
+ left = (l * 100) / 15;
+ right = (r * 100) / 15;
-return left | (right << 8);
+ return left | (right << 8);
}
static int
essmix_setrecsrc(struct snd_mixer *m, u_int32_t src)
{
-struct ess_info *sc = mix_getdevinfo(m);
-u_char recdev;
-
-switch (src) {
-case SOUND_MASK_CD:
-recdev = 0x02;
-break;
-
-case SOUND_MASK_LINE:
-recdev = 0x06;
-break;
+ struct ess_info *sc = mix_getdevinfo(m);
+ u_char recdev;
-case SOUND_MASK_IMIX:
-recdev = 0x05;
-break;
+ switch (src) {
+ case SOUND_MASK_CD:
+ recdev = 0x02;
+ break;
+
+ case SOUND_MASK_LINE:
+ recdev = 0x06;
+ break;
+
+ case SOUND_MASK_IMIX:
+ recdev = 0x05;
+ break;
+
+ case SOUND_MASK_MIC:
+ default:
+ recdev = 0x00;
+ src = SOUND_MASK_MIC;
+ break;
+ }
-case SOUND_MASK_MIC:
-default:
-recdev = 0x00;
-src = SOUND_MASK_MIC;
-break;
-}
-
-ess_setmixer(sc, 0x1c, recdev);
+ ess_setmixer(sc, 0x1c, recdev);
-return src;
+ return src;
}
static kobj_method_t essmixer_methods[] = {
-KOBJMETHOD(mixer_init, essmix_init),
-KOBJMETHOD(mixer_set, essmix_set),
-KOBJMETHOD(mixer_setrecsrc, essmix_setrecsrc),
-{ 0, 0 }
+ KOBJMETHOD(mixer_init, essmix_init),
+ KOBJMETHOD(mixer_set, essmix_set),
+ KOBJMETHOD(mixer_setrecsrc, essmix_setrecsrc),
+ { 0, 0 }
};
MIXER_DECLARE(essmixer);
@@ -784,157 +785,155 @@
static int
ess_probe(device_t dev)
{
-uintptr_t func, ver, r, f;
+ uintptr_t func, ver, r, f;
-/* The parent device has already been probed. */
-r = BUS_READ_IVAR(device_get_parent(dev), dev, 0, &func);
-if (func != SCF_PCM)
-return (ENXIO);
+ /* The parent device has already been probed. */
+ r = BUS_READ_IVAR(device_get_parent(dev), dev, 0, &func);
+ if (func != SCF_PCM)
+ return (ENXIO);
-r = BUS_READ_IVAR(device_get_parent(dev), dev, 1, &ver);
-f = (ver & 0xffff0000) >> 16;
-if (!(f & BD_F_ESS))
-return (ENXIO);
+ r = BUS_READ_IVAR(device_get_parent(dev), dev, 1, &ver);
+ f = (ver & 0xffff0000) >> 16;
+ if (!(f & BD_F_ESS))
+ return (ENXIO);
-device_set_desc(dev, "ESS 18xx DSP");
+ device_set_desc(dev, "ESS 18xx DSP");
-return 0;
+ return 0;
}
static int
ess_attach(device_t dev)
{
-struct ess_info *sc;
-char status[SND_STATUSLEN], buf[64];
-int ver;
-
-sc = (struct ess_info *)malloc(sizeof *sc, M_DEVBUF, M_NOWAIT | M_ZERO);
-if (!sc)
-return ENXIO;
-
-sc->parent_dev = device_get_parent(dev);
-sc->bufsize = pcm_getbuffersize(dev, 4096, ESS_BUFFSIZE, 65536);
-if (ess_alloc_resources(sc, dev))
-goto no;
-if (ess_reset_dsp(sc))
-goto no;
-if (mixer_init(dev, &essmixer_class, sc))
-goto no;
-
-sc->duplex = 0;
-sc->newspeed = 0;
-ver = (ess_getmixer(sc, 0x40) << 8) | ess_rd(sc, SB_MIX_DATA);
-snprintf(buf, sizeof buf, "ESS %x DSP", ver);
-device_set_desc_copy(dev, buf);
-if (bootverbose)
-device_printf(dev, "ESS%x detected", ver);
-
-switch (ver) {
-case 0x1869:
-case 0x1879:
+ struct ess_info *sc;
+ char status[SND_STATUSLEN], buf[64];
+ int ver;
+
+ sc = malloc(sizeof(*sc), M_DEVBUF, M_WAITOK | M_ZERO);
+ sc->parent_dev = device_get_parent(dev);
+ sc->bufsize = pcm_getbuffersize(dev, 4096, ESS_BUFFSIZE, 65536);
+ if (ess_alloc_resources(sc, dev))
+ goto no;
+ if (ess_reset_dsp(sc))
+ goto no;
+ if (mixer_init(dev, &essmixer_class, sc))
+ goto no;
+
+ sc->duplex = 0;
+ sc->newspeed = 0;
+ ver = (ess_getmixer(sc, 0x40) << 8) | ess_rd(sc, SB_MIX_DATA);
+ snprintf(buf, sizeof buf, "ESS %x DSP", ver);
+ device_set_desc_copy(dev, buf);
+ if (bootverbose)
+ device_printf(dev, "ESS%x detected", ver);
+
+ switch (ver) {
+ case 0x1869:
+ case 0x1879:
#ifdef ESS18XX_DUPLEX
-sc->duplex = sc->drq2? 1 : 0;
+ sc->duplex = sc->drq2? 1 : 0;
#endif
#ifdef ESS18XX_NEWSPEED
-sc->newspeed = 1;
+ sc->newspeed = 1;
#endif
-break;
-}
-if (bootverbose)
-printf("%s%sn", sc->duplex? ", duplex" : "",
-sc->newspeed? ", newspeed" : "");
-
-if (sc->newspeed)
-ess_setmixer(sc, 0x71, 0x22);
-
-snd_setup_intr(dev, sc->irq, 0, ess_intr, sc, &sc->ih);
-if (!sc->duplex)
-pcm_setflags(dev, pcm_getflags(dev) | SD_F_SIMPLEX);
-
-if (bus_dma_tag_create(/*parent*/NULL, /*alignment*/2, /*boundary*/0,
-/*lowaddr*/BUS_SPACE_MAXADDR_24BIT,
-/*highaddr*/BUS_SPACE_MAXADDR,
-/*filter*/NULL, /*filterarg*/NULL,
-/*maxsize*/sc->bufsize, /*nsegments*/1,
-/*maxsegz*/0x3ffff,
-/*flags*/0, /*lockfunc*/busdma_lock_mutex,
-/*lockarg*/&Giant, &sc->parent_dmat) != 0) {
-device_printf(dev, "unable to create dma tagn");
-goto no;
-}
-
-if (sc->drq2)
-snprintf(buf, SND_STATUSLEN, ":%ld", rman_get_start(sc->drq2));
-else
-buf[0] = '0';
-
-snprintf(status, SND_STATUSLEN, "at io 0x%lx irq %ld drq %ld%s bufsz %u %s",
-rman_get_start(sc->io_base), rman_get_start(sc->irq),
-rman_get_start(sc->drq1), buf, sc->bufsize,
-PCM_KLDSTRING(snd_ess));
-
-if (pcm_register(dev, sc, 1, 1))
-goto no;
-pcm_addchan(dev, PCMDIR_REC, &esschan_class, sc);
-pcm_addchan(dev, PCMDIR_PLAY, &esschan_class, sc);
-pcm_setstatus(dev, status);
+ break;
+ }
+ if (bootverbose)
+ printf("%s%s\n", sc->duplex? ", duplex" : "",
+ sc->newspeed? ", newspeed" : "");
+
+ if (sc->newspeed)
+ ess_setmixer(sc, 0x71, 0x22);
+
+ snd_setup_intr(dev, sc->irq, 0, ess_intr, sc, &sc->ih);
+ if (!sc->duplex)
+ pcm_setflags(dev, pcm_getflags(dev) | SD_F_SIMPLEX);
+
+ if (bus_dma_tag_create(/*parent*/bus_get_dma_tag(dev), /*alignment*/2,
+ /*boundary*/0,
+ /*lowaddr*/BUS_SPACE_MAXADDR_24BIT,
+ /*highaddr*/BUS_SPACE_MAXADDR,
+ /*filter*/NULL, /*filterarg*/NULL,
+ /*maxsize*/sc->bufsize, /*nsegments*/1,
+ /*maxsegz*/0x3ffff,
+ /*flags*/0, /*lockfunc*/busdma_lock_mutex,
+ /*lockarg*/&Giant, &sc->parent_dmat) != 0) {
+ device_printf(dev, "unable to create dma tag\n");
+ goto no;
+ }
+
+ if (sc->drq2)
+ snprintf(buf, SND_STATUSLEN, ":%ld", rman_get_start(sc->drq2));
+ else
+ buf[0] = '\0';
+
+ snprintf(status, SND_STATUSLEN, "at io 0x%lx irq %ld drq %ld%s bufsz %u %s",
+ rman_get_start(sc->io_base), rman_get_start(sc->irq),
+ rman_get_start(sc->drq1), buf, sc->bufsize,
+ PCM_KLDSTRING(snd_ess));
+
+ if (pcm_register(dev, sc, 1, 1))
+ goto no;
+ pcm_addchan(dev, PCMDIR_REC, &esschan_class, sc);
+ pcm_addchan(dev, PCMDIR_PLAY, &esschan_class, sc);
+ pcm_setstatus(dev, status);
-return 0;
+ return 0;
no:
-ess_release_resources(sc, dev);
-return ENXIO;
+ ess_release_resources(sc, dev);
+ return ENXIO;
}
static int
ess_detach(device_t dev)
{
-int r;
-struct ess_info *sc;
+ int r;
+ struct ess_info *sc;
-r = pcm_unregister(dev);
-if (r)
-return r;
-
-sc = pcm_getdevinfo(dev);
-ess_release_resources(sc, dev);
-return 0;
+ r = pcm_unregister(dev);
+ if (r)
+ return r;
+
+ sc = pcm_getdevinfo(dev);
+ ess_release_resources(sc, dev);
+ return 0;
}
static int
ess_resume(device_t dev)
{
-struct ess_info *sc;
+ struct ess_info *sc;
-sc = pcm_getdevinfo(dev);
+ sc = pcm_getdevinfo(dev);
-if (ess_reset_dsp(sc)) {
-device_printf(dev, "unable to reset DSP at resumen");
-return ENXIO;
-}
+ if (ess_reset_dsp(sc)) {
+ device_printf(dev, "unable to reset DSP at resume\n");
+ return ENXIO;
+ }
-if (mixer_reinit(dev)) {
-device_printf(dev, "unable to reinitialize mixer at resumen");
-return ENXIO;
-}
+ if (mixer_reinit(dev)) {
+ device_printf(dev, "unable to reinitialize mixer at resume\n");
+ return ENXIO;
+ }
-return 0;
+ return 0;
}
static device_method_t ess_methods[] = {
-/* Device interface */
-DEVMETHOD(device_probe, ess_probe),
-DEVMETHOD(device_attach, ess_attach),
-DEVMETHOD(device_detach, ess_detach),
-DEVMETHOD(device_resume, ess_resume),
+ /* Device interface */
+ DEVMETHOD(device_probe, ess_probe),
+ DEVMETHOD(device_attach, ess_attach),
+ DEVMETHOD(device_detach, ess_detach),
+ DEVMETHOD(device_resume, ess_resume),
-{ 0, 0 }
+ { 0, 0 }
};
static driver_t ess_driver = {
-"pcm",
-ess_methods,
-PCM_SOFTC_SIZE,
+ "pcm",
+ ess_methods,
+ PCM_SOFTC_SIZE,
};
DRIVER_MODULE(snd_ess, sbc, ess_driver, pcm_devclass, 0, 0);
@@ -947,66 +946,66 @@
static devclass_t esscontrol_devclass;
static struct isa_pnp_id essc_ids[] = {
-{0x06007316, "ESS Control"},
-{0}
+ {0x06007316, "ESS Control"},
+ {0}
};
static int
esscontrol_probe(device_t dev)
{
-int i;
+ int i;
-i = ISA_PNP_PROBE(device_get_parent(dev), dev, essc_ids);
-if (i == 0)
-device_quiet(dev);
-return i;
+ i = ISA_PNP_PROBE(device_get_parent(dev), dev, essc_ids);
+ if (i == 0)
+ device_quiet(dev);
+ return i;
}
static int
esscontrol_attach(device_t dev)
{
#ifdef notyet
-struct resource *io;
-int rid, i, x;
+ struct resource *io;
+ int rid, i, x;
-rid = 0;
-io = bus_alloc_resource_any(dev, SYS_RES_IOPORT, &rid, RF_ACTIVE);
-x = 0;
-for (i = 0; i < 0x100; i++) {
-port_wr(io, 0, i);
-x = port_rd(io, 1);
-if ((i & 0x0f) == 0)
-printf("%3.3x: ", i);
-printf("%2.2x ", x);
-if ((i & 0x0f) == 0x0f)
-printf("n");
-}
-bus_release_resource(dev, SYS_RES_IOPORT, 0, io);
-io = NULL;
+ rid = 0;
+ io = bus_alloc_resource_any(dev, SYS_RES_IOPORT, &rid, RF_ACTIVE);
+ x = 0;
+ for (i = 0; i < 0x100; i++) {
+ port_wr(io, 0, i);
+ x = port_rd(io, 1);
+ if ((i & 0x0f) == 0)
+ printf("%3.3x: ", i);
+ printf("%2.2x ", x);
+ if ((i & 0x0f) == 0x0f)
+ printf("\n");
+ }
+ bus_release_resource(dev, SYS_RES_IOPORT, 0, io);
+ io = NULL;
#endif
-return 0;
+ return 0;
}
static int
esscontrol_detach(device_t dev)
{
-return 0;
+ return 0;
}
static device_method_t esscontrol_methods[] = {
-/* Device interface */
-DEVMETHOD(device_probe, esscontrol_probe),
-DEVMETHOD(device_attach, esscontrol_attach),
-DEVMETHOD(device_detach, esscontrol_detach),
+ /* Device interface */
+ DEVMETHOD(device_probe, esscontrol_probe),
+ DEVMETHOD(device_attach, esscontrol_attach),
+ DEVMETHOD(device_detach, esscontrol_detach),
-{ 0, 0 }
+ { 0, 0 }
};
static driver_t esscontrol_driver = {
-"esscontrol",
-esscontrol_methods,
-1,
+ "esscontrol",
+ esscontrol_methods,
+ 1,
};
DRIVER_MODULE(esscontrol, isa, esscontrol_driver, esscontrol_devclass, 0, 0);
Index: mss.c
===================================================================
RCS file: /home/cvs/src/sys/dev/sound/isa/mss.c,v
retrieving revision 1.3
retrieving revision 1.4
diff -L sys/dev/sound/isa/mss.c -L sys/dev/sound/isa/mss.c -u -r1.3 -r1.4
--- sys/dev/sound/isa/mss.c
+++ sys/dev/sound/isa/mss.c
@@ -1,35 +1,35 @@
/*-
-* Copyright (c) 2001 George Reid <greid at ukug.uk.freebsd.org>
-* Copyright (c) 1999 Cameron Grant <cg at freebsd.org>
-* Copyright Luigi Rizzo, 1997,1998
-* Copyright by Hannu Savolainen 1994, 1995
-* All rights reserved.
-*
-* Redistribution and use in source and binary forms, with or without
-* modification, are permitted provided that the following conditions
-* are met:
-* 1. Redistributions of source code must retain the above copyright
-* notice, this list of conditions and the following disclaimer.
-* 2. Redistributions in binary form must reproduce the above copyright
-* notice, this list of conditions and the following disclaimer in the
-* documentation and/or other materials provided with the distribution.
-*
-* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
-* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
-* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
-* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
-* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
-* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
-* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
-* SUCH DAMAGE.
-*/
+ * Copyright (c) 2001 George Reid <greid at ukug.uk.freebsd.org>
+ * Copyright (c) 1999 Cameron Grant <cg at freebsd.org>
+ * Copyright (c) 1997,1998 Luigi Rizzo
+ * Copyright (c) 1994,1995 Hannu Savolainen
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
#include <dev/sound/pcm/sound.h>
-SND_DECLARE_FILE("$MidnightBSD$");
+SND_DECLARE_FILE("$FreeBSD: src/sys/dev/sound/isa/mss.c,v 1.112 2007/06/17 06:10:40 ariff Exp $");
/* board-specific include files */
#include <dev/sound/isa/mss.h>
@@ -47,42 +47,42 @@
struct mss_info;
struct mss_chinfo {
-struct mss_info *parent;
-struct pcm_channel *channel;
-struct snd_dbuf *buffer;
-int dir;
-u_int32_t fmt, blksz;
+ struct mss_info *parent;
+ struct pcm_channel *channel;
+ struct snd_dbuf *buffer;
+ int dir;
+ u_int32_t fmt, blksz;
};
struct mss_info {
-struct resource *io_base; /* primary I/O address for the board */
-int io_rid;
-struct resource *conf_base; /* and the opti931 also has a config space */
-int conf_rid;
-struct resource *irq;
-int irq_rid;
-struct resource *drq1; /* play */
-int drq1_rid;
-struct resource *drq2; /* rec */
-int drq2_rid;
-void *ih;
-bus_dma_tag_t parent_dmat;
-struct mtx *lock;
-
-char mss_indexed_regs[MSS_INDEXED_REGS];
-char opl_indexed_regs[OPL_INDEXED_REGS];
-int bd_id; /* used to hold board-id info, eg. sb version,
-* mss codec type, etc. etc.
-*/
-int opti_offset; /* offset from config_base for opti931 */
-u_long bd_flags; /* board-specific flags */
-int optibase; /* base address for OPTi9xx config */
-struct resource *indir; /* Indirect register index address */
-int indir_rid;
-int password; /* password for opti9xx cards */
-int passwdreg; /* password register */
-unsigned int bufsize;
-struct mss_chinfo pch, rch;
+ struct resource *io_base; /* primary I/O address for the board */
+ int io_rid;
+ struct resource *conf_base; /* and the opti931 also has a config space */
+ int conf_rid;
+ struct resource *irq;
+ int irq_rid;
+ struct resource *drq1; /* play */
+ int drq1_rid;
+ struct resource *drq2; /* rec */
+ int drq2_rid;
+ void *ih;
+ bus_dma_tag_t parent_dmat;
+ struct mtx *lock;
+
+ char mss_indexed_regs[MSS_INDEXED_REGS];
+ char opl_indexed_regs[OPL_INDEXED_REGS];
+ int bd_id; /* used to hold board-id info, eg. sb version,
+ * mss codec type, etc. etc.
+ */
+ int opti_offset; /* offset from config_base for opti931 */
+ u_long bd_flags; /* board-specific flags */
+ int optibase; /* base address for OPTi9xx config */
+ struct resource *indir; /* Indirect register index address */
+ int indir_rid;
+ int password; /* password for opti9xx cards */
+ int passwdreg; /* password register */
+ unsigned int bufsize;
+ struct mss_chinfo pch, rch;
};
static int mss_probe(device_t dev);
@@ -112,7 +112,7 @@
/* OPTi-specific functions */
static void opti_write(struct mss_info *mss, u_char reg,
-u_char data);
+ u_char data);
#ifndef PC98
static u_char opti_read(struct mss_info *mss, u_char reg);
#endif
@@ -128,35 +128,35 @@
static driver_intr_t opti931_intr;
static u_int32_t mss_fmt[] = {
-AFMT_U8,
-AFMT_STEREO | AFMT_U8,
-AFMT_S16_LE,
-AFMT_STEREO | AFMT_S16_LE,
-AFMT_MU_LAW,
-AFMT_STEREO | AFMT_MU_LAW,
-AFMT_A_LAW,
-AFMT_STEREO | AFMT_A_LAW,
-0
+ AFMT_U8,
+ AFMT_STEREO | AFMT_U8,
+ AFMT_S16_LE,
+ AFMT_STEREO | AFMT_S16_LE,
+ AFMT_MU_LAW,
+ AFMT_STEREO | AFMT_MU_LAW,
+ AFMT_A_LAW,
+ AFMT_STEREO | AFMT_A_LAW,
+ 0
};
static struct pcmchan_caps mss_caps = {4000, 48000, mss_fmt, 0};
static u_int32_t guspnp_fmt[] = {
-AFMT_U8,
-AFMT_STEREO | AFMT_U8,
-AFMT_S16_LE,
-AFMT_STEREO | AFMT_S16_LE,
-AFMT_A_LAW,
-AFMT_STEREO | AFMT_A_LAW,
-0
+ AFMT_U8,
+ AFMT_STEREO | AFMT_U8,
+ AFMT_S16_LE,
+ AFMT_STEREO | AFMT_S16_LE,
+ AFMT_A_LAW,
+ AFMT_STEREO | AFMT_A_LAW,
+ 0
};
static struct pcmchan_caps guspnp_caps = {4000, 48000, guspnp_fmt, 0};
static u_int32_t opti931_fmt[] = {
-AFMT_U8,
-AFMT_STEREO | AFMT_U8,
-AFMT_S16_LE,
-AFMT_STEREO | AFMT_S16_LE,
-0
+ AFMT_U8,
+ AFMT_STEREO | AFMT_U8,
+ AFMT_S16_LE,
+ AFMT_STEREO | AFMT_S16_LE,
+ 0
};
static struct pcmchan_caps opti931_caps = {4000, 48000, opti931_fmt, 0};
@@ -180,210 +180,210 @@
static void
mss_lock(struct mss_info *mss)
{
-snd_mtxlock(mss->lock);
+ snd_mtxlock(mss->lock);
}
static void
mss_unlock(struct mss_info *mss)
{
-snd_mtxunlock(mss->lock);
+ snd_mtxunlock(mss->lock);
}
static int
port_rd(struct resource *port, int off)
{
-if (port)
-return bus_space_read_1(rman_get_bustag(port),
-rman_get_bushandle(port),
-off);
-else
-return -1;
+ if (port)
+ return bus_space_read_1(rman_get_bustag(port),
+ rman_get_bushandle(port),
+ off);
+ else
+ return -1;
}
static void
port_wr(struct resource *port, int off, u_int8_t data)
{
-if (port)
-bus_space_write_1(rman_get_bustag(port),
-rman_get_bushandle(port),
-off, data);
+ if (port)
+ bus_space_write_1(rman_get_bustag(port),
+ rman_get_bushandle(port),
+ off, data);
}
static int
io_rd(struct mss_info *mss, int reg)
{
-if (mss->bd_flags & BD_F_MSS_OFFSET) reg -= 4;
-return port_rd(mss->io_base, reg);
+ if (mss->bd_flags & BD_F_MSS_OFFSET) reg -= 4;
+ return port_rd(mss->io_base, reg);
}
static void
io_wr(struct mss_info *mss, int reg, u_int8_t data)
{
-if (mss->bd_flags & BD_F_MSS_OFFSET) reg -= 4;
-port_wr(mss->io_base, reg, data);
+ if (mss->bd_flags & BD_F_MSS_OFFSET) reg -= 4;
+ port_wr(mss->io_base, reg, data);
}
static void
conf_wr(struct mss_info *mss, u_char reg, u_char value)
{
-port_wr(mss->conf_base, 0, reg);
-port_wr(mss->conf_base, 1, value);
+ port_wr(mss->conf_base, 0, reg);
+ port_wr(mss->conf_base, 1, value);
}
static u_char
conf_rd(struct mss_info *mss, u_char reg)
{
-port_wr(mss->conf_base, 0, reg);
-return port_rd(mss->conf_base, 1);
+ port_wr(mss->conf_base, 0, reg);
+ return port_rd(mss->conf_base, 1);
}
static void
opti_wr(struct mss_info *mss, u_char reg, u_char value)
{
-port_wr(mss->conf_base, mss->opti_offset + 0, reg);
-port_wr(mss->conf_base, mss->opti_offset + 1, value);
+ port_wr(mss->conf_base, mss->opti_offset + 0, reg);
+ port_wr(mss->conf_base, mss->opti_offset + 1, value);
}
static u_char
opti_rd(struct mss_info *mss, u_char reg)
{
-port_wr(mss->conf_base, mss->opti_offset + 0, reg);
-return port_rd(mss->conf_base, mss->opti_offset + 1);
+ port_wr(mss->conf_base, mss->opti_offset + 0, reg);
+ return port_rd(mss->conf_base, mss->opti_offset + 1);
}
static void
gus_wr(struct mss_info *mss, u_char reg, u_char value)
{
-port_wr(mss->conf_base, 3, reg);
-port_wr(mss->conf_base, 5, value);
+ port_wr(mss->conf_base, 3, reg);
+ port_wr(mss->conf_base, 5, value);
}
static u_char
gus_rd(struct mss_info *mss, u_char reg)
{
-port_wr(mss->conf_base, 3, reg);
-return port_rd(mss->conf_base, 5);
+ port_wr(mss->conf_base, 3, reg);
+ return port_rd(mss->conf_base, 5);
}
static void
mss_release_resources(struct mss_info *mss, device_t dev)
{
-if (mss->irq) {
-if (mss->ih)
-bus_teardown_intr(dev, mss->irq, mss->ih);
-bus_release_resource(dev, SYS_RES_IRQ, mss->irq_rid,
-mss->irq);
-mss->irq = 0;
-}
-if (mss->drq2) {
-if (mss->drq2 != mss->drq1) {
-isa_dma_release(rman_get_start(mss->drq2));
-bus_release_resource(dev, SYS_RES_DRQ, mss->drq2_rid,
-mss->drq2);
-}
-mss->drq2 = 0;
-}
-if (mss->drq1) {
-isa_dma_release(rman_get_start(mss->drq1));
-bus_release_resource(dev, SYS_RES_DRQ, mss->drq1_rid,
-mss->drq1);
-mss->drq1 = 0;
-}
-if (mss->io_base) {
-bus_release_resource(dev, SYS_RES_IOPORT, mss->io_rid,
-mss->io_base);
-mss->io_base = 0;
-}
-if (mss->conf_base) {
-bus_release_resource(dev, SYS_RES_IOPORT, mss->conf_rid,
-mss->conf_base);
-mss->conf_base = 0;
-}
-if (mss->indir) {
-bus_release_resource(dev, SYS_RES_IOPORT, mss->indir_rid,
-mss->indir);
-mss->indir = 0;
-}
-if (mss->parent_dmat) {
-bus_dma_tag_destroy(mss->parent_dmat);
-mss->parent_dmat = 0;
-}
-if (mss->lock) snd_mtxfree(mss->lock);
+ if (mss->irq) {
+ if (mss->ih)
+ bus_teardown_intr(dev, mss->irq, mss->ih);
+ bus_release_resource(dev, SYS_RES_IRQ, mss->irq_rid,
+ mss->irq);
+ mss->irq = 0;
+ }
+ if (mss->drq2) {
+ if (mss->drq2 != mss->drq1) {
+ isa_dma_release(rman_get_start(mss->drq2));
+ bus_release_resource(dev, SYS_RES_DRQ, mss->drq2_rid,
+ mss->drq2);
+ }
+ mss->drq2 = 0;
+ }
+ if (mss->drq1) {
+ isa_dma_release(rman_get_start(mss->drq1));
+ bus_release_resource(dev, SYS_RES_DRQ, mss->drq1_rid,
+ mss->drq1);
+ mss->drq1 = 0;
+ }
+ if (mss->io_base) {
+ bus_release_resource(dev, SYS_RES_IOPORT, mss->io_rid,
+ mss->io_base);
+ mss->io_base = 0;
+ }
+ if (mss->conf_base) {
+ bus_release_resource(dev, SYS_RES_IOPORT, mss->conf_rid,
+ mss->conf_base);
+ mss->conf_base = 0;
+ }
+ if (mss->indir) {
+ bus_release_resource(dev, SYS_RES_IOPORT, mss->indir_rid,
+ mss->indir);
+ mss->indir = 0;
+ }
+ if (mss->parent_dmat) {
+ bus_dma_tag_destroy(mss->parent_dmat);
+ mss->parent_dmat = 0;
+ }
+ if (mss->lock) snd_mtxfree(mss->lock);
-free(mss, M_DEVBUF);
+ free(mss, M_DEVBUF);
}
static int
mss_alloc_resources(struct mss_info *mss, device_t dev)
{
-int pdma, rdma, ok = 1;
-if (!mss->io_base)
-mss->io_base = bus_alloc_resource_any(dev, SYS_RES_IOPORT,
-&mss->io_rid, RF_ACTIVE);
-if (!mss->irq)
-mss->irq = bus_alloc_resource_any(dev, SYS_RES_IRQ,
-&mss->irq_rid, RF_ACTIVE);
-if (!mss->drq1)
-mss->drq1 = bus_alloc_resource_any(dev, SYS_RES_DRQ,
-&mss->drq1_rid,
-RF_ACTIVE);
-if (mss->conf_rid >= 0 && !mss->conf_base)
-mss->conf_base = bus_alloc_resource_any(dev, SYS_RES_IOPORT,
-&mss->conf_rid,
-RF_ACTIVE);
-if (mss->drq2_rid >= 0 && !mss->drq2)
-mss->drq2 = bus_alloc_resource_any(dev, SYS_RES_DRQ,
-&mss->drq2_rid,
-RF_ACTIVE);
-
-if (!mss->io_base || !mss->drq1 || !mss->irq) ok = 0;
-if (mss->conf_rid >= 0 && !mss->conf_base) ok = 0;
-if (mss->drq2_rid >= 0 && !mss->drq2) ok = 0;
-
-if (ok) {
-pdma = rman_get_start(mss->drq1);
-isa_dma_acquire(pdma);
-isa_dmainit(pdma, mss->bufsize);
-mss->bd_flags &= ~BD_F_DUPLEX;
-if (mss->drq2) {
-rdma = rman_get_start(mss->drq2);
-isa_dma_acquire(rdma);
-isa_dmainit(rdma, mss->bufsize);
-mss->bd_flags |= BD_F_DUPLEX;
-} else mss->drq2 = mss->drq1;
-}
-return ok;
+ int pdma, rdma, ok = 1;
+ if (!mss->io_base)
+ mss->io_base = bus_alloc_resource_any(dev, SYS_RES_IOPORT,
+ &mss->io_rid, RF_ACTIVE);
+ if (!mss->irq)
+ mss->irq = bus_alloc_resource_any(dev, SYS_RES_IRQ,
+ &mss->irq_rid, RF_ACTIVE);
+ if (!mss->drq1)
+ mss->drq1 = bus_alloc_resource_any(dev, SYS_RES_DRQ,
+ &mss->drq1_rid,
+ RF_ACTIVE);
+ if (mss->conf_rid >= 0 && !mss->conf_base)
+ mss->conf_base = bus_alloc_resource_any(dev, SYS_RES_IOPORT,
+ &mss->conf_rid,
+ RF_ACTIVE);
+ if (mss->drq2_rid >= 0 && !mss->drq2)
+ mss->drq2 = bus_alloc_resource_any(dev, SYS_RES_DRQ,
+ &mss->drq2_rid,
+ RF_ACTIVE);
+
+ if (!mss->io_base || !mss->drq1 || !mss->irq) ok = 0;
+ if (mss->conf_rid >= 0 && !mss->conf_base) ok = 0;
+ if (mss->drq2_rid >= 0 && !mss->drq2) ok = 0;
+
+ if (ok) {
+ pdma = rman_get_start(mss->drq1);
+ isa_dma_acquire(pdma);
+ isa_dmainit(pdma, mss->bufsize);
+ mss->bd_flags &= ~BD_F_DUPLEX;
+ if (mss->drq2) {
+ rdma = rman_get_start(mss->drq2);
+ isa_dma_acquire(rdma);
+ isa_dmainit(rdma, mss->bufsize);
+ mss->bd_flags |= BD_F_DUPLEX;
+ } else mss->drq2 = mss->drq1;
+ }
+ return ok;
}
/*
-* The various mixers use a variety of bitmasks etc. The Voxware
-* driver had a very nice technique to describe a mixer and interface
-* to it. A table defines, for each channel, which register, bits,
-* offset, polarity to use. This procedure creates the new value
-* using the table and the old value.
-*/
+ * The various mixers use a variety of bitmasks etc. The Voxware
+ * driver had a very nice technique to describe a mixer and interface
+ * to it. A table defines, for each channel, which register, bits,
+ * offset, polarity to use. This procedure creates the new value
+ * using the table and the old value.
+ */
static void
change_bits(mixer_tab *t, u_char *regval, int dev, int chn, int newval)
{
-u_char mask;
-int shift;
+ u_char mask;
+ int shift;
-DEB(printf("ch_bits dev %d ch %d val %d old 0x%02x "
-"r %d p %d bit %d off %dn",
-dev, chn, newval, *regval,
-(*t)[dev][chn].regno, (*t)[dev][chn].polarity,
-(*t)[dev][chn].nbits, (*t)[dev][chn].bitoffs ) );
-
-if ( (*t)[dev][chn].polarity == 1) /* reverse */
-newval = 100 - newval ;
-
-mask = (1 << (*t)[dev][chn].nbits) - 1;
-newval = (int) ((newval * mask) + 50) / 100; /* Scale it */
-shift = (*t)[dev][chn].bitoffs /*- (*t)[dev][LEFT_CHN].nbits + 1*/;
+ DEB(printf("ch_bits dev %d ch %d val %d old 0x%02x "
+ "r %d p %d bit %d off %d\n",
+ dev, chn, newval, *regval,
+ (*t)[dev][chn].regno, (*t)[dev][chn].polarity,
+ (*t)[dev][chn].nbits, (*t)[dev][chn].bitoffs ) );
+
+ if ( (*t)[dev][chn].polarity == 1) /* reverse */
+ newval = 100 - newval ;
+
+ mask = (1 << (*t)[dev][chn].nbits) - 1;
+ newval = (int) ((newval * mask) + 50) / 100; /* Scale it */
+ shift = (*t)[dev][chn].bitoffs /*- (*t)[dev][LEFT_CHN].nbits + 1*/;
-*regval &= ~(mask << shift); /* Filter out the previous value */
-*regval |= (newval & mask) << shift; /* Set the new value */
+ *regval &= ~(mask << shift); /* Filter out the previous value */
+ *regval |= (newval & mask) << shift; /* Set the new value */
}
/* -------------------------------------------------------------------- */
@@ -391,83 +391,83 @@
static int
mss_set_recsrc(struct mss_info *mss, int mask)
{
-u_char recdev;
+ u_char recdev;
-switch (mask) {
-case SOUND_MASK_LINE:
-case SOUND_MASK_LINE3:
-recdev = 0;
-break;
-
-case SOUND_MASK_CD:
-case SOUND_MASK_LINE1:
-recdev = 0x40;
-break;
-
-case SOUND_MASK_IMIX:
-recdev = 0xc0;
-break;
-
-case SOUND_MASK_MIC:
-default:
-mask = SOUND_MASK_MIC;
-recdev = 0x80;
-}
-ad_write(mss, 0, (ad_read(mss, 0) & 0x3f) | recdev);
-ad_write(mss, 1, (ad_read(mss, 1) & 0x3f) | recdev);
-return mask;
+ switch (mask) {
+ case SOUND_MASK_LINE:
+ case SOUND_MASK_LINE3:
+ recdev = 0;
+ break;
+
+ case SOUND_MASK_CD:
+ case SOUND_MASK_LINE1:
+ recdev = 0x40;
+ break;
+
+ case SOUND_MASK_IMIX:
+ recdev = 0xc0;
+ break;
+
+ case SOUND_MASK_MIC:
+ default:
+ mask = SOUND_MASK_MIC;
+ recdev = 0x80;
+ }
+ ad_write(mss, 0, (ad_read(mss, 0) & 0x3f) | recdev);
+ ad_write(mss, 1, (ad_read(mss, 1) & 0x3f) | recdev);
+ return mask;
}
/* there are differences in the mixer depending on the actual sound card. */
static int
mss_mixer_set(struct mss_info *mss, int dev, int left, int right)
{
-int regoffs;
-mixer_tab *mix_d;
-u_char old, val;
-
-switch (mss->bd_id) {
-case MD_OPTI931:
-mix_d = &opti931_devices;
-break;
-case MD_OPTI930:
-mix_d = &opti930_devices;
-break;
-default:
-mix_d = &mix_devices;
-}
-
-if ((*mix_d)[dev][LEFT_CHN].nbits == 0) {
-DEB(printf("nbits = 0 for dev %dn", dev));
-return -1;
-}
-
-if ((*mix_d)[dev][RIGHT_CHN].nbits == 0) right = left; /* mono */
-
-/* Set the left channel */
-
-regoffs = (*mix_d)[dev][LEFT_CHN].regno;
-old = val = ad_read(mss, regoffs);
-/* if volume is 0, mute chan. Otherwise, unmute. */
-if (regoffs != 0) val = (left == 0)? old | 0x80 : old & 0x7f;
-change_bits(mix_d, &val, dev, LEFT_CHN, left);
-ad_write(mss, regoffs, val);
-
-DEB(printf("LEFT: dev %d reg %d old 0x%02x new 0x%02xn",
-dev, regoffs, old, val));
-
-if ((*mix_d)[dev][RIGHT_CHN].nbits != 0) { /* have stereo */
-/* Set the right channel */
-regoffs = (*mix_d)[dev][RIGHT_CHN].regno;
-old = val = ad_read(mss, regoffs);
-if (regoffs != 1) val = (right == 0)? old | 0x80 : old & 0x7f;
-change_bits(mix_d, &val, dev, RIGHT_CHN, right);
-ad_write(mss, regoffs, val);
-
-DEB(printf("RIGHT: dev %d reg %d old 0x%02x new 0x%02xn",
-dev, regoffs, old, val));
-}
-return 0; /* success */
+ int regoffs;
+ mixer_tab *mix_d;
+ u_char old, val;
+
+ switch (mss->bd_id) {
+ case MD_OPTI931:
+ mix_d = &opti931_devices;
+ break;
+ case MD_OPTI930:
+ mix_d = &opti930_devices;
+ break;
+ default:
+ mix_d = &mix_devices;
+ }
+
+ if ((*mix_d)[dev][LEFT_CHN].nbits == 0) {
+ DEB(printf("nbits = 0 for dev %d\n", dev));
+ return -1;
+ }
+
+ if ((*mix_d)[dev][RIGHT_CHN].nbits == 0) right = left; /* mono */
+
+ /* Set the left channel */
+
+ regoffs = (*mix_d)[dev][LEFT_CHN].regno;
+ old = val = ad_read(mss, regoffs);
+ /* if volume is 0, mute chan. Otherwise, unmute. */
+ if (regoffs != 0) val = (left == 0)? old | 0x80 : old & 0x7f;
+ change_bits(mix_d, &val, dev, LEFT_CHN, left);
+ ad_write(mss, regoffs, val);
+
+ DEB(printf("LEFT: dev %d reg %d old 0x%02x new 0x%02x\n",
+ dev, regoffs, old, val));
+
+ if ((*mix_d)[dev][RIGHT_CHN].nbits != 0) { /* have stereo */
+ /* Set the right channel */
+ regoffs = (*mix_d)[dev][RIGHT_CHN].regno;
+ old = val = ad_read(mss, regoffs);
+ if (regoffs != 1) val = (right == 0)? old | 0x80 : old & 0x7f;
+ change_bits(mix_d, &val, dev, RIGHT_CHN, right);
+ ad_write(mss, regoffs, val);
+
+ DEB(printf("RIGHT: dev %d reg %d old 0x%02x new 0x%02x\n",
+ dev, regoffs, old, val));
+ }
+ return 0; /* success */
}
/* -------------------------------------------------------------------- */
@@ -475,67 +475,67 @@
static int
mssmix_init(struct snd_mixer *m)
{
-struct mss_info *mss = mix_getdevinfo(m);
+ struct mss_info *mss = mix_getdevinfo(m);
-mix_setdevs(m, MODE2_MIXER_DEVICES);
-mix_setrecdevs(m, MSS_REC_DEVICES);
-switch(mss->bd_id) {
-case MD_OPTI930:
-mix_setdevs(m, OPTI930_MIXER_DEVICES);
-break;
-
-case MD_OPTI931:
-mix_setdevs(m, OPTI931_MIXER_DEVICES);
-mss_lock(mss);
-ad_write(mss, 20, 0x88);
-ad_write(mss, 21, 0x88);
-mss_unlock(mss);
-break;
-
-case MD_AD1848:
-mix_setdevs(m, MODE1_MIXER_DEVICES);
-break;
-
-case MD_GUSPNP:
-case MD_GUSMAX:
-/* this is only necessary in mode 3 ... */
-mss_lock(mss);
-ad_write(mss, 22, 0x88);
-ad_write(mss, 23, 0x88);
-mss_unlock(mss);
-break;
-}
-return 0;
+ mix_setdevs(m, MODE2_MIXER_DEVICES);
+ mix_setrecdevs(m, MSS_REC_DEVICES);
+ switch(mss->bd_id) {
+ case MD_OPTI930:
+ mix_setdevs(m, OPTI930_MIXER_DEVICES);
+ break;
+
+ case MD_OPTI931:
+ mix_setdevs(m, OPTI931_MIXER_DEVICES);
+ mss_lock(mss);
+ ad_write(mss, 20, 0x88);
+ ad_write(mss, 21, 0x88);
+ mss_unlock(mss);
+ break;
+
+ case MD_AD1848:
+ mix_setdevs(m, MODE1_MIXER_DEVICES);
+ break;
+
+ case MD_GUSPNP:
+ case MD_GUSMAX:
+ /* this is only necessary in mode 3 ... */
+ mss_lock(mss);
+ ad_write(mss, 22, 0x88);
+ ad_write(mss, 23, 0x88);
+ mss_unlock(mss);
+ break;
+ }
+ return 0;
}
static int
mssmix_set(struct snd_mixer *m, unsigned dev, unsigned left, unsigned right)
{
-struct mss_info *mss = mix_getdevinfo(m);
+ struct mss_info *mss = mix_getdevinfo(m);
-mss_lock(mss);
-mss_mixer_set(mss, dev, left, right);
-mss_unlock(mss);
+ mss_lock(mss);
+ mss_mixer_set(mss, dev, left, right);
+ mss_unlock(mss);
-return left | (right << 8);
+ return left | (right << 8);
}
static int
mssmix_setrecsrc(struct snd_mixer *m, u_int32_t src)
{
-struct mss_info *mss = mix_getdevinfo(m);
+ struct mss_info *mss = mix_getdevinfo(m);
-mss_lock(mss);
-src = mss_set_recsrc(mss, src);
-mss_unlock(mss);
-return src;
+ mss_lock(mss);
+ src = mss_set_recsrc(mss, src);
+ mss_unlock(mss);
+ return src;
}
static kobj_method_t mssmix_mixer_methods[] = {
-KOBJMETHOD(mixer_init, mssmix_init),
-KOBJMETHOD(mixer_set, mssmix_set),
-KOBJMETHOD(mixer_setrecsrc, mssmix_setrecsrc),
-{ 0, 0 }
+ KOBJMETHOD(mixer_init, mssmix_init),
+ KOBJMETHOD(mixer_set, mssmix_set),
+ KOBJMETHOD(mixer_setrecsrc, mssmix_setrecsrc),
+ { 0, 0 }
};
MIXER_DECLARE(mssmix_mixer);
@@ -544,598 +544,600 @@
static int
ymmix_init(struct snd_mixer *m)
{
-struct mss_info *mss = mix_getdevinfo(m);
+ struct mss_info *mss = mix_getdevinfo(m);
-mssmix_init(m);
-mix_setdevs(m, mix_getdevs(m) | SOUND_MASK_VOLUME | SOUND_MASK_MIC
-| SOUND_MASK_BASS | SOUND_MASK_TREBLE);
-/* Set master volume */
-mss_lock(mss);
-conf_wr(mss, OPL3SAx_VOLUMEL, 7);
-conf_wr(mss, OPL3SAx_VOLUMER, 7);
-mss_unlock(mss);
+ mssmix_init(m);
+ mix_setdevs(m, mix_getdevs(m) | SOUND_MASK_VOLUME | SOUND_MASK_MIC
+ | SOUND_MASK_BASS | SOUND_MASK_TREBLE);
+ /* Set master volume */
+ mss_lock(mss);
+ conf_wr(mss, OPL3SAx_VOLUMEL, 7);
+ conf_wr(mss, OPL3SAx_VOLUMER, 7);
+ mss_unlock(mss);
-return 0;
+ return 0;
}
static int
ymmix_set(struct snd_mixer *m, unsigned dev, unsigned left, unsigned right)
{
-struct mss_info *mss = mix_getdevinfo(m);
-int t, l, r;
-
-mss_lock(mss);
-switch (dev) {
-case SOUND_MIXER_VOLUME:
-if (left) t = 15 - (left * 15) / 100;
-else t = 0x80; /* mute */
-conf_wr(mss, OPL3SAx_VOLUMEL, t);
-if (right) t = 15 - (right * 15) / 100;
-else t = 0x80; /* mute */
-conf_wr(mss, OPL3SAx_VOLUMER, t);
-break;
-
-case SOUND_MIXER_MIC:
-t = left;
-if (left) t = 31 - (left * 31) / 100;
-else t = 0x80; /* mute */
-conf_wr(mss, OPL3SAx_MIC, t);
-break;
-
-case SOUND_MIXER_BASS:
-l = (left * 7) / 100;
-r = (right * 7) / 100;
-t = (r << 4) | l;
-conf_wr(mss, OPL3SAx_BASS, t);
-break;
-
-case SOUND_MIXER_TREBLE:
-l = (left * 7) / 100;
-r = (right * 7) / 100;
-t = (r << 4) | l;
-conf_wr(mss, OPL3SAx_TREBLE, t);
-break;
+ struct mss_info *mss = mix_getdevinfo(m);
+ int t, l, r;
-default:
-mss_mixer_set(mss, dev, left, right);
-}
-mss_unlock(mss);
+ mss_lock(mss);
+ switch (dev) {
+ case SOUND_MIXER_VOLUME:
+ if (left) t = 15 - (left * 15) / 100;
+ else t = 0x80; /* mute */
+ conf_wr(mss, OPL3SAx_VOLUMEL, t);
+ if (right) t = 15 - (right * 15) / 100;
+ else t = 0x80; /* mute */
+ conf_wr(mss, OPL3SAx_VOLUMER, t);
+ break;
+
+ case SOUND_MIXER_MIC:
+ t = left;
+ if (left) t = 31 - (left * 31) / 100;
+ else t = 0x80; /* mute */
+ conf_wr(mss, OPL3SAx_MIC, t);
+ break;
+
+ case SOUND_MIXER_BASS:
+ l = (left * 7) / 100;
+ r = (right * 7) / 100;
+ t = (r << 4) | l;
+ conf_wr(mss, OPL3SAx_BASS, t);
+ break;
+
+ case SOUND_MIXER_TREBLE:
+ l = (left * 7) / 100;
+ r = (right * 7) / 100;
+ t = (r << 4) | l;
+ conf_wr(mss, OPL3SAx_TREBLE, t);
+ break;
+
+ default:
+ mss_mixer_set(mss, dev, left, right);
+ }
+ mss_unlock(mss);
-return left | (right << 8);
+ return left | (right << 8);
}
static int
ymmix_setrecsrc(struct snd_mixer *m, u_int32_t src)
{
-struct mss_info *mss = mix_getdevinfo(m);
-mss_lock(mss);
-src = mss_set_recsrc(mss, src);
-mss_unlock(mss);
-return src;
+ struct mss_info *mss = mix_getdevinfo(m);
+ mss_lock(mss);
+ src = mss_set_recsrc(mss, src);
+ mss_unlock(mss);
+ return src;
}
static kobj_method_t ymmix_mixer_methods[] = {
-KOBJMETHOD(mixer_init, ymmix_init),
-KOBJMETHOD(mixer_set, ymmix_set),
-KOBJMETHOD(mixer_setrecsrc, ymmix_setrecsrc),
-{ 0, 0 }
+ KOBJMETHOD(mixer_init, ymmix_init),
+ KOBJMETHOD(mixer_set, ymmix_set),
+ KOBJMETHOD(mixer_setrecsrc, ymmix_setrecsrc),
+ { 0, 0 }
};
MIXER_DECLARE(ymmix_mixer);
/* -------------------------------------------------------------------- */
/*
-* XXX This might be better off in the gusc driver.
-*/
+ * XXX This might be better off in the gusc driver.
+ */
static void
gusmax_setup(struct mss_info *mss, device_t dev, struct resource *alt)
{
-static const unsigned char irq_bits[16] = {
-0, 0, 0, 3, 0, 2, 0, 4, 0, 1, 0, 5, 6, 0, 0, 7
-};
-static const unsigned char dma_bits[8] = {
-0, 1, 0, 2, 0, 3, 4, 5
-};
-device_t parent = device_get_parent(dev);
-unsigned char irqctl, dmactl;
-int s;
-
-s = splhigh();
-
-port_wr(alt, 0x0f, 0x05);
-port_wr(alt, 0x00, 0x0c);
-port_wr(alt, 0x0b, 0x00);
-
-port_wr(alt, 0x0f, 0x00);
-
-irqctl = irq_bits[isa_get_irq(parent)];
-/* Share the IRQ with the MIDI driver. */
-irqctl |= 0x40;
-dmactl = dma_bits[isa_get_drq(parent)];
-if (device_get_flags(parent) & DV_F_DUAL_DMA)
-dmactl |= dma_bits[device_get_flags(parent) & DV_F_DRQ_MASK]
-<< 3;
-
-/*
-* Set the DMA and IRQ control latches.
-*/
-port_wr(alt, 0x00, 0x0c);
-port_wr(alt, 0x0b, dmactl | 0x80);
-port_wr(alt, 0x00, 0x4c);
-port_wr(alt, 0x0b, irqctl);
-
-port_wr(alt, 0x00, 0x0c);
-port_wr(alt, 0x0b, dmactl);
-port_wr(alt, 0x00, 0x4c);
-port_wr(alt, 0x0b, irqctl);
-
-port_wr(mss->conf_base, 2, 0);
-port_wr(alt, 0x00, 0x0c);
-port_wr(mss->conf_base, 2, 0);
+ static const unsigned char irq_bits[16] = {
+ 0, 0, 0, 3, 0, 2, 0, 4, 0, 1, 0, 5, 6, 0, 0, 7
+ };
+ static const unsigned char dma_bits[8] = {
+ 0, 1, 0, 2, 0, 3, 4, 5
+ };
+ device_t parent = device_get_parent(dev);
+ unsigned char irqctl, dmactl;
+ int s;
+
+ s = splhigh();
+
+ port_wr(alt, 0x0f, 0x05);
+ port_wr(alt, 0x00, 0x0c);
+ port_wr(alt, 0x0b, 0x00);
+
+ port_wr(alt, 0x0f, 0x00);
+
+ irqctl = irq_bits[isa_get_irq(parent)];
+ /* Share the IRQ with the MIDI driver. */
+ irqctl |= 0x40;
+ dmactl = dma_bits[isa_get_drq(parent)];
+ if (device_get_flags(parent) & DV_F_DUAL_DMA)
+ dmactl |= dma_bits[device_get_flags(parent) & DV_F_DRQ_MASK]
+ << 3;
+
+ /*
+ * Set the DMA and IRQ control latches.
+ */
+ port_wr(alt, 0x00, 0x0c);
+ port_wr(alt, 0x0b, dmactl | 0x80);
+ port_wr(alt, 0x00, 0x4c);
+ port_wr(alt, 0x0b, irqctl);
+
+ port_wr(alt, 0x00, 0x0c);
+ port_wr(alt, 0x0b, dmactl);
+ port_wr(alt, 0x00, 0x4c);
+ port_wr(alt, 0x0b, irqctl);
+
+ port_wr(mss->conf_base, 2, 0);
+ port_wr(alt, 0x00, 0x0c);
+ port_wr(mss->conf_base, 2, 0);
-splx(s);
+ splx(s);
}
static int
mss_init(struct mss_info *mss, device_t dev)
{
-u_char r6, r9;
-struct resource *alt;
-int rid, tmp;
-
-mss->bd_flags |= BD_F_MCE_BIT;
-switch(mss->bd_id) {
-case MD_OPTI931:
-/*
-* The MED3931 v.1.0 allocates 3 bytes for the config
-* space, whereas v.2.0 allocates 4 bytes. What I know
-* for sure is that the upper two ports must be used,
-* and they should end on a boundary of 4 bytes. So I
-* need the following trick.
-*/
-mss->opti_offset =
-(rman_get_start(mss->conf_base) & ~3) + 2
-- rman_get_start(mss->conf_base);
-BVDDB(printf("mss_init: opti_offset=%dn", mss->opti_offset));
-opti_wr(mss, 4, 0xd6); /* fifo empty, OPL3, audio enable, SB3.2 */
-ad_write(mss, 10, 2); /* enable interrupts */
-opti_wr(mss, 6, 2); /* MCIR6: mss enable, sb disable */
-opti_wr(mss, 5, 0x28); /* MCIR5: codec in exp. mode,fifo */
-break;
-
-case MD_GUSPNP:
-case MD_GUSMAX:
-gus_wr(mss, 0x4c /* _URSTI */, 0);/* Pull reset */
-DELAY(1000 * 30);
-/* release reset and enable DAC */
-gus_wr(mss, 0x4c /* _URSTI */, 3);
-DELAY(1000 * 30);
-/* end of reset */
-
-rid = 0;
-alt = bus_alloc_resource_any(dev, SYS_RES_IOPORT, &rid,
-RF_ACTIVE);
-if (alt == NULL) {
-printf("XXX couldn't init GUS PnP/MAXn");
-break;
-}
-port_wr(alt, 0, 0xC); /* enable int and dma */
-if (mss->bd_id == MD_GUSMAX)
-gusmax_setup(mss, dev, alt);
-bus_release_resource(dev, SYS_RES_IOPORT, rid, alt);
-
-/*
-* unmute left & right line. Need to go in mode3, unmute,
-* and back to mode 2
-*/
-tmp = ad_read(mss, 0x0c);
-ad_write(mss, 0x0c, 0x6c); /* special value to enter mode 3 */
-ad_write(mss, 0x19, 0); /* unmute left */
-ad_write(mss, 0x1b, 0); /* unmute right */
-ad_write(mss, 0x0c, tmp); /* restore old mode */
-
-/* send codec interrupts on irq1 and only use that one */
-gus_wr(mss, 0x5a, 0x4f);
-
-/* enable access to hidden regs */
-tmp = gus_rd(mss, 0x5b /* IVERI */);
-gus_wr(mss, 0x5b, tmp | 1);
-BVDDB(printf("GUS: silicon rev %cn", 'A' + ((tmp & 0xf) >> 4)));
-break;
-
-case MD_YM0020:
-conf_wr(mss, OPL3SAx_DMACONF, 0xa9); /* dma-b rec, dma-a play */
-r6 = conf_rd(mss, OPL3SAx_DMACONF);
-r9 = conf_rd(mss, OPL3SAx_MISC); /* version */
-BVDDB(printf("Yamaha: ver 0x%x DMA config 0x%xn", r6, r9);)
-/* yamaha - set volume to max */
-conf_wr(mss, OPL3SAx_VOLUMEL, 0);
-conf_wr(mss, OPL3SAx_VOLUMER, 0);
-conf_wr(mss, OPL3SAx_DMACONF, FULL_DUPLEX(mss)? 0xa9 : 0x8b);
-break;
-}
-if (FULL_DUPLEX(mss) && mss->bd_id != MD_OPTI931)
-ad_write(mss, 12, ad_read(mss, 12) | 0x40); /* mode 2 */
-ad_enter_MCE(mss);
-ad_write(mss, 9, FULL_DUPLEX(mss)? 0 : 4);
-ad_leave_MCE(mss);
-ad_write(mss, 10, 2); /* int enable */
-io_wr(mss, MSS_STATUS, 0); /* Clear interrupt status */
-/* the following seem required on the CS4232 */
-ad_unmute(mss);
-return 0;
-}
-
-
-/*
-* main irq handler for the CS423x. The OPTi931 code is
-* a separate one.
-* The correct way to operate for a device with multiple internal
-* interrupt sources is to loop on the status register and ack
-* interrupts until all interrupts are served and none are reported. At
-* this point the IRQ line to the ISA IRQ controller should go low
-* and be raised at the next interrupt.
-*
-* Since the ISA IRQ controller is sent EOI _before_ passing control
-* to the isr, it might happen that we serve an interrupt early, in
-* which case the status register at the next interrupt should just
-* say that there are no more interrupts...
-*/
+ u_char r6, r9;
+ struct resource *alt;
+ int rid, tmp;
+
+ mss->bd_flags |= BD_F_MCE_BIT;
+ switch(mss->bd_id) {
+ case MD_OPTI931:
+ /*
+ * The MED3931 v.1.0 allocates 3 bytes for the config
+ * space, whereas v.2.0 allocates 4 bytes. What I know
+ * for sure is that the upper two ports must be used,
+ * and they should end on a boundary of 4 bytes. So I
+ * need the following trick.
+ */
+ mss->opti_offset =
+ (rman_get_start(mss->conf_base) & ~3) + 2
+ - rman_get_start(mss->conf_base);
+ BVDDB(printf("mss_init: opti_offset=%d\n", mss->opti_offset));
+ opti_wr(mss, 4, 0xd6); /* fifo empty, OPL3, audio enable, SB3.2 */
+ ad_write(mss, 10, 2); /* enable interrupts */
+ opti_wr(mss, 6, 2); /* MCIR6: mss enable, sb disable */
+ opti_wr(mss, 5, 0x28); /* MCIR5: codec in exp. mode,fifo */
+ break;
+
+ case MD_GUSPNP:
+ case MD_GUSMAX:
+ gus_wr(mss, 0x4c /* _URSTI */, 0);/* Pull reset */
+ DELAY(1000 * 30);
+ /* release reset and enable DAC */
+ gus_wr(mss, 0x4c /* _URSTI */, 3);
+ DELAY(1000 * 30);
+ /* end of reset */
+
+ rid = 0;
+ alt = bus_alloc_resource_any(dev, SYS_RES_IOPORT, &rid,
+ RF_ACTIVE);
+ if (alt == NULL) {
+ printf("XXX couldn't init GUS PnP/MAX\n");
+ break;
+ }
+ port_wr(alt, 0, 0xC); /* enable int and dma */
+ if (mss->bd_id == MD_GUSMAX)
+ gusmax_setup(mss, dev, alt);
+ bus_release_resource(dev, SYS_RES_IOPORT, rid, alt);
+
+ /*
+ * unmute left & right line. Need to go in mode3, unmute,
+ * and back to mode 2
+ */
+ tmp = ad_read(mss, 0x0c);
+ ad_write(mss, 0x0c, 0x6c); /* special value to enter mode 3 */
+ ad_write(mss, 0x19, 0); /* unmute left */
+ ad_write(mss, 0x1b, 0); /* unmute right */
+ ad_write(mss, 0x0c, tmp); /* restore old mode */
+
+ /* send codec interrupts on irq1 and only use that one */
+ gus_wr(mss, 0x5a, 0x4f);
+
+ /* enable access to hidden regs */
+ tmp = gus_rd(mss, 0x5b /* IVERI */);
+ gus_wr(mss, 0x5b, tmp | 1);
+ BVDDB(printf("GUS: silicon rev %c\n", 'A' + ((tmp & 0xf) >> 4)));
+ break;
+
+ case MD_YM0020:
+ conf_wr(mss, OPL3SAx_DMACONF, 0xa9); /* dma-b rec, dma-a play */
+ r6 = conf_rd(mss, OPL3SAx_DMACONF);
+ r9 = conf_rd(mss, OPL3SAx_MISC); /* version */
+ BVDDB(printf("Yamaha: ver 0x%x DMA config 0x%x\n", r6, r9);)
+ /* yamaha - set volume to max */
+ conf_wr(mss, OPL3SAx_VOLUMEL, 0);
+ conf_wr(mss, OPL3SAx_VOLUMER, 0);
+ conf_wr(mss, OPL3SAx_DMACONF, FULL_DUPLEX(mss)? 0xa9 : 0x8b);
+ break;
+ }
+ if (FULL_DUPLEX(mss) && mss->bd_id != MD_OPTI931)
+ ad_write(mss, 12, ad_read(mss, 12) | 0x40); /* mode 2 */
+ ad_enter_MCE(mss);
+ ad_write(mss, 9, FULL_DUPLEX(mss)? 0 : 4);
+ ad_leave_MCE(mss);
+ ad_write(mss, 10, 2); /* int enable */
+ io_wr(mss, MSS_STATUS, 0); /* Clear interrupt status */
+ /* the following seem required on the CS4232 */
+ ad_unmute(mss);
+ return 0;
+}
+
+
+/*
+ * main irq handler for the CS423x. The OPTi931 code is
+ * a separate one.
+ * The correct way to operate for a device with multiple internal
+ * interrupt sources is to loop on the status register and ack
+ * interrupts until all interrupts are served and none are reported. At
+ * this point the IRQ line to the ISA IRQ controller should go low
+ * and be raised at the next interrupt.
+ *
+ * Since the ISA IRQ controller is sent EOI _before_ passing control
+ * to the isr, it might happen that we serve an interrupt early, in
+ * which case the status register at the next interrupt should just
+ * say that there are no more interrupts...
+ */
static void
mss_intr(void *arg)
{
-struct mss_info *mss = arg;
-u_char c = 0, served = 0;
-int i;
-
-DEB(printf("mss_intrn"));
-mss_lock(mss);
-ad_read(mss, 11); /* fake read of status bits */
-
-/* loop until there are interrupts, but no more than 10 times. */
-for (i = 10; i > 0 && io_rd(mss, MSS_STATUS) & 1; i--) {
-/* get exact reason for full-duplex boards */
-c = FULL_DUPLEX(mss)? ad_read(mss, 24) : 0x30;
-c &= ~served;
-if (sndbuf_runsz(mss->pch.buffer) && (c & 0x10)) {
-served |= 0x10;
-mss_unlock(mss);
-chn_intr(mss->pch.channel);
-mss_lock(mss);
-}
-if (sndbuf_runsz(mss->rch.buffer) && (c & 0x20)) {
-served |= 0x20;
-mss_unlock(mss);
-chn_intr(mss->rch.channel);
-mss_lock(mss);
-}
-/* now ack the interrupt */
-if (FULL_DUPLEX(mss)) ad_write(mss, 24, ~c); /* ack selectively */
-else io_wr(mss, MSS_STATUS, 0); /* Clear interrupt status */
-}
-if (i == 10) {
-BVDDB(printf("mss_intr: irq, but not from mssn"));
-} else if (served == 0) {
-BVDDB(printf("mss_intr: unexpected irq with reason %xn", c));
-/*
-* this should not happen... I have no idea what to do now.
-* maybe should do a sanity check and restart dmas ?
-*/
-io_wr(mss, MSS_STATUS, 0); /* Clear interrupt status */
-}
-mss_unlock(mss);
+ struct mss_info *mss = arg;
+ u_char c = 0, served = 0;
+ int i;
+
+ DEB(printf("mss_intr\n"));
+ mss_lock(mss);
+ ad_read(mss, 11); /* fake read of status bits */
+
+ /* loop until there are interrupts, but no more than 10 times. */
+ for (i = 10; i > 0 && io_rd(mss, MSS_STATUS) & 1; i--) {
+ /* get exact reason for full-duplex boards */
+ c = FULL_DUPLEX(mss)? ad_read(mss, 24) : 0x30;
+ c &= ~served;
+ if (sndbuf_runsz(mss->pch.buffer) && (c & 0x10)) {
+ served |= 0x10;
+ mss_unlock(mss);
+ chn_intr(mss->pch.channel);
+ mss_lock(mss);
+ }
+ if (sndbuf_runsz(mss->rch.buffer) && (c & 0x20)) {
+ served |= 0x20;
+ mss_unlock(mss);
+ chn_intr(mss->rch.channel);
+ mss_lock(mss);
+ }
+ /* now ack the interrupt */
+ if (FULL_DUPLEX(mss)) ad_write(mss, 24, ~c); /* ack selectively */
+ else io_wr(mss, MSS_STATUS, 0); /* Clear interrupt status */
+ }
+ if (i == 10) {
+ BVDDB(printf("mss_intr: irq, but not from mss\n"));
+ } else if (served == 0) {
+ BVDDB(printf("mss_intr: unexpected irq with reason %x\n", c));
+ /*
+ * this should not happen... I have no idea what to do now.
+ * maybe should do a sanity check and restart dmas ?
+ */
+ io_wr(mss, MSS_STATUS, 0); /* Clear interrupt status */
+ }
+ mss_unlock(mss);
}
/*
-* AD_WAIT_INIT waits if we are initializing the board and
-* we cannot modify its settings
-*/
+ * AD_WAIT_INIT waits if we are initializing the board and
+ * we cannot modify its settings
+ */
static int
ad_wait_init(struct mss_info *mss, int x)
{
-int arg = x, n = 0; /* to shut up the compiler... */
-for (; x > 0; x--)
-if ((n = io_rd(mss, MSS_INDEX)) & MSS_IDXBUSY) DELAY(10);
-else return n;
-printf("AD_WAIT_INIT FAILED %d 0x%02xn", arg, n);
-return n;
+ int arg = x, n = 0; /* to shut up the compiler... */
+ for (; x > 0; x--)
+ if ((n = io_rd(mss, MSS_INDEX)) & MSS_IDXBUSY) DELAY(10);
+ else return n;
+ printf("AD_WAIT_INIT FAILED %d 0x%02x\n", arg, n);
+ return n;
}
static int
ad_read(struct mss_info *mss, int reg)
{
-int x;
+ int x;
-ad_wait_init(mss, 201000);
-x = io_rd(mss, MSS_INDEX) & ~MSS_IDXMASK;
-io_wr(mss, MSS_INDEX, (u_char)(reg & MSS_IDXMASK) | x);
-x = io_rd(mss, MSS_IDATA);
-/* printf("ad_read %d, %xn", reg, x); */
-return x;
+ ad_wait_init(mss, 201000);
+ x = io_rd(mss, MSS_INDEX) & ~MSS_IDXMASK;
+ io_wr(mss, MSS_INDEX, (u_char)(reg & MSS_IDXMASK) | x);
+ x = io_rd(mss, MSS_IDATA);
+ /* printf("ad_read %d, %x\n", reg, x); */
+ return x;
}
static void
ad_write(struct mss_info *mss, int reg, u_char data)
{
-int x;
+ int x;
-/* printf("ad_write %d, %xn", reg, data); */
-ad_wait_init(mss, 1002000);
-x = io_rd(mss, MSS_INDEX) & ~MSS_IDXMASK;
-io_wr(mss, MSS_INDEX, (u_char)(reg & MSS_IDXMASK) | x);
-io_wr(mss, MSS_IDATA, data);
+ /* printf("ad_write %d, %x\n", reg, data); */
+ ad_wait_init(mss, 1002000);
+ x = io_rd(mss, MSS_INDEX) & ~MSS_IDXMASK;
+ io_wr(mss, MSS_INDEX, (u_char)(reg & MSS_IDXMASK) | x);
+ io_wr(mss, MSS_IDATA, data);
}
static void
ad_write_cnt(struct mss_info *mss, int reg, u_short cnt)
{
-ad_write(mss, reg+1, cnt & 0xff);
-ad_write(mss, reg, cnt >> 8); /* upper base must be last */
+ ad_write(mss, reg+1, cnt & 0xff);
+ ad_write(mss, reg, cnt >> 8); /* upper base must be last */
}
static void
wait_for_calibration(struct mss_info *mss)
{
-int t;
+ int t;
-/*
-* Wait until the auto calibration process has finished.
-*
-* 1) Wait until the chip becomes ready (reads don't return 0x80).
-* 2) Wait until the ACI bit of I11 gets on
-* 3) Wait until the ACI bit of I11 gets off
-*/
-
-t = ad_wait_init(mss, 1000000);
-if (t & MSS_IDXBUSY) printf("mss: Auto calibration timed out(1).n");
-
-/*
-* The calibration mode for chips that support it is set so that
-* we never see ACI go on.
-*/
-if (mss->bd_id == MD_GUSMAX || mss->bd_id == MD_GUSPNP) {
-for (t = 100; t > 0 && (ad_read(mss, 11) & 0x20) == 0; t--);
-} else {
-/*
-* XXX This should only be enabled for cards that *really*
-* need it. Are there any?
-*/
-for (t = 100; t > 0 && (ad_read(mss, 11) & 0x20) == 0; t--) DELAY(100);
-}
-for (t = 100; t > 0 && ad_read(mss, 11) & 0x20; t--) DELAY(100);
+ /*
+ * Wait until the auto calibration process has finished.
+ *
+ * 1) Wait until the chip becomes ready (reads don't return 0x80).
+ * 2) Wait until the ACI bit of I11 gets on
+ * 3) Wait until the ACI bit of I11 gets off
+ */
+
+ t = ad_wait_init(mss, 1000000);
+ if (t & MSS_IDXBUSY) printf("mss: Auto calibration timed out(1).\n");
+
+ /*
+ * The calibration mode for chips that support it is set so that
+ * we never see ACI go on.
+ */
+ if (mss->bd_id == MD_GUSMAX || mss->bd_id == MD_GUSPNP) {
+ for (t = 100; t > 0 && (ad_read(mss, 11) & 0x20) == 0; t--);
+ } else {
+ /*
+ * XXX This should only be enabled for cards that *really*
+ * need it. Are there any?
+ */
+ for (t = 100; t > 0 && (ad_read(mss, 11) & 0x20) == 0; t--) DELAY(100);
+ }
+ for (t = 100; t > 0 && ad_read(mss, 11) & 0x20; t--) DELAY(100);
}
static void
ad_unmute(struct mss_info *mss)
{
-ad_write(mss, 6, ad_read(mss, 6) & ~I6_MUTE);
-ad_write(mss, 7, ad_read(mss, 7) & ~I6_MUTE);
+ ad_write(mss, 6, ad_read(mss, 6) & ~I6_MUTE);
+ ad_write(mss, 7, ad_read(mss, 7) & ~I6_MUTE);
}
static void
ad_enter_MCE(struct mss_info *mss)
{
-int prev;
+ int prev;
-mss->bd_flags |= BD_F_MCE_BIT;
-ad_wait_init(mss, 203000);
-prev = io_rd(mss, MSS_INDEX);
-prev &= ~MSS_TRD;
-io_wr(mss, MSS_INDEX, prev | MSS_MCE);
+ mss->bd_flags |= BD_F_MCE_BIT;
+ ad_wait_init(mss, 203000);
+ prev = io_rd(mss, MSS_INDEX);
+ prev &= ~MSS_TRD;
+ io_wr(mss, MSS_INDEX, prev | MSS_MCE);
}
static void
ad_leave_MCE(struct mss_info *mss)
{
-u_char prev;
+ u_char prev;
-if ((mss->bd_flags & BD_F_MCE_BIT) == 0) {
-DEB(printf("--- hey, leave_MCE: MCE bit was not set!n"));
-return;
-}
+ if ((mss->bd_flags & BD_F_MCE_BIT) == 0) {
+ DEB(printf("--- hey, leave_MCE: MCE bit was not set!\n"));
+ return;
+ }
-ad_wait_init(mss, 1000000);
+ ad_wait_init(mss, 1000000);
-mss->bd_flags &= ~BD_F_MCE_BIT;
+ mss->bd_flags &= ~BD_F_MCE_BIT;
-prev = io_rd(mss, MSS_INDEX);
-prev &= ~MSS_TRD;
-io_wr(mss, MSS_INDEX, prev & ~MSS_MCE); /* Clear the MCE bit */
-wait_for_calibration(mss);
+ prev = io_rd(mss, MSS_INDEX);
+ prev &= ~MSS_TRD;
+ io_wr(mss, MSS_INDEX, prev & ~MSS_MCE); /* Clear the MCE bit */
+ wait_for_calibration(mss);
}
static int
mss_speed(struct mss_chinfo *ch, int speed)
{
-struct mss_info *mss = ch->parent;
-/*
-* In the CS4231, the low 4 bits of I8 are used to hold the
-* sample rate. Only a fixed number of values is allowed. This
-* table lists them. The speed-setting routines scans the table
-* looking for the closest match. This is the only supported method.
-*
-* In the CS4236, there is an alternate metod (which we do not
-* support yet) which provides almost arbitrary frequency setting.
-* In the AD1845, it looks like the sample rate can be
-* almost arbitrary, and written directly to a register.
-* In the OPTi931, there is a SB command which provides for
-* almost arbitrary frequency setting.
-*
-*/
-ad_enter_MCE(mss);
-if (mss->bd_id == MD_AD1845) { /* Use alternate speed select regs */
-ad_write(mss, 22, (speed >> 8) & 0xff); /* Speed MSB */
-ad_write(mss, 23, speed & 0xff); /* Speed LSB */
-/* XXX must also do something in I27 for the ad1845 */
-} else {
-int i, sel = 0; /* assume entry 0 does not contain -1 */
-static int speeds[] =
-{8000, 5512, 16000, 11025, 27429, 18900, 32000, 22050,
--1, 37800, -1, 44100, 48000, 33075, 9600, 6615};
-
-for (i = 1; i < 16; i++)
-if (speeds[i] > 0 &&
-abs(speed-speeds[i]) < abs(speed-speeds[sel])) sel = i;
-speed = speeds[sel];
-ad_write(mss, 8, (ad_read(mss, 8) & 0xf0) | sel);
-ad_wait_init(mss, 10000);
-}
-ad_leave_MCE(mss);
-
-return speed;
+ struct mss_info *mss = ch->parent;
+ /*
+ * In the CS4231, the low 4 bits of I8 are used to hold the
+ * sample rate. Only a fixed number of values is allowed. This
+ * table lists them. The speed-setting routines scans the table
+ * looking for the closest match. This is the only supported method.
+ *
+ * In the CS4236, there is an alternate metod (which we do not
+ * support yet) which provides almost arbitrary frequency setting.
+ * In the AD1845, it looks like the sample rate can be
+ * almost arbitrary, and written directly to a register.
+ * In the OPTi931, there is a SB command which provides for
+ * almost arbitrary frequency setting.
+ *
+ */
+ ad_enter_MCE(mss);
+ if (mss->bd_id == MD_AD1845) { /* Use alternate speed select regs */
+ ad_write(mss, 22, (speed >> 8) & 0xff); /* Speed MSB */
+ ad_write(mss, 23, speed & 0xff); /* Speed LSB */
+ /* XXX must also do something in I27 for the ad1845 */
+ } else {
+ int i, sel = 0; /* assume entry 0 does not contain -1 */
+ static int speeds[] =
+ {8000, 5512, 16000, 11025, 27429, 18900, 32000, 22050,
+ -1, 37800, -1, 44100, 48000, 33075, 9600, 6615};
+
+ for (i = 1; i < 16; i++)
+ if (speeds[i] > 0 &&
+ abs(speed-speeds[i]) < abs(speed-speeds[sel])) sel = i;
+ speed = speeds[sel];
+ ad_write(mss, 8, (ad_read(mss, 8) & 0xf0) | sel);
+ ad_wait_init(mss, 10000);
+ }
+ ad_leave_MCE(mss);
+
+ return speed;
}
/*
-* mss_format checks that the format is supported (or defaults to AFMT_U8)
-* and returns the bit setting for the 1848 register corresponding to
-* the desired format.
-*
-* fixed lr970724
-*/
+ * mss_format checks that the format is supported (or defaults to AFMT_U8)
+ * and returns the bit setting for the 1848 register corresponding to
+ * the desired format.
+ *
+ * fixed lr970724
+ */
static int
mss_format(struct mss_chinfo *ch, u_int32_t format)
{
-struct mss_info *mss = ch->parent;
-int i, arg = format & ~AFMT_STEREO;
+ struct mss_info *mss = ch->parent;
+ int i, arg = format & ~AFMT_STEREO;
-/*
-* The data format uses 3 bits (just 2 on the 1848). For each
-* bit setting, the following array returns the corresponding format.
-* The code scans the array looking for a suitable format. In
-* case it is not found, default to AFMT_U8 (not such a good
-* choice, but let's do it for compatibility...).
-*/
-
-static int fmts[] =
-{AFMT_U8, AFMT_MU_LAW, AFMT_S16_LE, AFMT_A_LAW,
--1, AFMT_IMA_ADPCM, AFMT_U16_BE, -1};
-
-ch->fmt = format;
-for (i = 0; i < 8; i++) if (arg == fmts[i]) break;
-arg = i << 1;
-if (format & AFMT_STEREO) arg |= 1;
-arg <<= 4;
-ad_enter_MCE(mss);
-ad_write(mss, 8, (ad_read(mss, 8) & 0x0f) | arg);
-ad_wait_init(mss, 10000);
-if (ad_read(mss, 12) & 0x40) { /* mode2? */
-ad_write(mss, 28, arg); /* capture mode */
-ad_wait_init(mss, 10000);
-}
-ad_leave_MCE(mss);
-return format;
+ /*
+ * The data format uses 3 bits (just 2 on the 1848). For each
+ * bit setting, the following array returns the corresponding format.
+ * The code scans the array looking for a suitable format. In
+ * case it is not found, default to AFMT_U8 (not such a good
+ * choice, but let's do it for compatibility...).
+ */
+
+ static int fmts[] =
+ {AFMT_U8, AFMT_MU_LAW, AFMT_S16_LE, AFMT_A_LAW,
+ -1, AFMT_IMA_ADPCM, AFMT_U16_BE, -1};
+
+ ch->fmt = format;
+ for (i = 0; i < 8; i++) if (arg == fmts[i]) break;
+ arg = i << 1;
+ if (format & AFMT_STEREO) arg |= 1;
+ arg <<= 4;
+ ad_enter_MCE(mss);
+ ad_write(mss, 8, (ad_read(mss, 8) & 0x0f) | arg);
+ ad_wait_init(mss, 10000);
+ if (ad_read(mss, 12) & 0x40) { /* mode2? */
+ ad_write(mss, 28, arg); /* capture mode */
+ ad_wait_init(mss, 10000);
+ }
+ ad_leave_MCE(mss);
+ return format;
}
static int
mss_trigger(struct mss_chinfo *ch, int go)
{
-struct mss_info *mss = ch->parent;
-u_char m;
-int retry, wr, cnt, ss;
-
-ss = 1;
-ss <<= (ch->fmt & AFMT_STEREO)? 1 : 0;
-ss <<= (ch->fmt & AFMT_16BIT)? 1 : 0;
-
-wr = (ch->dir == PCMDIR_PLAY)? 1 : 0;
-m = ad_read(mss, 9);
-switch (go) {
-case PCMTRIG_START:
-cnt = (ch->blksz / ss) - 1;
-
-DEB(if (m & 4) printf("OUCH! reg 9 0x%02xn", m););
-m |= wr? I9_PEN : I9_CEN; /* enable DMA */
-ad_write_cnt(mss, (wr || !FULL_DUPLEX(mss))? 14 : 30, cnt);
-break;
-
-case PCMTRIG_STOP:
-case PCMTRIG_ABORT: /* XXX check this... */
-m &= ~(wr? I9_PEN : I9_CEN); /* Stop DMA */
+ struct mss_info *mss = ch->parent;
+ u_char m;
+ int retry, wr, cnt, ss;
+
+ ss = 1;
+ ss <<= (ch->fmt & AFMT_STEREO)? 1 : 0;
+ ss <<= (ch->fmt & AFMT_16BIT)? 1 : 0;
+
+ wr = (ch->dir == PCMDIR_PLAY)? 1 : 0;
+ m = ad_read(mss, 9);
+ switch (go) {
+ case PCMTRIG_START:
+ cnt = (ch->blksz / ss) - 1;
+
+ DEB(if (m & 4) printf("OUCH! reg 9 0x%02x\n", m););
+ m |= wr? I9_PEN : I9_CEN; /* enable DMA */
+ ad_write_cnt(mss, (wr || !FULL_DUPLEX(mss))? 14 : 30, cnt);
+ break;
+
+ case PCMTRIG_STOP:
+ case PCMTRIG_ABORT: /* XXX check this... */
+ m &= ~(wr? I9_PEN : I9_CEN); /* Stop DMA */
#if 0
-/*
-* try to disable DMA by clearing count registers. Not sure it
-* is needed, and it might cause false interrupts when the
-* DMA is re-enabled later.
-*/
-ad_write_cnt(mss, (wr || !FULL_DUPLEX(mss))? 14 : 30, 0);
+ /*
+ * try to disable DMA by clearing count registers. Not sure it
+ * is needed, and it might cause false interrupts when the
+ * DMA is re-enabled later.
+ */
+ ad_write_cnt(mss, (wr || !FULL_DUPLEX(mss))? 14 : 30, 0);
#endif
-}
-/* on the OPTi931 the enable bit seems hard to set... */
-for (retry = 10; retry > 0; retry--) {
-ad_write(mss, 9, m);
-if (ad_read(mss, 9) == m) break;
-}
-if (retry == 0) BVDDB(printf("stop dma, failed to set bit 0x%02x 0x%02xn", m, ad_read(mss, 9)));
-return 0;
+ }
+ /* on the OPTi931 the enable bit seems hard to set... */
+ for (retry = 10; retry > 0; retry--) {
+ ad_write(mss, 9, m);
+ if (ad_read(mss, 9) == m) break;
+ }
+ if (retry == 0) BVDDB(printf("stop dma, failed to set bit 0x%02x 0x%02x\n", \
+ m, ad_read(mss, 9)));
+ return 0;
}
/*
-* the opti931 seems to miss interrupts when working in full
-* duplex, so we try some heuristics to catch them.
-*/
+ * the opti931 seems to miss interrupts when working in full
+ * duplex, so we try some heuristics to catch them.
+ */
static void
opti931_intr(void *arg)
{
-struct mss_info *mss = (struct mss_info *)arg;
-u_char masked = 0, i11, mc11, c = 0;
-u_char reason; /* b0 = playback, b1 = capture, b2 = timer */
-int loops = 10;
+ struct mss_info *mss = (struct mss_info *)arg;
+ u_char masked = 0, i11, mc11, c = 0;
+ u_char reason; /* b0 = playback, b1 = capture, b2 = timer */
+ int loops = 10;
#if 0
-reason = io_rd(mss, MSS_STATUS);
-if (!(reason & 1)) {/* no int, maybe a shared line ? */
-DEB(printf("intr: flag 0, mcir11 0x%02xn", ad_read(mss, 11)));
-return;
-}
+ reason = io_rd(mss, MSS_STATUS);
+ if (!(reason & 1)) {/* no int, maybe a shared line ? */
+ DEB(printf("intr: flag 0, mcir11 0x%02x\n", ad_read(mss, 11)));
+ return;
+ }
#endif
-mss_lock(mss);
-i11 = ad_read(mss, 11); /* XXX what's for ? */
-again:
-
-c = mc11 = FULL_DUPLEX(mss)? opti_rd(mss, 11) : 0xc;
-mc11 &= 0x0c;
-if (c & 0x10) {
-DEB(printf("Warning: CD interruptn");)
-mc11 |= 0x10;
-}
-if (c & 0x20) {
-DEB(printf("Warning: MPU interruptn");)
-mc11 |= 0x20;
-}
-if (mc11 & masked) BVDDB(printf("irq reset failed, mc11 0x%02x, 0x%02xn", mc11, masked));
-masked |= mc11;
-/*
-* the nice OPTi931 sets the IRQ line before setting the bits in
-* mc11. So, on some occasions I have to retry (max 10 times).
-*/
-if (mc11 == 0) { /* perhaps can return ... */
-reason = io_rd(mss, MSS_STATUS);
-if (reason & 1) {
-DEB(printf("one more try...n");)
-if (--loops) goto again;
-else BVDDB(printf("intr, but mc11 not setn");)
-}
-if (loops == 0) BVDDB(printf("intr, nothing in mcir11 0x%02xn", mc11));
-mss_unlock(mss);
-return;
-}
-
-if (sndbuf_runsz(mss->rch.buffer) && (mc11 & 8)) {
-mss_unlock(mss);
-chn_intr(mss->rch.channel);
-mss_lock(mss);
-}
-if (sndbuf_runsz(mss->pch.buffer) && (mc11 & 4)) {
-mss_unlock(mss);
-chn_intr(mss->pch.channel);
-mss_lock(mss);
-}
-opti_wr(mss, 11, ~mc11); /* ack */
-if (--loops) goto again;
-mss_unlock(mss);
-DEB(printf("xxx too many loopsn");)
+ mss_lock(mss);
+ i11 = ad_read(mss, 11); /* XXX what's for ? */
+ again:
+
+ c = mc11 = FULL_DUPLEX(mss)? opti_rd(mss, 11) : 0xc;
+ mc11 &= 0x0c;
+ if (c & 0x10) {
+ DEB(printf("Warning: CD interrupt\n");)
+ mc11 |= 0x10;
+ }
+ if (c & 0x20) {
+ DEB(printf("Warning: MPU interrupt\n");)
+ mc11 |= 0x20;
+ }
+ if (mc11 & masked) BVDDB(printf("irq reset failed, mc11 0x%02x, 0x%02x\n",\
+ mc11, masked));
+ masked |= mc11;
+ /*
+ * the nice OPTi931 sets the IRQ line before setting the bits in
+ * mc11. So, on some occasions I have to retry (max 10 times).
+ */
+ if (mc11 == 0) { /* perhaps can return ... */
+ reason = io_rd(mss, MSS_STATUS);
+ if (reason & 1) {
+ DEB(printf("one more try...\n");)
+ if (--loops) goto again;
+ else BVDDB(printf("intr, but mc11 not set\n");)
+ }
+ if (loops == 0) BVDDB(printf("intr, nothing in mcir11 0x%02x\n", mc11));
+ mss_unlock(mss);
+ return;
+ }
+
+ if (sndbuf_runsz(mss->rch.buffer) && (mc11 & 8)) {
+ mss_unlock(mss);
+ chn_intr(mss->rch.channel);
+ mss_lock(mss);
+ }
+ if (sndbuf_runsz(mss->pch.buffer) && (mc11 & 4)) {
+ mss_unlock(mss);
+ chn_intr(mss->pch.channel);
+ mss_lock(mss);
+ }
+ opti_wr(mss, 11, ~mc11); /* ack */
+ if (--loops) goto again;
+ mss_unlock(mss);
+ DEB(printf("xxx too many loops\n");)
}
/* -------------------------------------------------------------------- */
@@ -1143,766 +1145,767 @@
static void *
msschan_init(kobj_t obj, void *devinfo, struct snd_dbuf *b, struct pcm_channel *c, int dir)
{
-struct mss_info *mss = devinfo;
-struct mss_chinfo *ch = (dir == PCMDIR_PLAY)? &mss->pch : &mss->rch;
+ struct mss_info *mss = devinfo;
+ struct mss_chinfo *ch = (dir == PCMDIR_PLAY)? &mss->pch : &mss->rch;
-ch->parent = mss;
-ch->channel = c;
-ch->buffer = b;
-ch->dir = dir;
-if (sndbuf_alloc(ch->buffer, mss->parent_dmat, mss->bufsize) != 0)
-return NULL;
-sndbuf_dmasetup(ch->buffer, (dir == PCMDIR_PLAY)? mss->drq1 : mss->drq2);
-return ch;
+ ch->parent = mss;
+ ch->channel = c;
+ ch->buffer = b;
+ ch->dir = dir;
+ if (sndbuf_alloc(ch->buffer, mss->parent_dmat, 0, mss->bufsize) != 0)
+ return NULL;
+ sndbuf_dmasetup(ch->buffer, (dir == PCMDIR_PLAY)? mss->drq1 : mss->drq2);
+ return ch;
}
static int
msschan_setformat(kobj_t obj, void *data, u_int32_t format)
{
-struct mss_chinfo *ch = data;
-struct mss_info *mss = ch->parent;
+ struct mss_chinfo *ch = data;
+ struct mss_info *mss = ch->parent;
-mss_lock(mss);
-mss_format(ch, format);
-mss_unlock(mss);
-return 0;
+ mss_lock(mss);
+ mss_format(ch, format);
+ mss_unlock(mss);
+ return 0;
}
static int
msschan_setspeed(kobj_t obj, void *data, u_int32_t speed)
{
-struct mss_chinfo *ch = data;
-struct mss_info *mss = ch->parent;
-int r;
-
-mss_lock(mss);
-r = mss_speed(ch, speed);
-mss_unlock(mss);
+ struct mss_chinfo *ch = data;
+ struct mss_info *mss = ch->parent;
+ int r;
+
+ mss_lock(mss);
+ r = mss_speed(ch, speed);
+ mss_unlock(mss);
-return r;
+ return r;
}
static int
msschan_setblocksize(kobj_t obj, void *data, u_int32_t blocksize)
{
-struct mss_chinfo *ch = data;
+ struct mss_chinfo *ch = data;
-ch->blksz = blocksize;
-sndbuf_resize(ch->buffer, 2, ch->blksz);
+ ch->blksz = blocksize;
+ sndbuf_resize(ch->buffer, 2, ch->blksz);
-return ch->blksz;
+ return ch->blksz;
}
static int
msschan_trigger(kobj_t obj, void *data, int go)
{
-struct mss_chinfo *ch = data;
-struct mss_info *mss = ch->parent;
+ struct mss_chinfo *ch = data;
+ struct mss_info *mss = ch->parent;
-if (go == PCMTRIG_EMLDMAWR || go == PCMTRIG_EMLDMARD)
-return 0;
+ if (!PCMTRIG_COMMON(go))
+ return 0;
-sndbuf_dma(ch->buffer, go);
-mss_lock(mss);
-mss_trigger(ch, go);
-mss_unlock(mss);
-return 0;
+ sndbuf_dma(ch->buffer, go);
+ mss_lock(mss);
+ mss_trigger(ch, go);
+ mss_unlock(mss);
+ return 0;
}
static int
msschan_getptr(kobj_t obj, void *data)
{
-struct mss_chinfo *ch = data;
-return sndbuf_dmaptr(ch->buffer);
+ struct mss_chinfo *ch = data;
+ return sndbuf_dmaptr(ch->buffer);
}
static struct pcmchan_caps *
msschan_getcaps(kobj_t obj, void *data)
{
-struct mss_chinfo *ch = data;
+ struct mss_chinfo *ch = data;
-switch(ch->parent->bd_id) {
-case MD_OPTI931:
-return &opti931_caps;
-break;
-
-case MD_GUSPNP:
-case MD_GUSMAX:
-return &guspnp_caps;
-break;
-
-default:
-return &mss_caps;
-break;
-}
+ switch(ch->parent->bd_id) {
+ case MD_OPTI931:
+ return &opti931_caps;
+ break;
+
+ case MD_GUSPNP:
+ case MD_GUSMAX:
+ return &guspnp_caps;
+ break;
+
+ default:
+ return &mss_caps;
+ break;
+ }
}
static kobj_method_t msschan_methods[] = {
-KOBJMETHOD(channel_init, msschan_init),
-KOBJMETHOD(channel_setformat, msschan_setformat),
-KOBJMETHOD(channel_setspeed, msschan_setspeed),
-KOBJMETHOD(channel_setblocksize, msschan_setblocksize),
-KOBJMETHOD(channel_trigger, msschan_trigger),
-KOBJMETHOD(channel_getptr, msschan_getptr),
-KOBJMETHOD(channel_getcaps, msschan_getcaps),
-{ 0, 0 }
+ KOBJMETHOD(channel_init, msschan_init),
+ KOBJMETHOD(channel_setformat, msschan_setformat),
+ KOBJMETHOD(channel_setspeed, msschan_setspeed),
+ KOBJMETHOD(channel_setblocksize, msschan_setblocksize),
+ KOBJMETHOD(channel_trigger, msschan_trigger),
+ KOBJMETHOD(channel_getptr, msschan_getptr),
+ KOBJMETHOD(channel_getcaps, msschan_getcaps),
+ { 0, 0 }
};
CHANNEL_DECLARE(msschan);
/* -------------------------------------------------------------------- */
/*
-* mss_probe() is the probe routine. Note, it is not necessary to
-* go through this for PnP devices, since they are already
-* indentified precisely using their PnP id.
-*
-* The base address supplied in the device refers to the old MSS
-* specs where the four 4 registers in io space contain configuration
-* information. Some boards (as an example, early MSS boards)
-* has such a block of registers, whereas others (generally CS42xx)
-* do not. In order to distinguish between the two and do not have
-* to supply two separate probe routines, the flags entry in isa_device
-* has a bit to mark this.
-*
-*/
+ * mss_probe() is the probe routine. Note, it is not necessary to
+ * go through this for PnP devices, since they are already
+ * indentified precisely using their PnP id.
+ *
+ * The base address supplied in the device refers to the old MSS
+ * specs where the four 4 registers in io space contain configuration
+ * information. Some boards (as an example, early MSS boards)
+ * has such a block of registers, whereas others (generally CS42xx)
+ * do not. In order to distinguish between the two and do not have
+ * to supply two separate probe routines, the flags entry in isa_device
+ * has a bit to mark this.
+ *
+ */
static int
mss_probe(device_t dev)
{
-u_char tmp, tmpx;
-int flags, irq, drq, result = ENXIO, setres = 0;
-struct mss_info *mss;
-
-if (isa_get_logicalid(dev)) return ENXIO; /* not yet */
-
-mss = (struct mss_info *)malloc(sizeof *mss, M_DEVBUF, M_NOWAIT | M_ZERO);
-if (!mss) return ENXIO;
-
-mss->io_rid = 0;
-mss->conf_rid = -1;
-mss->irq_rid = 0;
-mss->drq1_rid = 0;
-mss->drq2_rid = -1;
-mss->io_base = bus_alloc_resource(dev, SYS_RES_IOPORT, &mss->io_rid,
-0, ~0, 8, RF_ACTIVE);
-if (!mss->io_base) {
-BVDDB(printf("mss_probe: no address given, try 0x%xn", 0x530));
-mss->io_rid = 0;
-/* XXX verify this */
-setres = 1;
-bus_set_resource(dev, SYS_RES_IOPORT, mss->io_rid,
-0x530, 8);
-mss->io_base = bus_alloc_resource(dev, SYS_RES_IOPORT, &mss->io_rid,
-0, ~0, 8, RF_ACTIVE);
-}
-if (!mss->io_base) goto no;
-
-/* got irq/dma regs? */
-flags = device_get_flags(dev);
-irq = isa_get_irq(dev);
-drq = isa_get_drq(dev);
-
-if (!(device_get_flags(dev) & DV_F_TRUE_MSS)) goto mss_probe_end;
-
-/*
-* Check if the IO port returns valid signature. The original MS
-* Sound system returns 0x04 while some cards
-* (AudioTriX Pro for example) return 0x00 or 0x0f.
-*/
-
-device_set_desc(dev, "MSS");
-tmpx = tmp = io_rd(mss, 3);
-if (tmp == 0xff) { /* Bus float */
-BVDDB(printf("I/O addr inactive (%x), try pseudo_mssn", tmp));
-device_set_flags(dev, flags & ~DV_F_TRUE_MSS);
-goto mss_probe_end;
-}
-tmp &= 0x3f;
-if (!(tmp == 0x04 || tmp == 0x0f || tmp == 0x00)) {
-BVDDB(printf("No MSS signature detected on port 0x%lx (0x%x)n",
-rman_get_start(mss->io_base), tmpx));
-goto no;
-}
+ u_char tmp, tmpx;
+ int flags, irq, drq, result = ENXIO, setres = 0;
+ struct mss_info *mss;
+
+ if (isa_get_logicalid(dev)) return ENXIO; /* not yet */
+
+ mss = (struct mss_info *)malloc(sizeof *mss, M_DEVBUF, M_NOWAIT | M_ZERO);
+ if (!mss) return ENXIO;
+
+ mss->io_rid = 0;
+ mss->conf_rid = -1;
+ mss->irq_rid = 0;
+ mss->drq1_rid = 0;
+ mss->drq2_rid = -1;
+ mss->io_base = bus_alloc_resource(dev, SYS_RES_IOPORT, &mss->io_rid,
+ 0, ~0, 8, RF_ACTIVE);
+ if (!mss->io_base) {
+ BVDDB(printf("mss_probe: no address given, try 0x%x\n", 0x530));
+ mss->io_rid = 0;
+ /* XXX verify this */
+ setres = 1;
+ bus_set_resource(dev, SYS_RES_IOPORT, mss->io_rid,
+ 0x530, 8);
+ mss->io_base = bus_alloc_resource(dev, SYS_RES_IOPORT, &mss->io_rid,
+ 0, ~0, 8, RF_ACTIVE);
+ }
+ if (!mss->io_base) goto no;
+
+ /* got irq/dma regs? */
+ flags = device_get_flags(dev);
+ irq = isa_get_irq(dev);
+ drq = isa_get_drq(dev);
+
+ if (!(device_get_flags(dev) & DV_F_TRUE_MSS)) goto mss_probe_end;
+
+ /*
+ * Check if the IO port returns valid signature. The original MS
+ * Sound system returns 0x04 while some cards
+ * (AudioTriX Pro for example) return 0x00 or 0x0f.
+ */
+
+ device_set_desc(dev, "MSS");
+ tmpx = tmp = io_rd(mss, 3);
+ if (tmp == 0xff) { /* Bus float */
+ BVDDB(printf("I/O addr inactive (%x), try pseudo_mss\n", tmp));
+ device_set_flags(dev, flags & ~DV_F_TRUE_MSS);
+ goto mss_probe_end;
+ }
+ tmp &= 0x3f;
+ if (!(tmp == 0x04 || tmp == 0x0f || tmp == 0x00 || tmp == 0x05)) {
+ BVDDB(printf("No MSS signature detected on port 0x%lx (0x%x)\n",
+ rman_get_start(mss->io_base), tmpx));
+ goto no;
+ }
#ifdef PC98
-if (irq > 12) {
+ if (irq > 12) {
#else
-if (irq > 11) {
+ if (irq > 11) {
#endif
-printf("MSS: Bad IRQ %dn", irq);
-goto no;
-}
-if (!(drq == 0 || drq == 1 || drq == 3)) {
-printf("MSS: Bad DMA %dn", drq);
-goto no;
-}
-if (tmpx & 0x80) {
-/* 8-bit board: only drq1/3 and irq7/9 */
-if (drq == 0) {
-printf("MSS: Can't use DMA0 with a 8 bit card/slotn");
-goto no;
-}
-if (!(irq == 7 || irq == 9)) {
-printf("MSS: Can't use IRQ%d with a 8 bit card/slotn",
-irq);
-goto no;
-}
-}
-mss_probe_end:
-result = mss_detect(dev, mss);
-no:
-mss_release_resources(mss, dev);
+ printf("MSS: Bad IRQ %d\n", irq);
+ goto no;
+ }
+ if (!(drq == 0 || drq == 1 || drq == 3)) {
+ printf("MSS: Bad DMA %d\n", drq);
+ goto no;
+ }
+ if (tmpx & 0x80) {
+ /* 8-bit board: only drq1/3 and irq7/9 */
+ if (drq == 0) {
+ printf("MSS: Can't use DMA0 with a 8 bit card/slot\n");
+ goto no;
+ }
+ if (!(irq == 7 || irq == 9)) {
+ printf("MSS: Can't use IRQ%d with a 8 bit card/slot\n",
+ irq);
+ goto no;
+ }
+ }
+ mss_probe_end:
+ result = mss_detect(dev, mss);
+ no:
+ mss_release_resources(mss, dev);
#if 0
-if (setres) ISA_DELETE_RESOURCE(device_get_parent(dev), dev,
-SYS_RES_IOPORT, mss->io_rid); /* XXX ? */
+ if (setres) ISA_DELETE_RESOURCE(device_get_parent(dev), dev,
+ SYS_RES_IOPORT, mss->io_rid); /* XXX ? */
#endif
-return result;
+ return result;
}
static int
mss_detect(device_t dev, struct mss_info *mss)
{
-int i;
-u_char tmp = 0, tmp1, tmp2;
-char *name, *yamaha;
-
-if (mss->bd_id != 0) {
-device_printf(dev, "presel bd_id 0x%04x -- %sn", mss->bd_id,
-device_get_desc(dev));
-return 0;
-}
+ int i;
+ u_char tmp = 0, tmp1, tmp2;
+ char *name, *yamaha;
+
+ if (mss->bd_id != 0) {
+ device_printf(dev, "presel bd_id 0x%04x -- %s\n", mss->bd_id,
+ device_get_desc(dev));
+ return 0;
+ }
-name = "AD1848";
-mss->bd_id = MD_AD1848; /* AD1848 or CS4248 */
+ name = "AD1848";
+ mss->bd_id = MD_AD1848; /* AD1848 or CS4248 */
#ifndef PC98
-if (opti_detect(dev, mss)) {
-switch (mss->bd_id) {
-case MD_OPTI924:
-name = "OPTi924";
-break;
-case MD_OPTI930:
-name = "OPTi930";
-break;
-}
-printf("Found OPTi device %sn", name);
-if (opti_init(dev, mss) == 0) goto gotit;
-}
+ if (opti_detect(dev, mss)) {
+ switch (mss->bd_id) {
+ case MD_OPTI924:
+ name = "OPTi924";
+ break;
+ case MD_OPTI930:
+ name = "OPTi930";
+ break;
+ }
+ printf("Found OPTi device %s\n", name);
+ if (opti_init(dev, mss) == 0) goto gotit;
+ }
#endif
-/*
-* Check that the I/O address is in use.
-*
-* bit 7 of the base I/O port is known to be 0 after the chip has
-* performed its power on initialization. Just assume this has
-* happened before the OS is starting.
-*
-* If the I/O address is unused, it typically returns 0xff.
-*/
-
-for (i = 0; i < 10; i++)
-if ((tmp = io_rd(mss, MSS_INDEX)) & MSS_IDXBUSY) DELAY(10000);
-else break;
-
-if (i >= 10) { /* Not an AD1848 */
-BVDDB(printf("mss_detect, busy still set (0x%02x)n", tmp));
-goto no;
-}
-/*
-* Test if it's possible to change contents of the indirect
-* registers. Registers 0 and 1 are ADC volume registers. The bit
-* 0x10 is read only so try to avoid using it.
-*/
-
-ad_write(mss, 0, 0xaa);
-ad_write(mss, 1, 0x45);/* 0x55 with bit 0x10 clear */
-tmp1 = ad_read(mss, 0);
-tmp2 = ad_read(mss, 1);
-if (tmp1 != 0xaa || tmp2 != 0x45) {
-BVDDB(printf("mss_detect error - IREG (%x/%x)n", tmp1, tmp2));
-goto no;
-}
-
-ad_write(mss, 0, 0x45);
-ad_write(mss, 1, 0xaa);
-tmp1 = ad_read(mss, 0);
-tmp2 = ad_read(mss, 1);
-if (tmp1 != 0x45 || tmp2 != 0xaa) {
-BVDDB(printf("mss_detect error - IREG2 (%x/%x)n", tmp1, tmp2));
-goto no;
-}
-
-/*
-* The indirect register I12 has some read only bits. Lets try to
-* change them.
-*/
-
-tmp = ad_read(mss, 12);
-ad_write(mss, 12, (~tmp) & 0x0f);
-tmp1 = ad_read(mss, 12);
-
-if ((tmp & 0x0f) != (tmp1 & 0x0f)) {
-BVDDB(printf("mss_detect - I12 (0x%02x was 0x%02x)n", tmp1, tmp));
-goto no;
-}
-
-/*
-* NOTE! Last 4 bits of the reg I12 tell the chip revision.
-* 0x01=RevB
-* 0x0A=RevC. also CS4231/CS4231A and OPTi931
-*/
+ /*
+ * Check that the I/O address is in use.
+ *
+ * bit 7 of the base I/O port is known to be 0 after the chip has
+ * performed its power on initialization. Just assume this has
+ * happened before the OS is starting.
+ *
+ * If the I/O address is unused, it typically returns 0xff.
+ */
+
+ for (i = 0; i < 10; i++)
+ if ((tmp = io_rd(mss, MSS_INDEX)) & MSS_IDXBUSY) DELAY(10000);
+ else break;
+
+ if (i >= 10) { /* Not an AD1848 */
+ BVDDB(printf("mss_detect, busy still set (0x%02x)\n", tmp));
+ goto no;
+ }
+ /*
+ * Test if it's possible to change contents of the indirect
+ * registers. Registers 0 and 1 are ADC volume registers. The bit
+ * 0x10 is read only so try to avoid using it.
+ */
+
+ ad_write(mss, 0, 0xaa);
+ ad_write(mss, 1, 0x45);/* 0x55 with bit 0x10 clear */
+ tmp1 = ad_read(mss, 0);
+ tmp2 = ad_read(mss, 1);
+ if (tmp1 != 0xaa || tmp2 != 0x45) {
+ BVDDB(printf("mss_detect error - IREG (%x/%x)\n", tmp1, tmp2));
+ goto no;
+ }
+
+ ad_write(mss, 0, 0x45);
+ ad_write(mss, 1, 0xaa);
+ tmp1 = ad_read(mss, 0);
+ tmp2 = ad_read(mss, 1);
+ if (tmp1 != 0x45 || tmp2 != 0xaa) {
+ BVDDB(printf("mss_detect error - IREG2 (%x/%x)\n", tmp1, tmp2));
+ goto no;
+ }
+
+ /*
+ * The indirect register I12 has some read only bits. Lets try to
+ * change them.
+ */
+
+ tmp = ad_read(mss, 12);
+ ad_write(mss, 12, (~tmp) & 0x0f);
+ tmp1 = ad_read(mss, 12);
+
+ if ((tmp & 0x0f) != (tmp1 & 0x0f)) {
+ BVDDB(printf("mss_detect - I12 (0x%02x was 0x%02x)\n", tmp1, tmp));
+ goto no;
+ }
+
+ /*
+ * NOTE! Last 4 bits of the reg I12 tell the chip revision.
+ * 0x01=RevB
+ * 0x0A=RevC. also CS4231/CS4231A and OPTi931
+ */
+
+ BVDDB(printf("mss_detect - chip revision 0x%02x\n", tmp & 0x0f);)
+
+ /*
+ * The original AD1848/CS4248 has just 16 indirect registers. This
+ * means that I0 and I16 should return the same value (etc.). Ensure
+ * that the Mode2 enable bit of I12 is 0. Otherwise this test fails
+ * with new parts.
+ */
-BVDDB(printf("mss_detect - chip revision 0x%02xn", tmp & 0x0f);)
-
-/*
-* The original AD1848/CS4248 has just 16 indirect registers. This
-* means that I0 and I16 should return the same value (etc.). Ensure
-* that the Mode2 enable bit of I12 is 0. Otherwise this test fails
-* with new parts.
-*/
-
-ad_write(mss, 12, 0); /* Mode2=disabled */
+ ad_write(mss, 12, 0); /* Mode2=disabled */
#if 0
-for (i = 0; i < 16; i++) {
-if ((tmp1 = ad_read(mss, i)) != (tmp2 = ad_read(mss, i + 16))) {
-BVDDB(printf("mss_detect warning - I%d: 0x%02x/0x%02xn",
-i, tmp1, tmp2));
-/*
-* note - this seems to fail on the 4232 on I11. So we just break
-* rather than fail. (which makes this test pointless - cg)
-*/
-break; /* return 0; */
-}
-}
+ for (i = 0; i < 16; i++) {
+ if ((tmp1 = ad_read(mss, i)) != (tmp2 = ad_read(mss, i + 16))) {
+ BVDDB(printf("mss_detect warning - I%d: 0x%02x/0x%02x\n",
+ i, tmp1, tmp2));
+ /*
+ * note - this seems to fail on the 4232 on I11. So we just break
+ * rather than fail. (which makes this test pointless - cg)
+ */
+ break; /* return 0; */
+ }
+ }
#endif
-/*
-* Try to switch the chip to mode2 (CS4231) by setting the MODE2 bit
-* (0x40). The bit 0x80 is always 1 in CS4248 and CS4231.
-*
-* On the OPTi931, however, I12 is readonly and only contains the
-* chip revision ID (as in the CS4231A). The upper bits return 0.
-*/
-
-ad_write(mss, 12, 0x40); /* Set mode2, clear 0x80 */
-
-tmp1 = ad_read(mss, 12);
-if (tmp1 & 0x80) name = "CS4248"; /* Our best knowledge just now */
-if ((tmp1 & 0xf0) == 0x00) {
-BVDDB(printf("this should be an OPTi931n");)
-} else if ((tmp1 & 0xc0) != 0xC0) goto gotit;
-/*
-* The 4231 has bit7=1 always, and bit6 we just set to 1.
-* We want to check that this is really a CS4231
-* Verify that setting I0 doesn't change I16.
-*/
-ad_write(mss, 16, 0); /* Set I16 to known value */
-ad_write(mss, 0, 0x45);
-if ((tmp1 = ad_read(mss, 16)) == 0x45) goto gotit;
-
-ad_write(mss, 0, 0xaa);
-if ((tmp1 = ad_read(mss, 16)) == 0xaa) { /* Rotten bits? */
-BVDDB(printf("mss_detect error - step H(%x)n", tmp1));
-goto no;
-}
-/* Verify that some bits of I25 are read only. */
-tmp1 = ad_read(mss, 25); /* Original bits */
-ad_write(mss, 25, ~tmp1); /* Invert all bits */
-if ((ad_read(mss, 25) & 0xe7) == (tmp1 & 0xe7)) {
-int id;
-
-/* It's at least CS4231 */
-name = "CS4231";
-mss->bd_id = MD_CS42XX;
-
-/*
-* It could be an AD1845 or CS4231A as well.
-* CS4231 and AD1845 report the same revision info in I25
-* while the CS4231A reports different.
-*/
-
-id = ad_read(mss, 25) & 0xe7;
-/*
-* b7-b5 = version number;
-* 100 : all CS4231
-* 101 : CS4231A
-*
-* b2-b0 = chip id;
-*/
-switch (id) {
-
-case 0xa0:
-name = "CS4231A";
-mss->bd_id = MD_CS42XX;
-break;
-
-case 0xa2:
-name = "CS4232";
-mss->bd_id = MD_CS42XX;
-break;
-
-case 0xb2:
-/* strange: the 4231 data sheet says b4-b3 are XX
-* so this should be the same as 0xa2
-*/
-name = "CS4232A";
-mss->bd_id = MD_CS42XX;
-break;
-
-case 0x80:
-/*
-* It must be a CS4231 or AD1845. The register I23
-* of CS4231 is undefined and it appears to be read
-* only. AD1845 uses I23 for setting sample rate.
-* Assume the chip is AD1845 if I23 is changeable.
-*/
-
-tmp = ad_read(mss, 23);
-
-ad_write(mss, 23, ~tmp);
-if (ad_read(mss, 23) != tmp) { /* AD1845 ? */
-name = "AD1845";
-mss->bd_id = MD_AD1845;
-}
-ad_write(mss, 23, tmp); /* Restore */
-
-yamaha = ymf_test(dev, mss);
-if (yamaha) {
-mss->bd_id = MD_YM0020;
-name = yamaha;
-}
-break;
-
-case 0x83: /* CS4236 */
-case 0x03: /* CS4236 on Intel PR440FX motherboard XXX */
-name = "CS4236";
-mss->bd_id = MD_CS42XX;
-break;
-
-default: /* Assume CS4231 */
-BVDDB(printf("unknown id 0x%02x, assuming CS4231n", id);)
-mss->bd_id = MD_CS42XX;
-}
-}
-ad_write(mss, 25, tmp1); /* Restore bits */
+ /*
+ * Try to switch the chip to mode2 (CS4231) by setting the MODE2 bit
+ * (0x40). The bit 0x80 is always 1 in CS4248 and CS4231.
+ *
+ * On the OPTi931, however, I12 is readonly and only contains the
+ * chip revision ID (as in the CS4231A). The upper bits return 0.
+ */
+
+ ad_write(mss, 12, 0x40); /* Set mode2, clear 0x80 */
+
+ tmp1 = ad_read(mss, 12);
+ if (tmp1 & 0x80) name = "CS4248"; /* Our best knowledge just now */
+ if ((tmp1 & 0xf0) == 0x00) {
+ BVDDB(printf("this should be an OPTi931\n");)
+ } else if ((tmp1 & 0xc0) != 0xC0) goto gotit;
+ /*
+ * The 4231 has bit7=1 always, and bit6 we just set to 1.
+ * We want to check that this is really a CS4231
+ * Verify that setting I0 doesn't change I16.
+ */
+ ad_write(mss, 16, 0); /* Set I16 to known value */
+ ad_write(mss, 0, 0x45);
+ if ((tmp1 = ad_read(mss, 16)) == 0x45) goto gotit;
+
+ ad_write(mss, 0, 0xaa);
+ if ((tmp1 = ad_read(mss, 16)) == 0xaa) { /* Rotten bits? */
+ BVDDB(printf("mss_detect error - step H(%x)\n", tmp1));
+ goto no;
+ }
+ /* Verify that some bits of I25 are read only. */
+ tmp1 = ad_read(mss, 25); /* Original bits */
+ ad_write(mss, 25, ~tmp1); /* Invert all bits */
+ if ((ad_read(mss, 25) & 0xe7) == (tmp1 & 0xe7)) {
+ int id;
+
+ /* It's at least CS4231 */
+ name = "CS4231";
+ mss->bd_id = MD_CS42XX;
+
+ /*
+ * It could be an AD1845 or CS4231A as well.
+ * CS4231 and AD1845 report the same revision info in I25
+ * while the CS4231A reports different.
+ */
+
+ id = ad_read(mss, 25) & 0xe7;
+ /*
+ * b7-b5 = version number;
+ * 100 : all CS4231
+ * 101 : CS4231A
+ *
+ * b2-b0 = chip id;
+ */
+ switch (id) {
+
+ case 0xa0:
+ name = "CS4231A";
+ mss->bd_id = MD_CS42XX;
+ break;
+
+ case 0xa2:
+ name = "CS4232";
+ mss->bd_id = MD_CS42XX;
+ break;
+
+ case 0xb2:
+ /* strange: the 4231 data sheet says b4-b3 are XX
+ * so this should be the same as 0xa2
+ */
+ name = "CS4232A";
+ mss->bd_id = MD_CS42XX;
+ break;
+
+ case 0x80:
+ /*
+ * It must be a CS4231 or AD1845. The register I23
+ * of CS4231 is undefined and it appears to be read
+ * only. AD1845 uses I23 for setting sample rate.
+ * Assume the chip is AD1845 if I23 is changeable.
+ */
+
+ tmp = ad_read(mss, 23);
+
+ ad_write(mss, 23, ~tmp);
+ if (ad_read(mss, 23) != tmp) { /* AD1845 ? */
+ name = "AD1845";
+ mss->bd_id = MD_AD1845;
+ }
+ ad_write(mss, 23, tmp); /* Restore */
+
+ yamaha = ymf_test(dev, mss);
+ if (yamaha) {
+ mss->bd_id = MD_YM0020;
+ name = yamaha;
+ }
+ break;
+
+ case 0x83: /* CS4236 */
+ case 0x03: /* CS4236 on Intel PR440FX motherboard XXX */
+ name = "CS4236";
+ mss->bd_id = MD_CS42XX;
+ break;
+
+ default: /* Assume CS4231 */
+ BVDDB(printf("unknown id 0x%02x, assuming CS4231\n", id);)
+ mss->bd_id = MD_CS42XX;
+ }
+ }
+ ad_write(mss, 25, tmp1); /* Restore bits */
gotit:
-BVDDB(printf("mss_detect() - Detected %sn", name));
-device_set_desc(dev, name);
-device_set_flags(dev,
-((device_get_flags(dev) & ~DV_F_DEV_MASK) |
-((mss->bd_id << DV_F_DEV_SHIFT) & DV_F_DEV_MASK)));
-return 0;
+ BVDDB(printf("mss_detect() - Detected %s\n", name));
+ device_set_desc(dev, name);
+ device_set_flags(dev,
+ ((device_get_flags(dev) & ~DV_F_DEV_MASK) |
+ ((mss->bd_id << DV_F_DEV_SHIFT) & DV_F_DEV_MASK)));
+ return 0;
no:
-return ENXIO;
+ return ENXIO;
}
#ifndef PC98
static int
opti_detect(device_t dev, struct mss_info *mss)
{
-int c;
-static const struct opticard {
-int boardid;
-int passwdreg;
-int password;
-int base;
-int indir_reg;
-} cards[] = {
-{ MD_OPTI930, 0, 0xe4, 0xf8f, 0xe0e }, /* 930 */
-{ MD_OPTI924, 3, 0xe5, 0xf8c, 0, }, /* 924 */
-{ 0 },
-};
-mss->conf_rid = 3;
-mss->indir_rid = 4;
-for (c = 0; cards[c].base; c++) {
-mss->optibase = cards[c].base;
-mss->password = cards[c].password;
-mss->passwdreg = cards[c].passwdreg;
-mss->bd_id = cards[c].boardid;
-
-if (cards[c].indir_reg)
-mss->indir = bus_alloc_resource(dev, SYS_RES_IOPORT,
-&mss->indir_rid, cards[c].indir_reg,
-cards[c].indir_reg+1, 1, RF_ACTIVE);
-
-mss->conf_base = bus_alloc_resource(dev, SYS_RES_IOPORT,
-&mss->conf_rid, mss->optibase, mss->optibase+9,
-9, RF_ACTIVE);
-
-if (opti_read(mss, 1) != 0xff) {
-return 1;
-} else {
-if (mss->indir)
-bus_release_resource(dev, SYS_RES_IOPORT, mss->indir_rid, mss->indir);
-mss->indir = NULL;
-if (mss->conf_base)
-bus_release_resource(dev, SYS_RES_IOPORT, mss->conf_rid, mss->conf_base);
-mss->conf_base = NULL;
-}
-}
-return 0;
+ int c;
+ static const struct opticard {
+ int boardid;
+ int passwdreg;
+ int password;
+ int base;
+ int indir_reg;
+ } cards[] = {
+ { MD_OPTI930, 0, 0xe4, 0xf8f, 0xe0e }, /* 930 */
+ { MD_OPTI924, 3, 0xe5, 0xf8c, 0, }, /* 924 */
+ { 0 },
+ };
+ mss->conf_rid = 3;
+ mss->indir_rid = 4;
+ for (c = 0; cards[c].base; c++) {
+ mss->optibase = cards[c].base;
+ mss->password = cards[c].password;
+ mss->passwdreg = cards[c].passwdreg;
+ mss->bd_id = cards[c].boardid;
+
+ if (cards[c].indir_reg)
+ mss->indir = bus_alloc_resource(dev, SYS_RES_IOPORT,
+ &mss->indir_rid, cards[c].indir_reg,
+ cards[c].indir_reg+1, 1, RF_ACTIVE);
+
+ mss->conf_base = bus_alloc_resource(dev, SYS_RES_IOPORT,
+ &mss->conf_rid, mss->optibase, mss->optibase+9,
+ 9, RF_ACTIVE);
+
+ if (opti_read(mss, 1) != 0xff) {
+ return 1;
+ } else {
+ if (mss->indir)
+ bus_release_resource(dev, SYS_RES_IOPORT, mss->indir_rid, mss->indir);
+ mss->indir = NULL;
+ if (mss->conf_base)
+ bus_release_resource(dev, SYS_RES_IOPORT, mss->conf_rid, mss->conf_base);
+ mss->conf_base = NULL;
+ }
+ }
+ return 0;
}
#endif
static char *
ymf_test(device_t dev, struct mss_info *mss)
{
-static int ports[] = {0x370, 0x310, 0x538};
-int p, i, j, version;
-static char *chipset[] = {
-NULL, /* 0 */
-"OPL3-SA2 (YMF711)", /* 1 */
-"OPL3-SA3 (YMF715)", /* 2 */
-"OPL3-SA3 (YMF715)", /* 3 */
-"OPL3-SAx (YMF719)", /* 4 */
-"OPL3-SAx (YMF719)", /* 5 */
-"OPL3-SAx (YMF719)", /* 6 */
-"OPL3-SAx (YMF719)", /* 7 */
-};
-
-for (p = 0; p < 3; p++) {
-mss->conf_rid = 1;
-mss->conf_base = bus_alloc_resource(dev,
-SYS_RES_IOPORT,
-&mss->conf_rid,
-ports[p], ports[p] + 1, 2,
-RF_ACTIVE);
-if (!mss->conf_base) return 0;
-
-/* Test the index port of the config registers */
-i = port_rd(mss->conf_base, 0);
-port_wr(mss->conf_base, 0, OPL3SAx_DMACONF);
-j = (port_rd(mss->conf_base, 0) == OPL3SAx_DMACONF)? 1 : 0;
-port_wr(mss->conf_base, 0, i);
-if (!j) {
-bus_release_resource(dev, SYS_RES_IOPORT,
-mss->conf_rid, mss->conf_base);
+ static int ports[] = {0x370, 0x310, 0x538};
+ int p, i, j, version;
+ static char *chipset[] = {
+ NULL, /* 0 */
+ "OPL3-SA2 (YMF711)", /* 1 */
+ "OPL3-SA3 (YMF715)", /* 2 */
+ "OPL3-SA3 (YMF715)", /* 3 */
+ "OPL3-SAx (YMF719)", /* 4 */
+ "OPL3-SAx (YMF719)", /* 5 */
+ "OPL3-SAx (YMF719)", /* 6 */
+ "OPL3-SAx (YMF719)", /* 7 */
+ };
+
+ for (p = 0; p < 3; p++) {
+ mss->conf_rid = 1;
+ mss->conf_base = bus_alloc_resource(dev,
+ SYS_RES_IOPORT,
+ &mss->conf_rid,
+ ports[p], ports[p] + 1, 2,
+ RF_ACTIVE);
+ if (!mss->conf_base) return 0;
+
+ /* Test the index port of the config registers */
+ i = port_rd(mss->conf_base, 0);
+ port_wr(mss->conf_base, 0, OPL3SAx_DMACONF);
+ j = (port_rd(mss->conf_base, 0) == OPL3SAx_DMACONF)? 1 : 0;
+ port_wr(mss->conf_base, 0, i);
+ if (!j) {
+ bus_release_resource(dev, SYS_RES_IOPORT,
+ mss->conf_rid, mss->conf_base);
#ifdef PC98
-/* PC98 need this. I don't know reason why. */
-bus_delete_resource(dev, SYS_RES_IOPORT, mss->conf_rid);
+ /* PC98 need this. I don't know reason why. */
+ bus_delete_resource(dev, SYS_RES_IOPORT, mss->conf_rid);
#endif
-mss->conf_base = 0;
-continue;
-}
-version = conf_rd(mss, OPL3SAx_MISC) & 0x07;
-return chipset[version];
-}
-return NULL;
+ mss->conf_base = 0;
+ continue;
+ }
+ version = conf_rd(mss, OPL3SAx_MISC) & 0x07;
+ return chipset[version];
+ }
+ return NULL;
}
static int
mss_doattach(device_t dev, struct mss_info *mss)
{
-int pdma, rdma, flags = device_get_flags(dev);
-char status[SND_STATUSLEN], status2[SND_STATUSLEN];
+ int pdma, rdma, flags = device_get_flags(dev);
+ char status[SND_STATUSLEN], status2[SND_STATUSLEN];
-mss->lock = snd_mtxcreate(device_get_nameunit(dev), "sound softc");
-mss->bufsize = pcm_getbuffersize(dev, 4096, MSS_DEFAULT_BUFSZ, 65536);
-if (!mss_alloc_resources(mss, dev)) goto no;
-mss_init(mss, dev);
-pdma = rman_get_start(mss->drq1);
-rdma = rman_get_start(mss->drq2);
-if (flags & DV_F_TRUE_MSS) {
-/* has IRQ/DMA registers, set IRQ and DMA addr */
+ mss->lock = snd_mtxcreate(device_get_nameunit(dev), "snd_mss softc");
+ mss->bufsize = pcm_getbuffersize(dev, 4096, MSS_DEFAULT_BUFSZ, 65536);
+ if (!mss_alloc_resources(mss, dev)) goto no;
+ mss_init(mss, dev);
+ pdma = rman_get_start(mss->drq1);
+ rdma = rman_get_start(mss->drq2);
+ if (flags & DV_F_TRUE_MSS) {
+ /* has IRQ/DMA registers, set IRQ and DMA addr */
#ifdef PC98 /* CS423[12] in PC98 can use IRQ3,5,10,12 */
-static char interrupt_bits[13] =
-{-1, -1, -1, 0x08, -1, 0x10, -1, -1, -1, -1, 0x18, -1, 0x20};
+ static char interrupt_bits[13] =
+ {-1, -1, -1, 0x08, -1, 0x10, -1, -1, -1, -1, 0x18, -1, 0x20};
#else
-static char interrupt_bits[12] =
-{-1, -1, -1, -1, -1, 0x28, -1, 0x08, -1, 0x10, 0x18, 0x20};
+ static char interrupt_bits[12] =
+ {-1, -1, -1, -1, -1, 0x28, -1, 0x08, -1, 0x10, 0x18, 0x20};
#endif
-static char pdma_bits[4] = {1, 2, -1, 3};
-static char valid_rdma[4] = {1, 0, -1, 0};
-char bits;
+ static char pdma_bits[4] = {1, 2, -1, 3};
+ static char valid_rdma[4] = {1, 0, -1, 0};
+ char bits;
-if (!mss->irq || (bits = interrupt_bits[rman_get_start(mss->irq)]) == -1)
-goto no;
+ if (!mss->irq || (bits = interrupt_bits[rman_get_start(mss->irq)]) == -1)
+ goto no;
#ifndef PC98 /* CS423[12] in PC98 don't support this. */
-io_wr(mss, 0, bits | 0x40); /* config port */
-if ((io_rd(mss, 3) & 0x40) == 0) device_printf(dev, "IRQ Conflict?n");
+ io_wr(mss, 0, bits | 0x40); /* config port */
+ if ((io_rd(mss, 3) & 0x40) == 0) device_printf(dev, "IRQ Conflict?\n");
#endif
-/* Write IRQ+DMA setup */
-if (pdma_bits[pdma] == -1) goto no;
-bits |= pdma_bits[pdma];
-if (pdma != rdma) {
-if (rdma == valid_rdma[pdma]) bits |= 4;
-else {
-printf("invalid dual dma config %d:%dn", pdma, rdma);
-goto no;
-}
-}
-io_wr(mss, 0, bits);
-printf("drq/irq conf %xn", io_rd(mss, 0));
-}
-mixer_init(dev, (mss->bd_id == MD_YM0020)? &ymmix_mixer_class : &mssmix_mixer_class, mss);
-switch (mss->bd_id) {
-case MD_OPTI931:
-snd_setup_intr(dev, mss->irq, 0, opti931_intr, mss, &mss->ih);
-break;
-default:
-snd_setup_intr(dev, mss->irq, 0, mss_intr, mss, &mss->ih);
-}
-if (pdma == rdma)
-pcm_setflags(dev, pcm_getflags(dev) | SD_F_SIMPLEX);
-if (bus_dma_tag_create(/*parent*/NULL, /*alignment*/2, /*boundary*/0,
-/*lowaddr*/BUS_SPACE_MAXADDR_24BIT,
-/*highaddr*/BUS_SPACE_MAXADDR,
-/*filter*/NULL, /*filterarg*/NULL,
-/*maxsize*/mss->bufsize, /*nsegments*/1,
-/*maxsegz*/0x3ffff, /*flags*/0,
-/*lockfunc*/busdma_lock_mutex, /*lockarg*/&Giant,
-&mss->parent_dmat) != 0) {
-device_printf(dev, "unable to create dma tagn");
-goto no;
-}
-
-if (pdma != rdma)
-snprintf(status2, SND_STATUSLEN, ":%d", rdma);
-else
-status2[0] = '0';
-
-snprintf(status, SND_STATUSLEN, "at io 0x%lx irq %ld drq %d%s bufsz %u",
-rman_get_start(mss->io_base), rman_get_start(mss->irq), pdma, status2, mss->bufsize);
-
-if (pcm_register(dev, mss, 1, 1)) goto no;
-pcm_addchan(dev, PCMDIR_REC, &msschan_class, mss);
-pcm_addchan(dev, PCMDIR_PLAY, &msschan_class, mss);
-pcm_setstatus(dev, status);
+ /* Write IRQ+DMA setup */
+ if (pdma_bits[pdma] == -1) goto no;
+ bits |= pdma_bits[pdma];
+ if (pdma != rdma) {
+ if (rdma == valid_rdma[pdma]) bits |= 4;
+ else {
+ printf("invalid dual dma config %d:%d\n", pdma, rdma);
+ goto no;
+ }
+ }
+ io_wr(mss, 0, bits);
+ printf("drq/irq conf %x\n", io_rd(mss, 0));
+ }
+ mixer_init(dev, (mss->bd_id == MD_YM0020)? &ymmix_mixer_class : &mssmix_mixer_class, mss);
+ switch (mss->bd_id) {
+ case MD_OPTI931:
+ snd_setup_intr(dev, mss->irq, 0, opti931_intr, mss, &mss->ih);
+ break;
+ default:
+ snd_setup_intr(dev, mss->irq, 0, mss_intr, mss, &mss->ih);
+ }
+ if (pdma == rdma)
+ pcm_setflags(dev, pcm_getflags(dev) | SD_F_SIMPLEX);
+ if (bus_dma_tag_create(/*parent*/bus_get_dma_tag(dev), /*alignment*/2,
+ /*boundary*/0,
+ /*lowaddr*/BUS_SPACE_MAXADDR_24BIT,
+ /*highaddr*/BUS_SPACE_MAXADDR,
+ /*filter*/NULL, /*filterarg*/NULL,
+ /*maxsize*/mss->bufsize, /*nsegments*/1,
+ /*maxsegz*/0x3ffff, /*flags*/0,
+ /*lockfunc*/busdma_lock_mutex, /*lockarg*/&Giant,
+ &mss->parent_dmat) != 0) {
+ device_printf(dev, "unable to create dma tag\n");
+ goto no;
+ }
+
+ if (pdma != rdma)
+ snprintf(status2, SND_STATUSLEN, ":%d", rdma);
+ else
+ status2[0] = '\0';
+
+ snprintf(status, SND_STATUSLEN, "at io 0x%lx irq %ld drq %d%s bufsz %u",
+ rman_get_start(mss->io_base), rman_get_start(mss->irq), pdma, status2, mss->bufsize);
+
+ if (pcm_register(dev, mss, 1, 1)) goto no;
+ pcm_addchan(dev, PCMDIR_REC, &msschan_class, mss);
+ pcm_addchan(dev, PCMDIR_PLAY, &msschan_class, mss);
+ pcm_setstatus(dev, status);
-return 0;
+ return 0;
no:
-mss_release_resources(mss, dev);
-return ENXIO;
+ mss_release_resources(mss, dev);
+ return ENXIO;
}
static int
mss_detach(device_t dev)
{
-int r;
-struct mss_info *mss;
+ int r;
+ struct mss_info *mss;
-r = pcm_unregister(dev);
-if (r)
-return r;
+ r = pcm_unregister(dev);
+ if (r)
+ return r;
-mss = pcm_getdevinfo(dev);
-mss_release_resources(mss, dev);
+ mss = pcm_getdevinfo(dev);
+ mss_release_resources(mss, dev);
-return 0;
+ return 0;
}
static int
mss_attach(device_t dev)
{
-struct mss_info *mss;
-int flags = device_get_flags(dev);
+ struct mss_info *mss;
+ int flags = device_get_flags(dev);
-mss = (struct mss_info *)malloc(sizeof *mss, M_DEVBUF, M_NOWAIT | M_ZERO);
-if (!mss) return ENXIO;
+ mss = (struct mss_info *)malloc(sizeof *mss, M_DEVBUF, M_NOWAIT | M_ZERO);
+ if (!mss) return ENXIO;
-mss->io_rid = 0;
-mss->conf_rid = -1;
-mss->irq_rid = 0;
-mss->drq1_rid = 0;
-mss->drq2_rid = -1;
-if (flags & DV_F_DUAL_DMA) {
-bus_set_resource(dev, SYS_RES_DRQ, 1,
-flags & DV_F_DRQ_MASK, 1);
-mss->drq2_rid = 1;
-}
-mss->bd_id = (device_get_flags(dev) & DV_F_DEV_MASK) >> DV_F_DEV_SHIFT;
-if (mss->bd_id == MD_YM0020) ymf_test(dev, mss);
-return mss_doattach(dev, mss);
+ mss->io_rid = 0;
+ mss->conf_rid = -1;
+ mss->irq_rid = 0;
+ mss->drq1_rid = 0;
+ mss->drq2_rid = -1;
+ if (flags & DV_F_DUAL_DMA) {
+ bus_set_resource(dev, SYS_RES_DRQ, 1,
+ flags & DV_F_DRQ_MASK, 1);
+ mss->drq2_rid = 1;
+ }
+ mss->bd_id = (device_get_flags(dev) & DV_F_DEV_MASK) >> DV_F_DEV_SHIFT;
+ if (mss->bd_id == MD_YM0020) ymf_test(dev, mss);
+ return mss_doattach(dev, mss);
}
/*
-* mss_resume() is the code to allow a laptop to resume using the sound
-* card.
-*
-* This routine re-sets the state of the board to the state before going
-* to sleep. According to the yamaha docs this is the right thing to do,
-* but getting DMA restarted appears to be a bit of a trick, so the device
-* has to be closed and re-opened to be re-used, but there is no skipping
-* problem, and volume, bass/treble and most other things are restored
-* properly.
-*
-*/
+ * mss_resume() is the code to allow a laptop to resume using the sound
+ * card.
+ *
+ * This routine re-sets the state of the board to the state before going
+ * to sleep. According to the yamaha docs this is the right thing to do,
+ * but getting DMA restarted appears to be a bit of a trick, so the device
+ * has to be closed and re-opened to be re-used, but there is no skipping
+ * problem, and volume, bass/treble and most other things are restored
+ * properly.
+ *
+ */
static int
mss_resume(device_t dev)
{
-/*
-* Restore the state taken below.
-*/
-struct mss_info *mss;
-int i;
-
-mss = pcm_getdevinfo(dev);
-
-if(mss->bd_id == MD_YM0020 || mss->bd_id == MD_CS423X) {
-/* This works on a Toshiba Libretto 100CT. */
-for (i = 0; i < MSS_INDEXED_REGS; i++)
-ad_write(mss, i, mss->mss_indexed_regs[i]);
-for (i = 0; i < OPL_INDEXED_REGS; i++)
-conf_wr(mss, i, mss->opl_indexed_regs[i]);
-mss_intr(mss);
-}
-
-if (mss->bd_id == MD_CS423X) {
-/* Needed on IBM Thinkpad 600E */
-mss_lock(mss);
-mss_format(&mss->pch, mss->pch.channel->format);
-mss_speed(&mss->pch, mss->pch.channel->speed);
-mss_unlock(mss);
-}
-
-return 0;
+ /*
+ * Restore the state taken below.
+ */
+ struct mss_info *mss;
+ int i;
+
+ mss = pcm_getdevinfo(dev);
+
+ if(mss->bd_id == MD_YM0020 || mss->bd_id == MD_CS423X) {
+ /* This works on a Toshiba Libretto 100CT. */
+ for (i = 0; i < MSS_INDEXED_REGS; i++)
+ ad_write(mss, i, mss->mss_indexed_regs[i]);
+ for (i = 0; i < OPL_INDEXED_REGS; i++)
+ conf_wr(mss, i, mss->opl_indexed_regs[i]);
+ mss_intr(mss);
+ }
+
+ if (mss->bd_id == MD_CS423X) {
+ /* Needed on IBM Thinkpad 600E */
+ mss_lock(mss);
+ mss_format(&mss->pch, mss->pch.channel->format);
+ mss_speed(&mss->pch, mss->pch.channel->speed);
+ mss_unlock(mss);
+ }
+
+ return 0;
}
/*
-* mss_suspend() is the code that gets called right before a laptop
-* suspends.
-*
-* This code saves the state of the sound card right before shutdown
-* so it can be restored above.
-*
-*/
+ * mss_suspend() is the code that gets called right before a laptop
+ * suspends.
+ *
+ * This code saves the state of the sound card right before shutdown
+ * so it can be restored above.
+ *
+ */
static int
mss_suspend(device_t dev)
{
-int i;
-struct mss_info *mss;
+ int i;
+ struct mss_info *mss;
-mss = pcm_getdevinfo(dev);
+ mss = pcm_getdevinfo(dev);
-if(mss->bd_id == MD_YM0020 || mss->bd_id == MD_CS423X)
-{
-/* this stops playback. */
-conf_wr(mss, 0x12, 0x0c);
-for(i = 0; i < MSS_INDEXED_REGS; i++)
-mss->mss_indexed_regs[i] = ad_read(mss, i);
-for(i = 0; i < OPL_INDEXED_REGS; i++)
-mss->opl_indexed_regs[i] = conf_rd(mss, i);
-mss->opl_indexed_regs[0x12] = 0x0;
-}
-return 0;
+ if(mss->bd_id == MD_YM0020 || mss->bd_id == MD_CS423X)
+ {
+ /* this stops playback. */
+ conf_wr(mss, 0x12, 0x0c);
+ for(i = 0; i < MSS_INDEXED_REGS; i++)
+ mss->mss_indexed_regs[i] = ad_read(mss, i);
+ for(i = 0; i < OPL_INDEXED_REGS; i++)
+ mss->opl_indexed_regs[i] = conf_rd(mss, i);
+ mss->opl_indexed_regs[0x12] = 0x0;
+ }
+ return 0;
}
static device_method_t mss_methods[] = {
-/* Device interface */
-DEVMETHOD(device_probe, mss_probe),
-DEVMETHOD(device_attach, mss_attach),
-DEVMETHOD(device_detach, mss_detach),
-DEVMETHOD(device_suspend, mss_suspend),
-DEVMETHOD(device_resume, mss_resume),
+ /* Device interface */
+ DEVMETHOD(device_probe, mss_probe),
+ DEVMETHOD(device_attach, mss_attach),
+ DEVMETHOD(device_detach, mss_detach),
+ DEVMETHOD(device_suspend, mss_suspend),
+ DEVMETHOD(device_resume, mss_resume),
-{ 0, 0 }
+ { 0, 0 }
};
static driver_t mss_driver = {
-"pcm",
-mss_methods,
-PCM_SOFTC_SIZE,
+ "pcm",
+ mss_methods,
+ PCM_SOFTC_SIZE,
};
DRIVER_MODULE(snd_mss, isa, mss_driver, pcm_devclass, 0, 0);
@@ -1912,314 +1915,311 @@
static int
azt2320_mss_mode(struct mss_info *mss, device_t dev)
{
-struct resource *sbport;
-int i, ret, rid;
+ struct resource *sbport;
+ int i, ret, rid;
-rid = 0;
-ret = -1;
-sbport = bus_alloc_resource_any(dev, SYS_RES_IOPORT, &rid, RF_ACTIVE);
-if (sbport) {
-for (i = 0; i < 1000; i++) {
-if ((port_rd(sbport, SBDSP_STATUS) & 0x80))
-DELAY((i > 100) ? 1000 : 10);
-else {
-port_wr(sbport, SBDSP_CMD, 0x09);
-break;
-}
-}
-for (i = 0; i < 1000; i++) {
-if ((port_rd(sbport, SBDSP_STATUS) & 0x80))
-DELAY((i > 100) ? 1000 : 10);
-else {
-port_wr(sbport, SBDSP_CMD, 0x00);
-ret = 0;
-break;
-}
-}
-DELAY(1000);
-bus_release_resource(dev, SYS_RES_IOPORT, rid, sbport);
-}
-return ret;
+ rid = 0;
+ ret = -1;
+ sbport = bus_alloc_resource_any(dev, SYS_RES_IOPORT, &rid, RF_ACTIVE);
+ if (sbport) {
+ for (i = 0; i < 1000; i++) {
+ if ((port_rd(sbport, SBDSP_STATUS) & 0x80))
+ DELAY((i > 100) ? 1000 : 10);
+ else {
+ port_wr(sbport, SBDSP_CMD, 0x09);
+ break;
+ }
+ }
+ for (i = 0; i < 1000; i++) {
+ if ((port_rd(sbport, SBDSP_STATUS) & 0x80))
+ DELAY((i > 100) ? 1000 : 10);
+ else {
+ port_wr(sbport, SBDSP_CMD, 0x00);
+ ret = 0;
+ break;
+ }
+ }
+ DELAY(1000);
+ bus_release_resource(dev, SYS_RES_IOPORT, rid, sbport);
+ }
+ return ret;
}
static struct isa_pnp_id pnpmss_ids[] = {
-{0x0000630e, "CS423x"}, /* CSC0000 */
-{0x0001630e, "CS423x-PCI"}, /* CSC0100 */
-{0x01000000, "CMI8330"}, /* @@@0001 */
-{0x2100a865, "Yamaha OPL-SAx"}, /* YMH0021 */
-{0x1110d315, "ENSONIQ SoundscapeVIVO"}, /* ENS1011 */
-{0x1093143e, "OPTi931"}, /* OPT9310 */
-{0x5092143e, "OPTi925"}, /* OPT9250 XXX guess */
-{0x0000143e, "OPTi924"}, /* OPT0924 */
-{0x1022b839, "Neomagic 256AV (non-ac97)"}, /* NMX2210 */
-{0x01005407, "Aztech 2320"}, /* AZT0001 */
+ {0x0000630e, "CS423x"}, /* CSC0000 */
+ {0x0001630e, "CS423x-PCI"}, /* CSC0100 */
+ {0x01000000, "CMI8330"}, /* @@@0001 */
+ {0x2100a865, "Yamaha OPL-SAx"}, /* YMH0021 */
+ {0x1110d315, "ENSONIQ SoundscapeVIVO"}, /* ENS1011 */
+ {0x1093143e, "OPTi931"}, /* OPT9310 */
+ {0x5092143e, "OPTi925"}, /* OPT9250 XXX guess */
+ {0x0000143e, "OPTi924"}, /* OPT0924 */
+ {0x1022b839, "Neomagic 256AV (non-ac97)"}, /* NMX2210 */
+ {0x01005407, "Aztech 2320"}, /* AZT0001 */
#if 0
-{0x0000561e, "GusPnP"}, /* GRV0000 */
+ {0x0000561e, "GusPnP"}, /* GRV0000 */
#endif
-{0},
+ {0},
};
static int
pnpmss_probe(device_t dev)
{
-u_int32_t lid, vid;
+ u_int32_t lid, vid;
-lid = isa_get_logicalid(dev);
-vid = isa_get_vendorid(dev);
-if (lid == 0x01000000 && vid != 0x0100a90d) /* CMI0001 */
-return ENXIO;
-return ISA_PNP_PROBE(device_get_parent(dev), dev, pnpmss_ids);
+ lid = isa_get_logicalid(dev);
+ vid = isa_get_vendorid(dev);
+ if (lid == 0x01000000 && vid != 0x0100a90d) /* CMI0001 */
+ return ENXIO;
+ return ISA_PNP_PROBE(device_get_parent(dev), dev, pnpmss_ids);
}
static int
pnpmss_attach(device_t dev)
{
-struct mss_info *mss;
-
-mss = (struct mss_info *)malloc(sizeof *mss, M_DEVBUF, M_NOWAIT | M_ZERO);
-if (!mss)
-return ENXIO;
-
-mss->io_rid = 0;
-mss->conf_rid = -1;
-mss->irq_rid = 0;
-mss->drq1_rid = 0;
-mss->drq2_rid = 1;
-mss->bd_id = MD_CS42XX;
-
-switch (isa_get_logicalid(dev)) {
-case 0x0000630e: /* CSC0000 */
-case 0x0001630e: /* CSC0100 */
-mss->bd_flags |= BD_F_MSS_OFFSET;
-mss->bd_id = MD_CS423X;
-break;
-
-case 0x2100a865: /* YHM0021 */
-mss->io_rid = 1;
-mss->conf_rid = 4;
-mss->bd_id = MD_YM0020;
-break;
-
-case 0x1110d315: /* ENS1011 */
-mss->io_rid = 1;
-mss->bd_id = MD_VIVO;
-break;
-
-case 0x1093143e: /* OPT9310 */
-mss->bd_flags |= BD_F_MSS_OFFSET;
-mss->conf_rid = 3;
-mss->bd_id = MD_OPTI931;
-break;
-
-case 0x5092143e: /* OPT9250 XXX guess */
-mss->io_rid = 1;
-mss->conf_rid = 3;
-mss->bd_id = MD_OPTI925;
-break;
-
-case 0x0000143e: /* OPT0924 */
-mss->password = 0xe5;
-mss->passwdreg = 3;
-mss->optibase = 0xf0c;
-mss->io_rid = 2;
-mss->conf_rid = 3;
-mss->bd_id = MD_OPTI924;
-mss->bd_flags |= BD_F_924PNP;
-if(opti_init(dev, mss) != 0) {
-free(mss, M_DEVBUF);
-return ENXIO;
-}
-break;
-
-case 0x1022b839: /* NMX2210 */
-mss->io_rid = 1;
-break;
-
-case 0x01005407: /* AZT0001 */
-/* put into MSS mode first (snatched from NetBSD) */
-if (azt2320_mss_mode(mss, dev) == -1) {
-free(mss, M_DEVBUF);
-return ENXIO;
-}
-
-mss->bd_flags |= BD_F_MSS_OFFSET;
-mss->io_rid = 2;
-break;
+ struct mss_info *mss;
+ mss = malloc(sizeof(*mss), M_DEVBUF, M_WAITOK | M_ZERO);
+ mss->io_rid = 0;
+ mss->conf_rid = -1;
+ mss->irq_rid = 0;
+ mss->drq1_rid = 0;
+ mss->drq2_rid = 1;
+ mss->bd_id = MD_CS42XX;
+
+ switch (isa_get_logicalid(dev)) {
+ case 0x0000630e: /* CSC0000 */
+ case 0x0001630e: /* CSC0100 */
+ mss->bd_flags |= BD_F_MSS_OFFSET;
+ mss->bd_id = MD_CS423X;
+ break;
+
+ case 0x2100a865: /* YHM0021 */
+ mss->io_rid = 1;
+ mss->conf_rid = 4;
+ mss->bd_id = MD_YM0020;
+ break;
+
+ case 0x1110d315: /* ENS1011 */
+ mss->io_rid = 1;
+ mss->bd_id = MD_VIVO;
+ break;
+
+ case 0x1093143e: /* OPT9310 */
+ mss->bd_flags |= BD_F_MSS_OFFSET;
+ mss->conf_rid = 3;
+ mss->bd_id = MD_OPTI931;
+ break;
+
+ case 0x5092143e: /* OPT9250 XXX guess */
+ mss->io_rid = 1;
+ mss->conf_rid = 3;
+ mss->bd_id = MD_OPTI925;
+ break;
+
+ case 0x0000143e: /* OPT0924 */
+ mss->password = 0xe5;
+ mss->passwdreg = 3;
+ mss->optibase = 0xf0c;
+ mss->io_rid = 2;
+ mss->conf_rid = 3;
+ mss->bd_id = MD_OPTI924;
+ mss->bd_flags |= BD_F_924PNP;
+ if(opti_init(dev, mss) != 0) {
+ free(mss, M_DEVBUF);
+ return ENXIO;
+ }
+ break;
+
+ case 0x1022b839: /* NMX2210 */
+ mss->io_rid = 1;
+ break;
+
+ case 0x01005407: /* AZT0001 */
+ /* put into MSS mode first (snatched from NetBSD) */
+ if (azt2320_mss_mode(mss, dev) == -1) {
+ free(mss, M_DEVBUF);
+ return ENXIO;
+ }
+
+ mss->bd_flags |= BD_F_MSS_OFFSET;
+ mss->io_rid = 2;
+ break;
+
#if 0
-case 0x0000561e: /* GRV0000 */
-mss->bd_flags |= BD_F_MSS_OFFSET;
-mss->io_rid = 2;
-mss->conf_rid = 1;
-mss->drq1_rid = 1;
-mss->drq2_rid = 0;
-mss->bd_id = MD_GUSPNP;
-break;
+ case 0x0000561e: /* GRV0000 */
+ mss->bd_flags |= BD_F_MSS_OFFSET;
+ mss->io_rid = 2;
+ mss->conf_rid = 1;
+ mss->drq1_rid = 1;
+ mss->drq2_rid = 0;
+ mss->bd_id = MD_GUSPNP;
+ break;
#endif
-case 0x01000000: /* @@@0001 */
-mss->drq2_rid = -1;
-break;
-
-/* Unknown MSS default. We could let the CSC0000 stuff match too */
-default:
-mss->bd_flags |= BD_F_MSS_OFFSET;
-break;
-}
-return mss_doattach(dev, mss);
+ case 0x01000000: /* @@@0001 */
+ mss->drq2_rid = -1;
+ break;
+
+ /* Unknown MSS default. We could let the CSC0000 stuff match too */
+ default:
+ mss->bd_flags |= BD_F_MSS_OFFSET;
+ break;
+ }
+ return mss_doattach(dev, mss);
}
static int
opti_init(device_t dev, struct mss_info *mss)
{
-int flags = device_get_flags(dev);
-int basebits = 0;
+ int flags = device_get_flags(dev);
+ int basebits = 0;
-if (!mss->conf_base) {
-bus_set_resource(dev, SYS_RES_IOPORT, mss->conf_rid,
-mss->optibase, 0x9);
-
-mss->conf_base = bus_alloc_resource(dev, SYS_RES_IOPORT,
-&mss->conf_rid, mss->optibase, mss->optibase+0x9,
-0x9, RF_ACTIVE);
-}
-
-if (!mss->conf_base)
-return ENXIO;
-
-if (!mss->io_base)
-mss->io_base = bus_alloc_resource(dev, SYS_RES_IOPORT,
-&mss->io_rid, 0, ~0, 8, RF_ACTIVE);
-
-if (!mss->io_base) /* No hint specified, use 0x530 */
-mss->io_base = bus_alloc_resource(dev, SYS_RES_IOPORT,
-&mss->io_rid, 0x530, 0x537, 8, RF_ACTIVE);
-
-if (!mss->io_base)
-return ENXIO;
-
-switch (rman_get_start(mss->io_base)) {
-case 0x530:
-basebits = 0x0;
-break;
-case 0xe80:
-basebits = 0x10;
-break;
-case 0xf40:
-basebits = 0x20;
-break;
-case 0x604:
-basebits = 0x30;
-break;
-default:
-printf("opti_init: invalid MSS base address!n");
-return ENXIO;
-}
-
-
-switch (mss->bd_id) {
-case MD_OPTI924:
-opti_write(mss, 1, 0x80 | basebits); /* MSS mode */
-opti_write(mss, 2, 0x00); /* Disable CD */
-opti_write(mss, 3, 0xf0); /* Disable SB IRQ */
-opti_write(mss, 4, 0xf0);
-opti_write(mss, 5, 0x00);
-opti_write(mss, 6, 0x02); /* MPU stuff */
-break;
-
-case MD_OPTI930:
-opti_write(mss, 1, 0x00 | basebits);
-opti_write(mss, 3, 0x00); /* Disable SB IRQ/DMA */
-opti_write(mss, 4, 0x52); /* Empty FIFO */
-opti_write(mss, 5, 0x3c); /* Mode 2 */
-opti_write(mss, 6, 0x02); /* Enable MSS */
-break;
-}
-
-if (mss->bd_flags & BD_F_924PNP) {
-u_int32_t irq = isa_get_irq(dev);
-u_int32_t drq = isa_get_drq(dev);
-bus_set_resource(dev, SYS_RES_IRQ, 0, irq, 1);
-bus_set_resource(dev, SYS_RES_DRQ, mss->drq1_rid, drq, 1);
-if (flags & DV_F_DUAL_DMA) {
-bus_set_resource(dev, SYS_RES_DRQ, 1,
-flags & DV_F_DRQ_MASK, 1);
-mss->drq2_rid = 1;
-}
-}
+ if (!mss->conf_base) {
+ bus_set_resource(dev, SYS_RES_IOPORT, mss->conf_rid,
+ mss->optibase, 0x9);
+
+ mss->conf_base = bus_alloc_resource(dev, SYS_RES_IOPORT,
+ &mss->conf_rid, mss->optibase, mss->optibase+0x9,
+ 0x9, RF_ACTIVE);
+ }
+
+ if (!mss->conf_base)
+ return ENXIO;
+
+ if (!mss->io_base)
+ mss->io_base = bus_alloc_resource(dev, SYS_RES_IOPORT,
+ &mss->io_rid, 0, ~0, 8, RF_ACTIVE);
+
+ if (!mss->io_base) /* No hint specified, use 0x530 */
+ mss->io_base = bus_alloc_resource(dev, SYS_RES_IOPORT,
+ &mss->io_rid, 0x530, 0x537, 8, RF_ACTIVE);
+
+ if (!mss->io_base)
+ return ENXIO;
+
+ switch (rman_get_start(mss->io_base)) {
+ case 0x530:
+ basebits = 0x0;
+ break;
+ case 0xe80:
+ basebits = 0x10;
+ break;
+ case 0xf40:
+ basebits = 0x20;
+ break;
+ case 0x604:
+ basebits = 0x30;
+ break;
+ default:
+ printf("opti_init: invalid MSS base address!\n");
+ return ENXIO;
+ }
+
+
+ switch (mss->bd_id) {
+ case MD_OPTI924:
+ opti_write(mss, 1, 0x80 | basebits); /* MSS mode */
+ opti_write(mss, 2, 0x00); /* Disable CD */
+ opti_write(mss, 3, 0xf0); /* Disable SB IRQ */
+ opti_write(mss, 4, 0xf0);
+ opti_write(mss, 5, 0x00);
+ opti_write(mss, 6, 0x02); /* MPU stuff */
+ break;
+
+ case MD_OPTI930:
+ opti_write(mss, 1, 0x00 | basebits);
+ opti_write(mss, 3, 0x00); /* Disable SB IRQ/DMA */
+ opti_write(mss, 4, 0x52); /* Empty FIFO */
+ opti_write(mss, 5, 0x3c); /* Mode 2 */
+ opti_write(mss, 6, 0x02); /* Enable MSS */
+ break;
+ }
+
+ if (mss->bd_flags & BD_F_924PNP) {
+ u_int32_t irq = isa_get_irq(dev);
+ u_int32_t drq = isa_get_drq(dev);
+ bus_set_resource(dev, SYS_RES_IRQ, 0, irq, 1);
+ bus_set_resource(dev, SYS_RES_DRQ, mss->drq1_rid, drq, 1);
+ if (flags & DV_F_DUAL_DMA) {
+ bus_set_resource(dev, SYS_RES_DRQ, 1,
+ flags & DV_F_DRQ_MASK, 1);
+ mss->drq2_rid = 1;
+ }
+ }
-/* OPTixxx has I/DRQ registers */
+ /* OPTixxx has I/DRQ registers */
-device_set_flags(dev, device_get_flags(dev) | DV_F_TRUE_MSS);
+ device_set_flags(dev, device_get_flags(dev) | DV_F_TRUE_MSS);
-return 0;
+ return 0;
}
static void
opti_write(struct mss_info *mss, u_char reg, u_char val)
{
-port_wr(mss->conf_base, mss->passwdreg, mss->password);
+ port_wr(mss->conf_base, mss->passwdreg, mss->password);
-switch(mss->bd_id) {
-case MD_OPTI924:
-if (reg > 7) { /* Indirect register */
-port_wr(mss->conf_base, mss->passwdreg, reg);
-port_wr(mss->conf_base, mss->passwdreg,
-mss->password);
-port_wr(mss->conf_base, 9, val);
-return;
-}
-port_wr(mss->conf_base, reg, val);
-break;
-
-case MD_OPTI930:
-port_wr(mss->indir, 0, reg);
-port_wr(mss->conf_base, mss->passwdreg, mss->password);
-port_wr(mss->indir, 1, val);
-break;
-}
+ switch(mss->bd_id) {
+ case MD_OPTI924:
+ if (reg > 7) { /* Indirect register */
+ port_wr(mss->conf_base, mss->passwdreg, reg);
+ port_wr(mss->conf_base, mss->passwdreg,
+ mss->password);
+ port_wr(mss->conf_base, 9, val);
+ return;
+ }
+ port_wr(mss->conf_base, reg, val);
+ break;
+
+ case MD_OPTI930:
+ port_wr(mss->indir, 0, reg);
+ port_wr(mss->conf_base, mss->passwdreg, mss->password);
+ port_wr(mss->indir, 1, val);
+ break;
+ }
}
#ifndef PC98
u_char
opti_read(struct mss_info *mss, u_char reg)
{
-port_wr(mss->conf_base, mss->passwdreg, mss->password);
+ port_wr(mss->conf_base, mss->passwdreg, mss->password);
-switch(mss->bd_id) {
-case MD_OPTI924:
-if (reg > 7) { /* Indirect register */
-port_wr(mss->conf_base, mss->passwdreg, reg);
-port_wr(mss->conf_base, mss->passwdreg, mss->password);
-return(port_rd(mss->conf_base, 9));
-}
-return(port_rd(mss->conf_base, reg));
-break;
-
-case MD_OPTI930:
-port_wr(mss->indir, 0, reg);
-port_wr(mss->conf_base, mss->passwdreg, mss->password);
-return port_rd(mss->indir, 1);
-break;
-}
-return -1;
+ switch(mss->bd_id) {
+ case MD_OPTI924:
+ if (reg > 7) { /* Indirect register */
+ port_wr(mss->conf_base, mss->passwdreg, reg);
+ port_wr(mss->conf_base, mss->passwdreg, mss->password);
+ return(port_rd(mss->conf_base, 9));
+ }
+ return(port_rd(mss->conf_base, reg));
+ break;
+
+ case MD_OPTI930:
+ port_wr(mss->indir, 0, reg);
+ port_wr(mss->conf_base, mss->passwdreg, mss->password);
+ return port_rd(mss->indir, 1);
+ break;
+ }
+ return -1;
}
#endif
static device_method_t pnpmss_methods[] = {
-/* Device interface */
-DEVMETHOD(device_probe, pnpmss_probe),
-DEVMETHOD(device_attach, pnpmss_attach),
-DEVMETHOD(device_detach, mss_detach),
-DEVMETHOD(device_suspend, mss_suspend),
-DEVMETHOD(device_resume, mss_resume),
+ /* Device interface */
+ DEVMETHOD(device_probe, pnpmss_probe),
+ DEVMETHOD(device_attach, pnpmss_attach),
+ DEVMETHOD(device_detach, mss_detach),
+ DEVMETHOD(device_suspend, mss_suspend),
+ DEVMETHOD(device_resume, mss_resume),
-{ 0, 0 }
+ { 0, 0 }
};
static driver_t pnpmss_driver = {
-"pcm",
-pnpmss_methods,
-PCM_SOFTC_SIZE,
+ "pcm",
+ pnpmss_methods,
+ PCM_SOFTC_SIZE,
};
DRIVER_MODULE(snd_pnpmss, isa, pnpmss_driver, pcm_devclass, 0, 0);
@@ -2230,81 +2230,81 @@
static int
guspcm_probe(device_t dev)
{
-struct sndcard_func *func;
+ struct sndcard_func *func;
-func = device_get_ivars(dev);
-if (func == NULL || func->func != SCF_PCM)
-return ENXIO;
+ func = device_get_ivars(dev);
+ if (func == NULL || func->func != SCF_PCM)
+ return ENXIO;
-device_set_desc(dev, "GUS CS4231");
-return 0;
+ device_set_desc(dev, "GUS CS4231");
+ return 0;
}
static int
guspcm_attach(device_t dev)
{
-device_t parent = device_get_parent(dev);
-struct mss_info *mss;
-int base, flags;
-unsigned char ctl;
-
-mss = (struct mss_info *)malloc(sizeof *mss, M_DEVBUF, M_NOWAIT | M_ZERO);
-if (mss == NULL)
-return ENOMEM;
-
-mss->bd_flags = BD_F_MSS_OFFSET;
-mss->io_rid = 2;
-mss->conf_rid = 1;
-mss->irq_rid = 0;
-mss->drq1_rid = 1;
-mss->drq2_rid = -1;
-
-if (isa_get_logicalid(parent) == 0)
-mss->bd_id = MD_GUSMAX;
-else {
-mss->bd_id = MD_GUSPNP;
-mss->drq2_rid = 0;
-goto skip_setup;
-}
-
-flags = device_get_flags(parent);
-if (flags & DV_F_DUAL_DMA)
-mss->drq2_rid = 0;
-
-mss->conf_base = bus_alloc_resource(dev, SYS_RES_IOPORT, &mss->conf_rid,
-0, ~0, 8, RF_ACTIVE);
-
-if (mss->conf_base == NULL) {
-mss_release_resources(mss, dev);
-return ENXIO;
-}
-
-base = isa_get_port(parent);
-
-ctl = 0x40; /* CS4231 enable */
-if (isa_get_drq(dev) > 3)
-ctl |= 0x10; /* 16-bit dma channel 1 */
-if ((flags & DV_F_DUAL_DMA) != 0 && (flags & DV_F_DRQ_MASK) > 3)
-ctl |= 0x20; /* 16-bit dma channel 2 */
-ctl |= (base >> 4) & 0x0f; /* 2X0 -> 3XC */
-port_wr(mss->conf_base, 6, ctl);
+ device_t parent = device_get_parent(dev);
+ struct mss_info *mss;
+ int base, flags;
+ unsigned char ctl;
+
+ mss = (struct mss_info *)malloc(sizeof *mss, M_DEVBUF, M_NOWAIT | M_ZERO);
+ if (mss == NULL)
+ return ENOMEM;
+
+ mss->bd_flags = BD_F_MSS_OFFSET;
+ mss->io_rid = 2;
+ mss->conf_rid = 1;
+ mss->irq_rid = 0;
+ mss->drq1_rid = 1;
+ mss->drq2_rid = -1;
+
+ if (isa_get_logicalid(parent) == 0)
+ mss->bd_id = MD_GUSMAX;
+ else {
+ mss->bd_id = MD_GUSPNP;
+ mss->drq2_rid = 0;
+ goto skip_setup;
+ }
+
+ flags = device_get_flags(parent);
+ if (flags & DV_F_DUAL_DMA)
+ mss->drq2_rid = 0;
+
+ mss->conf_base = bus_alloc_resource(dev, SYS_RES_IOPORT, &mss->conf_rid,
+ 0, ~0, 8, RF_ACTIVE);
+
+ if (mss->conf_base == NULL) {
+ mss_release_resources(mss, dev);
+ return ENXIO;
+ }
+
+ base = isa_get_port(parent);
+
+ ctl = 0x40; /* CS4231 enable */
+ if (isa_get_drq(dev) > 3)
+ ctl |= 0x10; /* 16-bit dma channel 1 */
+ if ((flags & DV_F_DUAL_DMA) != 0 && (flags & DV_F_DRQ_MASK) > 3)
+ ctl |= 0x20; /* 16-bit dma channel 2 */
+ ctl |= (base >> 4) & 0x0f; /* 2X0 -> 3XC */
+ port_wr(mss->conf_base, 6, ctl);
skip_setup:
-return mss_doattach(dev, mss);
+ return mss_doattach(dev, mss);
}
static device_method_t guspcm_methods[] = {
-DEVMETHOD(device_probe, guspcm_probe),
-DEVMETHOD(device_attach, guspcm_attach),
-DEVMETHOD(device_detach, mss_detach),
+ DEVMETHOD(device_probe, guspcm_probe),
+ DEVMETHOD(device_attach, guspcm_attach),
+ DEVMETHOD(device_detach, mss_detach),
-{ 0, 0 }
+ { 0, 0 }
};
static driver_t guspcm_driver = {
-"pcm",
-guspcm_methods,
-PCM_SOFTC_SIZE,
+ "pcm",
+ guspcm_methods,
+ PCM_SOFTC_SIZE,
};
DRIVER_MODULE(snd_guspcm, gusc, guspcm_driver, pcm_devclass, 0, 0);
Index: driver.c
===================================================================
RCS file: /home/cvs/src/sys/dev/sound/driver.c,v
retrieving revision 1.2
retrieving revision 1.3
diff -L sys/dev/sound/driver.c -L sys/dev/sound/driver.c -u -r1.2 -r1.3
--- sys/dev/sound/driver.c
+++ sys/dev/sound/driver.c
@@ -1,31 +1,30 @@
/*-
-* Copyright (c) 2000 Cameron Grant <cg at freebsd.org>
-* All rights reserved.
-*
-* Redistribution and use in source and binary forms, with or without
-* modification, are permitted provided that the following conditions
-* are met:
-* 1. Redistributions of source code must retain the above copyright
-* notice, this list of conditions and the following disclaimer.
-* 2. Redistributions in binary form must reproduce the above copyright
-* notice, this list of conditions and the following disclaimer in the
-* documentation and/or other materials provided with the distribution.
-*
-* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
-* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
-* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
-* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
-* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHERIN CONTRACT, STRICT
-* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
-* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THEPOSSIBILITY OF
-* SUCH DAMAGE.
-*
-* $MidnightBSD$
-* $FreeBSD: src/sys/dev/sound/driver.c,v 1.13.2.2 2006/01/24 18:56:11 joel Exp $
-*/
+ * Copyright (c) 2000 Cameron Grant <cg at freebsd.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD: src/sys/dev/sound/driver.c,v 1.21 2007/01/31 08:53:45 joel Exp $
+ */
#include <dev/sound/pcm/sound.h>
@@ -33,22 +32,22 @@
snd_modevent(module_t mod, int type, void *data)
{
-switch (type) {
-case MOD_LOAD:
-break;
-case MOD_UNLOAD:
-break;
-default:
-return (EOPNOTSUPP);
-break;
-}
-return 0;
+ switch (type) {
+ case MOD_LOAD:
+ break;
+ case MOD_UNLOAD:
+ break;
+ default:
+ return (EOPNOTSUPP);
+ break;
+ }
+ return 0;
}
static moduledata_t snd_mod = {
-"snd_driver",
-snd_modevent,
-NULL
+ "snd_driver",
+ snd_modevent,
+ NULL
};
DECLARE_MODULE(snd_driver, snd_mod, SI_SUB_DRIVERS, SI_ORDER_MIDDLE);
MODULE_VERSION(snd_driver, 1);
@@ -62,9 +61,10 @@
MODULE_DEPEND(snd_driver, snd_csa, 1, 1, 1);
MODULE_DEPEND(snd_driver, snd_csapcm, 1, 1, 1);
MODULE_DEPEND(snd_driver, snd_ds1, 1, 1, 1);
-MODULE_DEPEND(snd_driver, snd_emu10k1, 1, 1, 1);
+MODULE_DEPEND(snd_driver, snd_emu10kx, 1, 1, 1);
+MODULE_DEPEND(snd_driver, snd_envy24, 1, 1, 1);
+MODULE_DEPEND(snd_driver, snd_envy24ht, 1, 1, 1);
MODULE_DEPEND(snd_driver, snd_es137x, 1, 1, 1);
-MODULE_DEPEND(snd_driver, snd_es1888, 1, 1, 1);
MODULE_DEPEND(snd_driver, snd_ess, 1, 1, 1);
MODULE_DEPEND(snd_driver, snd_fm801, 1, 1, 1);
MODULE_DEPEND(snd_driver, snd_gusc, 1, 1, 1);
@@ -78,6 +78,7 @@
MODULE_DEPEND(snd_driver, snd_sb8, 1, 1, 1);
MODULE_DEPEND(snd_driver, snd_sbc, 1, 1, 1);
MODULE_DEPEND(snd_driver, snd_solo, 1, 1, 1);
+MODULE_DEPEND(snd_driver, snd_spicds, 1, 1, 1);
MODULE_DEPEND(snd_driver, snd_t4dwave, 1, 1, 1);
MODULE_DEPEND(snd_driver, snd_via8233, 1, 1, 1);
MODULE_DEPEND(snd_driver, snd_via82c686, 1, 1, 1);
Index: chip.h
===================================================================
RCS file: /home/cvs/src/sys/dev/sound/chip.h,v
retrieving revision 1.2
retrieving revision 1.3
diff -L sys/dev/sound/chip.h -L sys/dev/sound/chip.h -u -r1.2 -r1.3
--- sys/dev/sound/chip.h
+++ sys/dev/sound/chip.h
@@ -1,48 +1,47 @@
/*-
-* Copyright (c) 1999 Seigo Tanimura
-* All rights reserved.
-*
-* Redistribution and use in source and binary forms, with or without
-* modification, are permitted provided that the following conditions
-* are met:
-* 1. Redistributions of source code must retain the above copyright
-* notice, this list of conditions and the following disclaimer.
-* 2. Redistributions in binary form must reproduce the above copyright
-* notice, this list of conditions and the following disclaimer in the
-* documentation and/or other materials provided with the distribution.
-*
-* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
-* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
-* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
-* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
-* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
-* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
-* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
-* SUCH DAMAGE.
-*
-* $MidnightBSD$
-* $FreeBSD: src/sys/dev/sound/chip.h,v 1.2 2000/01/03 02:51:14 tanimura Exp $
-*/
+ * Copyright (c) 1999 Seigo Tanimura
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD: src/sys/dev/sound/chip.h,v 1.2 2000/01/03 02:51:14 tanimura Exp $
+ */
/*
-* These are the function codes assigned to the children of
-* sound cards.
-*/
+ * These are the function codes assigned to the children of
+ * sound cards.
+ */
enum {
-SCF_PCM,
-SCF_MIDI,
-SCF_SYNTH,
+ SCF_PCM,
+ SCF_MIDI,
+ SCF_SYNTH,
};
/*
-* This is the device information struct, used by
-* a bridge device to pass the device function code
-* to the children.
-*/
+ * This is the device information struct, used by
+ * a bridge device to pass the device function code
+ * to the children.
+ */
struct sndcard_func {
-int func; /* The function code. */
-void *varinfo; /* Bridge-specific information. */
+ int func; /* The function code. */
+ void *varinfo; /* Bridge-specific information. */
};
Index: mixer.h
===================================================================
RCS file: /home/cvs/src/sys/dev/sound/pcm/mixer.h,v
retrieving revision 1.2
retrieving revision 1.3
diff -L sys/dev/sound/pcm/mixer.h -L sys/dev/sound/pcm/mixer.h -u -r1.2 -r1.3
--- sys/dev/sound/pcm/mixer.h
+++ sys/dev/sound/pcm/mixer.h
@@ -1,41 +1,52 @@
/*-
-* Copyright (c) 1999 Cameron Grant <cg at freebsd.org>
-* All rights reserved.
-*
-* Redistribution and use in source and binary forms, with or without
-* modification, are permitted provided that the following conditions
-* are met:
-* 1. Redistributions of source code must retain the above copyright
-* notice, this list of conditions and the following disclaimer.
-* 2. Redistributions in binary form must reproduce the above copyright
-* notice, this list of conditions and the following disclaimer in the
-* documentation and/or other materials provided with the distribution.
-*
-* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
-* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
-* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
-* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
-* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
-* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
-* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
-* SUCH DAMAGE.
-*
-* $MidnightBSD$
-* $FreeBSD: src/sys/dev/sound/pcm/mixer.h,v 1.14 2005/01/06 01:43:21 imp Exp $
-*/
+ * Copyright (c) 1999 Cameron Grant <cg at freebsd.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD: src/sys/dev/sound/pcm/mixer.h,v 1.19 2007/06/16 03:37:28 ariff Exp $
+ */
+struct snd_mixer *mixer_create(device_t dev, kobj_class_t cls, void *devinfo,
+ const char *desc);
+int mixer_delete(struct snd_mixer *m);
int mixer_init(device_t dev, kobj_class_t cls, void *devinfo);
int mixer_uninit(device_t dev);
int mixer_reinit(device_t dev);
-int mixer_ioctl(struct cdev *i_dev, u_long cmd, caddr_t arg, int mode, struct thread *td);
+int mixer_ioctl_cmd(struct cdev *i_dev, u_long cmd, caddr_t arg, int mode, struct thread *td, int from);
+int mixer_oss_mixerinfo(struct cdev *i_dev, oss_mixerinfo *mi);
int mixer_hwvol_init(device_t dev);
void mixer_hwvol_mute(device_t dev);
void mixer_hwvol_step(device_t dev, int left_step, int right_step);
+int mixer_busy(struct snd_mixer *m);
+
+int mix_set(struct snd_mixer *m, u_int dev, u_int left, u_int right);
+int mix_get(struct snd_mixer *m, u_int dev);
+int mix_setrecsrc(struct snd_mixer *m, u_int32_t src);
+u_int32_t mix_getrecsrc(struct snd_mixer *m);
+int mix_get_type(struct snd_mixer *m);
+
void mix_setdevs(struct snd_mixer *m, u_int32_t v);
void mix_setrecdevs(struct snd_mixer *m, u_int32_t v);
u_int32_t mix_getdevs(struct snd_mixer *m);
@@ -46,10 +57,19 @@
u_int32_t mix_getchild(struct snd_mixer *m, u_int32_t dev);
void *mix_getdevinfo(struct snd_mixer *m);
+extern int mixer_count;
+
+#define MIXER_CMD_DIRECT 0 /* send command within driver */
+#define MIXER_CMD_CDEV 1 /* send command from cdev/ioctl */
+
+#define MIXER_TYPE_PRIMARY 0 /* mixer_init() */
+#define MIXER_TYPE_SECONDARY 1 /* mixer_create() */
+
/*
-* this is a kludge to allow hiding of the struct snd_mixer definition
-* 512 should be enough for all architectures
-*/
-#define MIXER_SIZE (512 + sizeof(struct kobj))
+ * this is a kludge to allow hiding of the struct snd_mixer definition
+ * 512 should be enough for all architectures
+ */
+#define MIXER_SIZE (512 + sizeof(struct kobj) + \
+ sizeof(oss_mixer_enuminfo))
-#define MIXER_DECLARE(name) DEFINE_CLASS(name, name ## _methods, MIXER_SIZE)
+#define MIXER_DECLARE(name) static DEFINE_CLASS(name, name ## _methods, MIXER_SIZE)
Index: feeder_if.m
===================================================================
RCS file: /home/cvs/src/sys/dev/sound/pcm/feeder_if.m,v
retrieving revision 1.2
retrieving revision 1.3
diff -L sys/dev/sound/pcm/feeder_if.m -L sys/dev/sound/pcm/feeder_if.m -u -r1.2 -r1.3
--- sys/dev/sound/pcm/feeder_if.m
+++ sys/dev/sound/pcm/feeder_if.m
@@ -25,7 +25,6 @@
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
# SUCH DAMAGE.
#
-# $MidnightBSD$
# $FreeBSD: src/sys/dev/sound/pcm/feeder_if.m,v 1.6 2005/01/06 01:43:21 imp Exp $
#
@@ -35,22 +34,26 @@
CODE {
- static int feeder_noinit(struct pcm_feeder* feeder)
+ static int
+ feeder_noinit(struct pcm_feeder* feeder)
{
return 0;
}
- static int feeder_nofree(struct pcm_feeder* feeder)
+ static int
+ feeder_nofree(struct pcm_feeder* feeder)
{
return 0;
}
- static int feeder_noset(struct pcm_feeder* feeder, int what, int value)
+ static int
+ feeder_noset(struct pcm_feeder* feeder, int what, int value)
{
return -1;
}
- static int feeder_noget(struct pcm_feeder* feeder, int what)
+ static int
+ feeder_noget(struct pcm_feeder* feeder, int what)
{
return -1;
}
@@ -58,28 +61,28 @@
};
METHOD int init {
-struct pcm_feeder* feeder;
+ struct pcm_feeder* feeder;
} DEFAULT feeder_noinit;
METHOD int free {
-struct pcm_feeder* feeder;
+ struct pcm_feeder* feeder;
} DEFAULT feeder_nofree;
METHOD int set {
-struct pcm_feeder* feeder;
-int what;
-int value;
+ struct pcm_feeder* feeder;
+ int what;
+ int value;
} DEFAULT feeder_noset;
METHOD int get {
-struct pcm_feeder* feeder;
-int what;
+ struct pcm_feeder* feeder;
+ int what;
} DEFAULT feeder_noget;
METHOD int feed {
-struct pcm_feeder* feeder;
-struct pcm_channel* c;
-u_int8_t* buffer;
-u_int32_t count;
-void* source;
+ struct pcm_feeder* feeder;
+ struct pcm_channel* c;
+ u_int8_t* buffer;
+ u_int32_t count;
+ void* source;
};
Index: feeder.h
===================================================================
RCS file: /home/cvs/src/sys/dev/sound/pcm/feeder.h,v
retrieving revision 1.2
retrieving revision 1.3
diff -L sys/dev/sound/pcm/feeder.h -L sys/dev/sound/pcm/feeder.h -u -r1.2 -r1.3
--- sys/dev/sound/pcm/feeder.h
+++ sys/dev/sound/pcm/feeder.h
@@ -1,60 +1,59 @@
/*-
-* Copyright (c) 1999 Cameron Grant <cg at freebsd.org>
-* All rights reserved.
-*
-* Redistribution and use in source and binary forms, with or without
-* modification, are permitted provided that the following conditions
-* are met:
-* 1. Redistributions of source code must retain the above copyright
-* notice, this list of conditions and the following disclaimer.
-* 2. Redistributions in binary form must reproduce the above copyright
-* notice, this list of conditions and the following disclaimer in the
-* documentation and/or other materials provided with the distribution.
-*
-* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
-* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
-* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
-* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
-* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
-* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
-* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
-* SUCH DAMAGE.
-*
-* $MidnightBSD$
-* $FreeBSD: src/sys/dev/sound/pcm/feeder.h,v 1.12.2.1 2006/01/29 02:27:28 ariff Exp $
-*/
+ * Copyright (c) 1999 Cameron Grant <cg at freebsd.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD: src/sys/dev/sound/pcm/feeder.h,v 1.15 2007/03/16 17:15:33 ariff Exp $
+ */
struct pcm_feederdesc {
-u_int32_t type;
-u_int32_t in, out;
-u_int32_t flags;
-int idx;
+ u_int32_t type;
+ u_int32_t in, out;
+ u_int32_t flags;
+ int idx;
};
struct feeder_class {
-KOBJ_CLASS_FIELDS;
-int align;
-struct pcm_feederdesc *desc;
-void *data;
+ KOBJ_CLASS_FIELDS;
+ int align;
+ struct pcm_feederdesc *desc;
+ void *data;
};
struct pcm_feeder {
-KOBJ_FIELDS;
-int align;
-struct pcm_feederdesc *desc, desc_static;
-void *data;
-struct feeder_class *class;
-struct pcm_feeder *source, *parent;
+ KOBJ_FIELDS;
+ int align;
+ struct pcm_feederdesc *desc, desc_static;
+ void *data;
+ struct feeder_class *class;
+ struct pcm_feeder *source, *parent;
};
void feeder_register(void *p);
struct feeder_class *feeder_getclass(struct pcm_feederdesc *desc);
-int chn_fmtscore(u_int32_t fmt);
+u_int32_t chn_fmtscore(u_int32_t fmt);
u_int32_t chn_fmtbestbit(u_int32_t fmt, u_int32_t *fmts);
u_int32_t chn_fmtbeststereo(u_int32_t fmt, u_int32_t *fmts);
u_int32_t chn_fmtbest(u_int32_t fmt, u_int32_t *fmts);
@@ -64,17 +63,50 @@
struct pcm_feeder *chn_findfeeder(struct pcm_channel *c, u_int32_t type);
void feeder_printchain(struct pcm_feeder *head);
-#define FEEDER_DECLARE(feeder, palign, pdata) static struct feeder_class feeder ## _class = { .name = #feeder, .methods = feeder ## _methods, .size = sizeof(struct pcm_feeder), .align = palign, .desc = feeder ## _desc, .data = pdata, }; SYSINIT(feeder, SI_SUB_DRIVERS, SI_ORDER_MIDDLE, feeder_register, &feeder ## _class);
-
-#define FEEDER_ROOT 1
-#define FEEDER_FMT 2
-#define FEEDER_MIXER 3
-#define FEEDER_RATE 4
-#define FEEDER_FILTER 5
-#define FEEDER_VOLUME 6
-#define FEEDER_LAST FEEDER_VOLUME
+#define FEEDER_DECLARE(feeder, palign, pdata) \
+static struct feeder_class feeder ## _class = { \
+ .name = #feeder, \
+ .methods = feeder ## _methods, \
+ .size = sizeof(struct pcm_feeder), \
+ .align = palign, \
+ .desc = feeder ## _desc, \
+ .data = pdata, \
+}; \
+SYSINIT(feeder, SI_SUB_DRIVERS, SI_ORDER_ANY, feeder_register, &feeder ## _class);
+
+#define FEEDER_ROOT 0
+#define FEEDER_FMT 1
+#define FEEDER_MIXER 2
+#define FEEDER_RATE 3
+#define FEEDER_FILTER 4
+#define FEEDER_VOLUME 5
+#define FEEDER_SWAPLR 6
+#define FEEDER_LAST 32
#define FEEDRATE_SRC 1
#define FEEDRATE_DST 2
+#define FEEDRATE_RATEMIN 1
+#define FEEDRATE_RATEMAX 2016000 /* 48000 * 42 */
+
+#define FEEDRATE_MIN 1
+#define FEEDRATE_MAX 0x7fffff /* sign 24bit ~ 8ghz ! */
+#define FEEDRATE_ROUNDHZ 25
+#define FEEDRATE_ROUNDHZ_MIN 0
+#define FEEDRATE_ROUNDHZ_MAX 500
+
+/*
+ * Default buffer size for feeder processing.
+ *
+ * Big = less sndbuf_feed(), more memory usage.
+ * Small = aggresive sndbuf_feed() (perhaps too much), less memory usage.
+ */
+#define FEEDBUFSZ 16384
+#define FEEDBUFSZ_MIN 2048
+#define FEEDBUFSZ_MAX 131072
+
+extern int feeder_rate_min;
+extern int feeder_rate_max;
+extern int feeder_rate_round;
+extern int feeder_buffersize;
Index: channel_if.m
===================================================================
RCS file: /home/cvs/src/sys/dev/sound/pcm/channel_if.m,v
retrieving revision 1.2
retrieving revision 1.3
diff -L sys/dev/sound/pcm/channel_if.m -L sys/dev/sound/pcm/channel_if.m -u -r1.2 -r1.3
--- sys/dev/sound/pcm/channel_if.m
+++ sys/dev/sound/pcm/channel_if.m
@@ -25,8 +25,7 @@
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
# SUCH DAMAGE.
#
-# $MidnightBSD$
-# $FreeBSD: src/sys/dev/sound/pcm/channel_if.m,v 1.5 2005/01/06 01:43:20 imp Exp $
+# $FreeBSD: src/sys/dev/sound/pcm/channel_if.m,v 1.7 2007/03/16 17:16:24 ariff Exp $
#
#include <dev/sound/pcm/sound.h>
@@ -35,32 +34,57 @@
CODE {
- static int channel_nosetdir(kobj_t obj, void *data, int dir)
+ static int
+ channel_nosetdir(kobj_t obj, void *data, int dir)
{
return 0;
}
- static int channel_noreset(kobj_t obj, void *data)
+ static int
+ channel_noreset(kobj_t obj, void *data)
{
return 0;
}
- static int channel_noresetdone(kobj_t obj, void *data)
+ static int
+ channel_noresetdone(kobj_t obj, void *data)
{
return 0;
}
- static int channel_nofree(kobj_t obj, void *data)
+ static int
+ channel_nofree(kobj_t obj, void *data)
{
return 1;
}
- static u_int32_t channel_nogetptr(kobj_t obj, void *data)
+ static u_int32_t
+ channel_nogetptr(kobj_t obj, void *data)
{
return 0;
}
- static int channel_nonotify(kobj_t obj, void *data, u_int32_t changed)
+ static int
+ channel_nonotify(kobj_t obj, void *data, u_int32_t changed)
+ {
+ return 0;
+ }
+
+ static int
+ channel_nogetpeaks(kobj_t obj, void *data, int *lpeak, int *rpeak)
+ {
+ return -1;
+ }
+
+ static int
+ channel_nogetrates(kobj_t obj, void *data, int **rates)
+ {
+ *rates = NULL;
+ return 0;
+ }
+
+ static int
+ channel_nosetfragments(kobj_t obj, void *data, u_int32_t blocksize, u_int32_t blockcount)
{
return 0;
}
@@ -68,70 +92,128 @@
};
METHOD void* init {
-kobj_t obj;
-void *devinfo;
-struct snd_dbuf *b;
-struct pcm_channel *c;
-int dir;
+ kobj_t obj;
+ void *devinfo;
+ struct snd_dbuf *b;
+ struct pcm_channel *c;
+ int dir;
};
METHOD int free {
-kobj_t obj;
-void *data;
+ kobj_t obj;
+ void *data;
} DEFAULT channel_nofree;
METHOD int reset {
-kobj_t obj;
-void *data;
+ kobj_t obj;
+ void *data;
} DEFAULT channel_noreset;
METHOD int resetdone {
-kobj_t obj;
-void *data;
+ kobj_t obj;
+ void *data;
} DEFAULT channel_noresetdone;
METHOD int setdir {
-kobj_t obj;
-void *data;
-int dir;
+ kobj_t obj;
+ void *data;
+ int dir;
} DEFAULT channel_nosetdir;
METHOD u_int32_t setformat {
-kobj_t obj;
-void *data;
-u_int32_t format;
+ kobj_t obj;
+ void *data;
+ u_int32_t format;
};
METHOD u_int32_t setspeed {
-kobj_t obj;
-void *data;
-u_int32_t speed;
+ kobj_t obj;
+ void *data;
+ u_int32_t speed;
};
METHOD u_int32_t setblocksize {
-kobj_t obj;
-void *data;
-u_int32_t blocksize;
+ kobj_t obj;
+ void *data;
+ u_int32_t blocksize;
};
+METHOD int setfragments {
+ kobj_t obj;
+ void *data;
+ u_int32_t blocksize;
+ u_int32_t blockcount;
+} DEFAULT channel_nosetfragments;
+
METHOD int trigger {
-kobj_t obj;
-void *data;
-int go;
+ kobj_t obj;
+ void *data;
+ int go;
};
METHOD u_int32_t getptr {
-kobj_t obj;
-void *data;
+ kobj_t obj;
+ void *data;
} DEFAULT channel_nogetptr;
METHOD struct pcmchan_caps* getcaps {
-kobj_t obj;
-void *data;
+ kobj_t obj;
+ void *data;
};
METHOD int notify {
-kobj_t obj;
-void *data;
-u_int32_t changed;
+ kobj_t obj;
+ void *data;
+ u_int32_t changed;
} DEFAULT channel_nonotify;
+
+/**
+ * @brief Retrieve channel peak values
+ *
+ * This function is intended to obtain peak volume values for samples
+ * played/recorded on a channel. Values are on a linear scale from 0 to
+ * 32767. If the channel is monaural, a single value should be recorded
+ * in @c lpeak.
+ *
+ * If hardware support isn't available, the SNDCTL_DSP_GET[IO]PEAKS
+ * operation should return EINVAL. However, we may opt to provide
+ * software support that the user may toggle via sysctl/mixext.
+ *
+ * @param obj standard kobj object (usually @c channel->methods)
+ * @param data driver-specific data (usually @c channel->devinfo)
+ * @param lpeak pointer to store left peak level
+ * @param rpeak pointer to store right peak level
+ *
+ * @retval -1 Error; usually operation isn't supported.
+ * @retval 0 success
+ */
+METHOD int getpeaks {
+ kobj_t obj;
+ void *data;
+ int *lpeak;
+ int *rpeak;
+} DEFAULT channel_nogetpeaks;
+
+/**
+ * @brief Retrieve discrete supported sample rates
+ *
+ * Some cards operate at fixed rates, and this call is intended to retrieve
+ * those rates primarily for when in-kernel rate adjustment is undesirable
+ * (e.g., application wants direct DMA access after setting a channel to run
+ * "uncooked").
+ *
+ * The parameter @c rates is a double pointer which will be reset to
+ * point to an array of supported sample rates. The number of elements
+ * in the array is returned to the caller.
+ *
+ * @param obj standard kobj object (usually @c channel->methods)
+ * @param data driver-specific data (usually @c channel->devinfo)
+ * @param rates rate array pointer
+ *
+ * @return Number of rates in the array
+ */
+METHOD int getrates {
+ kobj_t obj;
+ void *data;
+ int **rates;
+} DEFAULT channel_nogetrates;
Index: fake.c
===================================================================
RCS file: /home/cvs/src/sys/dev/sound/pcm/fake.c,v
retrieving revision 1.2
retrieving revision 1.3
diff -L sys/dev/sound/pcm/fake.c -L sys/dev/sound/pcm/fake.c -u -r1.2 -r1.3
--- sys/dev/sound/pcm/fake.c
+++ sys/dev/sound/pcm/fake.c
@@ -1,67 +1,67 @@
/*-
-* Copyright (c) 1999 Cameron Grant <cg at freebsd.org>
-* All rights reserved.
-*
-* Redistribution and use in source and binary forms, with or without
-* modification, are permitted provided that the following conditions
-* are met:
-* 1. Redistributions of source code must retain the above copyright
-* notice, this list of conditions and the following disclaimer.
-* 2. Redistributions in binary form must reproduce the above copyright
-* notice, this list of conditions and the following disclaimer in the
-* documentation and/or other materials provided with the distribution.
-*
-* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
-* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
-* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
-* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
-* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
-* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
-* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
-* SUCH DAMAGE.
-*/
+ * Copyright (c) 1999 Cameron Grant <cg at freebsd.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
#include <dev/sound/pcm/sound.h>
-SND_DECLARE_FILE("$MidnightBSD$");
+SND_DECLARE_FILE("$FreeBSD: src/sys/dev/sound/pcm/fake.c,v 1.18 2007/03/15 18:19:01 ariff Exp $");
static u_int32_t fk_fmt[] = {
-AFMT_MU_LAW,
-AFMT_STEREO | AFMT_MU_LAW,
-AFMT_A_LAW,
-AFMT_STEREO | AFMT_A_LAW,
-AFMT_U8,
-AFMT_STEREO | AFMT_U8,
-AFMT_S8,
-AFMT_STEREO | AFMT_S8,
-AFMT_S16_LE,
-AFMT_STEREO | AFMT_S16_LE,
-AFMT_U16_LE,
-AFMT_STEREO | AFMT_U16_LE,
-AFMT_S16_BE,
-AFMT_STEREO | AFMT_S16_BE,
-AFMT_U16_BE,
-AFMT_STEREO | AFMT_U16_BE,
-AFMT_S24_LE,
-AFMT_STEREO | AFMT_S24_LE,
-AFMT_U24_LE,
-AFMT_STEREO | AFMT_U24_LE,
-AFMT_S24_BE,
-AFMT_STEREO | AFMT_S24_BE,
-AFMT_U24_BE,
-AFMT_STEREO | AFMT_U24_BE,
-AFMT_S32_LE,
-AFMT_STEREO | AFMT_S32_LE,
-AFMT_U32_LE,
-AFMT_STEREO | AFMT_U32_LE,
-AFMT_S32_BE,
-AFMT_STEREO | AFMT_S32_BE,
-AFMT_U32_BE,
-AFMT_STEREO | AFMT_U32_BE,
-0
+ AFMT_MU_LAW,
+ AFMT_STEREO | AFMT_MU_LAW,
+ AFMT_A_LAW,
+ AFMT_STEREO | AFMT_A_LAW,
+ AFMT_U8,
+ AFMT_STEREO | AFMT_U8,
+ AFMT_S8,
+ AFMT_STEREO | AFMT_S8,
+ AFMT_S16_LE,
+ AFMT_STEREO | AFMT_S16_LE,
+ AFMT_U16_LE,
+ AFMT_STEREO | AFMT_U16_LE,
+ AFMT_S16_BE,
+ AFMT_STEREO | AFMT_S16_BE,
+ AFMT_U16_BE,
+ AFMT_STEREO | AFMT_U16_BE,
+ AFMT_S24_LE,
+ AFMT_STEREO | AFMT_S24_LE,
+ AFMT_U24_LE,
+ AFMT_STEREO | AFMT_U24_LE,
+ AFMT_S24_BE,
+ AFMT_STEREO | AFMT_S24_BE,
+ AFMT_U24_BE,
+ AFMT_STEREO | AFMT_U24_BE,
+ AFMT_S32_LE,
+ AFMT_STEREO | AFMT_S32_LE,
+ AFMT_U32_LE,
+ AFMT_STEREO | AFMT_U32_LE,
+ AFMT_S32_BE,
+ AFMT_STEREO | AFMT_S32_BE,
+ AFMT_U32_BE,
+ AFMT_STEREO | AFMT_U32_BE,
+ 0
};
static struct pcmchan_caps fk_caps = {0, 1000000, fk_fmt, 0};
@@ -72,92 +72,93 @@
static void *
fkchan_init(kobj_t obj, void *devinfo, struct snd_dbuf *b, struct pcm_channel *c, int dir)
{
-sndbuf_setup(b, fakebuf, FKBUFSZ);
-return (void *)0xbabef00d;
+ sndbuf_setup(b, fakebuf, FKBUFSZ);
+ return (void *)0xbabef00d;
}
static int
fkchan_free(kobj_t obj, void *data)
{
-return 0;
+ return 0;
}
static int
fkchan_setformat(kobj_t obj, void *data, u_int32_t format)
{
-return 0;
+ return 0;
}
static int
fkchan_setspeed(kobj_t obj, void *data, u_int32_t speed)
{
-return speed;
+ return speed;
}
static int
fkchan_setblocksize(kobj_t obj, void *data, u_int32_t blocksize)
{
-return blocksize;
+ return blocksize;
}
static int
fkchan_trigger(kobj_t obj, void *data, int go)
{
-return 0;
+ return 0;
}
static int
fkchan_getptr(kobj_t obj, void *data)
{
-return 0;
+ return 0;
}
static struct pcmchan_caps *
fkchan_getcaps(kobj_t obj, void *data)
{
-return &fk_caps;
+ return &fk_caps;
}
static kobj_method_t fkchan_methods[] = {
-KOBJMETHOD(channel_init, fkchan_init),
-KOBJMETHOD(channel_free, fkchan_free),
-KOBJMETHOD(channel_setformat, fkchan_setformat),
-KOBJMETHOD(channel_setspeed, fkchan_setspeed),
-KOBJMETHOD(channel_setblocksize, fkchan_setblocksize),
-KOBJMETHOD(channel_trigger, fkchan_trigger),
-KOBJMETHOD(channel_getptr, fkchan_getptr),
-KOBJMETHOD(channel_getcaps, fkchan_getcaps),
-{ 0, 0 }
+ KOBJMETHOD(channel_init, fkchan_init),
+ KOBJMETHOD(channel_free, fkchan_free),
+ KOBJMETHOD(channel_setformat, fkchan_setformat),
+ KOBJMETHOD(channel_setspeed, fkchan_setspeed),
+ KOBJMETHOD(channel_setblocksize, fkchan_setblocksize),
+ KOBJMETHOD(channel_trigger, fkchan_trigger),
+ KOBJMETHOD(channel_getptr, fkchan_getptr),
+ KOBJMETHOD(channel_getcaps, fkchan_getcaps),
+ { 0, 0 }
};
CHANNEL_DECLARE(fkchan);
struct pcm_channel *
fkchan_setup(device_t dev)
{
-struct snddev_info *d = device_get_softc(dev);
-struct pcm_channel *c;
+ struct snddev_info *d = device_get_softc(dev);
+ struct pcm_channel *c;
-c = malloc(sizeof(*c), M_DEVBUF, M_WAITOK);
-c->methods = kobj_create(&fkchan_class, M_DEVBUF, M_WAITOK);
-c->parentsnddev = d;
-/*
-* Fake channel is such a blessing in disguise. Using this,
-* we can keep track prefered virtual channel speed without
-* querying kernel hint repetitively (see vchan_create / vchan.c).
-*/
-c->speed = 0;
-snprintf(c->name, CHN_NAMELEN, "%s:fake", device_get_nameunit(dev));
+ c = malloc(sizeof(*c), M_DEVBUF, M_WAITOK | M_ZERO);
+ c->methods = kobj_create(&fkchan_class, M_DEVBUF, M_WAITOK);
+ c->parentsnddev = d;
+ /*
+ * Fake channel is such a blessing in disguise. Using this,
+ * we can keep track prefered virtual channel speed / format without
+ * querying kernel hint repetitively (see vchan_create / vchan.c).
+ */
+ c->speed = 0;
+ c->format = 0;
+ snprintf(c->name, CHN_NAMELEN, "%s:fake", device_get_nameunit(dev));
-return c;
+ return c;
}
int
fkchan_kill(struct pcm_channel *c)
{
-kobj_delete(c->methods, M_DEVBUF);
-c->methods = NULL;
-free(c, M_DEVBUF);
-return 0;
+ kobj_delete(c->methods, M_DEVBUF);
+ c->methods = NULL;
+ free(c, M_DEVBUF);
+ return 0;
}
Index: vchan.c
===================================================================
RCS file: /home/cvs/src/sys/dev/sound/pcm/vchan.c,v
retrieving revision 1.3
retrieving revision 1.4
diff -L sys/dev/sound/pcm/vchan.c -L sys/dev/sound/pcm/vchan.c -u -r1.3 -r1.4
--- sys/dev/sound/pcm/vchan.c
+++ sys/dev/sound/pcm/vchan.c
@@ -1,624 +1,1030 @@
/*-
-* Copyright (c) 2001 Cameron Grant <cg at freebsd.org>
-* All rights reserved.
-*
-* Redistribution and use in source and binary forms, with or without
-* modification, are permitted provided that the following conditions
-* are met:
-* 1. Redistributions of source code must retain the above copyright
-* notice, this list of conditions and the following disclaimer.
-* 2. Redistributions in binary form must reproduce the above copyright
-* notice, this list of conditions and the following disclaimer in the
-* documentation and/or other materials provided with the distribution.
-*
-* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
-* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
-* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
-* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
-* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
-* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
-* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
-* SUCH DAMAGE.
-*/
+ * Copyright (c) 2001 Cameron Grant <cg at FreeBSD.org>
+ * Copyright (c) 2006 Ariff Abdullah <ariff at FreeBSD.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/* Almost entirely rewritten to add multi-format/channels mixing support. */
#include <dev/sound/pcm/sound.h>
#include <dev/sound/pcm/vchan.h>
#include "feeder_if.h"
-SND_DECLARE_FILE("$MidnightBSD$");
+SND_DECLARE_FILE("$FreeBSD: src/sys/dev/sound/pcm/vchan.c,v 1.36 2007/06/16 03:37:28 ariff Exp $");
-/*
-* Default speed
-*/
-#define VCHAN_DEFAULT_SPEED 48000
+MALLOC_DEFINE(M_VCHANFEEDER, "vchanfeed", "pcm vchan feeder");
-extern int feeder_rate_ratemin;
-extern int feeder_rate_ratemax;
+typedef uint32_t (*feed_vchan_mixer)(uint8_t *, uint8_t *, uint32_t);
struct vchinfo {
-u_int32_t spd, fmt, blksz, bps, run;
-struct pcm_channel *channel, *parent;
-struct pcmchan_caps caps;
+ struct pcm_channel *channel;
+ struct pcmchan_caps caps;
+ uint32_t fmtlist[2];
+ int trigger;
+};
+
+/* support everything (mono / stereo), except a-law / mu-law */
+static struct afmtstr_table vchan_supported_fmts[] = {
+ { "u8", AFMT_U8 }, { "s8", AFMT_S8 },
+ { "s16le", AFMT_S16_LE }, { "s16be", AFMT_S16_BE },
+ { "u16le", AFMT_U16_LE }, { "u16be", AFMT_U16_BE },
+ { "s24le", AFMT_S24_LE }, { "s24be", AFMT_S24_BE },
+ { "u24le", AFMT_U24_LE }, { "u24be", AFMT_U24_BE },
+ { "s32le", AFMT_S32_LE }, { "s32be", AFMT_S32_BE },
+ { "u32le", AFMT_U32_LE }, { "u32be", AFMT_U32_BE },
+ { NULL, 0 },
+};
+
+/* alias table, shorter. */
+static const struct {
+ char *alias, *fmtstr;
+} vchan_fmtstralias[] = {
+ { "8", "u8" }, { "16", "s16le" },
+ { "24", "s24le" }, { "32", "s32le" },
+ { NULL, NULL },
+};
+
+#define vchan_valid_format(fmt) \
+ afmt2afmtstr(vchan_supported_fmts, fmt, NULL, 0, 0, \
+ AFMTSTR_STEREO_RETURN)
+#define vchan_valid_strformat(strfmt) \
+ afmtstr2afmt(vchan_supported_fmts, strfmt, AFMTSTR_STEREO_RETURN);
+
+/*
+ * Need specialized WRITE macros since 32bit might involved saturation
+ * if calculation is done within 32bit arithmetic.
+ */
+#define VCHAN_PCM_WRITE_S8_NE(b8, val) PCM_WRITE_S8(b8, val)
+#define VCHAN_PCM_WRITE_S16_LE(b8, val) PCM_WRITE_S16_LE(b8, val)
+#define VCHAN_PCM_WRITE_S24_LE(b8, val) PCM_WRITE_S24_LE(b8, val)
+#define VCHAN_PCM_WRITE_S32_LE(b8, val) _PCM_WRITE_S32_LE(b8, val)
+#define VCHAN_PCM_WRITE_S16_BE(b8, val) PCM_WRITE_S16_BE(b8, val)
+#define VCHAN_PCM_WRITE_S24_BE(b8, val) PCM_WRITE_S24_BE(b8, val)
+#define VCHAN_PCM_WRITE_S32_BE(b8, val) _PCM_WRITE_S32_BE(b8, val)
+#define VCHAN_PCM_WRITE_U8_NE(b8, val) PCM_WRITE_U8(b8, val)
+#define VCHAN_PCM_WRITE_U16_LE(b8, val) PCM_WRITE_U16_LE(b8, val)
+#define VCHAN_PCM_WRITE_U24_LE(b8, val) PCM_WRITE_U24_LE(b8, val)
+#define VCHAN_PCM_WRITE_U32_LE(b8, val) _PCM_WRITE_U32_LE(b8, val)
+#define VCHAN_PCM_WRITE_U16_BE(b8, val) PCM_WRITE_U16_BE(b8, val)
+#define VCHAN_PCM_WRITE_U24_BE(b8, val) PCM_WRITE_U24_BE(b8, val)
+#define VCHAN_PCM_WRITE_U32_BE(b8, val) _PCM_WRITE_U32_BE(b8, val)
+
+#define FEEDER_VCHAN_MIX(FMTBIT, VCHAN_INTCAST, SIGN, SIGNS, ENDIAN, ENDIANS) \
+static uint32_t \
+feed_vchan_mix_##SIGNS##FMTBIT##ENDIANS(uint8_t *to, uint8_t *tmp, \
+ uint32_t count) \
+{ \
+ int32_t x, y; \
+ VCHAN_INTCAST z; \
+ int i; \
+ \
+ i = count; \
+ tmp += i; \
+ to += i; \
+ \
+ do { \
+ tmp -= PCM_##FMTBIT##_BPS; \
+ to -= PCM_##FMTBIT##_BPS; \
+ i -= PCM_##FMTBIT##_BPS; \
+ x = PCM_READ_##SIGN##FMTBIT##_##ENDIAN(tmp); \
+ y = PCM_READ_##SIGN##FMTBIT##_##ENDIAN(to); \
+ z = (VCHAN_INTCAST)x + y; \
+ x = PCM_CLAMP_##SIGN##FMTBIT(z); \
+ VCHAN_PCM_WRITE_##SIGN##FMTBIT##_##ENDIAN(to, x); \
+ } while (i != 0); \
+ \
+ return (count); \
+}
+
+FEEDER_VCHAN_MIX(8, int32_t, S, s, NE, ne)
+FEEDER_VCHAN_MIX(16, int32_t, S, s, LE, le)
+FEEDER_VCHAN_MIX(24, int32_t, S, s, LE, le)
+FEEDER_VCHAN_MIX(32, intpcm_t, S, s, LE, le)
+FEEDER_VCHAN_MIX(16, int32_t, S, s, BE, be)
+FEEDER_VCHAN_MIX(24, int32_t, S, s, BE, be)
+FEEDER_VCHAN_MIX(32, intpcm_t, S, s, BE, be)
+FEEDER_VCHAN_MIX(8, int32_t, U, u, NE, ne)
+FEEDER_VCHAN_MIX(16, int32_t, U, u, LE, le)
+FEEDER_VCHAN_MIX(24, int32_t, U, u, LE, le)
+FEEDER_VCHAN_MIX(32, intpcm_t, U, u, LE, le)
+FEEDER_VCHAN_MIX(16, int32_t, U, u, BE, be)
+FEEDER_VCHAN_MIX(24, int32_t, U, u, BE, be)
+FEEDER_VCHAN_MIX(32, intpcm_t, U, u, BE, be)
+
+struct feed_vchan_info {
+ uint32_t format;
+ int bps;
+ feed_vchan_mixer mix;
};
-static u_int32_t vchan_fmt[] = {
-AFMT_STEREO | AFMT_S16_LE,
-0
+static struct feed_vchan_info feed_vchan_info_tbl[] = {
+ { AFMT_S8, PCM_8_BPS, feed_vchan_mix_s8ne },
+ { AFMT_S16_LE, PCM_16_BPS, feed_vchan_mix_s16le },
+ { AFMT_S24_LE, PCM_24_BPS, feed_vchan_mix_s24le },
+ { AFMT_S32_LE, PCM_32_BPS, feed_vchan_mix_s32le },
+ { AFMT_S16_BE, PCM_16_BPS, feed_vchan_mix_s16be },
+ { AFMT_S24_BE, PCM_24_BPS, feed_vchan_mix_s24be },
+ { AFMT_S32_BE, PCM_32_BPS, feed_vchan_mix_s32be },
+ { AFMT_U8, PCM_8_BPS, feed_vchan_mix_u8ne },
+ { AFMT_U16_LE, PCM_16_BPS, feed_vchan_mix_u16le },
+ { AFMT_U24_LE, PCM_24_BPS, feed_vchan_mix_u24le },
+ { AFMT_U32_LE, PCM_32_BPS, feed_vchan_mix_u32le },
+ { AFMT_U16_BE, PCM_16_BPS, feed_vchan_mix_u16be },
+ { AFMT_U24_BE, PCM_24_BPS, feed_vchan_mix_u24be },
+ { AFMT_U32_BE, PCM_32_BPS, feed_vchan_mix_u32be },
};
+#define FVCHAN_DATA(i, c) ((intptr_t)((((i) & 0x1f) << 4) | ((c) & 0xf)))
+#define FVCHAN_INFOIDX(m) (((m) >> 4) & 0x1f)
+#define FVCHAN_CHANNELS(m) ((m) & 0xf)
+
static int
-vchan_mix_s16(int16_t *to, int16_t *tmp, unsigned int count)
+feed_vchan_init(struct pcm_feeder *f)
{
-/*
-* to is the output buffer, tmp is the input buffer
-* count is the number of 16bit samples to mix
-*/
-int i;
-int x;
-
-for(i = 0; i < count; i++) {
-x = to[i];
-x += tmp[i];
-if (x < -32768) {
-/* printf("%d + %d = %d (u)n", to[i], tmp[i], x); */
-x = -32768;
-}
-if (x > 32767) {
-/* printf("%d + %d = %d (o)n", to[i], tmp[i], x); */
-x = 32767;
-}
-to[i] = x & 0x0000ffff;
+ int i, channels;
+
+ if (f->desc->out != f->desc->in)
+ return (EINVAL);
+
+ channels = (f->desc->out & AFMT_STEREO) ? 2 : 1;
+
+ for (i = 0; i < sizeof(feed_vchan_info_tbl) /
+ sizeof(feed_vchan_info_tbl[0]); i++) {
+ if ((f->desc->out & ~AFMT_STEREO) ==
+ feed_vchan_info_tbl[i].format) {
+ f->data = (void *)FVCHAN_DATA(i, channels);
+ return (0);
+ }
+ }
+
+ return (-1);
}
-return 0;
+
+static __inline int
+feed_vchan_rec(struct pcm_channel *c)
+{
+ struct pcm_channel *ch;
+ struct snd_dbuf *b, *bs;
+ int cnt, rdy;
+
+ /*
+ * Reset ready and moving pointer. We're not using bufsoft
+ * anywhere since its sole purpose is to become the primary
+ * distributor for the recorded buffer and also as an interrupt
+ * threshold progress indicator.
+ */
+ b = c->bufsoft;
+ b->rp = 0;
+ b->rl = 0;
+ cnt = sndbuf_getsize(b);
+
+ do {
+ cnt = FEEDER_FEED(c->feeder->source, c, b->tmpbuf, cnt,
+ c->bufhard);
+ if (cnt != 0) {
+ sndbuf_acquire(b, b->tmpbuf, cnt);
+ cnt = sndbuf_getfree(b);
+ }
+ } while (cnt != 0);
+
+ /* Not enough data */
+ if (b->rl < sndbuf_getbps(b)) {
+ b->rl = 0;
+ return (0);
+ }
+
+ /*
+ * Keep track of ready and moving pointer since we will use
+ * bufsoft over and over again, pretending nothing has happened.
+ */
+ rdy = b->rl;
+
+ CHN_FOREACH(ch, c, children.busy) {
+ CHN_LOCK(ch);
+ if (!(ch->flags & CHN_F_TRIGGERED)) {
+ CHN_UNLOCK(ch);
+ continue;
+ }
+ bs = ch->bufsoft;
+ if (ch->flags & CHN_F_MAPPED)
+ sndbuf_dispose(bs, NULL, sndbuf_getready(bs));
+ cnt = sndbuf_getfree(bs);
+ if (cnt < sndbuf_getbps(bs)) {
+ CHN_UNLOCK(ch);
+ continue;
+ }
+ do {
+ cnt = FEEDER_FEED(ch->feeder, ch, bs->tmpbuf, cnt, b);
+ if (cnt != 0) {
+ sndbuf_acquire(bs, bs->tmpbuf, cnt);
+ cnt = sndbuf_getfree(bs);
+ }
+ } while (cnt != 0);
+ /*
+ * Not entirely flushed out...
+ */
+ if (b->rl != 0)
+ ch->xruns++;
+ CHN_UNLOCK(ch);
+ /*
+ * Rewind buffer position for next virtual channel.
+ */
+ b->rp = 0;
+ b->rl = rdy;
+ }
+
+ /*
+ * Set ready pointer to indicate that our children are ready
+ * to be woken up, also as an interrupt threshold progress
+ * indicator.
+ */
+ b->rl = 1;
+
+ /*
+ * Return 0 to bail out early from sndbuf_feed() loop.
+ * No need to increase feedcount counter since part of this
+ * feeder chains already include feed_root().
+ */
+ return (0);
}
static int
-feed_vchan_s16(struct pcm_feeder *f, struct pcm_channel *c, u_int8_t *b, u_int32_t count, void *source)
+feed_vchan(struct pcm_feeder *f, struct pcm_channel *c, uint8_t *b,
+ uint32_t count, void *source)
{
-/* we're going to abuse things a bit */
-struct snd_dbuf *src = source;
-struct pcmchan_children *cce;
-struct pcm_channel *ch;
-uint32_t sz;
-int16_t *tmp, *dst;
-unsigned int cnt, rcnt = 0;
-
-#if 0
-if (sndbuf_getsize(src) < count)
-panic("feed_vchan_s16(%s): tmp buffer size %d < count %d, flags = 0x%x",
-c->name, sndbuf_getsize(src), count, c->flags);
-#endif
-sz = sndbuf_getsize(src);
-if (sz < count)
-count = sz;
-count &= ~1;
-if (count < 2)
-return 0;
-bzero(b, count);
-
-/*
-* we are going to use our source as a temporary buffer since it's
-* got no other purpose. we obtain our data by traversing the channel
-* list of children and calling vchan_mix_* to mix count bytes from each
-* into our destination buffer, b
-*/
-dst = (int16_t *)b;
-tmp = (int16_t *)sndbuf_getbuf(src);
-bzero(tmp, count);
-SLIST_FOREACH(cce, &c->children, link) {
-ch = cce->channel;
-CHN_LOCK(ch);
-if (ch->flags & CHN_F_TRIGGERED) {
-if (ch->flags & CHN_F_MAPPED)
-sndbuf_acquire(ch->bufsoft, NULL, sndbuf_getfree(ch->bufsoft));
-cnt = FEEDER_FEED(ch->feeder, ch, (u_int8_t *)tmp, count, ch->bufsoft);
-vchan_mix_s16(dst, tmp, cnt >> 1);
-if (cnt > rcnt)
-rcnt = cnt;
-}
-CHN_UNLOCK(ch);
-}
-
-return rcnt & ~1;
-}
-
-static struct pcm_feederdesc feeder_vchan_s16_desc[] = {
-{FEEDER_MIXER, AFMT_S16_LE | AFMT_STEREO, AFMT_S16_LE | AFMT_STEREO, 0},
-{0},
+ struct feed_vchan_info *info;
+ struct snd_dbuf *src = source;
+ struct pcm_channel *ch;
+ uint32_t cnt, mcnt, rcnt, sz;
+ uint8_t *tmp;
+
+ if (c->direction == PCMDIR_REC)
+ return (feed_vchan_rec(c));
+
+ sz = sndbuf_getsize(src);
+ if (sz < count)
+ count = sz;
+
+ info = &feed_vchan_info_tbl[FVCHAN_INFOIDX((intptr_t)f->data)];
+ sz = info->bps * FVCHAN_CHANNELS((intptr_t)f->data);
+ count -= count % sz;
+ if (count < sz)
+ return (0);
+
+ /*
+ * we are going to use our source as a temporary buffer since it's
+ * got no other purpose. we obtain our data by traversing the channel
+ * list of children and calling vchan_mix_* to mix count bytes from
+ * each into our destination buffer, b
+ */
+ tmp = sndbuf_getbuf(src);
+ rcnt = 0;
+ mcnt = 0;
+
+ CHN_FOREACH(ch, c, children.busy) {
+ CHN_LOCK(ch);
+ if (!(ch->flags & CHN_F_TRIGGERED)) {
+ CHN_UNLOCK(ch);
+ continue;
+ }
+ if ((ch->flags & CHN_F_MAPPED) && !(ch->flags & CHN_F_CLOSING))
+ sndbuf_acquire(ch->bufsoft, NULL,
+ sndbuf_getfree(ch->bufsoft));
+ if (rcnt == 0) {
+ rcnt = FEEDER_FEED(ch->feeder, ch, b, count,
+ ch->bufsoft);
+ rcnt -= rcnt % sz;
+ mcnt = count - rcnt;
+ } else {
+ cnt = FEEDER_FEED(ch->feeder, ch, tmp, count,
+ ch->bufsoft);
+ cnt -= cnt % sz;
+ if (cnt != 0) {
+ if (mcnt != 0) {
+ memset(b + rcnt,
+ sndbuf_zerodata(f->desc->out),
+ mcnt);
+ mcnt = 0;
+ }
+ cnt = info->mix(b, tmp, cnt);
+ if (cnt > rcnt)
+ rcnt = cnt;
+ }
+ }
+ CHN_UNLOCK(ch);
+ }
+
+ if (++c->feedcount == 0)
+ c->feedcount = 2;
+
+ return (rcnt);
+}
+
+static struct pcm_feederdesc feeder_vchan_desc[] = {
+ {FEEDER_MIXER, AFMT_S8, AFMT_S8, 0},
+ {FEEDER_MIXER, AFMT_S16_LE, AFMT_S16_LE, 0},
+ {FEEDER_MIXER, AFMT_S24_LE, AFMT_S24_LE, 0},
+ {FEEDER_MIXER, AFMT_S32_LE, AFMT_S32_LE, 0},
+ {FEEDER_MIXER, AFMT_S16_BE, AFMT_S16_BE, 0},
+ {FEEDER_MIXER, AFMT_S24_BE, AFMT_S24_BE, 0},
+ {FEEDER_MIXER, AFMT_S32_BE, AFMT_S32_BE, 0},
+ {FEEDER_MIXER, AFMT_S8 | AFMT_STEREO, AFMT_S8 | AFMT_STEREO, 0},
+ {FEEDER_MIXER, AFMT_S16_LE | AFMT_STEREO, AFMT_S16_LE | AFMT_STEREO, 0},
+ {FEEDER_MIXER, AFMT_S24_LE | AFMT_STEREO, AFMT_S24_LE | AFMT_STEREO, 0},
+ {FEEDER_MIXER, AFMT_S32_LE | AFMT_STEREO, AFMT_S32_LE | AFMT_STEREO, 0},
+ {FEEDER_MIXER, AFMT_S16_BE | AFMT_STEREO, AFMT_S16_BE | AFMT_STEREO, 0},
+ {FEEDER_MIXER, AFMT_S24_BE | AFMT_STEREO, AFMT_S24_BE | AFMT_STEREO, 0},
+ {FEEDER_MIXER, AFMT_S32_BE | AFMT_STEREO, AFMT_S32_BE | AFMT_STEREO, 0},
+ {FEEDER_MIXER, AFMT_U8, AFMT_U8, 0},
+ {FEEDER_MIXER, AFMT_U16_LE, AFMT_U16_LE, 0},
+ {FEEDER_MIXER, AFMT_U24_LE, AFMT_U24_LE, 0},
+ {FEEDER_MIXER, AFMT_U32_LE, AFMT_U32_LE, 0},
+ {FEEDER_MIXER, AFMT_U16_BE, AFMT_U16_BE, 0},
+ {FEEDER_MIXER, AFMT_U24_BE, AFMT_U24_BE, 0},
+ {FEEDER_MIXER, AFMT_U32_BE, AFMT_U32_BE, 0},
+ {FEEDER_MIXER, AFMT_U8 | AFMT_STEREO, AFMT_U8 | AFMT_STEREO, 0},
+ {FEEDER_MIXER, AFMT_U16_LE | AFMT_STEREO, AFMT_U16_LE | AFMT_STEREO, 0},
+ {FEEDER_MIXER, AFMT_U24_LE | AFMT_STEREO, AFMT_U24_LE | AFMT_STEREO, 0},
+ {FEEDER_MIXER, AFMT_U32_LE | AFMT_STEREO, AFMT_U32_LE | AFMT_STEREO, 0},
+ {FEEDER_MIXER, AFMT_U16_BE | AFMT_STEREO, AFMT_U16_BE | AFMT_STEREO, 0},
+ {FEEDER_MIXER, AFMT_U24_BE | AFMT_STEREO, AFMT_U24_BE | AFMT_STEREO, 0},
+ {FEEDER_MIXER, AFMT_U32_BE | AFMT_STEREO, AFMT_U32_BE | AFMT_STEREO, 0},
+ {0, 0, 0, 0},
};
-static kobj_method_t feeder_vchan_s16_methods[] = {
-KOBJMETHOD(feeder_feed, feed_vchan_s16),
-{ 0, 0 }
+static kobj_method_t feeder_vchan_methods[] = {
+ KOBJMETHOD(feeder_init, feed_vchan_init),
+ KOBJMETHOD(feeder_feed, feed_vchan),
+ {0, 0}
};
-FEEDER_DECLARE(feeder_vchan_s16, 2, NULL);
+FEEDER_DECLARE(feeder_vchan, 2, NULL);
/************************************************************/
static void *
-vchan_init(kobj_t obj, void *devinfo, struct snd_dbuf *b, struct pcm_channel *c, int dir)
+vchan_init(kobj_t obj, void *devinfo, struct snd_dbuf *b,
+ struct pcm_channel *c, int dir)
{
-struct vchinfo *ch;
-struct pcm_channel *parent = devinfo;
+ struct vchinfo *ch;
+
+ KASSERT(dir == PCMDIR_PLAY || dir == PCMDIR_REC,
+ ("vchan_init: bad direction"));
+ KASSERT(c != NULL && c->parentchannel != NULL,
+ ("vchan_init: bad channels"));
-KASSERT(dir == PCMDIR_PLAY, ("vchan_init: bad direction"));
-ch = malloc(sizeof(*ch), M_DEVBUF, M_WAITOK | M_ZERO);
-if (!ch)
-return NULL;
-ch->parent = parent;
-ch->channel = c;
-ch->fmt = AFMT_U8;
-ch->spd = DSP_DEFAULT_SPEED;
-ch->blksz = 2048;
+ ch = malloc(sizeof(*ch), M_DEVBUF, M_WAITOK | M_ZERO);
+ ch->channel = c;
+ ch->trigger = PCMTRIG_STOP;
-c->flags |= CHN_F_VIRTUAL;
+ c->flags |= CHN_F_VIRTUAL;
-return ch;
+ return (ch);
}
static int
vchan_free(kobj_t obj, void *data)
{
-free(data, M_DEVBUF);
-return 0;
-}
+ free(data, M_DEVBUF);
-static int
-vchan_setformat(kobj_t obj, void *data, u_int32_t format)
-{
-struct vchinfo *ch = data;
-struct pcm_channel *parent = ch->parent;
-struct pcm_channel *channel = ch->channel;
-
-ch->fmt = format;
-ch->bps = 1;
-ch->bps <<= (ch->fmt & AFMT_STEREO)? 1 : 0;
-if (ch->fmt & AFMT_16BIT)
-ch->bps <<= 1;
-else if (ch->fmt & AFMT_24BIT)
-ch->bps *= 3;
-else if (ch->fmt & AFMT_32BIT)
-ch->bps <<= 2;
-CHN_UNLOCK(channel);
-chn_notify(parent, CHN_N_FORMAT);
-CHN_LOCK(channel);
-sndbuf_setfmt(channel->bufsoft, format);
-return 0;
+ return (0);
}
static int
-vchan_setspeed(kobj_t obj, void *data, u_int32_t speed)
+vchan_setformat(kobj_t obj, void *data, uint32_t format)
{
-struct vchinfo *ch = data;
-struct pcm_channel *parent = ch->parent;
-struct pcm_channel *channel = ch->channel;
-
-ch->spd = speed;
-CHN_UNLOCK(channel);
-CHN_LOCK(parent);
-speed = sndbuf_getspd(parent->bufsoft);
-CHN_UNLOCK(parent);
-CHN_LOCK(channel);
-return speed;
+ struct vchinfo *ch = data;
+
+ if (fmtvalid(format, ch->fmtlist) == 0)
+ return (-1);
+
+ return (0);
}
static int
-vchan_setblocksize(kobj_t obj, void *data, u_int32_t blocksize)
+vchan_setspeed(kobj_t obj, void *data, uint32_t speed)
{
-struct vchinfo *ch = data;
-struct pcm_channel *channel = ch->channel;
-struct pcm_channel *parent = ch->parent;
-/* struct pcm_channel *channel = ch->channel; */
-int prate, crate;
-
-ch->blksz = blocksize;
-/* CHN_UNLOCK(channel); */
-sndbuf_setblksz(channel->bufhard, blocksize);
-chn_notify(parent, CHN_N_BLOCKSIZE);
-CHN_LOCK(parent);
-/* CHN_LOCK(channel); */
-
-crate = ch->spd * ch->bps;
-prate = sndbuf_getspd(parent->bufsoft) * sndbuf_getbps(parent->bufsoft);
-blocksize = sndbuf_getblksz(parent->bufsoft);
-CHN_UNLOCK(parent);
-blocksize *= prate;
-blocksize /= crate;
+ struct vchinfo *ch = data;
+ struct pcm_channel *p = ch->channel->parentchannel;
-return blocksize;
+ return (sndbuf_getspd(p->bufsoft));
}
static int
vchan_trigger(kobj_t obj, void *data, int go)
{
-struct vchinfo *ch = data;
-struct pcm_channel *parent = ch->parent;
-struct pcm_channel *channel = ch->channel;
-
-if (go == PCMTRIG_EMLDMAWR || go == PCMTRIG_EMLDMARD)
-return 0;
-
-ch->run = (go == PCMTRIG_START)? 1 : 0;
-CHN_UNLOCK(channel);
-chn_notify(parent, CHN_N_TRIGGER);
-CHN_LOCK(channel);
+ struct vchinfo *ch = data;
+ struct pcm_channel *c, *p;
+ int err, otrigger;
+
+ if (!PCMTRIG_COMMON(go) || go == ch->trigger)
+ return (0);
+
+ c = ch->channel;
+ p = c->parentchannel;
+ otrigger = ch->trigger;
+ ch->trigger = go;
+
+ CHN_UNLOCK(c);
+ CHN_LOCK(p);
+
+ switch (go) {
+ case PCMTRIG_START:
+ if (otrigger != PCMTRIG_START) {
+ CHN_INSERT_HEAD(p, c, children.busy);
+ }
+ break;
+ case PCMTRIG_STOP:
+ case PCMTRIG_ABORT:
+ if (otrigger == PCMTRIG_START) {
+ CHN_REMOVE(p, c, children.busy);
+ }
+ break;
+ default:
+ break;
+ }
+
+ err = chn_notify(p, CHN_N_TRIGGER);
+ CHN_UNLOCK(p);
+ CHN_LOCK(c);
-return 0;
+ return (err);
}
static struct pcmchan_caps *
vchan_getcaps(kobj_t obj, void *data)
{
-struct vchinfo *ch = data;
-
-ch->caps.minspeed = sndbuf_getspd(ch->parent->bufsoft);
-ch->caps.maxspeed = ch->caps.minspeed;
-ch->caps.fmtlist = vchan_fmt;
-ch->caps.caps = 0;
+ struct vchinfo *ch = data;
+ struct pcm_channel *c, *p;
+ uint32_t fmt;
+
+ c = ch->channel;
+ p = c->parentchannel;
+ ch->caps.minspeed = sndbuf_getspd(p->bufsoft);
+ ch->caps.maxspeed = ch->caps.minspeed;
+ ch->caps.caps = 0;
+ ch->fmtlist[1] = 0;
+ fmt = sndbuf_getfmt(p->bufsoft);
+ if (fmt != vchan_valid_format(fmt)) {
+ device_printf(c->dev,
+ "%s: WARNING: invalid vchan format! (0x%08x)\n",
+ __func__, fmt);
+ fmt = VCHAN_DEFAULT_AFMT;
+ }
+ ch->fmtlist[0] = fmt;
+ ch->caps.fmtlist = ch->fmtlist;
-return &ch->caps;
+ return (&ch->caps);
}
static kobj_method_t vchan_methods[] = {
-KOBJMETHOD(channel_init, vchan_init),
-KOBJMETHOD(channel_free, vchan_free),
-KOBJMETHOD(channel_setformat, vchan_setformat),
-KOBJMETHOD(channel_setspeed, vchan_setspeed),
-KOBJMETHOD(channel_setblocksize, vchan_setblocksize),
-KOBJMETHOD(channel_trigger, vchan_trigger),
-KOBJMETHOD(channel_getcaps, vchan_getcaps),
-{ 0, 0 }
+ KOBJMETHOD(channel_init, vchan_init),
+ KOBJMETHOD(channel_free, vchan_free),
+ KOBJMETHOD(channel_setformat, vchan_setformat),
+ KOBJMETHOD(channel_setspeed, vchan_setspeed),
+ KOBJMETHOD(channel_trigger, vchan_trigger),
+ KOBJMETHOD(channel_getcaps, vchan_getcaps),
+ {0, 0}
};
CHANNEL_DECLARE(vchan);
-#if 0
/*
-* On the fly vchan rate settings
-*/
+ * On the fly vchan rate settings
+ */
#ifdef SND_DYNSYSCTL
static int
sysctl_hw_snd_vchanrate(SYSCTL_HANDLER_ARGS)
{
-struct snddev_info *d;
-struct snddev_channel *sce;
-struct pcm_channel *c, *ch = NULL, *fake;
-struct pcmchan_caps *caps;
-int err = 0;
-int newspd = 0;
-
-d = oidp->oid_arg1;
-if (!(d->flags & SD_F_AUTOVCHAN) || d->vchancount < 1)
-return EINVAL;
-if (pcm_inprog(d, 1) != 1 && req->newptr != NULL) {
-pcm_inprog(d, -1);
-return EINPROGRESS;
-}
-SLIST_FOREACH(sce, &d->channels, link) {
-c = sce->channel;
-CHN_LOCK(c);
-if (c->direction == PCMDIR_PLAY) {
-if (c->flags & CHN_F_VIRTUAL) {
-/* Sanity check */
-if (ch != NULL && ch != c->parentchannel) {
-CHN_UNLOCK(c);
-pcm_inprog(d, -1);
-return EINVAL;
-}
-if (req->newptr != NULL &&
-(c->flags & CHN_F_BUSY)) {
-CHN_UNLOCK(c);
-pcm_inprog(d, -1);
-return EBUSY;
-}
-} else if (c->flags & CHN_F_HAS_VCHAN) {
-/* No way!! */
-if (ch != NULL) {
-CHN_UNLOCK(c);
-pcm_inprog(d, -1);
-return EINVAL;
-}
-ch = c;
-newspd = ch->speed;
-}
-}
-CHN_UNLOCK(c);
-}
-if (ch == NULL) {
-pcm_inprog(d, -1);
-return EINVAL;
-}
-err = sysctl_handle_int(oidp, &newspd, sizeof(newspd), req);
-if (err == 0 && req->newptr != NULL) {
-if (newspd < 1 || newspd < feeder_rate_ratemin ||
-newspd > feeder_rate_ratemax) {
-pcm_inprog(d, -1);
-return EINVAL;
-}
-CHN_LOCK(ch);
-caps = chn_getcaps(ch);
-if (caps == NULL || newspd < caps->minspeed ||
-newspd > caps->maxspeed) {
-CHN_UNLOCK(ch);
-pcm_inprog(d, -1);
-return EINVAL;
-}
-if (newspd != ch->speed) {
-err = chn_setspeed(ch, newspd);
-/*
-* Try to avoid FEEDER_RATE on parent channel if the
-* requested value is not supported by the hardware.
-*/
-if (!err && (ch->feederflags & (1 << FEEDER_RATE))) {
-newspd = sndbuf_getspd(ch->bufhard);
-err = chn_setspeed(ch, newspd);
-}
-CHN_UNLOCK(ch);
-if (err == 0) {
-fake = pcm_getfakechan(d);
-if (fake != NULL) {
-CHN_LOCK(fake);
-fake->speed = newspd;
-CHN_UNLOCK(fake);
-}
-}
-} else
-CHN_UNLOCK(ch);
-}
-pcm_inprog(d, -1);
-return err;
-}
-#endif
-#endif
-
-/* virtual channel interface */
+ struct snddev_info *d;
+ struct pcm_channel *c, *ch = NULL;
+ struct pcmchan_caps *caps;
+ int *vchanrate, vchancount, direction, err, newspd;
+
+ d = devclass_get_softc(pcm_devclass, VCHAN_SYSCTL_UNIT(oidp->oid_arg1));
+ if (!PCM_REGISTERED(d) || !(d->flags & SD_F_AUTOVCHAN))
+ return (EINVAL);
+
+ pcm_lock(d);
+ PCM_WAIT(d);
+
+ switch (VCHAN_SYSCTL_DIR(oidp->oid_arg1)) {
+ case VCHAN_PLAY:
+ direction = PCMDIR_PLAY;
+ vchancount = d->pvchancount;
+ vchanrate = &d->pvchanrate;
+ break;
+ case VCHAN_REC:
+ direction = PCMDIR_REC;
+ vchancount = d->rvchancount;
+ vchanrate = &d->rvchanrate;
+ break;
+ default:
+ pcm_unlock(d);
+ return (EINVAL);
+ break;
+ }
+
+ if (vchancount < 1) {
+ pcm_unlock(d);
+ return (EINVAL);
+ }
+
+ PCM_ACQUIRE(d);
+ pcm_unlock(d);
+
+ newspd = 0;
+
+ CHN_FOREACH(c, d, channels.pcm) {
+ CHN_LOCK(c);
+ if (c->direction == direction) {
+ if (c->flags & CHN_F_VIRTUAL) {
+ /* Sanity check */
+ if (ch != NULL && ch != c->parentchannel) {
+ CHN_UNLOCK(c);
+ PCM_RELEASE_QUICK(d);
+ return (EINVAL);
+ }
+ } else if (c->flags & CHN_F_HAS_VCHAN) {
+ /* No way!! */
+ if (ch != NULL) {
+ CHN_UNLOCK(c);
+ PCM_RELEASE_QUICK(d);
+ return (EINVAL);
+ }
+ ch = c;
+ newspd = ch->speed;
+ }
+ }
+ CHN_UNLOCK(c);
+ }
+ if (ch == NULL) {
+ PCM_RELEASE_QUICK(d);
+ return (EINVAL);
+ }
+
+ err = sysctl_handle_int(oidp, &newspd, 0, req);
+ if (err == 0 && req->newptr != NULL) {
+ if (newspd < 1 || newspd < feeder_rate_min ||
+ newspd > feeder_rate_max) {
+ PCM_RELEASE_QUICK(d);
+ return (EINVAL);
+ }
+ CHN_LOCK(ch);
+ if (feeder_rate_round) {
+ caps = chn_getcaps(ch);
+ if (caps == NULL || newspd < caps->minspeed ||
+ newspd > caps->maxspeed) {
+ CHN_UNLOCK(ch);
+ PCM_RELEASE_QUICK(d);
+ return (EINVAL);
+ }
+ }
+ if (CHN_STOPPED(ch) && newspd != ch->speed) {
+ err = chn_setspeed(ch, newspd);
+ /*
+ * Try to avoid FEEDER_RATE on parent channel if the
+ * requested value is not supported by the hardware.
+ */
+ if (!err && feeder_rate_round &&
+ (ch->feederflags & (1 << FEEDER_RATE))) {
+ newspd = sndbuf_getspd(ch->bufhard);
+ err = chn_setspeed(ch, newspd);
+ }
+ if (err == 0)
+ *vchanrate = newspd;
+ }
+ CHN_UNLOCK(ch);
+ }
-int
-vchan_create(struct pcm_channel *parent)
-{
-struct snddev_info *d = parent->parentsnddev;
-struct pcmchan_children *pce;
-struct pcm_channel *child, *fake;
-struct pcmchan_caps *parent_caps;
-int err, first, speed = 0;
+ PCM_RELEASE_QUICK(d);
-if (!(parent->flags & CHN_F_BUSY))
-return EBUSY;
-
-
-CHN_UNLOCK(parent);
-
-pce = malloc(sizeof(*pce), M_DEVBUF, M_WAITOK | M_ZERO);
-if (!pce) {
-CHN_LOCK(parent);
-return ENOMEM;
+ return (err);
}
-/* create a new playback channel */
-child = pcm_chn_create(d, parent, &vchan_class, PCMDIR_VIRTUAL, parent);
-if (!child) {
-free(pce, M_DEVBUF);
-CHN_LOCK(parent);
-return ENODEV;
-}
-pce->channel = child;
+static int
+sysctl_hw_snd_vchanformat(SYSCTL_HANDLER_ARGS)
+{
+ struct snddev_info *d;
+ struct pcm_channel *c, *ch = NULL;
+ uint32_t newfmt, spd;
+ int *vchanformat, vchancount, direction, err, i;
+ char fmtstr[AFMTSTR_MAXSZ];
+
+ d = devclass_get_softc(pcm_devclass, VCHAN_SYSCTL_UNIT(oidp->oid_arg1));
+ if (!PCM_REGISTERED(d) || !(d->flags & SD_F_AUTOVCHAN))
+ return (EINVAL);
+
+ pcm_lock(d);
+ PCM_WAIT(d);
+
+ switch (VCHAN_SYSCTL_DIR(oidp->oid_arg1)) {
+ case VCHAN_PLAY:
+ direction = PCMDIR_PLAY;
+ vchancount = d->pvchancount;
+ vchanformat = &d->pvchanformat;
+ break;
+ case VCHAN_REC:
+ direction = PCMDIR_REC;
+ vchancount = d->rvchancount;
+ vchanformat = &d->rvchanformat;
+ break;
+ default:
+ pcm_unlock(d);
+ return (EINVAL);
+ break;
+ }
+
+ if (vchancount < 1) {
+ pcm_unlock(d);
+ return (EINVAL);
+ }
+
+ PCM_ACQUIRE(d);
+ pcm_unlock(d);
+
+ CHN_FOREACH(c, d, channels.pcm) {
+ CHN_LOCK(c);
+ if (c->direction == direction) {
+ if (c->flags & CHN_F_VIRTUAL) {
+ /* Sanity check */
+ if (ch != NULL && ch != c->parentchannel) {
+ CHN_UNLOCK(c);
+ PCM_RELEASE_QUICK(d);
+ return (EINVAL);
+ }
+ } else if (c->flags & CHN_F_HAS_VCHAN) {
+ /* No way!! */
+ if (ch != NULL) {
+ CHN_UNLOCK(c);
+ PCM_RELEASE_QUICK(d);
+ return (EINVAL);
+ }
+ ch = c;
+ if (ch->format !=
+ afmt2afmtstr(vchan_supported_fmts,
+ ch->format, fmtstr, sizeof(fmtstr),
+ AFMTSTR_FULL, AFMTSTR_STEREO_RETURN)) {
+ strlcpy(fmtstr, VCHAN_DEFAULT_STRFMT,
+ sizeof(fmtstr));
+ }
+ }
+ }
+ CHN_UNLOCK(c);
+ }
+ if (ch == NULL) {
+ PCM_RELEASE_QUICK(d);
+ return (EINVAL);
+ }
+
+ err = sysctl_handle_string(oidp, fmtstr, sizeof(fmtstr), req);
+ if (err == 0 && req->newptr != NULL) {
+ for (i = 0; vchan_fmtstralias[i].alias != NULL; i++) {
+ if (strcmp(fmtstr, vchan_fmtstralias[i].alias) == 0) {
+ strlcpy(fmtstr, vchan_fmtstralias[i].fmtstr,
+ sizeof(fmtstr));
+ break;
+ }
+ }
+ newfmt = vchan_valid_strformat(fmtstr);
+ if (newfmt == 0) {
+ PCM_RELEASE_QUICK(d);
+ return (EINVAL);
+ }
+ CHN_LOCK(ch);
+ if (CHN_STOPPED(ch) && newfmt != ch->format) {
+ /* Get channel speed, before chn_reset() screw it. */
+ spd = ch->speed;
+ err = chn_reset(ch, newfmt);
+ if (err == 0)
+ err = chn_setspeed(ch, spd);
+ if (err == 0)
+ *vchanformat = newfmt;
+ }
+ CHN_UNLOCK(ch);
+ }
-/* add us to our grandparent's channel list */
-/*
-* XXX maybe we shouldn't always add the dev_t
-*/
-err = pcm_chn_add(d, child);
-if (err) {
-pcm_chn_destroy(child);
-free(pce, M_DEVBUF);
-CHN_LOCK(parent);
-return err;
-}
-
-CHN_LOCK(parent);
-/* add us to our parent channel's children */
-first = SLIST_EMPTY(&parent->children);
-SLIST_INSERT_HEAD(&parent->children, pce, link);
-parent->flags |= CHN_F_HAS_VCHAN;
-
-if (first) {
-parent_caps = chn_getcaps(parent);
-if (parent_caps == NULL)
-err = EINVAL;
-
-if (!err)
-err = chn_reset(parent, AFMT_STEREO | AFMT_S16_LE);
-
-if (!err) {
-fake = pcm_getfakechan(d);
-if (fake != NULL) {
-/*
-* Avoid querying kernel hint, use saved value
-* from fake channel.
-*/
-CHN_UNLOCK(parent);
-CHN_LOCK(fake);
-speed = fake->speed;
-CHN_UNLOCK(fake);
-CHN_LOCK(parent);
-}
+ PCM_RELEASE_QUICK(d);
-/*
-* This is very sad. Few soundcards advertised as being
-* able to do (insanely) higher/lower speed, but in
-* reality, they simply can't. At least, we give user chance
-* to set sane value via kernel hints or sysctl.
-*/
-if (speed < 1) {
-int r;
-CHN_UNLOCK(parent);
-r = resource_int_value(device_get_name(parent->dev),
-device_get_unit(parent->dev),
-"vchanrate", &speed);
-CHN_LOCK(parent);
-if (r != 0) {
-/*
-* Workaround for sb16 running
-* poorly at 45k / 49k.
-*/
-switch (parent_caps->maxspeed) {
-case 45000:
-case 49000:
-speed = 44100;
-break;
-default:
-speed = VCHAN_DEFAULT_SPEED;
-break;
-}
-}
+ return (err);
}
+#endif
-/*
-* Limit speed based on driver caps.
-* This is supposed to help fixed rate, non-VRA
-* AC97 cards, but.. (see below)
-*/
-if (speed < parent_caps->minspeed)
-speed = parent_caps->minspeed;
-if (speed > parent_caps->maxspeed)
-speed = parent_caps->maxspeed;
+/* virtual channel interface */
-/*
-* We still need to limit the speed between
-* feeder_rate_ratemin <-> feeder_rate_ratemax. This is
-* just an escape goat if all of the above failed
-* miserably.
-*/
-if (speed < feeder_rate_ratemin)
-speed = feeder_rate_ratemin;
-if (speed > feeder_rate_ratemax)
-speed = feeder_rate_ratemax;
+#define VCHAN_FMT_HINT(x) ((x) == PCMDIR_PLAY_VIRTUAL) ? \
+ "play.vchanformat" : "rec.vchanformat"
+#define VCHAN_SPD_HINT(x) ((x) == PCMDIR_PLAY_VIRTUAL) ? \
+ "play.vchanrate" : "rec.vchanrate"
-err = chn_setspeed(parent, speed);
-/*
-* Try to avoid FEEDER_RATE on parent channel if the
-* requested value is not supported by the hardware.
-*/
-if (!err && (parent->feederflags & (1 << FEEDER_RATE))) {
-speed = sndbuf_getspd(parent->bufhard);
-err = chn_setspeed(parent, speed);
-}
-
-if (!err && fake != NULL) {
-/*
-* Save new value to fake channel.
-*/
-CHN_UNLOCK(parent);
-CHN_LOCK(fake);
-fake->speed = speed;
-CHN_UNLOCK(fake);
-CHN_LOCK(parent);
-}
-}
-
-if (err) {
-SLIST_REMOVE(&parent->children, pce, pcmchan_children, link);
-parent->flags &= ~CHN_F_HAS_VCHAN;
-CHN_UNLOCK(parent);
-free(pce, M_DEVBUF);
-if (pcm_chn_remove(d, child) == 0)
-pcm_chn_destroy(child);
-CHN_LOCK(parent);
-return err;
-}
-}
+int
+vchan_create(struct pcm_channel *parent, int num)
+{
+ struct snddev_info *d = parent->parentsnddev;
+ struct pcm_channel *ch, *tmp, *after;
+ struct pcmchan_caps *parent_caps;
+ uint32_t vchanfmt;
+ int err, first, speed, r;
+ int direction;
+
+ PCM_BUSYASSERT(d);
+
+ if (!(parent->flags & CHN_F_BUSY))
+ return (EBUSY);
+
+ if (parent->direction == PCMDIR_PLAY) {
+ direction = PCMDIR_PLAY_VIRTUAL;
+ vchanfmt = d->pvchanformat;
+ speed = d->pvchanrate;
+ } else if (parent->direction == PCMDIR_REC) {
+ direction = PCMDIR_REC_VIRTUAL;
+ vchanfmt = d->rvchanformat;
+ speed = d->rvchanrate;
+ } else
+ return (EINVAL);
+ CHN_UNLOCK(parent);
+
+ /* create a new playback channel */
+ pcm_lock(d);
+ ch = pcm_chn_create(d, parent, &vchan_class, direction, num, parent);
+ if (ch == NULL) {
+ pcm_unlock(d);
+ CHN_LOCK(parent);
+ return (ENODEV);
+ }
+
+ /* add us to our grandparent's channel list */
+ err = pcm_chn_add(d, ch);
+ pcm_unlock(d);
+ if (err) {
+ pcm_chn_destroy(ch);
+ CHN_LOCK(parent);
+ return (err);
+ }
+
+ CHN_LOCK(parent);
+ /* add us to our parent channel's children */
+ first = CHN_EMPTY(parent, children);
+ after = NULL;
+ CHN_FOREACH(tmp, parent, children) {
+ if (CHN_CHAN(tmp) > CHN_CHAN(ch))
+ after = tmp;
+ else if (CHN_CHAN(tmp) < CHN_CHAN(ch))
+ break;
+ }
+ if (after != NULL) {
+ CHN_INSERT_AFTER(after, ch, children);
+ } else {
+ CHN_INSERT_HEAD(parent, ch, children);
+ }
+ parent->flags |= CHN_F_HAS_VCHAN;
+
+ if (first) {
+ parent_caps = chn_getcaps(parent);
+ if (parent_caps == NULL)
+ err = EINVAL;
+
+ if (!err) {
+ if (vchanfmt == 0) {
+ const char *vfmt;
+
+ CHN_UNLOCK(parent);
+ r = resource_string_value(
+ device_get_name(parent->dev),
+ device_get_unit(parent->dev),
+ VCHAN_FMT_HINT(direction),
+ &vfmt);
+ CHN_LOCK(parent);
+ if (r != 0)
+ vfmt = NULL;
+ if (vfmt != NULL) {
+ vchanfmt = vchan_valid_strformat(vfmt);
+ for (r = 0; vchanfmt == 0 &&
+ vchan_fmtstralias[r].alias != NULL;
+ r++) {
+ if (strcmp(vfmt, vchan_fmtstralias[r].alias) == 0) {
+ vchanfmt = vchan_valid_strformat(vchan_fmtstralias[r].fmtstr);
+ break;
+ }
+ }
+ }
+ if (vchanfmt == 0)
+ vchanfmt = VCHAN_DEFAULT_AFMT;
+ }
+ err = chn_reset(parent, vchanfmt);
+ }
+
+ if (!err) {
+ /*
+ * This is very sad. Few soundcards advertised as being
+ * able to do (insanely) higher/lower speed, but in
+ * reality, they simply can't. At least, we give user chance
+ * to set sane value via kernel hints or sysctl.
+ */
+ if (speed < 1) {
+ CHN_UNLOCK(parent);
+ r = resource_int_value(
+ device_get_name(parent->dev),
+ device_get_unit(parent->dev),
+ VCHAN_SPD_HINT(direction),
+ &speed);
+ CHN_LOCK(parent);
+ if (r != 0) {
+ /*
+ * No saved value, no hint, NOTHING.
+ *
+ * Workaround for sb16 running
+ * poorly at 45k / 49k.
+ */
+ switch (parent_caps->maxspeed) {
+ case 45000:
+ case 49000:
+ speed = 44100;
+ break;
+ default:
+ speed = VCHAN_DEFAULT_SPEED;
+ if (speed > parent_caps->maxspeed)
+ speed = parent_caps->maxspeed;
+ break;
+ }
+ if (speed < parent_caps->minspeed)
+ speed = parent_caps->minspeed;
+ }
+ }
+
+ if (feeder_rate_round) {
+ /*
+ * Limit speed based on driver caps.
+ * This is supposed to help fixed rate, non-VRA
+ * AC97 cards, but.. (see below)
+ */
+ if (speed < parent_caps->minspeed)
+ speed = parent_caps->minspeed;
+ if (speed > parent_caps->maxspeed)
+ speed = parent_caps->maxspeed;
+ }
+
+ /*
+ * We still need to limit the speed between
+ * feeder_rate_min <-> feeder_rate_max. This is
+ * just an escape goat if all of the above failed
+ * miserably.
+ */
+ if (speed < feeder_rate_min)
+ speed = feeder_rate_min;
+ if (speed > feeder_rate_max)
+ speed = feeder_rate_max;
+
+ err = chn_setspeed(parent, speed);
+ /*
+ * Try to avoid FEEDER_RATE on parent channel if the
+ * requested value is not supported by the hardware.
+ */
+ if (!err && feeder_rate_round &&
+ (parent->feederflags & (1 << FEEDER_RATE))) {
+ speed = sndbuf_getspd(parent->bufhard);
+ err = chn_setspeed(parent, speed);
+ }
+
+ if (!err) {
+ /*
+ * Save new value.
+ */
+ CHN_UNLOCK(parent);
+ if (direction == PCMDIR_PLAY_VIRTUAL) {
+ d->pvchanformat = vchanfmt;
+ d->pvchanrate = speed;
+ } else {
+ d->rvchanformat = vchanfmt;
+ d->rvchanrate = speed;
+ }
+ CHN_LOCK(parent);
+ }
+ }
+
+ if (err) {
+ CHN_REMOVE(parent, ch, children);
+ parent->flags &= ~CHN_F_HAS_VCHAN;
+ CHN_UNLOCK(parent);
+ pcm_lock(d);
+ if (pcm_chn_remove(d, ch) == 0) {
+ pcm_unlock(d);
+ pcm_chn_destroy(ch);
+ } else
+ pcm_unlock(d);
+ CHN_LOCK(parent);
+ return (err);
+ }
+ }
-return 0;
+ return (0);
}
int
vchan_destroy(struct pcm_channel *c)
{
-struct pcm_channel *parent = c->parentchannel;
-struct snddev_info *d = parent->parentsnddev;
-struct pcmchan_children *pce;
-struct snddev_channel *sce;
-uint32_t spd;
-int err;
-
-CHN_LOCK(parent);
-if (!(parent->flags & CHN_F_BUSY)) {
-CHN_UNLOCK(parent);
-return EBUSY;
-}
-if (SLIST_EMPTY(&parent->children)) {
-CHN_UNLOCK(parent);
-return EINVAL;
-}
-
-/* remove us from our parent's children list */
-SLIST_FOREACH(pce, &parent->children, link) {
-if (pce->channel == c)
-goto gotch;
-}
-CHN_UNLOCK(parent);
-return EINVAL;
-gotch:
-SLIST_FOREACH(sce, &d->channels, link) {
-if (sce->channel == c) {
-if (sce->dsp_devt) {
-destroy_dev(sce->dsp_devt);
-sce->dsp_devt = NULL;
-}
-if (sce->dspW_devt) {
-destroy_dev(sce->dspW_devt);
-sce->dspW_devt = NULL;
-}
-if (sce->audio_devt) {
-destroy_dev(sce->audio_devt);
-sce->audio_devt = NULL;
-}
-if (sce->dspr_devt) {
-destroy_dev(sce->dspr_devt);
-sce->dspr_devt = NULL;
-}
-d->devcount--;
-break;
-}
-}
-SLIST_REMOVE(&parent->children, pce, pcmchan_children, link);
-free(pce, M_DEVBUF);
-
-if (SLIST_EMPTY(&parent->children)) {
-parent->flags &= ~(CHN_F_BUSY | CHN_F_HAS_VCHAN);
-spd = parent->speed;
-if (chn_reset(parent, parent->format) == 0)
-chn_setspeed(parent, spd);
-}
-
-/* remove us from our grandparent's channel list */
-err = pcm_chn_remove(d, c);
-
-CHN_UNLOCK(parent);
-/* destroy ourselves */
-if (!err)
-err = pcm_chn_destroy(c);
+ struct pcm_channel *parent = c->parentchannel;
+ struct snddev_info *d = parent->parentsnddev;
+ uint32_t spd;
+ int err;
+
+ PCM_BUSYASSERT(d);
+
+ CHN_LOCK(parent);
+ if (!(parent->flags & CHN_F_BUSY)) {
+ CHN_UNLOCK(parent);
+ return (EBUSY);
+ }
+ if (CHN_EMPTY(parent, children)) {
+ CHN_UNLOCK(parent);
+ return (EINVAL);
+ }
+
+ /* remove us from our parent's children list */
+ CHN_REMOVE(parent, c, children);
+
+ if (CHN_EMPTY(parent, children)) {
+ parent->flags &= ~(CHN_F_BUSY | CHN_F_HAS_VCHAN);
+ spd = parent->speed;
+ if (chn_reset(parent, parent->format) == 0)
+ chn_setspeed(parent, spd);
+ }
+
+ CHN_UNLOCK(parent);
+
+ /* remove us from our grandparent's channel list */
+ pcm_lock(d);
+ err = pcm_chn_remove(d, c);
+ pcm_unlock(d);
+
+ /* destroy ourselves */
+ if (!err)
+ err = pcm_chn_destroy(c);
-return err;
+ return (err);
}
int
vchan_initsys(device_t dev)
{
#ifdef SND_DYNSYSCTL
-struct snddev_info *d;
+ struct snddev_info *d;
+ int unit;
-d = device_get_softc(dev);
-SYSCTL_ADD_PROC(snd_sysctl_tree(dev), SYSCTL_CHILDREN(snd_sysctl_tree_top(dev)),
-OID_AUTO, "vchans", CTLTYPE_INT | CTLFLAG_RW, d, sizeof(d),
-sysctl_hw_snd_vchans, "I", "");
-#if 0
-SYSCTL_ADD_PROC(snd_sysctl_tree(dev), SYSCTL_CHILDREN(snd_sysctl_tree_top(dev)),
-OID_AUTO, "vchanrate", CTLTYPE_INT | CTLFLAG_RW, d, sizeof(d),
-sysctl_hw_snd_vchanrate, "I", "");
-#endif
+ unit = device_get_unit(dev);
+ d = device_get_softc(dev);
+
+ /* Play */
+ SYSCTL_ADD_PROC(&d->play_sysctl_ctx,
+ SYSCTL_CHILDREN(d->play_sysctl_tree),
+ OID_AUTO, "vchans", CTLTYPE_INT | CTLFLAG_RW,
+ VCHAN_SYSCTL_DATA(unit, PLAY), VCHAN_SYSCTL_DATA_SIZE,
+ sysctl_hw_snd_vchans, "I", "total allocated virtual channel");
+ SYSCTL_ADD_PROC(&d->play_sysctl_ctx,
+ SYSCTL_CHILDREN(d->play_sysctl_tree),
+ OID_AUTO, "vchanrate", CTLTYPE_INT | CTLFLAG_RW,
+ VCHAN_SYSCTL_DATA(unit, PLAY), VCHAN_SYSCTL_DATA_SIZE,
+ sysctl_hw_snd_vchanrate, "I", "virtual channel mixing speed/rate");
+ SYSCTL_ADD_PROC(&d->play_sysctl_ctx,
+ SYSCTL_CHILDREN(d->play_sysctl_tree),
+ OID_AUTO, "vchanformat", CTLTYPE_STRING | CTLFLAG_RW,
+ VCHAN_SYSCTL_DATA(unit, PLAY), VCHAN_SYSCTL_DATA_SIZE,
+ sysctl_hw_snd_vchanformat, "A", "virtual channel format");
+ /* Rec */
+ SYSCTL_ADD_PROC(&d->rec_sysctl_ctx,
+ SYSCTL_CHILDREN(d->rec_sysctl_tree),
+ OID_AUTO, "vchans", CTLTYPE_INT | CTLFLAG_RW,
+ VCHAN_SYSCTL_DATA(unit, REC), VCHAN_SYSCTL_DATA_SIZE,
+ sysctl_hw_snd_vchans, "I", "total allocated virtual channel");
+ SYSCTL_ADD_PROC(&d->rec_sysctl_ctx,
+ SYSCTL_CHILDREN(d->rec_sysctl_tree),
+ OID_AUTO, "vchanrate", CTLTYPE_INT | CTLFLAG_RW,
+ VCHAN_SYSCTL_DATA(unit, REC), VCHAN_SYSCTL_DATA_SIZE,
+ sysctl_hw_snd_vchanrate, "I", "virtual channel base speed/rate");
+ SYSCTL_ADD_PROC(&d->rec_sysctl_ctx,
+ SYSCTL_CHILDREN(d->rec_sysctl_tree),
+ OID_AUTO, "vchanformat", CTLTYPE_STRING | CTLFLAG_RW,
+ VCHAN_SYSCTL_DATA(unit, REC), VCHAN_SYSCTL_DATA_SIZE,
+ sysctl_hw_snd_vchanformat, "A", "virtual channel format");
#endif
-return 0;
+ return (0);
}
Index: sound.c
===================================================================
RCS file: /home/cvs/src/sys/dev/sound/pcm/sound.c,v
retrieving revision 1.3
retrieving revision 1.4
diff -L sys/dev/sound/pcm/sound.c -L sys/dev/sound/pcm/sound.c -u -r1.3 -r1.4
--- sys/dev/sound/pcm/sound.c
+++ sys/dev/sound/pcm/sound.c
@@ -1,84 +1,91 @@
/*-
-* Copyright (c) 1999 Cameron Grant <cg at freebsd.org>
-* (C) 1997 Luigi Rizzo (luigi at iet.unipi.it)
-* All rights reserved.
-*
-* Redistribution and use in source and binary forms, with or without
-* modification, are permitted provided that the following conditions
-* are met:
-* 1. Redistributions of source code must retain the above copyright
-* notice, this list of conditions and the following disclaimer.
-* 2. Redistributions in binary form must reproduce the above copyright
-* notice, this list of conditions and the following disclaimer in the
-* documentation and/or other materials provided with the distribution.
-*
-* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
-* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
-* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
-* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
-* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
-* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
-* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
-* SUCH DAMAGE.
-*/
+ * Copyright (c) 1999 Cameron Grant <cg at freebsd.org>
+ * (C) 1997 Luigi Rizzo
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
#include <dev/sound/pcm/sound.h>
+#include <dev/sound/pcm/ac97.h>
#include <dev/sound/pcm/vchan.h>
#include <dev/sound/pcm/dsp.h>
+#include <dev/sound/version.h>
+#include <sys/limits.h>
#include <sys/sysctl.h>
#include "feeder_if.h"
-SND_DECLARE_FILE("$MidnightBSD$");
+SND_DECLARE_FILE("$FreeBSD: src/sys/dev/sound/pcm/sound.c,v 1.119 2007/06/17 19:02:05 ariff Exp $");
devclass_t pcm_devclass;
int pcm_veto_load = 1;
#ifdef USING_DEVFS
-int snd_unit = 0;
-TUNABLE_INT("hw.snd.unit", &snd_unit);
+int snd_unit = -1;
+TUNABLE_INT("hw.snd.default_unit", &snd_unit);
#endif
-int snd_maxautovchans = 0;
+static int snd_unit_auto = 0;
+TUNABLE_INT("hw.snd.default_auto", &snd_unit_auto);
+SYSCTL_INT(_hw_snd, OID_AUTO, default_auto, CTLFLAG_RW,
+ &snd_unit_auto, 0, "assign default unit to a newly attached device");
+
+int snd_maxautovchans = 16;
+/* XXX: a tunable implies that we may need more than one sound channel before
+ the system can change a sysctl (/etc/sysctl.conf), do we really need
+ this? */
TUNABLE_INT("hw.snd.maxautovchans", &snd_maxautovchans);
SYSCTL_NODE(_hw, OID_AUTO, snd, CTLFLAG_RD, 0, "Sound driver");
-static int sndstat_prepare_pcm(struct sbuf *s, device_t dev, int verbose);
-
-struct sysctl_ctx_list *
-snd_sysctl_tree(device_t dev)
-{
-struct snddev_info *d = device_get_softc(dev);
-
-return &d->sysctl_tree;
-}
-
-struct sysctl_oid *
-snd_sysctl_tree_top(device_t dev)
-{
-struct snddev_info *d = device_get_softc(dev);
+/*
+ * XXX I've had enough with people not telling proper version/arch
+ * while reporting problems, not after 387397913213th questions/requests.
+ */
+static const char snd_driver_version[] =
+ __XSTRING(SND_DRV_VERSION)"/"MACHINE_ARCH;
+SYSCTL_STRING(_hw_snd, OID_AUTO, version, CTLFLAG_RD, &snd_driver_version,
+ 0, "Driver version/arch");
+
+/**
+ * @brief Unit number allocator for syncgroup IDs
+ */
+struct unrhdr *pcmsg_unrhdr = NULL;
-return d->sysctl_tree_top;
-}
+static int sndstat_prepare_pcm(struct sbuf *s, device_t dev, int verbose);
void *
snd_mtxcreate(const char *desc, const char *type)
{
#ifdef USING_MUTEX
-struct mtx *m;
+ struct mtx *m;
-m = malloc(sizeof(*m), M_DEVBUF, M_WAITOK | M_ZERO);
-if (m == NULL)
-return NULL;
-mtx_init(m, desc, type, MTX_DEF);
-return m;
+ m = malloc(sizeof(*m), M_DEVBUF, M_WAITOK | M_ZERO);
+ mtx_init(m, desc, type, MTX_DEF);
+ return m;
#else
-return (void *)0xcafebabe;
+ return (void *)0xcafebabe;
#endif
}
@@ -86,11 +93,11 @@
snd_mtxfree(void *m)
{
#ifdef USING_MUTEX
-struct mtx *mtx = m;
+ struct mtx *mtx = m;
-/* mtx_assert(mtx, MA_OWNED); */
-mtx_destroy(mtx);
-free(mtx, M_DEVBUF);
+ /* mtx_assert(mtx, MA_OWNED); */
+ mtx_destroy(mtx);
+ free(mtx, M_DEVBUF);
#endif
}
@@ -99,9 +106,9 @@
{
#ifdef USING_MUTEX
#ifdef INVARIANTS
-struct mtx *mtx = m;
+ struct mtx *mtx = m;
-mtx_assert(mtx, MA_OWNED);
+ mtx_assert(mtx, MA_OWNED);
#endif
#endif
}
@@ -110,9 +117,9 @@
snd_mtxlock(void *m)
{
#ifdef USING_MUTEX
-struct mtx *mtx = m;
+ struct mtx *mtx = m;
-mtx_lock(mtx);
+ mtx_lock(mtx);
#endif
}
@@ -120,870 +127,1103 @@
snd_mtxunlock(void *m)
{
#ifdef USING_MUTEX
-struct mtx *mtx = m;
+ struct mtx *mtx = m;
-mtx_unlock(mtx);
+ mtx_unlock(mtx);
#endif
}
*/
int
snd_setup_intr(device_t dev, struct resource *res, int flags, driver_intr_t hand, void *param, void **cookiep)
{
+ struct snddev_info *d;
#ifdef USING_MUTEX
-flags &= INTR_MPSAFE;
-flags |= INTR_TYPE_AV;
+ flags &= INTR_MPSAFE;
+ flags |= INTR_TYPE_AV;
#else
-flags = INTR_TYPE_AV;
+ flags = INTR_TYPE_AV;
+#endif
+ d = device_get_softc(dev);
+ if (d != NULL && (flags & INTR_MPSAFE))
+ d->flags |= SD_F_MPSAFE;
+
+ return bus_setup_intr(dev, res, flags,
+#if __FreeBSD_version >= 700031
+ NULL,
#endif
-return bus_setup_intr(dev, res, flags, hand, param, cookiep);
+ hand, param, cookiep);
}
#ifndef PCM_DEBUG_MTX
void
pcm_lock(struct snddev_info *d)
{
-snd_mtxlock(d->lock);
+ snd_mtxlock(d->lock);
}
void
pcm_unlock(struct snddev_info *d)
{
-snd_mtxunlock(d->lock);
+ snd_mtxunlock(d->lock);
}
#endif
struct pcm_channel *
pcm_getfakechan(struct snddev_info *d)
{
-return d->fakechan;
+ return d->fakechan;
}
-static int
-pcm_setvchans(struct snddev_info *d, int newcnt)
+static void
+pcm_clonereset(struct snddev_info *d)
{
-struct snddev_channel *sce = NULL;
-struct pcm_channel *c = NULL;
-int err = 0, vcnt, dcnt, i;
-
-pcm_inprog(d, 1);
-
-if (!(d->flags & SD_F_AUTOVCHAN)) {
-err = EINVAL;
-goto setvchans_out;
-}
-
-vcnt = d->vchancount;
-dcnt = d->playcount + d->reccount;
-
-if (newcnt < 0 || (dcnt + newcnt) > (PCMMAXCHAN + 1)) {
-err = E2BIG;
-goto setvchans_out;
-}
-
-dcnt += vcnt;
-
-if (newcnt > vcnt) {
-/* add new vchans - find a parent channel first */
-SLIST_FOREACH(sce, &d->channels, link) {
-c = sce->channel;
-CHN_LOCK(c);
-if (c->direction == PCMDIR_PLAY &&
-((c->flags & CHN_F_HAS_VCHAN) ||
-(vcnt == 0 &&
-!(c->flags & (CHN_F_BUSY | CHN_F_VIRTUAL)))))
-goto addok;
-CHN_UNLOCK(c);
-}
-err = EBUSY;
-goto setvchans_out;
-addok:
-c->flags |= CHN_F_BUSY;
-while (err == 0 && newcnt > vcnt) {
-if (dcnt > PCMMAXCHAN) {
-device_printf(d->dev, "%s: Maximum channel reached.n", __func__);
-break;
-}
-err = vchan_create(c);
-if (err == 0) {
-vcnt++;
-dcnt++;
-} else if (err == E2BIG && newcnt > vcnt)
-device_printf(d->dev, "%s: err=%d Maximum channel reached.n", __func__, err);
-}
-if (vcnt == 0)
-c->flags &= ~CHN_F_BUSY;
-CHN_UNLOCK(c);
-} else if (newcnt < vcnt) {
-#define ORPHAN_CDEVT(cdevt) ((cdevt) == NULL || ((cdevt)->si_drv1 == NULL && (cdevt)->si_drv2 == NULL))
-while (err == 0 && newcnt < vcnt) {
-i = 0;
-SLIST_FOREACH(sce, &d->channels, link) {
-c = sce->channel;
-CHN_LOCK(c);
-if (c->direction == PCMDIR_PLAY &&
-(c->flags & CHN_F_VIRTUAL) &&
-(i++ == newcnt)) {
-if (!(c->flags & CHN_F_BUSY) &&
-ORPHAN_CDEVT(sce->dsp_devt) &&
-ORPHAN_CDEVT(sce->dspW_devt) &&
-ORPHAN_CDEVT(sce->audio_devt) &&
-ORPHAN_CDEVT(sce->dspr_devt))
-goto remok;
-/*
-* Either we're busy, or our cdev
-* has been stolen by dsp_clone().
-* Skip, and increase newcnt.
-*/
-if (!(c->flags & CHN_F_BUSY))
-device_printf(d->dev,
-"%s: <%s> somebody steal my cdev!n",
-__func__, c->name);
-newcnt++;
-}
-CHN_UNLOCK(c);
-}
-if (vcnt != newcnt)
-err = EBUSY;
-break;
-remok:
-CHN_UNLOCK(c);
-err = vchan_destroy(c);
-if (err == 0)
-vcnt--;
-else
-device_printf(d->dev,
-"%s: WARNING: vchan_destroy() failed!",
-__func__);
-}
+ int cmax;
+
+ PCM_BUSYASSERT(d);
+
+ cmax = d->playcount + d->reccount - 1;
+ if (d->pvchancount > 0)
+ cmax += MAX(d->pvchancount, snd_maxautovchans) - 1;
+ if (d->rvchancount > 0)
+ cmax += MAX(d->rvchancount, snd_maxautovchans) - 1;
+ if (cmax > PCMMAXCLONE)
+ cmax = PCMMAXCLONE;
+ (void)snd_clone_gc(d->clones);
+ (void)snd_clone_setmaxunit(d->clones, cmax);
}
-setvchans_out:
-pcm_inprog(d, -1);
-return err;
+static int
+pcm_setvchans(struct snddev_info *d, int direction, int newcnt, int num)
+{
+ struct pcm_channel *c, *ch, *nch;
+ int err, vcnt;
+
+ PCM_BUSYASSERT(d);
+
+ if ((direction == PCMDIR_PLAY && d->playcount < 1) ||
+ (direction == PCMDIR_REC && d->reccount < 1))
+ return (ENODEV);
+
+ if (!(d->flags & SD_F_AUTOVCHAN))
+ return (EINVAL);
+
+ if (newcnt < 0 || newcnt > SND_MAXVCHANS)
+ return (E2BIG);
+
+ if (direction == PCMDIR_PLAY)
+ vcnt = d->pvchancount;
+ else if (direction == PCMDIR_REC)
+ vcnt = d->rvchancount;
+ else
+ return (EINVAL);
+
+ if (newcnt > vcnt) {
+ KASSERT(num == -1 ||
+ (num >= 0 && num < SND_MAXVCHANS && (newcnt - 1) == vcnt),
+ ("bogus vchan_create() request num=%d newcnt=%d vcnt=%d",
+ num, newcnt, vcnt));
+ /* add new vchans - find a parent channel first */
+ ch = NULL;
+ CHN_FOREACH(c, d, channels.pcm) {
+ CHN_LOCK(c);
+ if (c->direction == direction &&
+ ((c->flags & CHN_F_HAS_VCHAN) || (vcnt == 0 &&
+ !(c->flags & (CHN_F_BUSY | CHN_F_VIRTUAL))))) {
+ ch = c;
+ break;
+ }
+ CHN_UNLOCK(c);
+ }
+ if (ch == NULL)
+ return (EBUSY);
+ ch->flags |= CHN_F_BUSY;
+ err = 0;
+ while (err == 0 && newcnt > vcnt) {
+ err = vchan_create(ch, num);
+ if (err == 0)
+ vcnt++;
+ else if (err == E2BIG && newcnt > vcnt)
+ device_printf(d->dev,
+ "%s: err=%d Maximum channel reached.\n",
+ __func__, err);
+ }
+ if (vcnt == 0)
+ ch->flags &= ~CHN_F_BUSY;
+ CHN_UNLOCK(ch);
+ if (err != 0)
+ return (err);
+ else
+ pcm_clonereset(d);
+ } else if (newcnt < vcnt) {
+ KASSERT(num == -1,
+ ("bogus vchan_destroy() request num=%d", num));
+ CHN_FOREACH(c, d, channels.pcm) {
+ CHN_LOCK(c);
+ if (c->direction != direction ||
+ CHN_EMPTY(c, children) ||
+ !(c->flags & CHN_F_HAS_VCHAN)) {
+ CHN_UNLOCK(c);
+ continue;
+ }
+ CHN_FOREACH_SAFE(ch, c, nch, children) {
+ CHN_LOCK(ch);
+ if (!(ch->flags & CHN_F_BUSY)) {
+ CHN_UNLOCK(ch);
+ CHN_UNLOCK(c);
+ err = vchan_destroy(ch);
+ CHN_LOCK(c);
+ if (err == 0)
+ vcnt--;
+ } else
+ CHN_UNLOCK(ch);
+ if (vcnt == newcnt)
+ break;
+ }
+ CHN_UNLOCK(c);
+ break;
+ }
+ pcm_clonereset(d);
+ }
+
+ return (0);
}
/* return error status and a locked channel */
int
pcm_chnalloc(struct snddev_info *d, struct pcm_channel **ch, int direction,
-pid_t pid, int chnum)
+ pid_t pid, int devunit)
{
-struct pcm_channel *c;
-struct snddev_channel *sce;
-int err;
+ struct pcm_channel *c;
+ int err, vchancount;
+
+ KASSERT(d != NULL && ch != NULL && (devunit == -1 ||
+ !(devunit & ~(SND_U_MASK | SND_D_MASK | SND_C_MASK))) &&
+ (direction == PCMDIR_PLAY || direction == PCMDIR_REC),
+ ("%s(): invalid d=%p ch=%p direction=%d pid=%d devunit=%d",
+ __func__, d, ch, direction, pid, devunit));
+ PCM_BUSYASSERT(d);
+
+ /* Double check again. */
+ if (devunit != -1) {
+ switch (snd_unit2d(devunit)) {
+ case SND_DEV_DSPHW_PLAY:
+ case SND_DEV_DSPHW_VPLAY:
+ if (direction != PCMDIR_PLAY)
+ return (EOPNOTSUPP);
+ break;
+ case SND_DEV_DSPHW_REC:
+ case SND_DEV_DSPHW_VREC:
+ if (direction != PCMDIR_REC)
+ return (EOPNOTSUPP);
+ break;
+ default:
+ if (!(direction == PCMDIR_PLAY ||
+ direction == PCMDIR_REC))
+ return (EOPNOTSUPP);
+ break;
+ }
+ }
retry_chnalloc:
-err = ENODEV;
-/* scan for a free channel */
-SLIST_FOREACH(sce, &d->channels, link) {
-c = sce->channel;
-CHN_LOCK(c);
-if (c->direction == direction && !(c->flags & CHN_F_BUSY)) {
-if (chnum < 0 || sce->chan_num == chnum) {
-c->flags |= CHN_F_BUSY;
-c->pid = pid;
-*ch = c;
-return 0;
-}
-}
-if (sce->chan_num == chnum) {
-if (c->direction != direction)
-err = EOPNOTSUPP;
-else if (c->flags & CHN_F_BUSY)
-err = EBUSY;
-else
-err = EINVAL;
-CHN_UNLOCK(c);
-return err;
-} else if (c->direction == direction && (c->flags & CHN_F_BUSY))
-err = EBUSY;
-CHN_UNLOCK(c);
-}
-
-/* no channel available */
-if (chnum == -1 && direction == PCMDIR_PLAY && d->vchancount > 0 &&
-d->vchancount < snd_maxautovchans &&
-d->devcount <= PCMMAXCHAN) {
-err = pcm_setvchans(d, d->vchancount + 1);
-if (err == 0) {
-chnum = -2;
-goto retry_chnalloc;
-}
-}
+ err = EOPNOTSUPP;
+ /* scan for a free channel */
+ CHN_FOREACH(c, d, channels.pcm) {
+ CHN_LOCK(c);
+ if (c->direction == direction && !(c->flags & CHN_F_BUSY) &&
+ (devunit == -1 || devunit == -2 || c->unit == devunit)) {
+ c->flags |= CHN_F_BUSY;
+ c->pid = pid;
+ *ch = c;
+ return (0);
+ } else if (c->unit == devunit) {
+ if (c->direction != direction)
+ err = EOPNOTSUPP;
+ else if (c->flags & CHN_F_BUSY)
+ err = EBUSY;
+ else
+ err = EINVAL;
+ CHN_UNLOCK(c);
+ return (err);
+ } else if ((devunit == -1 || devunit == -2) &&
+ c->direction == direction && (c->flags & CHN_F_BUSY))
+ err = EBUSY;
+ CHN_UNLOCK(c);
+ }
+
+ if (devunit == -2)
+ return (err);
+
+ /* no channel available */
+ if (devunit == -1 || snd_unit2d(devunit) == SND_DEV_DSPHW_VPLAY ||
+ snd_unit2d(devunit) == SND_DEV_DSPHW_VREC) {
+ if (direction == PCMDIR_PLAY)
+ vchancount = d->pvchancount;
+ else
+ vchancount = d->rvchancount;
+ if (!(vchancount > 0 && vchancount < snd_maxautovchans) &&
+ (devunit == -1 || snd_unit2c(devunit) < snd_maxautovchans))
+ return (err);
+ err = pcm_setvchans(d, direction, vchancount + 1,
+ (devunit == -1) ? -1 : snd_unit2c(devunit));
+ if (err == 0) {
+ if (devunit == -1)
+ devunit = -2;
+ goto retry_chnalloc;
+ }
+ }
-return err;
+ return (err);
}
/* release a locked channel and unlock it */
int
pcm_chnrelease(struct pcm_channel *c)
{
-CHN_LOCKASSERT(c);
-c->flags &= ~CHN_F_BUSY;
-c->pid = -1;
-CHN_UNLOCK(c);
-return 0;
+ PCM_BUSYASSERT(c->parentsnddev);
+ CHN_LOCKASSERT(c);
+
+ c->flags &= ~CHN_F_BUSY;
+ c->pid = -1;
+ CHN_UNLOCK(c);
+
+ return (0);
}
int
pcm_chnref(struct pcm_channel *c, int ref)
{
-int r;
+ PCM_BUSYASSERT(c->parentsnddev);
+ CHN_LOCKASSERT(c);
-CHN_LOCKASSERT(c);
-c->refcount += ref;
-r = c->refcount;
-return r;
+ c->refcount += ref;
+
+ return (c->refcount);
}
int
pcm_inprog(struct snddev_info *d, int delta)
{
-int r;
+ snd_mtxassert(d->lock);
-if (delta == 0)
-return d->inprog;
+ d->inprog += delta;
-/* backtrace(); */
-pcm_lock(d);
-d->inprog += delta;
-r = d->inprog;
-pcm_unlock(d);
-return r;
+ return (d->inprog);
}
static void
pcm_setmaxautovchans(struct snddev_info *d, int num)
{
-if (num > 0 && d->vchancount == 0)
-pcm_setvchans(d, 1);
-else if (num == 0 && d->vchancount > 0)
-pcm_setvchans(d, 0);
+ PCM_BUSYASSERT(d);
+
+ if (num < 0)
+ return;
+
+ if (num >= 0 && d->pvchancount > num)
+ (void)pcm_setvchans(d, PCMDIR_PLAY, num, -1);
+ else if (num > 0 && d->pvchancount == 0)
+ (void)pcm_setvchans(d, PCMDIR_PLAY, 1, -1);
+
+ if (num >= 0 && d->rvchancount > num)
+ (void)pcm_setvchans(d, PCMDIR_REC, num, -1);
+ else if (num > 0 && d->rvchancount == 0)
+ (void)pcm_setvchans(d, PCMDIR_REC, 1, -1);
+
+ pcm_clonereset(d);
}
#ifdef USING_DEVFS
static int
-sysctl_hw_snd_unit(SYSCTL_HANDLER_ARGS)
+sysctl_hw_snd_default_unit(SYSCTL_HANDLER_ARGS)
{
-struct snddev_info *d;
-int error, unit;
+ struct snddev_info *d;
+ int error, unit;
-unit = snd_unit;
-error = sysctl_handle_int(oidp, &unit, sizeof(unit), req);
-if (error == 0 && req->newptr != NULL) {
-if (unit < 0 || unit >= devclass_get_maxunit(pcm_devclass))
-return EINVAL;
-d = devclass_get_softc(pcm_devclass, unit);
-if (d == NULL || SLIST_EMPTY(&d->channels))
-return EINVAL;
-snd_unit = unit;
-}
-return (error);
-}
-SYSCTL_PROC(_hw_snd, OID_AUTO, unit, CTLTYPE_INT | CTLFLAG_RW,
-0, sizeof(int), sysctl_hw_snd_unit, "I", "");
+ unit = snd_unit;
+ error = sysctl_handle_int(oidp, &unit, 0, req);
+ if (error == 0 && req->newptr != NULL) {
+ d = devclass_get_softc(pcm_devclass, unit);
+ if (!PCM_REGISTERED(d) || CHN_EMPTY(d, channels.pcm))
+ return EINVAL;
+ snd_unit = unit;
+ }
+ return (error);
+}
+/* XXX: do we need a way to let the user change the default unit? */
+SYSCTL_PROC(_hw_snd, OID_AUTO, default_unit, CTLTYPE_INT | CTLFLAG_RW,
+ 0, sizeof(int), sysctl_hw_snd_default_unit, "I", "default sound device");
#endif
static int
sysctl_hw_snd_maxautovchans(SYSCTL_HANDLER_ARGS)
{
-struct snddev_info *d;
-int i, v, error;
+ struct snddev_info *d;
+ int i, v, error;
-v = snd_maxautovchans;
-error = sysctl_handle_int(oidp, &v, sizeof(v), req);
-if (error == 0 && req->newptr != NULL) {
-if (v < 0 || v > PCMMAXCHAN)
-return E2BIG;
-if (pcm_devclass != NULL && v != snd_maxautovchans) {
-for (i = 0; i < devclass_get_maxunit(pcm_devclass); i++) {
-d = devclass_get_softc(pcm_devclass, i);
-if (!d)
-continue;
-pcm_setmaxautovchans(d, v);
-}
-}
-snd_maxautovchans = v;
-}
-return (error);
+ v = snd_maxautovchans;
+ error = sysctl_handle_int(oidp, &v, 0, req);
+ if (error == 0 && req->newptr != NULL) {
+ if (v < 0)
+ v = 0;
+ if (v > SND_MAXVCHANS)
+ v = SND_MAXVCHANS;
+ snd_maxautovchans = v;
+ for (i = 0; pcm_devclass != NULL &&
+ i < devclass_get_maxunit(pcm_devclass); i++) {
+ d = devclass_get_softc(pcm_devclass, i);
+ if (!PCM_REGISTERED(d))
+ continue;
+ PCM_ACQUIRE_QUICK(d);
+ pcm_setmaxautovchans(d, v);
+ PCM_RELEASE_QUICK(d);
+ }
+ }
+ return (error);
}
SYSCTL_PROC(_hw_snd, OID_AUTO, maxautovchans, CTLTYPE_INT | CTLFLAG_RW,
-0, sizeof(int), sysctl_hw_snd_maxautovchans, "I", "");
+ 0, sizeof(int), sysctl_hw_snd_maxautovchans, "I", "maximum virtual channel");
struct pcm_channel *
-pcm_chn_create(struct snddev_info *d, struct pcm_channel *parent, kobj_class_t cls, int dir, void *devinfo)
+pcm_chn_create(struct snddev_info *d, struct pcm_channel *parent, kobj_class_t cls, int dir, int num, void *devinfo)
{
-struct snddev_channel *sce;
-struct pcm_channel *ch, *c;
-char *dirs;
-uint32_t flsearch = 0;
-int direction, err, rpnum, *pnum;
-
-switch(dir) {
-case PCMDIR_PLAY:
-dirs = "play";
-direction = PCMDIR_PLAY;
-pnum = &d->playcount;
-break;
-
-case PCMDIR_REC:
-dirs = "record";
-direction = PCMDIR_REC;
-pnum = &d->reccount;
-break;
-
-case PCMDIR_VIRTUAL:
-dirs = "virtual";
-direction = PCMDIR_PLAY;
-pnum = &d->vchancount;
-flsearch = CHN_F_VIRTUAL;
-break;
-
-default:
-return NULL;
-}
-
-ch = malloc(sizeof(*ch), M_DEVBUF, M_WAITOK | M_ZERO);
-if (!ch)
-return NULL;
-
-ch->methods = kobj_create(cls, M_DEVBUF, M_WAITOK);
-if (!ch->methods) {
-free(ch, M_DEVBUF);
-
-return NULL;
-}
-
-snd_mtxlock(d->lock);
-ch->num = 0;
-rpnum = 0;
-SLIST_FOREACH(sce, &d->channels, link) {
-c = sce->channel;
-if (direction != c->direction ||
-(c->flags & CHN_F_VIRTUAL) != flsearch)
-continue;
-if (ch->num == c->num)
-ch->num++;
-else {
-#if 0
-device_printf(d->dev,
-"%s: %s channel numbering screwed (Expect: %d, Got: %d)n",
-__func__, dirs, ch->num, c->num);
-#endif
-goto retry_num_search;
-}
-rpnum++;
-}
-goto retry_num_search_out;
-retry_num_search:
-rpnum = 0;
-SLIST_FOREACH(sce, &d->channels, link) {
-c = sce->channel;
-if (direction != c->direction ||
-(c->flags & CHN_F_VIRTUAL) != flsearch)
-continue;
-if (ch->num == c->num) {
-ch->num++;
-goto retry_num_search;
-}
-rpnum++;
-}
-retry_num_search_out:
-if (*pnum != rpnum) {
-device_printf(d->dev,
-"%s: WARNING: pnum screwed : dirs=%s, pnum=%d, rpnum=%dn",
-__func__, dirs, *pnum, rpnum);
-*pnum = rpnum;
-}
-(*pnum)++;
-snd_mtxunlock(d->lock);
-
-ch->pid = -1;
-ch->parentsnddev = d;
-ch->parentchannel = parent;
-ch->dev = d->dev;
-snprintf(ch->name, CHN_NAMELEN, "%s:%s:%d", device_get_nameunit(ch->dev), dirs, ch->num);
-
-err = chn_init(ch, devinfo, dir, direction);
-if (err) {
-device_printf(d->dev, "chn_init(%s) failed: err = %dn", ch->name, err);
-kobj_delete(ch->methods, M_DEVBUF);
-free(ch, M_DEVBUF);
-snd_mtxlock(d->lock);
-(*pnum)--;
-snd_mtxunlock(d->lock);
-
-return NULL;
-}
+ struct pcm_channel *ch;
+ int direction, err, rpnum, *pnum, max;
+ int udc, device, chan;
+ char *dirs, *devname, buf[CHN_NAMELEN];
+
+ PCM_BUSYASSERT(d);
+ snd_mtxassert(d->lock);
+ KASSERT(num >= -1, ("invalid num=%d", num));
+
+
+ switch (dir) {
+ case PCMDIR_PLAY:
+ dirs = "play";
+ direction = PCMDIR_PLAY;
+ pnum = &d->playcount;
+ device = SND_DEV_DSPHW_PLAY;
+ max = SND_MAXHWCHAN;
+ break;
+ case PCMDIR_PLAY_VIRTUAL:
+ dirs = "virtual";
+ direction = PCMDIR_PLAY;
+ pnum = &d->pvchancount;
+ device = SND_DEV_DSPHW_VPLAY;
+ max = SND_MAXVCHANS;
+ break;
+ case PCMDIR_REC:
+ dirs = "record";
+ direction = PCMDIR_REC;
+ pnum = &d->reccount;
+ device = SND_DEV_DSPHW_REC;
+ max = SND_MAXHWCHAN;
+ break;
+ case PCMDIR_REC_VIRTUAL:
+ dirs = "virtual";
+ direction = PCMDIR_REC;
+ pnum = &d->rvchancount;
+ device = SND_DEV_DSPHW_VREC;
+ max = SND_MAXVCHANS;
+ break;
+ default:
+ return (NULL);
+ }
+
+ chan = (num == -1) ? 0 : num;
+
+ if (*pnum >= max || chan >= max)
+ return (NULL);
+
+ rpnum = 0;
+
+ CHN_FOREACH(ch, d, channels.pcm) {
+ if (CHN_DEV(ch) != device)
+ continue;
+ if (chan == CHN_CHAN(ch)) {
+ if (num != -1) {
+ device_printf(d->dev,
+ "channel num=%d allocated!\n", chan);
+ return (NULL);
+ }
+ chan++;
+ if (chan >= max) {
+ device_printf(d->dev,
+ "chan=%d > %d\n", chan, max);
+ return (NULL);
+ }
+ }
+ rpnum++;
+ }
+
+ if (*pnum != rpnum) {
+ device_printf(d->dev,
+ "%s(): WARNING: pnum screwed : dirs=%s pnum=%d rpnum=%d\n",
+ __func__, dirs, *pnum, rpnum);
+ return (NULL);
+ }
+
+ udc = snd_mkunit(device_get_unit(d->dev), device, chan);
+ devname = dsp_unit2name(buf, sizeof(buf), udc);
+
+ if (devname == NULL) {
+ device_printf(d->dev,
+ "Failed to query device name udc=0x%08x\n", udc);
+ return (NULL);
+ }
+
+ pcm_unlock(d);
+ ch = malloc(sizeof(*ch), M_DEVBUF, M_WAITOK | M_ZERO);
+ ch->methods = kobj_create(cls, M_DEVBUF, M_WAITOK | M_ZERO);
+ ch->unit = udc;
+ ch->pid = -1;
+ ch->parentsnddev = d;
+ ch->parentchannel = parent;
+ ch->dev = d->dev;
+ ch->trigger = PCMTRIG_STOP;
+ snprintf(ch->name, sizeof(ch->name), "%s:%s:%s",
+ device_get_nameunit(ch->dev), dirs, devname);
+
+ err = chn_init(ch, devinfo, dir, direction);
+ pcm_lock(d);
+ if (err) {
+ device_printf(d->dev, "chn_init(%s) failed: err = %d\n",
+ ch->name, err);
+ kobj_delete(ch->methods, M_DEVBUF);
+ free(ch, M_DEVBUF);
+ return (NULL);
+ }
-return ch;
+ return (ch);
}
int
pcm_chn_destroy(struct pcm_channel *ch)
{
-struct snddev_info *d;
-int err;
+ struct snddev_info *d;
+ int err;
-d = ch->parentsnddev;
-err = chn_kill(ch);
-if (err) {
-device_printf(d->dev, "chn_kill(%s) failed, err = %dn", ch->name, err);
-return err;
-}
+ d = ch->parentsnddev;
+ PCM_BUSYASSERT(d);
+
+ err = chn_kill(ch);
+ if (err) {
+ device_printf(ch->dev, "chn_kill(%s) failed, err = %d\n",
+ ch->name, err);
+ return (err);
+ }
-kobj_delete(ch->methods, M_DEVBUF);
-free(ch, M_DEVBUF);
+ kobj_delete(ch->methods, M_DEVBUF);
+ free(ch, M_DEVBUF);
-return 0;
+ return (0);
}
int
pcm_chn_add(struct snddev_info *d, struct pcm_channel *ch)
{
-struct snddev_channel *sce, *tmp, *after;
-unsigned rdevcount;
-int device = device_get_unit(d->dev);
-size_t namelen;
+ struct pcm_channel *tmp, *after;
+ int num;
-/*
-* Note it's confusing nomenclature.
-* dev_t
-* device -> pcm_device
-* unit -> pcm_channel
-* channel -> snddev_channel
-* device_t
-* unit -> pcm_device
-*/
+ PCM_BUSYASSERT(d);
+ snd_mtxassert(d->lock);
+ KASSERT(ch != NULL && (ch->direction == PCMDIR_PLAY ||
+ ch->direction == PCMDIR_REC), ("Invalid pcm channel"));
+
+ after = NULL;
+ tmp = NULL;
+ num = 0;
+
+ /*
+ * Look for possible device collision.
+ */
+ CHN_FOREACH(tmp, d, channels.pcm) {
+ if (tmp->unit == ch->unit) {
+ device_printf(d->dev, "%s(): Device collision "
+ "old=%p new=%p devunit=0x%08x\n",
+ __func__, tmp, ch, ch->unit);
+ return (ENODEV);
+ }
+ if (CHN_DEV(tmp) < CHN_DEV(ch)) {
+ if (num == 0)
+ after = tmp;
+ continue;
+ } else if (CHN_DEV(tmp) > CHN_DEV(ch))
+ break;
+ num++;
+ if (CHN_CHAN(tmp) < CHN_CHAN(ch))
+ after = tmp;
+ else if (CHN_CHAN(tmp) > CHN_CHAN(ch))
+ break;
+ }
+
+ if (after != NULL) {
+ CHN_INSERT_AFTER(after, ch, channels.pcm);
+ } else {
+ CHN_INSERT_HEAD(d, ch, channels.pcm);
+ }
+
+ switch (CHN_DEV(ch)) {
+ case SND_DEV_DSPHW_PLAY:
+ d->playcount++;
+ break;
+ case SND_DEV_DSPHW_VPLAY:
+ d->pvchancount++;
+ break;
+ case SND_DEV_DSPHW_REC:
+ d->reccount++;
+ break;
+ case SND_DEV_DSPHW_VREC:
+ d->rvchancount++;
+ break;
+ default:
+ break;
+ }
-sce = malloc(sizeof(*sce), M_DEVBUF, M_WAITOK | M_ZERO);
-if (!sce) {
-return ENOMEM;
-}
+ d->devcount++;
-snd_mtxlock(d->lock);
-sce->channel = ch;
-sce->chan_num = 0;
-rdevcount = 0;
-after = NULL;
-SLIST_FOREACH(tmp, &d->channels, link) {
-if (sce->chan_num == tmp->chan_num)
-sce->chan_num++;
-else {
-#if 0
-device_printf(d->dev,
-"%s: cdev numbering screwed (Expect: %d, Got: %d)n",
-__func__, sce->chan_num, tmp->chan_num);
-#endif
-goto retry_chan_num_search;
-}
-after = tmp;
-rdevcount++;
-}
-goto retry_chan_num_search_out;
-retry_chan_num_search:
-/*
-* Look for possible channel numbering collision. This may not
-* be optimized, but it will ensure that no collision occured.
-* Can be considered cheap since none of the locking/unlocking
-* operations involved.
-*/
-rdevcount = 0;
-after = NULL;
-SLIST_FOREACH(tmp, &d->channels, link) {
-if (sce->chan_num == tmp->chan_num) {
-sce->chan_num++;
-goto retry_chan_num_search;
-}
-if (sce->chan_num > tmp->chan_num)
-after = tmp;
-rdevcount++;
-}
-retry_chan_num_search_out:
-/*
-* Don't overflow PCMMKMINOR / PCMMAXCHAN.
-*/
-if (sce->chan_num > PCMMAXCHAN) {
-snd_mtxunlock(d->lock);
-device_printf(d->dev,
-"%s: WARNING: sce->chan_num overflow! (%d)n",
-__func__, sce->chan_num);
-free(sce, M_DEVBUF);
-return E2BIG;
-}
-if (d->devcount != rdevcount) {
-device_printf(d->dev,
-"%s: WARNING: devcount screwed! d->devcount=%u, rdevcount=%un",
-__func__, d->devcount, rdevcount);
-d->devcount = rdevcount;
-}
-d->devcount++;
-if (after == NULL) {
-SLIST_INSERT_HEAD(&d->channels, sce, link);
-} else {
-SLIST_INSERT_AFTER(after, sce, link);
-}
-#if 0
-if (1) {
-int cnum = 0;
-SLIST_FOREACH(tmp, &d->channels, link) {
-if (cnum != tmp->chan_num)
-device_printf(d->dev,
-"%s: WARNING: inconsistent cdev numbering! (Expect: %d, Got: %d)n",
-__func__, cnum, tmp->chan_num);
-cnum++;
-}
-}
-#endif
-
-namelen = strlen(ch->name);
-if ((CHN_NAMELEN - namelen) > 10) { /* ":dspXX.YYY" */
-snprintf(ch->name + namelen,
-CHN_NAMELEN - namelen, ":dsp%d.%d",
-device, sce->chan_num);
-}
-snd_mtxunlock(d->lock);
-
-/*
-* I will revisit these someday, and nuke it mercilessly..
-*/
-sce->dsp_devt = make_dev(&dsp_cdevsw,
-PCMMKMINOR(device, SND_DEV_DSP, sce->chan_num),
-UID_ROOT, GID_WHEEL, 0666, "dsp%d.%d",
-device, sce->chan_num);
-
-sce->dspW_devt = make_dev(&dsp_cdevsw,
-PCMMKMINOR(device, SND_DEV_DSP16, sce->chan_num),
-UID_ROOT, GID_WHEEL, 0666, "dspW%d.%d",
-device, sce->chan_num);
-
-sce->audio_devt = make_dev(&dsp_cdevsw,
-PCMMKMINOR(device, SND_DEV_AUDIO, sce->chan_num),
-UID_ROOT, GID_WHEEL, 0666, "audio%d.%d",
-device, sce->chan_num);
-
-if (ch->direction == PCMDIR_REC)
-sce->dspr_devt = make_dev(&dsp_cdevsw,
-PCMMKMINOR(device, SND_DEV_DSPREC,
-sce->chan_num), UID_ROOT, GID_WHEEL,
-0666, "dspr%d.%d", device, sce->chan_num);
-
-return 0;
+ return (0);
}
int
pcm_chn_remove(struct snddev_info *d, struct pcm_channel *ch)
{
-struct snddev_channel *sce;
-#if 0
-int ourlock;
+ struct pcm_channel *tmp;
-ourlock = 0;
-if (!mtx_owned(d->lock)) {
-snd_mtxlock(d->lock);
-ourlock = 1;
-}
-#endif
+ PCM_BUSYASSERT(d);
+ snd_mtxassert(d->lock);
-SLIST_FOREACH(sce, &d->channels, link) {
-if (sce->channel == ch)
-goto gotit;
-}
-#if 0
-if (ourlock)
-snd_mtxunlock(d->lock);
-#endif
-return EINVAL;
-gotit:
-SLIST_REMOVE(&d->channels, sce, snddev_channel, link);
-
-if (ch->flags & CHN_F_VIRTUAL)
-d->vchancount--;
-else if (ch->direction == PCMDIR_REC)
-d->reccount--;
-else
-d->playcount--;
+ tmp = NULL;
-#if 0
-if (ourlock)
-snd_mtxunlock(d->lock);
-#endif
-free(sce, M_DEVBUF);
+ CHN_FOREACH(tmp, d, channels.pcm) {
+ if (tmp == ch)
+ break;
+ }
+
+ if (tmp != ch)
+ return (EINVAL);
+
+ CHN_REMOVE(d, ch, channels.pcm);
+
+ switch (CHN_DEV(ch)) {
+ case SND_DEV_DSPHW_PLAY:
+ d->playcount--;
+ break;
+ case SND_DEV_DSPHW_VPLAY:
+ d->pvchancount--;
+ break;
+ case SND_DEV_DSPHW_REC:
+ d->reccount--;
+ break;
+ case SND_DEV_DSPHW_VREC:
+ d->rvchancount--;
+ break;
+ default:
+ break;
+ }
-return 0;
+ d->devcount--;
+
+ return (0);
}
int
pcm_addchan(device_t dev, int dir, kobj_class_t cls, void *devinfo)
{
-struct snddev_info *d = device_get_softc(dev);
-struct pcm_channel *ch;
-int err;
-
-ch = pcm_chn_create(d, NULL, cls, dir, devinfo);
-if (!ch) {
-device_printf(d->dev, "pcm_chn_create(%s, %d, %p) failedn", cls->name, dir, devinfo);
-return ENODEV;
-}
-
-err = pcm_chn_add(d, ch);
-if (err) {
-device_printf(d->dev, "pcm_chn_add(%s) failed, err=%dn", ch->name, err);
-pcm_chn_destroy(ch);
-return err;
-}
+ struct snddev_info *d = device_get_softc(dev);
+ struct pcm_channel *ch;
+ int err;
+
+ PCM_BUSYASSERT(d);
+
+ pcm_lock(d);
+ ch = pcm_chn_create(d, NULL, cls, dir, -1, devinfo);
+ if (!ch) {
+ device_printf(d->dev, "pcm_chn_create(%s, %d, %p) failed\n",
+ cls->name, dir, devinfo);
+ pcm_unlock(d);
+ return (ENODEV);
+ }
+
+ err = pcm_chn_add(d, ch);
+ pcm_unlock(d);
+ if (err) {
+ device_printf(d->dev, "pcm_chn_add(%s) failed, err=%d\n",
+ ch->name, err);
+ pcm_chn_destroy(ch);
+ }
-return err;
+ return (err);
}
static int
pcm_killchan(device_t dev)
{
-struct snddev_info *d = device_get_softc(dev);
-struct snddev_channel *sce;
-struct pcm_channel *ch;
-int error = 0;
-
-sce = SLIST_FIRST(&d->channels);
-ch = sce->channel;
-
-error = pcm_chn_remove(d, sce->channel);
-if (error)
-return (error);
-return (pcm_chn_destroy(ch));
+ struct snddev_info *d = device_get_softc(dev);
+ struct pcm_channel *ch;
+ int error;
+
+ PCM_BUSYASSERT(d);
+
+ ch = CHN_FIRST(d, channels.pcm);
+
+ pcm_lock(d);
+ error = pcm_chn_remove(d, ch);
+ pcm_unlock(d);
+ if (error)
+ return (error);
+ return (pcm_chn_destroy(ch));
}
int
pcm_setstatus(device_t dev, char *str)
{
-struct snddev_info *d = device_get_softc(dev);
+ struct snddev_info *d = device_get_softc(dev);
+
+ PCM_BUSYASSERT(d);
+
+ if (d->playcount == 0 || d->reccount == 0)
+ d->flags |= SD_F_SIMPLEX;
+
+ if ((d->playcount > 0 || d->reccount > 0) &&
+ !(d->flags & SD_F_AUTOVCHAN)) {
+ d->flags |= SD_F_AUTOVCHAN;
+ vchan_initsys(dev);
+ }
+
+ pcm_setmaxautovchans(d, snd_maxautovchans);
+
+ strlcpy(d->status, str, SND_STATUSLEN);
-snd_mtxlock(d->lock);
-strncpy(d->status, str, SND_STATUSLEN);
-snd_mtxunlock(d->lock);
-if (snd_maxautovchans > 0)
-pcm_setvchans(d, 1);
-return 0;
+ pcm_lock(d);
+
+ /* Last stage, enable cloning. */
+ if (d->clones != NULL)
+ (void)snd_clone_enable(d->clones);
+
+ /* Done, we're ready.. */
+ d->flags |= SD_F_REGISTERED;
+
+ PCM_RELEASE(d);
+
+ pcm_unlock(d);
+
+ if (snd_unit < 0 || snd_unit_auto != 0)
+ snd_unit = device_get_unit(dev);
+
+ return (0);
}
uint32_t
pcm_getflags(device_t dev)
{
-struct snddev_info *d = device_get_softc(dev);
+ struct snddev_info *d = device_get_softc(dev);
-return d->flags;
+ return d->flags;
}
void
pcm_setflags(device_t dev, uint32_t val)
{
-struct snddev_info *d = device_get_softc(dev);
+ struct snddev_info *d = device_get_softc(dev);
-d->flags = val;
+ d->flags = val;
}
void *
pcm_getdevinfo(device_t dev)
{
-struct snddev_info *d = device_get_softc(dev);
+ struct snddev_info *d = device_get_softc(dev);
-return d->devinfo;
+ return d->devinfo;
}
unsigned int
-pcm_getbuffersize(device_t dev, unsigned int min, unsigned int deflt, unsigned int max)
+pcm_getbuffersize(device_t dev, unsigned int minbufsz, unsigned int deflt, unsigned int maxbufsz)
{
-struct snddev_info *d = device_get_softc(dev);
-int sz, x;
+ struct snddev_info *d = device_get_softc(dev);
+ int sz, x;
-sz = 0;
-if (resource_int_value(device_get_name(dev), device_get_unit(dev), "buffersize", &sz) == 0) {
-x = sz;
-RANGE(sz, min, max);
-if (x != sz)
-device_printf(dev, "'buffersize=%d' hint is out of range (%d-%d), using %dn", x, min, max, sz);
-x = min;
-while (x < sz)
-x <<= 1;
-if (x > sz)
-x >>= 1;
-if (x != sz) {
-device_printf(dev, "'buffersize=%d' hint is not a power of 2, using %dn", sz, x);
-sz = x;
-}
-} else {
-sz = deflt;
-}
+ sz = 0;
+ if (resource_int_value(device_get_name(dev), device_get_unit(dev), "buffersize", &sz) == 0) {
+ x = sz;
+ RANGE(sz, minbufsz, maxbufsz);
+ if (x != sz)
+ device_printf(dev, "'buffersize=%d' hint is out of range (%d-%d), using %d\n", x, minbufsz, maxbufsz, sz);
+ x = minbufsz;
+ while (x < sz)
+ x <<= 1;
+ if (x > sz)
+ x >>= 1;
+ if (x != sz) {
+ device_printf(dev, "'buffersize=%d' hint is not a power of 2, using %d\n", sz, x);
+ sz = x;
+ }
+ } else {
+ sz = deflt;
+ }
-d->bufsz = sz;
+ d->bufsz = sz;
-return sz;
+ return sz;
}
-int
-pcm_register(device_t dev, void *devinfo, int numplay, int numrec)
+#if defined(SND_DYNSYSCTL) && defined(SND_DEBUG)
+static int
+sysctl_dev_pcm_clone_flags(SYSCTL_HANDLER_ARGS)
{
-struct snddev_info *d = device_get_softc(dev);
+ struct snddev_info *d;
+ uint32_t flags;
+ int err;
+
+ d = oidp->oid_arg1;
+ if (!PCM_REGISTERED(d) || d->clones == NULL)
+ return (ENODEV);
+
+ PCM_ACQUIRE_QUICK(d);
+
+ flags = snd_clone_getflags(d->clones);
+ err = sysctl_handle_int(oidp, &flags, 0, req);
+
+ if (err == 0 && req->newptr != NULL) {
+ if (flags & ~SND_CLONE_MASK)
+ err = EINVAL;
+ else
+ (void)snd_clone_setflags(d->clones, flags);
+ }
-if (pcm_veto_load) {
-device_printf(dev, "disabled due to an error while initialising: %dn", pcm_veto_load);
+ PCM_RELEASE_QUICK(d);
-return EINVAL;
+ return (err);
}
-d->lock = snd_mtxcreate(device_get_nameunit(dev), "sound cdev");
+static int
+sysctl_dev_pcm_clone_deadline(SYSCTL_HANDLER_ARGS)
+{
+ struct snddev_info *d;
+ int err, deadline;
-#if 0
-/*
-* d->flags should be cleared by the allocator of the softc.
-* We cannot clear this field here because several devices set
-* this flag before calling pcm_register().
-*/
-d->flags = 0;
-#endif
-d->dev = dev;
-d->devinfo = devinfo;
-d->devcount = 0;
-d->reccount = 0;
-d->playcount = 0;
-d->vchancount = 0;
-d->inprog = 0;
+ d = oidp->oid_arg1;
+ if (!PCM_REGISTERED(d) || d->clones == NULL)
+ return (ENODEV);
-SLIST_INIT(&d->channels);
+ PCM_ACQUIRE_QUICK(d);
-if ((numplay == 0 || numrec == 0) && numplay != numrec)
-d->flags |= SD_F_SIMPLEX;
+ deadline = snd_clone_getdeadline(d->clones);
+ err = sysctl_handle_int(oidp, &deadline, 0, req);
-d->fakechan = fkchan_setup(dev);
-chn_init(d->fakechan, NULL, 0, 0);
+ if (err == 0 && req->newptr != NULL) {
+ if (deadline < 0)
+ err = EINVAL;
+ else
+ (void)snd_clone_setdeadline(d->clones, deadline);
+ }
-#ifdef SND_DYNSYSCTL
-sysctl_ctx_init(&d->sysctl_tree);
-d->sysctl_tree_top = SYSCTL_ADD_NODE(&d->sysctl_tree,
-SYSCTL_STATIC_CHILDREN(_hw_snd), OID_AUTO,
-device_get_nameunit(dev), CTLFLAG_RD, 0, "");
-if (d->sysctl_tree_top == NULL) {
-sysctl_ctx_free(&d->sysctl_tree);
-goto no;
-}
-SYSCTL_ADD_INT(snd_sysctl_tree(dev), SYSCTL_CHILDREN(snd_sysctl_tree_top(dev)),
-OID_AUTO, "buffersize", CTLFLAG_RD, &d->bufsz, 0, "");
-#endif
-if (numplay > 0) {
-d->flags |= SD_F_AUTOVCHAN;
-vchan_initsys(dev);
+ PCM_RELEASE_QUICK(d);
+
+ return (err);
}
-sndstat_register(dev, d->status, sndstat_prepare_pcm);
-return 0;
-no:
-snd_mtxfree(d->lock);
-return ENXIO;
+static int
+sysctl_dev_pcm_clone_gc(SYSCTL_HANDLER_ARGS)
+{
+ struct snddev_info *d;
+ int err, val;
+
+ d = oidp->oid_arg1;
+ if (!PCM_REGISTERED(d) || d->clones == NULL)
+ return (ENODEV);
+
+ val = 0;
+ err = sysctl_handle_int(oidp, &val, 0, req);
+
+ if (err == 0 && req->newptr != NULL && val != 0) {
+ PCM_ACQUIRE_QUICK(d);
+ val = snd_clone_gc(d->clones);
+ PCM_RELEASE_QUICK(d);
+ if (bootverbose != 0 || snd_verbose > 3)
+ device_printf(d->dev, "clone gc: pruned=%d\n", val);
+ }
+
+ return (err);
}
+static int
+sysctl_hw_snd_clone_gc(SYSCTL_HANDLER_ARGS)
+{
+ struct snddev_info *d;
+ int i, err, val;
+
+ val = 0;
+ err = sysctl_handle_int(oidp, &val, 0, req);
+
+ if (err == 0 && req->newptr != NULL && val != 0) {
+ for (i = 0; pcm_devclass != NULL &&
+ i < devclass_get_maxunit(pcm_devclass); i++) {
+ d = devclass_get_softc(pcm_devclass, i);
+ if (!PCM_REGISTERED(d) || d->clones == NULL)
+ continue;
+ PCM_ACQUIRE_QUICK(d);
+ val = snd_clone_gc(d->clones);
+ PCM_RELEASE_QUICK(d);
+ if (bootverbose != 0 || snd_verbose > 3)
+ device_printf(d->dev, "clone gc: pruned=%d\n",
+ val);
+ }
+ }
+
+ return (err);
+}
+SYSCTL_PROC(_hw_snd, OID_AUTO, clone_gc, CTLTYPE_INT | CTLFLAG_RW,
+ 0, sizeof(int), sysctl_hw_snd_clone_gc, "I",
+ "global clone garbage collector");
+#endif
+
int
-pcm_unregister(device_t dev)
+pcm_register(device_t dev, void *devinfo, int numplay, int numrec)
{
-struct snddev_info *d = device_get_softc(dev);
-struct snddev_channel *sce;
-struct pcmchan_children *pce;
-struct pcm_channel *ch;
-
-if (sndstat_acquire() != 0) {
-device_printf(dev, "unregister: sndstat busyn");
-return EBUSY;
-}
-
-snd_mtxlock(d->lock);
-if (d->inprog) {
-device_printf(dev, "unregister: operation in progressn");
-snd_mtxunlock(d->lock);
-sndstat_release();
-return EBUSY;
-}
-
-SLIST_FOREACH(sce, &d->channels, link) {
-ch = sce->channel;
-if (ch->refcount > 0) {
-device_printf(dev, "unregister: channel %s busy (pid %d)n", ch->name, ch->pid);
-snd_mtxunlock(d->lock);
-sndstat_release();
-return EBUSY;
-}
-}
+ struct snddev_info *d;
-if (mixer_uninit(dev) == EBUSY) {
-device_printf(dev, "unregister: mixer busyn");
-snd_mtxunlock(d->lock);
-sndstat_release();
-return EBUSY;
-}
-
-SLIST_FOREACH(sce, &d->channels, link) {
-if (sce->dsp_devt) {
-destroy_dev(sce->dsp_devt);
-sce->dsp_devt = NULL;
-}
-if (sce->dspW_devt) {
-destroy_dev(sce->dspW_devt);
-sce->dspW_devt = NULL;
-}
-if (sce->audio_devt) {
-destroy_dev(sce->audio_devt);
-sce->audio_devt = NULL;
-}
-if (sce->dspr_devt) {
-destroy_dev(sce->dspr_devt);
-sce->dspr_devt = NULL;
-}
-d->devcount--;
-ch = sce->channel;
-if (ch == NULL)
-continue;
-pce = SLIST_FIRST(&ch->children);
-while (pce != NULL) {
+ if (pcm_veto_load) {
+ device_printf(dev, "disabled due to an error while initialising: %d\n", pcm_veto_load);
+
+ return EINVAL;
+ }
+
+ if (device_get_unit(dev) > PCMMAXUNIT) {
+ device_printf(dev, "PCMMAXUNIT reached : unit=%d > %d\n",
+ device_get_unit(dev), PCMMAXUNIT);
+ device_printf(dev,
+ "Use 'hw.snd.maxunit' tunable to raise the limit.\n");
+ return ENODEV;
+ }
+
+ d = device_get_softc(dev);
+ d->dev = dev;
+ d->lock = snd_mtxcreate(device_get_nameunit(dev), "sound cdev");
+ cv_init(&d->cv, device_get_nameunit(dev));
+ PCM_ACQUIRE_QUICK(d);
+ dsp_cdevinfo_init(d);
#if 0
-device_printf(d->dev, "<%s> removing <%s>n",
-ch->name, (pce->channel != NULL) ?
-pce->channel->name : "unknown");
-#endif
-SLIST_REMOVE(&ch->children, pce, pcmchan_children, link);
-free(pce, M_DEVBUF);
-pce = SLIST_FIRST(&ch->children);
-}
-}
+ /*
+ * d->flags should be cleared by the allocator of the softc.
+ * We cannot clear this field here because several devices set
+ * this flag before calling pcm_register().
+ */
+ d->flags = 0;
+#endif
+ d->devinfo = devinfo;
+ d->devcount = 0;
+ d->reccount = 0;
+ d->playcount = 0;
+ d->pvchancount = 0;
+ d->rvchancount = 0;
+ d->pvchanrate = 0;
+ d->pvchanformat = 0;
+ d->rvchanrate = 0;
+ d->rvchanformat = 0;
+ d->inprog = 0;
+
+ /*
+ * Create clone manager, disabled by default. Cloning will be
+ * enabled during final stage of driver iniialization through
+ * pcm_setstatus().
+ */
+ d->clones = snd_clone_create(SND_U_MASK | SND_D_MASK, PCMMAXCLONE,
+ SND_CLONE_DEADLINE_DEFAULT, SND_CLONE_WAITOK |
+ SND_CLONE_GC_ENABLE | SND_CLONE_GC_UNREF |
+ SND_CLONE_GC_LASTREF | SND_CLONE_GC_EXPIRED);
+
+ if (bootverbose != 0 || snd_verbose > 3) {
+ device_printf(dev,
+ "clone manager: deadline=%dms flags=0x%08x\n",
+ snd_clone_getdeadline(d->clones),
+ snd_clone_getflags(d->clones));
+ }
+
+ CHN_INIT(d, channels.pcm);
+ CHN_INIT(d, channels.pcm.busy);
+
+ /* XXX This is incorrect, but lets play along for now. */
+ if ((numplay == 0 || numrec == 0) && numplay != numrec)
+ d->flags |= SD_F_SIMPLEX;
+
+ d->fakechan = fkchan_setup(dev);
+ chn_init(d->fakechan, NULL, 0, 0);
#ifdef SND_DYNSYSCTL
-d->sysctl_tree_top = NULL;
-sysctl_ctx_free(&d->sysctl_tree);
+ sysctl_ctx_init(&d->play_sysctl_ctx);
+ d->play_sysctl_tree = SYSCTL_ADD_NODE(&d->play_sysctl_ctx,
+ SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO, "play",
+ CTLFLAG_RD, 0, "playback channels node");
+ sysctl_ctx_init(&d->rec_sysctl_ctx);
+ d->rec_sysctl_tree = SYSCTL_ADD_NODE(&d->rec_sysctl_ctx,
+ SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO, "rec",
+ CTLFLAG_RD, 0, "record channels node");
+ /* XXX: an user should be able to set this with a control tool, the
+ sysadmin then needs min+max sysctls for this */
+ SYSCTL_ADD_INT(device_get_sysctl_ctx(dev),
+ SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
+ OID_AUTO, "buffersize", CTLFLAG_RD, &d->bufsz, 0, "allocated buffer size");
+#ifdef SND_DEBUG
+ SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev),
+ SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO,
+ "clone_flags", CTLTYPE_UINT | CTLFLAG_RW, d, sizeof(d),
+ sysctl_dev_pcm_clone_flags, "IU",
+ "clone flags");
+ SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev),
+ SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO,
+ "clone_deadline", CTLTYPE_INT | CTLFLAG_RW, d, sizeof(d),
+ sysctl_dev_pcm_clone_deadline, "I",
+ "clone expiration deadline (ms)");
+ SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev),
+ SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO,
+ "clone_gc", CTLTYPE_INT | CTLFLAG_RW, d, sizeof(d),
+ sysctl_dev_pcm_clone_gc, "I",
+ "clone garbage collector");
+#endif
#endif
-#if 0
-SLIST_FOREACH(sce, &d->channels, link) {
-ch = sce->channel;
-if (ch == NULL)
-continue;
-if (!SLIST_EMPTY(&ch->children))
-device_printf(d->dev, "%s: WARNING: <%s> dangling child!n",
-__func__, ch->name);
+ if (numplay > 0 || numrec > 0) {
+ d->flags |= SD_F_AUTOVCHAN;
+ vchan_initsys(dev);
+ }
+
+ sndstat_register(dev, d->status, sndstat_prepare_pcm);
+
+ return 0;
}
-#endif
-while (!SLIST_EMPTY(&d->channels))
-pcm_killchan(dev);
-chn_kill(d->fakechan);
-fkchan_kill(d->fakechan);
+int
+pcm_unregister(device_t dev)
+{
+ struct snddev_info *d;
+ struct pcm_channel *ch;
+ struct thread *td;
+ int i;
+
+ td = curthread;
+ d = device_get_softc(dev);
+
+ if (!PCM_ALIVE(d)) {
+ device_printf(dev, "unregister: device not configured\n");
+ return (0);
+ }
+
+ if (sndstat_acquire(td) != 0) {
+ device_printf(dev, "unregister: sndstat busy\n");
+ return (EBUSY);
+ }
+
+ pcm_lock(d);
+ PCM_WAIT(d);
+
+ if (d->inprog != 0) {
+ device_printf(dev, "unregister: operation in progress\n");
+ pcm_unlock(d);
+ sndstat_release(td);
+ return (EBUSY);
+ }
+
+ PCM_ACQUIRE(d);
+ pcm_unlock(d);
+
+ CHN_FOREACH(ch, d, channels.pcm) {
+ CHN_LOCK(ch);
+ if (ch->refcount > 0) {
+ device_printf(dev,
+ "unregister: channel %s busy (pid %d)\n",
+ ch->name, ch->pid);
+ CHN_UNLOCK(ch);
+ PCM_RELEASE_QUICK(d);
+ sndstat_release(td);
+ return (EBUSY);
+ }
+ CHN_UNLOCK(ch);
+ }
+
+ if (d->clones != NULL) {
+ if (snd_clone_busy(d->clones) != 0) {
+ device_printf(dev, "unregister: clone busy\n");
+ PCM_RELEASE_QUICK(d);
+ sndstat_release(td);
+ return (EBUSY);
+ } else {
+ pcm_lock(d);
+ (void)snd_clone_disable(d->clones);
+ pcm_unlock(d);
+ }
+ }
+
+ if (mixer_uninit(dev) == EBUSY) {
+ device_printf(dev, "unregister: mixer busy\n");
+ pcm_lock(d);
+ if (d->clones != NULL)
+ (void)snd_clone_enable(d->clones);
+ PCM_RELEASE(d);
+ pcm_unlock(d);
+ sndstat_release(td);
+ return (EBUSY);
+ }
+
+ pcm_lock(d);
+ d->flags |= SD_F_DYING;
+ d->flags &= ~SD_F_REGISTERED;
+ pcm_unlock(d);
+
+ /*
+ * No lock being held, so this thing can be flushed without
+ * stucking into devdrn oblivion.
+ */
+ if (d->clones != NULL) {
+ snd_clone_destroy(d->clones);
+ d->clones = NULL;
+ }
-#if 0
-device_printf(d->dev, "%s: devcount=%u, playcount=%u, "
-"reccount=%u, vchancount=%un",
-__func__, d->devcount, d->playcount, d->reccount,
-d->vchancount);
-#endif
-snd_mtxunlock(d->lock);
-snd_mtxfree(d->lock);
-sndstat_unregister(dev);
-sndstat_release();
-return 0;
+#ifdef SND_DYNSYSCTL
+ if (d->play_sysctl_tree != NULL) {
+ sysctl_ctx_free(&d->play_sysctl_ctx);
+ d->play_sysctl_tree = NULL;
+ }
+ if (d->rec_sysctl_tree != NULL) {
+ sysctl_ctx_free(&d->rec_sysctl_ctx);
+ d->rec_sysctl_tree = NULL;
+ }
+#endif
+
+ while (!CHN_EMPTY(d, channels.pcm))
+ pcm_killchan(dev);
+
+ chn_kill(d->fakechan);
+ fkchan_kill(d->fakechan);
+
+ dsp_cdevinfo_flush(d);
+
+ pcm_lock(d);
+ PCM_RELEASE(d);
+ cv_destroy(&d->cv);
+ pcm_unlock(d);
+ snd_mtxfree(d->lock);
+ sndstat_unregister(dev);
+ sndstat_release(td);
+
+ if (snd_unit == device_get_unit(dev)) {
+ /*
+ * Reassign default unit to the next available dev, but
+ * first, reset snd_unit to something ridiculous.
+ */
+ snd_unit = -1;
+ for (i = 0; pcm_devclass != NULL &&
+ i < devclass_get_maxunit(pcm_devclass); i++) {
+ if (device_get_unit(dev) == i)
+ continue;
+ d = devclass_get_softc(pcm_devclass, i);
+ if (PCM_REGISTERED(d)) {
+ snd_unit = i;
+ break;
+ }
+ }
+ }
+
+ return (0);
}
/************************************************************************/
@@ -991,108 +1231,96 @@
static int
sndstat_prepare_pcm(struct sbuf *s, device_t dev, int verbose)
{
-struct snddev_info *d;
-struct snddev_channel *sce;
-struct pcm_channel *c;
-struct pcm_feeder *f;
-int pc, rc, vc;
-
-if (verbose < 1)
-return 0;
-
-d = device_get_softc(dev);
-if (!d)
-return ENXIO;
-
-snd_mtxlock(d->lock);
-if (!SLIST_EMPTY(&d->channels)) {
-pc = rc = vc = 0;
-SLIST_FOREACH(sce, &d->channels, link) {
-c = sce->channel;
-if (c->direction == PCMDIR_PLAY) {
-if (c->flags & CHN_F_VIRTUAL)
-vc++;
-else
-pc++;
-} else
-rc++;
-}
-sbuf_printf(s, " (%dp/%dr/%dv channels%s%s)", d->playcount, d->reccount, d->vchancount,
-(d->flags & SD_F_SIMPLEX)? "" : " duplex",
+ struct snddev_info *d;
+ struct pcm_channel *c;
+ struct pcm_feeder *f;
+
+ if (verbose < 1)
+ return 0;
+
+ d = device_get_softc(dev);
+ if (!d)
+ return ENXIO;
+
+ PCM_BUSYASSERT(d);
+
+ if (CHN_EMPTY(d, channels.pcm)) {
+ sbuf_printf(s, " (mixer only)");
+ return 0;
+ }
+
+ sbuf_printf(s, " (%dp:%dv/%dr:%dv channels%s%s)",
+ d->playcount, d->pvchancount,
+ d->reccount, d->rvchancount,
+ (d->flags & SD_F_SIMPLEX)? "" : " duplex",
#ifdef USING_DEVFS
-(device_get_unit(dev) == snd_unit)? " default" : ""
+ (device_get_unit(dev) == snd_unit)? " default" : ""
#else
-""
+ ""
#endif
-);
+ );
+
+ if (verbose <= 1)
+ return 0;
-if (verbose <= 1) {
-snd_mtxunlock(d->lock);
-return 0;
-}
-
-SLIST_FOREACH(sce, &d->channels, link) {
-c = sce->channel;
-
-KASSERT(c->bufhard != NULL && c->bufsoft != NULL,
-("hosed pcm channel setup"));
-
-sbuf_printf(s, "nt");
-
-/* it would be better to indent child channels */
-sbuf_printf(s, "%s[%s]: ", c->parentchannel? c->parentchannel->name : "", c->name);
-sbuf_printf(s, "spd %d", c->speed);
-if (c->speed != sndbuf_getspd(c->bufhard))
-sbuf_printf(s, "/%d", sndbuf_getspd(c->bufhard));
-sbuf_printf(s, ", fmt 0x%08x", c->format);
-if (c->format != sndbuf_getfmt(c->bufhard))
-sbuf_printf(s, "/0x%08x", sndbuf_getfmt(c->bufhard));
-sbuf_printf(s, ", flags 0x%08x, 0x%08x", c->flags, c->feederflags);
-if (c->pid != -1)
-sbuf_printf(s, ", pid %d", c->pid);
-sbuf_printf(s, "nt");
-
-sbuf_printf(s, "interrupts %d, ", c->interrupts);
-if (c->direction == PCMDIR_REC)
-sbuf_printf(s, "overruns %d, hfree %d, sfree %d [b:%d/%d/%d|bs:%d/%d/%d]",
-c->xruns, sndbuf_getfree(c->bufhard), sndbuf_getfree(c->bufsoft),
-sndbuf_getsize(c->bufhard), sndbuf_getblksz(c->bufhard),
-sndbuf_getblkcnt(c->bufhard),
-sndbuf_getsize(c->bufsoft), sndbuf_getblksz(c->bufsoft),
-sndbuf_getblkcnt(c->bufsoft));
-else
-sbuf_printf(s, "underruns %d, ready %d [b:%d/%d/%d|bs:%d/%d/%d]",
-c->xruns, sndbuf_getready(c->bufsoft),
-sndbuf_getsize(c->bufhard), sndbuf_getblksz(c->bufhard),
-sndbuf_getblkcnt(c->bufhard),
-sndbuf_getsize(c->bufsoft), sndbuf_getblksz(c->bufsoft),
-sndbuf_getblkcnt(c->bufsoft));
-sbuf_printf(s, "nt");
-
-sbuf_printf(s, "{%s}", (c->direction == PCMDIR_REC)? "hardware" : "userland");
-sbuf_printf(s, " -> ");
-f = c->feeder;
-while (f->source != NULL)
-f = f->source;
-while (f != NULL) {
-sbuf_printf(s, "%s", f->class->name);
-if (f->desc->type == FEEDER_FMT)
-sbuf_printf(s, "(0x%08x -> 0x%08x)", f->desc->in, f->desc->out);
-if (f->desc->type == FEEDER_RATE)
-sbuf_printf(s, "(%d -> %d)", FEEDER_GET(f, FEEDRATE_SRC), FEEDER_GET(f, FEEDRATE_DST));
-if (f->desc->type == FEEDER_ROOT || f->desc->type == FEEDER_MIXER ||
-f->desc->type == FEEDER_VOLUME)
-sbuf_printf(s, "(0x%08x)", f->desc->out);
-sbuf_printf(s, " -> ");
-f = f->parent;
-}
-sbuf_printf(s, "{%s}", (c->direction == PCMDIR_REC)? "userland" : "hardware");
-}
-} else
-sbuf_printf(s, " (mixer only)");
-snd_mtxunlock(d->lock);
+ CHN_FOREACH(c, d, channels.pcm) {
-return 0;
+ KASSERT(c->bufhard != NULL && c->bufsoft != NULL,
+ ("hosed pcm channel setup"));
+
+ sbuf_printf(s, "\n\t");
+
+ /* it would be better to indent child channels */
+ sbuf_printf(s, "%s[%s]: ", c->parentchannel? c->parentchannel->name : "", c->name);
+ sbuf_printf(s, "spd %d", c->speed);
+ if (c->speed != sndbuf_getspd(c->bufhard))
+ sbuf_printf(s, "/%d", sndbuf_getspd(c->bufhard));
+ sbuf_printf(s, ", fmt 0x%08x", c->format);
+ if (c->format != sndbuf_getfmt(c->bufhard))
+ sbuf_printf(s, "/0x%08x", sndbuf_getfmt(c->bufhard));
+ sbuf_printf(s, ", flags 0x%08x, 0x%08x", c->flags, c->feederflags);
+ if (c->pid != -1)
+ sbuf_printf(s, ", pid %d", c->pid);
+ sbuf_printf(s, "\n\t");
+
+ sbuf_printf(s, "interrupts %d, ", c->interrupts);
+ if (c->direction == PCMDIR_REC)
+ sbuf_printf(s, "overruns %d, feed %u, hfree %d, sfree %d [b:%d/%d/%d|bs:%d/%d/%d]",
+ c->xruns, c->feedcount, sndbuf_getfree(c->bufhard), sndbuf_getfree(c->bufsoft),
+ sndbuf_getsize(c->bufhard), sndbuf_getblksz(c->bufhard),
+ sndbuf_getblkcnt(c->bufhard),
+ sndbuf_getsize(c->bufsoft), sndbuf_getblksz(c->bufsoft),
+ sndbuf_getblkcnt(c->bufsoft));
+ else
+ sbuf_printf(s, "underruns %d, feed %u, ready %d [b:%d/%d/%d|bs:%d/%d/%d]",
+ c->xruns, c->feedcount, sndbuf_getready(c->bufsoft),
+ sndbuf_getsize(c->bufhard), sndbuf_getblksz(c->bufhard),
+ sndbuf_getblkcnt(c->bufhard),
+ sndbuf_getsize(c->bufsoft), sndbuf_getblksz(c->bufsoft),
+ sndbuf_getblkcnt(c->bufsoft));
+ sbuf_printf(s, "\n\t");
+
+ sbuf_printf(s, "{%s}", (c->direction == PCMDIR_REC)? "hardware" : "userland");
+ sbuf_printf(s, " -> ");
+ f = c->feeder;
+ while (f->source != NULL)
+ f = f->source;
+ while (f != NULL) {
+ sbuf_printf(s, "%s", f->class->name);
+ if (f->desc->type == FEEDER_FMT)
+ sbuf_printf(s, "(0x%08x -> 0x%08x)", f->desc->in, f->desc->out);
+ if (f->desc->type == FEEDER_RATE)
+ sbuf_printf(s, "(%d -> %d)", FEEDER_GET(f, FEEDRATE_SRC), FEEDER_GET(f, FEEDRATE_DST));
+ if (f->desc->type == FEEDER_ROOT || f->desc->type == FEEDER_MIXER ||
+ f->desc->type == FEEDER_VOLUME)
+ sbuf_printf(s, "(0x%08x)", f->desc->out);
+ sbuf_printf(s, " -> ");
+ f = f->parent;
+ }
+ sbuf_printf(s, "{%s}", (c->direction == PCMDIR_REC)? "userland" : "hardware");
+ }
+
+ return 0;
}
/************************************************************************/
@@ -1101,30 +1329,197 @@
int
sysctl_hw_snd_vchans(SYSCTL_HANDLER_ARGS)
{
-struct snddev_info *d;
-int err, newcnt;
+ struct snddev_info *d;
+ int direction, vchancount;
+ int err, cnt;
+
+ d = devclass_get_softc(pcm_devclass, VCHAN_SYSCTL_UNIT(oidp->oid_arg1));
+ if (!PCM_REGISTERED(d) || !(d->flags & SD_F_AUTOVCHAN))
+ return (EINVAL);
+
+ pcm_lock(d);
+ PCM_WAIT(d);
+
+ switch (VCHAN_SYSCTL_DIR(oidp->oid_arg1)) {
+ case VCHAN_PLAY:
+ direction = PCMDIR_PLAY;
+ vchancount = d->pvchancount;
+ cnt = d->playcount;
+ break;
+ case VCHAN_REC:
+ direction = PCMDIR_REC;
+ vchancount = d->rvchancount;
+ cnt = d->reccount;
+ break;
+ default:
+ pcm_unlock(d);
+ return (EINVAL);
+ break;
+ }
+
+ if (cnt < 1) {
+ pcm_unlock(d);
+ return (ENODEV);
+ }
+
+ PCM_ACQUIRE(d);
+ pcm_unlock(d);
+
+ cnt = vchancount;
+ err = sysctl_handle_int(oidp, &cnt, 0, req);
+
+ if (err == 0 && req->newptr != NULL && vchancount != cnt) {
+ if (cnt < 0)
+ cnt = 0;
+ if (cnt > SND_MAXVCHANS)
+ cnt = SND_MAXVCHANS;
+ err = pcm_setvchans(d, direction, cnt, -1);
+ }
-d = oidp->oid_arg1;
+ PCM_RELEASE_QUICK(d);
-newcnt = d->vchancount;
-err = sysctl_handle_int(oidp, &newcnt, sizeof(newcnt), req);
+ return err;
+}
+#endif
-if (err == 0 && req->newptr != NULL && d->vchancount != newcnt)
-err = pcm_setvchans(d, newcnt);
+/************************************************************************/
-return err;
+/**
+ * @brief Handle OSSv4 SNDCTL_SYSINFO ioctl.
+ *
+ * @param si Pointer to oss_sysinfo struct where information about the
+ * sound subsystem will be written/copied.
+ *
+ * This routine returns information about the sound system, such as the
+ * current OSS version, number of audio, MIDI, and mixer drivers, etc.
+ * Also includes a bitmask showing which of the above types of devices
+ * are open (busy).
+ *
+ * @note
+ * Calling threads must not hold any snddev_info or pcm_channel locks.
+ *
+ * @author Ryan Beasley <ryanb at FreeBSD.org>
+ */
+void
+sound_oss_sysinfo(oss_sysinfo *si)
+{
+ static char si_product[] = "FreeBSD native OSS ABI";
+ static char si_version[] = __XSTRING(__FreeBSD_version);
+ static int intnbits = sizeof(int) * 8; /* Better suited as macro?
+ Must pester a C guru. */
+
+ struct snddev_info *d;
+ struct pcm_channel *c;
+ int i, j, ncards;
+
+ ncards = 0;
+
+ strlcpy(si->product, si_product, sizeof(si->product));
+ strlcpy(si->version, si_version, sizeof(si->version));
+ si->versionnum = SOUND_VERSION;
+
+ /*
+ * Iterate over PCM devices and their channels, gathering up data
+ * for the numaudios, ncards, and openedaudio fields.
+ */
+ si->numaudios = 0;
+ bzero((void *)&si->openedaudio, sizeof(si->openedaudio));
+
+ j = 0;
+
+ for (i = 0; pcm_devclass != NULL &&
+ i < devclass_get_maxunit(pcm_devclass); i++) {
+ d = devclass_get_softc(pcm_devclass, i);
+ if (!PCM_REGISTERED(d))
+ continue;
+
+ /* XXX Need Giant magic entry ??? */
+
+ /* See note in function's docblock */
+ mtx_assert(d->lock, MA_NOTOWNED);
+ pcm_lock(d);
+
+ si->numaudios += d->devcount;
+ ++ncards;
+
+ CHN_FOREACH(c, d, channels.pcm) {
+ mtx_assert(c->lock, MA_NOTOWNED);
+ CHN_LOCK(c);
+ if (c->flags & CHN_F_BUSY)
+ si->openedaudio[j / intnbits] |=
+ (1 << (j % intnbits));
+ CHN_UNLOCK(c);
+ j++;
+ }
+
+ pcm_unlock(d);
+ }
+
+ si->numsynths = 0; /* OSSv4 docs: this field is obsolete */
+ /**
+ * @todo Collect num{midis,timers}.
+ *
+ * Need access to sound/midi/midi.c::midistat_lock in order
+ * to safely touch midi_devices and get a head count of, well,
+ * MIDI devices. midistat_lock is a global static (i.e., local to
+ * midi.c), but midi_devices is a regular global; should the mutex
+ * be publicized, or is there another way to get this information?
+ *
+ * NB: MIDI/sequencer stuff is currently on hold.
+ */
+ si->nummidis = 0;
+ si->numtimers = 0;
+ si->nummixers = mixer_count;
+ si->numcards = ncards;
+ /* OSSv4 docs: Intended only for test apps; API doesn't
+ really have much of a concept of cards. Shouldn't be
+ used by applications. */
+
+ /**
+ * @todo Fill in "busy devices" fields.
+ *
+ * si->openedmidi = " MIDI devices
+ */
+ bzero((void *)&si->openedmidi, sizeof(si->openedmidi));
+
+ /*
+ * Si->filler is a reserved array, but according to docs each
+ * element should be set to -1.
+ */
+ for (i = 0; i < sizeof(si->filler)/sizeof(si->filler[0]); i++)
+ si->filler[i] = -1;
}
-#endif
/************************************************************************/
static int
sound_modevent(module_t mod, int type, void *data)
{
+ int ret;
#if 0
-return (midi_modevent(mod, type, data));
+ return (midi_modevent(mod, type, data));
#else
-return 0;
+ ret = 0;
+
+ switch(type) {
+ case MOD_LOAD:
+ pcmsg_unrhdr = new_unrhdr(1, INT_MAX, NULL);
+ break;
+ case MOD_UNLOAD:
+ case MOD_SHUTDOWN:
+ ret = sndstat_acquire(curthread);
+ if (ret != 0)
+ break;
+ if (pcmsg_unrhdr != NULL) {
+ delete_unrhdr(pcmsg_unrhdr);
+ pcmsg_unrhdr = NULL;
+ }
+ break;
+ default:
+ ret = EOPNOTSUPP;
+ }
+
+ return ret;
#endif
}
Index: feeder.c
===================================================================
RCS file: /home/cvs/src/sys/dev/sound/pcm/feeder.c,v
retrieving revision 1.3
retrieving revision 1.4
diff -L sys/dev/sound/pcm/feeder.c -L sys/dev/sound/pcm/feeder.c -u -r1.3 -r1.4
--- sys/dev/sound/pcm/feeder.c
+++ sys/dev/sound/pcm/feeder.c
@@ -1,518 +1,825 @@
/*-
-* Copyright (c) 1999 Cameron Grant <cg at freebsd.org>
-* All rights reserved.
-*
-* Redistribution and use in source and binary forms, with or without
-* modification, are permitted provided that the following conditions
-* are met:
-* 1. Redistributions of source code must retain the above copyright
-* notice, this list of conditions and the following disclaimer.
-* 2. Redistributions in binary form must reproduce the above copyright
-* notice, this list of conditions and the following disclaimer in the
-* documentation and/or other materials provided with the distribution.
-*
-* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
-* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
-* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
-* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
-* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
-* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
-* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
-* SUCH DAMAGE.
-*/
+ * Copyright (c) 1999 Cameron Grant <cg at freebsd.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
#include <dev/sound/pcm/sound.h>
#include "feeder_if.h"
-SND_DECLARE_FILE("$MidnightBSD$");
+SND_DECLARE_FILE("$FreeBSD: src/sys/dev/sound/pcm/feeder.c,v 1.44 2007/06/17 15:53:11 ariff Exp $");
MALLOC_DEFINE(M_FEEDER, "feeder", "pcm feeder");
#define MAXFEEDERS 256
#undef FEEDER_DEBUG
-struct feedertab_entry {
-SLIST_ENTRY(feedertab_entry) link;
-struct feeder_class *feederclass;
-struct pcm_feederdesc *desc;
+int feeder_buffersize = FEEDBUFSZ;
+TUNABLE_INT("hw.snd.feeder_buffersize", &feeder_buffersize);
-int idx;
-};
-static SLIST_HEAD(, feedertab_entry) feedertab;
+#ifdef SND_DEBUG
+static int
+sysctl_hw_snd_feeder_buffersize(SYSCTL_HANDLER_ARGS)
+{
+ int i, err, val;
-/*****************************************************************************/
+ val = feeder_buffersize;
+ err = sysctl_handle_int(oidp, &val, 0, req);
-void
-feeder_register(void *p)
-{
-static int feedercnt = 0;
+ if (err != 0 || req->newptr == NULL)
+ return err;
-struct feeder_class *fc = p;
-struct feedertab_entry *fte;
-int i;
+ if (val < FEEDBUFSZ_MIN || val > FEEDBUFSZ_MAX)
+ return EINVAL;
-if (feedercnt == 0) {
-KASSERT(fc->desc == NULL, ("first feeder not root: %s", fc->name));
+ i = 0;
+ while (val >> i)
+ i++;
+ i = 1 << i;
+ if (i > val && (i >> 1) > 0 && (i >> 1) >= ((val * 3) >> 2))
+ i >>= 1;
-SLIST_INIT(&feedertab);
-fte = malloc(sizeof(*fte), M_FEEDER, M_NOWAIT | M_ZERO);
-if (fte == NULL) {
-printf("can't allocate memory for root feeder: %sn",
-fc->name);
+ feeder_buffersize = i;
-return;
+ return err;
}
-fte->feederclass = fc;
-fte->desc = NULL;
-fte->idx = feedercnt;
-SLIST_INSERT_HEAD(&feedertab, fte, link);
-feedercnt++;
+SYSCTL_PROC(_hw_snd, OID_AUTO, feeder_buffersize, CTLTYPE_INT | CTLFLAG_RW,
+ 0, sizeof(int), sysctl_hw_snd_feeder_buffersize, "I",
+ "feeder buffer size");
+#else
+SYSCTL_INT(_hw_snd, OID_AUTO, feeder_buffersize, CTLFLAG_RD,
+ &feeder_buffersize, FEEDBUFSZ, "feeder buffer size");
+#endif
-/* we've got our root feeder so don't veto pcm loading anymore */
-pcm_veto_load = 0;
+struct feedertab_entry {
+ SLIST_ENTRY(feedertab_entry) link;
+ struct feeder_class *feederclass;
+ struct pcm_feederdesc *desc;
-return;
-}
+ int idx;
+};
+static SLIST_HEAD(, feedertab_entry) feedertab;
-KASSERT(fc->desc != NULL, ("feeder '%s' has no descriptor", fc->name));
+/*****************************************************************************/
-/* beyond this point failure is non-fatal but may result in some translations being unavailable */
-i = 0;
-while ((feedercnt < MAXFEEDERS) && (fc->desc[i].type > 0)) {
-/* printf("adding feeder %s, %x -> %xn", fc->name, fc->desc[i].in, fc->desc[i].out); */
-fte = malloc(sizeof(*fte), M_FEEDER, M_NOWAIT | M_ZERO);
-if (fte == NULL) {
-printf("can't allocate memory for feeder '%s', %x -> %xn", fc->name, fc->desc[i].in, fc->desc[i].out);
+void
+feeder_register(void *p)
+{
+ static int feedercnt = 0;
-return;
-}
-fte->feederclass = fc;
-fte->desc = &fc->desc[i];
-fte->idx = feedercnt;
-fte->desc->idx = feedercnt;
-SLIST_INSERT_HEAD(&feedertab, fte, link);
-i++;
-}
-feedercnt++;
-if (feedercnt >= MAXFEEDERS)
-printf("MAXFEEDERS (%d >= %d) exceededn", feedercnt, MAXFEEDERS);
+ struct feeder_class *fc = p;
+ struct feedertab_entry *fte;
+ int i;
+
+ if (feedercnt == 0) {
+ KASSERT(fc->desc == NULL, ("first feeder not root: %s", fc->name));
+
+ SLIST_INIT(&feedertab);
+ fte = malloc(sizeof(*fte), M_FEEDER, M_NOWAIT | M_ZERO);
+ if (fte == NULL) {
+ printf("can't allocate memory for root feeder: %s\n",
+ fc->name);
+
+ return;
+ }
+ fte->feederclass = fc;
+ fte->desc = NULL;
+ fte->idx = feedercnt;
+ SLIST_INSERT_HEAD(&feedertab, fte, link);
+ feedercnt++;
+
+ /* initialize global variables */
+
+ if (snd_verbose < 0 || snd_verbose > 4)
+ snd_verbose = 1;
+
+ /* initialize unit numbering */
+ snd_unit_init();
+ if (snd_unit < 0 || snd_unit > PCMMAXUNIT)
+ snd_unit = -1;
+
+ if (snd_maxautovchans < 0 ||
+ snd_maxautovchans > SND_MAXVCHANS)
+ snd_maxautovchans = 0;
+
+ if (chn_latency < CHN_LATENCY_MIN ||
+ chn_latency > CHN_LATENCY_MAX)
+ chn_latency = CHN_LATENCY_DEFAULT;
+
+ if (chn_latency_profile < CHN_LATENCY_PROFILE_MIN ||
+ chn_latency_profile > CHN_LATENCY_PROFILE_MAX)
+ chn_latency_profile = CHN_LATENCY_PROFILE_DEFAULT;
+
+ if (feeder_buffersize < FEEDBUFSZ_MIN ||
+ feeder_buffersize > FEEDBUFSZ_MAX)
+ feeder_buffersize = FEEDBUFSZ;
+
+ if (feeder_rate_min < FEEDRATE_MIN ||
+ feeder_rate_max < FEEDRATE_MIN ||
+ feeder_rate_min > FEEDRATE_MAX ||
+ feeder_rate_max > FEEDRATE_MAX ||
+ !(feeder_rate_min < feeder_rate_max)) {
+ feeder_rate_min = FEEDRATE_RATEMIN;
+ feeder_rate_max = FEEDRATE_RATEMAX;
+ }
+
+ if (feeder_rate_round < FEEDRATE_ROUNDHZ_MIN ||
+ feeder_rate_round > FEEDRATE_ROUNDHZ_MAX)
+ feeder_rate_round = FEEDRATE_ROUNDHZ;
+
+ if (bootverbose)
+ printf("%s: snd_unit=%d snd_maxautovchans=%d "
+ "latency=%d feeder_buffersize=%d "
+ "feeder_rate_min=%d feeder_rate_max=%d "
+ "feeder_rate_round=%d\n",
+ __func__, snd_unit, snd_maxautovchans,
+ chn_latency, feeder_buffersize,
+ feeder_rate_min, feeder_rate_max,
+ feeder_rate_round);
+
+ /* we've got our root feeder so don't veto pcm loading anymore */
+ pcm_veto_load = 0;
+
+ return;
+ }
+
+ KASSERT(fc->desc != NULL, ("feeder '%s' has no descriptor", fc->name));
+
+ /* beyond this point failure is non-fatal but may result in some translations being unavailable */
+ i = 0;
+ while ((feedercnt < MAXFEEDERS) && (fc->desc[i].type > 0)) {
+ /* printf("adding feeder %s, %x -> %x\n", fc->name, fc->desc[i].in, fc->desc[i].out); */
+ fte = malloc(sizeof(*fte), M_FEEDER, M_NOWAIT | M_ZERO);
+ if (fte == NULL) {
+ printf("can't allocate memory for feeder '%s', %x -> %x\n", fc->name, fc->desc[i].in, fc->desc[i].out);
+
+ return;
+ }
+ fte->feederclass = fc;
+ fte->desc = &fc->desc[i];
+ fte->idx = feedercnt;
+ fte->desc->idx = feedercnt;
+ SLIST_INSERT_HEAD(&feedertab, fte, link);
+ i++;
+ }
+ feedercnt++;
+ if (feedercnt >= MAXFEEDERS)
+ printf("MAXFEEDERS (%d >= %d) exceeded\n", feedercnt, MAXFEEDERS);
}
static void
feeder_unregisterall(void *p)
{
-struct feedertab_entry *fte, *next;
+ struct feedertab_entry *fte, *next;
-next = SLIST_FIRST(&feedertab);
-while (next != NULL) {
-fte = next;
-next = SLIST_NEXT(fte, link);
-free(fte, M_FEEDER);
-}
+ next = SLIST_FIRST(&feedertab);
+ while (next != NULL) {
+ fte = next;
+ next = SLIST_NEXT(fte, link);
+ free(fte, M_FEEDER);
+ }
}
static int
cmpdesc(struct pcm_feederdesc *n, struct pcm_feederdesc *m)
{
-return ((n->type == m->type) &&
-((n->in == 0) || (n->in == m->in)) &&
-((n->out == 0) || (n->out == m->out)) &&
-(n->flags == m->flags));
+ return ((n->type == m->type) &&
+ ((n->in == 0) || (n->in == m->in)) &&
+ ((n->out == 0) || (n->out == m->out)) &&
+ (n->flags == m->flags));
}
static void
feeder_destroy(struct pcm_feeder *f)
{
-FEEDER_FREE(f);
-kobj_delete((kobj_t)f, M_FEEDER);
+ FEEDER_FREE(f);
+ kobj_delete((kobj_t)f, M_FEEDER);
}
static struct pcm_feeder *
feeder_create(struct feeder_class *fc, struct pcm_feederdesc *desc)
{
-struct pcm_feeder *f;
-int err;
+ struct pcm_feeder *f;
+ int err;
-f = (struct pcm_feeder *)kobj_create((kobj_class_t)fc, M_FEEDER, M_NOWAIT | M_ZERO);
-if (f == NULL)
-return NULL;
-
-f->align = fc->align;
-f->data = fc->data;
-f->source = NULL;
-f->parent = NULL;
-f->class = fc;
-f->desc = &(f->desc_static);
-
-if (desc) {
-*(f->desc) = *desc;
-} else {
-f->desc->type = FEEDER_ROOT;
-f->desc->in = 0;
-f->desc->out = 0;
-f->desc->flags = 0;
-f->desc->idx = 0;
-}
-
-err = FEEDER_INIT(f);
-if (err) {
-printf("feeder_init(%p) on %s returned %dn", f, fc->name, err);
-feeder_destroy(f);
+ f = (struct pcm_feeder *)kobj_create((kobj_class_t)fc, M_FEEDER, M_NOWAIT | M_ZERO);
+ if (f == NULL)
+ return NULL;
+
+ f->align = fc->align;
+ f->data = fc->data;
+ f->source = NULL;
+ f->parent = NULL;
+ f->class = fc;
+ f->desc = &(f->desc_static);
+
+ if (desc) {
+ *(f->desc) = *desc;
+ } else {
+ f->desc->type = FEEDER_ROOT;
+ f->desc->in = 0;
+ f->desc->out = 0;
+ f->desc->flags = 0;
+ f->desc->idx = 0;
+ }
+
+ err = FEEDER_INIT(f);
+ if (err) {
+ printf("feeder_init(%p) on %s returned %d\n", f, fc->name, err);
+ feeder_destroy(f);
-return NULL;
-}
+ return NULL;
+ }
-return f;
+ return f;
}
struct feeder_class *
feeder_getclass(struct pcm_feederdesc *desc)
{
-struct feedertab_entry *fte;
+ struct feedertab_entry *fte;
-SLIST_FOREACH(fte, &feedertab, link) {
-if ((desc == NULL) && (fte->desc == NULL))
-return fte->feederclass;
-if ((fte->desc != NULL) && (desc != NULL) && cmpdesc(desc, fte->desc))
-return fte->feederclass;
-}
-return NULL;
+ SLIST_FOREACH(fte, &feedertab, link) {
+ if ((desc == NULL) && (fte->desc == NULL))
+ return fte->feederclass;
+ if ((fte->desc != NULL) && (desc != NULL) && cmpdesc(desc, fte->desc))
+ return fte->feederclass;
+ }
+ return NULL;
}
int
chn_addfeeder(struct pcm_channel *c, struct feeder_class *fc, struct pcm_feederdesc *desc)
{
-struct pcm_feeder *nf;
+ struct pcm_feeder *nf;
-nf = feeder_create(fc, desc);
-if (nf == NULL)
-return ENOSPC;
-
-nf->source = c->feeder;
-
-/* XXX we should use the lowest common denominator for align */
-if (nf->align > 0)
-c->align += nf->align;
-else if (nf->align < 0 && c->align < -nf->align)
-c->align = -nf->align;
-if (c->feeder != NULL)
-c->feeder->parent = nf;
-c->feeder = nf;
+ nf = feeder_create(fc, desc);
+ if (nf == NULL)
+ return ENOSPC;
+
+ nf->source = c->feeder;
+
+ /* XXX we should use the lowest common denominator for align */
+ if (nf->align > 0)
+ c->align += nf->align;
+ else if (nf->align < 0 && c->align < -nf->align)
+ c->align = -nf->align;
+ if (c->feeder != NULL)
+ c->feeder->parent = nf;
+ c->feeder = nf;
-return 0;
+ return 0;
}
int
chn_removefeeder(struct pcm_channel *c)
{
-struct pcm_feeder *f;
+ struct pcm_feeder *f;
-if (c->feeder == NULL)
-return -1;
-f = c->feeder;
-c->feeder = c->feeder->source;
-feeder_destroy(f);
+ if (c->feeder == NULL)
+ return -1;
+ f = c->feeder;
+ c->feeder = c->feeder->source;
+ feeder_destroy(f);
-return 0;
+ return 0;
}
struct pcm_feeder *
chn_findfeeder(struct pcm_channel *c, u_int32_t type)
{
-struct pcm_feeder *f;
+ struct pcm_feeder *f;
-f = c->feeder;
-while (f != NULL) {
-if (f->desc->type == type)
-return f;
-f = f->source;
-}
+ f = c->feeder;
+ while (f != NULL) {
+ if (f->desc->type == type)
+ return f;
+ f = f->source;
+ }
-return NULL;
+ return NULL;
}
static int
chainok(struct pcm_feeder *test, struct pcm_feeder *stop)
{
-u_int32_t visited[MAXFEEDERS / 32];
-u_int32_t idx, mask;
+ u_int32_t visited[MAXFEEDERS / 32];
+ u_int32_t idx, mask;
-bzero(visited, sizeof(visited));
-while (test && (test != stop)) {
-idx = test->desc->idx;
-if (idx < 0)
-panic("bad idx %d", idx);
-if (idx >= MAXFEEDERS)
-panic("bad idx %d", idx);
-mask = 1 << (idx & 31);
-idx >>= 5;
-if (visited[idx] & mask)
-return 0;
-visited[idx] |= mask;
-test = test->source;
-}
+ bzero(visited, sizeof(visited));
+ while (test && (test != stop)) {
+ idx = test->desc->idx;
+ if (idx < 0)
+ panic("bad idx %d", idx);
+ if (idx >= MAXFEEDERS)
+ panic("bad idx %d", idx);
+ mask = 1 << (idx & 31);
+ idx >>= 5;
+ if (visited[idx] & mask)
+ return 0;
+ visited[idx] |= mask;
+ test = test->source;
+ }
-return 1;
+ return 1;
}
-static struct pcm_feeder *
-feeder_fmtchain(u_int32_t *to, struct pcm_feeder *source, struct pcm_feeder *stop, int maxdepth)
-{
-struct feedertab_entry *fte;
-struct pcm_feeder *try, *ret;
-
-DEB(printf("trying %s (0x%08x -> 0x%08x)...n", source->class->name, source->desc->in, source->desc->out));
-if (fmtvalid(source->desc->out, to)) {
-DEB(printf("got itn"));
-return source;
-}
-
-if (maxdepth < 0)
-return NULL;
-
-SLIST_FOREACH(fte, &feedertab, link) {
-if (fte->desc == NULL)
-continue;
-if (fte->desc->type != FEEDER_FMT)
-continue;
-if (fte->desc->in == source->desc->out) {
-try = feeder_create(fte->feederclass, fte->desc);
-if (try) {
-try->source = source;
-ret = chainok(try, stop)? feeder_fmtchain(to, try, stop, maxdepth - 1) : NULL;
-if (ret != NULL)
-return ret;
-feeder_destroy(try);
-}
-}
-}
-/* printf("giving up %s...n", source->class->name); */
+/*
+ * See feeder_fmtchain() for the mumbo-jumbo ridiculous explanation
+ * of what the heck is this FMT_Q_*
+ */
+#define FMT_Q_UP 1
+#define FMT_Q_DOWN 2
+#define FMT_Q_EQ 3
+#define FMT_Q_MULTI 4
-return NULL;
-}
+/*
+ * 14bit format scoring
+ * --------------------
+ *
+ * 13 12 11 10 9 8 2 1 0 offset
+ * +---+---+---+---+---+---+-------------+---+---+
+ * | X | X | X | X | X | X | X X X X X X | X | X |
+ * +---+---+---+---+---+---+-------------+---+---+
+ * | | | | | | | | |
+ * | | | | | | | | +--> signed?
+ * | | | | | | | |
+ * | | | | | | | +------> bigendian?
+ * | | | | | | |
+ * | | | | | | +---------------> total channels
+ * | | | | | |
+ * | | | | | +------------------------> AFMT_A_LAW
+ * | | | | |
+ * | | | | +----------------------------> AFMT_MU_LAW
+ * | | | |
+ * | | | +--------------------------------> AFMT_8BIT
+ * | | |
+ * | | +------------------------------------> AFMT_16BIT
+ * | |
+ * | +----------------------------------------> AFMT_24BIT
+ * |
+ * +--------------------------------------------> AFMT_32BIT
+ */
+#define score_signeq(s1, s2) (((s1) & 0x1) == ((s2) & 0x1))
+#define score_endianeq(s1, s2) (((s1) & 0x2) == ((s2) & 0x2))
+#define score_cheq(s1, s2) (((s1) & 0xfc) == ((s2) & 0xfc))
+#define score_val(s1) ((s1) & 0x3f00)
+#define score_cse(s1) ((s1) & 0x7f)
-int
+u_int32_t
chn_fmtscore(u_int32_t fmt)
{
-if (fmt & AFMT_32BIT)
-return 60;
-if (fmt & AFMT_24BIT)
-return 50;
-if (fmt & AFMT_16BIT)
-return 40;
-if (fmt & (AFMT_U8|AFMT_S8))
-return 30;
-if (fmt & AFMT_MU_LAW)
-return 20;
-if (fmt & AFMT_A_LAW)
-return 10;
-return 0;
+ u_int32_t ret;
+
+ ret = 0;
+ if (fmt & AFMT_SIGNED)
+ ret |= 1 << 0;
+ if (fmt & AFMT_BIGENDIAN)
+ ret |= 1 << 1;
+ if (fmt & AFMT_STEREO)
+ ret |= (2 & 0x3f) << 2;
+ else
+ ret |= (1 & 0x3f) << 2;
+ if (fmt & AFMT_A_LAW)
+ ret |= 1 << 8;
+ else if (fmt & AFMT_MU_LAW)
+ ret |= 1 << 9;
+ else if (fmt & AFMT_8BIT)
+ ret |= 1 << 10;
+ else if (fmt & AFMT_16BIT)
+ ret |= 1 << 11;
+ else if (fmt & AFMT_24BIT)
+ ret |= 1 << 12;
+ else if (fmt & AFMT_32BIT)
+ ret |= 1 << 13;
+
+ return ret;
+}
+
+static u_int32_t
+chn_fmtbestfunc(u_int32_t fmt, u_int32_t *fmts, int cheq)
+{
+ u_int32_t best, score, score2, oldscore;
+ int i;
+
+ if (fmt == 0 || fmts == NULL || fmts[0] == 0)
+ return 0;
+
+ if (fmtvalid(fmt, fmts))
+ return fmt;
+
+ best = 0;
+ score = chn_fmtscore(fmt);
+ oldscore = 0;
+ for (i = 0; fmts[i] != 0; i++) {
+ score2 = chn_fmtscore(fmts[i]);
+ if (cheq && !score_cheq(score, score2))
+ continue;
+ if (oldscore == 0 ||
+ (score_val(score2) == score_val(score)) ||
+ (score_val(score2) == score_val(oldscore)) ||
+ (score_val(score2) > score_val(oldscore) &&
+ score_val(score2) < score_val(score)) ||
+ (score_val(score2) < score_val(oldscore) &&
+ score_val(score2) > score_val(score)) ||
+ (score_val(oldscore) < score_val(score) &&
+ score_val(score2) > score_val(oldscore))) {
+ if (score_val(oldscore) != score_val(score2) ||
+ score_cse(score) == score_cse(score2) ||
+ ((score_cse(oldscore) != score_cse(score) &&
+ !score_endianeq(score, oldscore) &&
+ (score_endianeq(score, score2) ||
+ (!score_signeq(score, oldscore) &&
+ score_signeq(score, score2)))))) {
+ best = fmts[i];
+ oldscore = score2;
+ }
+ }
+ }
+ return best;
}
u_int32_t
chn_fmtbestbit(u_int32_t fmt, u_int32_t *fmts)
{
-u_int32_t best;
-int i, score, score2, oldscore;
-
-best = 0;
-score = chn_fmtscore(fmt);
-oldscore = 0;
-for (i = 0; fmts[i] != 0; i++) {
-score2 = chn_fmtscore(fmts[i]);
-if (oldscore == 0 || (score2 == score) ||
-(score2 > oldscore && score2 < score) ||
-(score2 < oldscore && score2 > score) ||
-(oldscore < score && score2 > oldscore)) {
-best = fmts[i];
-oldscore = score2;
-}
-}
-return best;
+ return chn_fmtbestfunc(fmt, fmts, 0);
}
u_int32_t
chn_fmtbeststereo(u_int32_t fmt, u_int32_t *fmts)
{
-u_int32_t best;
-int i, score, score2, oldscore;
-
-best = 0;
-score = chn_fmtscore(fmt);
-oldscore = 0;
-for (i = 0; fmts[i] != 0; i++) {
-if ((fmt & AFMT_STEREO) == (fmts[i] & AFMT_STEREO)) {
-score2 = chn_fmtscore(fmts[i]);
-if (oldscore == 0 || (score2 == score) ||
-(score2 > oldscore && score2 < score) ||
-(score2 < oldscore && score2 > score) ||
-(oldscore < score && score2 > oldscore)) {
-best = fmts[i];
-oldscore = score2;
-}
-}
-}
-return best;
+ return chn_fmtbestfunc(fmt, fmts, 1);
}
u_int32_t
chn_fmtbest(u_int32_t fmt, u_int32_t *fmts)
{
-u_int32_t best1, best2;
-int score, score1, score2;
+ u_int32_t best1, best2;
+ u_int32_t score, score1, score2;
-best1 = chn_fmtbeststereo(fmt, fmts);
-best2 = chn_fmtbestbit(fmt, fmts);
+ if (fmtvalid(fmt, fmts))
+ return fmt;
-if (best1 != 0 && best2 != 0) {
-if (fmt & AFMT_STEREO)
-return best1;
-else {
-score = chn_fmtscore(fmt);
-score1 = chn_fmtscore(best1);
-score2 = chn_fmtscore(best2);
-if (score1 == score2 || score1 == score)
-return best1;
-else if (score2 == score)
-return best2;
-else if (score1 > score2)
-return best1;
-return best2;
-}
-} else if (best2 == 0)
-return best1;
-else
-return best2;
+ best1 = chn_fmtbeststereo(fmt, fmts);
+ best2 = chn_fmtbestbit(fmt, fmts);
+
+ if (best1 != 0 && best2 != 0 && best1 != best2) {
+ if (fmt & AFMT_STEREO)
+ return best1;
+ else {
+ score = score_val(chn_fmtscore(fmt));
+ score1 = score_val(chn_fmtscore(best1));
+ score2 = score_val(chn_fmtscore(best2));
+ if (score1 == score2 || score1 == score)
+ return best1;
+ else if (score2 == score)
+ return best2;
+ else if (score1 > score2)
+ return best1;
+ return best2;
+ }
+ } else if (best2 == 0)
+ return best1;
+ else
+ return best2;
}
-u_int32_t
-chn_fmtchain(struct pcm_channel *c, u_int32_t *to)
+static struct pcm_feeder *
+feeder_fmtchain(u_int32_t *to, struct pcm_feeder *source, struct pcm_feeder *stop, int maxdepth)
{
-struct pcm_feeder *try, *del, *stop;
-u_int32_t tmpfrom[2], tmpto[2], best, *from;
-int i, max, bestmax;
-
-KASSERT(c != NULL, ("c == NULL"));
-KASSERT(c->feeder != NULL, ("c->feeder == NULL"));
-KASSERT(to != NULL, ("to == NULL"));
-KASSERT(to[0] != 0, ("to[0] == 0"));
-
-stop = c->feeder;
-
-if (c->direction == PCMDIR_REC && c->feeder->desc->type == FEEDER_ROOT) {
-from = chn_getcaps(c)->fmtlist;
-if (fmtvalid(to[0], from))
-from = to;
-else {
-best = chn_fmtbest(to[0], from);
-if (best != 0) {
-tmpfrom[0] = best;
-tmpfrom[1] = 0;
-from = tmpfrom;
-}
-}
-} else {
-tmpfrom[0] = c->feeder->desc->out;
-tmpfrom[1] = 0;
-from = tmpfrom;
-if (to[1] != 0) {
-if (fmtvalid(tmpfrom[0], to)) {
-tmpto[0] = tmpfrom[0];
-tmpto[1] = 0;
-to = tmpto;
-} else {
-best = chn_fmtbest(tmpfrom[0], to);
-if (best != 0) {
-tmpto[0] = best;
-tmpto[1] = 0;
-to = tmpto;
-}
-}
-}
+ struct feedertab_entry *fte, *ftebest;
+ struct pcm_feeder *try, *ret;
+ uint32_t fl, qout, qsrc, qdst;
+ int qtype;
+
+ if (to == NULL || to[0] == 0)
+ return NULL;
+
+ DEB(printf("trying %s (0x%08x -> 0x%08x)...\n", source->class->name, source->desc->in, source->desc->out));
+ if (fmtvalid(source->desc->out, to)) {
+ DEB(printf("got it\n"));
+ return source;
+ }
+
+ if (maxdepth < 0)
+ return NULL;
+
+ /*
+ * WARNING: THIS IS _NOT_ FOR THE FAINT HEART
+ * Disclaimer: I don't expect anybody could understand this
+ * without deep logical and mathematical analysis
+ * involving various unnamed probability theorem.
+ *
+ * This "Best Fit Random Chain Selection" (BLEHBLEHWHATEVER) algorithm
+ * is **extremely** difficult to digest especially when applied to
+ * large sets / numbers of random chains (feeders), each with
+ * unique characteristic providing different sets of in/out format.
+ *
+ * Basically, our FEEDER_FMT (see feeder_fmt.c) chains characteristic:
+ * 1) Format chains
+ * 1.1 "8bit to any, not to 8bit"
+ * 1.1.1 sign can remain consistent, e.g: u8 -> u16[le|be]
+ * 1.1.2 sign can be changed, e.g: u8 -> s16[le|be]
+ * 1.1.3 endian can be changed, e.g: u8 -> u16[le|be]
+ * 1.1.4 both can be changed, e.g: u8 -> [u|s]16[le|be]
+ * 1.2 "Any to 8bit, not from 8bit"
+ * 1.2.1 sign can remain consistent, e.g: s16le -> s8
+ * 1.2.2 sign can be changed, e.g: s16le -> u8
+ * 1.2.3 source endian can be anything e.g: s16[le|be] -> s8
+ * 1.2.4 source endian / sign can be anything e.g: [u|s]16[le|be] -> u8
+ * 1.3 "Any to any where BOTH input and output either 8bit or non-8bit"
+ * 1.3.1 endian MUST remain consistent
+ * 1.3.2 sign CAN be changed
+ * 1.4 "Long jump" is allowed, e.g: from 16bit to 32bit, excluding
+ * 16bit to 24bit .
+ * 2) Channel chains (mono <-> stereo)
+ * 2.1 Both endian and sign MUST remain consistent
+ * 3) Endian chains (big endian <-> little endian)
+ * 3.1 Channels and sign MUST remain consistent
+ * 4) Sign chains (signed <-> unsigned)
+ * 4.1 Channels and endian MUST remain consistent
+ *
+ * .. and the mother of all chaining rules:
+ *
+ * Rules 0: Source and destination MUST not contain multiple selections.
+ * (qtype != FMT_Q_MULTI)
+ *
+ * First of all, our caller ( chn_fmtchain() ) will reduce the possible
+ * multiple from/to formats to a single best format using chn_fmtbest().
+ * Then, using chn_fmtscore(), we determine the chaining characteristic.
+ * Our main goal is to narrow it down until it reach FMT_Q_EQ chaining
+ * type while still adhering above chaining rules.
+ *
+ * The need for this complicated chaining procedures is inevitable,
+ * since currently we have more than 200 different types of FEEDER_FMT
+ * doing various unique format conversion. Without this (the old way),
+ * it is possible to generate broken chain since it doesn't do any
+ * sanity checking to ensure that the output format is "properly aligned"
+ * with the direction of conversion (quality up/down/equal).
+ *
+ * Conversion: s24le to s32le
+ * Possible chain: 1) s24le -> s32le (correct, optimized)
+ * 2) s24le -> s16le -> s32le
+ * (since we have feeder_24to16 and feeder_16to32)
+ * +-- obviously broken!
+ *
+ * Using scoring mechanisme, this will ensure that the chaining
+ * process do the right thing, or at least, give the best chain
+ * possible without causing quality (the 'Q') degradation.
+ */
+
+ qdst = chn_fmtscore(to[0]);
+ qsrc = chn_fmtscore(source->desc->out);
+
+#define score_q(s1) score_val(s1)
+#define score_8bit(s1) ((s1) & 0x700)
+#define score_non8bit(s1) (!score_8bit(s1))
+#define score_across8bit(s1, s2) ((score_8bit(s1) && score_non8bit(s2)) || \
+ (score_8bit(s2) && score_non8bit(s1)))
+
+#define FMT_CHAIN_Q_UP(s1, s2) (score_q(s1) < score_q(s2))
+#define FMT_CHAIN_Q_DOWN(s1, s2) (score_q(s1) > score_q(s2))
+#define FMT_CHAIN_Q_EQ(s1, s2) (score_q(s1) == score_q(s2))
+#define FMT_Q_DOWN_FLAGS(s1, s2) (0x1 | (score_across8bit(s1, s2) ? \
+ 0x2 : 0x0))
+#define FMT_Q_UP_FLAGS(s1, s2) FMT_Q_DOWN_FLAGS(s1, s2)
+#define FMT_Q_EQ_FLAGS(s1, s2) (0x3ffc | \
+ ((score_cheq(s1, s2) && \
+ score_endianeq(s1, s2)) ? \
+ 0x1 : 0x0) | \
+ ((score_cheq(s1, s2) && \
+ score_signeq(s1, s2)) ? \
+ 0x2 : 0x0))
+
+ /* Determine chaining direction and set matching flag */
+ fl = 0x3fff;
+ if (to[1] != 0) {
+ qtype = FMT_Q_MULTI;
+ printf("%s: WARNING: FMT_Q_MULTI chaining. Expect the unexpected.\n", __func__);
+ } else if (FMT_CHAIN_Q_DOWN(qsrc, qdst)) {
+ qtype = FMT_Q_DOWN;
+ fl = FMT_Q_DOWN_FLAGS(qsrc, qdst);
+ } else if (FMT_CHAIN_Q_UP(qsrc, qdst)) {
+ qtype = FMT_Q_UP;
+ fl = FMT_Q_UP_FLAGS(qsrc, qdst);
+ } else {
+ qtype = FMT_Q_EQ;
+ fl = FMT_Q_EQ_FLAGS(qsrc, qdst);
+ }
+
+ ftebest = NULL;
+
+ SLIST_FOREACH(fte, &feedertab, link) {
+ if (fte->desc == NULL)
+ continue;
+ if (fte->desc->type != FEEDER_FMT)
+ continue;
+ qout = chn_fmtscore(fte->desc->out);
+#define FMT_Q_MULTI_VALIDATE(qt) ((qt) == FMT_Q_MULTI)
+#define FMT_Q_FL_MATCH(qfl, s1, s2) (((s1) & (qfl)) == ((s2) & (qfl)))
+#define FMT_Q_UP_VALIDATE(qt, s1, s2, s3) ((qt) == FMT_Q_UP && \
+ score_q(s3) >= score_q(s1) && \
+ score_q(s3) <= score_q(s2))
+#define FMT_Q_DOWN_VALIDATE(qt, s1, s2, s3) ((qt) == FMT_Q_DOWN && \
+ score_q(s3) <= score_q(s1) && \
+ score_q(s3) >= score_q(s2))
+#define FMT_Q_EQ_VALIDATE(qt, s1, s2) ((qt) == FMT_Q_EQ && \
+ score_q(s1) == score_q(s2))
+ if (fte->desc->in == source->desc->out &&
+ (FMT_Q_MULTI_VALIDATE(qtype) ||
+ (FMT_Q_FL_MATCH(fl, qout, qdst) &&
+ (FMT_Q_UP_VALIDATE(qtype, qsrc, qdst, qout) ||
+ FMT_Q_DOWN_VALIDATE(qtype, qsrc, qdst, qout) ||
+ FMT_Q_EQ_VALIDATE(qtype, qdst, qout))))) {
+ try = feeder_create(fte->feederclass, fte->desc);
+ if (try) {
+ try->source = source;
+ ret = chainok(try, stop) ? feeder_fmtchain(to, try, stop, maxdepth - 1) : NULL;
+ if (ret != NULL)
+ return ret;
+ feeder_destroy(try);
+ }
+ } else if (fte->desc->in == source->desc->out) {
+ /* XXX quality must be considered! */
+ if (ftebest == NULL)
+ ftebest = fte;
+ }
+ }
+
+ if (ftebest != NULL) {
+ try = feeder_create(ftebest->feederclass, ftebest->desc);
+ if (try) {
+ try->source = source;
+ ret = chainok(try, stop) ? feeder_fmtchain(to, try, stop, maxdepth - 1) : NULL;
+ if (ret != NULL)
+ return ret;
+ feeder_destroy(try);
+ }
+ }
+
+ /* printf("giving up %s...\n", source->class->name); */
+
+ return NULL;
}
-i = 0;
-best = 0;
-bestmax = 100;
-while (from[i] != 0) {
-c->feeder->desc->out = from[i];
-try = NULL;
-max = 0;
-while (try == NULL && max < 8) {
-try = feeder_fmtchain(to, c->feeder, stop, max);
-if (try == NULL)
-max++;
-}
-if (try != NULL && max < bestmax) {
-bestmax = max;
-best = from[i];
-}
-while (try != NULL && try != stop) {
-del = try;
-try = try->source;
-feeder_destroy(del);
-}
-i++;
-}
-if (best == 0)
-return 0;
-
-c->feeder->desc->out = best;
-try = feeder_fmtchain(to, c->feeder, stop, bestmax);
-if (try == NULL)
-return 0;
+u_int32_t
+chn_fmtchain(struct pcm_channel *c, u_int32_t *to)
+{
+ struct pcm_feeder *try, *del, *stop;
+ u_int32_t tmpfrom[2], tmpto[2], best, *from;
+ int i, max, bestmax;
+
+ KASSERT(c != NULL, ("c == NULL"));
+ KASSERT(c->feeder != NULL, ("c->feeder == NULL"));
+ KASSERT(to != NULL, ("to == NULL"));
+ KASSERT(to[0] != 0, ("to[0] == 0"));
+
+ if (c == NULL || c->feeder == NULL || to == NULL || to[0] == 0)
+ return 0;
+
+ stop = c->feeder;
+ best = 0;
+
+ if (c->direction == PCMDIR_REC && c->feeder->desc->type == FEEDER_ROOT) {
+ from = chn_getcaps(c)->fmtlist;
+ if (from[1] != 0) {
+ best = chn_fmtbest(to[0], from);
+ if (best != 0) {
+ tmpfrom[0] = best;
+ tmpfrom[1] = 0;
+ from = tmpfrom;
+ }
+ }
+ } else {
+ tmpfrom[0] = c->feeder->desc->out;
+ tmpfrom[1] = 0;
+ from = tmpfrom;
+ if (to[1] != 0) {
+ best = chn_fmtbest(from[0], to);
+ if (best != 0) {
+ tmpto[0] = best;
+ tmpto[1] = 0;
+ to = tmpto;
+ }
+ }
+ }
+
+#define FEEDER_FMTCHAIN_MAXDEPTH 8
+
+ try = NULL;
+
+ if (to[0] != 0 && from[0] != 0 &&
+ to[1] == 0 && from[1] == 0) {
+ max = 0;
+ best = from[0];
+ c->feeder->desc->out = best;
+ do {
+ try = feeder_fmtchain(to, c->feeder, stop, max);
+ DEB(if (try != NULL) {
+ printf("%s: 0x%08x -> 0x%08x (maxdepth: %d)\n",
+ __func__, from[0], to[0], max);
+ });
+ } while (try == NULL && max++ < FEEDER_FMTCHAIN_MAXDEPTH);
+ } else {
+ printf("%s: Using the old-way format chaining!\n", __func__);
+ i = 0;
+ best = 0;
+ bestmax = 100;
+ while (from[i] != 0) {
+ c->feeder->desc->out = from[i];
+ try = NULL;
+ max = 0;
+ do {
+ try = feeder_fmtchain(to, c->feeder, stop, max);
+ } while (try == NULL && max++ < FEEDER_FMTCHAIN_MAXDEPTH);
+ if (try != NULL && max < bestmax) {
+ bestmax = max;
+ best = from[i];
+ }
+ while (try != NULL && try != stop) {
+ del = try;
+ try = try->source;
+ feeder_destroy(del);
+ }
+ i++;
+ }
+ if (best == 0)
+ return 0;
+
+ c->feeder->desc->out = best;
+ try = feeder_fmtchain(to, c->feeder, stop, bestmax);
+ }
+ if (try == NULL)
+ return 0;
-c->feeder = try;
-c->align = 0;
+ c->feeder = try;
+ c->align = 0;
#ifdef FEEDER_DEBUG
-printf("nnchain: ");
+ printf("\n\nchain: ");
#endif
-while (try && (try != stop)) {
+ while (try && (try != stop)) {
#ifdef FEEDER_DEBUG
-printf("%s [%d]", try->class->name, try->desc->idx);
-if (try->source)
-printf(" -> ");
+ printf("%s [%d]", try->class->name, try->desc->idx);
+ if (try->source)
+ printf(" -> ");
#endif
-if (try->source)
-try->source->parent = try;
-if (try->align > 0)
-c->align += try->align;
-else if (try->align < 0 && c->align < -try->align)
-c->align = -try->align;
-try = try->source;
-}
+ if (try->source)
+ try->source->parent = try;
+ if (try->align > 0)
+ c->align += try->align;
+ else if (try->align < 0 && c->align < -try->align)
+ c->align = -try->align;
+ try = try->source;
+ }
#ifdef FEEDER_DEBUG
-printf("%s [%d]n", try->class->name, try->desc->idx);
+ printf("%s [%d]\n", try->class->name, try->desc->idx);
#endif
-if (c->direction == PCMDIR_REC) {
-try = c->feeder;
-while (try != NULL) {
-if (try->desc->type == FEEDER_ROOT)
-return try->desc->out;
-try = try->source;
-}
-return best;
-} else
-return c->feeder->desc->out;
+ if (c->direction == PCMDIR_REC) {
+ try = c->feeder;
+ while (try != NULL) {
+ if (try->desc->type == FEEDER_ROOT)
+ return try->desc->out;
+ try = try->source;
+ }
+ return best;
+ } else
+ return c->feeder->desc->out;
}
void
feeder_printchain(struct pcm_feeder *head)
{
-struct pcm_feeder *f;
+ struct pcm_feeder *f;
-printf("feeder chain (head @%p)n", head);
-f = head;
-while (f != NULL) {
-printf("%s/%d @ %pn", f->class->name, f->desc->idx, f);
-f = f->source;
-}
-printf("[end]nn");
+ printf("feeder chain (head @%p)\n", head);
+ f = head;
+ while (f != NULL) {
+ printf("%s/%d @ %p\n", f->class->name, f->desc->idx, f);
+ f = f->source;
+ }
+ printf("[end]\n\n");
}
/*****************************************************************************/
@@ -520,49 +827,70 @@
static int
feed_root(struct pcm_feeder *feeder, struct pcm_channel *ch, u_int8_t *buffer, u_int32_t count, void *source)
{
-struct snd_dbuf *src = source;
-int l;
-u_int8_t x;
-
-KASSERT(count > 0, ("feed_root: count == 0"));
-/* count &= ~((1 << ch->align) - 1); */
-KASSERT(count > 0, ("feed_root: aligned count == 0 (align = %d)", ch->align));
-
-l = min(count, sndbuf_getready(src));
-sndbuf_dispose(src, buffer, l);
-
-/* When recording only return as much data as available */
-if (ch->direction == PCMDIR_REC)
-return l;
+ struct snd_dbuf *src = source;
+ int l, offset;
-/*
-if (l < count)
-printf("appending %d bytesn", count - l);
-*/
-
-x = (sndbuf_getfmt(src) & AFMT_SIGNED)? 0 : 0x80;
-while (l < count)
-buffer[l++] = x;
+ KASSERT(count > 0, ("feed_root: count == 0"));
+ /* count &= ~((1 << ch->align) - 1); */
+ KASSERT(count > 0, ("feed_root: aligned count == 0 (align = %d)", ch->align));
+
+ if (++ch->feedcount == 0)
+ ch->feedcount = 2;
+
+ l = min(count, sndbuf_getready(src));
+
+ /* When recording only return as much data as available */
+ if (ch->direction == PCMDIR_REC) {
+ sndbuf_dispose(src, buffer, l);
+ return l;
+ }
+
+
+ offset = count - l;
+
+ if (offset > 0) {
+ if (snd_verbose > 3)
+ printf("%s: (%s) %spending %d bytes "
+ "(count=%d l=%d feed=%d)\n",
+ __func__,
+ (ch->flags & CHN_F_VIRTUAL) ? "virtual" : "hardware",
+ (ch->feedcount == 1) ? "pre" : "ap",
+ offset, count, l, ch->feedcount);
+
+ if (ch->feedcount == 1) {
+ memset(buffer,
+ sndbuf_zerodata(sndbuf_getfmt(src)),
+ offset);
+ if (l > 0)
+ sndbuf_dispose(src, buffer + offset, l);
+ else
+ ch->feedcount--;
+ } else {
+ if (l > 0)
+ sndbuf_dispose(src, buffer, l);
+ memset(buffer + l,
+ sndbuf_zerodata(sndbuf_getfmt(src)),
+ offset);
+ if (!(ch->flags & CHN_F_CLOSING))
+ ch->xruns++;
+ }
+ } else if (l > 0)
+ sndbuf_dispose(src, buffer, l);
-return count;
+ return count;
}
static kobj_method_t feeder_root_methods[] = {
-KOBJMETHOD(feeder_feed, feed_root),
-{ 0, 0 }
+ KOBJMETHOD(feeder_feed, feed_root),
+ { 0, 0 }
};
static struct feeder_class feeder_root_class = {
-.name = "feeder_root",
-.methods = feeder_root_methods,
-.size = sizeof(struct pcm_feeder),
-.align = 0,
-.desc = NULL,
-.data = NULL,
+ .name = "feeder_root",
+ .methods = feeder_root_methods,
+ .size = sizeof(struct pcm_feeder),
+ .align = 0,
+ .desc = NULL,
+ .data = NULL,
};
SYSINIT(feeder_root, SI_SUB_DRIVERS, SI_ORDER_FIRST, feeder_register, &feeder_root_class);
SYSUNINIT(feeder_root, SI_SUB_DRIVERS, SI_ORDER_FIRST, feeder_unregisterall, NULL);
-
-
-
-
-
Index: buffer.c
===================================================================
RCS file: /home/cvs/src/sys/dev/sound/pcm/buffer.c,v
retrieving revision 1.2
retrieving revision 1.3
diff -L sys/dev/sound/pcm/buffer.c -L sys/dev/sound/pcm/buffer.c -u -r1.2 -r1.3
--- sys/dev/sound/pcm/buffer.c
+++ sys/dev/sound/pcm/buffer.c
@@ -1,571 +1,695 @@
/*-
-* Copyright (c) 1999 Cameron Grant <cg at freebsd.org>
-* All rights reserved.
-*
-* Redistribution and use in source and binary forms, with or without
-* modification, are permitted provided that the following conditions
-* are met:
-* 1. Redistributions of source code must retain the above copyright
-* notice, this list of conditions and the following disclaimer.
-* 2. Redistributions in binary form must reproduce the above copyright
-* notice, this list of conditions and the following disclaimer in the
-* documentation and/or other materials provided with the distribution.
-*
-* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
-* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
-* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
-* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
-* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
-* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
-* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
-* SUCH DAMAGE.
-*/
+ * Copyright (c) 1999 Cameron Grant <cg at freebsd.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
#include <dev/sound/pcm/sound.h>
#include "feeder_if.h"
-SND_DECLARE_FILE("$MidnightBSD$");
+SND_DECLARE_FILE("$FreeBSD: src/sys/dev/sound/pcm/buffer.c,v 1.37 2007/06/16 03:37:27 ariff Exp $");
struct snd_dbuf *
sndbuf_create(device_t dev, char *drv, char *desc, struct pcm_channel *channel)
{
-struct snd_dbuf *b;
+ struct snd_dbuf *b;
-b = malloc(sizeof(*b), M_DEVBUF, M_WAITOK | M_ZERO);
-snprintf(b->name, SNDBUF_NAMELEN, "%s:%s", drv, desc);
-b->dev = dev;
-b->channel = channel;
+ b = malloc(sizeof(*b), M_DEVBUF, M_WAITOK | M_ZERO);
+ snprintf(b->name, SNDBUF_NAMELEN, "%s:%s", drv, desc);
+ b->dev = dev;
+ b->channel = channel;
-return b;
+ return b;
}
void
sndbuf_destroy(struct snd_dbuf *b)
{
-if (b->tmpbuf)
-free(b->tmpbuf, M_DEVBUF);
-if (!(b->flags & SNDBUF_F_MANAGED) && b->buf)
-free(b->buf, M_DEVBUF);
-free(b, M_DEVBUF);
+ sndbuf_free(b);
+ free(b, M_DEVBUF);
}
bus_addr_t
sndbuf_getbufaddr(struct snd_dbuf *buf)
{
-return (buf->buf_addr);
+ return (buf->buf_addr);
}
static void
sndbuf_setmap(void *arg, bus_dma_segment_t *segs, int nseg, int error)
{
-struct snd_dbuf *b = (struct snd_dbuf *)arg;
+ struct snd_dbuf *b = (struct snd_dbuf *)arg;
-if (bootverbose) {
-device_printf(b->dev, "sndbuf_setmap %lx, %lx; ",
-(u_long)segs[0].ds_addr, (u_long)segs[0].ds_len);
-printf("%p -> %lxn", b->buf, (u_long)segs[0].ds_addr);
-}
-if (error == 0)
-b->buf_addr = segs[0].ds_addr;
-else
-b->buf_addr = 0;
+ if (bootverbose) {
+ device_printf(b->dev, "sndbuf_setmap %lx, %lx; ",
+ (u_long)segs[0].ds_addr, (u_long)segs[0].ds_len);
+ printf("%p -> %lx\n", b->buf, (u_long)segs[0].ds_addr);
+ }
+ if (error == 0)
+ b->buf_addr = segs[0].ds_addr;
+ else
+ b->buf_addr = 0;
}
/*
-* Allocate memory for DMA buffer. If the device does not use DMA transfers,
-* the driver can call malloc(9) and sndbuf_setup() itself.
-*/
+ * Allocate memory for DMA buffer. If the device does not use DMA transfers,
+ * the driver can call malloc(9) and sndbuf_setup() itself.
+ */
int
-sndbuf_alloc(struct snd_dbuf *b, bus_dma_tag_t dmatag, unsigned int size)
+sndbuf_alloc(struct snd_dbuf *b, bus_dma_tag_t dmatag, int dmaflags,
+ unsigned int size)
{
-int ret;
+ int ret;
-b->dmatag = dmatag;
-b->maxsize = size;
-b->bufsize = b->maxsize;
-b->buf_addr = 0;
-b->flags |= SNDBUF_F_MANAGED;
-if (bus_dmamem_alloc(b->dmatag, (void **)&b->buf, BUS_DMA_NOWAIT,
-&b->dmamap))
-return (ENOMEM);
-if (bus_dmamap_load(b->dmatag, b->dmamap, b->buf, b->maxsize,
-sndbuf_setmap, b, 0) != 0 || b->buf_addr == 0) {
-bus_dmamem_free(b->dmatag, b->buf, b->dmamap);
-b->dmamap = NULL;
-return (ENOMEM);
-}
-
-ret = sndbuf_resize(b, 2, b->maxsize / 2);
-if (ret != 0)
-sndbuf_free(b);
-return (ret);
+ b->dmatag = dmatag;
+ b->dmaflags = dmaflags | BUS_DMA_NOWAIT;
+ b->maxsize = size;
+ b->bufsize = b->maxsize;
+ b->buf_addr = 0;
+ b->flags |= SNDBUF_F_MANAGED;
+ if (bus_dmamem_alloc(b->dmatag, (void **)&b->buf, b->dmaflags,
+ &b->dmamap)) {
+ sndbuf_free(b);
+ return (ENOMEM);
+ }
+ if (bus_dmamap_load(b->dmatag, b->dmamap, b->buf, b->maxsize,
+ sndbuf_setmap, b, 0) != 0 || b->buf_addr == 0) {
+ sndbuf_free(b);
+ return (ENOMEM);
+ }
+
+ ret = sndbuf_resize(b, 2, b->maxsize / 2);
+ if (ret != 0)
+ sndbuf_free(b);
+
+ return (ret);
}
int
sndbuf_setup(struct snd_dbuf *b, void *buf, unsigned int size)
{
-if (buf)
-b->flags |= SNDBUF_F_MANAGED;
-b->buf = buf;
-b->maxsize = size;
-b->bufsize = b->maxsize;
-return sndbuf_resize(b, 2, b->maxsize / 2);
+ b->flags &= ~SNDBUF_F_MANAGED;
+ if (buf)
+ b->flags |= SNDBUF_F_MANAGED;
+ b->buf = buf;
+ b->maxsize = size;
+ b->bufsize = b->maxsize;
+ return sndbuf_resize(b, 2, b->maxsize / 2);
}
void
sndbuf_free(struct snd_dbuf *b)
{
-if (b->tmpbuf)
-free(b->tmpbuf, M_DEVBUF);
-b->tmpbuf = NULL;
-
-if (!(b->flags & SNDBUF_F_MANAGED) && b->buf)
-free(b->buf, M_DEVBUF);
-
-if (b->dmamap)
-bus_dmamap_unload(b->dmatag, b->dmamap);
-
-if (b->dmamap && b->buf)
-bus_dmamem_free(b->dmatag, b->buf, b->dmamap);
-b->dmamap = NULL;
-b->buf = NULL;
+ if (b->tmpbuf)
+ free(b->tmpbuf, M_DEVBUF);
+
+ if (b->shadbuf)
+ free(b->shadbuf, M_DEVBUF);
+
+ if (b->buf) {
+ if (b->flags & SNDBUF_F_MANAGED) {
+ if (b->dmamap)
+ bus_dmamap_unload(b->dmatag, b->dmamap);
+ if (b->dmatag)
+ bus_dmamem_free(b->dmatag, b->buf, b->dmamap);
+ } else
+ free(b->buf, M_DEVBUF);
+ }
+
+ b->tmpbuf = NULL;
+ b->shadbuf = NULL;
+ b->buf = NULL;
+ b->sl = 0;
+ b->dmatag = NULL;
+ b->dmamap = NULL;
}
+#define SNDBUF_CACHE_SHIFT 5
+
int
sndbuf_resize(struct snd_dbuf *b, unsigned int blkcnt, unsigned int blksz)
{
-u_int8_t *tmpbuf, *f2;
+ unsigned int bufsize, allocsize;
+ u_int8_t *tmpbuf;
+
+ chn_lock(b->channel);
+ if (b->maxsize == 0)
+ goto out;
+ if (blkcnt == 0)
+ blkcnt = b->blkcnt;
+ if (blksz == 0)
+ blksz = b->blksz;
+ if (blkcnt < 2 || blksz < 16 || (blkcnt * blksz) > b->maxsize) {
+ chn_unlock(b->channel);
+ return EINVAL;
+ }
+ if (blkcnt == b->blkcnt && blksz == b->blksz)
+ goto out;
+
+ bufsize = blkcnt * blksz;
+
+ if (bufsize > b->allocsize ||
+ bufsize < (b->allocsize >> SNDBUF_CACHE_SHIFT)) {
+ allocsize = round_page(bufsize);
+ chn_unlock(b->channel);
+ tmpbuf = malloc(allocsize, M_DEVBUF, M_WAITOK);
+ chn_lock(b->channel);
+ if (snd_verbose > 3)
+ printf("%s(): b=%p %p -> %p [%d -> %d : %d]\n",
+ __func__, b, b->tmpbuf, tmpbuf,
+ b->allocsize, allocsize, bufsize);
+ if (b->tmpbuf != NULL)
+ free(b->tmpbuf, M_DEVBUF);
+ b->tmpbuf = tmpbuf;
+ b->allocsize = allocsize;
+ } else if (snd_verbose > 3)
+ printf("%s(): b=%p %d [%d] NOCHANGE\n",
+ __func__, b, b->allocsize, b->bufsize);
+
+ b->blkcnt = blkcnt;
+ b->blksz = blksz;
+ b->bufsize = bufsize;
-chn_lock(b->channel);
-if (b->maxsize == 0)
-goto out;
-if (blkcnt == 0)
-blkcnt = b->blkcnt;
-if (blksz == 0)
-blksz = b->blksz;
-if (blkcnt < 2 || blksz < 16 || (blkcnt * blksz > b->maxsize)) {
-chn_unlock(b->channel);
-return EINVAL;
-}
-if (blkcnt == b->blkcnt && blksz == b->blksz)
-goto out;
-
-chn_unlock(b->channel);
-tmpbuf = malloc(blkcnt * blksz, M_DEVBUF, M_NOWAIT);
-if (tmpbuf == NULL)
-return ENOMEM;
-chn_lock(b->channel);
-b->blkcnt = blkcnt;
-b->blksz = blksz;
-b->bufsize = blkcnt * blksz;
-f2 = b->tmpbuf;
-b->tmpbuf = tmpbuf;
-sndbuf_reset(b);
-chn_unlock(b->channel);
-free(f2, M_DEVBUF);
-return 0;
+ sndbuf_reset(b);
out:
-chn_unlock(b->channel);
-return 0;
+ chn_unlock(b->channel);
+ return 0;
}
int
sndbuf_remalloc(struct snd_dbuf *b, unsigned int blkcnt, unsigned int blksz)
{
-u_int8_t *buf, *tmpbuf, *f1, *f2;
-unsigned int bufsize;
-int ret;
-
-if (blkcnt < 2 || blksz < 16)
-return EINVAL;
-
-bufsize = blksz * blkcnt;
-
-chn_unlock(b->channel);
-buf = malloc(bufsize, M_DEVBUF, M_WAITOK);
-if (buf == NULL) {
-ret = ENOMEM;
-goto out;
-}
-
-tmpbuf = malloc(bufsize, M_DEVBUF, M_WAITOK);
-if (tmpbuf == NULL) {
-free(buf, M_DEVBUF);
-ret = ENOMEM;
-goto out;
-}
-chn_lock(b->channel);
-
-b->blkcnt = blkcnt;
-b->blksz = blksz;
-b->bufsize = bufsize;
-b->maxsize = bufsize;
-f1 = b->buf;
-f2 = b->tmpbuf;
-b->buf = buf;
-b->tmpbuf = tmpbuf;
-
-sndbuf_reset(b);
-
-chn_unlock(b->channel);
-if (f1)
-free(f1, M_DEVBUF);
-if (f2)
-free(f2, M_DEVBUF);
+ unsigned int bufsize, allocsize;
+ u_int8_t *buf, *tmpbuf, *shadbuf;
-ret = 0;
-out:
-chn_lock(b->channel);
-return ret;
-}
+ if (blkcnt < 2 || blksz < 16)
+ return EINVAL;
+
+ bufsize = blksz * blkcnt;
+ if (bufsize > b->allocsize ||
+ bufsize < (b->allocsize >> SNDBUF_CACHE_SHIFT)) {
+ allocsize = round_page(bufsize);
+ chn_unlock(b->channel);
+ buf = malloc(allocsize, M_DEVBUF, M_WAITOK);
+ tmpbuf = malloc(allocsize, M_DEVBUF, M_WAITOK);
+ shadbuf = malloc(allocsize, M_DEVBUF, M_WAITOK);
+ chn_lock(b->channel);
+ if (b->buf != NULL)
+ free(b->buf, M_DEVBUF);
+ b->buf = buf;
+ if (b->tmpbuf != NULL)
+ free(b->tmpbuf, M_DEVBUF);
+ b->tmpbuf = tmpbuf;
+ if (b->shadbuf != NULL)
+ free(b->shadbuf, M_DEVBUF);
+ b->shadbuf = shadbuf;
+ if (snd_verbose > 3)
+ printf("%s(): b=%p %d -> %d [%d]\n",
+ __func__, b, b->allocsize, allocsize, bufsize);
+ b->allocsize = allocsize;
+ } else if (snd_verbose > 3)
+ printf("%s(): b=%p %d [%d] NOCHANGE\n",
+ __func__, b, b->allocsize, b->bufsize);
+
+ b->blkcnt = blkcnt;
+ b->blksz = blksz;
+ b->bufsize = bufsize;
+ b->maxsize = bufsize;
+ b->sl = bufsize;
+
+ sndbuf_reset(b);
+
+ return 0;
+}
+
+/**
+ * @brief Zero out space in buffer free area
+ *
+ * This function clears a chunk of @c length bytes in the buffer free area
+ * (i.e., where the next write will be placed).
+ *
+ * @param b buffer context
+ * @param length number of bytes to blank
+ */
void
sndbuf_clear(struct snd_dbuf *b, unsigned int length)
{
-int i;
-u_char data, *p;
-
-if (length == 0)
-return;
-if (length > b->bufsize)
-length = b->bufsize;
-
-if (b->fmt & AFMT_SIGNED)
-data = 0x00;
-else
-data = 0x80;
-
-i = sndbuf_getfreeptr(b);
-p = sndbuf_getbuf(b);
-while (length > 0) {
-p[i] = data;
-length--;
-i++;
-if (i >= b->bufsize)
-i = 0;
-}
-}
+ int i;
+ u_char data, *p;
+ if (length == 0)
+ return;
+ if (length > b->bufsize)
+ length = b->bufsize;
+
+ data = sndbuf_zerodata(b->fmt);
+
+ i = sndbuf_getfreeptr(b);
+ p = sndbuf_getbuf(b);
+ while (length > 0) {
+ p[i] = data;
+ length--;
+ i++;
+ if (i >= b->bufsize)
+ i = 0;
+ }
+}
+
+/**
+ * @brief Zap buffer contents, resetting "ready area" fields
+ *
+ * @param b buffer context
+ */
void
sndbuf_fillsilence(struct snd_dbuf *b)
{
-int i;
-u_char data, *p;
-
-if (b->fmt & AFMT_SIGNED)
-data = 0x00;
-else
-data = 0x80;
-
-i = 0;
-p = sndbuf_getbuf(b);
-while (i < b->bufsize)
-p[i++] = data;
-b->rp = 0;
-b->rl = b->bufsize;
+ if (b->bufsize > 0)
+ memset(sndbuf_getbuf(b), sndbuf_zerodata(b->fmt), b->bufsize);
+ b->rp = 0;
+ b->rl = b->bufsize;
+}
+
+/**
+ * @brief Reset buffer w/o flushing statistics
+ *
+ * This function just zeroes out buffer contents and sets the "ready length"
+ * to zero. This was originally to facilitate minimal playback interruption
+ * (i.e., dropped samples) in SNDCTL_DSP_SILENCE/SKIP ioctls.
+ *
+ * @param b buffer context
+ */
+void
+sndbuf_softreset(struct snd_dbuf *b)
+{
+ b->rl = 0;
+ if (b->buf && b->bufsize > 0)
+ sndbuf_clear(b, b->bufsize);
}
void
sndbuf_reset(struct snd_dbuf *b)
{
-b->hp = 0;
-b->rp = 0;
-b->rl = 0;
-b->dl = 0;
-b->prev_total = 0;
-b->total = 0;
-b->xrun = 0;
-if (b->buf && b->bufsize > 0)
-sndbuf_clear(b, b->bufsize);
+ b->hp = 0;
+ b->rp = 0;
+ b->rl = 0;
+ b->dl = 0;
+ b->prev_total = 0;
+ b->total = 0;
+ b->xrun = 0;
+ if (b->buf && b->bufsize > 0)
+ sndbuf_clear(b, b->bufsize);
+ sndbuf_clearshadow(b);
}
u_int32_t
sndbuf_getfmt(struct snd_dbuf *b)
{
-return b->fmt;
+ return b->fmt;
}
int
sndbuf_setfmt(struct snd_dbuf *b, u_int32_t fmt)
{
-b->fmt = fmt;
-b->bps = 1;
-b->bps <<= (b->fmt & AFMT_STEREO)? 1 : 0;
-if (b->fmt & AFMT_16BIT)
-b->bps <<= 1;
-else if (b->fmt & AFMT_24BIT)
-b->bps *= 3;
-else if (b->fmt & AFMT_32BIT)
-b->bps <<= 2;
-return 0;
+ b->fmt = fmt;
+ b->bps = 1;
+ b->bps <<= (b->fmt & AFMT_STEREO)? 1 : 0;
+ if (b->fmt & AFMT_16BIT)
+ b->bps <<= 1;
+ else if (b->fmt & AFMT_24BIT)
+ b->bps *= 3;
+ else if (b->fmt & AFMT_32BIT)
+ b->bps <<= 2;
+ return 0;
}
unsigned int
sndbuf_getspd(struct snd_dbuf *b)
{
-return b->spd;
+ return b->spd;
}
void
sndbuf_setspd(struct snd_dbuf *b, unsigned int spd)
{
-b->spd = spd;
+ b->spd = spd;
}
unsigned int
sndbuf_getalign(struct snd_dbuf *b)
{
-static int align[] = {0, 1, 1, 2, 2, 2, 2, 3};
+ static int align[] = {0, 1, 1, 2, 2, 2, 2, 3};
-return align[b->bps - 1];
+ return align[b->bps - 1];
}
unsigned int
sndbuf_getblkcnt(struct snd_dbuf *b)
{
-return b->blkcnt;
+ return b->blkcnt;
}
void
sndbuf_setblkcnt(struct snd_dbuf *b, unsigned int blkcnt)
{
-b->blkcnt = blkcnt;
+ b->blkcnt = blkcnt;
}
unsigned int
sndbuf_getblksz(struct snd_dbuf *b)
{
-return b->blksz;
+ return b->blksz;
}
void
sndbuf_setblksz(struct snd_dbuf *b, unsigned int blksz)
{
-b->blksz = blksz;
+ b->blksz = blksz;
}
unsigned int
sndbuf_getbps(struct snd_dbuf *b)
{
-return b->bps;
+ return b->bps;
}
void *
sndbuf_getbuf(struct snd_dbuf *b)
{
-return b->buf;
+ return b->buf;
}
void *
sndbuf_getbufofs(struct snd_dbuf *b, unsigned int ofs)
{
-KASSERT(ofs < b->bufsize, ("%s: ofs invalid %d", __func__, ofs));
+ KASSERT(ofs < b->bufsize, ("%s: ofs invalid %d", __func__, ofs));
-return b->buf + ofs;
+ return b->buf + ofs;
}
unsigned int
sndbuf_getsize(struct snd_dbuf *b)
{
-return b->bufsize;
+ return b->bufsize;
}
unsigned int
sndbuf_getmaxsize(struct snd_dbuf *b)
{
-return b->maxsize;
+ return b->maxsize;
+}
+
+unsigned int
+sndbuf_getallocsize(struct snd_dbuf *b)
+{
+ return b->allocsize;
}
unsigned int
sndbuf_runsz(struct snd_dbuf *b)
{
-return b->dl;
+ return b->dl;
}
void
sndbuf_setrun(struct snd_dbuf *b, int go)
{
-b->dl = go? b->blksz : 0;
+ b->dl = go? b->blksz : 0;
}
struct selinfo *
sndbuf_getsel(struct snd_dbuf *b)
{
-return &b->sel;
+ return &b->sel;
}
/************************************************************/
unsigned int
sndbuf_getxrun(struct snd_dbuf *b)
{
-SNDBUF_LOCKASSERT(b);
+ SNDBUF_LOCKASSERT(b);
-return b->xrun;
+ return b->xrun;
}
void
-sndbuf_setxrun(struct snd_dbuf *b, unsigned int cnt)
+sndbuf_setxrun(struct snd_dbuf *b, unsigned int xrun)
{
-SNDBUF_LOCKASSERT(b);
+ SNDBUF_LOCKASSERT(b);
-b->xrun = cnt;
+ b->xrun = xrun;
}
unsigned int
sndbuf_gethwptr(struct snd_dbuf *b)
{
-SNDBUF_LOCKASSERT(b);
+ SNDBUF_LOCKASSERT(b);
-return b->hp;
+ return b->hp;
}
void
sndbuf_sethwptr(struct snd_dbuf *b, unsigned int ptr)
{
-SNDBUF_LOCKASSERT(b);
+ SNDBUF_LOCKASSERT(b);
-b->hp = ptr;
+ b->hp = ptr;
}
unsigned int
sndbuf_getready(struct snd_dbuf *b)
{
-SNDBUF_LOCKASSERT(b);
-KASSERT((b->rl >= 0) && (b->rl <= b->bufsize), ("%s: b->rl invalid %d", __func__, b->rl));
+ SNDBUF_LOCKASSERT(b);
+ KASSERT((b->rl >= 0) && (b->rl <= b->bufsize), ("%s: b->rl invalid %d", __func__, b->rl));
-return b->rl;
+ return b->rl;
}
unsigned int
sndbuf_getreadyptr(struct snd_dbuf *b)
{
-SNDBUF_LOCKASSERT(b);
-KASSERT((b->rp >= 0) && (b->rp <= b->bufsize), ("%s: b->rp invalid %d", __func__, b->rp));
+ SNDBUF_LOCKASSERT(b);
+ KASSERT((b->rp >= 0) && (b->rp <= b->bufsize), ("%s: b->rp invalid %d", __func__, b->rp));
-return b->rp;
+ return b->rp;
}
unsigned int
sndbuf_getfree(struct snd_dbuf *b)
{
-SNDBUF_LOCKASSERT(b);
-KASSERT((b->rl >= 0) && (b->rl <= b->bufsize), ("%s: b->rl invalid %d", __func__, b->rl));
+ SNDBUF_LOCKASSERT(b);
+ KASSERT((b->rl >= 0) && (b->rl <= b->bufsize), ("%s: b->rl invalid %d", __func__, b->rl));
-return b->bufsize - b->rl;
+ return b->bufsize - b->rl;
}
unsigned int
sndbuf_getfreeptr(struct snd_dbuf *b)
{
-SNDBUF_LOCKASSERT(b);
-KASSERT((b->rp >= 0) && (b->rp <= b->bufsize), ("%s: b->rp invalid %d", __func__, b->rp));
-KASSERT((b->rl >= 0) && (b->rl <= b->bufsize), ("%s: b->rl invalid %d", __func__, b->rl));
+ SNDBUF_LOCKASSERT(b);
+ KASSERT((b->rp >= 0) && (b->rp <= b->bufsize), ("%s: b->rp invalid %d", __func__, b->rp));
+ KASSERT((b->rl >= 0) && (b->rl <= b->bufsize), ("%s: b->rl invalid %d", __func__, b->rl));
-return (b->rp + b->rl) % b->bufsize;
+ return (b->rp + b->rl) % b->bufsize;
}
unsigned int
sndbuf_getblocks(struct snd_dbuf *b)
{
-SNDBUF_LOCKASSERT(b);
+ SNDBUF_LOCKASSERT(b);
-return b->total / b->blksz;
+ return b->total / b->blksz;
}
unsigned int
sndbuf_getprevblocks(struct snd_dbuf *b)
{
-SNDBUF_LOCKASSERT(b);
+ SNDBUF_LOCKASSERT(b);
-return b->prev_total / b->blksz;
+ return b->prev_total / b->blksz;
}
unsigned int
sndbuf_gettotal(struct snd_dbuf *b)
{
-SNDBUF_LOCKASSERT(b);
+ SNDBUF_LOCKASSERT(b);
-return b->total;
+ return b->total;
}
void
sndbuf_updateprevtotal(struct snd_dbuf *b)
{
-SNDBUF_LOCKASSERT(b);
+ SNDBUF_LOCKASSERT(b);
-b->prev_total = b->total;
+ b->prev_total = b->total;
}
-/************************************************************/
+unsigned int
+snd_xbytes(unsigned int v, unsigned int from, unsigned int to)
+{
+ unsigned int w, x, y;
-int
-sndbuf_acquire(struct snd_dbuf *b, u_int8_t *from, unsigned int count)
+ if (from == to)
+ return v;
+
+ if (from == 0 || to == 0 || v == 0)
+ return 0;
+
+ x = from;
+ y = to;
+ while (y != 0) {
+ w = x % y;
+ x = y;
+ y = w;
+ }
+ from /= x;
+ to /= x;
+
+ return (unsigned int)(((u_int64_t)v * to) / from);
+}
+
+unsigned int
+sndbuf_xbytes(unsigned int v, struct snd_dbuf *from, struct snd_dbuf *to)
{
-int l;
+ if (from == NULL || to == NULL || v == 0)
+ return 0;
-KASSERT(count <= sndbuf_getfree(b), ("%s: count %d > free %d", __func__, count, sndbuf_getfree(b)));
-KASSERT((b->rl >= 0) && (b->rl <= b->bufsize), ("%s: b->rl invalid %d", __func__, b->rl));
-b->total += count;
-if (from != NULL) {
-while (count > 0) {
-l = MIN(count, sndbuf_getsize(b) - sndbuf_getfreeptr(b));
-bcopy(from, sndbuf_getbufofs(b, sndbuf_getfreeptr(b)), l);
-from += l;
-b->rl += l;
-count -= l;
-}
-} else
-b->rl += count;
-KASSERT((b->rl >= 0) && (b->rl <= b->bufsize), ("%s: b->rl invalid %d, count %d", __func__, b->rl, count));
+ return snd_xbytes(v, sndbuf_getbps(from) * sndbuf_getspd(from),
+ sndbuf_getbps(to) * sndbuf_getspd(to));
+}
-return 0;
+u_int8_t
+sndbuf_zerodata(u_int32_t fmt)
+{
+ if (fmt & AFMT_SIGNED)
+ return (0x00);
+ else if (fmt & AFMT_MU_LAW)
+ return (0x7f);
+ else if (fmt & AFMT_A_LAW)
+ return (0x55);
+ return (0x80);
}
+/************************************************************/
+
+/**
+ * @brief Acquire buffer space to extend ready area
+ *
+ * This function extends the ready area length by @c count bytes, and may
+ * optionally copy samples from another location stored in @c from. The
+ * counter @c snd_dbuf::total is also incremented by @c count bytes.
+ *
+ * @param b audio buffer
+ * @param from sample source (optional)
+ * @param count number of bytes to acquire
+ *
+ * @retval 0 Unconditional
+ */
+int
+sndbuf_acquire(struct snd_dbuf *b, u_int8_t *from, unsigned int count)
+{
+ int l;
+
+ KASSERT(count <= sndbuf_getfree(b), ("%s: count %d > free %d", __func__, count, sndbuf_getfree(b)));
+ KASSERT((b->rl >= 0) && (b->rl <= b->bufsize), ("%s: b->rl invalid %d", __func__, b->rl));
+ b->total += count;
+ if (from != NULL) {
+ while (count > 0) {
+ l = min(count, sndbuf_getsize(b) - sndbuf_getfreeptr(b));
+ bcopy(from, sndbuf_getbufofs(b, sndbuf_getfreeptr(b)), l);
+ from += l;
+ b->rl += l;
+ count -= l;
+ }
+ } else
+ b->rl += count;
+ KASSERT((b->rl >= 0) && (b->rl <= b->bufsize), ("%s: b->rl invalid %d, count %d", __func__, b->rl, count));
+
+ return 0;
+}
+
+/**
+ * @brief Dispose samples from channel buffer, increasing size of ready area
+ *
+ * This function discards samples from the supplied buffer by advancing the
+ * ready area start pointer and decrementing the ready area length. If
+ * @c to is not NULL, then the discard samples will be copied to the location
+ * it points to.
+ *
+ * @param b PCM channel sound buffer
+ * @param to destination buffer (optional)
+ * @param count number of bytes to discard
+ *
+ * @returns 0 unconditionally
+ */
int
sndbuf_dispose(struct snd_dbuf *b, u_int8_t *to, unsigned int count)
{
-int l;
+ int l;
-KASSERT(count <= sndbuf_getready(b), ("%s: count %d > ready %d", __func__, count, sndbuf_getready(b)));
-KASSERT((b->rl >= 0) && (b->rl <= b->bufsize), ("%s: b->rl invalid %d", __func__, b->rl));
-if (to != NULL) {
-while (count > 0) {
-l = MIN(count, sndbuf_getsize(b) - sndbuf_getreadyptr(b));
-bcopy(sndbuf_getbufofs(b, sndbuf_getreadyptr(b)), to, l);
-to += l;
-b->rl -= l;
-b->rp = (b->rp + l) % b->bufsize;
-count -= l;
-}
-} else {
-b->rl -= count;
-b->rp = (b->rp + count) % b->bufsize;
-}
-KASSERT((b->rl >= 0) && (b->rl <= b->bufsize), ("%s: b->rl invalid %d, count %d", __func__, b->rl, count));
+ KASSERT(count <= sndbuf_getready(b), ("%s: count %d > ready %d", __func__, count, sndbuf_getready(b)));
+ KASSERT((b->rl >= 0) && (b->rl <= b->bufsize), ("%s: b->rl invalid %d", __func__, b->rl));
+ if (to != NULL) {
+ while (count > 0) {
+ l = min(count, sndbuf_getsize(b) - sndbuf_getreadyptr(b));
+ bcopy(sndbuf_getbufofs(b, sndbuf_getreadyptr(b)), to, l);
+ to += l;
+ b->rl -= l;
+ b->rp = (b->rp + l) % b->bufsize;
+ count -= l;
+ }
+ } else {
+ b->rl -= count;
+ b->rp = (b->rp + count) % b->bufsize;
+ }
+ KASSERT((b->rl >= 0) && (b->rl <= b->bufsize), ("%s: b->rl invalid %d, count %d", __func__, b->rl, count));
-return 0;
+ return 0;
}
/* count is number of bytes we want added to destination buffer */
int
sndbuf_feed(struct snd_dbuf *from, struct snd_dbuf *to, struct pcm_channel *channel, struct pcm_feeder *feeder, unsigned int count)
{
-KASSERT(count > 0, ("can't feed 0 bytes"));
+ unsigned int cnt;
-if (sndbuf_getfree(to) < count)
-return EINVAL;
+ KASSERT(count > 0, ("can't feed 0 bytes"));
-count = FEEDER_FEED(feeder, channel, to->tmpbuf, count, from);
-if (count)
-sndbuf_acquire(to, to->tmpbuf, count);
-/* the root feeder has called sndbuf_dispose(from, , bytes fetched) */
+ if (sndbuf_getfree(to) < count)
+ return EINVAL;
-return 0;
+ do {
+ cnt = FEEDER_FEED(feeder, channel, to->tmpbuf, count, from);
+ if (cnt) {
+ sndbuf_acquire(to, to->tmpbuf, cnt);
+ count -= cnt;
+ }
+ } while (count && cnt);
+
+ return 0;
}
/************************************************************/
@@ -573,32 +697,74 @@
void
sndbuf_dump(struct snd_dbuf *b, char *s, u_int32_t what)
{
-printf("%s: [", s);
-if (what & 0x01)
-printf(" bufsize: %d, maxsize: %d", b->bufsize, b->maxsize);
-if (what & 0x02)
-printf(" dl: %d, rp: %d, rl: %d, hp: %d", b->dl, b->rp, b->rl, b->hp);
-if (what & 0x04)
-printf(" total: %d, prev_total: %d, xrun: %d", b->total, b->prev_total, b->xrun);
-if (what & 0x08)
-printf(" fmt: 0x%x, spd: %d", b->fmt, b->spd);
-if (what & 0x10)
-printf(" blksz: %d, blkcnt: %d, flags: 0x%x", b->blksz, b->blkcnt, b->flags);
-printf(" ]n");
+ printf("%s: [", s);
+ if (what & 0x01)
+ printf(" bufsize: %d, maxsize: %d", b->bufsize, b->maxsize);
+ if (what & 0x02)
+ printf(" dl: %d, rp: %d, rl: %d, hp: %d", b->dl, b->rp, b->rl, b->hp);
+ if (what & 0x04)
+ printf(" total: %d, prev_total: %d, xrun: %d", b->total, b->prev_total, b->xrun);
+ if (what & 0x08)
+ printf(" fmt: 0x%x, spd: %d", b->fmt, b->spd);
+ if (what & 0x10)
+ printf(" blksz: %d, blkcnt: %d, flags: 0x%x", b->blksz, b->blkcnt, b->flags);
+ printf(" ]\n");
}
/************************************************************/
u_int32_t
sndbuf_getflags(struct snd_dbuf *b)
{
-return b->flags;
+ return b->flags;
}
void
sndbuf_setflags(struct snd_dbuf *b, u_int32_t flags, int on)
{
-b->flags &= ~flags;
-if (on)
-b->flags |= flags;
+ b->flags &= ~flags;
+ if (on)
+ b->flags |= flags;
+}
+
+/**
+ * @brief Clear the shadow buffer by filling with samples equal to zero.
+ *
+ * @param b buffer to clear
+ */
+void
+sndbuf_clearshadow(struct snd_dbuf *b)
+{
+ KASSERT(b != NULL, ("b is a null pointer"));
+ KASSERT(b->sl >= 0, ("illegal shadow length"));
+
+ if ((b->shadbuf != NULL) && (b->sl > 0))
+ memset(b->shadbuf, sndbuf_zerodata(b->fmt), b->sl);
}
+#ifdef OSSV4_EXPERIMENT
+/**
+ * @brief Return peak value from samples in buffer ready area.
+ *
+ * Peak ranges from 0-32767. If channel is monaural, most significant 16
+ * bits will be zero. For now, only expects to work with 1-2 channel
+ * buffers.
+ *
+ * @note Currently only operates with linear PCM formats.
+ *
+ * @param b buffer to analyze
+ * @param lpeak pointer to store left peak value
+ * @param rpeak pointer to store right peak value
+ */
+void
+sndbuf_getpeaks(struct snd_dbuf *b, int *lp, int *rp)
+{
+ u_int32_t lpeak, rpeak;
+
+ lpeak = 0;
+ rpeak = 0;
+
+ /**
+ * @todo fill this in later
+ */
+}
+#endif
Index: ac97.c
===================================================================
RCS file: /home/cvs/src/sys/dev/sound/pcm/ac97.c,v
retrieving revision 1.2
retrieving revision 1.3
diff -L sys/dev/sound/pcm/ac97.c -L sys/dev/sound/pcm/ac97.c -u -r1.2 -r1.3
--- sys/dev/sound/pcm/ac97.c
+++ sys/dev/sound/pcm/ac97.c
@@ -1,968 +1,1079 @@
/*-
-* Copyright (c) 1999 Cameron Grant <cg at freebsd.org>
-* All rights reserved.
-*
-* Redistribution and use in source and binary forms, with or without
-* modification, are permitted provided that the following conditions
-* are met:
-* 1. Redistributions of source code must retain the above copyright
-* notice, this list of conditions and the following disclaimer.
-* 2. Redistributions in binary form must reproduce the above copyright
-* notice, this list of conditions and the following disclaimer in the
-* documentation and/or other materials provided with the distribution.
-*
-* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
-* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
-* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
-* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
-* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
-* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
-* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
-* SUCH DAMAGE.
-*/
+ * Copyright (c) 1999 Cameron Grant <cg at freebsd.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
#include <dev/sound/pcm/sound.h>
#include <dev/sound/pcm/ac97.h>
#include <dev/sound/pcm/ac97_patch.h>
+#include <dev/pci/pcivar.h>
+
#include "mixer_if.h"
-SND_DECLARE_FILE("$MidnightBSD$");
+SND_DECLARE_FILE("$FreeBSD: src/sys/dev/sound/pcm/ac97.c,v 1.73.2.1 2007/10/29 18:47:47 ariff Exp $");
MALLOC_DEFINE(M_AC97, "ac97", "ac97 codec");
struct ac97mixtable_entry {
-int reg:8; /* register index */
-/* reg < 0 if inverted polarity */
-unsigned bits:4; /* width of control field */
-unsigned ofs:4; /* offset (only if stereo=0) */
-unsigned stereo:1; /* set for stereo controls */
-unsigned mute:1; /* bit15 is MUTE */
-unsigned recidx:4; /* index in rec mux */
-unsigned mask:1; /* use only masked bits */
-unsigned enable:1; /* entry is enabled */
+ int reg; /* register index */
+ /* reg < 0 if inverted polarity */
+ unsigned bits:4; /* width of control field */
+ unsigned ofs:4; /* offset (only if stereo=0) */
+ unsigned stereo:1; /* set for stereo controls */
+ unsigned mute:1; /* bit15 is MUTE */
+ unsigned recidx:4; /* index in rec mux */
+ unsigned mask:1; /* use only masked bits */
+ unsigned enable:1; /* entry is enabled */
};
-#define AC97_NAMELEN 16
+#define AC97_MIXER_SIZE SOUND_MIXER_NRDEVICES
+
struct ac97_info {
-kobj_t methods;
-device_t dev;
-void *devinfo;
-u_int32_t id;
-unsigned count, caps, se, extcaps, extid, extstat, noext:1;
-u_int32_t flags;
-struct ac97mixtable_entry mix[32];
-char name[AC97_NAMELEN];
-struct mtx *lock;
+ kobj_t methods;
+ device_t dev;
+ void *devinfo;
+ u_int32_t id;
+ u_int32_t subvendor;
+ unsigned count, caps, se, extcaps, extid, extstat, noext:1;
+ u_int32_t flags;
+ struct ac97mixtable_entry mix[AC97_MIXER_SIZE];
+ char name[16];
+ struct mtx *lock;
};
struct ac97_vendorid {
-u_int32_t id;
-const char *name;
+ u_int32_t id;
+ const char *name;
};
struct ac97_codecid {
-u_int32_t id;
-u_int8_t stepmask;
-u_int8_t noext:1;
-char *name;
-ac97_patch patch;
-};
-
-static const struct ac97mixtable_entry ac97mixtable_default[32] = {
-/* [offset] reg bits of st mu re mk en */
-[SOUND_MIXER_VOLUME] = { AC97_MIX_MASTER, 5, 0, 1, 1, 6, 0, 1 },
-[SOUND_MIXER_OGAIN] = { AC97_MIX_AUXOUT, 5, 0, 1, 1, 0, 0, 0 },
-[SOUND_MIXER_PHONEOUT] = { AC97_MIX_MONO, 5, 0, 0, 1, 7, 0, 0 },
-[SOUND_MIXER_BASS] = { AC97_MIX_TONE, 4, 8, 0, 0, 0, 1, 0 },
-[SOUND_MIXER_TREBLE] = { AC97_MIX_TONE, 4, 0, 0, 0, 0, 1, 0 },
-[SOUND_MIXER_PCM] = { AC97_MIX_PCM, 5, 0, 1, 1, 0, 0, 1 },
-[SOUND_MIXER_SPEAKER] = { AC97_MIX_BEEP, 4, 1, 0, 1, 0, 0, 0 },
-[SOUND_MIXER_LINE] = { AC97_MIX_LINE, 5, 0, 1, 1, 5, 0, 1 },
-[SOUND_MIXER_PHONEIN] = { AC97_MIX_PHONE, 5, 0, 0, 1, 8, 0, 0 },
-[SOUND_MIXER_MIC] = { AC97_MIX_MIC, 5, 0, 0, 1, 1, 1, 1 },
-/* use igain for the mic 20dB boost */
-[SOUND_MIXER_IGAIN] = { -AC97_MIX_MIC, 1, 6, 0, 0, 0, 1, 1 },
-[SOUND_MIXER_CD] = { AC97_MIX_CD, 5, 0, 1, 1, 2, 0, 1 },
-[SOUND_MIXER_LINE1] = { AC97_MIX_AUX, 5, 0, 1, 1, 4, 0, 0 },
-[SOUND_MIXER_VIDEO] = { AC97_MIX_VIDEO, 5, 0, 1, 1, 3, 0, 0 },
-[SOUND_MIXER_RECLEV] = { -AC97_MIX_RGAIN, 4, 0, 1, 1, 0, 0, 1 }
+ u_int32_t id;
+ u_int8_t stepmask;
+ u_int8_t noext:1;
+ char *name;
+ ac97_patch patch;
+};
+
+static const struct ac97mixtable_entry ac97mixtable_default[AC97_MIXER_SIZE] = {
+ /* [offset] reg bits of st mu re mk en */
+ [SOUND_MIXER_VOLUME] = { AC97_MIX_MASTER, 5, 0, 1, 1, 6, 0, 1 },
+ [SOUND_MIXER_OGAIN] = { AC97_MIX_AUXOUT, 5, 0, 1, 1, 0, 0, 0 },
+ [SOUND_MIXER_PHONEOUT] = { AC97_MIX_MONO, 5, 0, 0, 1, 7, 0, 0 },
+ [SOUND_MIXER_BASS] = { AC97_MIX_TONE, 4, 8, 0, 0, 0, 1, 0 },
+ [SOUND_MIXER_TREBLE] = { AC97_MIX_TONE, 4, 0, 0, 0, 0, 1, 0 },
+ [SOUND_MIXER_PCM] = { AC97_MIX_PCM, 5, 0, 1, 1, 0, 0, 1 },
+ [SOUND_MIXER_SPEAKER] = { AC97_MIX_BEEP, 4, 1, 0, 1, 0, 0, 0 },
+ [SOUND_MIXER_LINE] = { AC97_MIX_LINE, 5, 0, 1, 1, 5, 0, 1 },
+ [SOUND_MIXER_PHONEIN] = { AC97_MIX_PHONE, 5, 0, 0, 1, 8, 0, 0 },
+ [SOUND_MIXER_MIC] = { AC97_MIX_MIC, 5, 0, 0, 1, 1, 1, 1 },
+ /* use igain for the mic 20dB boost */
+ [SOUND_MIXER_IGAIN] = { -AC97_MIX_MIC, 1, 6, 0, 0, 0, 1, 1 },
+ [SOUND_MIXER_CD] = { AC97_MIX_CD, 5, 0, 1, 1, 2, 0, 1 },
+ [SOUND_MIXER_LINE1] = { AC97_MIX_AUX, 5, 0, 1, 1, 4, 0, 0 },
+ [SOUND_MIXER_VIDEO] = { AC97_MIX_VIDEO, 5, 0, 1, 1, 3, 0, 0 },
+ [SOUND_MIXER_RECLEV] = { -AC97_MIX_RGAIN, 4, 0, 1, 1, 0, 0, 1 }
};
static const struct ac97_vendorid ac97vendorid[] = {
-{ 0x41445300, "Analog Devices" },
-{ 0x414b4d00, "Asahi Kasei" },
-{ 0x414c4300, "Realtek" },
-{ 0x414c4700, "Avance Logic" },
-{ 0x43525900, "Cirrus Logic" },
-{ 0x434d4900, "C-Media Electronics" },
-{ 0x43585400, "Conexant" },
-{ 0x44543000, "Diamond Technology" },
-{ 0x454d4300, "eMicro" },
-{ 0x45838300, "ESS Technology" },
-{ 0x48525300, "Intersil" },
-{ 0x49434500, "ICEnsemble" },
-{ 0x49544500, "ITE, Inc." },
-{ 0x4e534300, "National Semiconductor" },
-{ 0x50534300, "Philips Semiconductor" },
-{ 0x83847600, "SigmaTel" },
-{ 0x53494c00, "Silicon Laboratories" },
-{ 0x54524100, "TriTech" },
-{ 0x54584e00, "Texas Instruments" },
-{ 0x56494100, "VIA Technologies" },
-{ 0x57454300, "Winbond" },
-{ 0x574d4c00, "Wolfson" },
-{ 0x594d4800, "Yamaha" },
-/*
-* XXX This is a fluke, really! The real vendor
-* should be SigmaTel, not this! This should be
-* removed someday!
-*/
-{ 0x01408300, "Creative" },
-{ 0x00000000, NULL }
+ { 0x41445300, "Analog Devices" },
+ { 0x414b4d00, "Asahi Kasei" },
+ { 0x414c4300, "Realtek" },
+ { 0x414c4700, "Avance Logic" },
+ { 0x43525900, "Cirrus Logic" },
+ { 0x434d4900, "C-Media Electronics" },
+ { 0x43585400, "Conexant" },
+ { 0x44543000, "Diamond Technology" },
+ { 0x454d4300, "eMicro" },
+ { 0x45838300, "ESS Technology" },
+ { 0x48525300, "Intersil" },
+ { 0x49434500, "ICEnsemble" },
+ { 0x49544500, "ITE, Inc." },
+ { 0x4e534300, "National Semiconductor" },
+ { 0x50534300, "Philips Semiconductor" },
+ { 0x83847600, "SigmaTel" },
+ { 0x53494c00, "Silicon Laboratories" },
+ { 0x54524100, "TriTech" },
+ { 0x54584e00, "Texas Instruments" },
+ { 0x56494100, "VIA Technologies" },
+ { 0x57454300, "Winbond" },
+ { 0x574d4c00, "Wolfson" },
+ { 0x594d4800, "Yamaha" },
+ /*
+ * XXX This is a fluke, really! The real vendor
+ * should be SigmaTel, not this! This should be
+ * removed someday!
+ */
+ { 0x01408300, "Creative" },
+ { 0x00000000, NULL }
};
static struct ac97_codecid ac97codecid[] = {
-{ 0x41445303, 0x00, 0, "AD1819", 0 },
-{ 0x41445340, 0x00, 0, "AD1881", 0 },
-{ 0x41445348, 0x00, 0, "AD1881A", 0 },
-{ 0x41445360, 0x00, 0, "AD1885", 0 },
-{ 0x41445361, 0x00, 0, "AD1886", ad1886_patch },
-{ 0x41445362, 0x00, 0, "AD1887", 0 },
-{ 0x41445363, 0x00, 0, "AD1886A", 0 },
-{ 0x41445368, 0x00, 0, "AD1888", ad198x_patch },
-{ 0x41445370, 0x00, 0, "AD1980", ad198x_patch },
-{ 0x41445372, 0x00, 0, "AD1981A", 0 },
-{ 0x41445374, 0x00, 0, "AD1981B", ad1981b_patch },
-{ 0x41445375, 0x00, 0, "AD1985", ad198x_patch },
-{ 0x41445378, 0x00, 0, "AD1986", ad198x_patch },
-{ 0x414b4d00, 0x00, 1, "AK4540", 0 },
-{ 0x414b4d01, 0x00, 1, "AK4542", 0 },
-{ 0x414b4d02, 0x00, 1, "AK4543", 0 },
-{ 0x414b4d06, 0x00, 0, "AK4544A", 0 },
-{ 0x454b4d07, 0x00, 0, "AK4545", 0 },
-{ 0x414c4320, 0x0f, 0, "ALC100", 0 },
-{ 0x414c4730, 0x0f, 0, "ALC101", 0 },
-{ 0x414c4710, 0x0f, 0, "ALC200", 0 },
-{ 0x414c4740, 0x0f, 0, "ALC202", 0 },
-{ 0x414c4720, 0x0f, 0, "ALC650", 0 },
-{ 0x414c4752, 0x0f, 0, "ALC250", 0 },
-{ 0x414c4760, 0x0f, 0, "ALC655", 0 },
-{ 0x414c4770, 0x0f, 0, "ALC203", 0 },
-{ 0x414c4780, 0x0f, 0, "ALC658", 0 },
-{ 0x414c4790, 0x0f, 0, "ALC850", 0 },
-{ 0x43525900, 0x07, 0, "CS4297", 0 },
-{ 0x43525910, 0x07, 0, "CS4297A", 0 },
-{ 0x43525920, 0x07, 0, "CS4294/98", 0 },
-{ 0x4352592d, 0x07, 0, "CS4294", 0 },
-{ 0x43525930, 0x07, 0, "CS4299", 0 },
-{ 0x43525940, 0x07, 0, "CS4201", 0 },
-{ 0x43525958, 0x07, 0, "CS4205", 0 },
-{ 0x43525960, 0x07, 0, "CS4291A", 0 },
-{ 0x434d4961, 0x00, 0, "CMI9739", cmi9739_patch },
-{ 0x434d4941, 0x00, 0, "CMI9738", 0 },
-{ 0x434d4978, 0x00, 0, "CMI9761", 0 },
-{ 0x434d4982, 0x00, 0, "CMI9761", 0 },
-{ 0x434d4983, 0x00, 0, "CMI9761", 0 },
-{ 0x43585421, 0x00, 0, "HSD11246", 0 },
-{ 0x43585428, 0x07, 0, "CX20468", 0 },
-{ 0x43585430, 0x00, 0, "CX20468-21", 0 },
-{ 0x44543000, 0x00, 0, "DT0398", 0 },
-{ 0x454d4323, 0x00, 0, "EM28023", 0 },
-{ 0x454d4328, 0x00, 0, "EM28028", 0 },
-{ 0x45838308, 0x00, 0, "ES1988", 0 }, /* Formerly ES1921(?) */
-{ 0x48525300, 0x00, 0, "HMP9701", 0 },
-{ 0x49434501, 0x00, 0, "ICE1230", 0 },
-{ 0x49434511, 0x00, 0, "ICE1232", 0 },
-{ 0x49434514, 0x00, 0, "ICE1232A", 0 },
-{ 0x49434551, 0x03, 0, "VT1616", 0 }, /* Via badged ICE */
-{ 0x49544520, 0x00, 0, "ITE2226E", 0 },
-{ 0x49544560, 0x07, 0, "ITE2646E", 0 }, /* XXX: patch needed */
-{ 0x4e534340, 0x00, 0, "LM4540", 0 }, /* Spec blank on revid */
-{ 0x4e534343, 0x00, 0, "LM4543", 0 }, /* Ditto */
-{ 0x4e534346, 0x00, 0, "LM4546A", 0 },
-{ 0x4e534348, 0x00, 0, "LM4548A", 0 },
-{ 0x4e534331, 0x00, 0, "LM4549", 0 },
-{ 0x4e534349, 0x00, 0, "LM4549A", 0 },
-{ 0x4e534350, 0x00, 0, "LM4550", 0 },
-{ 0x50534301, 0x00, 0, "UCB1510", 0 },
-{ 0x50534304, 0x00, 0, "UCB1400", 0 },
-{ 0x83847600, 0x00, 0, "STAC9700/83/84", 0 },
-{ 0x83847604, 0x00, 0, "STAC9701/03/04/05", 0 },
-{ 0x83847605, 0x00, 0, "STAC9704", 0 },
-{ 0x83847608, 0x00, 0, "STAC9708/11", 0 },
-{ 0x83847609, 0x00, 0, "STAC9721/23", 0 },
-{ 0x83847644, 0x00, 0, "STAC9744/45", 0 },
-{ 0x83847650, 0x00, 0, "STAC9750/51", 0 },
-{ 0x83847652, 0x00, 0, "STAC9752/53", 0 },
-{ 0x83847656, 0x00, 0, "STAC9756/57", 0 },
-{ 0x83847658, 0x00, 0, "STAC9758/59", 0 },
-{ 0x83847660, 0x00, 0, "STAC9760/61", 0 }, /* Extrapolated */
-{ 0x83847662, 0x00, 0, "STAC9762/63", 0 }, /* Extrapolated */
-{ 0x83847666, 0x00, 0, "STAC9766/67", 0 },
-{ 0x53494c22, 0x00, 0, "Si3036", 0 },
-{ 0x53494c23, 0x00, 0, "Si3038", 0 },
-{ 0x54524103, 0x00, 0, "TR28023", 0 }, /* Extrapolated */
-{ 0x54524106, 0x00, 0, "TR28026", 0 },
-{ 0x54524108, 0x00, 0, "TR28028", 0 },
-{ 0x54524123, 0x00, 0, "TR28602", 0 },
-{ 0x54524e03, 0x07, 0, "TLV320AIC27", 0 },
-{ 0x54584e20, 0x00, 0, "TLC320AD90", 0 },
-{ 0x56494161, 0x00, 0, "VIA1612A", 0 },
-{ 0x56494170, 0x00, 0, "VIA1617A", 0 },
-{ 0x574d4c00, 0x00, 0, "WM9701A", 0 },
-{ 0x574d4c03, 0x00, 0, "WM9703/4/7/8", 0 },
-{ 0x574d4c04, 0x00, 0, "WM9704Q", 0 },
-{ 0x574d4c05, 0x00, 0, "WM9705/10", 0 },
-{ 0x574d4d09, 0x00, 0, "WM9709", 0 },
-{ 0x574d4c12, 0x00, 0, "WM9711/12", 0 }, /* XXX: patch needed */
-{ 0x57454301, 0x00, 0, "W83971D", 0 },
-{ 0x594d4800, 0x00, 0, "YMF743", 0 },
-{ 0x594d4802, 0x00, 0, "YMF752", 0 },
-{ 0x594d4803, 0x00, 0, "YMF753", 0 },
-/*
-* XXX This is a fluke, really! The real codec
-* should be STAC9704, not this! This should be
-* removed someday!
-*/
-{ 0x01408384, 0x00, 0, "EV1938", 0 },
-{ 0, 0, 0, NULL, 0 }
+ { 0x41445303, 0x00, 0, "AD1819", 0 },
+ { 0x41445340, 0x00, 0, "AD1881", 0 },
+ { 0x41445348, 0x00, 0, "AD1881A", 0 },
+ { 0x41445360, 0x00, 0, "AD1885", 0 },
+ { 0x41445361, 0x00, 0, "AD1886", ad1886_patch },
+ { 0x41445362, 0x00, 0, "AD1887", 0 },
+ { 0x41445363, 0x00, 0, "AD1886A", 0 },
+ { 0x41445368, 0x00, 0, "AD1888", ad198x_patch },
+ { 0x41445370, 0x00, 0, "AD1980", ad198x_patch },
+ { 0x41445372, 0x00, 0, "AD1981A", 0 },
+ { 0x41445374, 0x00, 0, "AD1981B", ad1981b_patch },
+ { 0x41445375, 0x00, 0, "AD1985", ad198x_patch },
+ { 0x41445378, 0x00, 0, "AD1986", ad198x_patch },
+ { 0x414b4d00, 0x00, 1, "AK4540", 0 },
+ { 0x414b4d01, 0x00, 1, "AK4542", 0 },
+ { 0x414b4d02, 0x00, 1, "AK4543", 0 },
+ { 0x414b4d06, 0x00, 0, "AK4544A", 0 },
+ { 0x454b4d07, 0x00, 0, "AK4545", 0 },
+ { 0x414c4320, 0x0f, 0, "ALC100", 0 },
+ { 0x414c4730, 0x0f, 0, "ALC101", 0 },
+ { 0x414c4710, 0x0f, 0, "ALC200", 0 },
+ { 0x414c4740, 0x0f, 0, "ALC202", 0 },
+ { 0x414c4720, 0x0f, 0, "ALC650", 0 },
+ { 0x414c4752, 0x0f, 0, "ALC250", 0 },
+ { 0x414c4760, 0x0f, 0, "ALC655", alc655_patch },
+ { 0x414c4770, 0x0f, 0, "ALC203", 0 },
+ { 0x414c4780, 0x0f, 0, "ALC658", 0 },
+ { 0x414c4790, 0x0f, 0, "ALC850", 0 },
+ { 0x43525900, 0x07, 0, "CS4297", 0 },
+ { 0x43525910, 0x07, 0, "CS4297A", 0 },
+ { 0x43525920, 0x07, 0, "CS4294/98", 0 },
+ { 0x4352592d, 0x07, 0, "CS4294", 0 },
+ { 0x43525930, 0x07, 0, "CS4299", 0 },
+ { 0x43525940, 0x07, 0, "CS4201", 0 },
+ { 0x43525958, 0x07, 0, "CS4205", 0 },
+ { 0x43525960, 0x07, 0, "CS4291A", 0 },
+ { 0x434d4961, 0x00, 0, "CMI9739", cmi9739_patch },
+ { 0x434d4941, 0x00, 0, "CMI9738", 0 },
+ { 0x434d4978, 0x00, 0, "CMI9761", 0 },
+ { 0x434d4982, 0x00, 0, "CMI9761", 0 },
+ { 0x434d4983, 0x00, 0, "CMI9761", 0 },
+ { 0x43585421, 0x00, 0, "HSD11246", 0 },
+ { 0x43585428, 0x07, 0, "CX20468", 0 },
+ { 0x43585430, 0x00, 0, "CX20468-21", 0 },
+ { 0x44543000, 0x00, 0, "DT0398", 0 },
+ { 0x454d4323, 0x00, 0, "EM28023", 0 },
+ { 0x454d4328, 0x00, 0, "EM28028", 0 },
+ { 0x45838308, 0x00, 0, "ES1988", 0 }, /* Formerly ES1921(?) */
+ { 0x48525300, 0x00, 0, "HMP9701", 0 },
+ { 0x49434501, 0x00, 0, "ICE1230", 0 },
+ { 0x49434511, 0x00, 0, "ICE1232", 0 },
+ { 0x49434514, 0x00, 0, "ICE1232A", 0 },
+ { 0x49434551, 0x03, 0, "VT1616", 0 }, /* Via badged ICE */
+ { 0x49544520, 0x00, 0, "ITE2226E", 0 },
+ { 0x49544560, 0x07, 0, "ITE2646E", 0 }, /* XXX: patch needed */
+ { 0x4e534340, 0x00, 0, "LM4540", 0 }, /* Spec blank on revid */
+ { 0x4e534343, 0x00, 0, "LM4543", 0 }, /* Ditto */
+ { 0x4e534346, 0x00, 0, "LM4546A", 0 },
+ { 0x4e534348, 0x00, 0, "LM4548A", 0 },
+ { 0x4e534331, 0x00, 0, "LM4549", 0 },
+ { 0x4e534349, 0x00, 0, "LM4549A", 0 },
+ { 0x4e534350, 0x00, 0, "LM4550", 0 },
+ { 0x50534301, 0x00, 0, "UCB1510", 0 },
+ { 0x50534304, 0x00, 0, "UCB1400", 0 },
+ { 0x83847600, 0x00, 0, "STAC9700/83/84", 0 },
+ { 0x83847604, 0x00, 0, "STAC9701/03/04/05", 0 },
+ { 0x83847605, 0x00, 0, "STAC9704", 0 },
+ { 0x83847608, 0x00, 0, "STAC9708/11", 0 },
+ { 0x83847609, 0x00, 0, "STAC9721/23", 0 },
+ { 0x83847644, 0x00, 0, "STAC9744/45", 0 },
+ { 0x83847650, 0x00, 0, "STAC9750/51", 0 },
+ { 0x83847652, 0x00, 0, "STAC9752/53", 0 },
+ { 0x83847656, 0x00, 0, "STAC9756/57", 0 },
+ { 0x83847658, 0x00, 0, "STAC9758/59", 0 },
+ { 0x83847660, 0x00, 0, "STAC9760/61", 0 }, /* Extrapolated */
+ { 0x83847662, 0x00, 0, "STAC9762/63", 0 }, /* Extrapolated */
+ { 0x83847666, 0x00, 0, "STAC9766/67", 0 },
+ { 0x53494c22, 0x00, 0, "Si3036", 0 },
+ { 0x53494c23, 0x00, 0, "Si3038", 0 },
+ { 0x54524103, 0x00, 0, "TR28023", 0 }, /* Extrapolated */
+ { 0x54524106, 0x00, 0, "TR28026", 0 },
+ { 0x54524108, 0x00, 0, "TR28028", 0 },
+ { 0x54524123, 0x00, 0, "TR28602", 0 },
+ { 0x54524e03, 0x07, 0, "TLV320AIC27", 0 },
+ { 0x54584e20, 0x00, 0, "TLC320AD90", 0 },
+ { 0x56494161, 0x00, 0, "VIA1612A", 0 },
+ { 0x56494170, 0x00, 0, "VIA1617A", 0 },
+ { 0x574d4c00, 0x00, 0, "WM9701A", 0 },
+ { 0x574d4c03, 0x00, 0, "WM9703/4/7/8", 0 },
+ { 0x574d4c04, 0x00, 0, "WM9704Q", 0 },
+ { 0x574d4c05, 0x00, 0, "WM9705/10", 0 },
+ { 0x574d4d09, 0x00, 0, "WM9709", 0 },
+ { 0x574d4c12, 0x00, 0, "WM9711/12", 0 }, /* XXX: patch needed */
+ { 0x57454301, 0x00, 0, "W83971D", 0 },
+ { 0x594d4800, 0x00, 0, "YMF743", 0 },
+ { 0x594d4802, 0x00, 0, "YMF752", 0 },
+ { 0x594d4803, 0x00, 0, "YMF753", 0 },
+ /*
+ * XXX This is a fluke, really! The real codec
+ * should be STAC9704, not this! This should be
+ * removed someday!
+ */
+ { 0x01408384, 0x00, 0, "EV1938", 0 },
+ { 0, 0, 0, NULL, 0 }
};
static char *ac97enhancement[] = {
-"no 3D Stereo Enhancement",
-"Analog Devices Phat Stereo",
-"Creative Stereo Enhancement",
-"National Semi 3D Stereo Enhancement",
-"Yamaha Ymersion",
-"BBE 3D Stereo Enhancement",
-"Crystal Semi 3D Stereo Enhancement",
-"Qsound QXpander",
-"Spatializer 3D Stereo Enhancement",
-"SRS 3D Stereo Enhancement",
-"Platform Tech 3D Stereo Enhancement",
-"AKM 3D Audio",
-"Aureal Stereo Enhancement",
-"Aztech 3D Enhancement",
-"Binaura 3D Audio Enhancement",
-"ESS Technology Stereo Enhancement",
-"Harman International VMAx",
-"Nvidea 3D Stereo Enhancement",
-"Philips Incredible Sound",
-"Texas Instruments 3D Stereo Enhancement",
-"VLSI Technology 3D Stereo Enhancement",
-"TriTech 3D Stereo Enhancement",
-"Realtek 3D Stereo Enhancement",
-"Samsung 3D Stereo Enhancement",
-"Wolfson Microelectronics 3D Enhancement",
-"Delta Integration 3D Enhancement",
-"SigmaTel 3D Enhancement",
-"Reserved 27",
-"Rockwell 3D Stereo Enhancement",
-"Reserved 29",
-"Reserved 30",
-"Reserved 31"
+ "no 3D Stereo Enhancement",
+ "Analog Devices Phat Stereo",
+ "Creative Stereo Enhancement",
+ "National Semi 3D Stereo Enhancement",
+ "Yamaha Ymersion",
+ "BBE 3D Stereo Enhancement",
+ "Crystal Semi 3D Stereo Enhancement",
+ "Qsound QXpander",
+ "Spatializer 3D Stereo Enhancement",
+ "SRS 3D Stereo Enhancement",
+ "Platform Tech 3D Stereo Enhancement",
+ "AKM 3D Audio",
+ "Aureal Stereo Enhancement",
+ "Aztech 3D Enhancement",
+ "Binaura 3D Audio Enhancement",
+ "ESS Technology Stereo Enhancement",
+ "Harman International VMAx",
+ "Nvidea 3D Stereo Enhancement",
+ "Philips Incredible Sound",
+ "Texas Instruments 3D Stereo Enhancement",
+ "VLSI Technology 3D Stereo Enhancement",
+ "TriTech 3D Stereo Enhancement",
+ "Realtek 3D Stereo Enhancement",
+ "Samsung 3D Stereo Enhancement",
+ "Wolfson Microelectronics 3D Enhancement",
+ "Delta Integration 3D Enhancement",
+ "SigmaTel 3D Enhancement",
+ "Reserved 27",
+ "Rockwell 3D Stereo Enhancement",
+ "Reserved 29",
+ "Reserved 30",
+ "Reserved 31"
};
static char *ac97feature[] = {
-"mic channel",
-"reserved",
-"tone",
-"simulated stereo",
-"headphone",
-"bass boost",
-"18 bit DAC",
-"20 bit DAC",
-"18 bit ADC",
-"20 bit ADC"
+ "mic channel",
+ "reserved",
+ "tone",
+ "simulated stereo",
+ "headphone",
+ "bass boost",
+ "18 bit DAC",
+ "20 bit DAC",
+ "18 bit ADC",
+ "20 bit ADC"
};
static char *ac97extfeature[] = {
-"variable rate PCM",
-"double rate PCM",
-"reserved 1",
-"variable rate mic",
-"reserved 2",
-"reserved 3",
-"center DAC",
-"surround DAC",
-"LFE DAC",
-"AMAP",
-"reserved 4",
-"reserved 5",
-"reserved 6",
-"reserved 7",
+ "variable rate PCM",
+ "double rate PCM",
+ "reserved 1",
+ "variable rate mic",
+ "reserved 2",
+ "reserved 3",
+ "center DAC",
+ "surround DAC",
+ "LFE DAC",
+ "AMAP",
+ "reserved 4",
+ "reserved 5",
+ "reserved 6",
+ "reserved 7",
};
u_int16_t
ac97_rdcd(struct ac97_info *codec, int reg)
{
-if (codec->flags & AC97_F_RDCD_BUG) {
-u_int16_t i[2], j = 100;
+ if (codec->flags & AC97_F_RDCD_BUG) {
+ u_int16_t i[2], j = 100;
-i[0] = AC97_READ(codec->methods, codec->devinfo, reg);
-i[1] = AC97_READ(codec->methods, codec->devinfo, reg);
-while (i[0] != i[1] && j)
-i[j-- & 1] = AC97_READ(codec->methods, codec->devinfo, reg);
+ i[0] = AC97_READ(codec->methods, codec->devinfo, reg);
+ i[1] = AC97_READ(codec->methods, codec->devinfo, reg);
+ while (i[0] != i[1] && j)
+ i[j-- & 1] = AC97_READ(codec->methods, codec->devinfo, reg);
#if 0
-if (j < 100) {
-device_printf(codec->dev, "%s(): Inconsistent register value at"
-" 0x%08x (retry: %d)n", __func__, reg, 100 - j);
-}
+ if (j < 100) {
+ device_printf(codec->dev, "%s(): Inconsistent register value at"
+ " 0x%08x (retry: %d)\n", __func__, reg, 100 - j);
+ }
#endif
-return i[!(j & 1)];
-}
-return AC97_READ(codec->methods, codec->devinfo, reg);
+ return i[!(j & 1)];
+ }
+ return AC97_READ(codec->methods, codec->devinfo, reg);
}
void
ac97_wrcd(struct ac97_info *codec, int reg, u_int16_t val)
{
-AC97_WRITE(codec->methods, codec->devinfo, reg, val);
+ AC97_WRITE(codec->methods, codec->devinfo, reg, val);
}
static void
ac97_reset(struct ac97_info *codec)
{
-u_int32_t i, ps;
-ac97_wrcd(codec, AC97_REG_RESET, 0);
-for (i = 0; i < 500; i++) {
-ps = ac97_rdcd(codec, AC97_REG_POWER) & AC97_POWER_STATUS;
-if (ps == AC97_POWER_STATUS)
-return;
-DELAY(1000);
-}
-device_printf(codec->dev, "AC97 reset timed out.n");
+ u_int32_t i, ps;
+ ac97_wrcd(codec, AC97_REG_RESET, 0);
+ for (i = 0; i < 500; i++) {
+ ps = ac97_rdcd(codec, AC97_REG_POWER) & AC97_POWER_STATUS;
+ if (ps == AC97_POWER_STATUS)
+ return;
+ DELAY(1000);
+ }
+ device_printf(codec->dev, "AC97 reset timed out.\n");
}
int
ac97_setrate(struct ac97_info *codec, int which, int rate)
{
-u_int16_t v;
+ u_int16_t v;
-switch(which) {
-case AC97_REGEXT_FDACRATE:
-case AC97_REGEXT_SDACRATE:
-case AC97_REGEXT_LDACRATE:
-case AC97_REGEXT_LADCRATE:
-case AC97_REGEXT_MADCRATE:
-break;
-
-default:
-return -1;
-}
-
-snd_mtxlock(codec->lock);
-if (rate != 0) {
-v = rate;
-if (codec->extstat & AC97_EXTCAP_DRA)
-v >>= 1;
-ac97_wrcd(codec, which, v);
-}
-v = ac97_rdcd(codec, which);
-if (codec->extstat & AC97_EXTCAP_DRA)
-v <<= 1;
-snd_mtxunlock(codec->lock);
-return v;
+ switch(which) {
+ case AC97_REGEXT_FDACRATE:
+ case AC97_REGEXT_SDACRATE:
+ case AC97_REGEXT_LDACRATE:
+ case AC97_REGEXT_LADCRATE:
+ case AC97_REGEXT_MADCRATE:
+ break;
+
+ default:
+ return -1;
+ }
+
+ snd_mtxlock(codec->lock);
+ if (rate != 0) {
+ v = rate;
+ if (codec->extstat & AC97_EXTCAP_DRA)
+ v >>= 1;
+ ac97_wrcd(codec, which, v);
+ }
+ v = ac97_rdcd(codec, which);
+ if (codec->extstat & AC97_EXTCAP_DRA)
+ v <<= 1;
+ snd_mtxunlock(codec->lock);
+ return v;
}
int
ac97_setextmode(struct ac97_info *codec, u_int16_t mode)
{
-mode &= AC97_EXTCAPS;
-if ((mode & ~codec->extcaps) != 0) {
-device_printf(codec->dev, "ac97 invalid mode set 0x%04xn",
-mode);
-return -1;
-}
-snd_mtxlock(codec->lock);
-ac97_wrcd(codec, AC97_REGEXT_STAT, mode);
-codec->extstat = ac97_rdcd(codec, AC97_REGEXT_STAT) & AC97_EXTCAPS;
-snd_mtxunlock(codec->lock);
-return (mode == codec->extstat)? 0 : -1;
+ mode &= AC97_EXTCAPS;
+ if ((mode & ~codec->extcaps) != 0) {
+ device_printf(codec->dev, "ac97 invalid mode set 0x%04x\n",
+ mode);
+ return -1;
+ }
+ snd_mtxlock(codec->lock);
+ ac97_wrcd(codec, AC97_REGEXT_STAT, mode);
+ codec->extstat = ac97_rdcd(codec, AC97_REGEXT_STAT) & AC97_EXTCAPS;
+ snd_mtxunlock(codec->lock);
+ return (mode == codec->extstat)? 0 : -1;
}
u_int16_t
ac97_getextmode(struct ac97_info *codec)
{
-return codec->extstat;
+ return codec->extstat;
}
u_int16_t
ac97_getextcaps(struct ac97_info *codec)
{
-return codec->extcaps;
+ return codec->extcaps;
}
u_int16_t
ac97_getcaps(struct ac97_info *codec)
{
-return codec->caps;
+ return codec->caps;
+}
+
+u_int32_t
+ac97_getsubvendor(struct ac97_info *codec)
+{
+ return codec->subvendor;
}
static int
ac97_setrecsrc(struct ac97_info *codec, int channel)
{
-struct ac97mixtable_entry *e = &codec->mix[channel];
+ struct ac97mixtable_entry *e = &codec->mix[channel];
-if (e->recidx > 0) {
-int val = e->recidx - 1;
-val |= val << 8;
-snd_mtxlock(codec->lock);
-ac97_wrcd(codec, AC97_REG_RECSEL, val);
-snd_mtxunlock(codec->lock);
-return 0;
-} else
-return -1;
+ if (e->recidx > 0) {
+ int val = e->recidx - 1;
+ val |= val << 8;
+ snd_mtxlock(codec->lock);
+ ac97_wrcd(codec, AC97_REG_RECSEL, val);
+ snd_mtxunlock(codec->lock);
+ return 0;
+ } else
+ return -1;
}
static int
ac97_setmixer(struct ac97_info *codec, unsigned channel, unsigned left, unsigned right)
{
-struct ac97mixtable_entry *e = &codec->mix[channel];
+ struct ac97mixtable_entry *e = &codec->mix[channel];
-if (e->reg && e->enable && e->bits) {
-int mask, max, val, reg;
+ if (e->reg && e->enable && e->bits) {
+ int mask, max, val, reg;
-reg = (e->reg >= 0) ? e->reg : -e->reg; /* AC97 register */
-max = (1 << e->bits) - 1; /* actual range */
-mask = (max << 8) | max; /* bits of interest */
-
-if (!e->stereo)
-right = left;
-
-/*
-* Invert the range if the polarity requires so,
-* then scale to 0..max-1 to compute the value to
-* write into the codec, and scale back to 0..100
-* for the return value.
-*/
-if (e->reg > 0) {
-left = 100 - left;
-right = 100 - right;
-}
-
-left = (left * max) / 100;
-right = (right * max) / 100;
-
-val = (left << 8) | right;
-
-left = (left * 100) / max;
-right = (right * 100) / max;
-
-if (e->reg > 0) {
-left = 100 - left;
-right = 100 - right;
-}
-
-/*
-* For mono controls, trim val and mask, also taking
-* care of e->ofs (offset of control field).
-*/
-if (e->ofs) {
-val &= max;
-val <<= e->ofs;
-mask = (max << e->ofs);
-}
-
-/*
-* If we have a mute bit, add it to the mask and
-* update val and set mute if both channels require a
-* zero volume.
-*/
-if (e->mute == 1) {
-mask |= AC97_MUTE;
-if (left == 0 && right == 0)
-val = AC97_MUTE;
-}
-
-/*
-* If the mask bit is set, do not alter the other bits.
-*/
-snd_mtxlock(codec->lock);
-if (e->mask) {
-int cur = ac97_rdcd(codec, reg);
-val |= cur & ~(mask);
-}
-ac97_wrcd(codec, reg, val);
-snd_mtxunlock(codec->lock);
-return left | (right << 8);
-} else {
+ reg = (e->reg >= 0) ? e->reg : -e->reg; /* AC97 register */
+ max = (1 << e->bits) - 1; /* actual range */
+ mask = (max << 8) | max; /* bits of interest */
+
+ if (!e->stereo)
+ right = left;
+
+ /*
+ * Invert the range if the polarity requires so,
+ * then scale to 0..max-1 to compute the value to
+ * write into the codec, and scale back to 0..100
+ * for the return value.
+ */
+ if (e->reg > 0) {
+ left = 100 - left;
+ right = 100 - right;
+ }
+
+ left = (left * max) / 100;
+ right = (right * max) / 100;
+
+ val = (left << 8) | right;
+
+ left = (left * 100) / max;
+ right = (right * 100) / max;
+
+ if (e->reg > 0) {
+ left = 100 - left;
+ right = 100 - right;
+ }
+
+ /*
+ * For mono controls, trim val and mask, also taking
+ * care of e->ofs (offset of control field).
+ */
+ if (e->ofs) {
+ val &= max;
+ val <<= e->ofs;
+ mask = (max << e->ofs);
+ }
+
+ /*
+ * If we have a mute bit, add it to the mask and
+ * update val and set mute if both channels require a
+ * zero volume.
+ */
+ if (e->mute == 1) {
+ mask |= AC97_MUTE;
+ if (left == 0 && right == 0)
+ val = AC97_MUTE;
+ }
+
+ /*
+ * If the mask bit is set, do not alter the other bits.
+ */
+ snd_mtxlock(codec->lock);
+ if (e->mask) {
+ int cur = ac97_rdcd(codec, reg);
+ val |= cur & ~(mask);
+ }
+ ac97_wrcd(codec, reg, val);
+ snd_mtxunlock(codec->lock);
+ return left | (right << 8);
+ } else {
#if 0
-printf("ac97_setmixer: reg=%d, bits=%d, enable=%dn", e->reg, e->bits, e->enable);
+ printf("ac97_setmixer: reg=%d, bits=%d, enable=%d\n", e->reg, e->bits, e->enable);
#endif
-return -1;
-}
+ return -1;
+ }
}
static void
ac97_fix_auxout(struct ac97_info *codec)
{
-int keep_ogain;
+ int keep_ogain;
-/*
-* By default, The ac97 aux_out register (0x04) corresponds to OSS's
-* OGAIN setting.
-*
-* We first check whether aux_out is a valid register. If not
-* we may not want to keep ogain.
-*/
-keep_ogain = ac97_rdcd(codec, AC97_MIX_AUXOUT) & 0x8000;
-
-/*
-* Determine what AUX_OUT really means, it can be:
-*
-* 1. Headphone out.
-* 2. 4-Channel Out
-* 3. True line level out (effectively master volume).
-*
-* See Sections 5.2.1 and 5.27 for AUX_OUT Options in AC97r2.{2,3}.
-*/
-if (codec->extcaps & AC97_EXTCAP_SDAC &&
-ac97_rdcd(codec, AC97_MIXEXT_SURROUND) == 0x8080) {
-codec->mix[SOUND_MIXER_OGAIN].reg = AC97_MIXEXT_SURROUND;
-keep_ogain = 1;
-}
-
-if (keep_ogain == 0) {
-bzero(&codec->mix[SOUND_MIXER_OGAIN],
-sizeof(codec->mix[SOUND_MIXER_OGAIN]));
-}
+ /*
+ * By default, The ac97 aux_out register (0x04) corresponds to OSS's
+ * OGAIN setting.
+ *
+ * We first check whether aux_out is a valid register. If not
+ * we may not want to keep ogain.
+ */
+ keep_ogain = ac97_rdcd(codec, AC97_MIX_AUXOUT) & 0x8000;
+
+ /*
+ * Determine what AUX_OUT really means, it can be:
+ *
+ * 1. Headphone out.
+ * 2. 4-Channel Out
+ * 3. True line level out (effectively master volume).
+ *
+ * See Sections 5.2.1 and 5.27 for AUX_OUT Options in AC97r2.{2,3}.
+ */
+ if (codec->extcaps & AC97_EXTCAP_SDAC &&
+ ac97_rdcd(codec, AC97_MIXEXT_SURROUND) == 0x8080) {
+ codec->mix[SOUND_MIXER_OGAIN].reg = AC97_MIXEXT_SURROUND;
+ keep_ogain = 1;
+ }
+
+ if (keep_ogain == 0) {
+ bzero(&codec->mix[SOUND_MIXER_OGAIN],
+ sizeof(codec->mix[SOUND_MIXER_OGAIN]));
+ }
}
static void
ac97_fix_tone(struct ac97_info *codec)
{
-/* Hide treble and bass if they don't exist */
-if ((codec->caps & AC97_CAP_TONE) == 0) {
-bzero(&codec->mix[SOUND_MIXER_BASS],
-sizeof(codec->mix[SOUND_MIXER_BASS]));
-bzero(&codec->mix[SOUND_MIXER_TREBLE],
-sizeof(codec->mix[SOUND_MIXER_TREBLE]));
-}
+ /*
+ * YMF chips does not indicate tone and 3D enhancement capability
+ * in the AC97_REG_RESET register.
+ */
+ switch (codec->id) {
+ case 0x594d4800: /* YMF743 */
+ case 0x594d4803: /* YMF753 */
+ codec->caps |= AC97_CAP_TONE;
+ codec->se |= 0x04;
+ break;
+ case 0x594d4802: /* YMF752 */
+ codec->se |= 0x04;
+ break;
+ default:
+ break;
+ }
+
+ /* Hide treble and bass if they don't exist */
+ if ((codec->caps & AC97_CAP_TONE) == 0) {
+ bzero(&codec->mix[SOUND_MIXER_BASS],
+ sizeof(codec->mix[SOUND_MIXER_BASS]));
+ bzero(&codec->mix[SOUND_MIXER_TREBLE],
+ sizeof(codec->mix[SOUND_MIXER_TREBLE]));
+ }
}
static const char*
ac97_hw_desc(u_int32_t id, const char* vname, const char* cname, char* buf)
{
-if (cname == NULL) {
-sprintf(buf, "Unknown AC97 Codec (id = 0x%08x)", id);
-return buf;
-}
-
-if (vname == NULL) vname = "Unknown";
-
-if (bootverbose) {
-sprintf(buf, "%s %s AC97 Codec (id = 0x%08x)", vname, cname, id);
-} else {
-sprintf(buf, "%s %s AC97 Codec", vname, cname);
-}
-return buf;
+ if (cname == NULL) {
+ sprintf(buf, "Unknown AC97 Codec (id = 0x%08x)", id);
+ return buf;
+ }
+
+ if (vname == NULL) vname = "Unknown";
+
+ if (bootverbose) {
+ sprintf(buf, "%s %s AC97 Codec (id = 0x%08x)", vname, cname, id);
+ } else {
+ sprintf(buf, "%s %s AC97 Codec", vname, cname);
+ }
+ return buf;
}
static unsigned
ac97_initmixer(struct ac97_info *codec)
{
-ac97_patch codec_patch;
-const char *cname, *vname;
-char desc[80];
-u_int8_t model, step;
-unsigned i, j, k, bit, old;
-u_int32_t id;
-int reg;
-
-snd_mtxlock(codec->lock);
-codec->count = AC97_INIT(codec->methods, codec->devinfo);
-if (codec->count == 0) {
-device_printf(codec->dev, "ac97 codec init failedn");
-snd_mtxunlock(codec->lock);
-return ENODEV;
-}
-
-ac97_wrcd(codec, AC97_REG_POWER, (codec->flags & AC97_F_EAPD_INV)? 0x8000 : 0x0000);
-ac97_reset(codec);
-ac97_wrcd(codec, AC97_REG_POWER, (codec->flags & AC97_F_EAPD_INV)? 0x8000 : 0x0000);
-
-i = ac97_rdcd(codec, AC97_REG_RESET);
-j = ac97_rdcd(codec, AC97_REG_RESET);
-/*
-* Let see if this codec can return consistent value.
-* If not, turn on aggressive read workaround
-* (STAC9704 comes in mind).
-*/
-if (i != j) {
-codec->flags |= AC97_F_RDCD_BUG;
-i = ac97_rdcd(codec, AC97_REG_RESET);
-}
-codec->caps = i & 0x03ff;
-codec->se = (i & 0x7c00) >> 10;
-
-id = (ac97_rdcd(codec, AC97_REG_ID1) << 16) | ac97_rdcd(codec, AC97_REG_ID2);
-if (id == 0 || id == 0xffffffff) {
-device_printf(codec->dev, "ac97 codec invalid or not present (id == %x)n", id);
-snd_mtxunlock(codec->lock);
-return ENODEV;
-}
-
-codec->id = id;
-codec->noext = 0;
-codec_patch = NULL;
-
-cname = NULL;
-model = step = 0;
-for (i = 0; ac97codecid[i].id; i++) {
-u_int32_t modelmask = 0xffffffff ^ ac97codecid[i].stepmask;
-if ((ac97codecid[i].id & modelmask) == (id & modelmask)) {
-codec->noext = ac97codecid[i].noext;
-codec_patch = ac97codecid[i].patch;
-cname = ac97codecid[i].name;
-model = (id & modelmask) & 0xff;
-step = (id & ~modelmask) & 0xff;
-break;
-}
-}
-
-vname = NULL;
-for (i = 0; ac97vendorid[i].id; i++) {
-if (ac97vendorid[i].id == (id & 0xffffff00)) {
-vname = ac97vendorid[i].name;
-break;
-}
-}
-
-codec->extcaps = 0;
-codec->extid = 0;
-codec->extstat = 0;
-if (!codec->noext) {
-i = ac97_rdcd(codec, AC97_REGEXT_ID);
-if (i != 0xffff) {
-codec->extcaps = i & 0x3fff;
-codec->extid = (i & 0xc000) >> 14;
-codec->extstat = ac97_rdcd(codec, AC97_REGEXT_STAT) & AC97_EXTCAPS;
-}
-}
-
-for (i = 0; i < 32; i++) {
-codec->mix[i] = ac97mixtable_default[i];
-}
-ac97_fix_auxout(codec);
-ac97_fix_tone(codec);
-if (codec_patch)
-codec_patch(codec);
-
-for (i = 0; i < 32; i++) {
-k = codec->noext? codec->mix[i].enable : 1;
-reg = codec->mix[i].reg;
-if (reg < 0)
-reg = -reg;
-if (k && reg) {
-j = old = ac97_rdcd(codec, reg);
-/*
-* Test for mute bit (except for AC97_MIX_TONE,
-* where we simply assume it as available).
-*/
-if (codec->mix[i].mute) {
-ac97_wrcd(codec, reg, j | 0x8000);
-j = ac97_rdcd(codec, reg);
-} else
-j |= 0x8000;
-if ((j & 0x8000)) {
-/*
-* Test whether the control width should be
-* 4, 5 or 6 bit. For 5bit register, we should
-* test it whether it's really 5 or 6bit. Leave
-* 4bit register alone, because sometimes an
-* attempt to write past 4th bit may cause
-* incorrect result especially for AC97_MIX_BEEP
-* (ac97 2.3).
-*/
-bit = codec->mix[i].bits;
-if (bit == 5)
-bit++;
-j = ((1 << bit) - 1) << codec->mix[i].ofs;
-ac97_wrcd(codec, reg,
-j | (codec->mix[i].mute ? 0x8000 : 0));
-k = ac97_rdcd(codec, reg) & j;
-k >>= codec->mix[i].ofs;
-if (reg == AC97_MIX_TONE &&
-((k & 0x0001) == 0x0000))
-k >>= 1;
-for (j = 0; k >> j; j++)
-;
-if (j != 0) {
+ ac97_patch codec_patch;
+ const char *cname, *vname;
+ char desc[80];
+ u_int8_t model, step;
+ unsigned i, j, k, bit, old;
+ u_int32_t id;
+ int reg;
+
+ snd_mtxlock(codec->lock);
+ codec->count = AC97_INIT(codec->methods, codec->devinfo);
+ if (codec->count == 0) {
+ device_printf(codec->dev, "ac97 codec init failed\n");
+ snd_mtxunlock(codec->lock);
+ return ENODEV;
+ }
+
+ ac97_wrcd(codec, AC97_REG_POWER, (codec->flags & AC97_F_EAPD_INV)? 0x8000 : 0x0000);
+ ac97_reset(codec);
+ ac97_wrcd(codec, AC97_REG_POWER, (codec->flags & AC97_F_EAPD_INV)? 0x8000 : 0x0000);
+
+ i = ac97_rdcd(codec, AC97_REG_RESET);
+ j = ac97_rdcd(codec, AC97_REG_RESET);
+ k = ac97_rdcd(codec, AC97_REG_RESET);
+ /*
+ * Let see if this codec can return consistent value.
+ * If not, turn on aggressive read workaround
+ * (STAC9704 comes in mind).
+ */
+ if (i != j || j != k) {
+ codec->flags |= AC97_F_RDCD_BUG;
+ i = ac97_rdcd(codec, AC97_REG_RESET);
+ }
+ codec->caps = i & 0x03ff;
+ codec->se = (i & 0x7c00) >> 10;
+
+ id = (ac97_rdcd(codec, AC97_REG_ID1) << 16) | ac97_rdcd(codec, AC97_REG_ID2);
+ if (id == 0 || id == 0xffffffff) {
+ device_printf(codec->dev, "ac97 codec invalid or not present (id == %x)\n", id);
+ snd_mtxunlock(codec->lock);
+ return ENODEV;
+ }
+
+ codec->id = id;
+ codec->subvendor = (u_int32_t)pci_get_subdevice(codec->dev) << 16;
+ codec->subvendor |= (u_int32_t)pci_get_subvendor(codec->dev) &
+ 0x0000ffff;
+ codec->noext = 0;
+ codec_patch = NULL;
+
+ cname = NULL;
+ model = step = 0;
+ for (i = 0; ac97codecid[i].id; i++) {
+ u_int32_t modelmask = 0xffffffff ^ ac97codecid[i].stepmask;
+ if ((ac97codecid[i].id & modelmask) == (id & modelmask)) {
+ codec->noext = ac97codecid[i].noext;
+ codec_patch = ac97codecid[i].patch;
+ cname = ac97codecid[i].name;
+ model = (id & modelmask) & 0xff;
+ step = (id & ~modelmask) & 0xff;
+ break;
+ }
+ }
+
+ vname = NULL;
+ for (i = 0; ac97vendorid[i].id; i++) {
+ if (ac97vendorid[i].id == (id & 0xffffff00)) {
+ vname = ac97vendorid[i].name;
+ break;
+ }
+ }
+
+ codec->extcaps = 0;
+ codec->extid = 0;
+ codec->extstat = 0;
+ if (!codec->noext) {
+ i = ac97_rdcd(codec, AC97_REGEXT_ID);
+ if (i != 0xffff) {
+ codec->extcaps = i & 0x3fff;
+ codec->extid = (i & 0xc000) >> 14;
+ codec->extstat = ac97_rdcd(codec, AC97_REGEXT_STAT) & AC97_EXTCAPS;
+ }
+ }
+
+ for (i = 0; i < AC97_MIXER_SIZE; i++) {
+ codec->mix[i] = ac97mixtable_default[i];
+ }
+ ac97_fix_auxout(codec);
+ ac97_fix_tone(codec);
+ if (codec_patch)
+ codec_patch(codec);
+
+ for (i = 0; i < AC97_MIXER_SIZE; i++) {
+ k = codec->noext? codec->mix[i].enable : 1;
+ reg = codec->mix[i].reg;
+ if (reg < 0)
+ reg = -reg;
+ if (k && reg) {
+ j = old = ac97_rdcd(codec, reg);
+ /*
+ * Test for mute bit (except for AC97_MIX_TONE,
+ * where we simply assume it as available).
+ */
+ if (codec->mix[i].mute) {
+ ac97_wrcd(codec, reg, j | 0x8000);
+ j = ac97_rdcd(codec, reg);
+ } else
+ j |= 0x8000;
+ if ((j & 0x8000)) {
+ /*
+ * Test whether the control width should be
+ * 4, 5 or 6 bit. For 5bit register, we should
+ * test it whether it's really 5 or 6bit. Leave
+ * 4bit register alone, because sometimes an
+ * attempt to write past 4th bit may cause
+ * incorrect result especially for AC97_MIX_BEEP
+ * (ac97 2.3).
+ */
+ bit = codec->mix[i].bits;
+ if (bit == 5)
+ bit++;
+ j = ((1 << bit) - 1) << codec->mix[i].ofs;
+ ac97_wrcd(codec, reg,
+ j | (codec->mix[i].mute ? 0x8000 : 0));
+ k = ac97_rdcd(codec, reg) & j;
+ k >>= codec->mix[i].ofs;
+ if (reg == AC97_MIX_TONE &&
+ ((k & 0x0001) == 0x0000))
+ k >>= 1;
+ for (j = 0; k >> j; j++)
+ ;
+ if (j != 0) {
#if 0
-device_printf(codec->dev, "%2d: [ac97_rdcd() = %d] [Testbit = %d] %d -> %dn",
-i, k, bit, codec->mix[i].bits, j);
+ device_printf(codec->dev, "%2d: [ac97_rdcd() = %d] [Testbit = %d] %d -> %d\n",
+ i, k, bit, codec->mix[i].bits, j);
#endif
-codec->mix[i].enable = 1;
-codec->mix[i].bits = j;
-} else if (reg == AC97_MIX_BEEP) {
-/*
-* Few codec such as CX20468-21 does
-* have this control register, although
-* the only usable part is the mute bit.
-*/
-codec->mix[i].enable = 1;
-} else
-codec->mix[i].enable = 0;
-} else
-codec->mix[i].enable = 0;
-ac97_wrcd(codec, reg, old);
-}
+ codec->mix[i].enable = 1;
+ codec->mix[i].bits = j;
+ } else if (reg == AC97_MIX_BEEP) {
+ /*
+ * Few codec such as CX20468-21 does
+ * have this control register, although
+ * the only usable part is the mute bit.
+ */
+ codec->mix[i].enable = 1;
+ } else
+ codec->mix[i].enable = 0;
+ } else
+ codec->mix[i].enable = 0;
+ ac97_wrcd(codec, reg, old);
+ }
#if 0
-printf("mixch %d, en=%d, b=%dn", i, codec->mix[i].enable, codec->mix[i].bits);
+ printf("mixch %d, en=%d, b=%d\n", i, codec->mix[i].enable, codec->mix[i].bits);
#endif
-}
+ }
-device_printf(codec->dev, "<%s>n",
-ac97_hw_desc(codec->id, vname, cname, desc));
+ device_printf(codec->dev, "<%s>\n",
+ ac97_hw_desc(codec->id, vname, cname, desc));
-if (bootverbose) {
-if (codec->flags & AC97_F_RDCD_BUG)
-device_printf(codec->dev, "Buggy AC97 Codec: aggressive ac97_rdcd() workaround enabledn");
-device_printf(codec->dev, "Codec features ");
-for (i = j = 0; i < 10; i++)
-if (codec->caps & (1 << i))
-printf("%s%s", j++? ", " : "", ac97feature[i]);
-printf("%s%d bit master volume", j++? ", " : "", codec->mix[SOUND_MIXER_VOLUME].bits);
-printf("%s%sn", j? ", " : "", ac97enhancement[codec->se]);
-
-if (codec->extcaps != 0 || codec->extid) {
-device_printf(codec->dev, "%s codec",
-codec->extid? "Secondary" : "Primary");
-if (codec->extcaps)
-printf(" extended features ");
-for (i = j = 0; i < 14; i++)
-if (codec->extcaps & (1 << i))
-printf("%s%s", j++? ", " : "", ac97extfeature[i]);
-printf("n");
-}
-}
-
-i = 0;
-while ((ac97_rdcd(codec, AC97_REG_POWER) & 2) == 0) {
-if (++i == 100) {
-device_printf(codec->dev, "ac97 codec reports dac not readyn");
-break;
-}
-DELAY(1000);
-}
-if (bootverbose)
-device_printf(codec->dev, "ac97 codec dac ready count: %dn", i);
-snd_mtxunlock(codec->lock);
-return 0;
+ if (bootverbose) {
+ if (codec->flags & AC97_F_RDCD_BUG)
+ device_printf(codec->dev, "Buggy AC97 Codec: aggressive ac97_rdcd() workaround enabled\n");
+ device_printf(codec->dev, "Codec features ");
+ for (i = j = 0; i < 10; i++)
+ if (codec->caps & (1 << i))
+ printf("%s%s", j++? ", " : "", ac97feature[i]);
+ printf("%s%d bit master volume", j++? ", " : "", codec->mix[SOUND_MIXER_VOLUME].bits);
+ printf("%s%s\n", j? ", " : "", ac97enhancement[codec->se]);
+
+ if (codec->extcaps != 0 || codec->extid) {
+ device_printf(codec->dev, "%s codec",
+ codec->extid? "Secondary" : "Primary");
+ if (codec->extcaps)
+ printf(" extended features ");
+ for (i = j = 0; i < 14; i++)
+ if (codec->extcaps & (1 << i))
+ printf("%s%s", j++? ", " : "", ac97extfeature[i]);
+ printf("\n");
+ }
+ }
+
+ i = 0;
+ while ((ac97_rdcd(codec, AC97_REG_POWER) & 2) == 0) {
+ if (++i == 100) {
+ device_printf(codec->dev, "ac97 codec reports dac not ready\n");
+ break;
+ }
+ DELAY(1000);
+ }
+ if (bootverbose)
+ device_printf(codec->dev, "ac97 codec dac ready count: %d\n", i);
+ snd_mtxunlock(codec->lock);
+ return 0;
}
static unsigned
ac97_reinitmixer(struct ac97_info *codec)
{
-snd_mtxlock(codec->lock);
-codec->count = AC97_INIT(codec->methods, codec->devinfo);
-if (codec->count == 0) {
-device_printf(codec->dev, "ac97 codec init failedn");
-snd_mtxunlock(codec->lock);
-return ENODEV;
-}
-
-ac97_wrcd(codec, AC97_REG_POWER, (codec->flags & AC97_F_EAPD_INV)? 0x8000 : 0x0000);
-ac97_reset(codec);
-ac97_wrcd(codec, AC97_REG_POWER, (codec->flags & AC97_F_EAPD_INV)? 0x8000 : 0x0000);
-
-if (!codec->noext) {
-ac97_wrcd(codec, AC97_REGEXT_STAT, codec->extstat);
-if ((ac97_rdcd(codec, AC97_REGEXT_STAT) & AC97_EXTCAPS)
-!= codec->extstat)
-device_printf(codec->dev, "ac97 codec failed to reset extended mode (%x, got %x)n",
-codec->extstat,
-ac97_rdcd(codec, AC97_REGEXT_STAT) &
-AC97_EXTCAPS);
-}
-
-if ((ac97_rdcd(codec, AC97_REG_POWER) & 2) == 0)
-device_printf(codec->dev, "ac97 codec reports dac not readyn");
-snd_mtxunlock(codec->lock);
-return 0;
+ snd_mtxlock(codec->lock);
+ codec->count = AC97_INIT(codec->methods, codec->devinfo);
+ if (codec->count == 0) {
+ device_printf(codec->dev, "ac97 codec init failed\n");
+ snd_mtxunlock(codec->lock);
+ return ENODEV;
+ }
+
+ ac97_wrcd(codec, AC97_REG_POWER, (codec->flags & AC97_F_EAPD_INV)? 0x8000 : 0x0000);
+ ac97_reset(codec);
+ ac97_wrcd(codec, AC97_REG_POWER, (codec->flags & AC97_F_EAPD_INV)? 0x8000 : 0x0000);
+
+ if (!codec->noext) {
+ ac97_wrcd(codec, AC97_REGEXT_STAT, codec->extstat);
+ if ((ac97_rdcd(codec, AC97_REGEXT_STAT) & AC97_EXTCAPS)
+ != codec->extstat)
+ device_printf(codec->dev, "ac97 codec failed to reset extended mode (%x, got %x)\n",
+ codec->extstat,
+ ac97_rdcd(codec, AC97_REGEXT_STAT) &
+ AC97_EXTCAPS);
+ }
+
+ if ((ac97_rdcd(codec, AC97_REG_POWER) & 2) == 0)
+ device_printf(codec->dev, "ac97 codec reports dac not ready\n");
+ snd_mtxunlock(codec->lock);
+ return 0;
}
struct ac97_info *
ac97_create(device_t dev, void *devinfo, kobj_class_t cls)
{
-struct ac97_info *codec;
-int eapd_inv;
+ struct ac97_info *codec;
+ int eapdinv;
-codec = (struct ac97_info *)malloc(sizeof *codec, M_AC97, M_NOWAIT | M_ZERO);
-if (codec == NULL)
-return NULL;
-
-snprintf(codec->name, AC97_NAMELEN, "%s:ac97", device_get_nameunit(dev));
-codec->lock = snd_mtxcreate(codec->name, "ac97 codec");
-codec->methods = kobj_create(cls, M_AC97, M_WAITOK | M_ZERO);
-if (codec->methods == NULL) {
-snd_mtxlock(codec->lock);
-snd_mtxfree(codec->lock);
-free(codec, M_AC97);
-return NULL;
-}
-
-codec->dev = dev;
-codec->devinfo = devinfo;
-codec->flags = 0;
-if (resource_int_value(device_get_name(dev), device_get_unit(dev),
-"ac97_eapd_inv", &eapd_inv) == 0) {
-if (eapd_inv != 0)
-codec->flags |= AC97_F_EAPD_INV;
-}
-return codec;
+ codec = malloc(sizeof(*codec), M_AC97, M_WAITOK | M_ZERO);
+ snprintf(codec->name, sizeof(codec->name), "%s:ac97",
+ device_get_nameunit(dev));
+ codec->lock = snd_mtxcreate(codec->name, "ac97 codec");
+ codec->methods = kobj_create(cls, M_AC97, M_WAITOK | M_ZERO);
+ codec->dev = dev;
+ codec->devinfo = devinfo;
+ codec->flags = 0;
+ if (resource_int_value(device_get_name(dev), device_get_unit(dev),
+ "eapdinv", &eapdinv) == 0) {
+ if (eapdinv != 0)
+ codec->flags |= AC97_F_EAPD_INV;
+ }
+ return codec;
}
void
ac97_destroy(struct ac97_info *codec)
{
-snd_mtxlock(codec->lock);
-if (codec->methods != NULL)
-kobj_delete(codec->methods, M_AC97);
-snd_mtxfree(codec->lock);
-free(codec, M_AC97);
+ snd_mtxlock(codec->lock);
+ if (codec->methods != NULL)
+ kobj_delete(codec->methods, M_AC97);
+ snd_mtxfree(codec->lock);
+ free(codec, M_AC97);
}
void
ac97_setflags(struct ac97_info *codec, u_int32_t val)
{
-codec->flags = val;
+ codec->flags = val;
}
u_int32_t
ac97_getflags(struct ac97_info *codec)
{
-return codec->flags;
+ return codec->flags;
}
/* -------------------------------------------------------------------- */
+#ifdef SND_DYNSYSCTL
static int
-ac97mix_init(struct snd_mixer *m)
+sysctl_hw_snd_ac97_eapd(SYSCTL_HANDLER_ARGS)
{
-struct ac97_info *codec = mix_getdevinfo(m);
-struct snddev_info *d;
-u_int32_t i, mask;
-
-if (codec == NULL)
-return -1;
-
-if (ac97_initmixer(codec))
-return -1;
-
-mask = 0;
-for (i = 0; i < 32; i++)
-mask |= codec->mix[i].enable? 1 << i : 0;
-mix_setdevs(m, mask);
-
-switch (codec->id) {
-case 0x41445374: /* AD1981B */
-/*mask = 0;
-if (codec->mix[SOUND_MIXER_OGAIN].enable)
-mask |= SOUND_MASK_OGAIN;
-if (codec->mix[SOUND_MIXER_PHONEOUT].enable)
-mask |= SOUND_MASK_PHONEOUT;*/
-/* Tie ogain/phone to master volume */
-/*if (codec->mix[SOUND_MIXER_VOLUME].enable)
-mix_setparentchild(m, SOUND_MIXER_VOLUME, mask);
-else {
-mix_setparentchild(m, SOUND_MIXER_VOLUME, mask);
-mix_setrealdev(m, SOUND_MIXER_VOLUME, SOUND_MIXER_NONE);
-}*/
-break;
-case 0x434d4941: /* CMI9738 */
-case 0x434d4961: /* CMI9739 */
-case 0x434d4978: /* CMI9761 */
-case 0x434d4982: /* CMI9761 */
-case 0x434d4983: /* CMI9761 */
-ac97_wrcd(codec, AC97_MIX_PCM, 0);
-bzero(&codec->mix[SOUND_MIXER_PCM],
-sizeof(codec->mix[SOUND_MIXER_PCM]));
-d = device_get_softc(codec->dev);
-if (d != NULL)
-d->flags |= SD_F_SOFTPCMVOL;
-/* XXX How about master volume ? */
-break;
-default:
-break;
+ struct ac97_info *codec;
+ int ea, inv, err = 0;
+ u_int16_t val;
+
+ codec = oidp->oid_arg1;
+ if (codec == NULL || codec->id == 0 || codec->lock == NULL)
+ return EINVAL;
+ snd_mtxlock(codec->lock);
+ val = ac97_rdcd(codec, AC97_REG_POWER);
+ inv = (codec->flags & AC97_F_EAPD_INV) ? 0 : 1;
+ ea = (val >> 15) ^ inv;
+ snd_mtxunlock(codec->lock);
+ err = sysctl_handle_int(oidp, &ea, 0, req);
+ if (err == 0 && req->newptr != NULL) {
+ if (ea != 0 && ea != 1)
+ return EINVAL;
+ if (ea != ((val >> 15) ^ inv)) {
+ snd_mtxlock(codec->lock);
+ ac97_wrcd(codec, AC97_REG_POWER, val ^ 0x8000);
+ snd_mtxunlock(codec->lock);
+ }
+ }
+ return err;
}
+#endif
+
+static void
+ac97_init_sysctl(struct ac97_info *codec)
+{
+#ifdef SND_DYNSYSCTL
+ u_int16_t orig, val;
+
+ if (codec == NULL || codec->dev == NULL)
+ return;
+ snd_mtxlock(codec->lock);
+ orig = ac97_rdcd(codec, AC97_REG_POWER);
+ ac97_wrcd(codec, AC97_REG_POWER, orig ^ 0x8000);
+ val = ac97_rdcd(codec, AC97_REG_POWER);
+ ac97_wrcd(codec, AC97_REG_POWER, orig);
+ snd_mtxunlock(codec->lock);
+ if ((val & 0x8000) == (orig & 0x8000))
+ return;
+ SYSCTL_ADD_PROC(device_get_sysctl_ctx(codec->dev),
+ SYSCTL_CHILDREN(device_get_sysctl_tree(codec->dev)),
+ OID_AUTO, "eapd", CTLTYPE_INT | CTLFLAG_RW,
+ codec, sizeof(codec), sysctl_hw_snd_ac97_eapd,
+ "I", "AC97 External Amplifier");
+#endif
+}
+
+static int
+ac97mix_init(struct snd_mixer *m)
+{
+ struct ac97_info *codec = mix_getdevinfo(m);
+ u_int32_t i, mask;
+
+ if (codec == NULL)
+ return -1;
+
+ if (ac97_initmixer(codec))
+ return -1;
+
+ switch (codec->id) {
+ case 0x41445374: /* AD1981B */
+ switch (codec->subvendor) {
+ case 0x02d91014:
+ /*
+ * IBM Thinkcentre:
+ *
+ * Tie "ogain" and "phout" to "vol" since its
+ * master volume is basically useless and can't
+ * control anything.
+ */
+ mask = 0;
+ if (codec->mix[SOUND_MIXER_OGAIN].enable)
+ mask |= SOUND_MASK_OGAIN;
+ if (codec->mix[SOUND_MIXER_PHONEOUT].enable)
+ mask |= SOUND_MASK_PHONEOUT;
+ if (codec->mix[SOUND_MIXER_VOLUME].enable)
+ mix_setparentchild(m, SOUND_MIXER_VOLUME,
+ mask);
+ else {
+ mix_setparentchild(m, SOUND_MIXER_VOLUME,
+ mask);
+ mix_setrealdev(m, SOUND_MIXER_VOLUME,
+ SOUND_MIXER_NONE);
+ }
+ break;
+ case 0x099c103c:
+ /*
+ * HP nx6110:
+ *
+ * By default, "vol" is controlling internal speakers
+ * (not a master volume!) and "ogain" is controlling
+ * headphone. Enable dummy "phout" so it can be
+ * remapped to internal speakers and virtualize
+ * "vol" to control both.
+ */
+ codec->mix[SOUND_MIXER_OGAIN].enable = 1;
+ codec->mix[SOUND_MIXER_PHONEOUT].enable = 1;
+ mix_setrealdev(m, SOUND_MIXER_PHONEOUT,
+ SOUND_MIXER_VOLUME);
+ mix_setrealdev(m, SOUND_MIXER_VOLUME,
+ SOUND_MIXER_NONE);
+ mix_setparentchild(m, SOUND_MIXER_VOLUME,
+ SOUND_MASK_OGAIN | SOUND_MASK_PHONEOUT);
+ break;
+ default:
+ break;
+ }
+ break;
+ case 0x434d4941: /* CMI9738 */
+ case 0x434d4961: /* CMI9739 */
+ case 0x434d4978: /* CMI9761 */
+ case 0x434d4982: /* CMI9761 */
+ case 0x434d4983: /* CMI9761 */
+ ac97_wrcd(codec, AC97_MIX_PCM, 0);
+ bzero(&codec->mix[SOUND_MIXER_PCM],
+ sizeof(codec->mix[SOUND_MIXER_PCM]));
+ pcm_setflags(codec->dev, pcm_getflags(codec->dev) |
+ SD_F_SOFTPCMVOL);
+ /* XXX How about master volume ? */
+ break;
+ default:
+ break;
+ }
#if 0
-/* XXX For the sake of debugging purposes */
-mix_setparentchild(m, SOUND_MIXER_VOLUME,
-SOUND_MASK_PCM | SOUND_MASK_CD);
-mix_setrealdev(m, SOUND_MIXER_VOLUME, SOUND_MIXER_NONE);
-ac97_wrcd(codec, AC97_MIX_MASTER, 0);
+ /* XXX For the sake of debugging purposes */
+ mix_setparentchild(m, SOUND_MIXER_VOLUME,
+ SOUND_MASK_PCM | SOUND_MASK_CD);
+ mix_setrealdev(m, SOUND_MIXER_VOLUME, SOUND_MIXER_NONE);
+ ac97_wrcd(codec, AC97_MIX_MASTER, 0);
#endif
-mask = 0;
-for (i = 0; i < 32; i++)
-mask |= codec->mix[i].recidx? 1 << i : 0;
-mix_setrecdevs(m, mask);
-return 0;
+ mask = 0;
+ for (i = 0; i < AC97_MIXER_SIZE; i++)
+ mask |= codec->mix[i].enable? 1 << i : 0;
+ mix_setdevs(m, mask);
+
+ mask = 0;
+ for (i = 0; i < AC97_MIXER_SIZE; i++)
+ mask |= codec->mix[i].recidx? 1 << i : 0;
+ mix_setrecdevs(m, mask);
+
+ ac97_init_sysctl(codec);
+
+ return 0;
}
static int
ac97mix_uninit(struct snd_mixer *m)
{
-struct ac97_info *codec = mix_getdevinfo(m);
+ struct ac97_info *codec = mix_getdevinfo(m);
-if (codec == NULL)
-return -1;
-/*
-if (ac97_uninitmixer(codec))
-return -1;
-*/
-ac97_destroy(codec);
-return 0;
+ if (codec == NULL)
+ return -1;
+ /*
+ if (ac97_uninitmixer(codec))
+ return -1;
+ */
+ ac97_destroy(codec);
+ return 0;
}
static int
ac97mix_reinit(struct snd_mixer *m)
{
-struct ac97_info *codec = mix_getdevinfo(m);
+ struct ac97_info *codec = mix_getdevinfo(m);
-if (codec == NULL)
-return -1;
-return ac97_reinitmixer(codec);
+ if (codec == NULL)
+ return -1;
+ return ac97_reinitmixer(codec);
}
static int
ac97mix_set(struct snd_mixer *m, unsigned dev, unsigned left, unsigned right)
{
-struct ac97_info *codec = mix_getdevinfo(m);
+ struct ac97_info *codec = mix_getdevinfo(m);
-if (codec == NULL)
-return -1;
-return ac97_setmixer(codec, dev, left, right);
+ if (codec == NULL || dev >= AC97_MIXER_SIZE)
+ return -1;
+ return ac97_setmixer(codec, dev, left, right);
}
static int
ac97mix_setrecsrc(struct snd_mixer *m, u_int32_t src)
{
-int i;
-struct ac97_info *codec = mix_getdevinfo(m);
+ int i;
+ struct ac97_info *codec = mix_getdevinfo(m);
-if (codec == NULL)
-return -1;
-for (i = 0; i < SOUND_MIXER_NRDEVICES; i++)
-if ((src & (1 << i)) != 0)
-break;
-return (ac97_setrecsrc(codec, i) == 0)? 1 << i : -1;
+ if (codec == NULL)
+ return -1;
+ for (i = 0; i < AC97_MIXER_SIZE; i++)
+ if ((src & (1 << i)) != 0)
+ break;
+ return (ac97_setrecsrc(codec, i) == 0)? 1 << i : -1;
}
static kobj_method_t ac97mixer_methods[] = {
-KOBJMETHOD(mixer_init, ac97mix_init),
-KOBJMETHOD(mixer_uninit, ac97mix_uninit),
-KOBJMETHOD(mixer_reinit, ac97mix_reinit),
-KOBJMETHOD(mixer_set, ac97mix_set),
-KOBJMETHOD(mixer_setrecsrc, ac97mix_setrecsrc),
-{ 0, 0 }
+ KOBJMETHOD(mixer_init, ac97mix_init),
+ KOBJMETHOD(mixer_uninit, ac97mix_uninit),
+ KOBJMETHOD(mixer_reinit, ac97mix_reinit),
+ KOBJMETHOD(mixer_set, ac97mix_set),
+ KOBJMETHOD(mixer_setrecsrc, ac97mix_setrecsrc),
+ { 0, 0 }
};
MIXER_DECLARE(ac97mixer);
@@ -971,7 +1082,5 @@
kobj_class_t
ac97_getmixerclass(void)
{
-return &ac97mixer_class;
+ return &ac97mixer_class;
}
-
-
Index: feeder_rate.c
===================================================================
RCS file: /home/cvs/src/sys/dev/sound/pcm/feeder_rate.c,v
retrieving revision 1.2
retrieving revision 1.3
diff -L sys/dev/sound/pcm/feeder_rate.c -L sys/dev/sound/pcm/feeder_rate.c -u -r1.2 -r1.3
--- sys/dev/sound/pcm/feeder_rate.c
+++ sys/dev/sound/pcm/feeder_rate.c
@@ -1,832 +1,640 @@
/*-
-* Copyright (c) 1999 Cameron Grant <cg at FreeBSD.org>
-* Copyright (c) 2003 Orion Hodson <orion at FreeBSD.org>
-* Copyright (c) 2005 Ariff Abdullah <ariff at FreeBSD.org>
-* All rights reserved.
-*
-* Redistribution and use in source and binary forms, with or without
-* modification, are permitted provided that the following conditions
-* are met:
-* 1. Redistributions of source code must retain the above copyright
-* notice, this list of conditions and the following disclaimer.
-* 2. Redistributions in binary form must reproduce the above copyright
-* notice, this list of conditions and the following disclaimer in the
-* documentation and/or other materials provided with the distribution.
-*
-* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
-* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
-* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
-* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
-* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
-* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
-* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
-* SUCH DAMAGE.
-*
-* 2005-06-11:
-* ==========
-*
-* *New* and rewritten soft sample rate converter supporting arbitrary sample
-* rates, fine grained scaling/coefficients and a unified up/down stereo
-* converter. Most of the disclaimers from orion's notes also applies
-* here, regarding linear interpolation deficiencies and pre/post
-* anti-aliasing filtering issues. This version comes with a much simpler and
-* tighter interface, although it works almost exactly like the older one.
-*
-* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
-* *
-* This new implementation is fully dedicated in memory of Cameron Grant, *
-* the creator of the magnificent, highly addictive feeder infrastructure. *
-* *
-* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
-*
-* Orion's notes:
-* =============
-*
-* This rate conversion code uses linear interpolation without any
-* pre- or post- interpolation filtering to combat aliasing. This
-* greatly limits the sound quality and should be addressed at some
-* stage in the future.
-*
-* Since this accuracy of interpolation is sensitive and examination
-* of the algorithm output is harder from the kernel, the code is
-* designed to be compiled in the kernel and in a userland test
-* harness. This is done by selectively including and excluding code
-* with several portions based on whether _KERNEL is defined. It's a
-* little ugly, but exceedingly useful. The testsuite and its
-* revisions can be found at:
-* http://people.freebsd.org/~orion/files/feedrate/
-*
-* Special thanks to Ken Marx for exposing flaws in the code and for
-* testing revisions.
-*/
+ * Copyright (c) 1999 Cameron Grant <cg at FreeBSD.org>
+ * Copyright (c) 2003 Orion Hodson <orion at FreeBSD.org>
+ * Copyright (c) 2005 Ariff Abdullah <ariff at FreeBSD.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * 2006-02-21:
+ * ==========
+ *
+ * Major cleanup and overhaul to remove much redundant codes.
+ * Highlights:
+ * 1) Support for signed / unsigned 16, 24 and 32 bit,
+ * big / little endian,
+ * 2) Unlimited channels.
+ *
+ * 2005-06-11:
+ * ==========
+ *
+ * *New* and rewritten soft sample rate converter supporting arbitrary sample
+ * rates, fine grained scaling/coefficients and a unified up/down stereo
+ * converter. Most of the disclaimers from orion's notes also applies
+ * here, regarding linear interpolation deficiencies and pre/post
+ * anti-aliasing filtering issues. This version comes with a much simpler and
+ * tighter interface, although it works almost exactly like the older one.
+ *
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * *
+ * This new implementation is fully dedicated in memory of Cameron Grant, *
+ * the creator of the magnificent, highly addictive feeder infrastructure. *
+ * *
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ *
+ * Orion's notes:
+ * =============
+ *
+ * This rate conversion code uses linear interpolation without any
+ * pre- or post- interpolation filtering to combat aliasing. This
+ * greatly limits the sound quality and should be addressed at some
+ * stage in the future.
+ *
+ * Since this accuracy of interpolation is sensitive and examination
+ * of the algorithm output is harder from the kernel, the code is
+ * designed to be compiled in the kernel and in a userland test
+ * harness. This is done by selectively including and excluding code
+ * with several portions based on whether _KERNEL is defined. It's a
+ * little ugly, but exceedingly useful. The testsuite and its
+ * revisions can be found at:
+ * http://people.freebsd.org/~orion/files/feedrate/
+ *
+ * Special thanks to Ken Marx for exposing flaws in the code and for
+ * testing revisions.
+ */
#include <dev/sound/pcm/sound.h>
#include "feeder_if.h"
-SND_DECLARE_FILE("$MidnightBSD$");
+SND_DECLARE_FILE("$FreeBSD: src/sys/dev/sound/pcm/feeder_rate.c,v 1.23 2007/06/16 03:37:28 ariff Exp $");
-#define RATE_ASSERT(x, y) /* KASSERT(x,y) */
-#define RATE_TEST(x, y) /* if (!(x)) printf y */
-#define RATE_TRACE(x...) /* printf(x) */
+#define RATE_ASSERT(x, y) /* KASSERT(x,y) */
+#define RATE_TEST(x, y) /* if (!(x)) printf y */
+#define RATE_TRACE(x...) /* printf(x) */
MALLOC_DEFINE(M_RATEFEEDER, "ratefeed", "pcm rate feeder");
-#define FEEDBUFSZ 8192
-#define ROUNDHZ 25
-#define RATEMIN 4000
-/* 8000 * 138 or 11025 * 100 . This is insane, indeed! */
-#define RATEMAX 1102500
-#define MINGAIN 92
-#define MAXGAIN 96
-
-#define FEEDRATE_CONVERT_64 0
-#define FEEDRATE_CONVERT_SCALE64 1
-#define FEEDRATE_CONVERT_SCALE32 2
-#define FEEDRATE_CONVERT_PLAIN 3
-#define FEEDRATE_CONVERT_FIXED 4
-#define FEEDRATE_CONVERT_OPTIMAL 5
-#define FEEDRATE_CONVERT_WORST 6
+/*
+ * Don't overflow 32bit integer, since everything is done
+ * within 32bit arithmetic.
+ */
+#define RATE_FACTOR_MIN 1
+#define RATE_FACTOR_MAX PCM_S24_MAX
+#define RATE_FACTOR_SAFE(val) (!((val) < RATE_FACTOR_MIN || \
+ (val) > RATE_FACTOR_MAX))
+
+struct feed_rate_info;
-#define FEEDRATE_64_MAXROLL 32
-#define FEEDRATE_32_MAXROLL 16
+typedef uint32_t (*feed_rate_converter)(struct feed_rate_info *,
+ uint8_t *, uint32_t);
struct feed_rate_info {
-uint32_t src, dst; /* rounded source / destination rates */
-uint32_t rsrc, rdst; /* original source / destination rates */
-uint32_t gx, gy; /* interpolation / decimation ratio */
-uint32_t alpha; /* interpolation distance */
-uint32_t pos, bpos; /* current sample / buffer positions */
-uint32_t bufsz; /* total buffer size */
-uint32_t stray; /* stray bytes */
-int32_t scale, roll; /* scale / roll factor */
-int16_t *buffer;
-uint32_t (*convert)(struct feed_rate_info *, int16_t *, uint32_t);
+ uint32_t src, dst; /* rounded source / destination rates */
+ uint32_t rsrc, rdst; /* original source / destination rates */
+ uint32_t gx, gy; /* interpolation / decimation ratio */
+ uint32_t alpha; /* interpolation distance */
+ uint32_t pos, bpos; /* current sample / buffer positions */
+ uint32_t bufsz; /* total buffer size limit */
+ uint32_t bufsz_init; /* allocated buffer size */
+ uint32_t channels; /* total channels */
+ uint32_t bps; /* bytes-per-sample */
+#ifdef FEEDRATE_STRAY
+ uint32_t stray; /* stray bytes */
+#endif
+ uint8_t *buffer;
+ feed_rate_converter convert;
};
-static uint32_t
-feed_convert_64(struct feed_rate_info *, int16_t *, uint32_t);
-static uint32_t
-feed_convert_scale64(struct feed_rate_info *, int16_t *, uint32_t);
-static uint32_t
-feed_convert_scale32(struct feed_rate_info *, int16_t *, uint32_t);
-static uint32_t
-feed_convert_plain(struct feed_rate_info *, int16_t *, uint32_t);
-
-int feeder_rate_ratemin = RATEMIN;
-int feeder_rate_ratemax = RATEMAX;
-/*
-* See 'Feeder Scaling Type' below..
-*/
-static int feeder_rate_scaling = FEEDRATE_CONVERT_OPTIMAL;
-static int feeder_rate_buffersize = FEEDBUFSZ & ~1;
-
-#if 0
-/*
-* sysctls.. I love sysctls..
-*/
-TUNABLE_INT("hw.snd.feeder_rate_ratemin", &feeder_rate_ratemin);
-TUNABLE_INT("hw.snd.feeder_rate_ratemax", &feeder_rate_ratemin);
-TUNABLE_INT("hw.snd.feeder_rate_scaling", &feeder_rate_scaling);
-TUNABLE_INT("hw.snd.feeder_rate_buffersize", &feeder_rate_buffersize);
+int feeder_rate_min = FEEDRATE_RATEMIN;
+int feeder_rate_max = FEEDRATE_RATEMAX;
+int feeder_rate_round = FEEDRATE_ROUNDHZ;
+
+TUNABLE_INT("hw.snd.feeder_rate_min", &feeder_rate_min);
+TUNABLE_INT("hw.snd.feeder_rate_max", &feeder_rate_max);
+TUNABLE_INT("hw.snd.feeder_rate_round", &feeder_rate_round);
static int
-sysctl_hw_snd_feeder_rate_ratemin(SYSCTL_HANDLER_ARGS)
+sysctl_hw_snd_feeder_rate_min(SYSCTL_HANDLER_ARGS)
{
-int err, val;
+ int err, val;
-val = feeder_rate_ratemin;
-err = sysctl_handle_int(oidp, &val, sizeof(val), req);
-if (val < 1 || val >= feeder_rate_ratemax)
-err = EINVAL;
-else
-feeder_rate_ratemin = val;
-return err;
-}
-SYSCTL_PROC(_hw_snd, OID_AUTO, feeder_rate_ratemin, CTLTYPE_INT | CTLFLAG_RW,
-0, sizeof(int), sysctl_hw_snd_feeder_rate_ratemin, "I", "");
+ val = feeder_rate_min;
+ err = sysctl_handle_int(oidp, &val, 0, req);
+ if (err != 0 || req->newptr == NULL)
+ return (err);
+ if (RATE_FACTOR_SAFE(val) && val < feeder_rate_max)
+ feeder_rate_min = val;
+ else
+ err = EINVAL;
+ return (err);
+}
+SYSCTL_PROC(_hw_snd, OID_AUTO, feeder_rate_min, CTLTYPE_INT | CTLFLAG_RW,
+ 0, sizeof(int), sysctl_hw_snd_feeder_rate_min, "I",
+ "minimum allowable rate");
static int
-sysctl_hw_snd_feeder_rate_ratemax(SYSCTL_HANDLER_ARGS)
+sysctl_hw_snd_feeder_rate_max(SYSCTL_HANDLER_ARGS)
{
-int err, val;
+ int err, val;
-val = feeder_rate_ratemax;
-err = sysctl_handle_int(oidp, &val, sizeof(val), req);
-if (val <= feeder_rate_ratemin || val > 0x7fffff)
-err = EINVAL;
-else
-feeder_rate_ratemax = val;
-return err;
-}
-SYSCTL_PROC(_hw_snd, OID_AUTO, feeder_rate_ratemax, CTLTYPE_INT | CTLFLAG_RW,
-0, sizeof(int), sysctl_hw_snd_feeder_rate_ratemax, "I", "");
+ val = feeder_rate_max;
+ err = sysctl_handle_int(oidp, &val, 0, req);
+ if (err != 0 || req->newptr == NULL)
+ return (err);
+ if (RATE_FACTOR_SAFE(val) && val > feeder_rate_min)
+ feeder_rate_max = val;
+ else
+ err = EINVAL;
+ return (err);
+}
+SYSCTL_PROC(_hw_snd, OID_AUTO, feeder_rate_max, CTLTYPE_INT | CTLFLAG_RW,
+ 0, sizeof(int), sysctl_hw_snd_feeder_rate_max, "I",
+ "maximum allowable rate");
static int
-sysctl_hw_snd_feeder_rate_scaling(SYSCTL_HANDLER_ARGS)
+sysctl_hw_snd_feeder_rate_round(SYSCTL_HANDLER_ARGS)
{
-int err, val;
+ int err, val;
-val = feeder_rate_scaling;
-err = sysctl_handle_int(oidp, &val, sizeof(val), req);
-/*
-* Feeder Scaling Type
-* ===================
-*
-* 1. Plain 64bit (high precision)
-* 2. 64bit scaling (high precision, CPU friendly, but can
-* cause gain up/down).
-* 3. 32bit scaling (somehow can cause hz roundup, gain
-* up/down).
-* 4. Plain copy (default if src == dst. Except if src == dst,
-* this is the worst / silly conversion method!).
-*
-* Sysctl options:-
-*
-* 0 - Plain 64bit - no fallback.
-* 1 - 64bit scaling - no fallback.
-* 2 - 32bit scaling - no fallback.
-* 3 - Plain copy - no fallback.
-* 4 - Fixed rate. Means that, choose optimal conversion method
-* without causing hz roundup.
-* 32bit scaling (as long as hz roundup does not occur),
-* 64bit scaling, Plain 64bit.
-* 5 - Optimal / CPU friendly (DEFAULT).
-* 32bit scaling, 64bit scaling, Plain 64bit
-* 6 - Optimal to worst, no 64bit arithmetic involved.
-* 32bit scaling, Plain copy.
-*/
-if (val < FEEDRATE_CONVERT_64 || val > FEEDRATE_CONVERT_WORST)
-err = EINVAL;
-else
-feeder_rate_scaling = val;
-return err;
-}
-SYSCTL_PROC(_hw_snd, OID_AUTO, feeder_rate_scaling, CTLTYPE_INT | CTLFLAG_RW,
-0, sizeof(int), sysctl_hw_snd_feeder_rate_scaling, "I", "");
-
-static int
-sysctl_hw_snd_feeder_rate_buffersize(SYSCTL_HANDLER_ARGS)
-{
-int err, val;
-
-val = feeder_rate_buffersize;
-err = sysctl_handle_int(oidp, &val, sizeof(val), req);
-/*
-* Don't waste too much kernel space
-*/
-if (val < 2 || val > 65536)
-err = EINVAL;
-else
-feeder_rate_buffersize = val & ~1;
-return err;
-}
-SYSCTL_PROC(_hw_snd, OID_AUTO, feeder_rate_buffersize, CTLTYPE_INT | CTLFLAG_RW,
-0, sizeof(int), sysctl_hw_snd_feeder_rate_buffersize, "I", "");
-#endif
+ val = feeder_rate_round;
+ err = sysctl_handle_int(oidp, &val, 0, req);
+ if (err != 0 || req->newptr == NULL)
+ return (err);
+ if (val < FEEDRATE_ROUNDHZ_MIN || val > FEEDRATE_ROUNDHZ_MAX)
+ err = EINVAL;
+ else
+ feeder_rate_round = val - (val % FEEDRATE_ROUNDHZ);
+ return (err);
+}
+SYSCTL_PROC(_hw_snd, OID_AUTO, feeder_rate_round, CTLTYPE_INT | CTLFLAG_RW,
+ 0, sizeof(int), sysctl_hw_snd_feeder_rate_round, "I",
+ "sample rate converter rounding threshold");
+
+#define FEEDER_RATE_CONVERT(FMTBIT, RATE_INTCAST, SIGN, SIGNS, ENDIAN, ENDIANS) \
+static uint32_t \
+feed_convert_##SIGNS##FMTBIT##ENDIANS(struct feed_rate_info *info, \
+ uint8_t *dst, uint32_t max) \
+{ \
+ uint32_t ret, smpsz, ch, pos, bpos, gx, gy, alpha, d1, d2; \
+ int32_t x, y; \
+ int i; \
+ uint8_t *src, *sx, *sy; \
+ \
+ ret = 0; \
+ alpha = info->alpha; \
+ gx = info->gx; \
+ gy = info->gy; \
+ pos = info->pos; \
+ bpos = info->bpos; \
+ src = info->buffer + pos; \
+ ch = info->channels; \
+ smpsz = PCM_##FMTBIT##_BPS * ch; \
+ for (;;) { \
+ if (alpha < gx) { \
+ alpha += gy; \
+ pos += smpsz; \
+ if (pos == bpos) \
+ break; \
+ src += smpsz; \
+ } else { \
+ alpha -= gx; \
+ d1 = (alpha << PCM_FXSHIFT) / gy; \
+ d2 = (1U << PCM_FXSHIFT) - d1; \
+ sx = src - smpsz; \
+ sy = src; \
+ i = ch; \
+ do { \
+ x = PCM_READ_##SIGN##FMTBIT##_##ENDIAN(sx); \
+ y = PCM_READ_##SIGN##FMTBIT##_##ENDIAN(sy); \
+ x = (((RATE_INTCAST)x * d1) + \
+ ((RATE_INTCAST)y * d2)) >> PCM_FXSHIFT; \
+ PCM_WRITE_##SIGN##FMTBIT##_##ENDIAN(dst, x); \
+ dst += PCM_##FMTBIT##_BPS; \
+ sx += PCM_##FMTBIT##_BPS; \
+ sy += PCM_##FMTBIT##_BPS; \
+ ret += PCM_##FMTBIT##_BPS; \
+ } while (--i != 0); \
+ if (ret == max) \
+ break; \
+ } \
+ } \
+ info->alpha = alpha; \
+ info->pos = pos; \
+ return (ret); \
+}
+
+FEEDER_RATE_CONVERT(8, int32_t, S, s, NE, ne)
+FEEDER_RATE_CONVERT(16, int32_t, S, s, LE, le)
+FEEDER_RATE_CONVERT(24, int32_t, S, s, LE, le)
+FEEDER_RATE_CONVERT(32, intpcm_t, S, s, LE, le)
+FEEDER_RATE_CONVERT(16, int32_t, S, s, BE, be)
+FEEDER_RATE_CONVERT(24, int32_t, S, s, BE, be)
+FEEDER_RATE_CONVERT(32, intpcm_t, S, s, BE, be)
+FEEDER_RATE_CONVERT(8, int32_t, U, u, NE, ne)
+FEEDER_RATE_CONVERT(16, int32_t, U, u, LE, le)
+FEEDER_RATE_CONVERT(24, int32_t, U, u, LE, le)
+FEEDER_RATE_CONVERT(32, intpcm_t, U, u, LE, le)
+FEEDER_RATE_CONVERT(16, int32_t, U, u, BE, be)
+FEEDER_RATE_CONVERT(24, int32_t, U, u, BE, be)
+FEEDER_RATE_CONVERT(32, intpcm_t, U, u, BE, be)
static void
-feed_speed_ratio(uint32_t x, uint32_t y, uint32_t *gx, uint32_t *gy)
+feed_speed_ratio(uint32_t src, uint32_t dst, uint32_t *gx, uint32_t *gy)
{
-uint32_t w, src = x, dst = y;
+ uint32_t w, x = src, y = dst;
-while (y != 0) {
-w = x % y;
-x = y;
-y = w;
-}
-*gx = src / x;
-*gy = dst / x;
-}
-
-static void
-feed_scale_roll(uint32_t dst, int32_t *scale, int32_t *roll, int32_t max)
-{
-int64_t k, tscale;
-int32_t j, troll;
-
-*scale = *roll = -1;
-for (j = MAXGAIN; j >= MINGAIN; j -= 3) {
-for (troll = 0; troll < max; troll++) {
-tscale = (1 << troll) / dst;
-k = (tscale * dst * 100) >> troll;
-if (k > j && k <= 100) {
-*scale = tscale;
-*roll = troll;
-return;
-}
-}
-}
-}
-
-static int
-feed_get_best_coef(uint32_t *src, uint32_t *dst, uint32_t *gx, uint32_t *gy,
-int32_t *scale, int32_t *roll)
-{
-uint32_t tsrc, tdst, sscale, dscale;
-int32_t tscale, troll;
-int i, j, hzmin, hzmax;
-
-*scale = *roll = -1;
-for (i = 0; i < 2; i++) {
-hzmin = (ROUNDHZ * i) + 1;
-hzmax = hzmin + ROUNDHZ;
-for (j = hzmin; j < hzmax; j++) {
-tsrc = *src - (*src % j);
-tdst = *dst;
-if (tsrc < 1 || tdst < 1)
-goto coef_failed;
-feed_speed_ratio(tsrc, tdst, &sscale, &dscale);
-feed_scale_roll(dscale, &tscale, &troll,
-FEEDRATE_32_MAXROLL);
-if (tscale != -1 && troll != -1) {
-*src = tsrc;
-*gx = sscale;
-*gy = dscale;
-*scale = tscale;
-*roll = troll;
-return j;
-}
-}
-for (j = hzmin; j < hzmax; j++) {
-tsrc = *src - (*src % j);
-tdst = *dst - (*dst % j);
-if (tsrc < 1 || tdst < 1)
-goto coef_failed;
-feed_speed_ratio(tsrc, tdst, &sscale, &dscale);
-feed_scale_roll(dscale, &tscale, &troll,
-FEEDRATE_32_MAXROLL);
-if (tscale != -1 && troll != -1) {
-*src = tsrc;
-*dst = tdst;
-*gx = sscale;
-*gy = dscale;
-*scale = tscale;
-*roll = troll;
-return j;
-}
-}
-for (j = hzmin; j < hzmax; j++) {
-tsrc = *src;
-tdst = *dst - (*dst % j);
-if (tsrc < 1 || tdst < 1)
-goto coef_failed;
-feed_speed_ratio(tsrc, tdst, &sscale, &dscale);
-feed_scale_roll(dscale, &tscale, &troll,
-FEEDRATE_32_MAXROLL);
-if (tscale != -1 && troll != -1) {
-*src = tsrc;
-*dst = tdst;
-*gx = sscale;
-*gy = dscale;
-*scale = tscale;
-*roll = troll;
-return j;
-}
-}
-}
-coef_failed:
-feed_speed_ratio(*src, *dst, gx, gy);
-feed_scale_roll(*gy, scale, roll, FEEDRATE_32_MAXROLL);
-return 0;
+ while (y != 0) {
+ w = x % y;
+ x = y;
+ y = w;
+ }
+ *gx = src / x;
+ *gy = dst / x;
}
static void
feed_rate_reset(struct feed_rate_info *info)
{
-info->scale = -1;
-info->roll = -1;
-info->src = info->rsrc;
-info->dst = info->rdst;
-info->gx = 0;
-info->gy = 0;
+ info->src = info->rsrc - (info->rsrc %
+ ((feeder_rate_round > 0) ? feeder_rate_round : 1));
+ info->dst = info->rdst - (info->rdst %
+ ((feeder_rate_round > 0) ? feeder_rate_round : 1));
+ info->gx = 1;
+ info->gy = 1;
+ info->alpha = 0;
+ info->channels = 1;
+ info->bps = PCM_8_BPS;
+ info->convert = NULL;
+ info->bufsz = info->bufsz_init;
+ info->pos = 1;
+ info->bpos = 2;
+#ifdef FEEDRATE_STRAY
+ info->stray = 0;
+#endif
}
static int
feed_rate_setup(struct pcm_feeder *f)
{
-struct feed_rate_info *info = f->data;
-int r = 0;
+ struct feed_rate_info *info = f->data;
+ static const struct {
+ uint32_t format; /* pcm / audio format */
+ uint32_t bps; /* bytes-per-sample, regardless of
+ total channels */
+ feed_rate_converter convert;
+ } convtbl[] = {
+ { AFMT_S8, PCM_8_BPS, feed_convert_s8ne },
+ { AFMT_S16_LE, PCM_16_BPS, feed_convert_s16le },
+ { AFMT_S24_LE, PCM_24_BPS, feed_convert_s24le },
+ { AFMT_S32_LE, PCM_32_BPS, feed_convert_s32le },
+ { AFMT_S16_BE, PCM_16_BPS, feed_convert_s16be },
+ { AFMT_S24_BE, PCM_24_BPS, feed_convert_s24be },
+ { AFMT_S32_BE, PCM_32_BPS, feed_convert_s32be },
+ { AFMT_U8, PCM_8_BPS, feed_convert_u8ne },
+ { AFMT_U16_LE, PCM_16_BPS, feed_convert_u16le },
+ { AFMT_U24_LE, PCM_24_BPS, feed_convert_u24le },
+ { AFMT_U32_LE, PCM_32_BPS, feed_convert_u32le },
+ { AFMT_U16_BE, PCM_16_BPS, feed_convert_u16be },
+ { AFMT_U24_BE, PCM_24_BPS, feed_convert_u24be },
+ { AFMT_U32_BE, PCM_32_BPS, feed_convert_u32be },
+ { 0, 0, NULL },
+ };
+ uint32_t i;
+
+ feed_rate_reset(info);
+
+ if (info->src != info->dst)
+ feed_speed_ratio(info->src, info->dst, &info->gx, &info->gy);
+
+ if (!(RATE_FACTOR_SAFE(info->gx) && RATE_FACTOR_SAFE(info->gy)))
+ return (-1);
+
+ for (i = 0; i < sizeof(convtbl) / sizeof(convtbl[0]); i++) {
+ if (convtbl[i].format == 0)
+ return (-1);
+ if ((f->desc->out & ~AFMT_STEREO) == convtbl[i].format) {
+ info->bps = convtbl[i].bps;
+ info->convert = convtbl[i].convert;
+ break;
+ }
+ }
+
+ /*
+ * No need to interpolate/decimate, just do plain copy.
+ */
+ if (info->gx == info->gy)
+ info->convert = NULL;
+
+ info->channels = (f->desc->out & AFMT_STEREO) ? 2 : 1;
+ info->pos = info->bps * info->channels;
+ info->bpos = info->pos << 1;
+ info->bufsz -= info->bufsz % info->pos;
+
+ memset(info->buffer, sndbuf_zerodata(f->desc->out), info->bpos);
+
+ RATE_TRACE("%s: %u (%u) -> %u (%u) [%u/%u] , "
+ "format=0x%08x, channels=%u, bufsz=%u\n",
+ __func__, info->src, info->rsrc, info->dst, info->rdst,
+ info->gx, info->gy, f->desc->out, info->channels,
+ info->bufsz - info->pos);
-info->pos = 2;
-info->bpos = 4;
-info->alpha = 0;
-info->stray = 0;
-feed_rate_reset(info);
-if (info->src == info->dst) {
-/*
-* No conversion ever needed. Just do plain copy.
-*/
-info->convert = feed_convert_plain;
-info->gx = 1;
-info->gy = 1;
-} else {
-switch (feeder_rate_scaling) {
-case FEEDRATE_CONVERT_64:
-feed_speed_ratio(info->src, info->dst,
-&info->gx, &info->gy);
-info->convert = feed_convert_64;
-break;
-case FEEDRATE_CONVERT_SCALE64:
-feed_speed_ratio(info->src, info->dst,
-&info->gx, &info->gy);
-feed_scale_roll(info->gy, &info->scale,
-&info->roll, FEEDRATE_64_MAXROLL);
-if (info->scale == -1 || info->roll == -1)
-return -1;
-info->convert = feed_convert_scale64;
-break;
-case FEEDRATE_CONVERT_SCALE32:
-r = feed_get_best_coef(&info->src, &info->dst,
-&info->gx, &info->gy, &info->scale,
-&info->roll);
-if (r == 0)
-return -1;
-info->convert = feed_convert_scale32;
-break;
-case FEEDRATE_CONVERT_PLAIN:
-feed_speed_ratio(info->src, info->dst,
-&info->gx, &info->gy);
-info->convert = feed_convert_plain;
-break;
-case FEEDRATE_CONVERT_FIXED:
-r = feed_get_best_coef(&info->src, &info->dst,
-&info->gx, &info->gy, &info->scale,
-&info->roll);
-if (r != 0 && info->src == info->rsrc &&
-info->dst == info->rdst)
-info->convert = feed_convert_scale32;
-else {
-/* Fallback */
-feed_rate_reset(info);
-feed_speed_ratio(info->src, info->dst,
-&info->gx, &info->gy);
-feed_scale_roll(info->gy, &info->scale,
-&info->roll, FEEDRATE_64_MAXROLL);
-if (info->scale != -1 && info->roll != -1)
-info->convert = feed_convert_scale64;
-else
-info->convert = feed_convert_64;
-}
-break;
-case FEEDRATE_CONVERT_OPTIMAL:
-r = feed_get_best_coef(&info->src, &info->dst,
-&info->gx, &info->gy, &info->scale,
-&info->roll);
-if (r != 0)
-info->convert = feed_convert_scale32;
-else {
-/* Fallback */
-feed_rate_reset(info);
-feed_speed_ratio(info->src, info->dst,
-&info->gx, &info->gy);
-feed_scale_roll(info->gy, &info->scale,
-&info->roll, FEEDRATE_64_MAXROLL);
-if (info->scale != -1 && info->roll != -1)
-info->convert = feed_convert_scale64;
-else
-info->convert = feed_convert_64;
-}
-break;
-case FEEDRATE_CONVERT_WORST:
-r = feed_get_best_coef(&info->src, &info->dst,
-&info->gx, &info->gy, &info->scale,
-&info->roll);
-if (r != 0)
-info->convert = feed_convert_scale32;
-else {
-/* Fallback */
-feed_rate_reset(info);
-feed_speed_ratio(info->src, info->dst,
-&info->gx, &info->gy);
-info->convert = feed_convert_plain;
-}
-break;
-default:
-return -1;
-break;
-}
-/* No way! */
-if (info->gx == 0 || info->gy == 0)
-return -1;
-/*
-* No need to interpolate/decimate, just do plain copy.
-* This probably caused by Hz roundup.
-*/
-if (info->gx == info->gy)
-info->convert = feed_convert_plain;
-}
-return 0;
+ return (0);
}
static int
-feed_rate_set(struct pcm_feeder *f, int what, int value)
+feed_rate_set(struct pcm_feeder *f, int what, int32_t value)
{
-struct feed_rate_info *info = f->data;
+ struct feed_rate_info *info = f->data;
-if (value < feeder_rate_ratemin || value > feeder_rate_ratemax)
-return -1;
+ if (value < feeder_rate_min || value > feeder_rate_max)
+ return (-1);
-switch (what) {
-case FEEDRATE_SRC:
-info->rsrc = value;
-break;
-case FEEDRATE_DST:
-info->rdst = value;
-break;
-default:
-return -1;
-}
-return feed_rate_setup(f);
+ switch (what) {
+ case FEEDRATE_SRC:
+ info->rsrc = value;
+ break;
+ case FEEDRATE_DST:
+ info->rdst = value;
+ break;
+ default:
+ return (-1);
+ }
+ return (feed_rate_setup(f));
}
static int
feed_rate_get(struct pcm_feeder *f, int what)
{
-struct feed_rate_info *info = f->data;
+ struct feed_rate_info *info = f->data;
-/*
-* Return *real* src/dst rate.
-*/
-switch (what) {
-case FEEDRATE_SRC:
-return info->rsrc;
-case FEEDRATE_DST:
-return info->rdst;
-default:
-return -1;
-}
-return -1;
+ switch (what) {
+ case FEEDRATE_SRC:
+ return (info->rsrc);
+ case FEEDRATE_DST:
+ return (info->rdst);
+ default:
+ return (-1);
+ }
+ return (-1);
}
static int
feed_rate_init(struct pcm_feeder *f)
{
-struct feed_rate_info *info;
+ struct feed_rate_info *info;
-info = malloc(sizeof(*info), M_RATEFEEDER, M_NOWAIT | M_ZERO);
-if (info == NULL)
-return ENOMEM;
-/*
-* bufsz = sample from last cycle + conversion space
-*/
-info->bufsz = 2 + feeder_rate_buffersize;
-info->buffer = malloc(sizeof(*info->buffer) * info->bufsz,
-M_RATEFEEDER, M_NOWAIT | M_ZERO);
-if (info->buffer == NULL) {
-free(info, M_RATEFEEDER);
-return ENOMEM;
-}
-info->rsrc = DSP_DEFAULT_SPEED;
-info->rdst = DSP_DEFAULT_SPEED;
-f->data = info;
-return feed_rate_setup(f);
+ if (f->desc->out != f->desc->in)
+ return (EINVAL);
+
+ info = malloc(sizeof(*info), M_RATEFEEDER, M_NOWAIT | M_ZERO);
+ if (info == NULL)
+ return (ENOMEM);
+ /*
+ * bufsz = sample from last cycle + conversion space
+ */
+ info->bufsz_init = 8 + feeder_buffersize;
+ info->buffer = malloc(info->bufsz_init, M_RATEFEEDER,
+ M_NOWAIT | M_ZERO);
+ if (info->buffer == NULL) {
+ free(info, M_RATEFEEDER);
+ return (ENOMEM);
+ }
+ info->rsrc = DSP_DEFAULT_SPEED;
+ info->rdst = DSP_DEFAULT_SPEED;
+ f->data = info;
+ return (feed_rate_setup(f));
}
static int
feed_rate_free(struct pcm_feeder *f)
{
-struct feed_rate_info *info = f->data;
-
-if (info) {
-if (info->buffer)
-free(info->buffer, M_RATEFEEDER);
-free(info, M_RATEFEEDER);
-}
-f->data = NULL;
-return 0;
-}
+ struct feed_rate_info *info = f->data;
-static uint32_t
-feed_convert_64(struct feed_rate_info *info, int16_t *dst, uint32_t max)
-{
-int64_t x, alpha, distance;
-uint32_t ret;
-int32_t pos, bpos, gx, gy;
-int16_t *src;
-/*
-* Plain, straight forward 64bit arith. No bit-magic applied here.
-*/
-ret = 0;
-alpha = info->alpha;
-gx = info->gx;
-gy = info->gy;
-pos = info->pos;
-bpos = info->bpos;
-src = info->buffer;
-for (;;) {
-if (alpha < gx) {
-alpha += gy;
-pos += 2;
-if (pos == bpos)
-break;
-} else {
-alpha -= gx;
-distance = gy - alpha;
-x = (alpha * src[pos - 2]) + (distance * src[pos]);
-dst[ret++] = x / gy;
-x = (alpha * src[pos - 1]) + (distance * src[pos + 1]);
-dst[ret++] = x / gy;
-if (ret == max)
-break;
-}
-}
-info->alpha = alpha;
-info->pos = pos;
-return ret;
-}
-
-static uint32_t
-feed_convert_scale64(struct feed_rate_info *info, int16_t *dst, uint32_t max)
-{
-int64_t x, alpha, distance;
-uint32_t ret;
-int32_t pos, bpos, gx, gy, roll;
-int16_t *src;
-/*
-* 64bit scaling.
-*/
-ret = 0;
-roll = info->roll;
-alpha = info->alpha * info->scale;
-gx = info->gx * info->scale;
-gy = info->gy * info->scale;
-pos = info->pos;
-bpos = info->bpos;
-src = info->buffer;
-for (;;) {
-if (alpha < gx) {
-alpha += gy;
-pos += 2;
-if (pos == bpos)
-break;
-} else {
-alpha -= gx;
-distance = gy - alpha;
-x = (alpha * src[pos - 2]) + (distance * src[pos]);
-dst[ret++] = x >> roll;
-x = (alpha * src[pos - 1]) + (distance * src[pos + 1]);
-dst[ret++] = x >> roll;
-if (ret == max)
-break;
-}
-}
-info->alpha = alpha / info->scale;
-info->pos = pos;
-return ret;
-}
-
-static uint32_t
-feed_convert_scale32(struct feed_rate_info *info, int16_t *dst, uint32_t max)
-{
-uint32_t ret;
-int32_t x, pos, bpos, gx, gy, alpha, roll, distance;
-int16_t *src;
-/*
-* 32bit scaling.
-*/
-ret = 0;
-roll = info->roll;
-alpha = info->alpha * info->scale;
-gx = info->gx * info->scale;
-gy = info->gy * info->scale;
-pos = info->pos;
-bpos = info->bpos;
-src = info->buffer;
-for (;;) {
-if (alpha < gx) {
-alpha += gy;
-pos += 2;
-if (pos == bpos)
-break;
-} else {
-alpha -= gx;
-distance = gy - alpha;
-x = (alpha * src[pos - 2]) + (distance * src[pos]);
-dst[ret++] = x >> roll;
-x = (alpha * src[pos - 1]) + (distance * src[pos + 1]);
-dst[ret++] = x >> roll;
-if (ret == max)
-break;
-}
-}
-info->alpha = alpha / info->scale;
-info->pos = pos;
-return ret;
-}
-
-static uint32_t
-feed_convert_plain(struct feed_rate_info *info, int16_t *dst, uint32_t max)
-{
-uint32_t ret;
-int32_t pos, bpos, gx, gy, alpha;
-int16_t *src;
-/*
-* Plain copy.
-*/
-ret = 0;
-gx = info->gx;
-gy = info->gy;
-alpha = info->alpha;
-pos = info->pos;
-bpos = info->bpos;
-src = info->buffer;
-for (;;) {
-if (alpha < gx) {
-alpha += gy;
-pos += 2;
-if (pos == bpos)
-break;
-} else {
-alpha -= gx;
-dst[ret++] = src[pos];
-dst[ret++] = src[pos + 1];
-if (ret == max)
-break;
-}
-}
-info->pos = pos;
-info->alpha = alpha;
-return ret;
+ if (info != NULL) {
+ if (info->buffer != NULL)
+ free(info->buffer, M_RATEFEEDER);
+ free(info, M_RATEFEEDER);
+ }
+ f->data = NULL;
+ return (0);
}
-static int32_t
+static int
feed_rate(struct pcm_feeder *f, struct pcm_channel *c, uint8_t *b,
-uint32_t count, void *source)
+ uint32_t count, void *source)
{
-struct feed_rate_info *info = f->data;
-uint32_t i;
-int32_t fetch, slot;
-int16_t *dst = (int16_t *)b;
-/*
-* This loop has been optimized to generalize both up / down
-* sampling without causing missing samples or excessive buffer
-* feeding.
-*/
-RATE_TEST(count >= 4 && (count & 3) == 0,
-("%s: Count size not byte integral (%d)n", __func__, count));
-if (count < 4)
-return 0;
-count >>= 1;
-count &= ~1;
-slot = (((info->gx * (count >> 1)) + info->gy - info->alpha - 1) / info->gy) << 1;
-RATE_TEST((slot & 1) == 0, ("%s: Slot count not sample integral (%d)n",
-__func__, slot));
-/*
-* Optimize buffer feeding aggressively to ensure calculated slot
-* can be fitted nicely into available buffer free space, hence
-* avoiding multiple feeding.
-*/
-RATE_TEST(info->stray == 0, ("%s: [1] Stray bytes: %un",
-__func__,info->stray));
-if (info->pos != 2 && info->bpos - info->pos == 2 &&
-info->bpos + slot > info->bufsz) {
-/*
-* Copy last unit sample and its previous to
-* beginning of buffer.
-*/
-info->buffer[0] = info->buffer[info->pos - 2];
-info->buffer[1] = info->buffer[info->pos - 1];
-info->buffer[2] = info->buffer[info->pos];
-info->buffer[3] = info->buffer[info->pos + 1];
-info->pos = 2;
-info->bpos = 4;
-}
-RATE_ASSERT(slot >= 0, ("%s: Negative Slot: %dn",
-__func__, slot));
-i = 0;
-for (;;) {
-for (;;) {
-fetch = (info->bufsz - info->bpos) << 1;
-fetch -= info->stray;
-RATE_ASSERT(fetch >= 0,
-("%s: [1] Buffer overrun: %d > %dn",
-__func__, info->bpos, info->bufsz));
-if ((slot << 1) < fetch)
-fetch = slot << 1;
-if (fetch > 0) {
-RATE_ASSERT(((info->bpos << 1) - info->stray) >= 0 &&
-((info->bpos << 1) - info->stray) < (info->bufsz << 1),
-("%s: DANGER - BUFFER OVERRUN! bufsz=%d, pos=%dn", __func__,
-info->bufsz << 1, (info->bpos << 1) - info->stray));
-fetch = FEEDER_FEED(f->source, c,
-(uint8_t *)(info->buffer) + (info->bpos << 1) - info->stray,
-fetch, source);
-info->stray = 0;
-if (fetch == 0)
-break;
-RATE_TEST((fetch & 3) == 0,
-("%s: Fetch size not byte integral (%d)n",
-__func__, fetch));
-info->stray += fetch & 3;
-RATE_TEST(info->stray == 0,
-("%s: Stray bytes detected (%d)n",
-__func__, info->stray));
-fetch >>= 1;
-fetch &= ~1;
-info->bpos += fetch;
-slot -= fetch;
-RATE_ASSERT(slot >= 0,
-("%s: Negative Slot: %dn", __func__,
-slot));
-if (slot == 0)
-break;
-if (info->bpos == info->bufsz)
-break;
-} else
-break;
-}
-if (info->pos == info->bpos) {
-RATE_TEST(info->pos == 2,
-("%s: EOF while in progressn", __func__));
-break;
-}
-RATE_ASSERT(info->pos <= info->bpos,
-("%s: [2] Buffer overrun: %d > %dn", __func__,
-info->pos, info->bpos));
-RATE_ASSERT(info->pos < info->bpos,
-("%s: Zero buffer!n", __func__));
-RATE_ASSERT(((info->bpos - info->pos) & 1) == 0,
-("%s: Buffer not sample integral (%d)n",
-__func__, info->bpos - info->pos));
-i += info->convert(info, dst + i, count - i);
-RATE_ASSERT(info->pos <= info->bpos,
-("%s: [3] Buffer overrun: %d > %dn",
-__func__, info->pos, info->bpos));
-if (info->pos == info->bpos) {
-/*
-* End of buffer cycle. Copy last unit sample
-* to beginning of buffer so next cycle can
-* interpolate using it.
-*/
-RATE_TEST(info->stray == 0, ("%s: [2] Stray bytes: %un", __func__, info->stray));
-info->buffer[0] = info->buffer[info->pos - 2];
-info->buffer[1] = info->buffer[info->pos - 1];
-info->bpos = 2;
-info->pos = 2;
-}
-if (i == count)
-break;
-}
-#if 0
-RATE_TEST(count == i, ("Expect: %u , Got: %un", count << 1, i << 1));
+ struct feed_rate_info *info = f->data;
+ uint32_t i, smpsz;
+ int32_t fetch, slot;
+
+ if (info->convert == NULL)
+ return (FEEDER_FEED(f->source, c, b, count, source));
+
+ /*
+ * This loop has been optimized to generalize both up / down
+ * sampling without causing missing samples or excessive buffer
+ * feeding. The tricky part is to calculate *precise* (slot) value
+ * needed for the entire conversion space since we are bound to
+ * return and fill up the buffer according to the requested 'count'.
+ * Too much feeding will cause the extra buffer stay within temporary
+ * circular buffer forever and always manifest itself as a truncated
+ * sound during end of playback / recording. Too few, and we end up
+ * with possible underruns and waste of cpu cycles.
+ *
+ * 'Stray' management exist to combat with possible unaligned
+ * buffering by the caller.
+ */
+ smpsz = info->bps * info->channels;
+ RATE_TEST(count >= smpsz && (count % smpsz) == 0,
+ ("%s: Count size not sample integral (%d)\n", __func__, count));
+ if (count < smpsz)
+ return (0);
+ count -= count % smpsz;
+ /*
+ * This slot count formula will stay here for the next million years
+ * to come. This is the key of our circular buffering precision.
+ */
+ slot = (((info->gx * (count / smpsz)) + info->gy - info->alpha - 1) /
+ info->gy) * smpsz;
+ RATE_TEST((slot % smpsz) == 0,
+ ("%s: Slot count not sample integral (%d)\n", __func__, slot));
+#ifdef FEEDRATE_STRAY
+ RATE_TEST(info->stray == 0, ("%s: [1] Stray bytes: %u\n", __func__,
+ info->stray));
+#endif
+ if (info->pos != smpsz && info->bpos - info->pos == smpsz &&
+ info->bpos + slot > info->bufsz) {
+ /*
+ * Copy last unit sample and its previous to
+ * beginning of buffer.
+ */
+ bcopy(info->buffer + info->pos - smpsz, info->buffer,
+ smpsz << 1);
+ info->pos = smpsz;
+ info->bpos = smpsz << 1;
+ }
+ RATE_ASSERT(slot >= 0, ("%s: Negative Slot: %d\n", __func__, slot));
+ i = 0;
+ for (;;) {
+ for (;;) {
+ fetch = info->bufsz - info->bpos;
+#ifdef FEEDRATE_STRAY
+ fetch -= info->stray;
+#endif
+ RATE_ASSERT(fetch >= 0,
+ ("%s: [1] Buffer overrun: %d > %d\n", __func__,
+ info->bpos, info->bufsz));
+ if (slot < fetch)
+ fetch = slot;
+#ifdef FEEDRATE_STRAY
+ if (fetch < 1)
+#else
+ if (fetch < smpsz)
+#endif
+ break;
+ RATE_ASSERT((int)(info->bpos
+#ifdef FEEDRATE_STRAY
+ - info->stray
+#endif
+ ) >= 0 &&
+ (info->bpos - info->stray) < info->bufsz,
+ ("%s: DANGER - BUFFER OVERRUN! bufsz=%d, pos=%d\n",
+ __func__, info->bufsz, info->bpos
+#ifdef FEEDRATE_STRAY
+ - info->stray
#endif
-RATE_TEST(info->stray == 0, ("%s: [3] Stray bytes: %un", __func__, info->stray));
-return i << 1;
+ ));
+ fetch = FEEDER_FEED(f->source, c,
+ info->buffer + info->bpos
+#ifdef FEEDRATE_STRAY
+ - info->stray
+#endif
+ , fetch, source);
+#ifdef FEEDRATE_STRAY
+ info->stray = 0;
+ if (fetch == 0)
+#else
+ if (fetch < smpsz)
+#endif
+ break;
+ RATE_TEST((fetch % smpsz) == 0,
+ ("%s: Fetch size not sample integral (%d)\n",
+ __func__, fetch));
+#ifdef FEEDRATE_STRAY
+ info->stray += fetch % smpsz;
+ RATE_TEST(info->stray == 0,
+ ("%s: Stray bytes detected (%d)\n", __func__,
+ info->stray));
+#endif
+ fetch -= fetch % smpsz;
+ info->bpos += fetch;
+ slot -= fetch;
+ RATE_ASSERT(slot >= 0, ("%s: Negative Slot: %d\n",
+ __func__, slot));
+ if (slot == 0 || info->bpos == info->bufsz)
+ break;
+ }
+ if (info->pos == info->bpos) {
+ RATE_TEST(info->pos == smpsz,
+ ("%s: EOF while in progress\n", __func__));
+ break;
+ }
+ RATE_ASSERT(info->pos <= info->bpos,
+ ("%s: [2] Buffer overrun: %d > %d\n", __func__, info->pos,
+ info->bpos));
+ RATE_ASSERT(info->pos < info->bpos,
+ ("%s: Zero buffer!\n", __func__));
+ RATE_ASSERT(((info->bpos - info->pos) % smpsz) == 0,
+ ("%s: Buffer not sample integral (%d)\n", __func__,
+ info->bpos - info->pos));
+ i += info->convert(info, b + i, count - i);
+ RATE_ASSERT(info->pos <= info->bpos,
+ ("%s: [3] Buffer overrun: %d > %d\n", __func__, info->pos,
+ info->bpos));
+ if (info->pos == info->bpos) {
+ /*
+ * End of buffer cycle. Copy last unit sample
+ * to beginning of buffer so next cycle can
+ * interpolate using it.
+ */
+#ifdef FEEDRATE_STRAY
+ RATE_TEST(info->stray == 0,
+ ("%s: [2] Stray bytes: %u\n", __func__,
+ info->stray));
+#endif
+ bcopy(info->buffer + info->pos - smpsz, info->buffer,
+ smpsz);
+ info->bpos = smpsz;
+ info->pos = smpsz;
+ }
+ if (i == count)
+ break;
+ }
+
+ RATE_TEST((slot == 0 && count == i) || (slot > 0 && count > i &&
+ info->pos == info->bpos && info->pos == smpsz),
+ ("%s: Inconsistent slot/count! "
+ "Count Expect: %u , Got: %u, Slot Left: %d\n", __func__, count, i,
+ slot));
+
+#ifdef FEEDRATE_STRAY
+ RATE_TEST(info->stray == 0, ("%s: [3] Stray bytes: %u\n", __func__,
+ info->stray));
+#endif
+
+ return (i);
}
static struct pcm_feederdesc feeder_rate_desc[] = {
-{FEEDER_RATE, AFMT_S16_LE | AFMT_STEREO, AFMT_S16_LE | AFMT_STEREO, 0},
-{0, 0, 0, 0},
+ {FEEDER_RATE, AFMT_S8, AFMT_S8, 0},
+ {FEEDER_RATE, AFMT_S16_LE, AFMT_S16_LE, 0},
+ {FEEDER_RATE, AFMT_S24_LE, AFMT_S24_LE, 0},
+ {FEEDER_RATE, AFMT_S32_LE, AFMT_S32_LE, 0},
+ {FEEDER_RATE, AFMT_S16_BE, AFMT_S16_BE, 0},
+ {FEEDER_RATE, AFMT_S24_BE, AFMT_S24_BE, 0},
+ {FEEDER_RATE, AFMT_S32_BE, AFMT_S32_BE, 0},
+ {FEEDER_RATE, AFMT_S8 | AFMT_STEREO, AFMT_S8 | AFMT_STEREO, 0},
+ {FEEDER_RATE, AFMT_S16_LE | AFMT_STEREO, AFMT_S16_LE | AFMT_STEREO, 0},
+ {FEEDER_RATE, AFMT_S24_LE | AFMT_STEREO, AFMT_S24_LE | AFMT_STEREO, 0},
+ {FEEDER_RATE, AFMT_S32_LE | AFMT_STEREO, AFMT_S32_LE | AFMT_STEREO, 0},
+ {FEEDER_RATE, AFMT_S16_BE | AFMT_STEREO, AFMT_S16_BE | AFMT_STEREO, 0},
+ {FEEDER_RATE, AFMT_S24_BE | AFMT_STEREO, AFMT_S24_BE | AFMT_STEREO, 0},
+ {FEEDER_RATE, AFMT_S32_BE | AFMT_STEREO, AFMT_S32_BE | AFMT_STEREO, 0},
+ {FEEDER_RATE, AFMT_U8, AFMT_U8, 0},
+ {FEEDER_RATE, AFMT_U16_LE, AFMT_U16_LE, 0},
+ {FEEDER_RATE, AFMT_U24_LE, AFMT_U24_LE, 0},
+ {FEEDER_RATE, AFMT_U32_LE, AFMT_U32_LE, 0},
+ {FEEDER_RATE, AFMT_U16_BE, AFMT_U16_BE, 0},
+ {FEEDER_RATE, AFMT_U24_BE, AFMT_U24_BE, 0},
+ {FEEDER_RATE, AFMT_U32_BE, AFMT_U32_BE, 0},
+ {FEEDER_RATE, AFMT_U8 | AFMT_STEREO, AFMT_U8 | AFMT_STEREO, 0},
+ {FEEDER_RATE, AFMT_U16_LE | AFMT_STEREO, AFMT_U16_LE | AFMT_STEREO, 0},
+ {FEEDER_RATE, AFMT_U24_LE | AFMT_STEREO, AFMT_U24_LE | AFMT_STEREO, 0},
+ {FEEDER_RATE, AFMT_U32_LE | AFMT_STEREO, AFMT_U32_LE | AFMT_STEREO, 0},
+ {FEEDER_RATE, AFMT_U16_BE | AFMT_STEREO, AFMT_U16_BE | AFMT_STEREO, 0},
+ {FEEDER_RATE, AFMT_U24_BE | AFMT_STEREO, AFMT_U24_BE | AFMT_STEREO, 0},
+ {FEEDER_RATE, AFMT_U32_BE | AFMT_STEREO, AFMT_U32_BE | AFMT_STEREO, 0},
+ {0, 0, 0, 0},
};
+
static kobj_method_t feeder_rate_methods[] = {
-KOBJMETHOD(feeder_init, feed_rate_init),
-KOBJMETHOD(feeder_free, feed_rate_free),
-KOBJMETHOD(feeder_set, feed_rate_set),
-KOBJMETHOD(feeder_get, feed_rate_get),
-KOBJMETHOD(feeder_feed, feed_rate),
-{0, 0}
+ KOBJMETHOD(feeder_init, feed_rate_init),
+ KOBJMETHOD(feeder_free, feed_rate_free),
+ KOBJMETHOD(feeder_set, feed_rate_set),
+ KOBJMETHOD(feeder_get, feed_rate_get),
+ KOBJMETHOD(feeder_feed, feed_rate),
+ {0, 0}
};
+
FEEDER_DECLARE(feeder_rate, 2, NULL);
Index: feeder_fmt.c
===================================================================
RCS file: /home/cvs/src/sys/dev/sound/pcm/feeder_fmt.c,v
retrieving revision 1.2
retrieving revision 1.3
diff -L sys/dev/sound/pcm/feeder_fmt.c -L sys/dev/sound/pcm/feeder_fmt.c -u -r1.2 -r1.3
--- sys/dev/sound/pcm/feeder_fmt.c
+++ sys/dev/sound/pcm/feeder_fmt.c
@@ -1,1142 +1,1435 @@
/*-
-* Copyright (c) 1999 Cameron Grant <cg at FreeBSD.org>
-* Copyright (c) 2005 Ariff Abdullah <ariff at FreeBSD.org>
-* All rights reserved.
-*
-* Redistribution and use in source and binary forms, with or without
-* modification, are permitted provided that the following conditions
-* are met:
-* 1. Redistributions of source code must retain the above copyright
-* notice, this list of conditions and the following disclaimer.
-* 2. Redistributions in binary form must reproduce the above copyright
-* notice, this list of conditions and the following disclaimer in the
-* documentation and/or other materials provided with the distribution.
-*
-* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
-* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
-* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
-* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
-* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
-* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
-* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
-* SUCH DAMAGE.
-*
-* *New* and rewritten soft format converter, supporting 24/32bit pcm data,
-* simplified and optimized.
-*
-* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
-* *
-* This new implementation is fully dedicated in memory of Cameron Grant, *
-* the creator of the magnificent, highly addictive feeder infrastructure. *
-* *
-* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
-*
-*/
+ * Copyright (c) 1999 Cameron Grant <cg at FreeBSD.org>
+ * Copyright (c) 2005 Ariff Abdullah <ariff at FreeBSD.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * *New* and rewritten soft format converter, supporting 24/32bit pcm data,
+ * simplified and optimized.
+ *
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * *
+ * This new implementation is fully dedicated in memory of Cameron Grant, *
+ * the creator of the magnificent, highly addictive feeder infrastructure. *
+ * *
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ *
+ */
#include <dev/sound/pcm/sound.h>
#include "feeder_if.h"
-SND_DECLARE_FILE("$MidnightBSD$");
-
-MALLOC_DEFINE(M_FMTFEEDER, "fmtfeed", "pcm format feeder");
+SND_DECLARE_FILE("$FreeBSD: src/sys/dev/sound/pcm/feeder_fmt.c,v 1.23 2007/06/02 13:07:44 joel Exp $");
-#define FEEDBUFSZ 8192
-#define FEEDBUF24SZ 8190
-
-#define FMT_TRACE(x...) /* printf(x) */
-#define FMT_TEST(x, y...) /* if (x) FMT_TRACE(y) */
-#define FMT_ALIGNBYTE(x) /* x */
-
-/*
-* Sign inverted ulaw/alaw -> 8 table
-*/
-static uint8_t ulaw_to_s8_tbl[] = {
-131, 135, 139, 143, 147, 151, 155, 159,
-163, 167, 171, 175, 179, 183, 187, 191,
-194, 196, 198, 200, 202, 204, 206, 208,
-210, 212, 214, 216, 218, 220, 222, 224,
-226, 227, 228, 229, 230, 231, 232, 233,
-234, 235, 236, 237, 238, 239, 240, 241,
-241, 242, 242, 243, 243, 244, 244, 245,
-245, 246, 246, 247, 247, 248, 248, 249,
-249, 249, 250, 250, 250, 250, 251, 251,
-251, 251, 252, 252, 252, 252, 253, 253,
-253, 253, 253, 253, 254, 254, 254, 254,
-254, 254, 254, 254, 255, 255, 255, 255,
-255, 255, 255, 255, 255, 255, 255, 255,
-0, 0, 0, 0, 0, 0, 0, 0,
-0, 0, 0, 0, 0, 0, 0, 0,
-0, 0, 0, 0, 0, 0, 0, 0,
-125, 121, 117, 113, 109, 105, 101, 97,
-93, 89, 85, 81, 77, 73, 69, 65,
-62, 60, 58, 56, 54, 52, 50, 48,
-46, 44, 42, 40, 38, 36, 34, 32,
-30, 29, 28, 27, 26, 25, 24, 23,
-22, 21, 20, 19, 18, 17, 16, 15,
-15, 14, 14, 13, 13, 12, 12, 11,
-11, 10, 10, 9, 9, 8, 8, 7,
-7, 7, 6, 6, 6, 6, 5, 5,
-5, 5, 4, 4, 4, 4, 3, 3,
-3, 3, 3, 3, 2, 2, 2, 2,
-2, 2, 2, 2, 1, 1, 1, 1,
-1, 1, 1, 1, 1, 1, 1, 1,
-0, 0, 0, 0, 0, 0, 0, 0,
-0, 0, 0, 0, 0, 0, 0, 0,
-0, 0, 0, 0, 0, 0, 0, 0,
-};
-
-static uint8_t alaw_to_s8_tbl[] = {
-236, 237, 234, 235, 240, 241, 238, 239,
-228, 229, 226, 227, 232, 233, 230, 231,
-246, 246, 245, 245, 248, 248, 247, 247,
-242, 242, 241, 241, 244, 244, 243, 243,
-171, 175, 163, 167, 187, 191, 179, 183,
-139, 143, 131, 135, 155, 159, 147, 151,
-214, 216, 210, 212, 222, 224, 218, 220,
-198, 200, 194, 196, 206, 208, 202, 204,
-255, 255, 255, 255, 255, 255, 255, 255,
-255, 255, 255, 255, 255, 255, 255, 255,
-0, 0, 0, 0, 0, 0, 0, 0,
-0, 0, 0, 0, 0, 0, 0, 0,
-251, 251, 251, 251, 252, 252, 252, 252,
-249, 249, 249, 249, 250, 250, 250, 250,
-254, 254, 254, 254, 254, 254, 254, 254,
-253, 253, 253, 253, 253, 253, 253, 253,
-20, 19, 22, 21, 16, 15, 18, 17,
-28, 27, 30, 29, 24, 23, 26, 25,
-10, 10, 11, 11, 8, 8, 9, 9,
-14, 14, 15, 15, 12, 12, 13, 13,
-85, 81, 93, 89, 69, 65, 77, 73,
-117, 113, 125, 121, 101, 97, 109, 105,
-42, 40, 46, 44, 34, 32, 38, 36,
-58, 56, 62, 60, 50, 48, 54, 52,
-1, 1, 1, 1, 1, 1, 1, 1,
-1, 1, 1, 1, 1, 1, 1, 1,
-0, 0, 0, 0, 0, 0, 0, 0,
-0, 0, 0, 0, 0, 0, 0, 0,
-5, 5, 5, 5, 4, 4, 4, 4,
-7, 7, 7, 7, 6, 6, 6, 6,
-2, 2, 2, 2, 2, 2, 2, 2,
-3, 3, 3, 3, 3, 3, 3, 3,
+static int feeder_fmt_stereodownmix = 0;
+TUNABLE_INT("hw.snd.feeder_fmt_stereodownmix", &feeder_fmt_stereodownmix);
+#ifdef SND_DEBUG
+SYSCTL_INT(_hw_snd, OID_AUTO, feeder_fmt_stereodownmix, CTLFLAG_RW,
+ &feeder_fmt_stereodownmix, 1, "averaging stereo downmix");
+#endif
+
+#define FEEDFMT_RESERVOIR 8 /* 32bit stereo */
+
+static uint8_t ulaw_to_u8_tbl[] = {
+ 3, 7, 11, 15, 19, 23, 27, 31,
+ 35, 39, 43, 47, 51, 55, 59, 63,
+ 66, 68, 70, 72, 74, 76, 78, 80,
+ 82, 84, 86, 88, 90, 92, 94, 96,
+ 98, 99, 100, 101, 102, 103, 104, 105,
+ 106, 107, 108, 109, 110, 111, 112, 113,
+ 113, 114, 114, 115, 115, 116, 116, 117,
+ 117, 118, 118, 119, 119, 120, 120, 121,
+ 121, 121, 122, 122, 122, 122, 123, 123,
+ 123, 123, 124, 124, 124, 124, 125, 125,
+ 125, 125, 125, 125, 126, 126, 126, 126,
+ 126, 126, 126, 126, 127, 127, 127, 127,
+ 127, 127, 127, 127, 127, 127, 127, 127,
+ 128, 128, 128, 128, 128, 128, 128, 128,
+ 128, 128, 128, 128, 128, 128, 128, 128,
+ 128, 128, 128, 128, 128, 128, 128, 128,
+ 253, 249, 245, 241, 237, 233, 229, 225,
+ 221, 217, 213, 209, 205, 201, 197, 193,
+ 190, 188, 186, 184, 182, 180, 178, 176,
+ 174, 172, 170, 168, 166, 164, 162, 160,
+ 158, 157, 156, 155, 154, 153, 152, 151,
+ 150, 149, 148, 147, 146, 145, 144, 143,
+ 143, 142, 142, 141, 141, 140, 140, 139,
+ 139, 138, 138, 137, 137, 136, 136, 135,
+ 135, 135, 134, 134, 134, 134, 133, 133,
+ 133, 133, 132, 132, 132, 132, 131, 131,
+ 131, 131, 131, 131, 130, 130, 130, 130,
+ 130, 130, 130, 130, 129, 129, 129, 129,
+ 129, 129, 129, 129, 129, 129, 129, 129,
+ 128, 128, 128, 128, 128, 128, 128, 128,
+ 128, 128, 128, 128, 128, 128, 128, 128,
+ 128, 128, 128, 128, 128, 128, 128, 128,
+};
+
+static uint8_t alaw_to_u8_tbl[] = {
+ 108, 109, 106, 107, 112, 113, 110, 111,
+ 100, 101, 98, 99, 104, 105, 102, 103,
+ 118, 118, 117, 117, 120, 120, 119, 119,
+ 114, 114, 113, 113, 116, 116, 115, 115,
+ 43, 47, 35, 39, 59, 63, 51, 55,
+ 11, 15, 3, 7, 27, 31, 19, 23,
+ 86, 88, 82, 84, 94, 96, 90, 92,
+ 70, 72, 66, 68, 78, 80, 74, 76,
+ 127, 127, 127, 127, 127, 127, 127, 127,
+ 127, 127, 127, 127, 127, 127, 127, 127,
+ 128, 128, 128, 128, 128, 128, 128, 128,
+ 128, 128, 128, 128, 128, 128, 128, 128,
+ 123, 123, 123, 123, 124, 124, 124, 124,
+ 121, 121, 121, 121, 122, 122, 122, 122,
+ 126, 126, 126, 126, 126, 126, 126, 126,
+ 125, 125, 125, 125, 125, 125, 125, 125,
+ 148, 147, 150, 149, 144, 143, 146, 145,
+ 156, 155, 158, 157, 152, 151, 154, 153,
+ 138, 138, 139, 139, 136, 136, 137, 137,
+ 142, 142, 143, 143, 140, 140, 141, 141,
+ 213, 209, 221, 217, 197, 193, 205, 201,
+ 245, 241, 253, 249, 229, 225, 237, 233,
+ 170, 168, 174, 172, 162, 160, 166, 164,
+ 186, 184, 190, 188, 178, 176, 182, 180,
+ 129, 129, 129, 129, 129, 129, 129, 129,
+ 129, 129, 129, 129, 129, 129, 129, 129,
+ 128, 128, 128, 128, 128, 128, 128, 128,
+ 128, 128, 128, 128, 128, 128, 128, 128,
+ 133, 133, 133, 133, 132, 132, 132, 132,
+ 135, 135, 135, 135, 134, 134, 134, 134,
+ 130, 130, 130, 130, 130, 130, 130, 130,
+ 131, 131, 131, 131, 131, 131, 131, 131,
};
static uint8_t u8_to_ulaw_tbl[] = {
-0, 0, 0, 0, 0, 1, 1, 1,
-1, 2, 2, 2, 2, 3, 3, 3,
-3, 4, 4, 4, 4, 5, 5, 5,
-5, 6, 6, 6, 6, 7, 7, 7,
-7, 8, 8, 8, 8, 9, 9, 9,
-9, 10, 10, 10, 10, 11, 11, 11,
-11, 12, 12, 12, 12, 13, 13, 13,
-13, 14, 14, 14, 14, 15, 15, 15,
-15, 16, 16, 17, 17, 18, 18, 19,
-19, 20, 20, 21, 21, 22, 22, 23,
-23, 24, 24, 25, 25, 26, 26, 27,
-27, 28, 28, 29, 29, 30, 30, 31,
-31, 32, 33, 34, 35, 36, 37, 38,
-39, 40, 41, 42, 43, 44, 45, 46,
-47, 49, 51, 53, 55, 57, 59, 61,
-63, 66, 70, 74, 78, 84, 92, 104,
-254, 231, 219, 211, 205, 201, 197, 193,
-190, 188, 186, 184, 182, 180, 178, 176,
-175, 174, 173, 172, 171, 170, 169, 168,
-167, 166, 165, 164, 163, 162, 161, 160,
-159, 159, 158, 158, 157, 157, 156, 156,
-155, 155, 154, 154, 153, 153, 152, 152,
-151, 151, 150, 150, 149, 149, 148, 148,
-147, 147, 146, 146, 145, 145, 144, 144,
-143, 143, 143, 143, 142, 142, 142, 142,
-141, 141, 141, 141, 140, 140, 140, 140,
-139, 139, 139, 139, 138, 138, 138, 138,
-137, 137, 137, 137, 136, 136, 136, 136,
-135, 135, 135, 135, 134, 134, 134, 134,
-133, 133, 133, 133, 132, 132, 132, 132,
-131, 131, 131, 131, 130, 130, 130, 130,
-129, 129, 129, 129, 128, 128, 128, 128,
+ 0, 0, 0, 0, 0, 1, 1, 1,
+ 1, 2, 2, 2, 2, 3, 3, 3,
+ 3, 4, 4, 4, 4, 5, 5, 5,
+ 5, 6, 6, 6, 6, 7, 7, 7,
+ 7, 8, 8, 8, 8, 9, 9, 9,
+ 9, 10, 10, 10, 10, 11, 11, 11,
+ 11, 12, 12, 12, 12, 13, 13, 13,
+ 13, 14, 14, 14, 14, 15, 15, 15,
+ 15, 16, 16, 17, 17, 18, 18, 19,
+ 19, 20, 20, 21, 21, 22, 22, 23,
+ 23, 24, 24, 25, 25, 26, 26, 27,
+ 27, 28, 28, 29, 29, 30, 30, 31,
+ 31, 32, 33, 34, 35, 36, 37, 38,
+ 39, 40, 41, 42, 43, 44, 45, 46,
+ 47, 49, 51, 53, 55, 57, 59, 61,
+ 63, 66, 70, 74, 78, 84, 92, 104,
+ 254, 231, 219, 211, 205, 201, 197, 193,
+ 190, 188, 186, 184, 182, 180, 178, 176,
+ 175, 174, 173, 172, 171, 170, 169, 168,
+ 167, 166, 165, 164, 163, 162, 161, 160,
+ 159, 159, 158, 158, 157, 157, 156, 156,
+ 155, 155, 154, 154, 153, 153, 152, 152,
+ 151, 151, 150, 150, 149, 149, 148, 148,
+ 147, 147, 146, 146, 145, 145, 144, 144,
+ 143, 143, 143, 143, 142, 142, 142, 142,
+ 141, 141, 141, 141, 140, 140, 140, 140,
+ 139, 139, 139, 139, 138, 138, 138, 138,
+ 137, 137, 137, 137, 136, 136, 136, 136,
+ 135, 135, 135, 135, 134, 134, 134, 134,
+ 133, 133, 133, 133, 132, 132, 132, 132,
+ 131, 131, 131, 131, 130, 130, 130, 130,
+ 129, 129, 129, 129, 128, 128, 128, 128,
};
static uint8_t u8_to_alaw_tbl[] = {
-42, 42, 42, 42, 42, 43, 43, 43,
-43, 40, 40, 40, 40, 41, 41, 41,
-41, 46, 46, 46, 46, 47, 47, 47,
-47, 44, 44, 44, 44, 45, 45, 45,
-45, 34, 34, 34, 34, 35, 35, 35,
-35, 32, 32, 32, 32, 33, 33, 33,
-33, 38, 38, 38, 38, 39, 39, 39,
-39, 36, 36, 36, 36, 37, 37, 37,
-37, 58, 58, 59, 59, 56, 56, 57,
-57, 62, 62, 63, 63, 60, 60, 61,
-61, 50, 50, 51, 51, 48, 48, 49,
-49, 54, 54, 55, 55, 52, 52, 53,
-53, 10, 11, 8, 9, 14, 15, 12,
-13, 2, 3, 0, 1, 6, 7, 4,
-5, 24, 30, 28, 18, 16, 22, 20,
-106, 110, 98, 102, 122, 114, 75, 90,
-213, 197, 245, 253, 229, 225, 237, 233,
-149, 151, 145, 147, 157, 159, 153, 155,
-133, 132, 135, 134, 129, 128, 131, 130,
-141, 140, 143, 142, 137, 136, 139, 138,
-181, 181, 180, 180, 183, 183, 182, 182,
-177, 177, 176, 176, 179, 179, 178, 178,
-189, 189, 188, 188, 191, 191, 190, 190,
-185, 185, 184, 184, 187, 187, 186, 186,
-165, 165, 165, 165, 164, 164, 164, 164,
-167, 167, 167, 167, 166, 166, 166, 166,
-161, 161, 161, 161, 160, 160, 160, 160,
-163, 163, 163, 163, 162, 162, 162, 162,
-173, 173, 173, 173, 172, 172, 172, 172,
-175, 175, 175, 175, 174, 174, 174, 174,
-169, 169, 169, 169, 168, 168, 168, 168,
-171, 171, 171, 171, 170, 170, 170, 170,
-};
-
-static int
-feed_table_u8(struct pcm_feeder *f, struct pcm_channel *c, uint8_t *b,
-uint32_t count, void *source)
-{
-int j, k = FEEDER_FEED(f->source, c, b, count, source);
-uint8_t *tbl = (uint8_t *)f->data;
+ 42, 42, 42, 42, 42, 43, 43, 43,
+ 43, 40, 40, 40, 40, 41, 41, 41,
+ 41, 46, 46, 46, 46, 47, 47, 47,
+ 47, 44, 44, 44, 44, 45, 45, 45,
+ 45, 34, 34, 34, 34, 35, 35, 35,
+ 35, 32, 32, 32, 32, 33, 33, 33,
+ 33, 38, 38, 38, 38, 39, 39, 39,
+ 39, 36, 36, 36, 36, 37, 37, 37,
+ 37, 58, 58, 59, 59, 56, 56, 57,
+ 57, 62, 62, 63, 63, 60, 60, 61,
+ 61, 50, 50, 51, 51, 48, 48, 49,
+ 49, 54, 54, 55, 55, 52, 52, 53,
+ 53, 10, 11, 8, 9, 14, 15, 12,
+ 13, 2, 3, 0, 1, 6, 7, 4,
+ 5, 24, 30, 28, 18, 16, 22, 20,
+ 106, 110, 98, 102, 122, 114, 75, 90,
+ 213, 197, 245, 253, 229, 225, 237, 233,
+ 149, 151, 145, 147, 157, 159, 153, 155,
+ 133, 132, 135, 134, 129, 128, 131, 130,
+ 141, 140, 143, 142, 137, 136, 139, 138,
+ 181, 181, 180, 180, 183, 183, 182, 182,
+ 177, 177, 176, 176, 179, 179, 178, 178,
+ 189, 189, 188, 188, 191, 191, 190, 190,
+ 185, 185, 184, 184, 187, 187, 186, 186,
+ 165, 165, 165, 165, 164, 164, 164, 164,
+ 167, 167, 167, 167, 166, 166, 166, 166,
+ 161, 161, 161, 161, 160, 160, 160, 160,
+ 163, 163, 163, 163, 162, 162, 162, 162,
+ 173, 173, 173, 173, 172, 172, 172, 172,
+ 175, 175, 175, 175, 174, 174, 174, 174,
+ 169, 169, 169, 169, 168, 168, 168, 168,
+ 171, 171, 171, 171, 170, 170, 170, 170,
+};
+
+static int
+feed_table_8(struct pcm_feeder *f, struct pcm_channel *c, uint8_t *b,
+ uint32_t count, void *source)
+{
+ int j, sign, k;
+ uint8_t *tbl = (uint8_t *)f->data;
+
+ if (count < PCM_8_BPS)
+ return (0);
+
+ k = FEEDER_FEED(f->source, c, b, count, source);
+ if (k < PCM_8_BPS)
+ return (0);
+
+ j = k;
+ sign = (f->desc->out & AFMT_SIGNED) ? 0x80 : 0x00;
+
+ do {
+ j--;
+ b[j] = tbl[b[j]] ^ sign;
+ } while (j != 0);
+
+ return (k);
+}
+
+static int
+feed_table_16(struct pcm_feeder *f, struct pcm_channel *c, uint8_t *b,
+ uint32_t count, void *source)
+{
+ int i, j, sign, k;
+ uint8_t *tbl = (uint8_t *)f->data;
+
+ if (count < PCM_16_BPS)
+ return (0);
+
+ k = FEEDER_FEED(f->source, c, b, count >> 1, source);
+ if (k < PCM_8_BPS)
+ return (0);
+
+ i = k;
+ k <<= 1;
+ j = k;
+ sign = (f->desc->out & AFMT_SIGNED) ? 0x80 : 0x00;
+
+ if (f->desc->out & AFMT_BIGENDIAN) {
+ do {
+ b[--j] = 0;
+ b[--j] = tbl[b[--i]] ^ sign;
+ } while (i != 0);
+ } else {
+ do {
+ b[--j] = tbl[b[--i]] ^ sign;
+ b[--j] = 0;
+ } while (i != 0);
+ }
-j = k;
-while (j > 0) {
-j--;
-b[j] = tbl[b[j]] ^ 0x80;
-}
-return k;
-}
-
-static int
-feed_table_s16le(struct pcm_feeder *f, struct pcm_channel *c, uint8_t *b,
-uint32_t count, void *source)
-{
-int i, j, k = FEEDER_FEED(f->source, c, b, count >> 1, source);
-uint8_t *tbl = (uint8_t *)f->data;
-
-i = k;
-k <<= 1;
-j = k;
-while (i > 0) {
-b[--j] = tbl[b[--i]];
-b[--j] = 0;
-}
-return k;
+ return (k);
}
static int
feed_table_xlaw(struct pcm_feeder *f, struct pcm_channel *c, uint8_t *b,
-uint32_t count, void *source)
+ uint32_t count, void *source)
{
-int j, k = FEEDER_FEED(f->source, c, b, count, source);
-uint8_t *tbl = (uint8_t *)f->data;
+ int j, sign, k;
+ uint8_t *tbl = (uint8_t *)f->data;
-j = k;
-while (j > 0) {
-j--;
-b[j] = tbl[b[j]];
-}
-return k;
-}
+ if (count < PCM_8_BPS)
+ return (0);
-static struct pcm_feederdesc feeder_ulawtou8_desc[] = {
-{FEEDER_FMT, AFMT_MU_LAW, AFMT_U8, 0},
-{FEEDER_FMT, AFMT_MU_LAW|AFMT_STEREO, AFMT_U8|AFMT_STEREO, 0},
-{0, 0, 0, 0},
-};
-static kobj_method_t feeder_ulawtou8_methods[] = {
-KOBJMETHOD(feeder_feed, feed_table_u8),
-{0, 0}
-};
-FEEDER_DECLARE(feeder_ulawtou8, 0, ulaw_to_s8_tbl);
-
-static struct pcm_feederdesc feeder_alawtou8_desc[] = {
-{FEEDER_FMT, AFMT_A_LAW, AFMT_U8, 0},
-{FEEDER_FMT, AFMT_A_LAW|AFMT_STEREO, AFMT_U8|AFMT_STEREO, 0},
-{0, 0, 0, 0},
-};
-static kobj_method_t feeder_alawtou8_methods[] = {
-KOBJMETHOD(feeder_feed, feed_table_u8),
-{0, 0}
+ k = FEEDER_FEED(f->source, c, b, count, source);
+ if (k < PCM_8_BPS)
+ return (0);
+
+ j = k ;
+ sign = (f->desc->in & AFMT_SIGNED) ? 0x80 : 0x00;
+
+ do {
+ j--;
+ b[j] = tbl[b[j] ^ sign];
+ } while (j != 0);
+
+ return (k);
+}
+
+static struct pcm_feederdesc feeder_ulawto8_desc[] = {
+ {FEEDER_FMT, AFMT_MU_LAW, AFMT_U8, 0},
+ {FEEDER_FMT, AFMT_MU_LAW | AFMT_STEREO, AFMT_U8 | AFMT_STEREO, 0},
+ {FEEDER_FMT, AFMT_MU_LAW, AFMT_S8, 0},
+ {FEEDER_FMT, AFMT_MU_LAW | AFMT_STEREO, AFMT_S8 | AFMT_STEREO, 0},
+ {0, 0, 0, 0},
+};
+static kobj_method_t feeder_ulawto8_methods[] = {
+ KOBJMETHOD(feeder_feed, feed_table_8),
+ {0, 0}
+};
+FEEDER_DECLARE(feeder_ulawto8, 0, ulaw_to_u8_tbl);
+
+static struct pcm_feederdesc feeder_alawto8_desc[] = {
+ {FEEDER_FMT, AFMT_A_LAW, AFMT_U8, 0},
+ {FEEDER_FMT, AFMT_A_LAW | AFMT_STEREO, AFMT_U8 | AFMT_STEREO, 0},
+ {FEEDER_FMT, AFMT_A_LAW, AFMT_S8, 0},
+ {FEEDER_FMT, AFMT_A_LAW | AFMT_STEREO, AFMT_S8 | AFMT_STEREO, 0},
+ {0, 0, 0, 0},
+};
+static kobj_method_t feeder_alawto8_methods[] = {
+ KOBJMETHOD(feeder_feed, feed_table_8),
+ {0, 0}
+};
+FEEDER_DECLARE(feeder_alawto8, 0, alaw_to_u8_tbl);
+
+static struct pcm_feederdesc feeder_ulawto16_desc[] = {
+ {FEEDER_FMT, AFMT_MU_LAW, AFMT_S16_LE, 0},
+ {FEEDER_FMT, AFMT_MU_LAW | AFMT_STEREO, AFMT_S16_LE | AFMT_STEREO, 0},
+ {FEEDER_FMT, AFMT_MU_LAW, AFMT_U16_LE, 0},
+ {FEEDER_FMT, AFMT_MU_LAW | AFMT_STEREO, AFMT_U16_LE | AFMT_STEREO, 0},
+ {FEEDER_FMT, AFMT_MU_LAW, AFMT_S16_BE, 0},
+ {FEEDER_FMT, AFMT_MU_LAW | AFMT_STEREO, AFMT_S16_BE | AFMT_STEREO, 0},
+ {FEEDER_FMT, AFMT_MU_LAW, AFMT_U16_BE, 0},
+ {FEEDER_FMT, AFMT_MU_LAW | AFMT_STEREO, AFMT_U16_BE | AFMT_STEREO, 0},
+ {0, 0, 0, 0},
+};
+static kobj_method_t feeder_ulawto16_methods[] = {
+ KOBJMETHOD(feeder_feed, feed_table_16),
+ {0, 0}
+};
+FEEDER_DECLARE(feeder_ulawto16, 0, ulaw_to_u8_tbl);
+
+static struct pcm_feederdesc feeder_alawto16_desc[] = {
+ {FEEDER_FMT, AFMT_A_LAW, AFMT_S16_LE, 0},
+ {FEEDER_FMT, AFMT_A_LAW | AFMT_STEREO, AFMT_S16_LE | AFMT_STEREO, 0},
+ {FEEDER_FMT, AFMT_A_LAW, AFMT_U16_LE, 0},
+ {FEEDER_FMT, AFMT_A_LAW | AFMT_STEREO, AFMT_U16_LE | AFMT_STEREO, 0},
+ {FEEDER_FMT, AFMT_A_LAW, AFMT_S16_BE, 0},
+ {FEEDER_FMT, AFMT_A_LAW | AFMT_STEREO, AFMT_S16_BE | AFMT_STEREO, 0},
+ {FEEDER_FMT, AFMT_A_LAW, AFMT_U16_BE, 0},
+ {FEEDER_FMT, AFMT_A_LAW | AFMT_STEREO, AFMT_U16_BE | AFMT_STEREO, 0},
+ {0, 0, 0, 0},
+};
+static kobj_method_t feeder_alawto16_methods[] = {
+ KOBJMETHOD(feeder_feed, feed_table_16),
+ {0, 0}
+};
+FEEDER_DECLARE(feeder_alawto16, 0, alaw_to_u8_tbl);
+
+static struct pcm_feederdesc feeder_8toulaw_desc[] = {
+ {FEEDER_FMT, AFMT_U8, AFMT_MU_LAW, 0},
+ {FEEDER_FMT, AFMT_U8 | AFMT_STEREO, AFMT_MU_LAW | AFMT_STEREO, 0},
+ {FEEDER_FMT, AFMT_S8, AFMT_MU_LAW, 0},
+ {FEEDER_FMT, AFMT_S8 | AFMT_STEREO, AFMT_MU_LAW | AFMT_STEREO, 0},
+ {0, 0, 0, 0},
+};
+static kobj_method_t feeder_8toulaw_methods[] = {
+ KOBJMETHOD(feeder_feed, feed_table_xlaw),
+ {0, 0}
+};
+FEEDER_DECLARE(feeder_8toulaw, 0, u8_to_ulaw_tbl);
+
+static struct pcm_feederdesc feeder_8toalaw_desc[] = {
+ {FEEDER_FMT, AFMT_U8, AFMT_A_LAW, 0},
+ {FEEDER_FMT, AFMT_U8 | AFMT_STEREO, AFMT_A_LAW | AFMT_STEREO, 0},
+ {FEEDER_FMT, AFMT_S8, AFMT_A_LAW, 0},
+ {FEEDER_FMT, AFMT_S8 | AFMT_STEREO, AFMT_A_LAW | AFMT_STEREO, 0},
+ {0, 0, 0, 0},
+};
+static kobj_method_t feeder_8toalaw_methods[] = {
+ KOBJMETHOD(feeder_feed, feed_table_xlaw),
+ {0, 0}
};
-FEEDER_DECLARE(feeder_alawtou8, 0, alaw_to_s8_tbl);
-
-static struct pcm_feederdesc feeder_ulawtos16le_desc[] = {
-{FEEDER_FMT, AFMT_MU_LAW, AFMT_S16_LE, 0},
-{FEEDER_FMT, AFMT_MU_LAW|AFMT_STEREO, AFMT_S16_LE|AFMT_STEREO, 0},
-{0, 0, 0, 0},
-};
-static kobj_method_t feeder_ulawtos16le_methods[] = {
-KOBJMETHOD(feeder_feed, feed_table_s16le),
-{0, 0}
-};
-FEEDER_DECLARE(feeder_ulawtos16le, 0, ulaw_to_s8_tbl);
-
-static struct pcm_feederdesc feeder_alawtos16le_desc[] = {
-{FEEDER_FMT, AFMT_A_LAW, AFMT_S16_LE, 0},
-{FEEDER_FMT, AFMT_A_LAW|AFMT_STEREO, AFMT_S16_LE|AFMT_STEREO, 0},
-{0, 0, 0, 0},
-};
-static kobj_method_t feeder_alawtos16le_methods[] = {
-KOBJMETHOD(feeder_feed, feed_table_s16le),
-{0, 0}
-};
-FEEDER_DECLARE(feeder_alawtos16le, 0, alaw_to_s8_tbl);
-
-static struct pcm_feederdesc feeder_u8toulaw_desc[] = {
-{FEEDER_FMT, AFMT_U8, AFMT_MU_LAW, 0},
-{FEEDER_FMT, AFMT_U8|AFMT_STEREO, AFMT_MU_LAW|AFMT_STEREO, 0},
-{0, 0, 0, 0},
-};
-static kobj_method_t feeder_u8toulaw_methods[] = {
-KOBJMETHOD(feeder_feed, feed_table_xlaw),
-{0, 0}
-};
-FEEDER_DECLARE(feeder_u8toulaw, 0, u8_to_ulaw_tbl);
-
-static struct pcm_feederdesc feeder_u8toalaw_desc[] = {
-{FEEDER_FMT, AFMT_U8, AFMT_A_LAW, 0},
-{FEEDER_FMT, AFMT_U8|AFMT_STEREO, AFMT_A_LAW|AFMT_STEREO, 0},
-{0, 0, 0, 0},
-};
-static kobj_method_t feeder_u8toalaw_methods[] = {
-KOBJMETHOD(feeder_feed, feed_table_xlaw),
-{0, 0}
-};
-FEEDER_DECLARE(feeder_u8toalaw, 0, u8_to_alaw_tbl);
+FEEDER_DECLARE(feeder_8toalaw, 0, u8_to_alaw_tbl);
/*
-* Conversion rules:-
-* 1. BE -> LE
-* 2. if fmt == u8 , u8 -> s8 (economical)
-* 3. Xle -> 16le
-* 4. if fmt != u8 && fmt == u16le , u16le -> s16le
-* 4. s16le mono -> s16le stereo
-*
-* All conversion done in byte level to preserve endianess.
-*/
+ * All conversion done in byte level to preserve endianess.
+ */
-static int
-feed_common_init(struct pcm_feeder *f)
-{
-f->data = malloc(FEEDBUFSZ, M_FMTFEEDER, M_NOWAIT|M_ZERO);
-if (f->data == NULL)
-return ENOMEM;
-return 0;
-}
-
-static int
-feed_common_free(struct pcm_feeder *f)
-{
-if (f->data)
-free(f->data, M_FMTFEEDER);
-f->data = NULL;
-return 0;
-}
+#define FEEDFMT_SWAP_SIGN(f) (((((f)->desc->in & AFMT_SIGNED) == 0) != \
+ (((f)->desc->out & AFMT_SIGNED) == 0)) \
+ ? 0x80 : 0x00)
/*
-* Bit conversion
-*/
-static int
-feed_8to16le(struct pcm_feeder *f, struct pcm_channel *c, uint8_t *b,
-uint32_t count, void *source)
-{
-int i, j, k = FEEDER_FEED(f->source, c, b, count >> 1, source);
+ * Bit conversion
+ */
-i = k;
-k <<= 1;
-j = k;
-while (i > 0) {
-b[--j] = b[--i];
-b[--j] = 0;
-}
-return k;
-}
-static struct pcm_feederdesc feeder_8to16le_desc[] = {
-{FEEDER_FMT, AFMT_U8, AFMT_U16_LE, 0},
-{FEEDER_FMT, AFMT_U8|AFMT_STEREO, AFMT_U16_LE|AFMT_STEREO, 0},
-{FEEDER_FMT, AFMT_S8, AFMT_S16_LE, 0},
-{FEEDER_FMT, AFMT_S8|AFMT_STEREO, AFMT_S16_LE|AFMT_STEREO, 0},
-{0, 0, 0, 0},
-};
-static kobj_method_t feeder_8to16le_methods[] = {
-KOBJMETHOD(feeder_feed, feed_8to16le),
-{0, 0}
-};
-FEEDER_DECLARE(feeder_8to16le, 0, NULL);
-
-static int
-feed_16leto8(struct pcm_feeder *f, struct pcm_channel *c, uint8_t *b,
-uint32_t count, void *source)
-{
-int i, j, k;
-uint8_t *src = (uint8_t *)f->data;
-
-k = count << 1;
-k = FEEDER_FEED(f->source, c, src, min(k, FEEDBUFSZ), source);
-if (k < 2) {
-FMT_TRACE("%s: Not enough data (Got: %d bytes)n",
-__func__, k);
-return 0;
-}
-FMT_TEST(k & 1, "%s: Bytes not 16bit aligned.n", __func__);
-FMT_ALIGNBYTE(k &= ~1);
-i = k;
-j = k >> 1;
-while (i > 0) {
-b[--j] = src[--i];
-i--;
-}
-return k >> 1;
-}
-static struct pcm_feederdesc feeder_16leto8_desc[] = {
-{FEEDER_FMT, AFMT_U16_LE, AFMT_U8, 0},
-{FEEDER_FMT, AFMT_U16_LE|AFMT_STEREO, AFMT_U8|AFMT_STEREO, 0},
-{FEEDER_FMT, AFMT_S16_LE, AFMT_S8, 0},
-{FEEDER_FMT, AFMT_S16_LE|AFMT_STEREO, AFMT_S8|AFMT_STEREO, 0},
-{0, 0, 0, 0},
-};
-static kobj_method_t feeder_16leto8_methods[] = {
-KOBJMETHOD(feeder_init, feed_common_init),
-KOBJMETHOD(feeder_free, feed_common_free),
-KOBJMETHOD(feeder_feed, feed_16leto8),
-{0, 0}
-};
-FEEDER_DECLARE(feeder_16leto8, 0, NULL);
-
-static int
-feed_16leto24le(struct pcm_feeder *f, struct pcm_channel *c, uint8_t *b,
-uint32_t count, void *source)
-{
-int i, j, k;
-
-k = (count / 3) << 1;
-k = FEEDER_FEED(f->source, c, b, k, source);
-if (k < 2) {
-FMT_TRACE("%s: Not enough data (Got: %d bytes)n",
-__func__, k);
-return 0;
-}
-FMT_TEST(k & 1, "%s: Bytes not 16bit aligned.n", __func__);
-FMT_ALIGNBYTE(k &= ~1);
-i = k;
-j = (k >> 1) * 3;
-k = j;
-while (i > 0) {
-b[--j] = b[--i];
-b[--j] = b[--i];
-b[--j] = 0;
-}
-return k;
-}
-static struct pcm_feederdesc feeder_16leto24le_desc[] = {
-{FEEDER_FMT, AFMT_U16_LE, AFMT_U24_LE, 0},
-{FEEDER_FMT, AFMT_U16_LE|AFMT_STEREO, AFMT_U24_LE|AFMT_STEREO, 0},
-{FEEDER_FMT, AFMT_S16_LE, AFMT_S24_LE, 0},
-{FEEDER_FMT, AFMT_S16_LE|AFMT_STEREO, AFMT_S24_LE|AFMT_STEREO, 0},
-{0, 0, 0, 0},
-};
-static kobj_method_t feeder_16leto24le_methods[] = {
-KOBJMETHOD(feeder_feed, feed_16leto24le),
-{0, 0}
-};
-FEEDER_DECLARE(feeder_16leto24le, 0, NULL);
-
-static int
-feed_24leto16le(struct pcm_feeder *f, struct pcm_channel *c, uint8_t *b,
-uint32_t count, void *source)
-{
-int i, j, k;
-uint8_t *src = (uint8_t *)f->data;
-
-k = (count * 3) >> 1;
-k = FEEDER_FEED(f->source, c, src, min(k, FEEDBUF24SZ), source);
-if (k < 3) {
-FMT_TRACE("%s: Not enough data (Got: %d bytes)n",
-__func__, k);
-return 0;
-}
-FMT_TEST(k % 3, "%s: Bytes not 24bit aligned.n", __func__);
-FMT_ALIGNBYTE(k -= k % 3);
-i = (k / 3) << 1;
-j = i;
-while (i > 0) {
-b[--i] = src[--k];
-b[--i] = src[--k];
-k--;
-}
-return j;
-}
-static struct pcm_feederdesc feeder_24leto16le_desc[] = {
-{FEEDER_FMT, AFMT_U24_LE, AFMT_U16_LE, 0},
-{FEEDER_FMT, AFMT_U24_LE|AFMT_STEREO, AFMT_U16_LE|AFMT_STEREO, 0},
-{FEEDER_FMT, AFMT_S24_LE, AFMT_S16_LE, 0},
-{FEEDER_FMT, AFMT_S24_LE|AFMT_STEREO, AFMT_S16_LE|AFMT_STEREO, 0},
-{0, 0, 0, 0},
-};
-static kobj_method_t feeder_24leto16le_methods[] = {
-KOBJMETHOD(feeder_init, feed_common_init),
-KOBJMETHOD(feeder_free, feed_common_free),
-KOBJMETHOD(feeder_feed, feed_24leto16le),
-{0, 0}
-};
-FEEDER_DECLARE(feeder_24leto16le, 1, NULL);
-
-static int
-feed_16leto32le(struct pcm_feeder *f, struct pcm_channel *c, uint8_t *b,
-uint32_t count, void *source)
-{
-int i, j, k = FEEDER_FEED(f->source, c, b, count >> 1, source);
-if (k < 2) {
-FMT_TRACE("%s: Not enough data (Got: %d bytes)n",
-__func__, k);
-return 0;
-}
-FMT_TEST(k & 1, "%s: Bytes not 16bit aligned.n", __func__);
-FMT_ALIGNBYTE(k &= ~1);
-i = k;
-j = k << 1;
-k = j;
-while (i > 0) {
-b[--j] = b[--i];
-b[--j] = b[--i];
-b[--j] = 0;
-b[--j] = 0;
-}
-return k;
-}
-static struct pcm_feederdesc feeder_16leto32le_desc[] = {
-{FEEDER_FMT, AFMT_U16_LE, AFMT_U32_LE, 0},
-{FEEDER_FMT, AFMT_U16_LE|AFMT_STEREO, AFMT_U32_LE|AFMT_STEREO, 0},
-{FEEDER_FMT, AFMT_S16_LE, AFMT_S32_LE, 0},
-{FEEDER_FMT, AFMT_S16_LE|AFMT_STEREO, AFMT_S32_LE|AFMT_STEREO, 0},
-{0, 0, 0, 0},
-};
-static kobj_method_t feeder_16leto32le_methods[] = {
-KOBJMETHOD(feeder_feed, feed_16leto32le),
-{0, 0}
-};
-FEEDER_DECLARE(feeder_16leto32le, 0, NULL);
-
-static int
-feed_32leto16le(struct pcm_feeder *f, struct pcm_channel *c, uint8_t *b,
-uint32_t count, void *source)
-{
-int i, j, k;
-uint8_t *src = (uint8_t *)f->data;
-
-k = count << 1;
-k = FEEDER_FEED(f->source, c, src, min(k, FEEDBUFSZ), source);
-if (k < 4) {
-FMT_TRACE("%s: Not enough data (Got: %d bytes)n",
-__func__, k);
-return 0;
-}
-FMT_TEST(k & 3, "%s: Bytes not 32bit aligned.n", __func__);
-FMT_ALIGNBYTE(k &= ~3);
-i = k;
-k >>= 1;
-j = k;
-while (i > 0) {
-b[--j] = src[--i];
-b[--j] = src[--i];
-i -= 2;
-}
-return k;
-}
-static struct pcm_feederdesc feeder_32leto16le_desc[] = {
-{FEEDER_FMT, AFMT_U32_LE, AFMT_U16_LE, 0},
-{FEEDER_FMT, AFMT_U32_LE|AFMT_STEREO, AFMT_U16_LE|AFMT_STEREO, 0},
-{FEEDER_FMT, AFMT_S32_LE, AFMT_S16_LE, 0},
-{FEEDER_FMT, AFMT_S32_LE|AFMT_STEREO, AFMT_S16_LE|AFMT_STEREO, 0},
-{0, 0, 0, 0},
-};
-static kobj_method_t feeder_32leto16le_methods[] = {
-KOBJMETHOD(feeder_init, feed_common_init),
-KOBJMETHOD(feeder_free, feed_common_free),
-KOBJMETHOD(feeder_feed, feed_32leto16le),
-{0, 0}
+#define FBIT_DATA(i, o, c) ((intptr_t)((((c) & 0xf) << 6) | \
+ (((i) & 0x7) << 3) | ((o) & 0x7)))
+#define FBIT_OUTBPS(m) ((m) & 0x7)
+#define FBIT_INBPS(m) FBIT_OUTBPS((m) >> 3)
+#define FBIT_CHANNELS(m) (((m) >> 6) & 0xf)
+
+static int
+feed_updownbit_init(struct pcm_feeder *f)
+{
+ int ibps, obps, channels;
+
+ if (f->desc->in == f->desc->out || (f->desc->in & AFMT_STEREO) !=
+ (f->desc->out & AFMT_STEREO))
+ return (-1);
+
+ channels = (f->desc->in & AFMT_STEREO) ? 2 : 1;
+
+ if (f->desc->in & AFMT_32BIT)
+ ibps = PCM_32_BPS;
+ else if (f->desc->in & AFMT_24BIT)
+ ibps = PCM_24_BPS;
+ else if (f->desc->in & AFMT_16BIT)
+ ibps = PCM_16_BPS;
+ else
+ ibps = PCM_8_BPS;
+
+ if (f->desc->out & AFMT_32BIT)
+ obps = PCM_32_BPS;
+ else if (f->desc->out & AFMT_24BIT)
+ obps = PCM_24_BPS;
+ else if (f->desc->out & AFMT_16BIT)
+ obps = PCM_16_BPS;
+ else
+ obps = PCM_8_BPS;
+
+ f->data = (void *)FBIT_DATA(ibps, obps, channels);
+
+ return (0);
+}
+
+static int
+feed_upbit(struct pcm_feeder *f, struct pcm_channel *c, uint8_t *b,
+ uint32_t count, void *source)
+{
+ int i, j, k, sign, ibps, ialign, obps, oalign, pad;
+ uint8_t *src, *dst;
+
+ ibps = FBIT_INBPS((intptr_t)f->data);
+ obps = FBIT_OUTBPS((intptr_t)f->data);
+
+ ialign = ibps * FBIT_CHANNELS((intptr_t)f->data);
+ oalign = obps * FBIT_CHANNELS((intptr_t)f->data);
+
+ if (count < oalign)
+ return (0);
+
+ k = FEEDER_FEED(f->source, c, b, (count / oalign) * ialign, source);
+ if (k < ialign)
+ return (0);
+
+ k -= k % ialign;
+ j = (k / ibps) * obps;
+ pad = obps - ibps;
+ src = b + k;
+ dst = b + j;
+ sign = FEEDFMT_SWAP_SIGN(f);
+
+ if (f->desc->out & AFMT_BIGENDIAN) {
+ do {
+ i = pad;
+ do {
+ *--dst = 0;
+ } while (--i != 0);
+ i = ibps;
+ while (--i != 0)
+ *--dst = *--src;
+ *--dst = *--src ^ sign;
+ } while (dst != b);
+ } else {
+ do {
+ *--dst = *--src ^ sign;
+ i = ibps;
+ while (--i != 0)
+ *--dst = *--src;
+ i = pad;
+ do {
+ *--dst = 0;
+ } while (--i != 0);
+ } while (dst != b);
+ }
+
+ return (j);
+}
+
+static struct pcm_feederdesc feeder_8to16_desc[] = {
+ {FEEDER_FMT, AFMT_U8, AFMT_U16_LE, 0},
+ {FEEDER_FMT, AFMT_U8 | AFMT_STEREO, AFMT_U16_LE | AFMT_STEREO, 0},
+ {FEEDER_FMT, AFMT_S8, AFMT_S16_LE, 0},
+ {FEEDER_FMT, AFMT_S8 | AFMT_STEREO, AFMT_S16_LE | AFMT_STEREO, 0},
+ {FEEDER_FMT, AFMT_U8, AFMT_U16_BE, 0},
+ {FEEDER_FMT, AFMT_U8 | AFMT_STEREO, AFMT_U16_BE | AFMT_STEREO, 0},
+ {FEEDER_FMT, AFMT_S8, AFMT_S16_BE, 0},
+ {FEEDER_FMT, AFMT_S8 | AFMT_STEREO, AFMT_S16_BE | AFMT_STEREO, 0},
+ {FEEDER_FMT, AFMT_U8, AFMT_S16_LE, 0},
+ {FEEDER_FMT, AFMT_U8 | AFMT_STEREO, AFMT_S16_LE | AFMT_STEREO, 0},
+ {FEEDER_FMT, AFMT_S8, AFMT_U16_LE, 0},
+ {FEEDER_FMT, AFMT_S8 | AFMT_STEREO, AFMT_U16_LE | AFMT_STEREO, 0},
+ {FEEDER_FMT, AFMT_U8, AFMT_S16_BE, 0},
+ {FEEDER_FMT, AFMT_U8 | AFMT_STEREO, AFMT_S16_BE | AFMT_STEREO, 0},
+ {FEEDER_FMT, AFMT_S8, AFMT_U16_BE, 0},
+ {FEEDER_FMT, AFMT_S8 | AFMT_STEREO, AFMT_U16_BE | AFMT_STEREO, 0},
+ {0, 0, 0, 0},
+};
+static kobj_method_t feeder_8to16_methods[] = {
+ KOBJMETHOD(feeder_init, feed_updownbit_init),
+ KOBJMETHOD(feeder_feed, feed_upbit),
+ {0, 0}
+};
+FEEDER_DECLARE(feeder_8to16, 0, NULL);
+
+static struct pcm_feederdesc feeder_8to24_desc[] = {
+ {FEEDER_FMT, AFMT_U8, AFMT_U24_LE, 0},
+ {FEEDER_FMT, AFMT_U8 | AFMT_STEREO, AFMT_U24_LE | AFMT_STEREO, 0},
+ {FEEDER_FMT, AFMT_S8, AFMT_S24_LE, 0},
+ {FEEDER_FMT, AFMT_S8 | AFMT_STEREO, AFMT_S24_LE | AFMT_STEREO, 0},
+ {FEEDER_FMT, AFMT_U8, AFMT_U24_BE, 0},
+ {FEEDER_FMT, AFMT_U8 | AFMT_STEREO, AFMT_U24_BE | AFMT_STEREO, 0},
+ {FEEDER_FMT, AFMT_S8, AFMT_S24_BE, 0},
+ {FEEDER_FMT, AFMT_S8 | AFMT_STEREO, AFMT_S24_BE | AFMT_STEREO, 0},
+ {FEEDER_FMT, AFMT_U8, AFMT_S24_LE, 0},
+ {FEEDER_FMT, AFMT_U8 | AFMT_STEREO, AFMT_S24_LE | AFMT_STEREO, 0},
+ {FEEDER_FMT, AFMT_S8, AFMT_U24_LE, 0},
+ {FEEDER_FMT, AFMT_S8 | AFMT_STEREO, AFMT_U24_LE | AFMT_STEREO, 0},
+ {FEEDER_FMT, AFMT_U8, AFMT_S24_BE, 0},
+ {FEEDER_FMT, AFMT_U8 | AFMT_STEREO, AFMT_S24_BE | AFMT_STEREO, 0},
+ {FEEDER_FMT, AFMT_S8, AFMT_U24_BE, 0},
+ {FEEDER_FMT, AFMT_S8 | AFMT_STEREO, AFMT_U24_BE | AFMT_STEREO, 0},
+ {0, 0, 0, 0},
+};
+static kobj_method_t feeder_8to24_methods[] = {
+ KOBJMETHOD(feeder_init, feed_updownbit_init),
+ KOBJMETHOD(feeder_feed, feed_upbit),
+ {0, 0}
+};
+FEEDER_DECLARE(feeder_8to24, 0, NULL);
+
+static struct pcm_feederdesc feeder_8to32_desc[] = {
+ {FEEDER_FMT, AFMT_U8, AFMT_U32_LE, 0},
+ {FEEDER_FMT, AFMT_U8 | AFMT_STEREO, AFMT_U32_LE | AFMT_STEREO, 0},
+ {FEEDER_FMT, AFMT_S8, AFMT_S32_LE, 0},
+ {FEEDER_FMT, AFMT_S8 | AFMT_STEREO, AFMT_S32_LE | AFMT_STEREO, 0},
+ {FEEDER_FMT, AFMT_U8, AFMT_U32_BE, 0},
+ {FEEDER_FMT, AFMT_U8 | AFMT_STEREO, AFMT_U32_BE | AFMT_STEREO, 0},
+ {FEEDER_FMT, AFMT_S8, AFMT_S32_BE, 0},
+ {FEEDER_FMT, AFMT_S8 | AFMT_STEREO, AFMT_S32_BE | AFMT_STEREO, 0},
+ {FEEDER_FMT, AFMT_U8, AFMT_S32_LE, 0},
+ {FEEDER_FMT, AFMT_U8 | AFMT_STEREO, AFMT_S32_LE | AFMT_STEREO, 0},
+ {FEEDER_FMT, AFMT_S8, AFMT_U32_LE, 0},
+ {FEEDER_FMT, AFMT_S8 | AFMT_STEREO, AFMT_U32_LE | AFMT_STEREO, 0},
+ {FEEDER_FMT, AFMT_U8, AFMT_S32_BE, 0},
+ {FEEDER_FMT, AFMT_U8 | AFMT_STEREO, AFMT_S32_BE | AFMT_STEREO, 0},
+ {FEEDER_FMT, AFMT_S8, AFMT_U32_BE, 0},
+ {FEEDER_FMT, AFMT_S8 | AFMT_STEREO, AFMT_U32_BE | AFMT_STEREO, 0},
+ {0, 0, 0, 0},
+};
+static kobj_method_t feeder_8to32_methods[] = {
+ KOBJMETHOD(feeder_init, feed_updownbit_init),
+ KOBJMETHOD(feeder_feed, feed_upbit),
+ {0, 0}
+};
+FEEDER_DECLARE(feeder_8to32, 0, NULL);
+
+static struct pcm_feederdesc feeder_16to24_desc[] = {
+ {FEEDER_FMT, AFMT_U16_LE, AFMT_U24_LE, 0},
+ {FEEDER_FMT, AFMT_U16_LE | AFMT_STEREO, AFMT_U24_LE | AFMT_STEREO, 0},
+ {FEEDER_FMT, AFMT_S16_LE, AFMT_S24_LE, 0},
+ {FEEDER_FMT, AFMT_S16_LE | AFMT_STEREO, AFMT_S24_LE | AFMT_STEREO, 0},
+ {FEEDER_FMT, AFMT_U16_BE, AFMT_U24_BE, 0},
+ {FEEDER_FMT, AFMT_U16_BE | AFMT_STEREO, AFMT_U24_BE | AFMT_STEREO, 0},
+ {FEEDER_FMT, AFMT_S16_BE, AFMT_S24_BE, 0},
+ {FEEDER_FMT, AFMT_S16_BE | AFMT_STEREO, AFMT_S24_BE | AFMT_STEREO, 0},
+ {FEEDER_FMT, AFMT_U16_LE, AFMT_S24_LE, 0},
+ {FEEDER_FMT, AFMT_U16_LE | AFMT_STEREO, AFMT_S24_LE | AFMT_STEREO, 0},
+ {FEEDER_FMT, AFMT_S16_LE, AFMT_U24_LE, 0},
+ {FEEDER_FMT, AFMT_S16_LE | AFMT_STEREO, AFMT_U24_LE | AFMT_STEREO, 0},
+ {FEEDER_FMT, AFMT_U16_BE, AFMT_S24_BE, 0},
+ {FEEDER_FMT, AFMT_U16_BE | AFMT_STEREO, AFMT_S24_BE | AFMT_STEREO, 0},
+ {FEEDER_FMT, AFMT_S16_BE, AFMT_U24_BE, 0},
+ {FEEDER_FMT, AFMT_S16_BE | AFMT_STEREO, AFMT_U24_BE | AFMT_STEREO, 0},
+ {0, 0, 0, 0},
+};
+static kobj_method_t feeder_16to24_methods[] = {
+ KOBJMETHOD(feeder_init, feed_updownbit_init),
+ KOBJMETHOD(feeder_feed, feed_upbit),
+ {0, 0}
+};
+FEEDER_DECLARE(feeder_16to24, 0, NULL);
+
+static struct pcm_feederdesc feeder_16to32_desc[] = {
+ {FEEDER_FMT, AFMT_U16_LE, AFMT_U32_LE, 0},
+ {FEEDER_FMT, AFMT_U16_LE | AFMT_STEREO, AFMT_U32_LE | AFMT_STEREO, 0},
+ {FEEDER_FMT, AFMT_S16_LE, AFMT_S32_LE, 0},
+ {FEEDER_FMT, AFMT_S16_LE | AFMT_STEREO, AFMT_S32_LE | AFMT_STEREO, 0},
+ {FEEDER_FMT, AFMT_U16_BE, AFMT_U32_BE, 0},
+ {FEEDER_FMT, AFMT_U16_BE | AFMT_STEREO, AFMT_U32_BE | AFMT_STEREO, 0},
+ {FEEDER_FMT, AFMT_S16_BE, AFMT_S32_BE, 0},
+ {FEEDER_FMT, AFMT_S16_BE | AFMT_STEREO, AFMT_S32_BE | AFMT_STEREO, 0},
+ {FEEDER_FMT, AFMT_U16_LE, AFMT_S32_LE, 0},
+ {FEEDER_FMT, AFMT_U16_LE | AFMT_STEREO, AFMT_S32_LE | AFMT_STEREO, 0},
+ {FEEDER_FMT, AFMT_S16_LE, AFMT_U32_LE, 0},
+ {FEEDER_FMT, AFMT_S16_LE | AFMT_STEREO, AFMT_U32_LE | AFMT_STEREO, 0},
+ {FEEDER_FMT, AFMT_U16_BE, AFMT_S32_BE, 0},
+ {FEEDER_FMT, AFMT_U16_BE | AFMT_STEREO, AFMT_S32_BE | AFMT_STEREO, 0},
+ {FEEDER_FMT, AFMT_S16_BE, AFMT_U32_BE, 0},
+ {FEEDER_FMT, AFMT_S16_BE | AFMT_STEREO, AFMT_U32_BE | AFMT_STEREO, 0},
+ {0, 0, 0, 0},
+};
+static kobj_method_t feeder_16to32_methods[] = {
+ KOBJMETHOD(feeder_init, feed_updownbit_init),
+ KOBJMETHOD(feeder_feed, feed_upbit),
+ {0, 0}
+};
+FEEDER_DECLARE(feeder_16to32, 0, NULL);
+
+static struct pcm_feederdesc feeder_24to32_desc[] = {
+ {FEEDER_FMT, AFMT_U24_LE, AFMT_U32_LE, 0},
+ {FEEDER_FMT, AFMT_U24_LE | AFMT_STEREO, AFMT_U32_LE | AFMT_STEREO, 0},
+ {FEEDER_FMT, AFMT_S24_LE, AFMT_S32_LE, 0},
+ {FEEDER_FMT, AFMT_S24_LE | AFMT_STEREO, AFMT_S32_LE | AFMT_STEREO, 0},
+ {FEEDER_FMT, AFMT_U24_BE, AFMT_U32_BE, 0},
+ {FEEDER_FMT, AFMT_U24_BE | AFMT_STEREO, AFMT_U32_BE | AFMT_STEREO, 0},
+ {FEEDER_FMT, AFMT_S24_BE, AFMT_S32_BE, 0},
+ {FEEDER_FMT, AFMT_S24_BE | AFMT_STEREO, AFMT_S32_BE | AFMT_STEREO, 0},
+ {FEEDER_FMT, AFMT_U24_LE, AFMT_S32_LE, 0},
+ {FEEDER_FMT, AFMT_U24_LE | AFMT_STEREO, AFMT_S32_LE | AFMT_STEREO, 0},
+ {FEEDER_FMT, AFMT_S24_LE, AFMT_U32_LE, 0},
+ {FEEDER_FMT, AFMT_S24_LE | AFMT_STEREO, AFMT_U32_LE | AFMT_STEREO, 0},
+ {FEEDER_FMT, AFMT_U24_BE, AFMT_S32_BE, 0},
+ {FEEDER_FMT, AFMT_U24_BE | AFMT_STEREO, AFMT_S32_BE | AFMT_STEREO, 0},
+ {FEEDER_FMT, AFMT_S24_BE, AFMT_U32_BE, 0},
+ {FEEDER_FMT, AFMT_S24_BE | AFMT_STEREO, AFMT_U32_BE | AFMT_STEREO, 0},
+ {0, 0, 0, 0},
+};
+static kobj_method_t feeder_24to32_methods[] = {
+ KOBJMETHOD(feeder_init, feed_updownbit_init),
+ KOBJMETHOD(feeder_feed, feed_upbit),
+ {0, 0}
+};
+FEEDER_DECLARE(feeder_24to32, 0, NULL);
+
+static int
+feed_downbit(struct pcm_feeder *f, struct pcm_channel *c, uint8_t *b,
+ uint32_t count, void *source)
+{
+ int i, j, k, sign, be, ibps, ialign, obps, oalign,dump;
+ uint8_t *src, *dst, *end;
+ uint8_t reservoir[FEEDFMT_RESERVOIR];
+
+ ibps = FBIT_INBPS((intptr_t)f->data);
+ obps = FBIT_OUTBPS((intptr_t)f->data);
+
+ ialign = ibps * FBIT_CHANNELS((intptr_t)f->data);
+ oalign = obps * FBIT_CHANNELS((intptr_t)f->data);
+
+ if (count < oalign)
+ return (0);
+
+ dst = b;
+ dump = ibps - obps;
+ sign = FEEDFMT_SWAP_SIGN(f);
+ be = (f->desc->in & AFMT_BIGENDIAN) ? 1 : 0;
+ k = count - (count % oalign);
+
+ do {
+ if (k < oalign)
+ break;
+
+ if (k < ialign) {
+ src = reservoir;
+ j = ialign;
+ } else {
+ src = dst;
+ j = k;
+ }
+
+ j = FEEDER_FEED(f->source, c, src, j - (j % ialign), source);
+ if (j < ialign)
+ break;
+
+ j -= j % ialign;
+ j *= obps;
+ j /= ibps;
+ end = dst + j;
+
+ if (be != 0) {
+ do {
+ *dst++ = *src++ ^ sign;
+ i = obps;
+ while (--i != 0)
+ *dst++ = *src++;
+ src += dump;
+ } while (dst != end);
+ } else {
+ do {
+ src += dump;
+ i = obps;
+ while (--i != 0)
+ *dst++ = *src++;
+ *dst++ = *src++ ^ sign;
+ } while (dst != end);
+ }
+
+ k -= j;
+ } while (k != 0);
+
+ return (dst - b);
+}
+
+static struct pcm_feederdesc feeder_16to8_desc[] = {
+ {FEEDER_FMT, AFMT_U16_LE, AFMT_U8, 0},
+ {FEEDER_FMT, AFMT_U16_LE | AFMT_STEREO, AFMT_U8 | AFMT_STEREO, 0},
+ {FEEDER_FMT, AFMT_S16_LE, AFMT_S8, 0},
+ {FEEDER_FMT, AFMT_S16_LE | AFMT_STEREO, AFMT_S8 | AFMT_STEREO, 0},
+ {FEEDER_FMT, AFMT_U16_BE, AFMT_U8, 0},
+ {FEEDER_FMT, AFMT_U16_BE | AFMT_STEREO, AFMT_U8 | AFMT_STEREO, 0},
+ {FEEDER_FMT, AFMT_S16_BE, AFMT_S8, 0},
+ {FEEDER_FMT, AFMT_S16_BE | AFMT_STEREO, AFMT_S8 | AFMT_STEREO, 0},
+ {FEEDER_FMT, AFMT_U16_LE, AFMT_S8, 0},
+ {FEEDER_FMT, AFMT_U16_LE | AFMT_STEREO, AFMT_S8 | AFMT_STEREO, 0},
+ {FEEDER_FMT, AFMT_S16_LE, AFMT_U8, 0},
+ {FEEDER_FMT, AFMT_S16_LE | AFMT_STEREO, AFMT_U8 | AFMT_STEREO, 0},
+ {FEEDER_FMT, AFMT_U16_BE, AFMT_S8, 0},
+ {FEEDER_FMT, AFMT_U16_BE | AFMT_STEREO, AFMT_S8 | AFMT_STEREO, 0},
+ {FEEDER_FMT, AFMT_S16_BE, AFMT_U8, 0},
+ {FEEDER_FMT, AFMT_S16_BE | AFMT_STEREO, AFMT_U8 | AFMT_STEREO, 0},
+ {0, 0, 0, 0},
+};
+static kobj_method_t feeder_16to8_methods[] = {
+ KOBJMETHOD(feeder_init, feed_updownbit_init),
+ KOBJMETHOD(feeder_feed, feed_downbit),
+ {0, 0}
+};
+FEEDER_DECLARE(feeder_16to8, 0, NULL);
+
+static struct pcm_feederdesc feeder_24to8_desc[] = {
+ {FEEDER_FMT, AFMT_U24_LE, AFMT_U8, 0},
+ {FEEDER_FMT, AFMT_U24_LE | AFMT_STEREO, AFMT_U8 | AFMT_STEREO, 0},
+ {FEEDER_FMT, AFMT_S24_LE, AFMT_S8, 0},
+ {FEEDER_FMT, AFMT_S24_LE | AFMT_STEREO, AFMT_S8 | AFMT_STEREO, 0},
+ {FEEDER_FMT, AFMT_U24_BE, AFMT_U8, 0},
+ {FEEDER_FMT, AFMT_U24_BE | AFMT_STEREO, AFMT_U8 | AFMT_STEREO, 0},
+ {FEEDER_FMT, AFMT_S24_BE, AFMT_S8, 0},
+ {FEEDER_FMT, AFMT_S24_BE | AFMT_STEREO, AFMT_S8 | AFMT_STEREO, 0},
+ {FEEDER_FMT, AFMT_U24_LE, AFMT_S8, 0},
+ {FEEDER_FMT, AFMT_U24_LE | AFMT_STEREO, AFMT_S8 | AFMT_STEREO, 0},
+ {FEEDER_FMT, AFMT_S24_LE, AFMT_U8, 0},
+ {FEEDER_FMT, AFMT_S24_LE | AFMT_STEREO, AFMT_U8 | AFMT_STEREO, 0},
+ {FEEDER_FMT, AFMT_U24_BE, AFMT_S8, 0},
+ {FEEDER_FMT, AFMT_U24_BE | AFMT_STEREO, AFMT_S8 | AFMT_STEREO, 0},
+ {FEEDER_FMT, AFMT_S24_BE, AFMT_U8, 0},
+ {FEEDER_FMT, AFMT_S24_BE | AFMT_STEREO, AFMT_U8 | AFMT_STEREO, 0},
+ {0, 0, 0, 0},
+};
+static kobj_method_t feeder_24to8_methods[] = {
+ KOBJMETHOD(feeder_init, feed_updownbit_init),
+ KOBJMETHOD(feeder_feed, feed_downbit),
+ {0, 0}
+};
+FEEDER_DECLARE(feeder_24to8, 0, NULL);
+
+static struct pcm_feederdesc feeder_24to16_desc[] = {
+ {FEEDER_FMT, AFMT_U24_LE, AFMT_U16_LE, 0},
+ {FEEDER_FMT, AFMT_U24_LE | AFMT_STEREO, AFMT_U16_LE | AFMT_STEREO, 0},
+ {FEEDER_FMT, AFMT_S24_LE, AFMT_S16_LE, 0},
+ {FEEDER_FMT, AFMT_S24_LE | AFMT_STEREO, AFMT_S16_LE | AFMT_STEREO, 0},
+ {FEEDER_FMT, AFMT_U24_BE, AFMT_U16_BE, 0},
+ {FEEDER_FMT, AFMT_U24_BE | AFMT_STEREO, AFMT_U16_BE | AFMT_STEREO, 0},
+ {FEEDER_FMT, AFMT_S24_BE, AFMT_S16_BE, 0},
+ {FEEDER_FMT, AFMT_S24_BE | AFMT_STEREO, AFMT_S16_BE | AFMT_STEREO, 0},
+ {FEEDER_FMT, AFMT_U24_LE, AFMT_S16_LE, 0},
+ {FEEDER_FMT, AFMT_U24_LE | AFMT_STEREO, AFMT_S16_LE | AFMT_STEREO, 0},
+ {FEEDER_FMT, AFMT_S24_LE, AFMT_U16_LE, 0},
+ {FEEDER_FMT, AFMT_S24_LE | AFMT_STEREO, AFMT_U16_LE | AFMT_STEREO, 0},
+ {FEEDER_FMT, AFMT_U24_BE, AFMT_S16_BE, 0},
+ {FEEDER_FMT, AFMT_U24_BE | AFMT_STEREO, AFMT_S16_BE | AFMT_STEREO, 0},
+ {FEEDER_FMT, AFMT_S24_BE, AFMT_U16_BE, 0},
+ {FEEDER_FMT, AFMT_S24_BE | AFMT_STEREO, AFMT_U16_BE | AFMT_STEREO, 0},
+ {0, 0, 0, 0},
+};
+static kobj_method_t feeder_24to16_methods[] = {
+ KOBJMETHOD(feeder_init, feed_updownbit_init),
+ KOBJMETHOD(feeder_feed, feed_downbit),
+ {0, 0}
+};
+FEEDER_DECLARE(feeder_24to16, 0, NULL);
+
+static struct pcm_feederdesc feeder_32to8_desc[] = {
+ {FEEDER_FMT, AFMT_U32_LE, AFMT_U8, 0},
+ {FEEDER_FMT, AFMT_U32_LE | AFMT_STEREO, AFMT_U8 | AFMT_STEREO, 0},
+ {FEEDER_FMT, AFMT_S32_LE, AFMT_S8, 0},
+ {FEEDER_FMT, AFMT_S32_LE | AFMT_STEREO, AFMT_S8 | AFMT_STEREO, 0},
+ {FEEDER_FMT, AFMT_U32_BE, AFMT_U8, 0},
+ {FEEDER_FMT, AFMT_U32_BE | AFMT_STEREO, AFMT_U8 | AFMT_STEREO, 0},
+ {FEEDER_FMT, AFMT_S32_BE, AFMT_S8, 0},
+ {FEEDER_FMT, AFMT_S32_BE | AFMT_STEREO, AFMT_S8 | AFMT_STEREO, 0},
+ {FEEDER_FMT, AFMT_U32_LE, AFMT_S8, 0},
+ {FEEDER_FMT, AFMT_U32_LE | AFMT_STEREO, AFMT_S8 | AFMT_STEREO, 0},
+ {FEEDER_FMT, AFMT_S32_LE, AFMT_U8, 0},
+ {FEEDER_FMT, AFMT_S32_LE | AFMT_STEREO, AFMT_U8 | AFMT_STEREO, 0},
+ {FEEDER_FMT, AFMT_U32_BE, AFMT_S8, 0},
+ {FEEDER_FMT, AFMT_U32_BE | AFMT_STEREO, AFMT_S8 | AFMT_STEREO, 0},
+ {FEEDER_FMT, AFMT_S32_BE, AFMT_U8, 0},
+ {FEEDER_FMT, AFMT_S32_BE | AFMT_STEREO, AFMT_U8 | AFMT_STEREO, 0},
+ {0, 0, 0, 0},
+};
+static kobj_method_t feeder_32to8_methods[] = {
+ KOBJMETHOD(feeder_init, feed_updownbit_init),
+ KOBJMETHOD(feeder_feed, feed_downbit),
+ {0, 0}
+};
+FEEDER_DECLARE(feeder_32to8, 0, NULL);
+
+static struct pcm_feederdesc feeder_32to16_desc[] = {
+ {FEEDER_FMT, AFMT_U32_LE, AFMT_U16_LE, 0},
+ {FEEDER_FMT, AFMT_U32_LE | AFMT_STEREO, AFMT_U16_LE | AFMT_STEREO, 0},
+ {FEEDER_FMT, AFMT_S32_LE, AFMT_S16_LE, 0},
+ {FEEDER_FMT, AFMT_S32_LE | AFMT_STEREO, AFMT_S16_LE | AFMT_STEREO, 0},
+ {FEEDER_FMT, AFMT_U32_BE, AFMT_U16_BE, 0},
+ {FEEDER_FMT, AFMT_U32_BE | AFMT_STEREO, AFMT_U16_BE | AFMT_STEREO, 0},
+ {FEEDER_FMT, AFMT_S32_BE, AFMT_S16_BE, 0},
+ {FEEDER_FMT, AFMT_S32_BE | AFMT_STEREO, AFMT_S16_BE | AFMT_STEREO, 0},
+ {FEEDER_FMT, AFMT_U32_LE, AFMT_S16_LE, 0},
+ {FEEDER_FMT, AFMT_U32_LE | AFMT_STEREO, AFMT_S16_LE | AFMT_STEREO, 0},
+ {FEEDER_FMT, AFMT_S32_LE, AFMT_U16_LE, 0},
+ {FEEDER_FMT, AFMT_S32_LE | AFMT_STEREO, AFMT_U16_LE | AFMT_STEREO, 0},
+ {FEEDER_FMT, AFMT_U32_BE, AFMT_S16_BE, 0},
+ {FEEDER_FMT, AFMT_U32_BE | AFMT_STEREO, AFMT_S16_BE | AFMT_STEREO, 0},
+ {FEEDER_FMT, AFMT_S32_BE, AFMT_U16_BE, 0},
+ {FEEDER_FMT, AFMT_S32_BE | AFMT_STEREO, AFMT_U16_BE | AFMT_STEREO, 0},
+ {0, 0, 0, 0},
+};
+static kobj_method_t feeder_32to16_methods[] = {
+ KOBJMETHOD(feeder_init, feed_updownbit_init),
+ KOBJMETHOD(feeder_feed, feed_downbit),
+ {0, 0}
+};
+FEEDER_DECLARE(feeder_32to16, 0, NULL);
+
+static struct pcm_feederdesc feeder_32to24_desc[] = {
+ {FEEDER_FMT, AFMT_U32_LE, AFMT_U24_LE, 0},
+ {FEEDER_FMT, AFMT_U32_LE | AFMT_STEREO, AFMT_U24_LE | AFMT_STEREO, 0},
+ {FEEDER_FMT, AFMT_S32_LE, AFMT_S24_LE, 0},
+ {FEEDER_FMT, AFMT_S32_LE | AFMT_STEREO, AFMT_S24_LE | AFMT_STEREO, 0},
+ {FEEDER_FMT, AFMT_U32_BE, AFMT_U24_BE, 0},
+ {FEEDER_FMT, AFMT_U32_BE | AFMT_STEREO, AFMT_U24_BE | AFMT_STEREO, 0},
+ {FEEDER_FMT, AFMT_S32_BE, AFMT_S24_BE, 0},
+ {FEEDER_FMT, AFMT_S32_BE | AFMT_STEREO, AFMT_S24_BE | AFMT_STEREO, 0},
+ {FEEDER_FMT, AFMT_U32_LE, AFMT_S24_LE, 0},
+ {FEEDER_FMT, AFMT_U32_LE | AFMT_STEREO, AFMT_S24_LE | AFMT_STEREO, 0},
+ {FEEDER_FMT, AFMT_S32_LE, AFMT_U24_LE, 0},
+ {FEEDER_FMT, AFMT_S32_LE | AFMT_STEREO, AFMT_U24_LE | AFMT_STEREO, 0},
+ {FEEDER_FMT, AFMT_U32_BE, AFMT_S24_BE, 0},
+ {FEEDER_FMT, AFMT_U32_BE | AFMT_STEREO, AFMT_S24_BE | AFMT_STEREO, 0},
+ {FEEDER_FMT, AFMT_S32_BE, AFMT_U24_BE, 0},
+ {FEEDER_FMT, AFMT_S32_BE | AFMT_STEREO, AFMT_U24_BE | AFMT_STEREO, 0},
+ {0, 0, 0, 0},
+};
+static kobj_method_t feeder_32to24_methods[] = {
+ KOBJMETHOD(feeder_init, feed_updownbit_init),
+ KOBJMETHOD(feeder_feed, feed_downbit),
+ {0, 0}
};
-FEEDER_DECLARE(feeder_32leto16le, 1, NULL);
+FEEDER_DECLARE(feeder_32to24, 0, NULL);
/*
-* Bit conversion end
-*/
+ * Bit conversion end
+ */
/*
-* Channel conversion (mono -> stereo)
-*/
+ * Channel conversion (mono -> stereo)
+ */
static int
-feed_monotostereo8(struct pcm_feeder *f, struct pcm_channel *c, uint8_t *b,
-uint32_t count, void *source)
+feed_monotostereo(struct pcm_feeder *f, struct pcm_channel *c, uint8_t *b,
+ uint32_t count, void *source)
{
-int i, j, k = FEEDER_FEED(f->source, c, b, count >> 1, source);
+ int bps, i, j, k, l;
+ uint8_t v;
-i = k;
-j = k << 1;
-while (i > 0) {
-b[--j] = b[--i];
-b[--j] = b[i];
-}
-return k << 1;
+ bps = (int)((intptr_t)f->data);
+ if (count < (bps << 1))
+ return (0);
+
+ j = FEEDER_FEED(f->source, c, b, (count - (count % bps)) >> 1, source);
+ if (j < bps)
+ return (0);
+
+ j -= j % bps;
+ i = j << 1;
+ l = i;
+
+ do {
+ k = bps;
+ do {
+ v = b[--j];
+ b[--i] = v;
+ b[i - bps] = v;
+ } while (--k != 0);
+ i -= bps;
+ } while (i != 0);
+
+ return (l);
}
+
static struct pcm_feederdesc feeder_monotostereo8_desc[] = {
-{FEEDER_FMT, AFMT_U8, AFMT_U8|AFMT_STEREO, 0},
-{FEEDER_FMT, AFMT_S8, AFMT_S8|AFMT_STEREO, 0},
-{0, 0, 0, 0},
+ {FEEDER_FMT, AFMT_U8, AFMT_U8 | AFMT_STEREO, 0},
+ {FEEDER_FMT, AFMT_S8, AFMT_S8 | AFMT_STEREO, 0},
+ {FEEDER_FMT, AFMT_MU_LAW, AFMT_MU_LAW | AFMT_STEREO, 0},
+ {FEEDER_FMT, AFMT_A_LAW, AFMT_A_LAW | AFMT_STEREO, 0},
+ {0, 0, 0, 0},
};
static kobj_method_t feeder_monotostereo8_methods[] = {
-KOBJMETHOD(feeder_feed, feed_monotostereo8),
-{0, 0}
+ KOBJMETHOD(feeder_feed, feed_monotostereo),
+ {0, 0}
};
-FEEDER_DECLARE(feeder_monotostereo8, 0, NULL);
+FEEDER_DECLARE(feeder_monotostereo8, 0, (void *)PCM_8_BPS);
-static int
-feed_monotostereo16(struct pcm_feeder *f, struct pcm_channel *c, uint8_t *b,
-uint32_t count, void *source)
-{
-int i, j, k = FEEDER_FEED(f->source, c, b, count >> 1, source);
-uint8_t l, m;
-
-if (k < 2) {
-FMT_TRACE("%s: Not enough data (Got: %d bytes)n",
-__func__, k);
-return 0;
-}
-FMT_TEST(k & 1, "%s: Bytes not 16bit aligned.n", __func__);
-FMT_ALIGNBYTE(k &= ~1);
-i = k;
-j = k << 1;
-while (i > 0) {
-l = b[--i];
-m = b[--i];
-b[--j] = l;
-b[--j] = m;
-b[--j] = l;
-b[--j] = m;
-}
-return k << 1;
-}
static struct pcm_feederdesc feeder_monotostereo16_desc[] = {
-{FEEDER_FMT, AFMT_U16_LE, AFMT_U16_LE|AFMT_STEREO, 0},
-{FEEDER_FMT, AFMT_S16_LE, AFMT_S16_LE|AFMT_STEREO, 0},
-{FEEDER_FMT, AFMT_U16_BE, AFMT_U16_BE|AFMT_STEREO, 0},
-{FEEDER_FMT, AFMT_S16_BE, AFMT_S16_BE|AFMT_STEREO, 0},
-{0, 0, 0, 0},
+ {FEEDER_FMT, AFMT_U16_LE, AFMT_U16_LE | AFMT_STEREO, 0},
+ {FEEDER_FMT, AFMT_S16_LE, AFMT_S16_LE | AFMT_STEREO, 0},
+ {FEEDER_FMT, AFMT_U16_BE, AFMT_U16_BE | AFMT_STEREO, 0},
+ {FEEDER_FMT, AFMT_S16_BE, AFMT_S16_BE | AFMT_STEREO, 0},
+ {0, 0, 0, 0},
};
static kobj_method_t feeder_monotostereo16_methods[] = {
-KOBJMETHOD(feeder_feed, feed_monotostereo16),
-{0, 0}
+ KOBJMETHOD(feeder_feed, feed_monotostereo),
+ {0, 0}
};
-FEEDER_DECLARE(feeder_monotostereo16, 0, NULL);
+FEEDER_DECLARE(feeder_monotostereo16, 0, (void *)PCM_16_BPS);
-static int
-feed_monotostereo24(struct pcm_feeder *f, struct pcm_channel *c, uint8_t *b,
-uint32_t count, void *source)
-{
-int i, j, k = FEEDER_FEED(f->source, c, b, count >> 1, source);
-uint8_t l, m, n;
-
-if (k < 3) {
-FMT_TRACE("%s: Not enough data (Got: %d bytes)n",
-__func__, k);
-return 0;
-}
-FMT_TEST(k % 3, "%s: Bytes not 24bit aligned.n", __func__);
-FMT_ALIGNBYTE(k -= k % 3);
-i = k;
-j = k << 1;
-while (i > 0) {
-l = b[--i];
-m = b[--i];
-n = b[--i];
-b[--j] = l;
-b[--j] = m;
-b[--j] = n;
-b[--j] = l;
-b[--j] = m;
-b[--j] = n;
-}
-return k << 1;
-}
static struct pcm_feederdesc feeder_monotostereo24_desc[] = {
-{FEEDER_FMT, AFMT_U24_LE, AFMT_U24_LE|AFMT_STEREO, 0},
-{FEEDER_FMT, AFMT_S24_LE, AFMT_S24_LE|AFMT_STEREO, 0},
-{FEEDER_FMT, AFMT_U24_BE, AFMT_U24_BE|AFMT_STEREO, 0},
-{FEEDER_FMT, AFMT_S24_BE, AFMT_S24_BE|AFMT_STEREO, 0},
-{0, 0, 0, 0},
+ {FEEDER_FMT, AFMT_U24_LE, AFMT_U24_LE | AFMT_STEREO, 0},
+ {FEEDER_FMT, AFMT_S24_LE, AFMT_S24_LE | AFMT_STEREO, 0},
+ {FEEDER_FMT, AFMT_U24_BE, AFMT_U24_BE | AFMT_STEREO, 0},
+ {FEEDER_FMT, AFMT_S24_BE, AFMT_S24_BE | AFMT_STEREO, 0},
+ {0, 0, 0, 0},
};
static kobj_method_t feeder_monotostereo24_methods[] = {
-KOBJMETHOD(feeder_feed, feed_monotostereo24),
-{0, 0}
+ KOBJMETHOD(feeder_feed, feed_monotostereo),
+ {0, 0}
};
-FEEDER_DECLARE(feeder_monotostereo24, 0, NULL);
+FEEDER_DECLARE(feeder_monotostereo24, 0, (void *)PCM_24_BPS);
-static int
-feed_monotostereo32(struct pcm_feeder *f, struct pcm_channel *c, uint8_t *b,
-uint32_t count, void *source)
-{
-int i, j, k = FEEDER_FEED(f->source, c, b, count >> 1, source);
-uint8_t l, m, n, o;
-
-if (k < 4) {
-FMT_TRACE("%s: Not enough data (Got: %d bytes)n",
-__func__, k);
-return 0;
-}
-FMT_TEST(k & 3, "%s: Bytes not 32bit aligned.n", __func__);
-FMT_ALIGNBYTE(k &= ~3);
-i = k;
-j = k << 1;
-while (i > 0) {
-l = b[--i];
-m = b[--i];
-n = b[--i];
-o = b[--i];
-b[--j] = l;
-b[--j] = m;
-b[--j] = n;
-b[--j] = o;
-b[--j] = l;
-b[--j] = m;
-b[--j] = n;
-b[--j] = o;
-}
-return k << 1;
-}
static struct pcm_feederdesc feeder_monotostereo32_desc[] = {
-{FEEDER_FMT, AFMT_U32_LE, AFMT_U32_LE|AFMT_STEREO, 0},
-{FEEDER_FMT, AFMT_S32_LE, AFMT_S32_LE|AFMT_STEREO, 0},
-{FEEDER_FMT, AFMT_U32_BE, AFMT_U32_BE|AFMT_STEREO, 0},
-{FEEDER_FMT, AFMT_S32_BE, AFMT_S32_BE|AFMT_STEREO, 0},
-{0, 0, 0, 0},
+ {FEEDER_FMT, AFMT_U32_LE, AFMT_U32_LE | AFMT_STEREO, 0},
+ {FEEDER_FMT, AFMT_S32_LE, AFMT_S32_LE | AFMT_STEREO, 0},
+ {FEEDER_FMT, AFMT_U32_BE, AFMT_U32_BE | AFMT_STEREO, 0},
+ {FEEDER_FMT, AFMT_S32_BE, AFMT_S32_BE | AFMT_STEREO, 0},
+ {0, 0, 0, 0},
};
static kobj_method_t feeder_monotostereo32_methods[] = {
-KOBJMETHOD(feeder_feed, feed_monotostereo32),
-{0, 0}
+ KOBJMETHOD(feeder_feed, feed_monotostereo),
+ {0, 0}
};
-FEEDER_DECLARE(feeder_monotostereo32, 0, NULL);
+FEEDER_DECLARE(feeder_monotostereo32, 0, (void *)PCM_32_BPS);
/*
-* Channel conversion (mono -> stereo) end
-*/
+ * Channel conversion (mono -> stereo) end
+ */
/*
-* Channel conversion (stereo -> mono)
-*/
-static int
-feed_stereotomono8(struct pcm_feeder *f, struct pcm_channel *c, uint8_t *b,
-uint32_t count, void *source)
-{
-int i, j, k;
-uint8_t *src = (uint8_t *)f->data;
+ * Channel conversion (stereo -> mono)
+ */
+#define FEEDER_FMT_STEREODOWNMIX(FMTBIT, FMT_INTCAST, SIGN, \
+ SIGNS, ENDIAN, ENDIANS) \
+static void \
+SIGNS##FMTBIT##ENDIANS##_stereodownmix(uint8_t *dst, uint8_t *sx, uint8_t *sy) \
+{ \
+ int32_t v; \
+ \
+ v = ((FMT_INTCAST)PCM_READ_##SIGN##FMTBIT##_##ENDIAN(sx) + \
+ PCM_READ_##SIGN##FMTBIT##_##ENDIAN(sy)) >> 1; \
+ PCM_WRITE_##SIGN##FMTBIT##_##ENDIAN(dst, v); \
+}
+
+FEEDER_FMT_STEREODOWNMIX(8, int32_t, S, s, NE, ne);
+FEEDER_FMT_STEREODOWNMIX(16, int32_t, S, s, LE, le);
+FEEDER_FMT_STEREODOWNMIX(24, int32_t, S, s, LE, le);
+FEEDER_FMT_STEREODOWNMIX(32, intpcm_t, S, s, LE, le);
+FEEDER_FMT_STEREODOWNMIX(16, int32_t, S, s, BE, be);
+FEEDER_FMT_STEREODOWNMIX(24, int32_t, S, s, BE, be);
+FEEDER_FMT_STEREODOWNMIX(32, intpcm_t, S, s, BE, be);
+FEEDER_FMT_STEREODOWNMIX(8, int32_t, U, u, NE, ne);
+FEEDER_FMT_STEREODOWNMIX(16, int32_t, U, u, LE, le);
+FEEDER_FMT_STEREODOWNMIX(24, int32_t, U, u, LE, le);
+FEEDER_FMT_STEREODOWNMIX(32, intpcm_t, U, u, LE, le);
+FEEDER_FMT_STEREODOWNMIX(16, int32_t, U, u, BE, be);
+FEEDER_FMT_STEREODOWNMIX(24, int32_t, U, u, BE, be);
+FEEDER_FMT_STEREODOWNMIX(32, intpcm_t, U, u, BE, be);
+
+static void
+ulaw_stereodownmix(uint8_t *dst, uint8_t *sx, uint8_t *sy)
+{
+ uint8_t v;
+
+ v = ((uint32_t)ulaw_to_u8_tbl[*sx] + ulaw_to_u8_tbl[*sy]) >> 1;
+ *dst = u8_to_ulaw_tbl[v];
+}
+
+static void
+alaw_stereodownmix(uint8_t *dst, uint8_t *sx, uint8_t *sy)
+{
+ uint8_t v;
+
+ v = ((uint32_t)alaw_to_u8_tbl[*sx] + alaw_to_u8_tbl[*sy]) >> 1;
+ *dst = u8_to_alaw_tbl[v];
+}
+
+typedef void (*feed_fmt_stereodownmix_filter)(uint8_t *,
+ uint8_t *, uint8_t *);
+
+struct feed_fmt_stereodownmix_info {
+ uint32_t format;
+ int bps;
+ feed_fmt_stereodownmix_filter func[2];
+};
+
+static struct feed_fmt_stereodownmix_info feed_fmt_stereodownmix_tbl[] = {
+ { AFMT_S8, PCM_8_BPS, { NULL, s8ne_stereodownmix }},
+ { AFMT_S16_LE, PCM_16_BPS, { NULL, s16le_stereodownmix }},
+ { AFMT_S16_BE, PCM_16_BPS, { NULL, s16be_stereodownmix }},
+ { AFMT_S24_LE, PCM_24_BPS, { NULL, s24le_stereodownmix }},
+ { AFMT_S24_BE, PCM_24_BPS, { NULL, s24be_stereodownmix }},
+ { AFMT_S32_LE, PCM_32_BPS, { NULL, s32le_stereodownmix }},
+ { AFMT_S32_BE, PCM_32_BPS, { NULL, s32be_stereodownmix }},
+ { AFMT_U8, PCM_8_BPS, { NULL, u8ne_stereodownmix }},
+ { AFMT_A_LAW, PCM_8_BPS, { NULL, alaw_stereodownmix }},
+ { AFMT_MU_LAW, PCM_8_BPS, { NULL, ulaw_stereodownmix }},
+ { AFMT_U16_LE, PCM_16_BPS, { NULL, u16le_stereodownmix }},
+ { AFMT_U16_BE, PCM_16_BPS, { NULL, u16be_stereodownmix }},
+ { AFMT_U24_LE, PCM_24_BPS, { NULL, u24le_stereodownmix }},
+ { AFMT_U24_BE, PCM_24_BPS, { NULL, u24be_stereodownmix }},
+ { AFMT_U32_LE, PCM_32_BPS, { NULL, u32le_stereodownmix }},
+ { AFMT_U32_BE, PCM_32_BPS, { NULL, u32be_stereodownmix }},
+};
+
+#define FSM_DATA(i, j) ((intptr_t)((((i) & 0x1f) << 1) | ((j) & 0x1)))
+#define FSM_INFOIDX(m) (((m) >> 1) & 0x1f)
+#define FSM_FUNCIDX(m) ((m) & 0x1)
+
+static int
+feed_stereotomono_init(struct pcm_feeder *f)
+{
+ int i, funcidx;
+
+ if (!(f->desc->in & AFMT_STEREO) || (f->desc->out & AFMT_STEREO))
+ return (-1);
+
+ funcidx = (feeder_fmt_stereodownmix != 0) ? 1 : 0;
+
+ for (i = 0; i < sizeof(feed_fmt_stereodownmix_tbl) /
+ sizeof(feed_fmt_stereodownmix_tbl[0]); i++) {
+ if (f->desc->out == feed_fmt_stereodownmix_tbl[i].format) {
+ f->data = (void *)FSM_DATA(i, funcidx);
+ return (0);
+ }
+ }
+
+ return (-1);
+}
+
+static int
+feed_stereotomono(struct pcm_feeder *f, struct pcm_channel *c, uint8_t *b,
+ uint32_t count, void *source)
+{
+ struct feed_fmt_stereodownmix_info *info;
+ feed_fmt_stereodownmix_filter stereodownmix;
+ int i, j, k, ibps, obps;
+ uint8_t *src, *dst, *end;
+ uint8_t reservoir[FEEDFMT_RESERVOIR];
+
+ info = &feed_fmt_stereodownmix_tbl[FSM_INFOIDX((intptr_t)f->data)];
+ obps = info->bps;
+
+ if (count < obps)
+ return (0);
+
+ stereodownmix = info->func[FSM_FUNCIDX((intptr_t)f->data)];
+ ibps = obps << 1;
+ dst = b;
+ k = count - (count % obps);
+
+ do {
+ if (k < obps)
+ break;
+
+ if (k < ibps) {
+ src = reservoir;
+ j = ibps;
+ } else {
+ src = dst;
+ j = k;
+ }
+
+ j = FEEDER_FEED(f->source, c, src, j - (j % ibps), source);
+ if (j < ibps)
+ break;
+
+ j -= j % ibps;
+ j >>= 1;
+ end = dst + j;
+
+ if (stereodownmix != NULL) {
+ do {
+ stereodownmix(dst, src, src + obps);
+ dst += obps;
+ src += ibps;
+ } while (dst != end);
+ } else {
+ do {
+ i = obps;
+ do {
+ *dst++ = *src++;
+ } while (--i != 0);
+ src += obps;
+ } while (dst != end);
+ }
-k = count << 1;
-k = FEEDER_FEED(f->source, c, src, min(k, FEEDBUFSZ), source);
-if (k < 2) {
-FMT_TRACE("%s: Not enough data (Got: %d bytes)n",
-__func__, k);
-return 0;
-}
-FMT_TEST(k & 1, "%s: Bytes not 8bit (stereo) aligned.n", __func__);
-FMT_ALIGNBYTE(k &= ~1);
-i = k >> 1;
-j = i;
-while (i > 0) {
-k--;
-b[--i] = src[--k];
-}
-return j;
+ k -= j;
+ } while (k != 0);
+
+ return (dst - b);
}
+
static struct pcm_feederdesc feeder_stereotomono8_desc[] = {
-{FEEDER_FMT, AFMT_U8|AFMT_STEREO, AFMT_U8, 0},
-{FEEDER_FMT, AFMT_S8|AFMT_STEREO, AFMT_S8, 0},
-{0, 0, 0, 0},
+ {FEEDER_FMT, AFMT_U8 | AFMT_STEREO, AFMT_U8, 0},
+ {FEEDER_FMT, AFMT_S8 | AFMT_STEREO, AFMT_S8, 0},
+ {FEEDER_FMT, AFMT_MU_LAW | AFMT_STEREO, AFMT_MU_LAW, 0},
+ {FEEDER_FMT, AFMT_A_LAW | AFMT_STEREO, AFMT_A_LAW, 0},
+ {0, 0, 0, 0},
};
static kobj_method_t feeder_stereotomono8_methods[] = {
-KOBJMETHOD(feeder_init, feed_common_init),
-KOBJMETHOD(feeder_free, feed_common_free),
-KOBJMETHOD(feeder_feed, feed_stereotomono8),
-{0, 0}
+ KOBJMETHOD(feeder_init, feed_stereotomono_init),
+ KOBJMETHOD(feeder_feed, feed_stereotomono),
+ {0, 0}
};
FEEDER_DECLARE(feeder_stereotomono8, 0, NULL);
-static int
-feed_stereotomono16(struct pcm_feeder *f, struct pcm_channel *c, uint8_t *b,
-uint32_t count, void *source)
-{
-int i, j, k;
-uint8_t *src = (uint8_t *)f->data;
-
-k = count << 1;
-k = FEEDER_FEED(f->source, c, src, min(k, FEEDBUFSZ), source);
-if (k < 4) {
-FMT_TRACE("%s: Not enough data (Got: %d bytes)n",
-__func__, k);
-return 0;
-}
-FMT_TEST(k & 3, "%s: Bytes not 16bit (stereo) aligned.n", __func__);
-FMT_ALIGNBYTE(k &= ~3);
-i = k >> 1;
-j = i;
-while (i > 0) {
-k -= 2;
-b[--i] = src[--k];
-b[--i] = src[--k];
-}
-return j;
-}
static struct pcm_feederdesc feeder_stereotomono16_desc[] = {
-{FEEDER_FMT, AFMT_U16_LE|AFMT_STEREO, AFMT_U16_LE, 0},
-{FEEDER_FMT, AFMT_S16_LE|AFMT_STEREO, AFMT_S16_LE, 0},
-{FEEDER_FMT, AFMT_U16_BE|AFMT_STEREO, AFMT_U16_BE, 0},
-{FEEDER_FMT, AFMT_S16_BE|AFMT_STEREO, AFMT_S16_BE, 0},
-{0, 0, 0, 0},
+ {FEEDER_FMT, AFMT_U16_LE | AFMT_STEREO, AFMT_U16_LE, 0},
+ {FEEDER_FMT, AFMT_S16_LE | AFMT_STEREO, AFMT_S16_LE, 0},
+ {FEEDER_FMT, AFMT_U16_BE | AFMT_STEREO, AFMT_U16_BE, 0},
+ {FEEDER_FMT, AFMT_S16_BE | AFMT_STEREO, AFMT_S16_BE, 0},
+ {0, 0, 0, 0},
};
static kobj_method_t feeder_stereotomono16_methods[] = {
-KOBJMETHOD(feeder_init, feed_common_init),
-KOBJMETHOD(feeder_free, feed_common_free),
-KOBJMETHOD(feeder_feed, feed_stereotomono16),
-{0, 0}
+ KOBJMETHOD(feeder_init, feed_stereotomono_init),
+ KOBJMETHOD(feeder_feed, feed_stereotomono),
+ {0, 0}
};
FEEDER_DECLARE(feeder_stereotomono16, 0, NULL);
-static int
-feed_stereotomono24(struct pcm_feeder *f, struct pcm_channel *c, uint8_t *b,
-uint32_t count, void *source)
-{
-int i, j, k;
-uint8_t *src = (uint8_t *)f->data;
-
-k = count << 1;
-k = FEEDER_FEED(f->source, c, src, min(k, FEEDBUF24SZ), source);
-if (k < 6) {
-FMT_TRACE("%s: Not enough data (Got: %d bytes)n",
-__func__, k);
-return 0;
-}
-FMT_TEST(k % 6, "%s: Bytes not 24bit (stereo) aligned.n", __func__);
-FMT_ALIGNBYTE(k -= k % 6);
-i = k >> 1;
-j = i;
-while (i > 0) {
-k -= 3;
-b[--i] = src[--k];
-b[--i] = src[--k];
-b[--i] = src[--k];
-}
-return j;
-}
static struct pcm_feederdesc feeder_stereotomono24_desc[] = {
-{FEEDER_FMT, AFMT_U24_LE|AFMT_STEREO, AFMT_U24_LE, 0},
-{FEEDER_FMT, AFMT_S24_LE|AFMT_STEREO, AFMT_S24_LE, 0},
-{FEEDER_FMT, AFMT_U24_BE|AFMT_STEREO, AFMT_U24_BE, 0},
-{FEEDER_FMT, AFMT_S24_BE|AFMT_STEREO, AFMT_S24_BE, 0},
-{0, 0, 0, 0},
+ {FEEDER_FMT, AFMT_U24_LE | AFMT_STEREO, AFMT_U24_LE, 0},
+ {FEEDER_FMT, AFMT_S24_LE | AFMT_STEREO, AFMT_S24_LE, 0},
+ {FEEDER_FMT, AFMT_U24_BE | AFMT_STEREO, AFMT_U24_BE, 0},
+ {FEEDER_FMT, AFMT_S24_BE | AFMT_STEREO, AFMT_S24_BE, 0},
+ {0, 0, 0, 0},
};
static kobj_method_t feeder_stereotomono24_methods[] = {
-KOBJMETHOD(feeder_init, feed_common_init),
-KOBJMETHOD(feeder_free, feed_common_free),
-KOBJMETHOD(feeder_feed, feed_stereotomono24),
-{0, 0}
+ KOBJMETHOD(feeder_init, feed_stereotomono_init),
+ KOBJMETHOD(feeder_feed, feed_stereotomono),
+ {0, 0}
};
FEEDER_DECLARE(feeder_stereotomono24, 0, NULL);
-static int
-feed_stereotomono32(struct pcm_feeder *f, struct pcm_channel *c, uint8_t *b,
-uint32_t count, void *source)
-{
-int i, j, k;
-uint8_t *src = (uint8_t *)f->data;
-
-k = count << 1;
-k = FEEDER_FEED(f->source, c, src, min(k, FEEDBUFSZ), source);
-if (k < 8) {
-FMT_TRACE("%s: Not enough data (Got: %d bytes)n",
-__func__, k);
-return 0;
-}
-FMT_TEST(k & 7, "%s: Bytes not 32bit (stereo) aligned.n", __func__);
-FMT_ALIGNBYTE(k &= ~7);
-i = k >> 1;
-j = i;
-while (i > 0) {
-k -= 4;
-b[--i] = src[--k];
-b[--i] = src[--k];
-b[--i] = src[--k];
-b[--i] = src[--k];
-}
-return j;
-}
static struct pcm_feederdesc feeder_stereotomono32_desc[] = {
-{FEEDER_FMT, AFMT_U32_LE|AFMT_STEREO, AFMT_U32_LE, 0},
-{FEEDER_FMT, AFMT_S32_LE|AFMT_STEREO, AFMT_S32_LE, 0},
-{FEEDER_FMT, AFMT_U32_BE|AFMT_STEREO, AFMT_U32_BE, 0},
-{FEEDER_FMT, AFMT_S32_BE|AFMT_STEREO, AFMT_S32_BE, 0},
-{0, 0, 0, 0},
+ {FEEDER_FMT, AFMT_U32_LE | AFMT_STEREO, AFMT_U32_LE, 0},
+ {FEEDER_FMT, AFMT_S32_LE | AFMT_STEREO, AFMT_S32_LE, 0},
+ {FEEDER_FMT, AFMT_U32_BE | AFMT_STEREO, AFMT_U32_BE, 0},
+ {FEEDER_FMT, AFMT_S32_BE | AFMT_STEREO, AFMT_S32_BE, 0},
+ {0, 0, 0, 0},
};
static kobj_method_t feeder_stereotomono32_methods[] = {
-KOBJMETHOD(feeder_init, feed_common_init),
-KOBJMETHOD(feeder_free, feed_common_free),
-KOBJMETHOD(feeder_feed, feed_stereotomono32),
-{0, 0}
+ KOBJMETHOD(feeder_init, feed_stereotomono_init),
+ KOBJMETHOD(feeder_feed, feed_stereotomono),
+ {0, 0}
};
FEEDER_DECLARE(feeder_stereotomono32, 0, NULL);
/*
-* Channel conversion (stereo -> mono) end
-*/
+ * Channel conversion (stereo -> mono) end
+ */
/*
-* Sign conversion
-*/
+ * Sign conversion
+ */
static int
-feed_sign8(struct pcm_feeder *f, struct pcm_channel *c, uint8_t *b,
-uint32_t count, void *source)
+feed_sign(struct pcm_feeder *f, struct pcm_channel *c, uint8_t *b,
+ uint32_t count, void *source)
{
-int i, j = FEEDER_FEED(f->source, c, b, count, source);
+ int i, j, bps, ofs;
-i = j;
-while (i > 0)
-b[--i] ^= 0x80;
-return j;
-}
-static struct pcm_feederdesc feeder_sign8_desc[] = {
-{FEEDER_FMT, AFMT_U8, AFMT_S8, 0},
-{FEEDER_FMT, AFMT_U8|AFMT_STEREO, AFMT_S8|AFMT_STEREO, 0},
-{FEEDER_FMT, AFMT_S8, AFMT_U8, 0},
-{FEEDER_FMT, AFMT_S8|AFMT_STEREO, AFMT_U8|AFMT_STEREO, 0},
-{0, 0, 0, 0},
-};
-static kobj_method_t feeder_sign8_methods[] = {
-KOBJMETHOD(feeder_feed, feed_sign8),
-{0, 0}
-};
-FEEDER_DECLARE(feeder_sign8, 0, NULL);
+ bps = (int)((intptr_t)f->data);
+ if (count < bps)
+ return (0);
-static int
-feed_sign16le(struct pcm_feeder *f, struct pcm_channel *c, uint8_t *b,
-uint32_t count, void *source)
-{
-int i, j = FEEDER_FEED(f->source, c, b, count, source);
+ i = FEEDER_FEED(f->source, c, b, count - (count % bps), source);
+ if (i < bps)
+ return (0);
-if (j < 2) {
-FMT_TRACE("%s: Not enough data (Got: %d bytes)n",
-__func__, j);
-return 0;
-}
-FMT_TEST(j & 1, "%s: Bytes not 16bit aligned.n", __func__);
-FMT_ALIGNBYTE(j &= ~1);
-i = j;
-while (i > 0) {
-b[--i] ^= 0x80;
-i--;
-}
-return j;
-}
-static struct pcm_feederdesc feeder_sign16le_desc[] = {
-{FEEDER_FMT, AFMT_U16_LE, AFMT_S16_LE, 0},
-{FEEDER_FMT, AFMT_U16_LE|AFMT_STEREO, AFMT_S16_LE|AFMT_STEREO, 0},
-{FEEDER_FMT, AFMT_S16_LE, AFMT_U16_LE, 0},
-{FEEDER_FMT, AFMT_S16_LE|AFMT_STEREO, AFMT_U16_LE|AFMT_STEREO, 0},
-{0, 0, 0, 0},
-};
-static kobj_method_t feeder_sign16le_methods[] = {
-KOBJMETHOD(feeder_feed, feed_sign16le),
-{0, 0}
-};
-FEEDER_DECLARE(feeder_sign16le, 0, NULL);
+ i -= i % bps;
+ j = i;
+ ofs = (f->desc->in & AFMT_BIGENDIAN) ? bps : 1;
-static int
-feed_sign24le(struct pcm_feeder *f, struct pcm_channel *c, uint8_t *b,
-uint32_t count, void *source)
-{
-int i, j = FEEDER_FEED(f->source, c, b, count, source);
+ do {
+ b[i - ofs] ^= 0x80;
+ i -= bps;
+ } while (i != 0);
-if (j < 3) {
-FMT_TRACE("%s: Not enough data (Got: %d bytes)n",
-__func__, j);
-return 0;
-}
-FMT_TEST(j % 3, "%s: Bytes not 24bit aligned.n", __func__);
-FMT_ALIGNBYTE(j -= j % 3);
-i = j;
-while (i > 0) {
-b[--i] ^= 0x80;
-i -= 2;
+ return (j);
}
-return j;
-}
-static struct pcm_feederdesc feeder_sign24le_desc[] = {
-{FEEDER_FMT, AFMT_U24_LE, AFMT_S24_LE, 0},
-{FEEDER_FMT, AFMT_U24_LE|AFMT_STEREO, AFMT_S24_LE|AFMT_STEREO, 0},
-{FEEDER_FMT, AFMT_S24_LE, AFMT_U24_LE, 0},
-{FEEDER_FMT, AFMT_S24_LE|AFMT_STEREO, AFMT_U24_LE|AFMT_STEREO, 0},
-{0, 0, 0, 0},
-};
-static kobj_method_t feeder_sign24le_methods[] = {
-KOBJMETHOD(feeder_feed, feed_sign24le),
-{0, 0}
+static struct pcm_feederdesc feeder_sign8_desc[] = {
+ {FEEDER_FMT, AFMT_U8, AFMT_S8, 0},
+ {FEEDER_FMT, AFMT_U8 | AFMT_STEREO, AFMT_S8 | AFMT_STEREO, 0},
+ {FEEDER_FMT, AFMT_S8, AFMT_U8, 0},
+ {FEEDER_FMT, AFMT_S8 | AFMT_STEREO, AFMT_U8 | AFMT_STEREO, 0},
+ {0, 0, 0, 0},
};
-FEEDER_DECLARE(feeder_sign24le, 0, NULL);
-
-static int
-feed_sign32le(struct pcm_feeder *f, struct pcm_channel *c, uint8_t *b,
-uint32_t count, void *source)
-{
-int i, j = FEEDER_FEED(f->source, c, b, count, source);
+static kobj_method_t feeder_sign8_methods[] = {
+ KOBJMETHOD(feeder_feed, feed_sign),
+ {0, 0}
+};
+FEEDER_DECLARE(feeder_sign8, 0, (void *)PCM_8_BPS);
-if (j < 4) {
-FMT_TRACE("%s: Not enough data (Got: %d bytes)n",
-__func__, j);
-return 0;
-}
-FMT_TEST(j & 3, "%s: Bytes not 32bit aligned.n", __func__);
-FMT_ALIGNBYTE(j &= ~3);
-i = j;
-while (i > 0) {
-b[--i] ^= 0x80;
-i -= 3;
-}
-return j;
-}
-static struct pcm_feederdesc feeder_sign32le_desc[] = {
-{FEEDER_FMT, AFMT_U32_LE, AFMT_S32_LE, 0},
-{FEEDER_FMT, AFMT_U32_LE|AFMT_STEREO, AFMT_S32_LE|AFMT_STEREO, 0},
-{FEEDER_FMT, AFMT_S32_LE, AFMT_U32_LE, 0},
-{FEEDER_FMT, AFMT_S32_LE|AFMT_STEREO, AFMT_U32_LE|AFMT_STEREO, 0},
-{0, 0, 0, 0},
-};
-static kobj_method_t feeder_sign32le_methods[] = {
-KOBJMETHOD(feeder_feed, feed_sign32le),
-{0, 0}
+static struct pcm_feederdesc feeder_sign16_desc[] = {
+ {FEEDER_FMT, AFMT_U16_LE, AFMT_S16_LE, 0},
+ {FEEDER_FMT, AFMT_U16_LE | AFMT_STEREO, AFMT_S16_LE | AFMT_STEREO, 0},
+ {FEEDER_FMT, AFMT_S16_LE, AFMT_U16_LE, 0},
+ {FEEDER_FMT, AFMT_S16_LE | AFMT_STEREO, AFMT_U16_LE | AFMT_STEREO, 0},
+ {FEEDER_FMT, AFMT_U16_BE, AFMT_S16_BE, 0},
+ {FEEDER_FMT, AFMT_U16_BE | AFMT_STEREO, AFMT_S16_BE | AFMT_STEREO, 0},
+ {FEEDER_FMT, AFMT_S16_BE, AFMT_U16_BE, 0},
+ {FEEDER_FMT, AFMT_S16_BE | AFMT_STEREO, AFMT_U16_BE | AFMT_STEREO, 0},
+ {0, 0, 0, 0},
+};
+static kobj_method_t feeder_sign16_methods[] = {
+ KOBJMETHOD(feeder_feed, feed_sign),
+ {0, 0}
+};
+FEEDER_DECLARE(feeder_sign16, 0, (void *)PCM_16_BPS);
+
+static struct pcm_feederdesc feeder_sign24_desc[] = {
+ {FEEDER_FMT, AFMT_U24_LE, AFMT_S24_LE, 0},
+ {FEEDER_FMT, AFMT_U24_LE | AFMT_STEREO, AFMT_S24_LE | AFMT_STEREO, 0},
+ {FEEDER_FMT, AFMT_S24_LE, AFMT_U24_LE, 0},
+ {FEEDER_FMT, AFMT_S24_LE | AFMT_STEREO, AFMT_U24_LE | AFMT_STEREO, 0},
+ {FEEDER_FMT, AFMT_U24_BE, AFMT_S24_BE, 0},
+ {FEEDER_FMT, AFMT_U24_BE | AFMT_STEREO, AFMT_S24_BE | AFMT_STEREO, 0},
+ {FEEDER_FMT, AFMT_S24_BE, AFMT_U24_BE, 0},
+ {FEEDER_FMT, AFMT_S24_BE | AFMT_STEREO, AFMT_U24_BE | AFMT_STEREO, 0},
+ {0, 0, 0, 0},
+};
+static kobj_method_t feeder_sign24_methods[] = {
+ KOBJMETHOD(feeder_feed, feed_sign),
+ {0, 0}
+};
+FEEDER_DECLARE(feeder_sign24, 0, (void *)PCM_24_BPS);
+
+static struct pcm_feederdesc feeder_sign32_desc[] = {
+ {FEEDER_FMT, AFMT_U32_LE, AFMT_S32_LE, 0},
+ {FEEDER_FMT, AFMT_U32_LE | AFMT_STEREO, AFMT_S32_LE | AFMT_STEREO, 0},
+ {FEEDER_FMT, AFMT_S32_LE, AFMT_U32_LE, 0},
+ {FEEDER_FMT, AFMT_S32_LE | AFMT_STEREO, AFMT_U32_LE | AFMT_STEREO, 0},
+ {FEEDER_FMT, AFMT_U32_BE, AFMT_S32_BE, 0},
+ {FEEDER_FMT, AFMT_U32_BE | AFMT_STEREO, AFMT_S32_BE | AFMT_STEREO, 0},
+ {FEEDER_FMT, AFMT_S32_BE, AFMT_U32_BE, 0},
+ {FEEDER_FMT, AFMT_S32_BE | AFMT_STEREO, AFMT_U32_BE | AFMT_STEREO, 0},
+ {0, 0, 0, 0},
+};
+static kobj_method_t feeder_sign32_methods[] = {
+ KOBJMETHOD(feeder_feed, feed_sign),
+ {0, 0}
};
-FEEDER_DECLARE(feeder_sign32le, 0, NULL);
-/*
-* Sign conversion end.
-*/
+FEEDER_DECLARE(feeder_sign32, 0, (void *)PCM_32_BPS);
/*
-* Endian conversion.
-*/
+ * Endian conversion
+ */
static int
-feed_endian16(struct pcm_feeder *f, struct pcm_channel *c, uint8_t *b,
-uint32_t count, void *source)
+feed_endian(struct pcm_feeder *f, struct pcm_channel *c, uint8_t *b,
+ uint32_t count, void *source)
{
-int i, j = FEEDER_FEED(f->source, c, b, count, source);
-uint8_t v;
+ int i, j, k, bps;
+ uint8_t *buf, v;
-if (j < 2) {
-FMT_TRACE("%s: Not enough data (Got: %d bytes)n",
-__func__, j);
-return 0;
-}
-FMT_TEST(j & 1, "%s: Bytes not 16bit aligned.n", __func__);
-FMT_ALIGNBYTE(j &= ~1);
-i = j;
-while (i > 0) {
-v = b[--i];
-b[i] = b[i - 1];
-b[--i] = v;
-}
-return j;
+ bps = (int)((intptr_t)f->data);
+ if (count < bps)
+ return (0);
+
+ k = FEEDER_FEED(f->source, c, b, count - (count % bps), source);
+ if (k < bps)
+ return (0);
+
+ k -= k % bps;
+ j = bps >> 1;
+ buf = b + k;
+
+ do {
+ buf -= bps;
+ i = j;
+ do {
+ v = buf[--i];
+ buf[i] = buf[bps - i - 1];
+ buf[bps - i - 1] = v;
+ } while (i != 0);
+ } while (buf != b);
+
+ return (k);
}
static struct pcm_feederdesc feeder_endian16_desc[] = {
-{FEEDER_FMT, AFMT_U16_LE, AFMT_U16_BE, 0},
-{FEEDER_FMT, AFMT_U16_LE|AFMT_STEREO, AFMT_U16_BE|AFMT_STEREO, 0},
-{FEEDER_FMT, AFMT_S16_LE, AFMT_S16_BE, 0},
-{FEEDER_FMT, AFMT_S16_LE|AFMT_STEREO, AFMT_S16_BE|AFMT_STEREO, 0},
-{FEEDER_FMT, AFMT_U16_BE, AFMT_U16_LE, 0},
-{FEEDER_FMT, AFMT_U16_BE|AFMT_STEREO, AFMT_U16_LE|AFMT_STEREO, 0},
-{FEEDER_FMT, AFMT_S16_BE, AFMT_S16_LE, 0},
-{FEEDER_FMT, AFMT_S16_BE|AFMT_STEREO, AFMT_S16_LE|AFMT_STEREO, 0},
-{0, 0, 0, 0},
+ {FEEDER_FMT, AFMT_U16_LE, AFMT_U16_BE, 0},
+ {FEEDER_FMT, AFMT_U16_LE | AFMT_STEREO, AFMT_U16_BE | AFMT_STEREO, 0},
+ {FEEDER_FMT, AFMT_S16_LE, AFMT_S16_BE, 0},
+ {FEEDER_FMT, AFMT_S16_LE | AFMT_STEREO, AFMT_S16_BE | AFMT_STEREO, 0},
+ {FEEDER_FMT, AFMT_U16_BE, AFMT_U16_LE, 0},
+ {FEEDER_FMT, AFMT_U16_BE | AFMT_STEREO, AFMT_U16_LE | AFMT_STEREO, 0},
+ {FEEDER_FMT, AFMT_S16_BE, AFMT_S16_LE, 0},
+ {FEEDER_FMT, AFMT_S16_BE | AFMT_STEREO, AFMT_S16_LE | AFMT_STEREO, 0},
+ {0, 0, 0, 0},
};
static kobj_method_t feeder_endian16_methods[] = {
-KOBJMETHOD(feeder_feed, feed_endian16),
-{0, 0}
+ KOBJMETHOD(feeder_feed, feed_endian),
+ {0, 0}
};
-FEEDER_DECLARE(feeder_endian16, 0, NULL);
-
-static int
-feed_endian24(struct pcm_feeder *f, struct pcm_channel *c, uint8_t *b,
-uint32_t count, void *source)
-{
-int i, j = FEEDER_FEED(f->source, c, b, count, source);
-uint8_t v;
+FEEDER_DECLARE(feeder_endian16, 0, (void *)PCM_16_BPS);
-if (j < 3) {
-FMT_TRACE("%s: Not enough data (Got: %d bytes)n",
-__func__, j);
-return 0;
-}
-FMT_TEST(j % 3, "%s: Bytes not 24bit aligned.n", __func__);
-FMT_ALIGNBYTE(j -= j % 3);
-i = j;
-while (i > 0) {
-v = b[--i];
-b[i] = b[i - 2];
-b[i -= 2] = v;
-}
-return j;
-}
static struct pcm_feederdesc feeder_endian24_desc[] = {
-{FEEDER_FMT, AFMT_U24_LE, AFMT_U24_BE, 0},
-{FEEDER_FMT, AFMT_U24_LE|AFMT_STEREO, AFMT_U24_BE|AFMT_STEREO, 0},
-{FEEDER_FMT, AFMT_S24_LE, AFMT_S24_BE, 0},
-{FEEDER_FMT, AFMT_S24_LE|AFMT_STEREO, AFMT_S24_BE|AFMT_STEREO, 0},
-{FEEDER_FMT, AFMT_U24_BE, AFMT_U24_LE, 0},
-{FEEDER_FMT, AFMT_U24_BE|AFMT_STEREO, AFMT_U24_LE|AFMT_STEREO, 0},
-{FEEDER_FMT, AFMT_S24_BE, AFMT_S24_LE, 0},
-{FEEDER_FMT, AFMT_S24_BE|AFMT_STEREO, AFMT_S24_LE|AFMT_STEREO, 0},
-{0, 0, 0, 0},
+ {FEEDER_FMT, AFMT_U24_LE, AFMT_U24_BE, 0},
+ {FEEDER_FMT, AFMT_U24_LE | AFMT_STEREO, AFMT_U24_BE | AFMT_STEREO, 0},
+ {FEEDER_FMT, AFMT_S24_LE, AFMT_S24_BE, 0},
+ {FEEDER_FMT, AFMT_S24_LE | AFMT_STEREO, AFMT_S24_BE | AFMT_STEREO, 0},
+ {FEEDER_FMT, AFMT_U24_BE, AFMT_U24_LE, 0},
+ {FEEDER_FMT, AFMT_U24_BE | AFMT_STEREO, AFMT_U24_LE | AFMT_STEREO, 0},
+ {FEEDER_FMT, AFMT_S24_BE, AFMT_S24_LE, 0},
+ {FEEDER_FMT, AFMT_S24_BE | AFMT_STEREO, AFMT_S24_LE | AFMT_STEREO, 0},
+ {0, 0, 0, 0},
};
static kobj_method_t feeder_endian24_methods[] = {
-KOBJMETHOD(feeder_feed, feed_endian24),
-{0, 0}
+ KOBJMETHOD(feeder_feed, feed_endian),
+ {0, 0}
};
-FEEDER_DECLARE(feeder_endian24, 0, NULL);
-
-static int
-feed_endian32(struct pcm_feeder *f, struct pcm_channel *c, uint8_t *b,
-uint32_t count, void *source)
-{
-int i, j = FEEDER_FEED(f->source, c, b, count, source);
-uint8_t l, m;
+FEEDER_DECLARE(feeder_endian24, 0, (void *)PCM_24_BPS);
-if (j < 4) {
-FMT_TRACE("%s: Not enough data (Got: %d bytes)n",
-__func__, j);
-return 0;
-}
-FMT_TEST(j & 3, "%s: Bytes not 32bit aligned.n", __func__);
-FMT_ALIGNBYTE(j &= ~3);
-i = j;
-while (i > 0) {
-l = b[--i];
-m = b[--i];
-b[i] = b[i - 1];
-b[i + 1] = b[i - 2];
-b[--i] = m;
-b[--i] = l;
-}
-return j;
-}
static struct pcm_feederdesc feeder_endian32_desc[] = {
-{FEEDER_FMT, AFMT_U32_LE, AFMT_U32_BE, 0},
-{FEEDER_FMT, AFMT_U32_LE|AFMT_STEREO, AFMT_U32_BE|AFMT_STEREO, 0},
-{FEEDER_FMT, AFMT_S32_LE, AFMT_S32_BE, 0},
-{FEEDER_FMT, AFMT_S32_LE|AFMT_STEREO, AFMT_S32_BE|AFMT_STEREO, 0},
-{FEEDER_FMT, AFMT_U32_BE, AFMT_U32_LE, 0},
-{FEEDER_FMT, AFMT_U32_BE|AFMT_STEREO, AFMT_U32_LE|AFMT_STEREO, 0},
-{FEEDER_FMT, AFMT_S32_BE, AFMT_S32_LE, 0},
-{FEEDER_FMT, AFMT_S32_BE|AFMT_STEREO, AFMT_S32_LE|AFMT_STEREO, 0},
-{0, 0, 0, 0},
+ {FEEDER_FMT, AFMT_U32_LE, AFMT_U32_BE, 0},
+ {FEEDER_FMT, AFMT_U32_LE | AFMT_STEREO, AFMT_U32_BE | AFMT_STEREO, 0},
+ {FEEDER_FMT, AFMT_S32_LE, AFMT_S32_BE, 0},
+ {FEEDER_FMT, AFMT_S32_LE | AFMT_STEREO, AFMT_S32_BE | AFMT_STEREO, 0},
+ {FEEDER_FMT, AFMT_U32_BE, AFMT_U32_LE, 0},
+ {FEEDER_FMT, AFMT_U32_BE | AFMT_STEREO, AFMT_U32_LE | AFMT_STEREO, 0},
+ {FEEDER_FMT, AFMT_S32_BE, AFMT_S32_LE, 0},
+ {FEEDER_FMT, AFMT_S32_BE | AFMT_STEREO, AFMT_S32_LE | AFMT_STEREO, 0},
+ {0, 0, 0, 0},
};
static kobj_method_t feeder_endian32_methods[] = {
-KOBJMETHOD(feeder_feed, feed_endian32),
-{0, 0}
+ KOBJMETHOD(feeder_feed, feed_endian),
+ {0, 0}
+};
+FEEDER_DECLARE(feeder_endian32, 0, (void *)PCM_32_BPS);
+/*
+ * Endian conversion end
+ */
+
+/*
+ * L/R swap conversion
+ */
+static int
+feed_swaplr(struct pcm_feeder *f, struct pcm_channel *c, uint8_t *b,
+ uint32_t count, void *source)
+{
+ int i, j, bps, smpsz;
+ uint8_t *buf, v;
+
+ bps = (int)((intptr_t)f->data);
+ smpsz = bps << 1;
+ if (count < smpsz)
+ return (0);
+
+ j = FEEDER_FEED(f->source, c, b, count - (count % smpsz), source);
+ if (j < smpsz)
+ return (0);
+
+ j -= j % smpsz;
+ buf = b + j;
+
+ do {
+ buf -= smpsz;
+ i = bps;
+ do {
+ v = buf[--i];
+ buf[i] = buf[bps + i];
+ buf[bps + i] = v;
+ } while (i != 0);
+ } while (buf != b);
+
+ return (j);
+}
+
+static struct pcm_feederdesc feeder_swaplr8_desc[] = {
+ {FEEDER_SWAPLR, AFMT_S8 | AFMT_STEREO, AFMT_S8 | AFMT_STEREO, 0},
+ {FEEDER_SWAPLR, AFMT_U8 | AFMT_STEREO, AFMT_U8 | AFMT_STEREO, 0},
+ {FEEDER_SWAPLR, AFMT_A_LAW | AFMT_STEREO, AFMT_A_LAW | AFMT_STEREO, 0},
+ {FEEDER_SWAPLR, AFMT_MU_LAW | AFMT_STEREO, AFMT_A_LAW | AFMT_STEREO, 0},
+ {0, 0, 0, 0},
+};
+static kobj_method_t feeder_swaplr8_methods[] = {
+ KOBJMETHOD(feeder_feed, feed_swaplr),
+ {0, 0}
+};
+FEEDER_DECLARE(feeder_swaplr8, -1, (void *)PCM_8_BPS);
+
+static struct pcm_feederdesc feeder_swaplr16_desc[] = {
+ {FEEDER_SWAPLR, AFMT_S16_LE | AFMT_STEREO, AFMT_S16_LE | AFMT_STEREO, 0},
+ {FEEDER_SWAPLR, AFMT_S16_BE | AFMT_STEREO, AFMT_S16_BE | AFMT_STEREO, 0},
+ {FEEDER_SWAPLR, AFMT_U16_LE | AFMT_STEREO, AFMT_U16_LE | AFMT_STEREO, 0},
+ {FEEDER_SWAPLR, AFMT_U16_BE | AFMT_STEREO, AFMT_U16_BE | AFMT_STEREO, 0},
+ {0, 0, 0, 0},
+};
+static kobj_method_t feeder_swaplr16_methods[] = {
+ KOBJMETHOD(feeder_feed, feed_swaplr),
+ {0, 0}
+};
+FEEDER_DECLARE(feeder_swaplr16, -1, (void *)PCM_16_BPS);
+
+static struct pcm_feederdesc feeder_swaplr24_desc[] = {
+ {FEEDER_SWAPLR, AFMT_S24_LE | AFMT_STEREO, AFMT_S24_LE | AFMT_STEREO, 0},
+ {FEEDER_SWAPLR, AFMT_S24_BE | AFMT_STEREO, AFMT_S24_BE | AFMT_STEREO, 0},
+ {FEEDER_SWAPLR, AFMT_U24_LE | AFMT_STEREO, AFMT_U24_LE | AFMT_STEREO, 0},
+ {FEEDER_SWAPLR, AFMT_U24_BE | AFMT_STEREO, AFMT_U24_BE | AFMT_STEREO, 0},
+ {0, 0, 0, 0},
+};
+static kobj_method_t feeder_swaplr24_methods[] = {
+ KOBJMETHOD(feeder_feed, feed_swaplr),
+ {0, 0}
+};
+FEEDER_DECLARE(feeder_swaplr24, -1, (void *)PCM_24_BPS);
+
+static struct pcm_feederdesc feeder_swaplr32_desc[] = {
+ {FEEDER_SWAPLR, AFMT_S32_LE | AFMT_STEREO, AFMT_S32_LE | AFMT_STEREO, 0},
+ {FEEDER_SWAPLR, AFMT_S32_BE | AFMT_STEREO, AFMT_S32_BE | AFMT_STEREO, 0},
+ {FEEDER_SWAPLR, AFMT_U32_LE | AFMT_STEREO, AFMT_U32_LE | AFMT_STEREO, 0},
+ {FEEDER_SWAPLR, AFMT_U32_BE | AFMT_STEREO, AFMT_U32_BE | AFMT_STEREO, 0},
+ {0, 0, 0, 0},
+};
+static kobj_method_t feeder_swaplr32_methods[] = {
+ KOBJMETHOD(feeder_feed, feed_swaplr),
+ {0, 0}
};
-FEEDER_DECLARE(feeder_endian32, 0, NULL);
+FEEDER_DECLARE(feeder_swaplr32, -1, (void *)PCM_32_BPS);
/*
-* Endian conversion end
-*/
+ * L/R swap conversion end
+ */
Index: ac97_if.m
===================================================================
RCS file: /home/cvs/src/sys/dev/sound/pcm/ac97_if.m,v
retrieving revision 1.2
retrieving revision 1.3
diff -L sys/dev/sound/pcm/ac97_if.m -L sys/dev/sound/pcm/ac97_if.m -u -r1.2 -r1.3
--- sys/dev/sound/pcm/ac97_if.m
+++ sys/dev/sound/pcm/ac97_if.m
@@ -25,7 +25,6 @@
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
# SUCH DAMAGE.
#
-# $MidnightBSD$
# $FreeBSD: src/sys/dev/sound/pcm/ac97_if.m,v 1.4 2005/01/06 01:43:20 imp Exp $
#
@@ -35,7 +34,8 @@
CODE {
- static u_int32_t ac97_noinit(kobj_t obj, void *devinfo)
+ static u_int32_t
+ ac97_noinit(kobj_t obj, void *devinfo)
{
return 1;
}
@@ -43,19 +43,19 @@
};
METHOD u_int32_t init {
-kobj_t obj;
-void *devinfo;
+ kobj_t obj;
+ void *devinfo;
} DEFAULT ac97_noinit;
METHOD int read {
-kobj_t obj;
-void *devinfo;
-int regno;
+ kobj_t obj;
+ void *devinfo;
+ int regno;
};
METHOD int write {
-kobj_t obj;
-void *devinfo;
-int regno;
-u_int32_t data;
+ kobj_t obj;
+ void *devinfo;
+ int regno;
+ u_int32_t data;
};
Index: dsp.c
===================================================================
RCS file: /home/cvs/src/sys/dev/sound/pcm/dsp.c,v
retrieving revision 1.3
retrieving revision 1.4
diff -L sys/dev/sound/pcm/dsp.c -L sys/dev/sound/pcm/dsp.c -u -r1.3 -r1.4
--- sys/dev/sound/pcm/dsp.c
+++ sys/dev/sound/pcm/dsp.c
@@ -1,35 +1,52 @@
/*-
-* Copyright (c) 1999 Cameron Grant <cg at freebsd.org>
-* All rights reserved.
-*
-* Redistribution and use in source and binary forms, with or without
-* modification, are permitted provided that the following conditions
-* are met:
-* 1. Redistributions of source code must retain the above copyright
-* notice, this list of conditions and the following disclaimer.
-* 2. Redistributions in binary form must reproduce the above copyright
-* notice, this list of conditions and the following disclaimer in the
-* documentation and/or other materials provided with the distribution.
-*
-* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
-* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
-* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
-* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
-* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
-* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
-* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
-* SUCH DAMAGE.
-*/
-
-#include <sys/param.h>
-#include <sys/queue.h>
+ * Copyright (c) 1999 Cameron Grant <cg at freebsd.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
#include <dev/sound/pcm/sound.h>
+#include <sys/ctype.h>
+
+SND_DECLARE_FILE("$FreeBSD: src/sys/dev/sound/pcm/dsp.c,v 1.107 2007/07/04 12:33:11 ariff Exp $");
+
+static int dsp_mmap_allow_prot_exec = 0;
+SYSCTL_INT(_hw_snd, OID_AUTO, compat_linux_mmap, CTLFLAG_RW,
+ &dsp_mmap_allow_prot_exec, 0, "linux mmap compatibility");
+
+struct dsp_cdevinfo {
+ struct pcm_channel *rdch, *wrch;
+ int busy, simplex;
+ TAILQ_ENTRY(dsp_cdevinfo) link;
+};
+
+#define PCM_RDCH(x) (((struct dsp_cdevinfo *)(x)->si_drv1)->rdch)
+#define PCM_WRCH(x) (((struct dsp_cdevinfo *)(x)->si_drv1)->wrch)
+#define PCM_SIMPLEX(x) (((struct dsp_cdevinfo *)(x)->si_drv1)->simplex)
-SND_DECLARE_FILE("$MidnightBSD$");
+#define DSP_CDEVINFO_CACHESIZE 8
+
+#define DSP_REGISTERED(x, y) (PCM_REGISTERED(x) && \
+ (y) != NULL && (y)->si_drv1 != NULL)
#define OLDPCM_IOCTL
@@ -42,1167 +59,2856 @@
static d_mmap_t dsp_mmap;
struct cdevsw dsp_cdevsw = {
-.d_version = D_VERSION,
-.d_flags = D_NEEDGIANT,
-.d_open = dsp_open,
-.d_close = dsp_close,
-.d_read = dsp_read,
-.d_write = dsp_write,
-.d_ioctl = dsp_ioctl,
-.d_poll = dsp_poll,
-.d_mmap = dsp_mmap,
-.d_name = "dsp",
+ .d_version = D_VERSION,
+ .d_open = dsp_open,
+ .d_close = dsp_close,
+ .d_read = dsp_read,
+ .d_write = dsp_write,
+ .d_ioctl = dsp_ioctl,
+ .d_poll = dsp_poll,
+ .d_mmap = dsp_mmap,
+ .d_name = "dsp",
};
#ifdef USING_DEVFS
-static eventhandler_tag dsp_ehtag;
+static eventhandler_tag dsp_ehtag = NULL;
+static int dsp_umax = -1;
+static int dsp_cmax = -1;
+#endif
+
+static int dsp_oss_syncgroup(struct pcm_channel *wrch, struct pcm_channel *rdch, oss_syncgroup *group);
+static int dsp_oss_syncstart(int sg_id);
+static int dsp_oss_policy(struct pcm_channel *wrch, struct pcm_channel *rdch, int policy);
+#ifdef OSSV4_EXPERIMENT
+static int dsp_oss_cookedmode(struct pcm_channel *wrch, struct pcm_channel *rdch, int enabled);
+static int dsp_oss_getchnorder(struct pcm_channel *wrch, struct pcm_channel *rdch, unsigned long long *map);
+static int dsp_oss_setchnorder(struct pcm_channel *wrch, struct pcm_channel *rdch, unsigned long long *map);
+static int dsp_oss_getlabel(struct pcm_channel *wrch, struct pcm_channel *rdch, oss_label_t *label);
+static int dsp_oss_setlabel(struct pcm_channel *wrch, struct pcm_channel *rdch, oss_label_t *label);
+static int dsp_oss_getsong(struct pcm_channel *wrch, struct pcm_channel *rdch, oss_longname_t *song);
+static int dsp_oss_setsong(struct pcm_channel *wrch, struct pcm_channel *rdch, oss_longname_t *song);
+static int dsp_oss_setname(struct pcm_channel *wrch, struct pcm_channel *rdch, oss_longname_t *name);
#endif
static struct snddev_info *
dsp_get_info(struct cdev *dev)
{
-struct snddev_info *d;
-int unit;
-
-unit = PCMUNIT(dev);
-if (unit >= devclass_get_maxunit(pcm_devclass))
-return NULL;
-d = devclass_get_softc(pcm_devclass, unit);
-
-return d;
+ return (devclass_get_softc(pcm_devclass, PCMUNIT(dev)));
}
-static u_int32_t
+static uint32_t
dsp_get_flags(struct cdev *dev)
{
-device_t bdev;
-int unit;
+ device_t bdev;
-unit = PCMUNIT(dev);
-if (unit >= devclass_get_maxunit(pcm_devclass))
-return 0xffffffff;
-bdev = devclass_get_device(pcm_devclass, unit);
+ bdev = devclass_get_device(pcm_devclass, PCMUNIT(dev));
-return pcm_getflags(bdev);
+ return ((bdev != NULL) ? pcm_getflags(bdev) : 0xffffffff);
}
static void
-dsp_set_flags(struct cdev *dev, u_int32_t flags)
+dsp_set_flags(struct cdev *dev, uint32_t flags)
{
-device_t bdev;
-int unit;
+ device_t bdev;
-unit = PCMUNIT(dev);
-if (unit >= devclass_get_maxunit(pcm_devclass))
-return;
-bdev = devclass_get_device(pcm_devclass, unit);
+ bdev = devclass_get_device(pcm_devclass, PCMUNIT(dev));
-pcm_setflags(bdev, flags);
+ if (bdev != NULL)
+ pcm_setflags(bdev, flags);
}
/*
-* return the channels associated with an open device instance.
-* set the priority if the device is simplex and one direction (only) is
-* specified.
-* lock channels specified.
-*/
+ * return the channels associated with an open device instance.
+ * lock channels specified.
+ */
static int
-getchns(struct cdev *dev, struct pcm_channel **rdch, struct pcm_channel **wrch, u_int32_t prio)
+getchns(struct cdev *dev, struct pcm_channel **rdch, struct pcm_channel **wrch,
+ uint32_t prio)
{
-struct snddev_info *d;
-u_int32_t flags;
-
-flags = dsp_get_flags(dev);
-d = dsp_get_info(dev);
-pcm_inprog(d, 1);
-pcm_lock(d);
-KASSERT((flags & SD_F_PRIO_SET) != SD_F_PRIO_SET, ("getchns: read and write both prioritised"));
+ struct snddev_info *d;
+ struct pcm_channel *ch;
+ uint32_t flags;
+
+ if (PCM_SIMPLEX(dev) != 0) {
+ d = dsp_get_info(dev);
+ if (!PCM_REGISTERED(d))
+ return (ENXIO);
+ pcm_lock(d);
+ PCM_WAIT(d);
+ PCM_ACQUIRE(d);
+ /*
+ * Note: order is important -
+ * pcm flags -> prio query flags -> wild guess
+ */
+ ch = NULL;
+ flags = dsp_get_flags(dev);
+ if (flags & SD_F_PRIO_WR) {
+ ch = PCM_RDCH(dev);
+ PCM_RDCH(dev) = NULL;
+ } else if (flags & SD_F_PRIO_RD) {
+ ch = PCM_WRCH(dev);
+ PCM_WRCH(dev) = NULL;
+ } else if (prio & SD_F_PRIO_WR) {
+ ch = PCM_RDCH(dev);
+ PCM_RDCH(dev) = NULL;
+ flags |= SD_F_PRIO_WR;
+ } else if (prio & SD_F_PRIO_RD) {
+ ch = PCM_WRCH(dev);
+ PCM_WRCH(dev) = NULL;
+ flags |= SD_F_PRIO_RD;
+ } else if (PCM_WRCH(dev) != NULL) {
+ ch = PCM_RDCH(dev);
+ PCM_RDCH(dev) = NULL;
+ flags |= SD_F_PRIO_WR;
+ } else if (PCM_RDCH(dev) != NULL) {
+ ch = PCM_WRCH(dev);
+ PCM_WRCH(dev) = NULL;
+ flags |= SD_F_PRIO_RD;
+ }
+ PCM_SIMPLEX(dev) = 0;
+ dsp_set_flags(dev, flags);
+ if (ch != NULL) {
+ CHN_LOCK(ch);
+ pcm_chnref(ch, -1);
+ pcm_chnrelease(ch);
+ }
+ PCM_RELEASE(d);
+ pcm_unlock(d);
+ }
+
+ *rdch = PCM_RDCH(dev);
+ *wrch = PCM_WRCH(dev);
+
+ if (*rdch != NULL && (prio & SD_F_PRIO_RD))
+ CHN_LOCK(*rdch);
+ if (*wrch != NULL && (prio & SD_F_PRIO_WR))
+ CHN_LOCK(*wrch);
-if ((flags & SD_F_PRIO_SET) == 0 && (prio != (SD_F_PRIO_RD | SD_F_PRIO_WR))) {
-flags |= prio & (SD_F_PRIO_RD | SD_F_PRIO_WR);
-dsp_set_flags(dev, flags);
-}
-
-*rdch = dev->si_drv1;
-*wrch = dev->si_drv2;
-if ((flags & SD_F_SIMPLEX) && (flags & SD_F_PRIO_SET)) {
-if (prio) {
-if (*rdch && flags & SD_F_PRIO_WR) {
-dev->si_drv1 = NULL;
-*rdch = pcm_getfakechan(d);
-} else if (*wrch && flags & SD_F_PRIO_RD) {
-dev->si_drv2 = NULL;
-*wrch = pcm_getfakechan(d);
-}
+ return (0);
}
-pcm_getfakechan(d)->flags |= CHN_F_BUSY;
+/* unlock specified channels */
+static void
+relchns(struct cdev *dev, struct pcm_channel *rdch, struct pcm_channel *wrch,
+ uint32_t prio)
+{
+ if (wrch != NULL && (prio & SD_F_PRIO_WR))
+ CHN_UNLOCK(wrch);
+ if (rdch != NULL && (prio & SD_F_PRIO_RD))
+ CHN_UNLOCK(rdch);
}
-pcm_unlock(d);
-if (*rdch && *rdch != pcm_getfakechan(d) && (prio & SD_F_PRIO_RD))
-CHN_LOCK(*rdch);
-if (*wrch && *wrch != pcm_getfakechan(d) && (prio & SD_F_PRIO_WR))
-CHN_LOCK(*wrch);
-
-return 0;
+static void
+dsp_cdevinfo_alloc(struct cdev *dev,
+ struct pcm_channel *rdch, struct pcm_channel *wrch)
+{
+ struct snddev_info *d;
+ struct dsp_cdevinfo *cdi;
+ int simplex;
+
+ d = dsp_get_info(dev);
+
+ KASSERT(PCM_REGISTERED(d) && dev != NULL && dev->si_drv1 == NULL &&
+ rdch != wrch,
+ ("bogus %s(), what are you trying to accomplish here?", __func__));
+ PCM_BUSYASSERT(d);
+ mtx_assert(d->lock, MA_OWNED);
+
+ simplex = (dsp_get_flags(dev) & SD_F_SIMPLEX) ? 1 : 0;
+
+ /*
+ * Scan for free instance entry and put it into the end of list.
+ * Create new one if necessary.
+ */
+ TAILQ_FOREACH(cdi, &d->dsp_cdevinfo_pool, link) {
+ if (cdi->busy != 0)
+ break;
+ cdi->rdch = rdch;
+ cdi->wrch = wrch;
+ cdi->simplex = simplex;
+ cdi->busy = 1;
+ TAILQ_REMOVE(&d->dsp_cdevinfo_pool, cdi, link);
+ TAILQ_INSERT_TAIL(&d->dsp_cdevinfo_pool, cdi, link);
+ dev->si_drv1 = cdi;
+ return;
+ }
+ pcm_unlock(d);
+ cdi = malloc(sizeof(*cdi), M_DEVBUF, M_WAITOK | M_ZERO);
+ pcm_lock(d);
+ cdi->rdch = rdch;
+ cdi->wrch = wrch;
+ cdi->simplex = simplex;
+ cdi->busy = 1;
+ TAILQ_INSERT_TAIL(&d->dsp_cdevinfo_pool, cdi, link);
+ dev->si_drv1 = cdi;
}
-/* unlock specified channels */
static void
-relchns(struct cdev *dev, struct pcm_channel *rdch, struct pcm_channel *wrch, u_int32_t prio)
+dsp_cdevinfo_free(struct cdev *dev)
{
-struct snddev_info *d;
+ struct snddev_info *d;
+ struct dsp_cdevinfo *cdi, *tmp;
+ uint32_t flags;
+ int i;
+
+ d = dsp_get_info(dev);
+
+ KASSERT(PCM_REGISTERED(d) && dev != NULL && dev->si_drv1 != NULL &&
+ PCM_RDCH(dev) == NULL && PCM_WRCH(dev) == NULL,
+ ("bogus %s(), what are you trying to accomplish here?", __func__));
+ PCM_BUSYASSERT(d);
+ mtx_assert(d->lock, MA_OWNED);
+
+ cdi = dev->si_drv1;
+ dev->si_drv1 = NULL;
+ cdi->rdch = NULL;
+ cdi->wrch = NULL;
+ cdi->simplex = 0;
+ cdi->busy = 0;
+
+ /*
+ * Once it is free, move it back to the beginning of list for
+ * faster new entry allocation.
+ */
+ TAILQ_REMOVE(&d->dsp_cdevinfo_pool, cdi, link);
+ TAILQ_INSERT_HEAD(&d->dsp_cdevinfo_pool, cdi, link);
+
+ /*
+ * Scan the list, cache free entries up to DSP_CDEVINFO_CACHESIZE.
+ * Reset simplex flags.
+ */
+ flags = dsp_get_flags(dev) & ~SD_F_PRIO_SET;
+ i = DSP_CDEVINFO_CACHESIZE;
+ TAILQ_FOREACH_SAFE(cdi, &d->dsp_cdevinfo_pool, link, tmp) {
+ if (cdi->busy != 0) {
+ if (cdi->simplex == 0) {
+ if (cdi->rdch != NULL)
+ flags |= SD_F_PRIO_RD;
+ if (cdi->wrch != NULL)
+ flags |= SD_F_PRIO_WR;
+ }
+ } else {
+ if (i == 0) {
+ TAILQ_REMOVE(&d->dsp_cdevinfo_pool, cdi, link);
+ free(cdi, M_DEVBUF);
+ } else
+ i--;
+ }
+ }
+ dsp_set_flags(dev, flags);
+}
+
+void
+dsp_cdevinfo_init(struct snddev_info *d)
+{
+ struct dsp_cdevinfo *cdi;
+ int i;
+
+ KASSERT(d != NULL, ("NULL snddev_info"));
+ PCM_BUSYASSERT(d);
+ mtx_assert(d->lock, MA_NOTOWNED);
+
+ TAILQ_INIT(&d->dsp_cdevinfo_pool);
+ for (i = 0; i < DSP_CDEVINFO_CACHESIZE; i++) {
+ cdi = malloc(sizeof(*cdi), M_DEVBUF, M_WAITOK | M_ZERO);
+ TAILQ_INSERT_HEAD(&d->dsp_cdevinfo_pool, cdi, link);
+ }
+}
+
+void
+dsp_cdevinfo_flush(struct snddev_info *d)
+{
+ struct dsp_cdevinfo *cdi, *tmp;
+
+ KASSERT(d != NULL, ("NULL snddev_info"));
+ PCM_BUSYASSERT(d);
+ mtx_assert(d->lock, MA_NOTOWNED);
+
+ cdi = TAILQ_FIRST(&d->dsp_cdevinfo_pool);
+ while (cdi != NULL) {
+ tmp = TAILQ_NEXT(cdi, link);
+ free(cdi, M_DEVBUF);
+ cdi = tmp;
+ }
+ TAILQ_INIT(&d->dsp_cdevinfo_pool);
+}
+
+/* duplex / simplex cdev type */
+enum {
+ DSP_CDEV_TYPE_RDONLY, /* simplex read-only (record) */
+ DSP_CDEV_TYPE_WRONLY, /* simplex write-only (play) */
+ DSP_CDEV_TYPE_RDWR, /* duplex read, write, or both */
+};
-d = dsp_get_info(dev);
-if (wrch && wrch != pcm_getfakechan(d) && (prio & SD_F_PRIO_WR))
-CHN_UNLOCK(wrch);
-if (rdch && rdch != pcm_getfakechan(d) && (prio & SD_F_PRIO_RD))
-CHN_UNLOCK(rdch);
-pcm_inprog(d, -1);
-}
+#define DSP_F_VALID(x) ((x) & (FREAD | FWRITE))
+#define DSP_F_DUPLEX(x) (((x) & (FREAD | FWRITE)) == (FREAD | FWRITE))
+#define DSP_F_SIMPLEX(x) (!DSP_F_DUPLEX(x))
+#define DSP_F_READ(x) ((x) & FREAD)
+#define DSP_F_WRITE(x) ((x) & FWRITE)
+
+static const struct {
+ int type;
+ char *name;
+ char *sep;
+ int use_sep;
+ int hw;
+ int max;
+ uint32_t fmt, spd;
+ int query;
+} dsp_cdevs[] = {
+ { SND_DEV_DSP, "dsp", ".", 0, 0, 0,
+ AFMT_U8, DSP_DEFAULT_SPEED, DSP_CDEV_TYPE_RDWR },
+ { SND_DEV_AUDIO, "audio", ".", 0, 0, 0,
+ AFMT_MU_LAW, DSP_DEFAULT_SPEED, DSP_CDEV_TYPE_RDWR },
+ { SND_DEV_DSP16, "dspW", ".", 0, 0, 0,
+ AFMT_S16_LE, DSP_DEFAULT_SPEED, DSP_CDEV_TYPE_RDWR },
+ { SND_DEV_DSPHW_PLAY, "dsp", ".p", 1, 1, SND_MAXHWCHAN,
+ AFMT_S16_LE | AFMT_STEREO, 48000, DSP_CDEV_TYPE_WRONLY },
+ { SND_DEV_DSPHW_VPLAY, "dsp", ".vp", 1, 1, SND_MAXVCHANS,
+ AFMT_S16_LE | AFMT_STEREO, 48000, DSP_CDEV_TYPE_WRONLY },
+ { SND_DEV_DSPHW_REC, "dsp", ".r", 1, 1, SND_MAXHWCHAN,
+ AFMT_S16_LE | AFMT_STEREO, 48000, DSP_CDEV_TYPE_RDONLY },
+ { SND_DEV_DSPHW_VREC, "dsp", ".vr", 1, 1, SND_MAXVCHANS,
+ AFMT_S16_LE | AFMT_STEREO, 48000, DSP_CDEV_TYPE_RDONLY },
+ { SND_DEV_DSPHW_CD, "dspcd", ".", 0, 0, 0,
+ AFMT_S16_LE | AFMT_STEREO, 44100, DSP_CDEV_TYPE_RDWR },
+ { SND_DEV_DSP_MMAP, "dsp_mmap", ".", 0, 0, 0,
+ AFMT_S16_LE | AFMT_STEREO, 48000, DSP_CDEV_TYPE_RDWR },
+};
+
+#define DSP_FIXUP_ERROR() do { \
+ prio = dsp_get_flags(i_dev); \
+ if (!DSP_F_VALID(flags)) \
+ error = EINVAL; \
+ if (!DSP_F_DUPLEX(flags) && \
+ ((DSP_F_READ(flags) && d->reccount == 0) || \
+ (DSP_F_WRITE(flags) && d->playcount == 0))) \
+ error = ENOTSUP; \
+ else if (!DSP_F_DUPLEX(flags) && (prio & SD_F_SIMPLEX) && \
+ ((DSP_F_READ(flags) && (prio & SD_F_PRIO_WR)) || \
+ (DSP_F_WRITE(flags) && (prio & SD_F_PRIO_RD)))) \
+ error = EBUSY; \
+ else if (DSP_REGISTERED(d, i_dev)) \
+ error = EBUSY; \
+} while(0)
static int
dsp_open(struct cdev *i_dev, int flags, int mode, struct thread *td)
{
-struct pcm_channel *rdch, *wrch;
-struct snddev_info *d;
-u_int32_t fmt;
-int devtype;
-int error;
-int chnum;
-
-if (i_dev == NULL || td == NULL)
-return ENODEV;
-
-if ((flags & (FREAD | FWRITE)) == 0)
-return EINVAL;
-
-d = dsp_get_info(i_dev);
-devtype = PCMDEV(i_dev);
-chnum = -1;
-
-/* decide default format */
-switch (devtype) {
-case SND_DEV_DSP16:
-fmt = AFMT_S16_LE;
-break;
-
-case SND_DEV_DSP:
-fmt = AFMT_U8;
-break;
-
-case SND_DEV_AUDIO:
-fmt = AFMT_MU_LAW;
-break;
-
-case SND_DEV_NORESET:
-fmt = 0;
-break;
-
-case SND_DEV_DSPREC:
-fmt = AFMT_U8;
-if (flags & FWRITE)
-return EINVAL;
-chnum = PCMCHAN(i_dev);
-break;
-
-default:
-panic("impossible devtype %d", devtype);
-}
-
-/* lock snddev so nobody else can monkey with it */
-pcm_lock(d);
-
-rdch = i_dev->si_drv1;
-wrch = i_dev->si_drv2;
-
-if (rdch || wrch || ((dsp_get_flags(i_dev) & SD_F_SIMPLEX) &&
-(flags & (FREAD | FWRITE)) == (FREAD | FWRITE))) {
-/* simplex or not, better safe than sorry. */
-pcm_unlock(d);
-return EBUSY;
-}
-
-/*
-* if we get here, the open request is valid- either:
-* * we were previously not open
-* * we were open for play xor record and the opener wants
-* the non-open direction
-*/
-if (flags & FREAD) {
-/* open for read */
-pcm_unlock(d);
-error = pcm_chnalloc(d, &rdch, PCMDIR_REC, td->td_proc->p_pid, chnum);
-if (error != 0 && error != EBUSY && chnum != -1 && (flags & FWRITE))
-error = pcm_chnalloc(d, &rdch, PCMDIR_REC, td->td_proc->p_pid, -1);
-
-if (error == 0 && (chn_reset(rdch, fmt) ||
-(fmt && chn_setspeed(rdch, DSP_DEFAULT_SPEED))))
-error = ENODEV;
-
-if (error != 0) {
-if (rdch)
-pcm_chnrelease(rdch);
-return error;
-}
-
-if (flags & O_NONBLOCK)
-rdch->flags |= CHN_F_NBIO;
-pcm_chnref(rdch, 1);
-CHN_UNLOCK(rdch);
-pcm_lock(d);
-}
-
-if (flags & FWRITE) {
-/* open for write */
-pcm_unlock(d);
-error = pcm_chnalloc(d, &wrch, PCMDIR_PLAY, td->td_proc->p_pid, chnum);
-if (error != 0 && error != EBUSY && chnum != -1 && (flags & FREAD))
-error = pcm_chnalloc(d, &wrch, PCMDIR_PLAY, td->td_proc->p_pid, -1);
-
-if (error == 0 && (chn_reset(wrch, fmt) ||
-(fmt && chn_setspeed(wrch, DSP_DEFAULT_SPEED))))
-error = ENODEV;
-
-if (error != 0) {
-if (wrch)
-pcm_chnrelease(wrch);
-if (rdch) {
-/*
-* Lock, deref and release previously created record channel
-*/
-CHN_LOCK(rdch);
-pcm_chnref(rdch, -1);
-pcm_chnrelease(rdch);
-}
-
-return error;
-}
+ struct pcm_channel *rdch, *wrch;
+ struct snddev_info *d;
+ uint32_t fmt, spd, prio;
+ int i, error, rderror, wrerror, devtype, wdevunit, rdevunit;
+
+ /* Kind of impossible.. */
+ if (i_dev == NULL || td == NULL)
+ return (ENODEV);
+
+ d = dsp_get_info(i_dev);
+ if (!PCM_REGISTERED(d))
+ return (EBADF);
+
+ PCM_GIANT_ENTER(d);
+
+ /* Lock snddev so nobody else can monkey with it. */
+ pcm_lock(d);
+ PCM_WAIT(d);
+
+ /*
+ * Try to acquire cloned device before someone else pick it.
+ * ENODEV means this is not a cloned droids.
+ */
+ error = snd_clone_acquire(i_dev);
+ if (!(error == 0 || error == ENODEV)) {
+ DSP_FIXUP_ERROR();
+ pcm_unlock(d);
+ PCM_GIANT_EXIT(d);
+ return (error);
+ }
+
+ error = 0;
+ DSP_FIXUP_ERROR();
+
+ if (error != 0) {
+ (void)snd_clone_release(i_dev);
+ pcm_unlock(d);
+ PCM_GIANT_EXIT(d);
+ return (error);
+ }
+
+ /*
+ * That is just enough. Acquire and unlock pcm lock so
+ * the other will just have to wait until we finish doing
+ * everything.
+ */
+ PCM_ACQUIRE(d);
+ pcm_unlock(d);
+
+ devtype = PCMDEV(i_dev);
+ wdevunit = -1;
+ rdevunit = -1;
+ fmt = 0;
+ spd = 0;
+
+ for (i = 0; i < (sizeof(dsp_cdevs) / sizeof(dsp_cdevs[0])); i++) {
+ if (devtype != dsp_cdevs[i].type)
+ continue;
+ if (DSP_F_SIMPLEX(flags) &&
+ ((dsp_cdevs[i].query == DSP_CDEV_TYPE_WRONLY &&
+ DSP_F_READ(flags)) ||
+ (dsp_cdevs[i].query == DSP_CDEV_TYPE_RDONLY &&
+ DSP_F_WRITE(flags)))) {
+ /*
+ * simplex, opposite direction? Please be gone..
+ */
+ (void)snd_clone_release(i_dev);
+ PCM_RELEASE_QUICK(d);
+ PCM_GIANT_EXIT(d);
+ return (ENOTSUP);
+ }
+ if (dsp_cdevs[i].query == DSP_CDEV_TYPE_WRONLY)
+ wdevunit = dev2unit(i_dev);
+ else if (dsp_cdevs[i].query == DSP_CDEV_TYPE_RDONLY)
+ rdevunit = dev2unit(i_dev);
+ fmt = dsp_cdevs[i].fmt;
+ spd = dsp_cdevs[i].spd;
+ break;
+ }
+
+ /* No matching devtype? */
+ if (fmt == 0 || spd == 0)
+ panic("impossible devtype %d", devtype);
+
+ rdch = NULL;
+ wrch = NULL;
+ rderror = 0;
+ wrerror = 0;
+
+ /*
+ * if we get here, the open request is valid- either:
+ * * we were previously not open
+ * * we were open for play xor record and the opener wants
+ * the non-open direction
+ */
+ if (DSP_F_READ(flags)) {
+ /* open for read */
+ rderror = pcm_chnalloc(d, &rdch, PCMDIR_REC,
+ td->td_proc->p_pid, rdevunit);
+
+ if (rderror == 0 && (chn_reset(rdch, fmt) != 0 ||
+ (chn_setspeed(rdch, spd) != 0)))
+ rderror = ENXIO;
+
+ if (rderror != 0) {
+ if (rdch != NULL)
+ pcm_chnrelease(rdch);
+ if (!DSP_F_DUPLEX(flags)) {
+ (void)snd_clone_release(i_dev);
+ PCM_RELEASE_QUICK(d);
+ PCM_GIANT_EXIT(d);
+ return (rderror);
+ }
+ rdch = NULL;
+ } else {
+ if (flags & O_NONBLOCK)
+ rdch->flags |= CHN_F_NBIO;
+ pcm_chnref(rdch, 1);
+ CHN_UNLOCK(rdch);
+ }
+ }
+
+ if (DSP_F_WRITE(flags)) {
+ /* open for write */
+ wrerror = pcm_chnalloc(d, &wrch, PCMDIR_PLAY,
+ td->td_proc->p_pid, wdevunit);
+
+ if (wrerror == 0 && (chn_reset(wrch, fmt) != 0 ||
+ (chn_setspeed(wrch, spd) != 0)))
+ wrerror = ENXIO;
+
+ if (wrerror != 0) {
+ if (wrch != NULL)
+ pcm_chnrelease(wrch);
+ if (!DSP_F_DUPLEX(flags)) {
+ if (rdch != NULL) {
+ /*
+ * Lock, deref and release previously
+ * created record channel
+ */
+ CHN_LOCK(rdch);
+ pcm_chnref(rdch, -1);
+ pcm_chnrelease(rdch);
+ }
+ (void)snd_clone_release(i_dev);
+ PCM_RELEASE_QUICK(d);
+ PCM_GIANT_EXIT(d);
+ return (wrerror);
+ }
+ wrch = NULL;
+ } else {
+ if (flags & O_NONBLOCK)
+ wrch->flags |= CHN_F_NBIO;
+ pcm_chnref(wrch, 1);
+ CHN_UNLOCK(wrch);
+ }
+ }
+
+ if (rdch == NULL && wrch == NULL) {
+ (void)snd_clone_release(i_dev);
+ PCM_RELEASE_QUICK(d);
+ PCM_GIANT_EXIT(d);
+ return ((wrerror != 0) ? wrerror : rderror);
+ }
+
+ pcm_lock(d);
+
+ /*
+ * We're done. Allocate channels information for this cdev.
+ */
+ dsp_cdevinfo_alloc(i_dev, rdch, wrch);
+
+ /*
+ * Increase clone refcount for its automatic garbage collector.
+ */
+ (void)snd_clone_ref(i_dev);
-if (flags & O_NONBLOCK)
-wrch->flags |= CHN_F_NBIO;
-pcm_chnref(wrch, 1);
-CHN_UNLOCK(wrch);
-pcm_lock(d);
-}
+ PCM_RELEASE(d);
+ pcm_unlock(d);
-i_dev->si_drv1 = rdch;
-i_dev->si_drv2 = wrch;
+ PCM_GIANT_LEAVE(d);
-pcm_unlock(d);
-return 0;
+ return (0);
}
static int
dsp_close(struct cdev *i_dev, int flags, int mode, struct thread *td)
{
-struct pcm_channel *rdch, *wrch;
-struct snddev_info *d;
-int refs;
-
-d = dsp_get_info(i_dev);
-pcm_lock(d);
-rdch = i_dev->si_drv1;
-wrch = i_dev->si_drv2;
-pcm_unlock(d);
-
-if (rdch || wrch) {
-refs = 0;
-if (rdch) {
-CHN_LOCK(rdch);
-refs += pcm_chnref(rdch, -1);
-chn_abort(rdch); /* won't sleep */
-rdch->flags &= ~(CHN_F_RUNNING | CHN_F_MAPPED | CHN_F_DEAD);
-chn_reset(rdch, 0);
-pcm_chnrelease(rdch);
-}
-if (wrch) {
-CHN_LOCK(wrch);
-refs += pcm_chnref(wrch, -1);
-/*
-* XXX: Maybe the right behaviour is to abort on non_block.
-* It seems that mplayer flushes the audio queue by quickly
-* closing and re-opening. In FBSD, there's a long pause
-* while the audio queue flushes that I presume isn't there in
-* linux.
-*/
-chn_flush(wrch); /* may sleep */
-wrch->flags &= ~(CHN_F_RUNNING | CHN_F_MAPPED | CHN_F_DEAD);
-chn_reset(wrch, 0);
-pcm_chnrelease(wrch);
-}
-
-pcm_lock(d);
-if (rdch)
-i_dev->si_drv1 = NULL;
-if (wrch)
-i_dev->si_drv2 = NULL;
-/*
-* If there are no more references, release the channels.
-*/
-if (refs == 0 && i_dev->si_drv1 == NULL &&
-i_dev->si_drv2 == NULL) {
-if (pcm_getfakechan(d))
-pcm_getfakechan(d)->flags = 0;
-/* What is this?!? */
-dsp_set_flags(i_dev, dsp_get_flags(i_dev) & ~SD_F_TRANSIENT);
-}
-pcm_unlock(d);
-}
-return 0;
-}
+ struct pcm_channel *rdch, *wrch;
+ struct snddev_info *d;
+ int sg_ids, refs;
+
+ d = dsp_get_info(i_dev);
+ if (!DSP_REGISTERED(d, i_dev))
+ return (EBADF);
+
+ PCM_GIANT_ENTER(d);
+
+ pcm_lock(d);
+ PCM_WAIT(d);
+
+ rdch = PCM_RDCH(i_dev);
+ wrch = PCM_WRCH(i_dev);
+
+ if (rdch || wrch) {
+ PCM_ACQUIRE(d);
+ pcm_unlock(d);
+
+ refs = 0;
+ if (rdch) {
+ /*
+ * The channel itself need not be locked because:
+ * a) Adding a channel to a syncgroup happens only in dsp_ioctl(),
+ * which cannot run concurrently to dsp_close().
+ * b) The syncmember pointer (sm) is protected by the global
+ * syncgroup list lock.
+ * c) A channel can't just disappear, invalidating pointers,
+ * unless it's closed/dereferenced first.
+ */
+ PCM_SG_LOCK();
+ sg_ids = chn_syncdestroy(rdch);
+ PCM_SG_UNLOCK();
+ if (sg_ids != 0)
+ free_unr(pcmsg_unrhdr, sg_ids);
+
+ CHN_LOCK(rdch);
+ refs += pcm_chnref(rdch, -1);
+ chn_abort(rdch); /* won't sleep */
+ rdch->flags &= ~(CHN_F_RUNNING | CHN_F_MAPPED | CHN_F_DEAD);
+ chn_reset(rdch, 0);
+ pcm_chnrelease(rdch);
+ PCM_RDCH(i_dev) = NULL;
+ }
+ if (wrch) {
+ /*
+ * Please see block above.
+ */
+ PCM_SG_LOCK();
+ sg_ids = chn_syncdestroy(wrch);
+ PCM_SG_UNLOCK();
+ if (sg_ids != 0)
+ free_unr(pcmsg_unrhdr, sg_ids);
+
+ CHN_LOCK(wrch);
+ refs += pcm_chnref(wrch, -1);
+ chn_flush(wrch); /* may sleep */
+ wrch->flags &= ~(CHN_F_RUNNING | CHN_F_MAPPED | CHN_F_DEAD);
+ chn_reset(wrch, 0);
+ pcm_chnrelease(wrch);
+ PCM_WRCH(i_dev) = NULL;
+ }
+
+ pcm_lock(d);
+ /*
+ * If there are no more references, release the channels.
+ */
+ if (refs == 0 && PCM_RDCH(i_dev) == NULL &&
+ PCM_WRCH(i_dev) == NULL) {
+ dsp_cdevinfo_free(i_dev);
+ /*
+ * Release clone busy state and unref it
+ * so the automatic garbage collector will
+ * get the hint and do the remaining cleanup
+ * process.
+ */
+ (void)snd_clone_release(i_dev);
+ (void)snd_clone_unref(i_dev);
+ }
+ PCM_RELEASE(d);
+ }
+
+ pcm_unlock(d);
+
+ PCM_GIANT_LEAVE(d);
+
+ return (0);
+}
+
+static __inline int
+dsp_io_ops(struct cdev *i_dev, struct uio *buf)
+{
+ struct snddev_info *d;
+ struct pcm_channel **ch, *rdch, *wrch;
+ int (*chn_io)(struct pcm_channel *, struct uio *);
+ int prio, ret;
+ pid_t runpid;
+
+ KASSERT(i_dev != NULL && buf != NULL &&
+ (buf->uio_rw == UIO_READ || buf->uio_rw == UIO_WRITE),
+ ("%s(): io train wreck!", __func__));
+
+ d = dsp_get_info(i_dev);
+ if (!DSP_REGISTERED(d, i_dev))
+ return (EBADF);
+
+ PCM_GIANT_ENTER(d);
+
+ switch (buf->uio_rw) {
+ case UIO_READ:
+ prio = SD_F_PRIO_RD;
+ ch = &rdch;
+ chn_io = chn_read;
+ break;
+ case UIO_WRITE:
+ prio = SD_F_PRIO_WR;
+ ch = &wrch;
+ chn_io = chn_write;
+ break;
+ default:
+ panic("invalid/corrupted uio direction: %d", buf->uio_rw);
+ break;
+ }
+
+ rdch = NULL;
+ wrch = NULL;
+ runpid = buf->uio_td->td_proc->p_pid;
+
+ getchns(i_dev, &rdch, &wrch, prio);
+
+ if (*ch == NULL || !((*ch)->flags & CHN_F_BUSY)) {
+ PCM_GIANT_EXIT(d);
+ return (EBADF);
+ }
+
+ if (((*ch)->flags & (CHN_F_MAPPED | CHN_F_DEAD)) ||
+ (((*ch)->flags & CHN_F_RUNNING) && (*ch)->pid != runpid)) {
+ relchns(i_dev, rdch, wrch, prio);
+ PCM_GIANT_EXIT(d);
+ return (EINVAL);
+ } else if (!((*ch)->flags & CHN_F_RUNNING)) {
+ (*ch)->flags |= CHN_F_RUNNING;
+ (*ch)->pid = runpid;
+ }
+
+ /*
+ * chn_read/write must give up channel lock in order to copy bytes
+ * from/to userland, so up the "in progress" counter to make sure
+ * someone else doesn't come along and muss up the buffer.
+ */
+ ++(*ch)->inprog;
+ ret = chn_io(*ch, buf);
+ --(*ch)->inprog;
-static int
-dsp_read(struct cdev *i_dev, struct uio *buf, int flag)
-{
-struct pcm_channel *rdch, *wrch;
-int ret;
+ CHN_BROADCAST(&(*ch)->cv);
-getchns(i_dev, &rdch, &wrch, SD_F_PRIO_RD);
+ relchns(i_dev, rdch, wrch, prio);
-KASSERT(rdch, ("dsp_read: nonexistant channel"));
-KASSERT(rdch->flags & CHN_F_BUSY, ("dsp_read: nonbusy channel"));
+ PCM_GIANT_LEAVE(d);
-if (rdch->flags & (CHN_F_MAPPED | CHN_F_DEAD)) {
-relchns(i_dev, rdch, wrch, SD_F_PRIO_RD);
-return EINVAL;
+ return (ret);
}
-if (!(rdch->flags & CHN_F_RUNNING))
-rdch->flags |= CHN_F_RUNNING;
-ret = chn_read(rdch, buf);
-relchns(i_dev, rdch, wrch, SD_F_PRIO_RD);
-return ret;
+static int
+dsp_read(struct cdev *i_dev, struct uio *buf, int flag)
+{
+ return (dsp_io_ops(i_dev, buf));
}
static int
dsp_write(struct cdev *i_dev, struct uio *buf, int flag)
{
-struct pcm_channel *rdch, *wrch;
-int ret;
-
-getchns(i_dev, &rdch, &wrch, SD_F_PRIO_WR);
-
-KASSERT(wrch, ("dsp_write: nonexistant channel"));
-KASSERT(wrch->flags & CHN_F_BUSY, ("dsp_write: nonbusy channel"));
-
-if (wrch->flags & (CHN_F_MAPPED | CHN_F_DEAD)) {
-relchns(i_dev, rdch, wrch, SD_F_PRIO_WR);
-return EINVAL;
-}
-if (!(wrch->flags & CHN_F_RUNNING))
-wrch->flags |= CHN_F_RUNNING;
-ret = chn_write(wrch, buf);
-relchns(i_dev, rdch, wrch, SD_F_PRIO_WR);
-
-return ret;
+ return (dsp_io_ops(i_dev, buf));
}
static int
dsp_ioctl(struct cdev *i_dev, u_long cmd, caddr_t arg, int mode, struct thread *td)
{
-struct pcm_channel *chn, *rdch, *wrch;
-struct snddev_info *d;
-int kill;
-int ret = 0, *arg_i = (int *)arg, tmp;
+ struct pcm_channel *chn, *rdch, *wrch;
+ struct snddev_info *d;
+ int *arg_i, ret, kill, tmp, xcmd;
+
+ d = dsp_get_info(i_dev);
+ if (!DSP_REGISTERED(d, i_dev))
+ return (EBADF);
+
+ PCM_GIANT_ENTER(d);
+
+ arg_i = (int *)arg;
+ ret = 0;
+ xcmd = 0;
+
+ /*
+ * this is an evil hack to allow broken apps to perform mixer ioctls
+ * on dsp devices.
+ */
+ if (IOCGROUP(cmd) == 'M') {
+ /*
+ * This is at least, a bug to bug compatible with OSS.
+ */
+ if (d->mixer_dev != NULL) {
+ PCM_ACQUIRE_QUICK(d);
+ ret = mixer_ioctl_cmd(d->mixer_dev, cmd, arg, -1, td,
+ MIXER_CMD_DIRECT);
+ PCM_RELEASE_QUICK(d);
+ } else
+ ret = EBADF;
+
+ PCM_GIANT_EXIT(d);
+
+ return (ret);
+ }
+
+ /*
+ * Certain ioctls may be made on any type of device (audio, mixer,
+ * and MIDI). Handle those special cases here.
+ */
+ if (IOCGROUP(cmd) == 'X') {
+ PCM_ACQUIRE_QUICK(d);
+ switch(cmd) {
+ case SNDCTL_SYSINFO:
+ sound_oss_sysinfo((oss_sysinfo *)arg);
+ break;
+ case SNDCTL_AUDIOINFO:
+ ret = dsp_oss_audioinfo(i_dev, (oss_audioinfo *)arg);
+ break;
+ case SNDCTL_MIXERINFO:
+ ret = mixer_oss_mixerinfo(i_dev, (oss_mixerinfo *)arg);
+ break;
+ default:
+ ret = EINVAL;
+ }
+ PCM_RELEASE_QUICK(d);
+ PCM_GIANT_EXIT(d);
+ return (ret);
+ }
+
+ getchns(i_dev, &rdch, &wrch, 0);
+
+ kill = 0;
+ if (wrch && (wrch->flags & CHN_F_DEAD))
+ kill |= 1;
+ if (rdch && (rdch->flags & CHN_F_DEAD))
+ kill |= 2;
+ if (kill == 3) {
+ relchns(i_dev, rdch, wrch, 0);
+ PCM_GIANT_EXIT(d);
+ return (EINVAL);
+ }
+ if (kill & 1)
+ wrch = NULL;
+ if (kill & 2)
+ rdch = NULL;
+
+ if (wrch == NULL && rdch == NULL) {
+ relchns(i_dev, rdch, wrch, 0);
+ PCM_GIANT_EXIT(d);
+ return (EINVAL);
+ }
-/*
-* this is an evil hack to allow broken apps to perform mixer ioctls
-* on dsp devices.
-*/
-
-d = dsp_get_info(i_dev);
-if (IOCGROUP(cmd) == 'M') {
-/*
-* This is at least, a bug to bug compatible with OSS.
-*/
-if (d->mixer_dev != NULL)
-return mixer_ioctl(d->mixer_dev, cmd, arg, -1, td);
-else
-return EBADF;
-}
-
-getchns(i_dev, &rdch, &wrch, 0);
-
-kill = 0;
-if (wrch && (wrch->flags & CHN_F_DEAD))
-kill |= 1;
-if (rdch && (rdch->flags & CHN_F_DEAD))
-kill |= 2;
-if (kill == 3) {
-relchns(i_dev, rdch, wrch, 0);
-return EINVAL;
-}
-if (kill & 1)
-wrch = NULL;
-if (kill & 2)
-rdch = NULL;
-
-switch(cmd) {
+ switch(cmd) {
#ifdef OLDPCM_IOCTL
+ /*
+ * we start with the new ioctl interface.
+ */
+ case AIONWRITE: /* how many bytes can write ? */
+ if (wrch) {
+ CHN_LOCK(wrch);
/*
-* we start with the new ioctl interface.
-*/
-case AIONWRITE: /* how many bytes can write ? */
-if (wrch) {
-CHN_LOCK(wrch);
-/*
-if (wrch && wrch->bufhard.dl)
-while (chn_wrfeed(wrch) == 0);
+ if (wrch && wrch->bufhard.dl)
+ while (chn_wrfeed(wrch) == 0);
*/
-*arg_i = sndbuf_getfree(wrch->bufsoft);
-CHN_UNLOCK(wrch);
-} else {
-*arg_i = 0;
-ret = EINVAL;
-}
-break;
-
-case AIOSSIZE: /* set the current blocksize */
-{
-struct snd_size *p = (struct snd_size *)arg;
-
-p->play_size = 0;
-p->rec_size = 0;
-if (wrch) {
-CHN_LOCK(wrch);
-chn_setblocksize(wrch, 2, p->play_size);
-p->play_size = sndbuf_getblksz(wrch->bufsoft);
-CHN_UNLOCK(wrch);
-}
-if (rdch) {
-CHN_LOCK(rdch);
-chn_setblocksize(rdch, 2, p->rec_size);
-p->rec_size = sndbuf_getblksz(rdch->bufsoft);
-CHN_UNLOCK(rdch);
-}
-}
-break;
-case AIOGSIZE: /* get the current blocksize */
-{
-struct snd_size *p = (struct snd_size *)arg;
-
-if (wrch) {
-CHN_LOCK(wrch);
-p->play_size = sndbuf_getblksz(wrch->bufsoft);
-CHN_UNLOCK(wrch);
-}
-if (rdch) {
-CHN_LOCK(rdch);
-p->rec_size = sndbuf_getblksz(rdch->bufsoft);
-CHN_UNLOCK(rdch);
-}
-}
-break;
-
-case AIOSFMT:
-case AIOGFMT:
-{
-snd_chan_param *p = (snd_chan_param *)arg;
-
-if (cmd == AIOSFMT &&
-((p->play_format != 0 && p->play_rate == 0) ||
-(p->rec_format != 0 && p->rec_rate == 0))) {
-ret = EINVAL;
-break;
-}
-if (wrch) {
-CHN_LOCK(wrch);
-if (cmd == AIOSFMT && p->play_format != 0) {
-chn_setformat(wrch, p->play_format);
-chn_setspeed(wrch, p->play_rate);
-}
-p->play_rate = wrch->speed;
-p->play_format = wrch->format;
-CHN_UNLOCK(wrch);
-} else {
-p->play_rate = 0;
-p->play_format = 0;
-}
-if (rdch) {
-CHN_LOCK(rdch);
-if (cmd == AIOSFMT && p->rec_format != 0) {
-chn_setformat(rdch, p->rec_format);
-chn_setspeed(rdch, p->rec_rate);
-}
-p->rec_rate = rdch->speed;
-p->rec_format = rdch->format;
-CHN_UNLOCK(rdch);
-} else {
-p->rec_rate = 0;
-p->rec_format = 0;
-}
-}
-break;
-
-case AIOGCAP: /* get capabilities */
-{
-snd_capabilities *p = (snd_capabilities *)arg;
-struct pcmchan_caps *pcaps = NULL, *rcaps = NULL;
-struct cdev *pdev;
-
-if (rdch) {
-CHN_LOCK(rdch);
-rcaps = chn_getcaps(rdch);
-}
-if (wrch) {
-CHN_LOCK(wrch);
-pcaps = chn_getcaps(wrch);
-}
-p->rate_min = max(rcaps? rcaps->minspeed : 0,
-pcaps? pcaps->minspeed : 0);
-p->rate_max = min(rcaps? rcaps->maxspeed : 1000000,
-pcaps? pcaps->maxspeed : 1000000);
-p->bufsize = min(rdch? sndbuf_getsize(rdch->bufsoft) : 1000000,
-wrch? sndbuf_getsize(wrch->bufsoft) : 1000000);
-/* XXX bad on sb16 */
-p->formats = (rdch? chn_getformats(rdch) : 0xffffffff) &
-(wrch? chn_getformats(wrch) : 0xffffffff);
-if (rdch && wrch)
-p->formats |= (dsp_get_flags(i_dev) & SD_F_SIMPLEX)? 0 : AFMT_FULLDUPLEX;
-pdev = d->mixer_dev;
-p->mixers = 1; /* default: one mixer */
-p->inputs = pdev->si_drv1? mix_getdevs(pdev->si_drv1) : 0;
-p->left = p->right = 100;
-if (rdch)
-CHN_UNLOCK(rdch);
-if (wrch)
-CHN_UNLOCK(wrch);
-}
-break;
-
-case AIOSTOP:
-if (*arg_i == AIOSYNC_PLAY && wrch) {
-CHN_LOCK(wrch);
-*arg_i = chn_abort(wrch);
-CHN_UNLOCK(wrch);
-} else if (*arg_i == AIOSYNC_CAPTURE && rdch) {
-CHN_LOCK(rdch);
-*arg_i = chn_abort(rdch);
-CHN_UNLOCK(rdch);
-} else {
-printf("AIOSTOP: bad channel 0x%xn", *arg_i);
-*arg_i = 0;
-}
-break;
-
-case AIOSYNC:
-printf("AIOSYNC chan 0x%03lx pos %lu unimplementedn",
-((snd_sync_parm *)arg)->chan, ((snd_sync_parm *)arg)->pos);
-break;
+ *arg_i = sndbuf_getfree(wrch->bufsoft);
+ CHN_UNLOCK(wrch);
+ } else {
+ *arg_i = 0;
+ ret = EINVAL;
+ }
+ break;
+
+ case AIOSSIZE: /* set the current blocksize */
+ {
+ struct snd_size *p = (struct snd_size *)arg;
+
+ p->play_size = 0;
+ p->rec_size = 0;
+ PCM_ACQUIRE_QUICK(d);
+ if (wrch) {
+ CHN_LOCK(wrch);
+ chn_setblocksize(wrch, 2, p->play_size);
+ p->play_size = sndbuf_getblksz(wrch->bufsoft);
+ CHN_UNLOCK(wrch);
+ }
+ if (rdch) {
+ CHN_LOCK(rdch);
+ chn_setblocksize(rdch, 2, p->rec_size);
+ p->rec_size = sndbuf_getblksz(rdch->bufsoft);
+ CHN_UNLOCK(rdch);
+ }
+ PCM_RELEASE_QUICK(d);
+ }
+ break;
+ case AIOGSIZE: /* get the current blocksize */
+ {
+ struct snd_size *p = (struct snd_size *)arg;
+
+ if (wrch) {
+ CHN_LOCK(wrch);
+ p->play_size = sndbuf_getblksz(wrch->bufsoft);
+ CHN_UNLOCK(wrch);
+ }
+ if (rdch) {
+ CHN_LOCK(rdch);
+ p->rec_size = sndbuf_getblksz(rdch->bufsoft);
+ CHN_UNLOCK(rdch);
+ }
+ }
+ break;
+
+ case AIOSFMT:
+ case AIOGFMT:
+ {
+ snd_chan_param *p = (snd_chan_param *)arg;
+
+ if (cmd == AIOSFMT &&
+ ((p->play_format != 0 && p->play_rate == 0) ||
+ (p->rec_format != 0 && p->rec_rate == 0))) {
+ ret = EINVAL;
+ break;
+ }
+ PCM_ACQUIRE_QUICK(d);
+ if (wrch) {
+ CHN_LOCK(wrch);
+ if (cmd == AIOSFMT && p->play_format != 0) {
+ chn_setformat(wrch, p->play_format);
+ chn_setspeed(wrch, p->play_rate);
+ }
+ p->play_rate = wrch->speed;
+ p->play_format = wrch->format;
+ CHN_UNLOCK(wrch);
+ } else {
+ p->play_rate = 0;
+ p->play_format = 0;
+ }
+ if (rdch) {
+ CHN_LOCK(rdch);
+ if (cmd == AIOSFMT && p->rec_format != 0) {
+ chn_setformat(rdch, p->rec_format);
+ chn_setspeed(rdch, p->rec_rate);
+ }
+ p->rec_rate = rdch->speed;
+ p->rec_format = rdch->format;
+ CHN_UNLOCK(rdch);
+ } else {
+ p->rec_rate = 0;
+ p->rec_format = 0;
+ }
+ PCM_RELEASE_QUICK(d);
+ }
+ break;
+
+ case AIOGCAP: /* get capabilities */
+ {
+ snd_capabilities *p = (snd_capabilities *)arg;
+ struct pcmchan_caps *pcaps = NULL, *rcaps = NULL;
+ struct cdev *pdev;
+
+ pcm_lock(d);
+ if (rdch) {
+ CHN_LOCK(rdch);
+ rcaps = chn_getcaps(rdch);
+ }
+ if (wrch) {
+ CHN_LOCK(wrch);
+ pcaps = chn_getcaps(wrch);
+ }
+ p->rate_min = max(rcaps? rcaps->minspeed : 0,
+ pcaps? pcaps->minspeed : 0);
+ p->rate_max = min(rcaps? rcaps->maxspeed : 1000000,
+ pcaps? pcaps->maxspeed : 1000000);
+ p->bufsize = min(rdch? sndbuf_getsize(rdch->bufsoft) : 1000000,
+ wrch? sndbuf_getsize(wrch->bufsoft) : 1000000);
+ /* XXX bad on sb16 */
+ p->formats = (rdch? chn_getformats(rdch) : 0xffffffff) &
+ (wrch? chn_getformats(wrch) : 0xffffffff);
+ if (rdch && wrch)
+ p->formats |= (dsp_get_flags(i_dev) & SD_F_SIMPLEX)? 0 : AFMT_FULLDUPLEX;
+ pdev = d->mixer_dev;
+ p->mixers = 1; /* default: one mixer */
+ p->inputs = pdev->si_drv1? mix_getdevs(pdev->si_drv1) : 0;
+ p->left = p->right = 100;
+ if (wrch)
+ CHN_UNLOCK(wrch);
+ if (rdch)
+ CHN_UNLOCK(rdch);
+ pcm_unlock(d);
+ }
+ break;
+
+ case AIOSTOP:
+ if (*arg_i == AIOSYNC_PLAY && wrch) {
+ CHN_LOCK(wrch);
+ *arg_i = chn_abort(wrch);
+ CHN_UNLOCK(wrch);
+ } else if (*arg_i == AIOSYNC_CAPTURE && rdch) {
+ CHN_LOCK(rdch);
+ *arg_i = chn_abort(rdch);
+ CHN_UNLOCK(rdch);
+ } else {
+ printf("AIOSTOP: bad channel 0x%x\n", *arg_i);
+ *arg_i = 0;
+ }
+ break;
+
+ case AIOSYNC:
+ printf("AIOSYNC chan 0x%03lx pos %lu unimplemented\n",
+ ((snd_sync_parm *)arg)->chan, ((snd_sync_parm *)arg)->pos);
+ break;
#endif
-/*
-* here follow the standard ioctls (filio.h etc.)
-*/
-case FIONREAD: /* get # bytes to read */
-if (rdch) {
-CHN_LOCK(rdch);
+ /*
+ * here follow the standard ioctls (filio.h etc.)
+ */
+ case FIONREAD: /* get # bytes to read */
+ if (rdch) {
+ CHN_LOCK(rdch);
/* if (rdch && rdch->bufhard.dl)
-while (chn_rdfeed(rdch) == 0);
-*/
-*arg_i = sndbuf_getready(rdch->bufsoft);
-CHN_UNLOCK(rdch);
-} else {
-*arg_i = 0;
-ret = EINVAL;
-}
-break;
-
-case FIOASYNC: /*set/clear async i/o */
-DEB( printf("FIOASYNCn") ; )
-break;
-
-case SNDCTL_DSP_NONBLOCK:
-case FIONBIO: /* set/clear non-blocking i/o */
-if (rdch) {
-CHN_LOCK(rdch);
-if (*arg_i)
-rdch->flags |= CHN_F_NBIO;
-else
-rdch->flags &= ~CHN_F_NBIO;
-CHN_UNLOCK(rdch);
-}
-if (wrch) {
-CHN_LOCK(wrch);
-if (*arg_i)
-wrch->flags |= CHN_F_NBIO;
-else
-wrch->flags &= ~CHN_F_NBIO;
-CHN_UNLOCK(wrch);
-}
-break;
-
-/*
-* Finally, here is the linux-compatible ioctl interface
+ while (chn_rdfeed(rdch) == 0);
*/
+ *arg_i = sndbuf_getready(rdch->bufsoft);
+ CHN_UNLOCK(rdch);
+ } else {
+ *arg_i = 0;
+ ret = EINVAL;
+ }
+ break;
+
+ case FIOASYNC: /*set/clear async i/o */
+ DEB( printf("FIOASYNC\n") ; )
+ break;
+
+ case SNDCTL_DSP_NONBLOCK: /* set non-blocking i/o */
+ case FIONBIO: /* set/clear non-blocking i/o */
+ if (rdch) {
+ CHN_LOCK(rdch);
+ if (cmd == SNDCTL_DSP_NONBLOCK || *arg_i)
+ rdch->flags |= CHN_F_NBIO;
+ else
+ rdch->flags &= ~CHN_F_NBIO;
+ CHN_UNLOCK(rdch);
+ }
+ if (wrch) {
+ CHN_LOCK(wrch);
+ if (cmd == SNDCTL_DSP_NONBLOCK || *arg_i)
+ wrch->flags |= CHN_F_NBIO;
+ else
+ wrch->flags &= ~CHN_F_NBIO;
+ CHN_UNLOCK(wrch);
+ }
+ break;
+
+ /*
+ * Finally, here is the linux-compatible ioctl interface
+ */
#define THE_REAL_SNDCTL_DSP_GETBLKSIZE _IOWR('P', 4, int)
-case THE_REAL_SNDCTL_DSP_GETBLKSIZE:
-case SNDCTL_DSP_GETBLKSIZE:
-chn = wrch ? wrch : rdch;
-if (chn) {
-CHN_LOCK(chn);
-*arg_i = sndbuf_getblksz(chn->bufsoft);
-CHN_UNLOCK(chn);
-} else {
-*arg_i = 0;
-ret = EINVAL;
-}
-break ;
-
-case SNDCTL_DSP_SETBLKSIZE:
-RANGE(*arg_i, 16, 65536);
-if (wrch) {
-CHN_LOCK(wrch);
-chn_setblocksize(wrch, 2, *arg_i);
-CHN_UNLOCK(wrch);
-}
-if (rdch) {
-CHN_LOCK(rdch);
-chn_setblocksize(rdch, 2, *arg_i);
-CHN_UNLOCK(rdch);
-}
-break;
-
-case SNDCTL_DSP_RESET:
-DEB(printf("dsp resetn"));
-if (wrch) {
-CHN_LOCK(wrch);
-chn_abort(wrch);
-chn_resetbuf(wrch);
-CHN_UNLOCK(wrch);
-}
-if (rdch) {
-CHN_LOCK(rdch);
-chn_abort(rdch);
-chn_resetbuf(rdch);
-CHN_UNLOCK(rdch);
-}
-break;
-
-case SNDCTL_DSP_SYNC:
-DEB(printf("dsp syncn"));
-/* chn_sync may sleep */
-if (wrch) {
-CHN_LOCK(wrch);
-chn_sync(wrch, sndbuf_getsize(wrch->bufsoft) - 4);
-CHN_UNLOCK(wrch);
-}
-break;
-
-case SNDCTL_DSP_SPEED:
-/* chn_setspeed may sleep */
-tmp = 0;
-if (wrch) {
-CHN_LOCK(wrch);
-ret = chn_setspeed(wrch, *arg_i);
-tmp = wrch->speed;
-CHN_UNLOCK(wrch);
-}
-if (rdch && ret == 0) {
-CHN_LOCK(rdch);
-ret = chn_setspeed(rdch, *arg_i);
-if (tmp == 0)
-tmp = rdch->speed;
-CHN_UNLOCK(rdch);
-}
-*arg_i = tmp;
-break;
-
-case SOUND_PCM_READ_RATE:
-chn = wrch ? wrch : rdch;
-if (chn) {
-CHN_LOCK(chn);
-*arg_i = chn->speed;
-CHN_UNLOCK(chn);
-} else {
-*arg_i = 0;
-ret = EINVAL;
-}
-break;
-
-case SNDCTL_DSP_STEREO:
-tmp = -1;
-*arg_i = (*arg_i)? AFMT_STEREO : 0;
-if (wrch) {
-CHN_LOCK(wrch);
-ret = chn_setformat(wrch, (wrch->format & ~AFMT_STEREO) | *arg_i);
-tmp = (wrch->format & AFMT_STEREO)? 1 : 0;
-CHN_UNLOCK(wrch);
-}
-if (rdch && ret == 0) {
-CHN_LOCK(rdch);
-ret = chn_setformat(rdch, (rdch->format & ~AFMT_STEREO) | *arg_i);
-if (tmp == -1)
-tmp = (rdch->format & AFMT_STEREO)? 1 : 0;
-CHN_UNLOCK(rdch);
-}
-*arg_i = tmp;
-break;
+ case THE_REAL_SNDCTL_DSP_GETBLKSIZE:
+ case SNDCTL_DSP_GETBLKSIZE:
+ chn = wrch ? wrch : rdch;
+ if (chn) {
+ CHN_LOCK(chn);
+ *arg_i = sndbuf_getblksz(chn->bufsoft);
+ CHN_UNLOCK(chn);
+ } else {
+ *arg_i = 0;
+ ret = EINVAL;
+ }
+ break;
+
+ case SNDCTL_DSP_SETBLKSIZE:
+ RANGE(*arg_i, 16, 65536);
+ PCM_ACQUIRE_QUICK(d);
+ if (wrch) {
+ CHN_LOCK(wrch);
+ chn_setblocksize(wrch, 2, *arg_i);
+ CHN_UNLOCK(wrch);
+ }
+ if (rdch) {
+ CHN_LOCK(rdch);
+ chn_setblocksize(rdch, 2, *arg_i);
+ CHN_UNLOCK(rdch);
+ }
+ PCM_RELEASE_QUICK(d);
+ break;
+
+ case SNDCTL_DSP_RESET:
+ DEB(printf("dsp reset\n"));
+ if (wrch) {
+ CHN_LOCK(wrch);
+ chn_abort(wrch);
+ chn_resetbuf(wrch);
+ CHN_UNLOCK(wrch);
+ }
+ if (rdch) {
+ CHN_LOCK(rdch);
+ chn_abort(rdch);
+ chn_resetbuf(rdch);
+ CHN_UNLOCK(rdch);
+ }
+ break;
+
+ case SNDCTL_DSP_SYNC:
+ DEB(printf("dsp sync\n"));
+ /* chn_sync may sleep */
+ if (wrch) {
+ CHN_LOCK(wrch);
+ chn_sync(wrch, 0);
+ CHN_UNLOCK(wrch);
+ }
+ break;
+
+ case SNDCTL_DSP_SPEED:
+ /* chn_setspeed may sleep */
+ tmp = 0;
+ PCM_ACQUIRE_QUICK(d);
+ if (wrch) {
+ CHN_LOCK(wrch);
+ ret = chn_setspeed(wrch, *arg_i);
+ tmp = wrch->speed;
+ CHN_UNLOCK(wrch);
+ }
+ if (rdch && ret == 0) {
+ CHN_LOCK(rdch);
+ ret = chn_setspeed(rdch, *arg_i);
+ if (tmp == 0)
+ tmp = rdch->speed;
+ CHN_UNLOCK(rdch);
+ }
+ PCM_RELEASE_QUICK(d);
+ *arg_i = tmp;
+ break;
+
+ case SOUND_PCM_READ_RATE:
+ chn = wrch ? wrch : rdch;
+ if (chn) {
+ CHN_LOCK(chn);
+ *arg_i = chn->speed;
+ CHN_UNLOCK(chn);
+ } else {
+ *arg_i = 0;
+ ret = EINVAL;
+ }
+ break;
+
+ case SNDCTL_DSP_STEREO:
+ tmp = -1;
+ *arg_i = (*arg_i)? AFMT_STEREO : 0;
+ PCM_ACQUIRE_QUICK(d);
+ if (wrch) {
+ CHN_LOCK(wrch);
+ ret = chn_setformat(wrch, (wrch->format & ~AFMT_STEREO) | *arg_i);
+ tmp = (wrch->format & AFMT_STEREO)? 1 : 0;
+ CHN_UNLOCK(wrch);
+ }
+ if (rdch && ret == 0) {
+ CHN_LOCK(rdch);
+ ret = chn_setformat(rdch, (rdch->format & ~AFMT_STEREO) | *arg_i);
+ if (tmp == -1)
+ tmp = (rdch->format & AFMT_STEREO)? 1 : 0;
+ CHN_UNLOCK(rdch);
+ }
+ PCM_RELEASE_QUICK(d);
+ *arg_i = tmp;
+ break;
-case SOUND_PCM_WRITE_CHANNELS:
+ case SOUND_PCM_WRITE_CHANNELS:
/* case SNDCTL_DSP_CHANNELS: ( == SOUND_PCM_WRITE_CHANNELS) */
-if (*arg_i != 0) {
-tmp = 0;
-*arg_i = (*arg_i != 1)? AFMT_STEREO : 0;
-if (wrch) {
-CHN_LOCK(wrch);
-ret = chn_setformat(wrch, (wrch->format & ~AFMT_STEREO) | *arg_i);
-tmp = (wrch->format & AFMT_STEREO)? 2 : 1;
-CHN_UNLOCK(wrch);
-}
-if (rdch && ret == 0) {
-CHN_LOCK(rdch);
-ret = chn_setformat(rdch, (rdch->format & ~AFMT_STEREO) | *arg_i);
-if (tmp == 0)
-tmp = (rdch->format & AFMT_STEREO)? 2 : 1;
-CHN_UNLOCK(rdch);
-}
-*arg_i = tmp;
-} else {
-chn = wrch ? wrch : rdch;
-CHN_LOCK(chn);
-*arg_i = (chn->format & AFMT_STEREO) ? 2 : 1;
-CHN_UNLOCK(chn);
-}
-break;
-
-case SOUND_PCM_READ_CHANNELS:
-chn = wrch ? wrch : rdch;
-if (chn) {
-CHN_LOCK(chn);
-*arg_i = (chn->format & AFMT_STEREO) ? 2 : 1;
-CHN_UNLOCK(chn);
-} else {
-*arg_i = 0;
-ret = EINVAL;
-}
-break;
-
-case SNDCTL_DSP_GETFMTS: /* returns a mask of supported fmts */
-chn = wrch ? wrch : rdch;
-if (chn) {
-CHN_LOCK(chn);
-*arg_i = chn_getformats(chn);
-CHN_UNLOCK(chn);
-} else {
-*arg_i = 0;
-ret = EINVAL;
-}
-break ;
-
-case SNDCTL_DSP_SETFMT: /* sets _one_ format */
-if ((*arg_i != AFMT_QUERY)) {
-tmp = 0;
-if (wrch) {
-CHN_LOCK(wrch);
-ret = chn_setformat(wrch, (*arg_i) | (wrch->format & AFMT_STEREO));
-tmp = wrch->format & ~AFMT_STEREO;
-CHN_UNLOCK(wrch);
-}
-if (rdch && ret == 0) {
-CHN_LOCK(rdch);
-ret = chn_setformat(rdch, (*arg_i) | (rdch->format & AFMT_STEREO));
-if (tmp == 0)
-tmp = rdch->format & ~AFMT_STEREO;
-CHN_UNLOCK(rdch);
-}
-*arg_i = tmp;
-} else {
-chn = wrch ? wrch : rdch;
-CHN_LOCK(chn);
-*arg_i = chn->format & ~AFMT_STEREO;
-CHN_UNLOCK(chn);
-}
-break;
-
-case SNDCTL_DSP_SETFRAGMENT:
-DEB(printf("SNDCTL_DSP_SETFRAGMENT 0x%08xn", *(int *)arg));
-{
-u_int32_t fragln = (*arg_i) & 0x0000ffff;
-u_int32_t maxfrags = ((*arg_i) & 0xffff0000) >> 16;
-u_int32_t fragsz;
-u_int32_t r_maxfrags, r_fragsz;
-
-RANGE(fragln, 4, 16);
-fragsz = 1 << fragln;
-
-if (maxfrags == 0)
-maxfrags = CHN_2NDBUFMAXSIZE / fragsz;
-if (maxfrags < 2)
-maxfrags = 2;
-if (maxfrags * fragsz > CHN_2NDBUFMAXSIZE)
-maxfrags = CHN_2NDBUFMAXSIZE / fragsz;
-
-DEB(printf("SNDCTL_DSP_SETFRAGMENT %d frags, %d szn", maxfrags, fragsz));
-if (rdch) {
-CHN_LOCK(rdch);
-ret = chn_setblocksize(rdch, maxfrags, fragsz);
-r_maxfrags = sndbuf_getblkcnt(rdch->bufsoft);
-r_fragsz = sndbuf_getblksz(rdch->bufsoft);
-CHN_UNLOCK(rdch);
-} else {
-r_maxfrags = maxfrags;
-r_fragsz = fragsz;
-}
-if (wrch && ret == 0) {
-CHN_LOCK(wrch);
-ret = chn_setblocksize(wrch, maxfrags, fragsz);
-maxfrags = sndbuf_getblkcnt(wrch->bufsoft);
-fragsz = sndbuf_getblksz(wrch->bufsoft);
-CHN_UNLOCK(wrch);
-} else { /* use whatever came from the read channel */
-maxfrags = r_maxfrags;
-fragsz = r_fragsz;
-}
-
-fragln = 0;
-while (fragsz > 1) {
-fragln++;
-fragsz >>= 1;
-}
-*arg_i = (maxfrags << 16) | fragln;
-}
-break;
-
-case SNDCTL_DSP_GETISPACE:
-/* return the size of data available in the input queue */
-{
-audio_buf_info *a = (audio_buf_info *)arg;
-if (rdch) {
-struct snd_dbuf *bs = rdch->bufsoft;
-
-CHN_LOCK(rdch);
-a->bytes = sndbuf_getready(bs);
-a->fragments = a->bytes / sndbuf_getblksz(bs);
-a->fragstotal = sndbuf_getblkcnt(bs);
-a->fragsize = sndbuf_getblksz(bs);
-CHN_UNLOCK(rdch);
-}
-}
-break;
-
-case SNDCTL_DSP_GETOSPACE:
-/* return space available in the output queue */
-{
-audio_buf_info *a = (audio_buf_info *)arg;
-if (wrch) {
-struct snd_dbuf *bs = wrch->bufsoft;
-
-CHN_LOCK(wrch);
-/* XXX abusive DMA update: chn_wrupdate(wrch); */
-a->bytes = sndbuf_getfree(bs);
-a->fragments = a->bytes / sndbuf_getblksz(bs);
-a->fragstotal = sndbuf_getblkcnt(bs);
-a->fragsize = sndbuf_getblksz(bs);
-CHN_UNLOCK(wrch);
-}
-}
-break;
-
-case SNDCTL_DSP_GETIPTR:
-{
-count_info *a = (count_info *)arg;
-if (rdch) {
-struct snd_dbuf *bs = rdch->bufsoft;
-
-CHN_LOCK(rdch);
-/* XXX abusive DMA update: chn_rdupdate(rdch); */
-a->bytes = sndbuf_gettotal(bs);
-a->blocks = sndbuf_getblocks(bs) - rdch->blocks;
-a->ptr = sndbuf_getreadyptr(bs);
-rdch->blocks = sndbuf_getblocks(bs);
-CHN_UNLOCK(rdch);
-} else
-ret = EINVAL;
-}
-break;
-
-case SNDCTL_DSP_GETOPTR:
-{
-count_info *a = (count_info *)arg;
-if (wrch) {
-struct snd_dbuf *bs = wrch->bufsoft;
-
-CHN_LOCK(wrch);
-/* XXX abusive DMA update: chn_wrupdate(wrch); */
-a->bytes = sndbuf_gettotal(bs);
-a->blocks = sndbuf_getblocks(bs) - wrch->blocks;
-a->ptr = sndbuf_getreadyptr(bs);
-wrch->blocks = sndbuf_getblocks(bs);
-CHN_UNLOCK(wrch);
-} else
-ret = EINVAL;
-}
-break;
-
-case SNDCTL_DSP_GETCAPS:
-*arg_i = DSP_CAP_REALTIME | DSP_CAP_MMAP | DSP_CAP_TRIGGER;
-if (rdch && wrch && !(dsp_get_flags(i_dev) & SD_F_SIMPLEX))
-*arg_i |= DSP_CAP_DUPLEX;
-break;
-
-case SOUND_PCM_READ_BITS:
-chn = wrch ? wrch : rdch;
-if (chn) {
-CHN_LOCK(chn);
-if (chn->format & AFMT_8BIT)
-*arg_i = 8;
-else if (chn->format & AFMT_16BIT)
-*arg_i = 16;
-else if (chn->format & AFMT_24BIT)
-*arg_i = 24;
-else if (chn->format & AFMT_32BIT)
-*arg_i = 32;
-else
-ret = EINVAL;
-CHN_UNLOCK(chn);
-} else {
-*arg_i = 0;
-ret = EINVAL;
-}
-break;
-
-case SNDCTL_DSP_SETTRIGGER:
-if (rdch) {
-CHN_LOCK(rdch);
-rdch->flags &= ~(CHN_F_TRIGGERED | CHN_F_NOTRIGGER);
-if (*arg_i & PCM_ENABLE_INPUT)
-chn_start(rdch, 1);
-else
-rdch->flags |= CHN_F_NOTRIGGER;
-CHN_UNLOCK(rdch);
-}
-if (wrch) {
-CHN_LOCK(wrch);
-wrch->flags &= ~(CHN_F_TRIGGERED | CHN_F_NOTRIGGER);
-if (*arg_i & PCM_ENABLE_OUTPUT)
-chn_start(wrch, 1);
-else
-wrch->flags |= CHN_F_NOTRIGGER;
-CHN_UNLOCK(wrch);
-}
-break;
-
-case SNDCTL_DSP_GETTRIGGER:
-*arg_i = 0;
-if (wrch) {
-CHN_LOCK(wrch);
-if (wrch->flags & CHN_F_TRIGGERED)
-*arg_i |= PCM_ENABLE_OUTPUT;
-CHN_UNLOCK(wrch);
-}
-if (rdch) {
-CHN_LOCK(rdch);
-if (rdch->flags & CHN_F_TRIGGERED)
-*arg_i |= PCM_ENABLE_INPUT;
-CHN_UNLOCK(rdch);
-}
-break;
-
-case SNDCTL_DSP_GETODELAY:
-if (wrch) {
-struct snd_dbuf *b = wrch->bufhard;
-struct snd_dbuf *bs = wrch->bufsoft;
-
-CHN_LOCK(wrch);
-/* XXX abusive DMA update: chn_wrupdate(wrch); */
-*arg_i = sndbuf_getready(b) + sndbuf_getready(bs);
-CHN_UNLOCK(wrch);
-} else
-ret = EINVAL;
-break;
-
-case SNDCTL_DSP_POST:
-if (wrch) {
-CHN_LOCK(wrch);
-wrch->flags &= ~CHN_F_NOTRIGGER;
-chn_start(wrch, 1);
-CHN_UNLOCK(wrch);
-}
-break;
+ if (*arg_i != 0) {
+ tmp = 0;
+ *arg_i = (*arg_i != 1)? AFMT_STEREO : 0;
+ PCM_ACQUIRE_QUICK(d);
+ if (wrch) {
+ CHN_LOCK(wrch);
+ ret = chn_setformat(wrch, (wrch->format & ~AFMT_STEREO) | *arg_i);
+ tmp = (wrch->format & AFMT_STEREO)? 2 : 1;
+ CHN_UNLOCK(wrch);
+ }
+ if (rdch && ret == 0) {
+ CHN_LOCK(rdch);
+ ret = chn_setformat(rdch, (rdch->format & ~AFMT_STEREO) | *arg_i);
+ if (tmp == 0)
+ tmp = (rdch->format & AFMT_STEREO)? 2 : 1;
+ CHN_UNLOCK(rdch);
+ }
+ PCM_RELEASE_QUICK(d);
+ *arg_i = tmp;
+ } else {
+ chn = wrch ? wrch : rdch;
+ CHN_LOCK(chn);
+ *arg_i = (chn->format & AFMT_STEREO) ? 2 : 1;
+ CHN_UNLOCK(chn);
+ }
+ break;
+
+ case SOUND_PCM_READ_CHANNELS:
+ chn = wrch ? wrch : rdch;
+ if (chn) {
+ CHN_LOCK(chn);
+ *arg_i = (chn->format & AFMT_STEREO) ? 2 : 1;
+ CHN_UNLOCK(chn);
+ } else {
+ *arg_i = 0;
+ ret = EINVAL;
+ }
+ break;
+
+ case SNDCTL_DSP_GETFMTS: /* returns a mask of supported fmts */
+ chn = wrch ? wrch : rdch;
+ if (chn) {
+ CHN_LOCK(chn);
+ *arg_i = chn_getformats(chn);
+ CHN_UNLOCK(chn);
+ } else {
+ *arg_i = 0;
+ ret = EINVAL;
+ }
+ break;
+
+ case SNDCTL_DSP_SETFMT: /* sets _one_ format */
+ if ((*arg_i != AFMT_QUERY)) {
+ tmp = 0;
+ PCM_ACQUIRE_QUICK(d);
+ if (wrch) {
+ CHN_LOCK(wrch);
+ ret = chn_setformat(wrch, (*arg_i) | (wrch->format & AFMT_STEREO));
+ tmp = wrch->format & ~AFMT_STEREO;
+ CHN_UNLOCK(wrch);
+ }
+ if (rdch && ret == 0) {
+ CHN_LOCK(rdch);
+ ret = chn_setformat(rdch, (*arg_i) | (rdch->format & AFMT_STEREO));
+ if (tmp == 0)
+ tmp = rdch->format & ~AFMT_STEREO;
+ CHN_UNLOCK(rdch);
+ }
+ PCM_RELEASE_QUICK(d);
+ *arg_i = tmp;
+ } else {
+ chn = wrch ? wrch : rdch;
+ CHN_LOCK(chn);
+ *arg_i = chn->format & ~AFMT_STEREO;
+ CHN_UNLOCK(chn);
+ }
+ break;
+
+ case SNDCTL_DSP_SETFRAGMENT:
+ DEB(printf("SNDCTL_DSP_SETFRAGMENT 0x%08x\n", *(int *)arg));
+ {
+ uint32_t fragln = (*arg_i) & 0x0000ffff;
+ uint32_t maxfrags = ((*arg_i) & 0xffff0000) >> 16;
+ uint32_t fragsz;
+ uint32_t r_maxfrags, r_fragsz;
+
+ RANGE(fragln, 4, 16);
+ fragsz = 1 << fragln;
+
+ if (maxfrags == 0)
+ maxfrags = CHN_2NDBUFMAXSIZE / fragsz;
+ if (maxfrags < 2)
+ maxfrags = 2;
+ if (maxfrags * fragsz > CHN_2NDBUFMAXSIZE)
+ maxfrags = CHN_2NDBUFMAXSIZE / fragsz;
+
+ DEB(printf("SNDCTL_DSP_SETFRAGMENT %d frags, %d sz\n", maxfrags, fragsz));
+ PCM_ACQUIRE_QUICK(d);
+ if (rdch) {
+ CHN_LOCK(rdch);
+ ret = chn_setblocksize(rdch, maxfrags, fragsz);
+ r_maxfrags = sndbuf_getblkcnt(rdch->bufsoft);
+ r_fragsz = sndbuf_getblksz(rdch->bufsoft);
+ CHN_UNLOCK(rdch);
+ } else {
+ r_maxfrags = maxfrags;
+ r_fragsz = fragsz;
+ }
+ if (wrch && ret == 0) {
+ CHN_LOCK(wrch);
+ ret = chn_setblocksize(wrch, maxfrags, fragsz);
+ maxfrags = sndbuf_getblkcnt(wrch->bufsoft);
+ fragsz = sndbuf_getblksz(wrch->bufsoft);
+ CHN_UNLOCK(wrch);
+ } else { /* use whatever came from the read channel */
+ maxfrags = r_maxfrags;
+ fragsz = r_fragsz;
+ }
+ PCM_RELEASE_QUICK(d);
+
+ fragln = 0;
+ while (fragsz > 1) {
+ fragln++;
+ fragsz >>= 1;
+ }
+ *arg_i = (maxfrags << 16) | fragln;
+ }
+ break;
+
+ case SNDCTL_DSP_GETISPACE:
+ /* return the size of data available in the input queue */
+ {
+ audio_buf_info *a = (audio_buf_info *)arg;
+ if (rdch) {
+ struct snd_dbuf *bs = rdch->bufsoft;
+
+ CHN_LOCK(rdch);
+ a->bytes = sndbuf_getready(bs);
+ a->fragments = a->bytes / sndbuf_getblksz(bs);
+ a->fragstotal = sndbuf_getblkcnt(bs);
+ a->fragsize = sndbuf_getblksz(bs);
+ CHN_UNLOCK(rdch);
+ } else
+ ret = EINVAL;
+ }
+ break;
+
+ case SNDCTL_DSP_GETOSPACE:
+ /* return space available in the output queue */
+ {
+ audio_buf_info *a = (audio_buf_info *)arg;
+ if (wrch) {
+ struct snd_dbuf *bs = wrch->bufsoft;
+
+ CHN_LOCK(wrch);
+ /* XXX abusive DMA update: chn_wrupdate(wrch); */
+ a->bytes = sndbuf_getfree(bs);
+ a->fragments = a->bytes / sndbuf_getblksz(bs);
+ a->fragstotal = sndbuf_getblkcnt(bs);
+ a->fragsize = sndbuf_getblksz(bs);
+ CHN_UNLOCK(wrch);
+ } else
+ ret = EINVAL;
+ }
+ break;
+
+ case SNDCTL_DSP_GETIPTR:
+ {
+ count_info *a = (count_info *)arg;
+ if (rdch) {
+ struct snd_dbuf *bs = rdch->bufsoft;
+
+ CHN_LOCK(rdch);
+ /* XXX abusive DMA update: chn_rdupdate(rdch); */
+ a->bytes = sndbuf_gettotal(bs);
+ a->blocks = sndbuf_getblocks(bs) - rdch->blocks;
+ a->ptr = sndbuf_getreadyptr(bs);
+ rdch->blocks = sndbuf_getblocks(bs);
+ CHN_UNLOCK(rdch);
+ } else
+ ret = EINVAL;
+ }
+ break;
+
+ case SNDCTL_DSP_GETOPTR:
+ {
+ count_info *a = (count_info *)arg;
+ if (wrch) {
+ struct snd_dbuf *bs = wrch->bufsoft;
+
+ CHN_LOCK(wrch);
+ /* XXX abusive DMA update: chn_wrupdate(wrch); */
+ a->bytes = sndbuf_gettotal(bs);
+ a->blocks = sndbuf_getblocks(bs) - wrch->blocks;
+ a->ptr = sndbuf_getreadyptr(bs);
+ wrch->blocks = sndbuf_getblocks(bs);
+ CHN_UNLOCK(wrch);
+ } else
+ ret = EINVAL;
+ }
+ break;
+
+ case SNDCTL_DSP_GETCAPS:
+ pcm_lock(d);
+ *arg_i = DSP_CAP_REALTIME | DSP_CAP_MMAP | DSP_CAP_TRIGGER;
+ if (rdch && wrch && !(dsp_get_flags(i_dev) & SD_F_SIMPLEX))
+ *arg_i |= DSP_CAP_DUPLEX;
+ pcm_unlock(d);
+ break;
+
+ case SOUND_PCM_READ_BITS:
+ chn = wrch ? wrch : rdch;
+ if (chn) {
+ CHN_LOCK(chn);
+ if (chn->format & AFMT_8BIT)
+ *arg_i = 8;
+ else if (chn->format & AFMT_16BIT)
+ *arg_i = 16;
+ else if (chn->format & AFMT_24BIT)
+ *arg_i = 24;
+ else if (chn->format & AFMT_32BIT)
+ *arg_i = 32;
+ else
+ ret = EINVAL;
+ CHN_UNLOCK(chn);
+ } else {
+ *arg_i = 0;
+ ret = EINVAL;
+ }
+ break;
+
+ case SNDCTL_DSP_SETTRIGGER:
+ if (rdch) {
+ CHN_LOCK(rdch);
+ rdch->flags &= ~(CHN_F_TRIGGERED | CHN_F_NOTRIGGER);
+ if (*arg_i & PCM_ENABLE_INPUT)
+ chn_start(rdch, 1);
+ else
+ rdch->flags |= CHN_F_NOTRIGGER;
+ CHN_UNLOCK(rdch);
+ }
+ if (wrch) {
+ CHN_LOCK(wrch);
+ wrch->flags &= ~(CHN_F_TRIGGERED | CHN_F_NOTRIGGER);
+ if (*arg_i & PCM_ENABLE_OUTPUT)
+ chn_start(wrch, 1);
+ else
+ wrch->flags |= CHN_F_NOTRIGGER;
+ CHN_UNLOCK(wrch);
+ }
+ break;
+
+ case SNDCTL_DSP_GETTRIGGER:
+ *arg_i = 0;
+ if (wrch) {
+ CHN_LOCK(wrch);
+ if (wrch->flags & CHN_F_TRIGGERED)
+ *arg_i |= PCM_ENABLE_OUTPUT;
+ CHN_UNLOCK(wrch);
+ }
+ if (rdch) {
+ CHN_LOCK(rdch);
+ if (rdch->flags & CHN_F_TRIGGERED)
+ *arg_i |= PCM_ENABLE_INPUT;
+ CHN_UNLOCK(rdch);
+ }
+ break;
+
+ case SNDCTL_DSP_GETODELAY:
+ if (wrch) {
+ struct snd_dbuf *bs = wrch->bufsoft;
+
+ CHN_LOCK(wrch);
+ /* XXX abusive DMA update: chn_wrupdate(wrch); */
+ *arg_i = sndbuf_getready(bs);
+ CHN_UNLOCK(wrch);
+ } else
+ ret = EINVAL;
+ break;
+
+ case SNDCTL_DSP_POST:
+ if (wrch) {
+ CHN_LOCK(wrch);
+ wrch->flags &= ~CHN_F_NOTRIGGER;
+ chn_start(wrch, 1);
+ CHN_UNLOCK(wrch);
+ }
+ break;
+
+ case SNDCTL_DSP_SETDUPLEX:
+ /*
+ * switch to full-duplex mode if card is in half-duplex
+ * mode and is able to work in full-duplex mode
+ */
+ pcm_lock(d);
+ if (rdch && wrch && (dsp_get_flags(i_dev) & SD_F_SIMPLEX))
+ dsp_set_flags(i_dev, dsp_get_flags(i_dev)^SD_F_SIMPLEX);
+ pcm_unlock(d);
+ break;
+
+ /*
+ * The following four ioctls are simple wrappers around mixer_ioctl
+ * with no further processing. xcmd is short for "translated
+ * command".
+ */
+ case SNDCTL_DSP_GETRECVOL:
+ if (xcmd == 0)
+ xcmd = SOUND_MIXER_READ_RECLEV;
+ /* FALLTHROUGH */
+ case SNDCTL_DSP_SETRECVOL:
+ if (xcmd == 0)
+ xcmd = SOUND_MIXER_WRITE_RECLEV;
+ /* FALLTHROUGH */
+ case SNDCTL_DSP_GETPLAYVOL:
+ if (xcmd == 0)
+ xcmd = SOUND_MIXER_READ_PCM;
+ /* FALLTHROUGH */
+ case SNDCTL_DSP_SETPLAYVOL:
+ if (xcmd == 0)
+ xcmd = SOUND_MIXER_WRITE_PCM;
+
+ if (d->mixer_dev != NULL) {
+ PCM_ACQUIRE_QUICK(d);
+ ret = mixer_ioctl_cmd(d->mixer_dev, xcmd, arg, -1, td,
+ MIXER_CMD_DIRECT);
+ PCM_RELEASE_QUICK(d);
+ } else
+ ret = ENOTSUP;
+ break;
+
+ case SNDCTL_DSP_GET_RECSRC_NAMES:
+ case SNDCTL_DSP_GET_RECSRC:
+ case SNDCTL_DSP_SET_RECSRC:
+ if (d->mixer_dev != NULL) {
+ PCM_ACQUIRE_QUICK(d);
+ ret = mixer_ioctl_cmd(d->mixer_dev, cmd, arg, -1, td,
+ MIXER_CMD_DIRECT);
+ PCM_RELEASE_QUICK(d);
+ } else
+ ret = ENOTSUP;
+ break;
+
+ /*
+ * The following 3 ioctls aren't very useful at the moment. For
+ * now, only a single channel is associated with a cdev (/dev/dspN
+ * instance), so there's only a single output routing to use (i.e.,
+ * the wrch bound to this cdev).
+ */
+ case SNDCTL_DSP_GET_PLAYTGT_NAMES:
+ {
+ oss_mixer_enuminfo *ei;
+ ei = (oss_mixer_enuminfo *)arg;
+ ei->dev = 0;
+ ei->ctrl = 0;
+ ei->version = 0; /* static for now */
+ ei->strindex[0] = 0;
+
+ if (wrch != NULL) {
+ ei->nvalues = 1;
+ strlcpy(ei->strings, wrch->name,
+ sizeof(ei->strings));
+ } else {
+ ei->nvalues = 0;
+ ei->strings[0] = '\0';
+ }
+ }
+ break;
+ case SNDCTL_DSP_GET_PLAYTGT:
+ case SNDCTL_DSP_SET_PLAYTGT: /* yes, they are the same for now */
+ /*
+ * Re: SET_PLAYTGT
+ * OSSv4: "The value that was accepted by the device will
+ * be returned back in the variable pointed by the
+ * argument."
+ */
+ if (wrch != NULL)
+ *arg_i = 0;
+ else
+ ret = EINVAL;
+ break;
+
+ case SNDCTL_DSP_SILENCE:
+ /*
+ * Flush the software (pre-feed) buffer, but try to minimize playback
+ * interruption. (I.e., record unplayed samples with intent to
+ * restore by SNDCTL_DSP_SKIP.) Intended for application "pause"
+ * functionality.
+ */
+ if (wrch == NULL)
+ ret = EINVAL;
+ else {
+ struct snd_dbuf *bs;
+ CHN_LOCK(wrch);
+ while (wrch->inprog != 0)
+ cv_wait(&wrch->cv, wrch->lock);
+ bs = wrch->bufsoft;
+ if ((bs->shadbuf != NULL) && (sndbuf_getready(bs) > 0)) {
+ bs->sl = sndbuf_getready(bs);
+ sndbuf_dispose(bs, bs->shadbuf, sndbuf_getready(bs));
+ sndbuf_fillsilence(bs);
+ chn_start(wrch, 0);
+ }
+ CHN_UNLOCK(wrch);
+ }
+ break;
+
+ case SNDCTL_DSP_SKIP:
+ /*
+ * OSSv4 docs: "This ioctl call discards all unplayed samples in the
+ * playback buffer by moving the current write position immediately
+ * before the point where the device is currently reading the samples."
+ */
+ if (wrch == NULL)
+ ret = EINVAL;
+ else {
+ struct snd_dbuf *bs;
+ CHN_LOCK(wrch);
+ while (wrch->inprog != 0)
+ cv_wait(&wrch->cv, wrch->lock);
+ bs = wrch->bufsoft;
+ if ((bs->shadbuf != NULL) && (bs->sl > 0)) {
+ sndbuf_softreset(bs);
+ sndbuf_acquire(bs, bs->shadbuf, bs->sl);
+ bs->sl = 0;
+ chn_start(wrch, 0);
+ }
+ CHN_UNLOCK(wrch);
+ }
+ break;
+
+ case SNDCTL_DSP_CURRENT_OPTR:
+ case SNDCTL_DSP_CURRENT_IPTR:
+ /**
+ * @note Changing formats resets the buffer counters, which differs
+ * from the 4Front drivers. However, I don't expect this to be
+ * much of a problem.
+ *
+ * @note In a test where @c CURRENT_OPTR is called immediately after write
+ * returns, this driver is about 32K samples behind whereas
+ * 4Front's is about 8K samples behind. Should determine source
+ * of discrepancy, even if only out of curiosity.
+ *
+ * @todo Actually test SNDCTL_DSP_CURRENT_IPTR.
+ */
+ chn = (cmd == SNDCTL_DSP_CURRENT_OPTR) ? wrch : rdch;
+ if (chn == NULL)
+ ret = EINVAL;
+ else {
+ struct snd_dbuf *bs;
+ /* int tmp; */
-case SNDCTL_DSP_SETDUPLEX:
-/*
-* switch to full-duplex mode if card is in half-duplex
-* mode and is able to work in full-duplex mode
-*/
-if (rdch && wrch && (dsp_get_flags(i_dev) & SD_F_SIMPLEX))
-dsp_set_flags(i_dev, dsp_get_flags(i_dev)^SD_F_SIMPLEX);
-break;
-
-case SNDCTL_DSP_MAPINBUF:
-case SNDCTL_DSP_MAPOUTBUF:
-case SNDCTL_DSP_SETSYNCRO:
-/* undocumented */
-
-case SNDCTL_DSP_SUBDIVIDE:
-case SOUND_PCM_WRITE_FILTER:
-case SOUND_PCM_READ_FILTER:
-/* dunno what these do, don't sound important */
-
-default:
-DEB(printf("default ioctl fn 0x%08lx failn", cmd));
-ret = EINVAL;
-break;
-}
-relchns(i_dev, rdch, wrch, 0);
-return ret;
+ oss_count_t *oc = (oss_count_t *)arg;
+
+ CHN_LOCK(chn);
+ bs = chn->bufsoft;
+#if 0
+ tmp = (sndbuf_getsize(b) + chn_getptr(chn) - sndbuf_gethwptr(b)) % sndbuf_getsize(b);
+ oc->samples = (sndbuf_gettotal(b) + tmp) / sndbuf_getbps(b);
+ oc->fifo_samples = (sndbuf_getready(b) - tmp) / sndbuf_getbps(b);
+#else
+ oc->samples = sndbuf_gettotal(bs) / sndbuf_getbps(bs);
+ oc->fifo_samples = sndbuf_getready(bs) / sndbuf_getbps(bs);
+#endif
+ CHN_UNLOCK(chn);
+ }
+ break;
+
+ case SNDCTL_DSP_HALT_OUTPUT:
+ case SNDCTL_DSP_HALT_INPUT:
+ chn = (cmd == SNDCTL_DSP_HALT_OUTPUT) ? wrch : rdch;
+ if (chn == NULL)
+ ret = EINVAL;
+ else {
+ CHN_LOCK(chn);
+ chn_abort(chn);
+ CHN_UNLOCK(chn);
+ }
+ break;
+
+ case SNDCTL_DSP_LOW_WATER:
+ /*
+ * Set the number of bytes required to attract attention by
+ * select/poll.
+ */
+ if (wrch != NULL) {
+ CHN_LOCK(wrch);
+ wrch->lw = (*arg_i > 1) ? *arg_i : 1;
+ CHN_UNLOCK(wrch);
+ }
+ if (rdch != NULL) {
+ CHN_LOCK(rdch);
+ rdch->lw = (*arg_i > 1) ? *arg_i : 1;
+ CHN_UNLOCK(rdch);
+ }
+ break;
+
+ case SNDCTL_DSP_GETERROR:
+ /*
+ * OSSv4 docs: "All errors and counters will automatically be
+ * cleared to zeroes after the call so each call will return only
+ * the errors that occurred after the previous invocation. ... The
+ * play_underruns and rec_overrun fields are the only usefull fields
+ * returned by OSS 4.0."
+ */
+ {
+ audio_errinfo *ei = (audio_errinfo *)arg;
+
+ bzero((void *)ei, sizeof(*ei));
+
+ if (wrch != NULL) {
+ CHN_LOCK(wrch);
+ ei->play_underruns = wrch->xruns;
+ wrch->xruns = 0;
+ CHN_UNLOCK(wrch);
+ }
+ if (rdch != NULL) {
+ CHN_LOCK(rdch);
+ ei->rec_overruns = rdch->xruns;
+ rdch->xruns = 0;
+ CHN_UNLOCK(rdch);
+ }
+ }
+ break;
+
+ case SNDCTL_DSP_SYNCGROUP:
+ PCM_ACQUIRE_QUICK(d);
+ ret = dsp_oss_syncgroup(wrch, rdch, (oss_syncgroup *)arg);
+ PCM_RELEASE_QUICK(d);
+ break;
+
+ case SNDCTL_DSP_SYNCSTART:
+ PCM_ACQUIRE_QUICK(d);
+ ret = dsp_oss_syncstart(*arg_i);
+ PCM_RELEASE_QUICK(d);
+ break;
+
+ case SNDCTL_DSP_POLICY:
+ PCM_ACQUIRE_QUICK(d);
+ ret = dsp_oss_policy(wrch, rdch, *arg_i);
+ PCM_RELEASE_QUICK(d);
+ break;
+
+#ifdef OSSV4_EXPERIMENT
+ /*
+ * XXX The following ioctls are not yet supported and just return
+ * EINVAL.
+ */
+ case SNDCTL_DSP_GETOPEAKS:
+ case SNDCTL_DSP_GETIPEAKS:
+ chn = (cmd == SNDCTL_DSP_GETOPEAKS) ? wrch : rdch;
+ if (chn == NULL)
+ ret = EINVAL;
+ else {
+ oss_peaks_t *op = (oss_peaks_t *)arg;
+ int lpeak, rpeak;
+
+ CHN_LOCK(chn);
+ ret = chn_getpeaks(chn, &lpeak, &rpeak);
+ if (ret == -1)
+ ret = EINVAL;
+ else {
+ (*op)[0] = lpeak;
+ (*op)[1] = rpeak;
+ }
+ CHN_UNLOCK(chn);
+ }
+ break;
+
+ /*
+ * XXX Once implemented, revisit this for proper cv protection
+ * (if necessary).
+ */
+ case SNDCTL_DSP_COOKEDMODE:
+ ret = dsp_oss_cookedmode(wrch, rdch, *arg_i);
+ break;
+ case SNDCTL_DSP_GET_CHNORDER:
+ ret = dsp_oss_getchnorder(wrch, rdch, (unsigned long long *)arg);
+ break;
+ case SNDCTL_DSP_SET_CHNORDER:
+ ret = dsp_oss_setchnorder(wrch, rdch, (unsigned long long *)arg);
+ break;
+ case SNDCTL_GETLABEL:
+ ret = dsp_oss_getlabel(wrch, rdch, (oss_label_t *)arg);
+ break;
+ case SNDCTL_SETLABEL:
+ ret = dsp_oss_setlabel(wrch, rdch, (oss_label_t *)arg);
+ break;
+ case SNDCTL_GETSONG:
+ ret = dsp_oss_getsong(wrch, rdch, (oss_longname_t *)arg);
+ break;
+ case SNDCTL_SETSONG:
+ ret = dsp_oss_setsong(wrch, rdch, (oss_longname_t *)arg);
+ break;
+ case SNDCTL_SETNAME:
+ ret = dsp_oss_setname(wrch, rdch, (oss_longname_t *)arg);
+ break;
+#if 0
+ /**
+ * @note The SNDCTL_CARDINFO ioctl was omitted per 4Front developer
+ * documentation. "The usability of this call is very limited. It's
+ * provided only for completeness of the API. OSS API doesn't have
+ * any concept of card. Any information returned by this ioctl calld
+ * is reserved exclusively for the utility programs included in the
+ * OSS package. Applications should not try to use for this
+ * information in any ways."
+ */
+ case SNDCTL_CARDINFO:
+ ret = EINVAL;
+ break;
+ /**
+ * @note The S/PDIF interface ioctls, @c SNDCTL_DSP_READCTL and
+ * @c SNDCTL_DSP_WRITECTL have been omitted at the suggestion of
+ * 4Front Technologies.
+ */
+ case SNDCTL_DSP_READCTL:
+ case SNDCTL_DSP_WRITECTL:
+ ret = EINVAL;
+ break;
+#endif /* !0 (explicitly omitted ioctls) */
+
+#endif /* !OSSV4_EXPERIMENT */
+ case SNDCTL_DSP_MAPINBUF:
+ case SNDCTL_DSP_MAPOUTBUF:
+ case SNDCTL_DSP_SETSYNCRO:
+ /* undocumented */
+
+ case SNDCTL_DSP_SUBDIVIDE:
+ case SOUND_PCM_WRITE_FILTER:
+ case SOUND_PCM_READ_FILTER:
+ /* dunno what these do, don't sound important */
+
+ default:
+ DEB(printf("default ioctl fn 0x%08lx fail\n", cmd));
+ ret = EINVAL;
+ break;
+ }
+
+ relchns(i_dev, rdch, wrch, 0);
+
+ PCM_GIANT_LEAVE(d);
+
+ return (ret);
}
static int
dsp_poll(struct cdev *i_dev, int events, struct thread *td)
{
-struct pcm_channel *wrch = NULL, *rdch = NULL;
-int ret, e;
+ struct snddev_info *d;
+ struct pcm_channel *wrch, *rdch;
+ int ret, e;
-ret = 0;
-getchns(i_dev, &rdch, &wrch, SD_F_PRIO_RD | SD_F_PRIO_WR);
+ d = dsp_get_info(i_dev);
+ if (!DSP_REGISTERED(d, i_dev))
+ return (EBADF);
-if (wrch) {
-e = (events & (POLLOUT | POLLWRNORM));
-if (e)
-ret |= chn_poll(wrch, e, td);
-}
-if (rdch) {
-e = (events & (POLLIN | POLLRDNORM));
-if (e)
-ret |= chn_poll(rdch, e, td);
-}
-relchns(i_dev, rdch, wrch, SD_F_PRIO_RD | SD_F_PRIO_WR);
+ PCM_GIANT_ENTER(d);
+
+ wrch = NULL;
+ rdch = NULL;
+ ret = 0;
+
+ getchns(i_dev, &rdch, &wrch, SD_F_PRIO_RD | SD_F_PRIO_WR);
-return ret;
+ if (wrch != NULL && !(wrch->flags & CHN_F_DEAD)) {
+ e = (events & (POLLOUT | POLLWRNORM));
+ if (e)
+ ret |= chn_poll(wrch, e, td);
+ }
+
+ if (rdch != NULL && !(rdch->flags & CHN_F_DEAD)) {
+ e = (events & (POLLIN | POLLRDNORM));
+ if (e)
+ ret |= chn_poll(rdch, e, td);
+ }
+
+ relchns(i_dev, rdch, wrch, SD_F_PRIO_RD | SD_F_PRIO_WR);
+
+ PCM_GIANT_LEAVE(d);
+
+ return (ret);
}
static int
dsp_mmap(struct cdev *i_dev, vm_offset_t offset, vm_paddr_t *paddr, int nprot)
{
-struct pcm_channel *wrch = NULL, *rdch = NULL, *c;
+ struct snddev_info *d;
+ struct pcm_channel *wrch, *rdch, *c;
-if (nprot & PROT_EXEC)
-return -1;
+ /*
+ * Reject PROT_EXEC by default. It just doesn't makes sense.
+ * Unfortunately, we have to give up this one due to linux_mmap
+ * changes.
+ *
+ * http://lists.freebsd.org/pipermail/freebsd-emulation/2007-June/003698.html
+ *
+ */
+ if ((nprot & PROT_EXEC) && dsp_mmap_allow_prot_exec == 0)
+ return (-1);
+
+ d = dsp_get_info(i_dev);
+ if (!DSP_REGISTERED(d, i_dev))
+ return (-1);
+
+ PCM_GIANT_ENTER(d);
+
+ getchns(i_dev, &rdch, &wrch, SD_F_PRIO_RD | SD_F_PRIO_WR);
+
+ /*
+ * XXX The linux api uses the nprot to select read/write buffer
+ * our vm system doesn't allow this, so force write buffer.
+ *
+ * This is just a quack to fool full-duplex mmap, so that at
+ * least playback _or_ recording works. If you really got the
+ * urge to make _both_ work at the same time, avoid O_RDWR.
+ * Just open each direction separately and mmap() it.
+ *
+ * Failure is not an option due to INVARIANTS check within
+ * device_pager.c, which means, we have to give up one over
+ * another.
+ */
+ c = (wrch != NULL) ? wrch : rdch;
+
+ if (c == NULL || (c->flags & CHN_F_MMAP_INVALID) ||
+ offset >= sndbuf_getsize(c->bufsoft) ||
+ (wrch != NULL && (wrch->flags & CHN_F_MMAP_INVALID)) ||
+ (rdch != NULL && (rdch->flags & CHN_F_MMAP_INVALID))) {
+ relchns(i_dev, rdch, wrch, SD_F_PRIO_RD | SD_F_PRIO_WR);
+ PCM_GIANT_EXIT(d);
+ return (-1);
+ }
+
+ /* XXX full-duplex quack. */
+ if (wrch != NULL)
+ wrch->flags |= CHN_F_MAPPED;
+ if (rdch != NULL)
+ rdch->flags |= CHN_F_MAPPED;
-getchns(i_dev, &rdch, &wrch, SD_F_PRIO_RD | SD_F_PRIO_WR);
-#if 0
-/*
-* XXX the linux api uses the nprot to select read/write buffer
-* our vm system doesn't allow this, so force write buffer
-*/
+ *paddr = vtophys(sndbuf_getbufofs(c->bufsoft, offset));
+ relchns(i_dev, rdch, wrch, SD_F_PRIO_RD | SD_F_PRIO_WR);
-if (wrch && (nprot & PROT_WRITE)) {
-c = wrch;
-} else if (rdch && (nprot & PROT_READ)) {
-c = rdch;
-} else {
-return -1;
-}
-#else
-c = wrch;
-#endif
+ PCM_GIANT_LEAVE(d);
-if (c == NULL) {
-relchns(i_dev, rdch, wrch, SD_F_PRIO_RD | SD_F_PRIO_WR);
-return -1;
+ return (0);
}
-if (offset >= sndbuf_getsize(c->bufsoft)) {
-relchns(i_dev, rdch, wrch, SD_F_PRIO_RD | SD_F_PRIO_WR);
-return -1;
-}
+#ifdef USING_DEVFS
-if (!(c->flags & CHN_F_MAPPED))
-c->flags |= CHN_F_MAPPED;
+/* So much for dev_stdclone() */
+static int
+dsp_stdclone(char *name, char *namep, char *sep, int use_sep, int *u, int *c)
+{
+ size_t len;
-*paddr = vtophys(sndbuf_getbufofs(c->bufsoft, offset));
-relchns(i_dev, rdch, wrch, SD_F_PRIO_RD | SD_F_PRIO_WR);
+ len = strlen(namep);
-return 0;
-}
+ if (bcmp(name, namep, len) != 0)
+ return (ENODEV);
-#ifdef USING_DEVFS
+ name += len;
+
+ if (isdigit(*name) == 0)
+ return (ENODEV);
+
+ len = strlen(sep);
+
+ if (*name == '0' && !(name[1] == '\0' || bcmp(name + 1, sep, len) == 0))
+ return (ENODEV);
+
+ for (*u = 0; isdigit(*name) != 0; name++) {
+ *u *= 10;
+ *u += *name - '0';
+ if (*u > dsp_umax)
+ return (ENODEV);
+ }
+
+ if (*name == '\0')
+ return ((use_sep == 0) ? 0 : ENODEV);
+
+ if (bcmp(name, sep, len) != 0 || isdigit(name[len]) == 0)
+ return (ENODEV);
+
+ name += len;
+
+ if (*name == '0' && name[1] != '\0')
+ return (ENODEV);
+
+ for (*c = 0; isdigit(*name) != 0; name++) {
+ *c *= 10;
+ *c += *name - '0';
+ if (*c > dsp_cmax)
+ return (ENODEV);
+ }
+
+ if (*name != '\0')
+ return (ENODEV);
+
+ return (0);
+}
-/*
-* Clone logic is this:
-* x E X = {dsp, dspW, audio}
-* x -> x${sysctl("hw.snd.unit")}
-* xN->
-* for i N = 1 to channels of device N
-* if xN.i isn't busy, return its dev_t
-*/
static void
-dsp_clone(void *arg, struct ucred *cred, char *name, int namelen,
-struct cdev **dev)
+dsp_clone(void *arg,
+#if __FreeBSD_version >= 600034
+ struct ucred *cred,
+#endif
+ char *name, int namelen, struct cdev **dev)
{
-struct cdev *pdev;
-struct snddev_info *pcm_dev;
-struct snddev_channel *pcm_chan;
-int i, unit, devtype;
-static int devtypes[3] = {SND_DEV_DSP, SND_DEV_DSP16, SND_DEV_AUDIO};
-static char *devnames[3] = {"dsp", "dspW", "audio"};
-
-if (*dev != NULL)
-return;
-if (pcm_devclass == NULL)
-return;
-
-devtype = 0;
-unit = -1;
-for (i = 0; (i < 3) && (unit == -1); i++) {
-devtype = devtypes[i];
-if (strcmp(name, devnames[i]) == 0) {
-unit = snd_unit;
-} else {
-if (dev_stdclone(name, NULL, devnames[i], &unit) != 1)
-unit = -1;
-}
-}
-if (unit == -1 || unit >= devclass_get_maxunit(pcm_devclass))
-return;
-
-pcm_dev = devclass_get_softc(pcm_devclass, unit);
-
-if (pcm_dev == NULL)
-return;
-
-SLIST_FOREACH(pcm_chan, &pcm_dev->channels, link) {
-
-switch(devtype) {
-case SND_DEV_DSP:
-pdev = pcm_chan->dsp_devt;
-break;
-case SND_DEV_DSP16:
-pdev = pcm_chan->dspW_devt;
-break;
-case SND_DEV_AUDIO:
-pdev = pcm_chan->audio_devt;
-break;
-default:
-panic("Unknown devtype %d", devtype);
-}
-
-if ((pdev != NULL) && (pdev->si_drv1 == NULL) && (pdev->si_drv2 == NULL)) {
-*dev = pdev;
-dev_ref(*dev);
-return;
-}
-}
+ struct snddev_info *d;
+ struct snd_clone_entry *ce;
+ struct pcm_channel *c;
+ int i, unit, udcmask, cunit, devtype, devhw, devcmax, tumax;
+ char *devname, *devsep;
+
+ KASSERT(dsp_umax >= 0 && dsp_cmax >= 0, ("Uninitialized unit!"));
+
+ if (*dev != NULL)
+ return;
+
+ unit = -1;
+ cunit = -1;
+ devtype = -1;
+ devhw = 0;
+ devcmax = -1;
+ tumax = -1;
+ devname = NULL;
+ devsep = NULL;
+
+ for (i = 0; unit == -1 &&
+ i < (sizeof(dsp_cdevs) / sizeof(dsp_cdevs[0])); i++) {
+ devtype = dsp_cdevs[i].type;
+ devname = dsp_cdevs[i].name;
+ devsep = dsp_cdevs[i].sep;
+ devhw = dsp_cdevs[i].hw;
+ devcmax = dsp_cdevs[i].max - 1;
+ if (strcmp(name, devname) == 0)
+ unit = snd_unit;
+ else if (dsp_stdclone(name, devname, devsep,
+ dsp_cdevs[i].use_sep, &unit, &cunit) != 0) {
+ unit = -1;
+ cunit = -1;
+ }
+ }
+
+ d = devclass_get_softc(pcm_devclass, unit);
+ if (!PCM_REGISTERED(d) || d->clones == NULL)
+ return;
+
+ /* XXX Need Giant magic entry ??? */
+
+ pcm_lock(d);
+ if (snd_clone_disabled(d->clones)) {
+ pcm_unlock(d);
+ return;
+ }
+
+ PCM_WAIT(d);
+ PCM_ACQUIRE(d);
+ pcm_unlock(d);
+
+ udcmask = snd_u2unit(unit) | snd_d2unit(devtype);
+
+ if (devhw != 0) {
+ KASSERT(devcmax <= dsp_cmax,
+ ("overflow: devcmax=%d, dsp_cmax=%d", devcmax, dsp_cmax));
+ if (cunit > devcmax) {
+ PCM_RELEASE_QUICK(d);
+ return;
+ }
+ udcmask |= snd_c2unit(cunit);
+ CHN_FOREACH(c, d, channels.pcm) {
+ CHN_LOCK(c);
+ if (c->unit != udcmask) {
+ CHN_UNLOCK(c);
+ continue;
+ }
+ CHN_UNLOCK(c);
+ udcmask &= ~snd_c2unit(cunit);
+ /*
+ * Temporarily increase clone maxunit to overcome
+ * vchan flexibility.
+ *
+ * # sysctl dev.pcm.0.play.vchans=256
+ * dev.pcm.0.play.vchans: 1 -> 256
+ * # cat /dev/zero > /dev/dsp0.vp255 &
+ * [1] 17296
+ * # sysctl dev.pcm.0.play.vchans=0
+ * dev.pcm.0.play.vchans: 256 -> 1
+ * # fg
+ * [1] + running cat /dev/zero > /dev/dsp0.vp255
+ * ^C
+ * # cat /dev/zero > /dev/dsp0.vp255
+ * zsh: operation not supported: /dev/dsp0.vp255
+ */
+ tumax = snd_clone_getmaxunit(d->clones);
+ if (cunit > tumax)
+ snd_clone_setmaxunit(d->clones, cunit);
+ else
+ tumax = -1;
+ goto dsp_clone_alloc;
+ }
+ /*
+ * Ok, so we're requesting unallocated vchan, but still
+ * within maximum vchan limit.
+ */
+ if (((devtype == SND_DEV_DSPHW_VPLAY && d->pvchancount > 0) ||
+ (devtype == SND_DEV_DSPHW_VREC && d->rvchancount > 0)) &&
+ cunit < snd_maxautovchans) {
+ udcmask &= ~snd_c2unit(cunit);
+ tumax = snd_clone_getmaxunit(d->clones);
+ if (cunit > tumax)
+ snd_clone_setmaxunit(d->clones, cunit);
+ else
+ tumax = -1;
+ goto dsp_clone_alloc;
+ }
+ PCM_RELEASE_QUICK(d);
+ return;
+ }
+
+dsp_clone_alloc:
+ ce = snd_clone_alloc(d->clones, dev, &cunit, udcmask);
+ if (tumax != -1)
+ snd_clone_setmaxunit(d->clones, tumax);
+ if (ce != NULL) {
+ udcmask |= snd_c2unit(cunit);
+ *dev = make_dev(&dsp_cdevsw, unit2minor(udcmask),
+ UID_ROOT, GID_WHEEL, 0666, "%s%d%s%d",
+ devname, unit, devsep, cunit);
+ snd_clone_register(ce, *dev);
+ }
+
+ PCM_RELEASE_QUICK(d);
+
+ if (*dev != NULL)
+ dev_ref(*dev);
}
static void
dsp_sysinit(void *p)
{
-dsp_ehtag = EVENTHANDLER_REGISTER(dev_clone, dsp_clone, 0, 1000);
+ if (dsp_ehtag != NULL)
+ return;
+ /* initialize unit numbering */
+ snd_unit_init();
+ dsp_umax = PCMMAXUNIT;
+ dsp_cmax = PCMMAXCHAN;
+ dsp_ehtag = EVENTHANDLER_REGISTER(dev_clone, dsp_clone, 0, 1000);
}
static void
dsp_sysuninit(void *p)
{
-if (dsp_ehtag != NULL)
-EVENTHANDLER_DEREGISTER(dev_clone, dsp_ehtag);
+ if (dsp_ehtag == NULL)
+ return;
+ EVENTHANDLER_DEREGISTER(dev_clone, dsp_ehtag);
+ dsp_ehtag = NULL;
}
SYSINIT(dsp_sysinit, SI_SUB_DRIVERS, SI_ORDER_MIDDLE, dsp_sysinit, NULL);
SYSUNINIT(dsp_sysuninit, SI_SUB_DRIVERS, SI_ORDER_MIDDLE, dsp_sysuninit, NULL);
#endif
+char *
+dsp_unit2name(char *buf, size_t len, int unit)
+{
+ int i, dtype;
+
+ KASSERT(buf != NULL && len != 0,
+ ("bogus buf=%p len=%ju", buf, (uintmax_t)len));
+ dtype = snd_unit2d(unit);
+
+ for (i = 0; i < (sizeof(dsp_cdevs) / sizeof(dsp_cdevs[0])); i++) {
+ if (dtype != dsp_cdevs[i].type)
+ continue;
+ snprintf(buf, len, "%s%d%s%d", dsp_cdevs[i].name,
+ snd_unit2u(unit), dsp_cdevs[i].sep, snd_unit2c(unit));
+ return (buf);
+ }
+
+ return (NULL);
+}
+
+/**
+ * @brief Handler for SNDCTL_AUDIOINFO.
+ *
+ * Gathers information about the audio device specified in ai->dev. If
+ * ai->dev == -1, then this function gathers information about the current
+ * device. If the call comes in on a non-audio device and ai->dev == -1,
+ * return EINVAL.
+ *
+ * This routine is supposed to go practically straight to the hardware,
+ * getting capabilities directly from the sound card driver, side-stepping
+ * the intermediate channel interface.
+ *
+ * Note, however, that the usefulness of this command is significantly
+ * decreased when requesting info about any device other than the one serving
+ * the request. While each snddev_channel refers to a specific device node,
+ * the converse is *not* true. Currently, when a sound device node is opened,
+ * the sound subsystem scans for an available audio channel (or channels, if
+ * opened in read+write) and then assigns them to the si_drv[12] private
+ * data fields. As a result, any information returned linking a channel to
+ * a specific character device isn't necessarily accurate.
+ *
+ * @note
+ * Calling threads must not hold any snddev_info or pcm_channel locks.
+ *
+ * @param dev device on which the ioctl was issued
+ * @param ai ioctl request data container
+ *
+ * @retval 0 success
+ * @retval EINVAL ai->dev specifies an invalid device
+ *
+ * @todo Verify correctness of Doxygen tags. ;)
+ */
+int
+dsp_oss_audioinfo(struct cdev *i_dev, oss_audioinfo *ai)
+{
+ struct pcmchan_caps *caps;
+ struct pcm_channel *ch;
+ struct snddev_info *d;
+ uint32_t fmts;
+ int i, nchan, *rates, minch, maxch;
+ char *devname, buf[CHN_NAMELEN];
+
+ /*
+ * If probing the device that received the ioctl, make sure it's a
+ * DSP device. (Users may use this ioctl with /dev/mixer and
+ * /dev/midi.)
+ */
+ if (ai->dev == -1 && i_dev->si_devsw != &dsp_cdevsw)
+ return (EINVAL);
+
+ ch = NULL;
+ devname = NULL;
+ nchan = 0;
+ bzero(buf, sizeof(buf));
+
+ /*
+ * Search for the requested audio device (channel). Start by
+ * iterating over pcm devices.
+ */
+ for (i = 0; pcm_devclass != NULL &&
+ i < devclass_get_maxunit(pcm_devclass); i++) {
+ d = devclass_get_softc(pcm_devclass, i);
+ if (!PCM_REGISTERED(d))
+ continue;
+
+ /* XXX Need Giant magic entry ??? */
+
+ /* See the note in function docblock */
+ mtx_assert(d->lock, MA_NOTOWNED);
+ pcm_lock(d);
+
+ CHN_FOREACH(ch, d, channels.pcm) {
+ mtx_assert(ch->lock, MA_NOTOWNED);
+ CHN_LOCK(ch);
+ if (ai->dev == -1) {
+ if (DSP_REGISTERED(d, i_dev) &&
+ (ch == PCM_RDCH(i_dev) || /* record ch */
+ ch == PCM_WRCH(i_dev))) { /* playback ch */
+ devname = dsp_unit2name(buf,
+ sizeof(buf), ch->unit);
+ }
+ } else if (ai->dev == nchan) {
+ devname = dsp_unit2name(buf, sizeof(buf),
+ ch->unit);
+ }
+ if (devname != NULL)
+ break;
+ CHN_UNLOCK(ch);
+ ++nchan;
+ }
+
+ if (devname != NULL) {
+ /*
+ * At this point, the following synchronization stuff
+ * has happened:
+ * - a specific PCM device is locked.
+ * - a specific audio channel has been locked, so be
+ * sure to unlock when exiting;
+ */
+
+ caps = chn_getcaps(ch);
+
+ /*
+ * With all handles collected, zero out the user's
+ * container and begin filling in its fields.
+ */
+ bzero((void *)ai, sizeof(oss_audioinfo));
+
+ ai->dev = nchan;
+ strlcpy(ai->name, ch->name, sizeof(ai->name));
+
+ if ((ch->flags & CHN_F_BUSY) == 0)
+ ai->busy = 0;
+ else
+ ai->busy = (ch->direction == PCMDIR_PLAY) ? OPEN_WRITE : OPEN_READ;
+
+ /**
+ * @note
+ * @c cmd - OSSv4 docs: "Only supported under Linux at
+ * this moment." Cop-out, I know, but I'll save
+ * running around in the process table for later.
+ * Is there a risk of leaking information?
+ */
+ ai->pid = ch->pid;
+
+ /*
+ * These flags stolen from SNDCTL_DSP_GETCAPS handler.
+ * Note, however, that a single channel operates in
+ * only one direction, so DSP_CAP_DUPLEX is out.
+ */
+ /**
+ * @todo @c SNDCTL_AUDIOINFO::caps - Make drivers keep
+ * these in pcmchan::caps?
+ */
+ ai->caps = DSP_CAP_REALTIME | DSP_CAP_MMAP | DSP_CAP_TRIGGER;
+
+ /*
+ * Collect formats supported @b natively by the
+ * device. Also determine min/max channels. (I.e.,
+ * mono, stereo, or both?)
+ *
+ * If any channel is stereo, maxch = 2;
+ * if all channels are stereo, minch = 2, too;
+ * if any channel is mono, minch = 1;
+ * and if all channels are mono, maxch = 1.
+ */
+ minch = 0;
+ maxch = 0;
+ fmts = 0;
+ for (i = 0; caps->fmtlist[i]; i++) {
+ fmts |= caps->fmtlist[i];
+ if (caps->fmtlist[i] & AFMT_STEREO) {
+ minch = (minch == 0) ? 2 : minch;
+ maxch = 2;
+ } else {
+ minch = 1;
+ maxch = (maxch == 0) ? 1 : maxch;
+ }
+ }
+
+ if (ch->direction == PCMDIR_PLAY)
+ ai->oformats = fmts;
+ else
+ ai->iformats = fmts;
+
+ /**
+ * @note
+ * @c magic - OSSv4 docs: "Reserved for internal use
+ * by OSS."
+ *
+ * @par
+ * @c card_number - OSSv4 docs: "Number of the sound
+ * card where this device belongs or -1 if this
+ * information is not available. Applications
+ * should normally not use this field for any
+ * purpose."
+ */
+ ai->card_number = -1;
+ /**
+ * @todo @c song_name - depends first on
+ * SNDCTL_[GS]ETSONG @todo @c label - depends
+ * on SNDCTL_[GS]ETLABEL
+ * @todo @c port_number - routing information?
+ */
+ ai->port_number = -1;
+ ai->mixer_dev = (d->mixer_dev != NULL) ? PCMUNIT(d->mixer_dev) : -1;
+ /**
+ * @note
+ * @c real_device - OSSv4 docs: "Obsolete."
+ */
+ ai->real_device = -1;
+ strlcpy(ai->devnode, devname, sizeof(ai->devnode));
+ ai->enabled = device_is_attached(d->dev) ? 1 : 0;
+ /**
+ * @note
+ * @c flags - OSSv4 docs: "Reserved for future use."
+ *
+ * @note
+ * @c binding - OSSv4 docs: "Reserved for future use."
+ *
+ * @todo @c handle - haven't decided how to generate
+ * this yet; bus, vendor, device IDs?
+ */
+ ai->min_rate = caps->minspeed;
+ ai->max_rate = caps->maxspeed;
+
+ ai->min_channels = minch;
+ ai->max_channels = maxch;
+
+ ai->nrates = chn_getrates(ch, &rates);
+ if (ai->nrates > OSS_MAX_SAMPLE_RATES)
+ ai->nrates = OSS_MAX_SAMPLE_RATES;
+
+ for (i = 0; i < ai->nrates; i++)
+ ai->rates[i] = rates[i];
+
+ CHN_UNLOCK(ch);
+ }
+
+ pcm_unlock(d);
+
+ if (devname != NULL)
+ return (0);
+ }
+
+ /* Exhausted the search -- nothing is locked, so return. */
+ return (EINVAL);
+}
+
+/**
+ * @brief Assigns a PCM channel to a sync group.
+ *
+ * Sync groups are used to enable audio operations on multiple devices
+ * simultaneously. They may be used with any number of devices and may
+ * span across applications. Devices are added to groups with
+ * the SNDCTL_DSP_SYNCGROUP ioctl, and operations are triggered with the
+ * SNDCTL_DSP_SYNCSTART ioctl.
+ *
+ * If the @c id field of the @c group parameter is set to zero, then a new
+ * sync group is created. Otherwise, wrch and rdch (if set) are added to
+ * the group specified.
+ *
+ * @todo As far as memory allocation, should we assume that things are
+ * okay and allocate with M_WAITOK before acquiring channel locks,
+ * freeing later if not?
+ *
+ * @param wrch output channel associated w/ device (if any)
+ * @param rdch input channel associated w/ device (if any)
+ * @param group Sync group parameters
+ *
+ * @retval 0 success
+ * @retval non-zero error to be propagated upstream
+ */
+static int
+dsp_oss_syncgroup(struct pcm_channel *wrch, struct pcm_channel *rdch, oss_syncgroup *group)
+{
+ struct pcmchan_syncmember *smrd, *smwr;
+ struct pcmchan_syncgroup *sg;
+ int ret, sg_ids[3];
+
+ smrd = NULL;
+ smwr = NULL;
+ sg = NULL;
+ ret = 0;
+
+ /*
+ * Free_unr() may sleep, so store released syncgroup IDs until after
+ * all locks are released.
+ */
+ sg_ids[0] = sg_ids[1] = sg_ids[2] = 0;
+
+ PCM_SG_LOCK();
+
+ /*
+ * - Insert channel(s) into group's member list.
+ * - Set CHN_F_NOTRIGGER on channel(s).
+ * - Stop channel(s).
+ */
+
+ /*
+ * If device's channels are already mapped to a group, unmap them.
+ */
+ if (wrch) {
+ CHN_LOCK(wrch);
+ sg_ids[0] = chn_syncdestroy(wrch);
+ }
+
+ if (rdch) {
+ CHN_LOCK(rdch);
+ sg_ids[1] = chn_syncdestroy(rdch);
+ }
+
+ /*
+ * Verify that mode matches character device properites.
+ * - Bail if PCM_ENABLE_OUTPUT && wrch == NULL.
+ * - Bail if PCM_ENABLE_INPUT && rdch == NULL.
+ */
+ if (((wrch == NULL) && (group->mode & PCM_ENABLE_OUTPUT)) ||
+ ((rdch == NULL) && (group->mode & PCM_ENABLE_INPUT))) {
+ ret = EINVAL;
+ goto out;
+ }
+
+ /*
+ * An id of zero indicates the user wants to create a new
+ * syncgroup.
+ */
+ if (group->id == 0) {
+ sg = (struct pcmchan_syncgroup *)malloc(sizeof(*sg), M_DEVBUF, M_NOWAIT);
+ if (sg != NULL) {
+ SLIST_INIT(&sg->members);
+ sg->id = alloc_unr(pcmsg_unrhdr);
+
+ group->id = sg->id;
+ SLIST_INSERT_HEAD(&snd_pcm_syncgroups, sg, link);
+ } else
+ ret = ENOMEM;
+ } else {
+ SLIST_FOREACH(sg, &snd_pcm_syncgroups, link) {
+ if (sg->id == group->id)
+ break;
+ }
+ if (sg == NULL)
+ ret = EINVAL;
+ }
+
+ /* Couldn't create or find a syncgroup. Fail. */
+ if (sg == NULL)
+ goto out;
+
+ /*
+ * Allocate a syncmember, assign it and a channel together, and
+ * insert into syncgroup.
+ */
+ if (group->mode & PCM_ENABLE_INPUT) {
+ smrd = (struct pcmchan_syncmember *)malloc(sizeof(*smrd), M_DEVBUF, M_NOWAIT);
+ if (smrd == NULL) {
+ ret = ENOMEM;
+ goto out;
+ }
+
+ SLIST_INSERT_HEAD(&sg->members, smrd, link);
+ smrd->parent = sg;
+ smrd->ch = rdch;
+
+ chn_abort(rdch);
+ rdch->flags |= CHN_F_NOTRIGGER;
+ rdch->sm = smrd;
+ }
+
+ if (group->mode & PCM_ENABLE_OUTPUT) {
+ smwr = (struct pcmchan_syncmember *)malloc(sizeof(*smwr), M_DEVBUF, M_NOWAIT);
+ if (smwr == NULL) {
+ ret = ENOMEM;
+ goto out;
+ }
+
+ SLIST_INSERT_HEAD(&sg->members, smwr, link);
+ smwr->parent = sg;
+ smwr->ch = wrch;
+
+ chn_abort(wrch);
+ wrch->flags |= CHN_F_NOTRIGGER;
+ wrch->sm = smwr;
+ }
+
+
+out:
+ if (ret != 0) {
+ if (smrd != NULL)
+ free(smrd, M_DEVBUF);
+ if ((sg != NULL) && SLIST_EMPTY(&sg->members)) {
+ sg_ids[2] = sg->id;
+ SLIST_REMOVE(&snd_pcm_syncgroups, sg, pcmchan_syncgroup, link);
+ free(sg, M_DEVBUF);
+ }
+
+ if (wrch)
+ wrch->sm = NULL;
+ if (rdch)
+ rdch->sm = NULL;
+ }
+
+ if (wrch)
+ CHN_UNLOCK(wrch);
+ if (rdch)
+ CHN_UNLOCK(rdch);
+
+ PCM_SG_UNLOCK();
+
+ if (sg_ids[0])
+ free_unr(pcmsg_unrhdr, sg_ids[0]);
+ if (sg_ids[1])
+ free_unr(pcmsg_unrhdr, sg_ids[1]);
+ if (sg_ids[2])
+ free_unr(pcmsg_unrhdr, sg_ids[2]);
+
+ return (ret);
+}
+
+/**
+ * @brief Launch a sync group into action
+ *
+ * Sync groups are established via SNDCTL_DSP_SYNCGROUP. This function
+ * iterates over all members, triggering them along the way.
+ *
+ * @note Caller must not hold any channel locks.
+ *
+ * @param sg_id sync group identifier
+ *
+ * @retval 0 success
+ * @retval non-zero error worthy of propagating upstream to user
+ */
+static int
+dsp_oss_syncstart(int sg_id)
+{
+ struct pcmchan_syncmember *sm, *sm_tmp;
+ struct pcmchan_syncgroup *sg;
+ struct pcm_channel *c;
+ int ret, needlocks;
+
+ /* Get the synclists lock */
+ PCM_SG_LOCK();
+
+ do {
+ ret = 0;
+ needlocks = 0;
+
+ /* Search for syncgroup by ID */
+ SLIST_FOREACH(sg, &snd_pcm_syncgroups, link) {
+ if (sg->id == sg_id)
+ break;
+ }
+
+ /* Return EINVAL if not found */
+ if (sg == NULL) {
+ ret = EINVAL;
+ break;
+ }
+
+ /* Any removals resulting in an empty group should've handled this */
+ KASSERT(!SLIST_EMPTY(&sg->members), ("found empty syncgroup"));
+
+ /*
+ * Attempt to lock all member channels - if any are already
+ * locked, unlock those acquired, sleep for a bit, and try
+ * again.
+ */
+ SLIST_FOREACH(sm, &sg->members, link) {
+ if (CHN_TRYLOCK(sm->ch) == 0) {
+ int timo = hz * 5/1000;
+ if (timo < 1)
+ timo = 1;
+
+ /* Release all locked channels so far, retry */
+ SLIST_FOREACH(sm_tmp, &sg->members, link) {
+ /* sm is the member already locked */
+ if (sm == sm_tmp)
+ break;
+ CHN_UNLOCK(sm_tmp->ch);
+ }
+
+ /** @todo Is PRIBIO correct/ */
+ ret = msleep(sm, &snd_pcm_syncgroups_mtx,
+ PRIBIO | PCATCH, "pcmsg", timo);
+ if (ret == EINTR || ret == ERESTART)
+ break;
+
+ needlocks = 1;
+ ret = 0; /* Assumes ret == EAGAIN... */
+ }
+ }
+ } while (needlocks && ret == 0);
+
+ /* Proceed only if no errors encountered. */
+ if (ret == 0) {
+ /* Launch channels */
+ while((sm = SLIST_FIRST(&sg->members)) != NULL) {
+ SLIST_REMOVE_HEAD(&sg->members, link);
+
+ c = sm->ch;
+ c->sm = NULL;
+ chn_start(c, 1);
+ c->flags &= ~CHN_F_NOTRIGGER;
+ CHN_UNLOCK(c);
+
+ free(sm, M_DEVBUF);
+ }
+
+ SLIST_REMOVE(&snd_pcm_syncgroups, sg, pcmchan_syncgroup, link);
+ free(sg, M_DEVBUF);
+ }
+
+ PCM_SG_UNLOCK();
+
+ /*
+ * Free_unr() may sleep, so be sure to give up the syncgroup lock
+ * first.
+ */
+ if (ret == 0)
+ free_unr(pcmsg_unrhdr, sg_id);
+
+ return (ret);
+}
+
+/**
+ * @brief Handler for SNDCTL_DSP_POLICY
+ *
+ * The SNDCTL_DSP_POLICY ioctl is a simpler interface to control fragment
+ * size and count like with SNDCTL_DSP_SETFRAGMENT. Instead of the user
+ * specifying those two parameters, s/he simply selects a number from 0..10
+ * which corresponds to a buffer size. Smaller numbers request smaller
+ * buffers with lower latencies (at greater overhead from more frequent
+ * interrupts), while greater numbers behave in the opposite manner.
+ *
+ * The 4Front spec states that a value of 5 should be the default. However,
+ * this implementation deviates slightly by using a linear scale without
+ * consulting drivers. I.e., even though drivers may have different default
+ * buffer sizes, a policy argument of 5 will have the same result across
+ * all drivers.
+ *
+ * See http://manuals.opensound.com/developer/SNDCTL_DSP_POLICY.html for
+ * more information.
+ *
+ * @todo When SNDCTL_DSP_COOKEDMODE is supported, it'll be necessary to
+ * work with hardware drivers directly.
+ *
+ * @note PCM channel arguments must not be locked by caller.
+ *
+ * @param wrch Pointer to opened playback channel (optional; may be NULL)
+ * @param rdch " recording channel (optional; may be NULL)
+ * @param policy Integer from [0:10]
+ *
+ * @retval 0 constant (for now)
+ */
+static int
+dsp_oss_policy(struct pcm_channel *wrch, struct pcm_channel *rdch, int policy)
+{
+ int ret;
+
+ if (policy < CHN_POLICY_MIN || policy > CHN_POLICY_MAX)
+ return (EIO);
+
+ /* Default: success */
+ ret = 0;
+
+ if (rdch) {
+ CHN_LOCK(rdch);
+ ret = chn_setlatency(rdch, policy);
+ CHN_UNLOCK(rdch);
+ }
+
+ if (wrch && ret == 0) {
+ CHN_LOCK(wrch);
+ ret = chn_setlatency(wrch, policy);
+ CHN_UNLOCK(wrch);
+ }
+
+ if (ret)
+ ret = EIO;
+
+ return (ret);
+}
+
+#ifdef OSSV4_EXPERIMENT
+/**
+ * @brief Enable or disable "cooked" mode
+ *
+ * This is a handler for @c SNDCTL_DSP_COOKEDMODE. When in cooked mode, which
+ * is the default, the sound system handles rate and format conversions
+ * automatically (ex: user writing 11025Hz/8 bit/unsigned but card only
+ * operates with 44100Hz/16bit/signed samples).
+ *
+ * Disabling cooked mode is intended for applications wanting to mmap()
+ * a sound card's buffer space directly, bypassing the FreeBSD 2-stage
+ * feeder architecture, presumably to gain as much control over audio
+ * hardware as possible.
+ *
+ * See @c http://manuals.opensound.com/developer/SNDCTL_DSP_COOKEDMODE.html
+ * for more details.
+ *
+ * @note Currently, this function is just a stub that always returns EINVAL.
+ *
+ * @todo Figure out how to and actually implement this.
+ *
+ * @param wrch playback channel (optional; may be NULL)
+ * @param rdch recording channel (optional; may be NULL)
+ * @param enabled 0 = raw mode, 1 = cooked mode
+ *
+ * @retval EINVAL Operation not yet supported.
+ */
+static int
+dsp_oss_cookedmode(struct pcm_channel *wrch, struct pcm_channel *rdch, int enabled)
+{
+ return (EINVAL);
+}
+
+/**
+ * @brief Retrieve channel interleaving order
+ *
+ * This is the handler for @c SNDCTL_DSP_GET_CHNORDER.
+ *
+ * See @c http://manuals.opensound.com/developer/SNDCTL_DSP_GET_CHNORDER.html
+ * for more details.
+ *
+ * @note As the ioctl definition is still under construction, FreeBSD
+ * does not currently support SNDCTL_DSP_GET_CHNORDER.
+ *
+ * @param wrch playback channel (optional; may be NULL)
+ * @param rdch recording channel (optional; may be NULL)
+ * @param map channel map (result will be stored there)
+ *
+ * @retval EINVAL Operation not yet supported.
+ */
+static int
+dsp_oss_getchnorder(struct pcm_channel *wrch, struct pcm_channel *rdch, unsigned long long *map)
+{
+ return (EINVAL);
+}
+
+/**
+ * @brief Specify channel interleaving order
+ *
+ * This is the handler for @c SNDCTL_DSP_SET_CHNORDER.
+ *
+ * @note As the ioctl definition is still under construction, FreeBSD
+ * does not currently support @c SNDCTL_DSP_SET_CHNORDER.
+ *
+ * @param wrch playback channel (optional; may be NULL)
+ * @param rdch recording channel (optional; may be NULL)
+ * @param map channel map
+ *
+ * @retval EINVAL Operation not yet supported.
+ */
+static int
+dsp_oss_setchnorder(struct pcm_channel *wrch, struct pcm_channel *rdch, unsigned long long *map)
+{
+ return (EINVAL);
+}
+
+/**
+ * @brief Retrieve an audio device's label
+ *
+ * This is a handler for the @c SNDCTL_GETLABEL ioctl.
+ *
+ * See @c http://manuals.opensound.com/developer/SNDCTL_GETLABEL.html
+ * for more details.
+ *
+ * From Hannu at 4Front: "For example ossxmix (just like some HW mixer
+ * consoles) can show variable "labels" for certain controls. By default
+ * the application name (say quake) is shown as the label but
+ * applications may change the labels themselves."
+ *
+ * @note As the ioctl definition is still under construction, FreeBSD
+ * does not currently support @c SNDCTL_GETLABEL.
+ *
+ * @param wrch playback channel (optional; may be NULL)
+ * @param rdch recording channel (optional; may be NULL)
+ * @param label label gets copied here
+ *
+ * @retval EINVAL Operation not yet supported.
+ */
+static int
+dsp_oss_getlabel(struct pcm_channel *wrch, struct pcm_channel *rdch, oss_label_t *label)
+{
+ return (EINVAL);
+}
+
+/**
+ * @brief Specify an audio device's label
+ *
+ * This is a handler for the @c SNDCTL_SETLABEL ioctl. Please see the
+ * comments for @c dsp_oss_getlabel immediately above.
+ *
+ * See @c http://manuals.opensound.com/developer/SNDCTL_GETLABEL.html
+ * for more details.
+ *
+ * @note As the ioctl definition is still under construction, FreeBSD
+ * does not currently support SNDCTL_SETLABEL.
+ *
+ * @param wrch playback channel (optional; may be NULL)
+ * @param rdch recording channel (optional; may be NULL)
+ * @param label label gets copied from here
+ *
+ * @retval EINVAL Operation not yet supported.
+ */
+static int
+dsp_oss_setlabel(struct pcm_channel *wrch, struct pcm_channel *rdch, oss_label_t *label)
+{
+ return (EINVAL);
+}
+
+/**
+ * @brief Retrieve name of currently played song
+ *
+ * This is a handler for the @c SNDCTL_GETSONG ioctl. Audio players could
+ * tell the system the name of the currently playing song, which would be
+ * visible in @c /dev/sndstat.
+ *
+ * See @c http://manuals.opensound.com/developer/SNDCTL_GETSONG.html
+ * for more details.
+ *
+ * @note As the ioctl definition is still under construction, FreeBSD
+ * does not currently support SNDCTL_GETSONG.
+ *
+ * @param wrch playback channel (optional; may be NULL)
+ * @param rdch recording channel (optional; may be NULL)
+ * @param song song name gets copied here
+ *
+ * @retval EINVAL Operation not yet supported.
+ */
+static int
+dsp_oss_getsong(struct pcm_channel *wrch, struct pcm_channel *rdch, oss_longname_t *song)
+{
+ return (EINVAL);
+}
+
+/**
+ * @brief Retrieve name of currently played song
+ *
+ * This is a handler for the @c SNDCTL_SETSONG ioctl. Audio players could
+ * tell the system the name of the currently playing song, which would be
+ * visible in @c /dev/sndstat.
+ *
+ * See @c http://manuals.opensound.com/developer/SNDCTL_SETSONG.html
+ * for more details.
+ *
+ * @note As the ioctl definition is still under construction, FreeBSD
+ * does not currently support SNDCTL_SETSONG.
+ *
+ * @param wrch playback channel (optional; may be NULL)
+ * @param rdch recording channel (optional; may be NULL)
+ * @param song song name gets copied from here
+ *
+ * @retval EINVAL Operation not yet supported.
+ */
+static int
+dsp_oss_setsong(struct pcm_channel *wrch, struct pcm_channel *rdch, oss_longname_t *song)
+{
+ return (EINVAL);
+}
+
+/**
+ * @brief Rename a device
+ *
+ * This is a handler for the @c SNDCTL_SETNAME ioctl.
+ *
+ * See @c http://manuals.opensound.com/developer/SNDCTL_SETNAME.html for
+ * more details.
+ *
+ * From Hannu at 4Front: "This call is used to change the device name
+ * reported in /dev/sndstat and ossinfo. So instead of using some generic
+ * 'OSS loopback audio (MIDI) driver' the device may be given a meaningfull
+ * name depending on the current context (for example 'OSS virtual wave table
+ * synth' or 'VoIP link to London')."
+ *
+ * @note As the ioctl definition is still under construction, FreeBSD
+ * does not currently support SNDCTL_SETNAME.
+ *
+ * @param wrch playback channel (optional; may be NULL)
+ * @param rdch recording channel (optional; may be NULL)
+ * @param name new device name gets copied from here
+ *
+ * @retval EINVAL Operation not yet supported.
+ */
+static int
+dsp_oss_setname(struct pcm_channel *wrch, struct pcm_channel *rdch, oss_longname_t *name)
+{
+ return (EINVAL);
+}
+#endif /* !OSSV4_EXPERIMENT */
Index: buffer.h
===================================================================
RCS file: /home/cvs/src/sys/dev/sound/pcm/buffer.h,v
retrieving revision 1.2
retrieving revision 1.3
diff -L sys/dev/sound/pcm/buffer.h -L sys/dev/sound/pcm/buffer.h -u -r1.2 -r1.3
--- sys/dev/sound/pcm/buffer.h
+++ sys/dev/sound/pcm/buffer.h
@@ -1,31 +1,30 @@
/*-
-* Copyright (c) 1999 Cameron Grant <cg at freebsd.org>
-* All rights reserved.
-*
-* Redistribution and use in source and binary forms, with or without
-* modification, are permitted provided that the following conditions
-* are met:
-* 1. Redistributions of source code must retain the above copyright
-* notice, this list of conditions and the following disclaimer.
-* 2. Redistributions in binary form must reproduce the above copyright
-* notice, this list of conditions and the following disclaimer in the
-* documentation and/or other materials provided with the distribution.
-*
-* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
-* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
-* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
-* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
-* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
-* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
-* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
-* SUCH DAMAGE.
-*
-* $MidnightBSD$
-* $FreeBSD: src/sys/dev/sound/pcm/buffer.h,v 1.10.2.1 2007/02/04 06:17:48 ariff Exp $
-*/
+ * Copyright (c) 1999 Cameron Grant <cg at freebsd.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD: src/sys/dev/sound/pcm/buffer.h,v 1.17 2007/06/14 11:15:51 ariff Exp $
+ */
#define SND_DMA(b) (sndbuf_getflags((b)) & SNDBUF_F_DMA)
#define SNDBUF_LOCKASSERT(b)
@@ -38,25 +37,28 @@
#define SNDBUF_NAMELEN 48
struct snd_dbuf {
-device_t dev;
-u_int8_t *buf, *tmpbuf;
-unsigned int bufsize, maxsize;
-volatile int dl; /* transfer size */
-volatile int rp; /* pointers to the ready area */
-volatile int rl; /* length of ready area */
-volatile int hp;
-volatile u_int32_t total, prev_total;
-int dmachan, dir; /* dma channel */
-u_int32_t fmt, spd, bps;
-unsigned int blksz, blkcnt;
-int xrun;
-u_int32_t flags;
-bus_dmamap_t dmamap;
-bus_dma_tag_t dmatag;
-u_int32_t buf_addr;
-struct selinfo sel;
-struct pcm_channel *channel;
-char name[SNDBUF_NAMELEN];
+ device_t dev;
+ u_int8_t *buf, *tmpbuf;
+ u_int8_t *shadbuf; /**< shadow buffer used w/ S_D_SILENCE/SKIP */
+ volatile int sl; /**< shadbuf ready length in # of bytes */
+ unsigned int bufsize, maxsize, allocsize;
+ volatile int dl; /* transfer size */
+ volatile int rp; /* pointers to the ready area */
+ volatile int rl; /* length of ready area */
+ volatile int hp;
+ volatile u_int32_t total, prev_total;
+ int dmachan, dir; /* dma channel */
+ u_int32_t fmt, spd, bps;
+ unsigned int blksz, blkcnt;
+ int xrun;
+ u_int32_t flags;
+ bus_dmamap_t dmamap;
+ bus_dma_tag_t dmatag;
+ bus_addr_t buf_addr;
+ int dmaflags;
+ struct selinfo sel;
+ struct pcm_channel *channel;
+ char name[SNDBUF_NAMELEN];
};
struct snd_dbuf *sndbuf_create(device_t dev, char *drv, char *desc, struct pcm_channel *channel);
@@ -64,7 +66,7 @@
void sndbuf_dump(struct snd_dbuf *b, char *s, u_int32_t what);
-int sndbuf_alloc(struct snd_dbuf *b, bus_dma_tag_t dmatag, unsigned int size);
+int sndbuf_alloc(struct snd_dbuf *b, bus_dma_tag_t dmatag, int dmaflags, unsigned int size);
int sndbuf_setup(struct snd_dbuf *b, void *buf, unsigned int size);
void sndbuf_free(struct snd_dbuf *b);
int sndbuf_resize(struct snd_dbuf *b, unsigned int blkcnt, unsigned int blksz);
@@ -72,6 +74,8 @@
void sndbuf_reset(struct snd_dbuf *b);
void sndbuf_clear(struct snd_dbuf *b, unsigned int length);
void sndbuf_fillsilence(struct snd_dbuf *b);
+void sndbuf_softreset(struct snd_dbuf *b);
+void sndbuf_clearshadow(struct snd_dbuf *b);
u_int32_t sndbuf_getfmt(struct snd_dbuf *b);
int sndbuf_setfmt(struct snd_dbuf *b, u_int32_t fmt);
@@ -85,6 +89,7 @@
void *sndbuf_getbufofs(struct snd_dbuf *b, unsigned int ofs);
unsigned int sndbuf_getsize(struct snd_dbuf *b);
unsigned int sndbuf_getmaxsize(struct snd_dbuf *b);
+unsigned int sndbuf_getallocsize(struct snd_dbuf *b);
unsigned int sndbuf_getalign(struct snd_dbuf *b);
unsigned int sndbuf_getblkcnt(struct snd_dbuf *b);
void sndbuf_setblkcnt(struct snd_dbuf *b, unsigned int blkcnt);
@@ -95,7 +100,7 @@
struct selinfo *sndbuf_getsel(struct snd_dbuf *b);
unsigned int sndbuf_getxrun(struct snd_dbuf *b);
-void sndbuf_setxrun(struct snd_dbuf *b, unsigned int cnt);
+void sndbuf_setxrun(struct snd_dbuf *b, unsigned int xrun);
unsigned int sndbuf_gethwptr(struct snd_dbuf *b);
void sndbuf_sethwptr(struct snd_dbuf *b, unsigned int ptr);
unsigned int sndbuf_getfree(struct snd_dbuf *b);
@@ -105,6 +110,9 @@
unsigned int sndbuf_getblocks(struct snd_dbuf *b);
unsigned int sndbuf_getprevblocks(struct snd_dbuf *b);
unsigned int sndbuf_gettotal(struct snd_dbuf *b);
+unsigned int snd_xbytes(unsigned int v, unsigned int from, unsigned int to);
+unsigned int sndbuf_xbytes(unsigned int v, struct snd_dbuf *from, struct snd_dbuf *to);
+u_int8_t sndbuf_zerodata(u_int32_t fmt);
void sndbuf_updateprevtotal(struct snd_dbuf *b);
int sndbuf_acquire(struct snd_dbuf *b, u_int8_t *from, unsigned int count);
@@ -119,3 +127,7 @@
void sndbuf_dma(struct snd_dbuf *b, int go);
int sndbuf_dmaptr(struct snd_dbuf *b);
void sndbuf_dmabounce(struct snd_dbuf *b);
+
+#ifdef OSSV4_EXPERIMENT
+void sndbuf_getpeaks(struct snd_dbuf *b, int *lp, int *rp);
+#endif
Index: mixer.c
===================================================================
RCS file: /home/cvs/src/sys/dev/sound/pcm/mixer.c,v
retrieving revision 1.3
retrieving revision 1.4
diff -L sys/dev/sound/pcm/mixer.c -L sys/dev/sound/pcm/mixer.c -u -r1.3 -r1.4
--- sys/dev/sound/pcm/mixer.c
+++ sys/dev/sound/pcm/mixer.c
@@ -1,692 +1,1282 @@
/*-
-* Copyright (c) 1999 Cameron Grant <cg at freebsd.org>
-* All rights reserved.
-*
-* Redistribution and use in source and binary forms, with or without
-* modification, are permitted provided that the following conditions
-* are met:
-* 1. Redistributions of source code must retain the above copyright
-* notice, this list of conditions and the following disclaimer.
-* 2. Redistributions in binary form must reproduce the above copyright
-* notice, this list of conditions and the following disclaimer in the
-* documentation and/or other materials provided with the distribution.
-*
-* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
-* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
-* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
-* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
-* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
-* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
-* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
-* SUCH DAMAGE.
-*/
+ * Copyright (c) 1999 Cameron Grant <cg at freebsd.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
#include <dev/sound/pcm/sound.h>
#include "mixer_if.h"
-SND_DECLARE_FILE("$MidnightBSD$");
+SND_DECLARE_FILE("$FreeBSD: src/sys/dev/sound/pcm/mixer.c,v 1.61 2007/06/16 03:37:28 ariff Exp $");
MALLOC_DEFINE(M_MIXER, "mixer", "mixer");
#define MIXER_NAMELEN 16
struct snd_mixer {
-KOBJ_FIELDS;
-const char *type;
-void *devinfo;
-int busy;
-int hwvol_muted;
-int hwvol_mixer;
-int hwvol_step;
-device_t dev;
-u_int32_t hwvol_mute_level;
-u_int32_t devs;
-u_int32_t recdevs;
-u_int32_t recsrc;
-u_int16_t level[32];
-u_int8_t parent[32];
-u_int32_t child[32];
-u_int8_t realdev[32];
-char name[MIXER_NAMELEN];
-struct mtx *lock;
+ KOBJ_FIELDS;
+ void *devinfo;
+ int busy;
+ int hwvol_muted;
+ int hwvol_mixer;
+ int hwvol_step;
+ int type;
+ device_t dev;
+ u_int32_t hwvol_mute_level;
+ u_int32_t devs;
+ u_int32_t recdevs;
+ u_int32_t recsrc;
+ u_int16_t level[32];
+ u_int8_t parent[32];
+ u_int32_t child[32];
+ u_int8_t realdev[32];
+ char name[MIXER_NAMELEN];
+ struct mtx *lock;
+ oss_mixer_enuminfo enuminfo;
+ /**
+ * Counter is incremented when applications change any of this
+ * mixer's controls. A change in value indicates that persistent
+ * mixer applications should update their displays.
+ */
+ int modify_counter;
};
static u_int16_t snd_mixerdefaults[SOUND_MIXER_NRDEVICES] = {
-[SOUND_MIXER_VOLUME] = 75,
-[SOUND_MIXER_BASS] = 50,
-[SOUND_MIXER_TREBLE] = 50,
-[SOUND_MIXER_SYNTH] = 75,
-[SOUND_MIXER_PCM] = 75,
-[SOUND_MIXER_SPEAKER] = 75,
-[SOUND_MIXER_LINE] = 75,
-[SOUND_MIXER_MIC] = 0,
-[SOUND_MIXER_CD] = 75,
-[SOUND_MIXER_IGAIN] = 0,
-[SOUND_MIXER_LINE1] = 75,
-[SOUND_MIXER_VIDEO] = 75,
-[SOUND_MIXER_RECLEV] = 0,
-[SOUND_MIXER_OGAIN] = 50,
-[SOUND_MIXER_MONITOR] = 75,
+ [SOUND_MIXER_VOLUME] = 75,
+ [SOUND_MIXER_BASS] = 50,
+ [SOUND_MIXER_TREBLE] = 50,
+ [SOUND_MIXER_SYNTH] = 75,
+ [SOUND_MIXER_PCM] = 75,
+ [SOUND_MIXER_SPEAKER] = 75,
+ [SOUND_MIXER_LINE] = 75,
+ [SOUND_MIXER_MIC] = 0,
+ [SOUND_MIXER_CD] = 75,
+ [SOUND_MIXER_IGAIN] = 0,
+ [SOUND_MIXER_LINE1] = 75,
+ [SOUND_MIXER_VIDEO] = 75,
+ [SOUND_MIXER_RECLEV] = 0,
+ [SOUND_MIXER_OGAIN] = 50,
+ [SOUND_MIXER_MONITOR] = 75,
};
static char* snd_mixernames[SOUND_MIXER_NRDEVICES] = SOUND_DEVICE_NAMES;
static d_open_t mixer_open;
static d_close_t mixer_close;
+static d_ioctl_t mixer_ioctl;
static struct cdevsw mixer_cdevsw = {
-.d_version = D_VERSION,
-.d_flags = D_TRACKCLOSE | D_NEEDGIANT,
-.d_open = mixer_open,
-.d_close = mixer_close,
-.d_ioctl = mixer_ioctl,
-.d_name = "mixer",
+ .d_version = D_VERSION,
+ .d_open = mixer_open,
+ .d_close = mixer_close,
+ .d_ioctl = mixer_ioctl,
+ .d_name = "mixer",
};
+/**
+ * Keeps a count of mixer devices; used only by OSSv4 SNDCTL_SYSINFO ioctl.
+ */
+int mixer_count = 0;
+
#ifdef USING_DEVFS
-static eventhandler_tag mixer_ehtag;
+static eventhandler_tag mixer_ehtag = NULL;
#endif
static struct cdev *
mixer_get_devt(device_t dev)
{
-struct snddev_info *snddev;
+ struct snddev_info *snddev;
-snddev = device_get_softc(dev);
+ snddev = device_get_softc(dev);
-return snddev->mixer_dev;
+ return snddev->mixer_dev;
}
#ifdef SND_DYNSYSCTL
static int
mixer_lookup(char *devname)
{
-int i;
+ int i;
-for (i = 0; i < SOUND_MIXER_NRDEVICES; i++)
-if (strncmp(devname, snd_mixernames[i],
-strlen(snd_mixernames[i])) == 0)
-return i;
-return -1;
+ for (i = 0; i < SOUND_MIXER_NRDEVICES; i++)
+ if (strncmp(devname, snd_mixernames[i],
+ strlen(snd_mixernames[i])) == 0)
+ return i;
+ return -1;
}
#endif
+#define MIXER_SET_UNLOCK(x, y) do { \
+ if ((y) != 0) \
+ snd_mtxunlock((x)->lock); \
+} while(0)
+
+#define MIXER_SET_LOCK(x, y) do { \
+ if ((y) != 0) \
+ snd_mtxlock((x)->lock); \
+} while(0)
+
static int
-mixer_set_softpcmvol(struct snd_mixer *mixer, struct snddev_info *d,
-unsigned left, unsigned right)
+mixer_set_softpcmvol(struct snd_mixer *m, struct snddev_info *d,
+ unsigned left, unsigned right)
{
-struct snddev_channel *sce;
-struct pcm_channel *ch;
-#ifdef USING_MUTEX
-int locked = (mixer->lock && mtx_owned((struct mtx *)(mixer->lock))) ? 1 : 0;
+ struct pcm_channel *c;
+ int dropmtx, acquiremtx;
-if (locked)
-snd_mtxunlock(mixer->lock);
-#endif
-SLIST_FOREACH(sce, &d->channels, link) {
-ch = sce->channel;
-CHN_LOCK(ch);
-if (ch->direction == PCMDIR_PLAY &&
-(ch->feederflags & (1 << FEEDER_VOLUME)))
-chn_setvolume(ch, left, right);
-CHN_UNLOCK(ch);
-}
-#ifdef USING_MUTEX
-if (locked)
-snd_mtxlock(mixer->lock);
-#endif
-return 0;
+ if (!PCM_REGISTERED(d))
+ return (EINVAL);
+
+ if (mtx_owned(m->lock))
+ dropmtx = 1;
+ else
+ dropmtx = 0;
+
+ if (!(d->flags & SD_F_MPSAFE) || mtx_owned(d->lock) != 0)
+ acquiremtx = 0;
+ else
+ acquiremtx = 1;
+
+ /*
+ * Be careful here. If we're coming from cdev ioctl, it is OK to
+ * not doing locking AT ALL (except on individual channel) since
+ * we've been heavily guarded by pcm cv, or if we're still
+ * under Giant influence. Since we also have mix_* calls, we cannot
+ * assume such protection and just do the lock as usuall.
+ */
+ MIXER_SET_UNLOCK(m, dropmtx);
+ MIXER_SET_LOCK(d, acquiremtx);
+
+ if (CHN_EMPTY(d, channels.pcm.busy)) {
+ CHN_FOREACH(c, d, channels.pcm) {
+ CHN_LOCK(c);
+ if (c->direction == PCMDIR_PLAY &&
+ (c->feederflags & (1 << FEEDER_VOLUME)))
+ chn_setvolume(c, left, right);
+ CHN_UNLOCK(c);
+ }
+ } else {
+ CHN_FOREACH(c, d, channels.pcm.busy) {
+ CHN_LOCK(c);
+ if (c->direction == PCMDIR_PLAY &&
+ (c->feederflags & (1 << FEEDER_VOLUME)))
+ chn_setvolume(c, left, right);
+ CHN_UNLOCK(c);
+ }
+ }
+
+ MIXER_SET_UNLOCK(d, acquiremtx);
+ MIXER_SET_LOCK(m, dropmtx);
+
+ return (0);
}
static int
mixer_set(struct snd_mixer *m, unsigned dev, unsigned lev)
{
-struct snddev_info *d;
-unsigned l, r, tl, tr;
-u_int32_t parent = SOUND_MIXER_NONE, child = 0;
-u_int32_t realdev;
-int i;
-
-if (m == NULL || dev >= SOUND_MIXER_NRDEVICES ||
-(0 == (m->devs & (1 << dev))))
-return -1;
-
-l = min((lev & 0x00ff), 100);
-r = min(((lev & 0xff00) >> 8), 100);
-realdev = m->realdev[dev];
-
-d = device_get_softc(m->dev);
-if (d == NULL)
-return -1;
-
-/* TODO: recursive handling */
-parent = m->parent[dev];
-if (parent >= SOUND_MIXER_NRDEVICES)
-parent = SOUND_MIXER_NONE;
-if (parent == SOUND_MIXER_NONE)
-child = m->child[dev];
-
-if (parent != SOUND_MIXER_NONE) {
-tl = (l * (m->level[parent] & 0x00ff)) / 100;
-tr = (r * ((m->level[parent] & 0xff00) >> 8)) / 100;
-if (dev == SOUND_MIXER_PCM && (d->flags & SD_F_SOFTPCMVOL))
-mixer_set_softpcmvol(m, d, tl, tr);
-else if (realdev != SOUND_MIXER_NONE &&
-MIXER_SET(m, realdev, tl, tr) < 0)
-return -1;
-} else if (child != 0) {
-for (i = 0; i < SOUND_MIXER_NRDEVICES; i++) {
-if (!(child & (1 << i)) || m->parent[i] != dev)
-continue;
-realdev = m->realdev[i];
-tl = (l * (m->level[i] & 0x00ff)) / 100;
-tr = (r * ((m->level[i] & 0xff00) >> 8)) / 100;
-if (i == SOUND_MIXER_PCM && (d->flags & SD_F_SOFTPCMVOL))
-mixer_set_softpcmvol(m, d, tl, tr);
-else if (realdev != SOUND_MIXER_NONE)
-MIXER_SET(m, realdev, tl, tr);
-}
-realdev = m->realdev[dev];
-if (realdev != SOUND_MIXER_NONE &&
-MIXER_SET(m, realdev, l, r) < 0)
-return -1;
-} else {
-if (dev == SOUND_MIXER_PCM && (d->flags & SD_F_SOFTPCMVOL))
-mixer_set_softpcmvol(m, d, l, r);
-else if (realdev != SOUND_MIXER_NONE &&
-MIXER_SET(m, realdev, l, r) < 0)
-return -1;
-}
+ struct snddev_info *d;
+ unsigned l, r, tl, tr;
+ u_int32_t parent = SOUND_MIXER_NONE, child = 0;
+ u_int32_t realdev;
+ int i, dropmtx;
+
+ if (m == NULL || dev >= SOUND_MIXER_NRDEVICES ||
+ (0 == (m->devs & (1 << dev))))
+ return -1;
+
+ l = min((lev & 0x00ff), 100);
+ r = min(((lev & 0xff00) >> 8), 100);
+ realdev = m->realdev[dev];
+
+ d = device_get_softc(m->dev);
+ if (d == NULL)
+ return -1;
+
+ /* It is safe to drop this mutex due to Giant. */
+ if (!(d->flags & SD_F_MPSAFE) && mtx_owned(m->lock) != 0)
+ dropmtx = 1;
+ else
+ dropmtx = 0;
+
+ MIXER_SET_UNLOCK(m, dropmtx);
+
+ /* TODO: recursive handling */
+ parent = m->parent[dev];
+ if (parent >= SOUND_MIXER_NRDEVICES)
+ parent = SOUND_MIXER_NONE;
+ if (parent == SOUND_MIXER_NONE)
+ child = m->child[dev];
+
+ if (parent != SOUND_MIXER_NONE) {
+ tl = (l * (m->level[parent] & 0x00ff)) / 100;
+ tr = (r * ((m->level[parent] & 0xff00) >> 8)) / 100;
+ if (dev == SOUND_MIXER_PCM && (d->flags & SD_F_SOFTPCMVOL))
+ (void)mixer_set_softpcmvol(m, d, tl, tr);
+ else if (realdev != SOUND_MIXER_NONE &&
+ MIXER_SET(m, realdev, tl, tr) < 0) {
+ MIXER_SET_LOCK(m, dropmtx);
+ return -1;
+ }
+ } else if (child != 0) {
+ for (i = 0; i < SOUND_MIXER_NRDEVICES; i++) {
+ if (!(child & (1 << i)) || m->parent[i] != dev)
+ continue;
+ realdev = m->realdev[i];
+ tl = (l * (m->level[i] & 0x00ff)) / 100;
+ tr = (r * ((m->level[i] & 0xff00) >> 8)) / 100;
+ if (i == SOUND_MIXER_PCM && (d->flags & SD_F_SOFTPCMVOL))
+ (void)mixer_set_softpcmvol(m, d, tl, tr);
+ else if (realdev != SOUND_MIXER_NONE)
+ MIXER_SET(m, realdev, tl, tr);
+ }
+ realdev = m->realdev[dev];
+ if (realdev != SOUND_MIXER_NONE &&
+ MIXER_SET(m, realdev, l, r) < 0) {
+ MIXER_SET_LOCK(m, dropmtx);
+ return -1;
+ }
+ } else {
+ if (dev == SOUND_MIXER_PCM && (d->flags & SD_F_SOFTPCMVOL))
+ (void)mixer_set_softpcmvol(m, d, l, r);
+ else if (realdev != SOUND_MIXER_NONE &&
+ MIXER_SET(m, realdev, l, r) < 0) {
+ MIXER_SET_LOCK(m, dropmtx);
+ return -1;
+ }
+ }
+
+ m->level[dev] = l | (r << 8);
-m->level[dev] = l | (r << 8);
+ MIXER_SET_LOCK(m, dropmtx);
-return 0;
+ return 0;
}
static int
mixer_get(struct snd_mixer *mixer, int dev)
{
-if ((dev < SOUND_MIXER_NRDEVICES) && (mixer->devs & (1 << dev)))
-return mixer->level[dev];
-else return -1;
+ if ((dev < SOUND_MIXER_NRDEVICES) && (mixer->devs & (1 << dev)))
+ return mixer->level[dev];
+ else
+ return -1;
}
static int
mixer_setrecsrc(struct snd_mixer *mixer, u_int32_t src)
{
-src &= mixer->recdevs;
-if (src == 0)
-src = SOUND_MASK_MIC;
-mixer->recsrc = MIXER_SETRECSRC(mixer, src);
-return 0;
+ struct snddev_info *d;
+ int dropmtx;
+
+ d = device_get_softc(mixer->dev);
+ if (d == NULL)
+ return -1;
+ if (!(d->flags & SD_F_MPSAFE) && mtx_owned(mixer->lock) != 0)
+ dropmtx = 1;
+ else
+ dropmtx = 0;
+ src &= mixer->recdevs;
+ if (src == 0)
+ src = SOUND_MASK_MIC;
+ /* It is safe to drop this mutex due to Giant. */
+ MIXER_SET_UNLOCK(mixer, dropmtx);
+ mixer->recsrc = MIXER_SETRECSRC(mixer, src);
+ MIXER_SET_LOCK(mixer, dropmtx);
+ return 0;
}
static int
mixer_getrecsrc(struct snd_mixer *mixer)
{
-return mixer->recsrc;
+ return mixer->recsrc;
}
-void
-mix_setdevs(struct snd_mixer *m, u_int32_t v)
+/**
+ * @brief Retrieve the route number of the current recording device
+ *
+ * OSSv4 assigns routing numbers to recording devices, unlike the previous
+ * API which relied on a fixed table of device numbers and names. This
+ * function returns the routing number of the device currently selected
+ * for recording.
+ *
+ * For now, this function is kind of a goofy compatibility stub atop the
+ * existing sound system. (For example, in theory, the old sound system
+ * allows multiple recording devices to be specified via a bitmask.)
+ *
+ * @param m mixer context container thing
+ *
+ * @retval 0 success
+ * @retval EIDRM no recording device found (generally not possible)
+ * @todo Ask about error code
+ */
+static int
+mixer_get_recroute(struct snd_mixer *m, int *route)
{
-struct snddev_info *d;
-int i;
+ int i, cnt;
-if (m == NULL)
-return;
+ cnt = 0;
-d = device_get_softc(m->dev);
-if (d != NULL && (d->flags & SD_F_SOFTPCMVOL))
-v |= SOUND_MASK_PCM;
-for (i = 0; i < SOUND_MIXER_NRDEVICES; i++) {
-if (m->parent[i] < SOUND_MIXER_NRDEVICES)
-v |= 1 << m->parent[i];
-v |= m->child[i];
-}
-m->devs = v;
+ for (i = 0; i < SOUND_MIXER_NRDEVICES; i++) {
+ /** @todo can user set a multi-device mask? (== or &?) */
+ if ((1 << i) == m->recsrc)
+ break;
+ if ((1 << i) & m->recdevs)
+ ++cnt;
+ }
+
+ if (i == SOUND_MIXER_NRDEVICES)
+ return EIDRM;
+
+ *route = cnt;
+ return 0;
+}
+
+/**
+ * @brief Select a device for recording
+ *
+ * This function sets a recording source based on a recording device's
+ * routing number. Said number is translated to an old school recdev
+ * mask and passed over mixer_setrecsrc.
+ *
+ * @param m mixer context container thing
+ *
+ * @retval 0 success(?)
+ * @retval EINVAL User specified an invalid device number
+ * @retval otherwise error from mixer_setrecsrc
+ */
+static int
+mixer_set_recroute(struct snd_mixer *m, int route)
+{
+ int i, cnt, ret;
+
+ ret = 0;
+ cnt = 0;
+
+ for (i = 0; i < SOUND_MIXER_NRDEVICES; i++) {
+ if ((1 << i) & m->recdevs) {
+ if (route == cnt)
+ break;
+ ++cnt;
+ }
+ }
+
+ if (i == SOUND_MIXER_NRDEVICES)
+ ret = EINVAL;
+ else
+ ret = mixer_setrecsrc(m, (1 << i));
+
+ return ret;
}
void
+mix_setdevs(struct snd_mixer *m, u_int32_t v)
+{
+ struct snddev_info *d;
+ int i;
+
+ if (m == NULL)
+ return;
+
+ d = device_get_softc(m->dev);
+ if (d != NULL && (d->flags & SD_F_SOFTPCMVOL))
+ v |= SOUND_MASK_PCM;
+ for (i = 0; i < SOUND_MIXER_NRDEVICES; i++) {
+ if (m->parent[i] < SOUND_MIXER_NRDEVICES)
+ v |= 1 << m->parent[i];
+ v |= m->child[i];
+ }
+ m->devs = v;
+}
+
+/**
+ * @brief Record mask of available recording devices
+ *
+ * Calling functions are responsible for defining the mask of available
+ * recording devices. This function records that value in a structure
+ * used by the rest of the mixer code.
+ *
+ * This function also populates a structure used by the SNDCTL_DSP_*RECSRC*
+ * family of ioctls that are part of OSSV4. All recording device labels
+ * are concatenated in ascending order corresponding to their routing
+ * numbers. (Ex: a system might have 0 => 'vol', 1 => 'cd', 2 => 'line',
+ * etc.) For now, these labels are just the standard recording device
+ * names (cd, line1, etc.), but will eventually be fully dynamic and user
+ * controlled.
+ *
+ * @param m mixer device context container thing
+ * @param v mask of recording devices
+ */
+void
mix_setrecdevs(struct snd_mixer *m, u_int32_t v)
{
-m->recdevs = v;
+ oss_mixer_enuminfo *ei;
+ char *loc;
+ int i, nvalues, nwrote, nleft, ncopied;
+
+ ei = &m->enuminfo;
+
+ nvalues = 0;
+ nwrote = 0;
+ nleft = sizeof(ei->strings);
+ loc = ei->strings;
+
+ for (i = 0; i < SOUND_MIXER_NRDEVICES; i++) {
+ if ((1 << i) & v) {
+ ei->strindex[nvalues] = nwrote;
+ ncopied = strlcpy(loc, snd_mixernames[i], nleft) + 1;
+ /* strlcpy retval doesn't include terminator */
+
+ nwrote += ncopied;
+ nleft -= ncopied;
+ nvalues++;
+
+ /*
+ * XXX I don't think this should ever be possible.
+ * Even with a move to dynamic device/channel names,
+ * each label is limited to ~16 characters, so that'd
+ * take a LOT to fill this buffer.
+ */
+ if ((nleft <= 0) || (nvalues >= OSS_ENUM_MAXVALUE)) {
+ device_printf(m->dev,
+ "mix_setrecdevs: Not enough room to store device names--please file a bug report.\n");
+ device_printf(m->dev,
+ "mix_setrecdevs: Please include details about your sound hardware, OS version, etc.\n");
+ break;
+ }
+
+ loc = &ei->strings[nwrote];
+ }
+ }
+
+ /*
+ * NB: The SNDCTL_DSP_GET_RECSRC_NAMES ioctl ignores the dev
+ * and ctrl fields.
+ */
+ ei->nvalues = nvalues;
+ m->recdevs = v;
}
void
mix_setparentchild(struct snd_mixer *m, u_int32_t parent, u_int32_t childs)
{
-u_int32_t mask = 0;
-int i;
+ u_int32_t mask = 0;
+ int i;
-if (m == NULL || parent >= SOUND_MIXER_NRDEVICES)
-return;
-for (i = 0; i < SOUND_MIXER_NRDEVICES; i++) {
-if (i == parent)
-continue;
-if (childs & (1 << i)) {
-mask |= 1 << i;
-if (m->parent[i] < SOUND_MIXER_NRDEVICES)
-m->child[m->parent[i]] &= ~(1 << i);
-m->parent[i] = parent;
-m->child[i] = 0;
-}
-}
-mask &= ~(1 << parent);
-m->child[parent] = mask;
+ if (m == NULL || parent >= SOUND_MIXER_NRDEVICES)
+ return;
+ for (i = 0; i < SOUND_MIXER_NRDEVICES; i++) {
+ if (i == parent)
+ continue;
+ if (childs & (1 << i)) {
+ mask |= 1 << i;
+ if (m->parent[i] < SOUND_MIXER_NRDEVICES)
+ m->child[m->parent[i]] &= ~(1 << i);
+ m->parent[i] = parent;
+ m->child[i] = 0;
+ }
+ }
+ mask &= ~(1 << parent);
+ m->child[parent] = mask;
}
void
mix_setrealdev(struct snd_mixer *m, u_int32_t dev, u_int32_t realdev)
{
-if (m == NULL || dev >= SOUND_MIXER_NRDEVICES ||
-!(realdev == SOUND_MIXER_NONE || realdev < SOUND_MIXER_NRDEVICES))
-return;
-m->realdev[dev] = realdev;
+ if (m == NULL || dev >= SOUND_MIXER_NRDEVICES ||
+ !(realdev == SOUND_MIXER_NONE || realdev < SOUND_MIXER_NRDEVICES))
+ return;
+ m->realdev[dev] = realdev;
}
u_int32_t
mix_getparent(struct snd_mixer *m, u_int32_t dev)
{
-if (m == NULL || dev >= SOUND_MIXER_NRDEVICES)
-return SOUND_MIXER_NONE;
-return m->parent[dev];
+ if (m == NULL || dev >= SOUND_MIXER_NRDEVICES)
+ return SOUND_MIXER_NONE;
+ return m->parent[dev];
}
u_int32_t
mix_getchild(struct snd_mixer *m, u_int32_t dev)
{
-if (m == NULL || dev >= SOUND_MIXER_NRDEVICES)
-return 0;
-return m->child[dev];
+ if (m == NULL || dev >= SOUND_MIXER_NRDEVICES)
+ return 0;
+ return m->child[dev];
}
u_int32_t
mix_getdevs(struct snd_mixer *m)
{
-return m->devs;
+ return m->devs;
}
u_int32_t
mix_getrecdevs(struct snd_mixer *m)
{
-return m->recdevs;
+ return m->recdevs;
}
void *
mix_getdevinfo(struct snd_mixer *m)
{
-return m->devinfo;
+ return m->devinfo;
+}
+
+static struct snd_mixer *
+mixer_obj_create(device_t dev, kobj_class_t cls, void *devinfo,
+ int type, const char *desc)
+{
+ struct snd_mixer *m;
+ int i;
+
+ KASSERT(dev != NULL && cls != NULL && devinfo != NULL,
+ ("%s(): NULL data dev=%p cls=%p devinfo=%p",
+ __func__, dev, cls, devinfo));
+ KASSERT(type == MIXER_TYPE_PRIMARY || type == MIXER_TYPE_SECONDARY,
+ ("invalid mixer type=%d", type));
+
+ m = (struct snd_mixer *)kobj_create(cls, M_MIXER, M_WAITOK | M_ZERO);
+ snprintf(m->name, sizeof(m->name), "%s:mixer",
+ device_get_nameunit(dev));
+ if (desc != NULL) {
+ strlcat(m->name, ":", sizeof(m->name));
+ strlcat(m->name, desc, sizeof(m->name));
+ }
+ m->lock = snd_mtxcreate(m->name, (type == MIXER_TYPE_PRIMARY) ?
+ "primary pcm mixer" : "secondary pcm mixer");
+ m->type = type;
+ m->devinfo = devinfo;
+ m->busy = 0;
+ m->dev = dev;
+ for (i = 0; i < (sizeof(m->parent) / sizeof(m->parent[0])); i++) {
+ m->parent[i] = SOUND_MIXER_NONE;
+ m->child[i] = 0;
+ m->realdev[i] = i;
+ }
+
+ if (MIXER_INIT(m)) {
+ snd_mtxlock(m->lock);
+ snd_mtxfree(m->lock);
+ kobj_delete((kobj_t)m, M_MIXER);
+ return (NULL);
+ }
+
+ return (m);
+}
+
+int
+mixer_delete(struct snd_mixer *m)
+{
+ KASSERT(m != NULL, ("NULL snd_mixer"));
+ KASSERT(m->type == MIXER_TYPE_SECONDARY,
+ ("%s(): illegal mixer type=%d", __func__, m->type));
+
+ snd_mtxlock(m->lock);
+
+ MIXER_UNINIT(m);
+
+ snd_mtxfree(m->lock);
+ kobj_delete((kobj_t)m, M_MIXER);
+
+ --mixer_count;
+
+ return (0);
+}
+
+struct snd_mixer *
+mixer_create(device_t dev, kobj_class_t cls, void *devinfo, const char *desc)
+{
+ struct snd_mixer *m;
+
+ m = mixer_obj_create(dev, cls, devinfo, MIXER_TYPE_SECONDARY, desc);
+
+ if (m != NULL)
+ ++mixer_count;
+
+ return (m);
}
int
mixer_init(device_t dev, kobj_class_t cls, void *devinfo)
{
-struct snddev_info *snddev;
-struct snd_mixer *m;
-u_int16_t v;
-struct cdev *pdev;
-int i, unit, val;
-
-m = (struct snd_mixer *)kobj_create(cls, M_MIXER, M_WAITOK | M_ZERO);
-snprintf(m->name, MIXER_NAMELEN, "%s:mixer", device_get_nameunit(dev));
-m->lock = snd_mtxcreate(m->name, "pcm mixer");
-m->type = cls->name;
-m->devinfo = devinfo;
-m->busy = 0;
-m->dev = dev;
-for (i = 0; i < 32; i++) {
-m->parent[i] = SOUND_MIXER_NONE;
-m->child[i] = 0;
-m->realdev[i] = i;
-}
-
-if (MIXER_INIT(m))
-goto bad;
-
-for (i = 0; i < SOUND_MIXER_NRDEVICES; i++) {
-v = snd_mixerdefaults[i];
-
-if (resource_int_value(device_get_name(dev),
-device_get_unit(dev), snd_mixernames[i], &val) == 0) {
-if (val >= 0 && val <= 100) {
-v = (u_int16_t) val;
-}
-}
-
-mixer_set(m, i, v | (v << 8));
-}
-
-mixer_setrecsrc(m, SOUND_MASK_MIC);
-
-unit = device_get_unit(dev);
-pdev = make_dev(&mixer_cdevsw, PCMMKMINOR(unit, SND_DEV_CTL, 0),
-UID_ROOT, GID_WHEEL, 0666, "mixer%d", unit);
-pdev->si_drv1 = m;
-snddev = device_get_softc(dev);
-snddev->mixer_dev = pdev;
-
-if (bootverbose) {
-for (i = 0; i < SOUND_MIXER_NRDEVICES; i++) {
-if (!(m->devs & (1 << i)))
-continue;
-if (m->realdev[i] != i) {
-device_printf(dev, "Mixer \"%s\" -> \"%s\":",
-snd_mixernames[i],
-(m->realdev[i] < SOUND_MIXER_NRDEVICES) ?
-snd_mixernames[m->realdev[i]] : "none");
-} else {
-device_printf(dev, "Mixer \"%s\":",
-snd_mixernames[i]);
-}
-if (m->parent[i] < SOUND_MIXER_NRDEVICES)
-printf(" parent=\"%s\"",
-snd_mixernames[m->parent[i]]);
-if (m->child[i] != 0)
-printf(" child=0x%08x", m->child[i]);
-printf("n");
-}
-if (snddev->flags & SD_F_SOFTPCMVOL)
-device_printf(dev, "Soft PCM mixer ENABLEDn");
-}
-
-return 0;
-
-bad:
-snd_mtxlock(m->lock);
-snd_mtxfree(m->lock);
-kobj_delete((kobj_t)m, M_MIXER);
-return -1;
+ struct snddev_info *snddev;
+ struct snd_mixer *m;
+ u_int16_t v;
+ struct cdev *pdev;
+ int i, unit, devunit, val;
+
+ m = mixer_obj_create(dev, cls, devinfo, MIXER_TYPE_PRIMARY, NULL);
+ if (m == NULL)
+ return (-1);
+
+ for (i = 0; i < SOUND_MIXER_NRDEVICES; i++) {
+ v = snd_mixerdefaults[i];
+
+ if (resource_int_value(device_get_name(dev),
+ device_get_unit(dev), snd_mixernames[i], &val) == 0) {
+ if (val >= 0 && val <= 100) {
+ v = (u_int16_t) val;
+ }
+ }
+
+ mixer_set(m, i, v | (v << 8));
+ }
+
+ mixer_setrecsrc(m, SOUND_MASK_MIC);
+
+ unit = device_get_unit(dev);
+ devunit = snd_mkunit(unit, SND_DEV_CTL, 0);
+ pdev = make_dev(&mixer_cdevsw, unit2minor(devunit),
+ UID_ROOT, GID_WHEEL, 0666, "mixer%d", unit);
+ pdev->si_drv1 = m;
+ snddev = device_get_softc(dev);
+ snddev->mixer_dev = pdev;
+
+ ++mixer_count;
+
+ if (bootverbose) {
+ for (i = 0; i < SOUND_MIXER_NRDEVICES; i++) {
+ if (!(m->devs & (1 << i)))
+ continue;
+ if (m->realdev[i] != i) {
+ device_printf(dev, "Mixer \"%s\" -> \"%s\":",
+ snd_mixernames[i],
+ (m->realdev[i] < SOUND_MIXER_NRDEVICES) ?
+ snd_mixernames[m->realdev[i]] : "none");
+ } else {
+ device_printf(dev, "Mixer \"%s\":",
+ snd_mixernames[i]);
+ }
+ if (m->parent[i] < SOUND_MIXER_NRDEVICES)
+ printf(" parent=\"%s\"",
+ snd_mixernames[m->parent[i]]);
+ if (m->child[i] != 0)
+ printf(" child=0x%08x", m->child[i]);
+ printf("\n");
+ }
+ if (snddev->flags & SD_F_SOFTPCMVOL)
+ device_printf(dev, "Soft PCM mixer ENABLED\n");
+ }
+
+ return (0);
}
int
mixer_uninit(device_t dev)
{
-int i;
-struct snddev_info *d;
-struct snd_mixer *m;
-struct cdev *pdev;
+ int i;
+ struct snddev_info *d;
+ struct snd_mixer *m;
+ struct cdev *pdev;
-d = device_get_softc(dev);
-pdev = mixer_get_devt(dev);
-if (d == NULL || pdev == NULL || pdev->si_drv1 == NULL)
-return EBADF;
-m = pdev->si_drv1;
-snd_mtxlock(m->lock);
+ d = device_get_softc(dev);
+ pdev = mixer_get_devt(dev);
+ if (d == NULL || pdev == NULL || pdev->si_drv1 == NULL)
+ return EBADF;
-if (m->busy) {
-snd_mtxunlock(m->lock);
-return EBUSY;
-}
+ m = pdev->si_drv1;
+ KASSERT(m != NULL, ("NULL snd_mixer"));
+ KASSERT(m->type == MIXER_TYPE_PRIMARY,
+ ("%s(): illegal mixer type=%d", __func__, m->type));
+
+ snd_mtxlock(m->lock);
+
+ if (m->busy) {
+ snd_mtxunlock(m->lock);
+ return EBUSY;
+ }
+
+ pdev->si_drv1 = NULL;
+ destroy_dev(pdev);
-pdev->si_drv1 = NULL;
-destroy_dev(pdev);
+ for (i = 0; i < SOUND_MIXER_NRDEVICES; i++)
+ mixer_set(m, i, 0);
-for (i = 0; i < SOUND_MIXER_NRDEVICES; i++)
-mixer_set(m, i, 0);
+ mixer_setrecsrc(m, SOUND_MASK_MIC);
-mixer_setrecsrc(m, SOUND_MASK_MIC);
+ MIXER_UNINIT(m);
-MIXER_UNINIT(m);
+ snd_mtxfree(m->lock);
+ kobj_delete((kobj_t)m, M_MIXER);
-snd_mtxfree(m->lock);
-kobj_delete((kobj_t)m, M_MIXER);
+ d->mixer_dev = NULL;
-d->mixer_dev = NULL;
+ --mixer_count;
-return 0;
+ return 0;
}
int
mixer_reinit(device_t dev)
{
-struct snd_mixer *m;
-struct cdev *pdev;
-int i;
+ struct snd_mixer *m;
+ struct cdev *pdev;
+ int i;
+
+ pdev = mixer_get_devt(dev);
+ m = pdev->si_drv1;
+ snd_mtxlock(m->lock);
+
+ i = MIXER_REINIT(m);
+ if (i) {
+ snd_mtxunlock(m->lock);
+ return i;
+ }
-pdev = mixer_get_devt(dev);
-m = pdev->si_drv1;
-snd_mtxlock(m->lock);
+ for (i = 0; i < SOUND_MIXER_NRDEVICES; i++)
+ mixer_set(m, i, m->level[i]);
-i = MIXER_REINIT(m);
-if (i) {
-snd_mtxunlock(m->lock);
-return i;
-}
-
-for (i = 0; i < SOUND_MIXER_NRDEVICES; i++)
-mixer_set(m, i, m->level[i]);
-
-mixer_setrecsrc(m, m->recsrc);
-snd_mtxunlock(m->lock);
+ mixer_setrecsrc(m, m->recsrc);
+ snd_mtxunlock(m->lock);
-return 0;
+ return 0;
}
#ifdef SND_DYNSYSCTL
static int
sysctl_hw_snd_hwvol_mixer(SYSCTL_HANDLER_ARGS)
{
-char devname[32];
-int error, dev;
-struct snd_mixer *m;
-
-m = oidp->oid_arg1;
-snd_mtxlock(m->lock);
-strncpy(devname, snd_mixernames[m->hwvol_mixer], sizeof(devname));
-snd_mtxunlock(m->lock);
-error = sysctl_handle_string(oidp, &devname[0], sizeof(devname), req);
-snd_mtxlock(m->lock);
-if (error == 0 && req->newptr != NULL) {
-dev = mixer_lookup(devname);
-if (dev == -1) {
-snd_mtxunlock(m->lock);
-return EINVAL;
-}
-else if (dev != m->hwvol_mixer) {
-m->hwvol_mixer = dev;
-m->hwvol_muted = 0;
-}
-}
-snd_mtxunlock(m->lock);
-return error;
+ char devname[32];
+ int error, dev;
+ struct snd_mixer *m;
+
+ m = oidp->oid_arg1;
+ snd_mtxlock(m->lock);
+ strlcpy(devname, snd_mixernames[m->hwvol_mixer], sizeof(devname));
+ snd_mtxunlock(m->lock);
+ error = sysctl_handle_string(oidp, &devname[0], sizeof(devname), req);
+ snd_mtxlock(m->lock);
+ if (error == 0 && req->newptr != NULL) {
+ dev = mixer_lookup(devname);
+ if (dev == -1) {
+ snd_mtxunlock(m->lock);
+ return EINVAL;
+ }
+ else if (dev != m->hwvol_mixer) {
+ m->hwvol_mixer = dev;
+ m->hwvol_muted = 0;
+ }
+ }
+ snd_mtxunlock(m->lock);
+ return error;
}
#endif
int
mixer_hwvol_init(device_t dev)
{
-struct snd_mixer *m;
-struct cdev *pdev;
+ struct snd_mixer *m;
+ struct cdev *pdev;
-pdev = mixer_get_devt(dev);
-m = pdev->si_drv1;
+ pdev = mixer_get_devt(dev);
+ m = pdev->si_drv1;
-m->hwvol_mixer = SOUND_MIXER_VOLUME;
-m->hwvol_step = 5;
+ m->hwvol_mixer = SOUND_MIXER_VOLUME;
+ m->hwvol_step = 5;
#ifdef SND_DYNSYSCTL
-SYSCTL_ADD_INT(snd_sysctl_tree(dev), SYSCTL_CHILDREN(snd_sysctl_tree_top(dev)),
-OID_AUTO, "hwvol_step", CTLFLAG_RW, &m->hwvol_step, 0, "");
-SYSCTL_ADD_PROC(snd_sysctl_tree(dev), SYSCTL_CHILDREN(snd_sysctl_tree_top(dev)),
-OID_AUTO, "hwvol_mixer", CTLTYPE_STRING | CTLFLAG_RW, m, 0,
-sysctl_hw_snd_hwvol_mixer, "A", "");
+ SYSCTL_ADD_INT(device_get_sysctl_ctx(dev),
+ SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
+ OID_AUTO, "hwvol_step", CTLFLAG_RW, &m->hwvol_step, 0, "");
+ SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev),
+ SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
+ OID_AUTO, "hwvol_mixer", CTLTYPE_STRING | CTLFLAG_RW, m, 0,
+ sysctl_hw_snd_hwvol_mixer, "A", "");
#endif
-return 0;
+ return 0;
}
void
mixer_hwvol_mute(device_t dev)
{
-struct snd_mixer *m;
-struct cdev *pdev;
+ struct snd_mixer *m;
+ struct cdev *pdev;
-pdev = mixer_get_devt(dev);
-m = pdev->si_drv1;
-snd_mtxlock(m->lock);
-if (m->hwvol_muted) {
-m->hwvol_muted = 0;
-mixer_set(m, m->hwvol_mixer, m->hwvol_mute_level);
-} else {
-m->hwvol_muted++;
-m->hwvol_mute_level = mixer_get(m, m->hwvol_mixer);
-mixer_set(m, m->hwvol_mixer, 0);
-}
-snd_mtxunlock(m->lock);
+ pdev = mixer_get_devt(dev);
+ m = pdev->si_drv1;
+ snd_mtxlock(m->lock);
+ if (m->hwvol_muted) {
+ m->hwvol_muted = 0;
+ mixer_set(m, m->hwvol_mixer, m->hwvol_mute_level);
+ } else {
+ m->hwvol_muted++;
+ m->hwvol_mute_level = mixer_get(m, m->hwvol_mixer);
+ mixer_set(m, m->hwvol_mixer, 0);
+ }
+ snd_mtxunlock(m->lock);
}
void
mixer_hwvol_step(device_t dev, int left_step, int right_step)
{
-struct snd_mixer *m;
-int level, left, right;
-struct cdev *pdev;
-
-pdev = mixer_get_devt(dev);
-m = pdev->si_drv1;
-snd_mtxlock(m->lock);
-if (m->hwvol_muted) {
-m->hwvol_muted = 0;
-level = m->hwvol_mute_level;
-} else
-level = mixer_get(m, m->hwvol_mixer);
-if (level != -1) {
-left = level & 0xff;
-right = level >> 8;
-left += left_step * m->hwvol_step;
-if (left < 0)
-left = 0;
-right += right_step * m->hwvol_step;
-if (right < 0)
-right = 0;
-mixer_set(m, m->hwvol_mixer, left | right << 8);
+ struct snd_mixer *m;
+ int level, left, right;
+ struct cdev *pdev;
+
+ pdev = mixer_get_devt(dev);
+ m = pdev->si_drv1;
+ snd_mtxlock(m->lock);
+ if (m->hwvol_muted) {
+ m->hwvol_muted = 0;
+ level = m->hwvol_mute_level;
+ } else
+ level = mixer_get(m, m->hwvol_mixer);
+ if (level != -1) {
+ left = level & 0xff;
+ right = level >> 8;
+ left += left_step * m->hwvol_step;
+ if (left < 0)
+ left = 0;
+ right += right_step * m->hwvol_step;
+ if (right < 0)
+ right = 0;
+ mixer_set(m, m->hwvol_mixer, left | right << 8);
+ }
+ snd_mtxunlock(m->lock);
}
-snd_mtxunlock(m->lock);
+
+int
+mixer_busy(struct snd_mixer *m)
+{
+ KASSERT(m != NULL, ("NULL snd_mixer"));
+
+ return (m->busy);
}
-/* ----------------------------------------------------------------------- */
+int
+mix_set(struct snd_mixer *m, u_int dev, u_int left, u_int right)
+{
+ int ret;
-static int
-mixer_open(struct cdev *i_dev, int flags, int mode, struct thread *td)
+ KASSERT(m != NULL, ("NULL snd_mixer"));
+
+ snd_mtxlock(m->lock);
+ ret = mixer_set(m, dev, left | (right << 8));
+ snd_mtxunlock(m->lock);
+
+ return ((ret != 0) ? ENXIO : 0);
+}
+
+int
+mix_get(struct snd_mixer *m, u_int dev)
{
-struct snd_mixer *m;
+ int ret;
-m = i_dev->si_drv1;
-snd_mtxlock(m->lock);
+ KASSERT(m != NULL, ("NULL snd_mixer"));
-m->busy++;
+ snd_mtxlock(m->lock);
+ ret = mixer_get(m, dev);
+ snd_mtxunlock(m->lock);
-snd_mtxunlock(m->lock);
-return 0;
+ return (ret);
}
-static int
-mixer_close(struct cdev *i_dev, int flags, int mode, struct thread *td)
+int
+mix_setrecsrc(struct snd_mixer *m, u_int32_t src)
{
-struct snd_mixer *m;
+ int ret;
+
+ KASSERT(m != NULL, ("NULL snd_mixer"));
-m = i_dev->si_drv1;
-snd_mtxlock(m->lock);
+ snd_mtxlock(m->lock);
+ ret = mixer_setrecsrc(m, src);
+ snd_mtxunlock(m->lock);
-if (!m->busy) {
-snd_mtxunlock(m->lock);
-return EBADF;
+ return ((ret != 0) ? ENXIO : 0);
}
-m->busy--;
-snd_mtxunlock(m->lock);
-return 0;
+u_int32_t
+mix_getrecsrc(struct snd_mixer *m)
+{
+ u_int32_t ret;
+
+ KASSERT(m != NULL, ("NULL snd_mixer"));
+
+ snd_mtxlock(m->lock);
+ ret = mixer_getrecsrc(m);
+ snd_mtxunlock(m->lock);
+
+ return (ret);
}
int
-mixer_ioctl(struct cdev *i_dev, u_long cmd, caddr_t arg, int mode, struct thread *td)
+mix_get_type(struct snd_mixer *m)
{
-struct snd_mixer *m;
-int ret, *arg_i = (int *)arg;
-int v = -1, j = cmd & 0xff;
+ KASSERT(m != NULL, ("NULL snd_mixer"));
-m = i_dev->si_drv1;
+ return (m->type);
+}
-if (m == NULL)
-return EBADF;
+/* ----------------------------------------------------------------------- */
-snd_mtxlock(m->lock);
-if (mode != -1 && !m->busy) {
-snd_mtxunlock(m->lock);
-return EBADF;
+static int
+mixer_open(struct cdev *i_dev, int flags, int mode, struct thread *td)
+{
+ struct snddev_info *d;
+ struct snd_mixer *m;
+
+
+ if (i_dev == NULL || i_dev->si_drv1 == NULL)
+ return (EBADF);
+
+ m = i_dev->si_drv1;
+ d = device_get_softc(m->dev);
+ if (!PCM_REGISTERED(d))
+ return (EBADF);
+
+ /* XXX Need Giant magic entry ??? */
+
+ snd_mtxlock(m->lock);
+ m->busy = 1;
+ snd_mtxunlock(m->lock);
+
+ return (0);
}
-if ((cmd & MIXER_WRITE(0)) == MIXER_WRITE(0)) {
-if (j == SOUND_MIXER_RECSRC)
-ret = mixer_setrecsrc(m, *arg_i);
-else
-ret = mixer_set(m, j, *arg_i);
-snd_mtxunlock(m->lock);
-return (ret == 0)? 0 : ENXIO;
+static int
+mixer_close(struct cdev *i_dev, int flags, int mode, struct thread *td)
+{
+ struct snddev_info *d;
+ struct snd_mixer *m;
+ int ret;
+
+ if (i_dev == NULL || i_dev->si_drv1 == NULL)
+ return (EBADF);
+
+ m = i_dev->si_drv1;
+ d = device_get_softc(m->dev);
+ if (!PCM_REGISTERED(d))
+ return (EBADF);
+
+ /* XXX Need Giant magic entry ??? */
+
+ snd_mtxlock(m->lock);
+ ret = (m->busy == 0) ? EBADF : 0;
+ m->busy = 0;
+ snd_mtxunlock(m->lock);
+
+ return (ret);
}
-if ((cmd & MIXER_READ(0)) == MIXER_READ(0)) {
-switch (j) {
-case SOUND_MIXER_DEVMASK:
-case SOUND_MIXER_CAPS:
-case SOUND_MIXER_STEREODEVS:
-v = mix_getdevs(m);
-break;
+static int
+mixer_ioctl(struct cdev *i_dev, u_long cmd, caddr_t arg, int mode,
+ struct thread *td)
+{
+ struct snddev_info *d;
+ int ret;
-case SOUND_MIXER_RECMASK:
-v = mix_getrecdevs(m);
-break;
+ if (i_dev == NULL || i_dev->si_drv1 == NULL)
+ return (EBADF);
-case SOUND_MIXER_RECSRC:
-v = mixer_getrecsrc(m);
-break;
+ d = device_get_softc(((struct snd_mixer *)i_dev->si_drv1)->dev);
+ if (!PCM_REGISTERED(d))
+ return (EBADF);
-default:
-v = mixer_get(m, j);
-}
-*arg_i = v;
-snd_mtxunlock(m->lock);
-return (v != -1)? 0 : ENXIO;
+ PCM_GIANT_ENTER(d);
+ PCM_ACQUIRE_QUICK(d);
+
+ ret = mixer_ioctl_cmd(i_dev, cmd, arg, mode, td, MIXER_CMD_CDEV);
+
+ PCM_RELEASE_QUICK(d);
+ PCM_GIANT_LEAVE(d);
+
+ return (ret);
}
-snd_mtxunlock(m->lock);
-return ENXIO;
+
+/*
+ * XXX Make sure you can guarantee concurrency safety before calling this
+ * function, be it through Giant, PCM_CV_*, etc !
+ */
+int
+mixer_ioctl_cmd(struct cdev *i_dev, u_long cmd, caddr_t arg, int mode,
+ struct thread *td, int from)
+{
+ struct snd_mixer *m;
+ int ret, *arg_i = (int *)arg;
+ int v = -1, j = cmd & 0xff;
+
+ m = i_dev->si_drv1;
+
+ if (m == NULL)
+ return (EBADF);
+
+ snd_mtxlock(m->lock);
+ if (from == MIXER_CMD_CDEV && !m->busy) {
+ snd_mtxunlock(m->lock);
+ return (EBADF);
+ }
+
+ if (cmd == SNDCTL_MIXERINFO) {
+ snd_mtxunlock(m->lock);
+ return (mixer_oss_mixerinfo(i_dev, (oss_mixerinfo *)arg));
+ }
+
+ if ((cmd & MIXER_WRITE(0)) == MIXER_WRITE(0)) {
+ if (j == SOUND_MIXER_RECSRC)
+ ret = mixer_setrecsrc(m, *arg_i);
+ else
+ ret = mixer_set(m, j, *arg_i);
+ snd_mtxunlock(m->lock);
+ return ((ret == 0) ? 0 : ENXIO);
+ }
+
+ if ((cmd & MIXER_READ(0)) == MIXER_READ(0)) {
+ switch (j) {
+ case SOUND_MIXER_DEVMASK:
+ case SOUND_MIXER_CAPS:
+ case SOUND_MIXER_STEREODEVS:
+ v = mix_getdevs(m);
+ break;
+
+ case SOUND_MIXER_RECMASK:
+ v = mix_getrecdevs(m);
+ break;
+
+ case SOUND_MIXER_RECSRC:
+ v = mixer_getrecsrc(m);
+ break;
+
+ default:
+ v = mixer_get(m, j);
+ }
+ *arg_i = v;
+ snd_mtxunlock(m->lock);
+ return ((v != -1) ? 0 : ENXIO);
+ }
+
+ ret = 0;
+
+ switch (cmd) {
+ /** @todo Double check return values, error codes. */
+ case SNDCTL_SYSINFO:
+ snd_mtxunlock(m->lock);
+ sound_oss_sysinfo((oss_sysinfo *)arg);
+ return (ret);
+ break;
+ case SNDCTL_AUDIOINFO:
+ snd_mtxunlock(m->lock);
+ return (dsp_oss_audioinfo(i_dev, (oss_audioinfo *)arg));
+ break;
+ case SNDCTL_DSP_GET_RECSRC_NAMES:
+ bcopy((void *)&m->enuminfo, arg, sizeof(oss_mixer_enuminfo));
+ break;
+ case SNDCTL_DSP_GET_RECSRC:
+ ret = mixer_get_recroute(m, arg_i);
+ break;
+ case SNDCTL_DSP_SET_RECSRC:
+ ret = mixer_set_recroute(m, *arg_i);
+ break;
+ case OSS_GETVERSION:
+ *arg_i = SOUND_VERSION;
+ break;
+ default:
+ ret = ENXIO;
+ break;
+ }
+
+ snd_mtxunlock(m->lock);
+
+ return (ret);
}
#ifdef USING_DEVFS
static void
-mixer_clone(void *arg, struct ucred *cred, char *name, int namelen,
-struct cdev **dev)
+mixer_clone(void *arg,
+#if __FreeBSD_version >= 600034
+ struct ucred *cred,
+#endif
+ char *name, int namelen, struct cdev **dev)
{
-struct snddev_info *sd;
+ struct snddev_info *d;
-if (*dev != NULL)
-return;
-if (strcmp(name, "mixer") == 0) {
-sd = devclass_get_softc(pcm_devclass, snd_unit);
-if (sd != NULL && sd->mixer_dev != NULL) {
-*dev = sd->mixer_dev;
-dev_ref(*dev);
-}
-}
+ if (*dev != NULL)
+ return;
+ if (strcmp(name, "mixer") == 0) {
+ d = devclass_get_softc(pcm_devclass, snd_unit);
+ if (PCM_REGISTERED(d) && d->mixer_dev != NULL) {
+ *dev = d->mixer_dev;
+ dev_ref(*dev);
+ }
+ }
}
static void
mixer_sysinit(void *p)
{
-mixer_ehtag = EVENTHANDLER_REGISTER(dev_clone, mixer_clone, 0, 1000);
+ if (mixer_ehtag != NULL)
+ return;
+ mixer_ehtag = EVENTHANDLER_REGISTER(dev_clone, mixer_clone, 0, 1000);
}
static void
mixer_sysuninit(void *p)
{
-if (mixer_ehtag != NULL)
-EVENTHANDLER_DEREGISTER(dev_clone, mixer_ehtag);
+ if (mixer_ehtag == NULL)
+ return;
+ EVENTHANDLER_DEREGISTER(dev_clone, mixer_ehtag);
+ mixer_ehtag = NULL;
}
SYSINIT(mixer_sysinit, SI_SUB_DRIVERS, SI_ORDER_MIDDLE, mixer_sysinit, NULL);
SYSUNINIT(mixer_sysuninit, SI_SUB_DRIVERS, SI_ORDER_MIDDLE, mixer_sysuninit, NULL);
#endif
+/**
+ * @brief Handler for SNDCTL_MIXERINFO
+ *
+ * This function searches for a mixer based on the numeric ID stored
+ * in oss_miserinfo::dev. If set to -1, then information about the
+ * current mixer handling the request is provided. Note, however, that
+ * this ioctl may be made with any sound device (audio, mixer, midi).
+ *
+ * @note Caller must not hold any PCM device, channel, or mixer locks.
+ *
+ * See http://manuals.opensound.com/developer/SNDCTL_MIXERINFO.html for
+ * more information.
+ *
+ * @param i_dev character device on which the ioctl arrived
+ * @param arg user argument (oss_mixerinfo *)
+ *
+ * @retval EINVAL oss_mixerinfo::dev specified a bad value
+ * @retval 0 success
+ */
+int
+mixer_oss_mixerinfo(struct cdev *i_dev, oss_mixerinfo *mi)
+{
+ struct snddev_info *d;
+ struct snd_mixer *m;
+ int nmix, i;
+
+ /*
+ * If probing the device handling the ioctl, make sure it's a mixer
+ * device. (This ioctl is valid on audio, mixer, and midi devices.)
+ */
+ if (mi->dev == -1 && i_dev->si_devsw != &mixer_cdevsw)
+ return (EINVAL);
+
+ d = NULL;
+ m = NULL;
+ nmix = 0;
+
+ /*
+ * There's a 1:1 relationship between mixers and PCM devices, so
+ * begin by iterating over PCM devices and search for our mixer.
+ */
+ for (i = 0; pcm_devclass != NULL &&
+ i < devclass_get_maxunit(pcm_devclass); i++) {
+ d = devclass_get_softc(pcm_devclass, i);
+ if (!PCM_REGISTERED(d))
+ continue;
+
+ /* XXX Need Giant magic entry */
+
+ /* See the note in function docblock. */
+ mtx_assert(d->lock, MA_NOTOWNED);
+ pcm_lock(d);
+
+ if (d->mixer_dev != NULL && d->mixer_dev->si_drv1 != NULL &&
+ ((mi->dev == -1 && d->mixer_dev == i_dev) ||
+ mi->dev == nmix)) {
+ m = d->mixer_dev->si_drv1;
+ mtx_lock(m->lock);
+
+ /*
+ * At this point, the following synchronization stuff
+ * has happened:
+ * - a specific PCM device is locked.
+ * - a specific mixer device has been locked, so be
+ * sure to unlock when existing.
+ */
+ bzero((void *)mi, sizeof(*mi));
+ mi->dev = nmix;
+ snprintf(mi->id, sizeof(mi->id), "mixer%d", i);
+ strlcpy(mi->name, m->name, sizeof(mi->name));
+ mi->modify_counter = m->modify_counter;
+ mi->card_number = i;
+ /*
+ * Currently, FreeBSD assumes 1:1 relationship between
+ * a pcm and mixer devices, so this is hardcoded to 0.
+ */
+ mi->port_number = 0;
+
+ /**
+ * @todo Fill in @sa oss_mixerinfo::mixerhandle.
+ * @note From 4Front: "mixerhandle is an arbitrary
+ * string that identifies the mixer better than
+ * the device number (mixerinfo.dev). Device
+ * numbers may change depending on the order the
+ * drivers are loaded. However the handle should
+ * remain the same provided that the sound card
+ * is not moved to another PCI slot."
+ */
+
+ /**
+ * @note
+ * @sa oss_mixerinfo::magic is a reserved field.
+ *
+ * @par
+ * From 4Front: "magic is usually 0. However some
+ * devices may have dedicated setup utilities and the
+ * magic field may contain an unique driver specific
+ * value (managed by [4Front])."
+ */
+
+ mi->enabled = device_is_attached(m->dev) ? 1 : 0;
+ /**
+ * The only flag for @sa oss_mixerinfo::caps is
+ * currently MIXER_CAP_VIRTUAL, which I'm not sure we
+ * really worry about.
+ */
+ /**
+ * Mixer extensions currently aren't supported, so
+ * leave @sa oss_mixerinfo::nrext blank for now.
+ */
+ /**
+ * @todo Fill in @sa oss_mixerinfo::priority (requires
+ * touching drivers?)
+ * @note The priority field is for mixer applets to
+ * determine which mixer should be the default, with 0
+ * being least preferred and 10 being most preferred.
+ * From 4Front: "OSS drivers like ICH use higher
+ * values (10) because such chips are known to be used
+ * only on motherboards. Drivers for high end pro
+ * devices use 0 because they will never be the
+ * default mixer. Other devices use values 1 to 9
+ * depending on the estimated probability of being the
+ * default device.
+ *
+ * XXX Described by Hannu at 4Front, but not found in
+ * soundcard.h.
+ strlcpy(mi->devnode, d->mixer_dev->si_name,
+ sizeof(mi->devnode));
+ mi->legacy_device = i;
+ */
+ mtx_unlock(m->lock);
+ } else
+ ++nmix;
+
+ pcm_unlock(d);
+
+ if (m != NULL)
+ return (0);
+ }
+ return (EINVAL);
+}
Index: sndstat.c
===================================================================
RCS file: /home/cvs/src/sys/dev/sound/pcm/sndstat.c,v
retrieving revision 1.2
retrieving revision 1.3
diff -L sys/dev/sound/pcm/sndstat.c -L sys/dev/sound/pcm/sndstat.c -u -r1.2 -r1.3
--- sys/dev/sound/pcm/sndstat.c
+++ sys/dev/sound/pcm/sndstat.c
@@ -1,36 +1,37 @@
/*-
-* Copyright (c) 2001 Cameron Grant <cg at freebsd.org>
-* All rights reserved.
-*
-* Redistribution and use in source and binary forms, with or without
-* modification, are permitted provided that the following conditions
-* are met:
-* 1. Redistributions of source code must retain the above copyright
-* notice, this list of conditions and the following disclaimer.
-* 2. Redistributions in binary form must reproduce the above copyright
-* notice, this list of conditions and the following disclaimer in the
-* documentation and/or other materials provided with the distribution.
-*
-* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
-* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
-* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
-* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
-* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
-* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
-* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
-* SUCH DAMAGE.
-*/
+ * Copyright (c) 2001 Cameron Grant <cg at freebsd.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
#include <dev/sound/pcm/sound.h>
#include <dev/sound/pcm/vchan.h>
+#include <dev/sound/version.h>
#ifdef USING_MUTEX
#include <sys/sx.h>
#endif
-SND_DECLARE_FILE("$MidnightBSD$");
+SND_DECLARE_FILE("$FreeBSD: src/sys/dev/sound/pcm/sndstat.c,v 1.28 2007/06/16 03:37:28 ariff Exp $");
#define SS_TYPE_MODULE 0
#define SS_TYPE_FIRST 1
@@ -44,39 +45,71 @@
static d_read_t sndstat_read;
static struct cdevsw sndstat_cdevsw = {
-.d_version = D_VERSION,
-.d_flags = D_NEEDGIANT,
-.d_open = sndstat_open,
-.d_close = sndstat_close,
-.d_read = sndstat_read,
-.d_name = "sndstat",
+ .d_version = D_VERSION,
+ .d_open = sndstat_open,
+ .d_close = sndstat_close,
+ .d_read = sndstat_read,
+ .d_name = "sndstat",
};
struct sndstat_entry {
-SLIST_ENTRY(sndstat_entry) link;
-device_t dev;
-char *str;
-sndstat_handler handler;
-int type, unit;
+ SLIST_ENTRY(sndstat_entry) link;
+ device_t dev;
+ char *str;
+ sndstat_handler handler;
+ int type, unit;
};
#ifdef USING_MUTEX
-static struct sx sndstat_lock;
+static struct mtx sndstat_lock;
#endif
static struct sbuf sndstat_sbuf;
-static struct cdev *sndstat_dev = 0;
-static int sndstat_isopen = 0;
-static int sndstat_bufptr;
+static struct cdev *sndstat_dev = NULL;
+static int sndstat_bufptr = -1;
static int sndstat_maxunit = -1;
static int sndstat_files = 0;
+#define SNDSTAT_PID(x) ((pid_t)((intptr_t)((x)->si_drv1)))
+#define SNDSTAT_PID_SET(x, y) (x)->si_drv1 = (void *)((intptr_t)(y))
+#define SNDSTAT_FLUSH() do { \
+ if (sndstat_bufptr != -1) { \
+ sbuf_delete(&sndstat_sbuf); \
+ sndstat_bufptr = -1; \
+ } \
+} while(0)
+
static SLIST_HEAD(, sndstat_entry) sndstat_devlist = SLIST_HEAD_INITIALIZER(none);
-static int sndstat_verbose = 1;
+int snd_verbose = 1;
#ifdef USING_MUTEX
-TUNABLE_INT("hw.snd.verbose", &sndstat_verbose);
+TUNABLE_INT("hw.snd.verbose", &snd_verbose);
#else
-TUNABLE_INT_DECL("hw.snd.verbose", 1, sndstat_verbose);
+TUNABLE_INT_DECL("hw.snd.verbose", 1, snd_verbose);
+#endif
+
+#ifdef SND_DEBUG
+static int
+sysctl_hw_snd_sndstat_pid(SYSCTL_HANDLER_ARGS)
+{
+ int err, val;
+
+ if (sndstat_dev == NULL)
+ return (EINVAL);
+
+ mtx_lock(&sndstat_lock);
+ val = (int)SNDSTAT_PID(sndstat_dev);
+ mtx_unlock(&sndstat_lock);
+ err = sysctl_handle_int(oidp, &val, 0, req);
+ if (err == 0 && req->newptr != NULL && val == 0) {
+ mtx_lock(&sndstat_lock);
+ SNDSTAT_FLUSH();
+ SNDSTAT_PID_SET(sndstat_dev, 0);
+ mtx_unlock(&sndstat_lock);
+ }
+ return (err);
+}
+SYSCTL_PROC(_hw_snd, OID_AUTO, sndstat_pid, CTLTYPE_INT | CTLFLAG_RW,
+ 0, sizeof(int), sysctl_hw_snd_sndstat_pid, "I", "sndstat busy pid");
#endif
static int sndstat_prepare(struct sbuf *s);
@@ -84,81 +117,97 @@
static int
sysctl_hw_sndverbose(SYSCTL_HANDLER_ARGS)
{
-int error, verbose;
+ int error, verbose;
-verbose = sndstat_verbose;
-error = sysctl_handle_int(oidp, &verbose, sizeof(verbose), req);
-if (error == 0 && req->newptr != NULL) {
-sx_xlock(&sndstat_lock);
-if (verbose < 0 || verbose > 3)
-error = EINVAL;
-else
-sndstat_verbose = verbose;
-sx_xunlock(&sndstat_lock);
-}
-return error;
+ verbose = snd_verbose;
+ error = sysctl_handle_int(oidp, &verbose, 0, req);
+ if (error == 0 && req->newptr != NULL) {
+ mtx_lock(&sndstat_lock);
+ if (verbose < 0 || verbose > 4)
+ error = EINVAL;
+ else
+ snd_verbose = verbose;
+ mtx_unlock(&sndstat_lock);
+ }
+ return error;
}
SYSCTL_PROC(_hw_snd, OID_AUTO, verbose, CTLTYPE_INT | CTLFLAG_RW,
-0, sizeof(int), sysctl_hw_sndverbose, "I", "");
+ 0, sizeof(int), sysctl_hw_sndverbose, "I", "verbosity level");
static int
sndstat_open(struct cdev *i_dev, int flags, int mode, struct thread *td)
{
-int error;
+ if (sndstat_dev == NULL || i_dev != sndstat_dev)
+ return EBADF;
-sx_xlock(&sndstat_lock);
-if (sndstat_isopen) {
-sx_xunlock(&sndstat_lock);
-return EBUSY;
-}
-sndstat_isopen = 1;
-sx_xunlock(&sndstat_lock);
-if (sbuf_new(&sndstat_sbuf, NULL, 4096, 0) == NULL) {
-error = ENXIO;
-goto out;
-}
-sndstat_bufptr = 0;
-error = (sndstat_prepare(&sndstat_sbuf) > 0) ? 0 : ENOMEM;
-out:
-if (error) {
-sx_xlock(&sndstat_lock);
-sndstat_isopen = 0;
-sx_xunlock(&sndstat_lock);
-}
-return (error);
+ mtx_lock(&sndstat_lock);
+ if (SNDSTAT_PID(i_dev) != 0) {
+ mtx_unlock(&sndstat_lock);
+ return EBUSY;
+ }
+ SNDSTAT_PID_SET(i_dev, td->td_proc->p_pid);
+ mtx_unlock(&sndstat_lock);
+ if (sbuf_new(&sndstat_sbuf, NULL, 4096, SBUF_AUTOEXTEND) == NULL) {
+ mtx_lock(&sndstat_lock);
+ SNDSTAT_PID_SET(i_dev, 0);
+ mtx_unlock(&sndstat_lock);
+ return ENXIO;
+ }
+ sndstat_bufptr = 0;
+ return 0;
}
static int
sndstat_close(struct cdev *i_dev, int flags, int mode, struct thread *td)
{
-sx_xlock(&sndstat_lock);
-if (!sndstat_isopen) {
-sx_xunlock(&sndstat_lock);
-return EBADF;
-}
-sbuf_delete(&sndstat_sbuf);
-sndstat_isopen = 0;
+ if (sndstat_dev == NULL || i_dev != sndstat_dev)
+ return EBADF;
-sx_xunlock(&sndstat_lock);
-return 0;
+ mtx_lock(&sndstat_lock);
+ if (SNDSTAT_PID(i_dev) == 0) {
+ mtx_unlock(&sndstat_lock);
+ return EBADF;
+ }
+
+ SNDSTAT_FLUSH();
+ SNDSTAT_PID_SET(i_dev, 0);
+
+ mtx_unlock(&sndstat_lock);
+
+ return 0;
}
static int
sndstat_read(struct cdev *i_dev, struct uio *buf, int flag)
{
-int l, err;
+ int l, err;
-sx_xlock(&sndstat_lock);
-if (!sndstat_isopen) {
-sx_xunlock(&sndstat_lock);
-return EBADF;
-}
-l = min(buf->uio_resid, sbuf_len(&sndstat_sbuf) - sndstat_bufptr);
-err = (l > 0)? uiomove(sbuf_data(&sndstat_sbuf) + sndstat_bufptr, l, buf) : 0;
-sndstat_bufptr += l;
+ if (sndstat_dev == NULL || i_dev != sndstat_dev)
+ return EBADF;
-sx_xunlock(&sndstat_lock);
-return err;
+ mtx_lock(&sndstat_lock);
+ if (SNDSTAT_PID(i_dev) != buf->uio_td->td_proc->p_pid ||
+ sndstat_bufptr == -1) {
+ mtx_unlock(&sndstat_lock);
+ return EBADF;
+ }
+ mtx_unlock(&sndstat_lock);
+
+ if (sndstat_bufptr == 0) {
+ err = (sndstat_prepare(&sndstat_sbuf) > 0) ? 0 : ENOMEM;
+ if (err) {
+ mtx_lock(&sndstat_lock);
+ SNDSTAT_FLUSH();
+ mtx_unlock(&sndstat_lock);
+ return err;
+ }
+ }
+
+ l = min(buf->uio_resid, sbuf_len(&sndstat_sbuf) - sndstat_bufptr);
+ err = (l > 0)? uiomove(sbuf_data(&sndstat_sbuf) + sndstat_bufptr, l, buf) : 0;
+ sndstat_bufptr += l;
+
+ return err;
}
/************************************************************************/
@@ -166,130 +215,133 @@
static struct sndstat_entry *
sndstat_find(int type, int unit)
{
-struct sndstat_entry *ent;
+ struct sndstat_entry *ent;
-SLIST_FOREACH(ent, &sndstat_devlist, link) {
-if (ent->type == type && ent->unit == unit)
-return ent;
-}
+ SLIST_FOREACH(ent, &sndstat_devlist, link) {
+ if (ent->type == type && ent->unit == unit)
+ return ent;
+ }
-return NULL;
+ return NULL;
}
int
-sndstat_acquire(void)
+sndstat_acquire(struct thread *td)
{
-sx_xlock(&sndstat_lock);
-if (sndstat_isopen) {
-sx_xunlock(&sndstat_lock);
-return EBUSY;
-}
-sndstat_isopen = 1;
-sx_xunlock(&sndstat_lock);
-return 0;
+ if (sndstat_dev == NULL)
+ return EBADF;
+
+ mtx_lock(&sndstat_lock);
+ if (SNDSTAT_PID(sndstat_dev) != 0) {
+ mtx_unlock(&sndstat_lock);
+ return EBUSY;
+ }
+ SNDSTAT_PID_SET(sndstat_dev, td->td_proc->p_pid);
+ mtx_unlock(&sndstat_lock);
+ return 0;
}
int
-sndstat_release(void)
+sndstat_release(struct thread *td)
{
-sx_xlock(&sndstat_lock);
-if (!sndstat_isopen) {
-sx_xunlock(&sndstat_lock);
-return EBADF;
-}
-sndstat_isopen = 0;
-sx_xunlock(&sndstat_lock);
-return 0;
+ if (sndstat_dev == NULL)
+ return EBADF;
+
+ mtx_lock(&sndstat_lock);
+ if (SNDSTAT_PID(sndstat_dev) != td->td_proc->p_pid) {
+ mtx_unlock(&sndstat_lock);
+ return EBADF;
+ }
+ SNDSTAT_PID_SET(sndstat_dev, 0);
+ mtx_unlock(&sndstat_lock);
+ return 0;
}
int
sndstat_register(device_t dev, char *str, sndstat_handler handler)
{
-struct sndstat_entry *ent;
-const char *devtype;
-int type, unit;
-
-if (dev) {
-unit = device_get_unit(dev);
-devtype = device_get_name(dev);
-if (!strcmp(devtype, "pcm"))
-type = SS_TYPE_PCM;
-else if (!strcmp(devtype, "midi"))
-type = SS_TYPE_MIDI;
-else if (!strcmp(devtype, "sequencer"))
-type = SS_TYPE_SEQUENCER;
-else
-return EINVAL;
-} else {
-type = SS_TYPE_MODULE;
-unit = -1;
-}
-
-ent = malloc(sizeof *ent, M_DEVBUF, M_ZERO | M_WAITOK);
-if (!ent)
-return ENOSPC;
-
-ent->dev = dev;
-ent->str = str;
-ent->type = type;
-ent->unit = unit;
-ent->handler = handler;
-
-sx_xlock(&sndstat_lock);
-SLIST_INSERT_HEAD(&sndstat_devlist, ent, link);
-if (type == SS_TYPE_MODULE)
-sndstat_files++;
-sndstat_maxunit = (unit > sndstat_maxunit)? unit : sndstat_maxunit;
-sx_xunlock(&sndstat_lock);
+ struct sndstat_entry *ent;
+ const char *devtype;
+ int type, unit;
+
+ if (dev) {
+ unit = device_get_unit(dev);
+ devtype = device_get_name(dev);
+ if (!strcmp(devtype, "pcm"))
+ type = SS_TYPE_PCM;
+ else if (!strcmp(devtype, "midi"))
+ type = SS_TYPE_MIDI;
+ else if (!strcmp(devtype, "sequencer"))
+ type = SS_TYPE_SEQUENCER;
+ else
+ return EINVAL;
+ } else {
+ type = SS_TYPE_MODULE;
+ unit = -1;
+ }
+
+ ent = malloc(sizeof *ent, M_DEVBUF, M_WAITOK | M_ZERO);
+ ent->dev = dev;
+ ent->str = str;
+ ent->type = type;
+ ent->unit = unit;
+ ent->handler = handler;
+
+ mtx_lock(&sndstat_lock);
+ SLIST_INSERT_HEAD(&sndstat_devlist, ent, link);
+ if (type == SS_TYPE_MODULE)
+ sndstat_files++;
+ sndstat_maxunit = (unit > sndstat_maxunit)? unit : sndstat_maxunit;
+ mtx_unlock(&sndstat_lock);
-return 0;
+ return 0;
}
int
sndstat_registerfile(char *str)
{
-return sndstat_register(NULL, str, NULL);
+ return sndstat_register(NULL, str, NULL);
}
int
sndstat_unregister(device_t dev)
{
-struct sndstat_entry *ent;
-
-sx_xlock(&sndstat_lock);
-SLIST_FOREACH(ent, &sndstat_devlist, link) {
-if (ent->dev == dev) {
-SLIST_REMOVE(&sndstat_devlist, ent, sndstat_entry, link);
-sx_xunlock(&sndstat_lock);
-free(ent, M_DEVBUF);
+ struct sndstat_entry *ent;
-return 0;
-}
-}
-sx_xunlock(&sndstat_lock);
+ mtx_lock(&sndstat_lock);
+ SLIST_FOREACH(ent, &sndstat_devlist, link) {
+ if (ent->dev == dev) {
+ SLIST_REMOVE(&sndstat_devlist, ent, sndstat_entry, link);
+ mtx_unlock(&sndstat_lock);
+ free(ent, M_DEVBUF);
+
+ return 0;
+ }
+ }
+ mtx_unlock(&sndstat_lock);
-return ENXIO;
+ return ENXIO;
}
int
sndstat_unregisterfile(char *str)
{
-struct sndstat_entry *ent;
+ struct sndstat_entry *ent;
-sx_xlock(&sndstat_lock);
-SLIST_FOREACH(ent, &sndstat_devlist, link) {
-if (ent->dev == NULL && ent->str == str) {
-SLIST_REMOVE(&sndstat_devlist, ent, sndstat_entry, link);
-sndstat_files--;
-sx_xunlock(&sndstat_lock);
-free(ent, M_DEVBUF);
+ mtx_lock(&sndstat_lock);
+ SLIST_FOREACH(ent, &sndstat_devlist, link) {
+ if (ent->dev == NULL && ent->str == str) {
+ SLIST_REMOVE(&sndstat_devlist, ent, sndstat_entry, link);
+ sndstat_files--;
+ mtx_unlock(&sndstat_lock);
+ free(ent, M_DEVBUF);
+
+ return 0;
+ }
+ }
+ mtx_unlock(&sndstat_lock);
-return 0;
-}
-}
-sx_xunlock(&sndstat_lock);
-
-return ENXIO;
+ return ENXIO;
}
/************************************************************************/
@@ -297,90 +349,104 @@
static int
sndstat_prepare(struct sbuf *s)
{
-struct sndstat_entry *ent;
-int i, j;
-
-sbuf_printf(s, "FreeBSD Audio Driver (newpcm)n");
-if (SLIST_EMPTY(&sndstat_devlist)) {
-sbuf_printf(s, "No devices installed.n");
-sbuf_finish(s);
-return sbuf_len(s);
-}
-
-sbuf_printf(s, "Installed devices:n");
+ struct sndstat_entry *ent;
+ struct snddev_info *d;
+ int i, j;
+
+ sbuf_printf(s, "FreeBSD Audio Driver (newpcm: %ubit %d/%s)\n",
+ (u_int)sizeof(intpcm_t) << 3, SND_DRV_VERSION, MACHINE_ARCH);
+ if (SLIST_EMPTY(&sndstat_devlist)) {
+ sbuf_printf(s, "No devices installed.\n");
+ sbuf_finish(s);
+ return sbuf_len(s);
+ }
+
+ sbuf_printf(s, "Installed devices:\n");
+
+ for (i = 0; i <= sndstat_maxunit; i++) {
+ for (j = SS_TYPE_FIRST; j <= SS_TYPE_LAST; j++) {
+ ent = sndstat_find(j, i);
+ if (!ent)
+ continue;
+ d = device_get_softc(ent->dev);
+ if (!PCM_REGISTERED(d))
+ continue;
+ /* XXX Need Giant magic entry ??? */
+ PCM_ACQUIRE_QUICK(d);
+ sbuf_printf(s, "%s:", device_get_nameunit(ent->dev));
+ sbuf_printf(s, " <%s>", device_get_desc(ent->dev));
+ sbuf_printf(s, " %s [%s]", ent->str,
+ (d->flags & SD_F_MPSAFE) ? "MPSAFE" : "GIANT");
+ if (ent->handler)
+ ent->handler(s, ent->dev, snd_verbose);
+ else
+ sbuf_printf(s, " [no handler]");
+ sbuf_printf(s, "\n");
+ PCM_RELEASE_QUICK(d);
+ }
+ }
+
+ if (snd_verbose >= 3 && sndstat_files > 0) {
+ sbuf_printf(s, "\nFile Versions:\n");
+
+ SLIST_FOREACH(ent, &sndstat_devlist, link) {
+ if (ent->dev == NULL && ent->str != NULL)
+ sbuf_printf(s, "%s\n", ent->str);
+ }
+ }
-for (i = 0; i <= sndstat_maxunit; i++) {
-for (j = SS_TYPE_FIRST; j <= SS_TYPE_LAST; j++) {
-ent = sndstat_find(j, i);
-if (!ent)
-continue;
-sbuf_printf(s, "%s:", device_get_nameunit(ent->dev));
-sbuf_printf(s, " <%s>", device_get_desc(ent->dev));
-sbuf_printf(s, " %s", ent->str);
-if (ent->handler)
-ent->handler(s, ent->dev, sndstat_verbose);
-else
-sbuf_printf(s, " [no handler]");
-sbuf_printf(s, "n");
-}
-}
-
-if (sndstat_verbose >= 3 && sndstat_files > 0) {
-sbuf_printf(s, "nFile Versions:n");
-
-SLIST_FOREACH(ent, &sndstat_devlist, link) {
-if (ent->dev == NULL && ent->str != NULL)
-sbuf_printf(s, "%sn", ent->str);
-}
-}
-
-sbuf_finish(s);
-return sbuf_len(s);
+ sbuf_finish(s);
+ return sbuf_len(s);
}
static int
sndstat_init(void)
{
-sx_init(&sndstat_lock, "sndstat");
-sndstat_dev = make_dev(&sndstat_cdevsw, SND_DEV_STATUS, UID_ROOT, GID_WHEEL, 0444, "sndstat");
-
-return (sndstat_dev != 0)? 0 : ENXIO;
+ if (sndstat_dev != NULL)
+ return EINVAL;
+ mtx_init(&sndstat_lock, "sndstat", "sndstat lock", MTX_DEF);
+ sndstat_dev = make_dev(&sndstat_cdevsw, SND_DEV_STATUS,
+ UID_ROOT, GID_WHEEL, 0444, "sndstat");
+ return 0;
}
static int
sndstat_uninit(void)
{
-sx_xlock(&sndstat_lock);
-if (sndstat_isopen) {
-sx_xunlock(&sndstat_lock);
-return EBUSY;
-}
+ if (sndstat_dev == NULL)
+ return EINVAL;
+
+ mtx_lock(&sndstat_lock);
+ if (SNDSTAT_PID(sndstat_dev) != curthread->td_proc->p_pid) {
+ mtx_unlock(&sndstat_lock);
+ return EBUSY;
+ }
-if (sndstat_dev)
-destroy_dev(sndstat_dev);
-sndstat_dev = 0;
-
-sx_xunlock(&sndstat_lock);
-sx_destroy(&sndstat_lock);
-return 0;
+ SNDSTAT_FLUSH();
+
+ mtx_unlock(&sndstat_lock);
+
+ destroy_dev(sndstat_dev);
+ sndstat_dev = NULL;
+
+ mtx_destroy(&sndstat_lock);
+ return 0;
}
static void
sndstat_sysinit(void *p)
{
-sndstat_init();
+ sndstat_init();
}
static void
sndstat_sysuninit(void *p)
{
-int error;
+ int error;
-error = sndstat_uninit();
-KASSERT(error == 0, ("%s: error = %d", __func__, error));
+ error = sndstat_uninit();
+ KASSERT(error == 0, ("%s: error = %d", __func__, error));
}
SYSINIT(sndstat_sysinit, SI_SUB_DRIVERS, SI_ORDER_FIRST, sndstat_sysinit, NULL);
SYSUNINIT(sndstat_sysuninit, SI_SUB_DRIVERS, SI_ORDER_FIRST, sndstat_sysuninit, NULL);
-
-
Index: ac97_patch.c
===================================================================
RCS file: /home/cvs/src/sys/dev/sound/pcm/ac97_patch.c,v
retrieving revision 1.2
retrieving revision 1.3
diff -L sys/dev/sound/pcm/ac97_patch.c -L sys/dev/sound/pcm/ac97_patch.c -u -r1.2 -r1.3
--- sys/dev/sound/pcm/ac97_patch.c
+++ sys/dev/sound/pcm/ac97_patch.c
@@ -1,64 +1,113 @@
/*-
-* Copyright 2002 FreeBSD, Inc. All rights reserved.
-*
-* Redistribution and use in source and binary forms, with or without
-* modification, are permitted provided that the following conditions
-* are met:
-* 1. Redistributions of source code must retain the above copyright
-* notice, this list of conditions and the following disclaimer.
-* 2. Redistributions in binary form must reproduce the above copyright
-* notice, this list of conditions and the following disclaimer in the
-* documentation and/or other materials provided with the distribution.
-*
-* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
-* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
-* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
-* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
-* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
-* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
-* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
-* SUCH DAMAGE.
-*/
+ * Copyright (c) 2002 Orion Hodson
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
#include <dev/sound/pcm/sound.h>
#include <dev/sound/pcm/ac97.h>
#include <dev/sound/pcm/ac97_patch.h>
-SND_DECLARE_FILE("$MidnightBSD$");
+SND_DECLARE_FILE("$FreeBSD: src/sys/dev/sound/pcm/ac97_patch.c,v 1.10.2.1 2007/10/29 18:47:27 ariff Exp $");
void ad1886_patch(struct ac97_info* codec)
{
#define AC97_AD_JACK_SPDIF 0x72
-/*
-* Presario700 workaround
-* for Jack Sense/SPDIF Register misetting causing
-* no audible output
-* by Santiago Nullo 04/05/2002
-*/
-ac97_wrcd(codec, AC97_AD_JACK_SPDIF, 0x0010);
+ /*
+ * Presario700 workaround
+ * for Jack Sense/SPDIF Register misetting causing
+ * no audible output
+ * by Santiago Nullo 04/05/2002
+ */
+ ac97_wrcd(codec, AC97_AD_JACK_SPDIF, 0x0010);
}
void ad198x_patch(struct ac97_info* codec)
{
-ac97_wrcd(codec, 0x76, ac97_rdcd(codec, 0x76) | 0x0420);
+ switch (ac97_getsubvendor(codec)) {
+ case 0x11931043: /* Not for ASUS A9T (probably else too). */
+ break;
+ default:
+ ac97_wrcd(codec, 0x76, ac97_rdcd(codec, 0x76) | 0x0420);
+ break;
+ }
}
void ad1981b_patch(struct ac97_info* codec)
{
-/*ac97_wrcd(codec, AC97_AD_JACK_SPDIF,
-ac97_rdcd(codec, AC97_AD_JACK_SPDIF) | 0x0800);*/
+ /*
+ * Enable headphone jack sensing.
+ */
+ switch (ac97_getsubvendor(codec)) {
+ case 0x02d91014: /* IBM Thinkcentre */
+ case 0x099c103c: /* HP nx6110 */
+ ac97_wrcd(codec, AC97_AD_JACK_SPDIF,
+ ac97_rdcd(codec, AC97_AD_JACK_SPDIF) | 0x0800);
+ break;
+ default:
+ break;
+ }
}
void cmi9739_patch(struct ac97_info* codec)
{
-/*
-* Few laptops (notably ASUS W1000N) need extra register
-* initialization to power up the internal speakers.
-*/
-ac97_wrcd(codec, AC97_REG_POWER, 0x000f);
-ac97_wrcd(codec, AC97_MIXEXT_CLFE, 0x0000);
-ac97_wrcd(codec, 0x64, 0x7110);
+ /*
+ * Few laptops need extra register initialization
+ * to power up the internal speakers.
+ */
+ switch (ac97_getsubvendor(codec)) {
+ case 0x18431043: /* ASUS W1000N */
+ ac97_wrcd(codec, AC97_REG_POWER, 0x000f);
+ ac97_wrcd(codec, AC97_MIXEXT_CLFE, 0x0000);
+ ac97_wrcd(codec, 0x64, 0x7110);
+ break;
+ default:
+ break;
+ }
+}
+
+void alc655_patch(struct ac97_info* codec)
+{
+ /*
+ * MSI (Micro-Star International) specific EAPD quirk.
+ */
+ switch (ac97_getsubvendor(codec)) {
+ case 0x00611462: /* MSI S250 */
+ case 0x01311462: /* MSI S270 */
+ case 0x01611462: /* LG K1 Express */
+ case 0x03511462: /* MSI L725 */
+ ac97_wrcd(codec, 0x7a, ac97_rdcd(codec, 0x7a) & 0xfffd);
+ break;
+ case 0x10ca1734:
+ /*
+ * Amilo Pro V2055 with ALC655 has phone out by default
+ * disabled (surround on), leaving us only with internal
+ * speakers. This should really go to mixer. We write the
+ * Data Flow Control reg.
+ */
+ ac97_wrcd(codec, 0x6a, ac97_rdcd(codec, 0x6a) | 0x0001);
+ break;
+ default:
+ break;
+ }
}
Index: channel.h
===================================================================
RCS file: /home/cvs/src/sys/dev/sound/pcm/channel.h,v
retrieving revision 1.2
retrieving revision 1.3
diff -L sys/dev/sound/pcm/channel.h -L sys/dev/sound/pcm/channel.h -u -r1.2 -r1.3
--- sys/dev/sound/pcm/channel.h
+++ sys/dev/sound/pcm/channel.h
@@ -1,72 +1,218 @@
/*-
-* Copyright (c) 1999 Cameron Grant <cg at freebsd.org>
-* All rights reserved.
-*
-* Redistribution and use in source and binary forms, with or without
-* modification, are permitted provided that the following conditions
-* are met:
-* 1. Redistributions of source code must retain the above copyright
-* notice, this list of conditions and the following disclaimer.
-* 2. Redistributions in binary form must reproduce the above copyright
-* notice, this list of conditions and the following disclaimer in the
-* documentation and/or other materials provided with the distribution.
-*
-* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
-* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
-* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
-* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
-* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
-* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
-* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
-* SUCH DAMAGE.
-*
-* $MidnightBSD$
-* $FreeBSD: src/sys/dev/sound/pcm/channel.h,v 1.31.2.1 2005/12/30 19:55:54 netchild Exp $
-*/
-
-struct pcmchan_children {
-SLIST_ENTRY(pcmchan_children) link;
-struct pcm_channel *channel;
-};
+ * Copyright (c) 1999 Cameron Grant <cg at freebsd.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD: src/sys/dev/sound/pcm/channel.h,v 1.37 2007/06/16 03:37:28 ariff Exp $
+ */
struct pcmchan_caps {
-u_int32_t minspeed, maxspeed;
-u_int32_t *fmtlist;
-u_int32_t caps;
+ u_int32_t minspeed, maxspeed;
+ u_int32_t *fmtlist;
+ u_int32_t caps;
+};
+
+/* Forward declarations */
+struct pcm_channel;
+struct pcmchan_syncgroup;
+struct pcmchan_syncmember;
+
+extern struct mtx snd_pcm_syncgroups_mtx;
+extern SLIST_HEAD(pcm_synclist, pcmchan_syncgroup) snd_pcm_syncgroups;
+
+#define PCM_SG_LOCK() mtx_lock(&snd_pcm_syncgroups_mtx)
+#define PCM_SG_TRYLOCK() mtx_trylock(&snd_pcm_syncgroups_mtx)
+#define PCM_SG_UNLOCK() mtx_unlock(&snd_pcm_syncgroups_mtx)
+#define PCM_SG_LOCKASSERT(arg) mtx_assert(&snd_pcm_syncgroups_mtx, arg)
+
+/**
+ * @brief Specifies an audio device sync group
+ */
+struct pcmchan_syncgroup {
+ SLIST_ENTRY(pcmchan_syncgroup) link;
+ SLIST_HEAD(, pcmchan_syncmember) members;
+ int id; /**< Group identifier; set to address of group. */
+};
+
+/**
+ * @brief Specifies a container for members of a sync group
+ */
+struct pcmchan_syncmember {
+ SLIST_ENTRY(pcmchan_syncmember) link;
+ struct pcmchan_syncgroup *parent; /**< group head */
+ struct pcm_channel *ch;
};
#define CHN_NAMELEN 32
struct pcm_channel {
-kobj_t methods;
+ kobj_t methods;
-int num;
-pid_t pid;
-int refcount;
-struct pcm_feeder *feeder;
-u_int32_t align;
-
-int volume;
-u_int32_t speed;
-u_int32_t format;
-u_int32_t flags;
-u_int32_t feederflags;
-u_int32_t blocks;
-
-int direction;
-unsigned int interrupts, xruns;
-struct snd_dbuf *bufhard, *bufsoft;
-struct snddev_info *parentsnddev;
-struct pcm_channel *parentchannel;
-void *devinfo;
-device_t dev;
-char name[CHN_NAMELEN];
-struct mtx *lock;
-SLIST_HEAD(, pcmchan_children) children;
+ pid_t pid;
+ int refcount;
+ struct pcm_feeder *feeder;
+ u_int32_t align;
+
+ int volume;
+ int latency;
+ u_int32_t speed;
+ u_int32_t format;
+ u_int32_t flags;
+ u_int32_t feederflags;
+ u_int32_t blocks;
+
+ int direction;
+ unsigned int interrupts, xruns, feedcount;
+ unsigned int timeout;
+ struct snd_dbuf *bufhard, *bufsoft;
+ struct snddev_info *parentsnddev;
+ struct pcm_channel *parentchannel;
+ void *devinfo;
+ device_t dev;
+ int unit;
+ char name[CHN_NAMELEN];
+ struct mtx *lock;
+ int trigger;
+ /**
+ * For interrupt manipulations.
+ */
+ struct cv intr_cv;
+ /**
+ * Increment,decrement this around operations that temporarily yield
+ * lock.
+ */
+ unsigned int inprog;
+ /**
+ * Special channel operations should examine @c inprog after acquiring
+ * lock. If zero, operations may continue. Else, thread should
+ * wait on this cv for previous operation to finish.
+ */
+ struct cv cv;
+ /**
+ * Low water mark for select()/poll().
+ *
+ * This is initialized to the channel's fragment size, and will be
+ * overwritten if a new fragment size is set. Users may alter this
+ * value directly with the @c SNDCTL_DSP_LOW_WATER ioctl.
+ */
+ unsigned int lw;
+ /**
+ * If part of a sync group, this will point to the syncmember
+ * container.
+ */
+ struct pcmchan_syncmember *sm;
+#ifdef OSSV4_EXPERIMENT
+ u_int16_t lpeak, rpeak; /**< Peak value from 0-32767. */
+#endif
+
+ struct {
+ SLIST_HEAD(, pcm_channel) head;
+ SLIST_ENTRY(pcm_channel) link;
+ struct {
+ SLIST_HEAD(, pcm_channel) head;
+ SLIST_ENTRY(pcm_channel) link;
+ } busy;
+ } children;
+
+ struct {
+ struct {
+ SLIST_ENTRY(pcm_channel) link;
+ struct {
+ SLIST_ENTRY(pcm_channel) link;
+ } busy;
+ } pcm;
+ } channels;
+
+ void *data1, *data2;
};
+#define CHN_HEAD(x, y) &(x)->y.head
+#define CHN_INIT(x, y) SLIST_INIT(CHN_HEAD(x, y))
+#define CHN_LINK(y) y.link
+#define CHN_EMPTY(x, y) SLIST_EMPTY(CHN_HEAD(x, y))
+#define CHN_FIRST(x, y) SLIST_FIRST(CHN_HEAD(x, y))
+
+#define CHN_FOREACH(x, y, z) \
+ SLIST_FOREACH(x, CHN_HEAD(y, z), CHN_LINK(z))
+
+#define CHN_FOREACH_SAFE(w, x, y, z) \
+ SLIST_FOREACH_SAFE(w, CHN_HEAD(x, z), CHN_LINK(z), y)
+
+#define CHN_INSERT_HEAD(x, y, z) \
+ SLIST_INSERT_HEAD(CHN_HEAD(x, z), y, CHN_LINK(z))
+
+#define CHN_INSERT_AFTER(x, y, z) \
+ SLIST_INSERT_AFTER(x, y, CHN_LINK(z))
+
+#define CHN_REMOVE(x, y, z) \
+ SLIST_REMOVE(CHN_HEAD(x, z), y, pcm_channel, CHN_LINK(z))
+
+#define CHN_INSERT_HEAD_SAFE(x, y, z) do { \
+ struct pcm_channel *t = NULL; \
+ CHN_FOREACH(t, x, z) { \
+ if (t == y) \
+ break; \
+ } \
+ if (t != y) { \
+ CHN_INSERT_HEAD(x, y, z); \
+ } \
+} while(0)
+
+#define CHN_INSERT_AFTER_SAFE(w, x, y, z) do { \
+ struct pcm_channel *t = NULL; \
+ CHN_FOREACH(t, w, z) { \
+ if (t == y) \
+ break; \
+ } \
+ if (t != y) { \
+ CHN_INSERT_AFTER(x, y, z); \
+ } \
+} while(0)
+
+#define CHN_REMOVE_SAFE(x, y, z) do { \
+ struct pcm_channel *t = NULL; \
+ CHN_FOREACH(t, x, z) { \
+ if (t == y) \
+ break; \
+ } \
+ if (t == y) { \
+ CHN_REMOVE(x, y, z); \
+ } \
+} while(0)
+
+#define CHN_UNIT(x) (snd_unit2u((x)->unit))
+#define CHN_DEV(x) (snd_unit2d((x)->unit))
+#define CHN_CHAN(x) (snd_unit2c((x)->unit))
+
+#define CHN_BUF_PARENT(x, y) \
+ (((x) != NULL && (x)->parentchannel != NULL && \
+ (x)->parentchannel->bufhard != NULL) ? \
+ (x)->parentchannel->bufhard : (y))
+
+#define CHN_BROADCAST(x) do { \
+ if ((x)->cv_waiters != 0) \
+ cv_broadcastpri(x, PRIBIO); \
+} while(0)
+
#include "channel_if.h"
int chn_reinit(struct pcm_channel *c);
@@ -85,6 +231,7 @@
int chn_setspeed(struct pcm_channel *c, int speed);
int chn_setformat(struct pcm_channel *c, u_int32_t fmt);
int chn_setblocksize(struct pcm_channel *c, int blkcnt, int blksz);
+int chn_setlatency(struct pcm_channel *c, int latency);
int chn_trigger(struct pcm_channel *c, int go);
int chn_getptr(struct pcm_channel *c);
struct pcmchan_caps *chn_getcaps(struct pcm_channel *c);
@@ -103,21 +250,56 @@
void chn_lock(struct pcm_channel *c);
void chn_unlock(struct pcm_channel *c);
+int chn_getrates(struct pcm_channel *c, int **rates);
+int chn_syncdestroy(struct pcm_channel *c);
+
+#ifdef OSSV4_EXPERIMENT
+int chn_getpeaks(struct pcm_channel *c, int *lpeak, int *rpeak);
+#endif
+
#ifdef USING_MUTEX
#define CHN_LOCK(c) mtx_lock((struct mtx *)((c)->lock))
#define CHN_UNLOCK(c) mtx_unlock((struct mtx *)((c)->lock))
+#define CHN_TRYLOCK(c) mtx_trylock((struct mtx *)((c)->lock))
#define CHN_LOCKASSERT(c) mtx_assert((struct mtx *)((c)->lock), MA_OWNED)
#else
#define CHN_LOCK(c)
#define CHN_UNLOCK(c)
+#define CHN_TRYLOCK(c)
#define CHN_LOCKASSERT(c)
#endif
int fmtvalid(u_int32_t fmt, u_int32_t *fmtlist);
-#define PCMDIR_VIRTUAL 2
-#define PCMDIR_PLAY 1
-#define PCMDIR_REC -1
+#define AFMTSTR_NONE 0 /* "s16le" */
+#define AFMTSTR_SIMPLE 1 /* "s16le:s" */
+#define AFMTSTR_NUM 2 /* "s16le:2" */
+#define AFMTSTR_FULL 3 /* "s16le:stereo" */
+
+#define AFMTSTR_MAXSZ 13 /* include null terminator */
+
+#define AFMTSTR_MONO_RETURN 0
+#define AFMTSTR_STEREO_RETURN 1
+
+struct afmtstr_table {
+ char *fmtstr;
+ u_int32_t format;
+};
+
+int afmtstr_swap_sign(char *);
+int afmtstr_swap_endian(char *);
+u_int32_t afmtstr2afmt(struct afmtstr_table *, const char *, int);
+u_int32_t afmt2afmtstr(struct afmtstr_table *, u_int32_t, char *, size_t, int, int);
+
+extern int chn_latency;
+extern int chn_latency_profile;
+extern int report_soft_formats;
+
+#define PCMDIR_FAKE 0
+#define PCMDIR_PLAY 1
+#define PCMDIR_PLAY_VIRTUAL 2
+#define PCMDIR_REC -1
+#define PCMDIR_REC_VIRTUAL -2
#define PCMTRIG_START 1
#define PCMTRIG_EMLDMAWR 2
@@ -125,11 +307,16 @@
#define PCMTRIG_STOP 0
#define PCMTRIG_ABORT -1
+#define PCMTRIG_COMMON(x) ((x) == PCMTRIG_START || \
+ (x) == PCMTRIG_STOP || \
+ (x) == PCMTRIG_ABORT)
+
#define CHN_F_CLOSING 0x00000004 /* a pending close */
#define CHN_F_ABORTING 0x00000008 /* a pending abort */
#define CHN_F_RUNNING 0x00000010 /* dma is running */
#define CHN_F_TRIGGERED 0x00000020
#define CHN_F_NOTRIGGER 0x00000040
+#define CHN_F_SLEEPING 0x00000080
#define CHN_F_BUSY 0x00001000 /* has been opened */
#define CHN_F_HAS_SIZE 0x00002000 /* user set block size */
@@ -142,8 +329,12 @@
#define CHN_F_VIRTUAL 0x10000000 /* not backed by hardware */
-#define CHN_F_RESET (CHN_F_BUSY | CHN_F_DEAD | CHN_F_HAS_VCHAN | CHN_F_VIRTUAL)
+#define CHN_F_RESET (CHN_F_BUSY | CHN_F_DEAD | \
+ CHN_F_HAS_VCHAN | CHN_F_VIRTUAL)
+#define CHN_F_MMAP_INVALID (CHN_F_DEAD | CHN_F_RUNNING)
+
+
#define CHN_N_RATE 0x00000001
#define CHN_N_FORMAT 0x00000002
@@ -151,11 +342,31 @@
#define CHN_N_BLOCKSIZE 0x00000008
#define CHN_N_TRIGGER 0x00000010
+#define CHN_LATENCY_MIN 0
+#define CHN_LATENCY_MAX 10
+#define CHN_LATENCY_DEFAULT 5
+#define CHN_POLICY_MIN CHN_LATENCY_MIN
+#define CHN_POLICY_MAX CHN_LATENCY_MAX
+#define CHN_POLICY_DEFAULT CHN_LATENCY_DEFAULT
+
+#define CHN_LATENCY_PROFILE_MIN 0
+#define CHN_LATENCY_PROFILE_MAX 1
+#define CHN_LATENCY_PROFILE_DEFAULT CHN_LATENCY_PROFILE_MAX
+
+#define CHN_STARTED(c) ((c)->flags & CHN_F_TRIGGERED)
+#define CHN_STOPPED(c) (!CHN_STARTED(c))
+#define CHN_DIRSTR(c) (((c)->direction == PCMDIR_PLAY) ? \
+ "PCMDIR_PLAY" : "PCMDIR_REC")
+
+#define CHN_TIMEOUT 5
+#define CHN_TIMEOUT_MIN 1
+#define CHN_TIMEOUT_MAX 10
+
/*
-* This should be large enough to hold all pcm data between
-* tsleeps in chn_{read,write} at the highest sample rate.
-* (which is usually 48kHz * 16bit * stereo = 192000 bytes/sec)
-*/
+ * This should be large enough to hold all pcm data between
+ * tsleeps in chn_{read,write} at the highest sample rate.
+ * (which is usually 48kHz * 16bit * stereo = 192000 bytes/sec)
+ */
#define CHN_2NDBUFBLKSIZE (2 * 1024)
/* The total number of blocks per secondary bufhard. */
#define CHN_2NDBUFBLKNUM (32)
Index: vchan.h
===================================================================
RCS file: /home/cvs/src/sys/dev/sound/pcm/vchan.h,v
retrieving revision 1.2
retrieving revision 1.3
diff -L sys/dev/sound/pcm/vchan.h -L sys/dev/sound/pcm/vchan.h -u -r1.2 -r1.3
--- sys/dev/sound/pcm/vchan.h
+++ sys/dev/sound/pcm/vchan.h
@@ -1,34 +1,52 @@
/*-
-* Copyright (c) 2001 Cameron Grant <cg at freebsd.org>
-* All rights reserved.
-*
-* Redistribution and use in source and binary forms, with or without
-* modification, are permitted provided that the following conditions
-* are met:
-* 1. Redistributions of source code must retain the above copyright
-* notice, this list of conditions and the following disclaimer.
-* 2. Redistributions in binary form must reproduce the above copyright
-* notice, this list of conditions and the following disclaimer in the
-* documentation and/or other materials provided with the distribution.
-*
-* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
-* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
-* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
-* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
-* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
-* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
-* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
-* SUCH DAMAGE.
-*
-* $MidnightBSD$
-* $FreeBSD: src/sys/dev/sound/pcm/vchan.h,v 1.4 2005/01/06 01:43:21 imp Exp $
-*/
+ * Copyright (c) 2001 Cameron Grant <cg at freebsd.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD: src/sys/dev/sound/pcm/vchan.h,v 1.5 2007/05/31 18:43:32 ariff Exp $
+ */
-int vchan_create(struct pcm_channel *parent);
+int vchan_create(struct pcm_channel *parent, int num);
int vchan_destroy(struct pcm_channel *c);
int vchan_initsys(device_t dev);
+/*
+ * Default speed / format
+ */
+#define VCHAN_DEFAULT_SPEED 48000
+#define VCHAN_DEFAULT_AFMT (AFMT_S16_LE | AFMT_STEREO)
+#define VCHAN_DEFAULT_STRFMT "s16le"
+#define VCHAN_PLAY 0
+#define VCHAN_REC 1
+
+/*
+ * Offset by +/- 1 so we can distinguish bogus pointer.
+ */
+#define VCHAN_SYSCTL_DATA(x, y) \
+ ((void *)((intptr_t)(((((x) + 1) & 0xfff) << 2) | \
+ (((VCHAN_##y) + 1) & 0x3))))
+
+#define VCHAN_SYSCTL_DATA_SIZE sizeof(void *)
+#define VCHAN_SYSCTL_UNIT(x) ((int)(((intptr_t)(x) >> 2) & 0xfff) - 1)
+#define VCHAN_SYSCTL_DIR(x) ((int)((intptr_t)(x) & 0x3) - 1)
Index: mixer_if.m
===================================================================
RCS file: /home/cvs/src/sys/dev/sound/pcm/mixer_if.m,v
retrieving revision 1.2
retrieving revision 1.3
diff -L sys/dev/sound/pcm/mixer_if.m -L sys/dev/sound/pcm/mixer_if.m -u -r1.2 -r1.3
--- sys/dev/sound/pcm/mixer_if.m
+++ sys/dev/sound/pcm/mixer_if.m
@@ -25,7 +25,6 @@
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
# SUCH DAMAGE.
#
-# $MidnightBSD$
# $FreeBSD: src/sys/dev/sound/pcm/mixer_if.m,v 1.6 2005/01/06 01:43:21 imp Exp $
#
@@ -35,7 +34,8 @@
CODE {
- static int mixer_noreinit(struct snd_mixer *m)
+ static int
+ mixer_noreinit(struct snd_mixer *m)
{
return 0;
}
@@ -43,25 +43,25 @@
};
METHOD int init {
-struct snd_mixer *m;
+ struct snd_mixer *m;
};
METHOD int reinit {
-struct snd_mixer *m;
+ struct snd_mixer *m;
} DEFAULT mixer_noreinit;
METHOD int uninit {
-struct snd_mixer *m;
+ struct snd_mixer *m;
};
METHOD int set {
-struct snd_mixer *m;
-unsigned dev;
-unsigned left;
-unsigned right;
+ struct snd_mixer *m;
+ unsigned dev;
+ unsigned left;
+ unsigned right;
};
METHOD u_int32_t setrecsrc {
-struct snd_mixer *m;
-u_int32_t src;
+ struct snd_mixer *m;
+ u_int32_t src;
};
Index: dsp.h
===================================================================
RCS file: /home/cvs/src/sys/dev/sound/pcm/dsp.h,v
retrieving revision 1.2
retrieving revision 1.3
diff -L sys/dev/sound/pcm/dsp.h -L sys/dev/sound/pcm/dsp.h -u -r1.2 -r1.3
--- sys/dev/sound/pcm/dsp.h
+++ sys/dev/sound/pcm/dsp.h
@@ -1,30 +1,42 @@
/*-
-* Copyright (c) 1999 Cameron Grant <cg at freebsd.org>
-* All rights reserved.
-*
-* Redistribution and use in source and binary forms, with or without
-* modification, are permitted provided that the following conditions
-* are met:
-* 1. Redistributions of source code must retain the above copyright
-* notice, this list of conditions and the following disclaimer.
-* 2. Redistributions in binary form must reproduce the above copyright
-* notice, this list of conditions and the following disclaimer in the
-* documentation and/or other materials provided with the distribution.
-*
-* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
-* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
-* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
-* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
-* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
-* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
-* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
-* SUCH DAMAGE.
-*
-* $MidnightBSD$
-* $FreeBSD: src/sys/dev/sound/pcm/dsp.h,v 1.9 2005/01/06 01:43:20 imp Exp $
-*/
+ * Copyright (c) 1999 Cameron Grant <cg at freebsd.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD: src/sys/dev/sound/pcm/dsp.h,v 1.13 2007/06/16 03:37:28 ariff Exp $
+ */
+
+#ifndef _PCMDSP_H_
+#define _PCMDSP_H_
extern struct cdevsw dsp_cdevsw;
+
+struct dsp_cdevinfo;
+
+char *dsp_unit2name(char *, size_t, int);
+int dsp_oss_audioinfo(struct cdev *, oss_audioinfo *);
+
+void dsp_cdevinfo_init(struct snddev_info *);
+void dsp_cdevinfo_flush(struct snddev_info *);
+
+#endif /* !_PCMDSP_H_ */
Index: feeder_volume.c
===================================================================
RCS file: /home/cvs/src/sys/dev/sound/pcm/feeder_volume.c,v
retrieving revision 1.2
retrieving revision 1.3
diff -L sys/dev/sound/pcm/feeder_volume.c -L sys/dev/sound/pcm/feeder_volume.c -u -r1.2 -r1.3
--- sys/dev/sound/pcm/feeder_volume.c
+++ sys/dev/sound/pcm/feeder_volume.c
@@ -1,78 +1,184 @@
/*-
-* Copyright (c) 2005 Ariff Abdullah <ariff at FreeBSD.org>
-* All rights reserved.
-*
-* Redistribution and use in source and binary forms, with or without
-* modification, are permitted provided that the following conditions
-* are met:
-* 1. Redistributions of source code must retain the above copyright
-* notice, this list of conditions and the following disclaimer.
-* 2. Redistributions in binary form must reproduce the above copyright
-* notice, this list of conditions and the following disclaimer in the
-* documentation and/or other materials provided with the distribution.
-*
-* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
-* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
-* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
-* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
-* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
-* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
-* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
-* SUCH DAMAGE.
-*
-* feeder_volume, a long 'Lost Technology' rather than a new feature.
-*/
+ * Copyright (c) 2005 Ariff Abdullah <ariff at FreeBSD.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/* feeder_volume, a long 'Lost Technology' rather than a new feature. */
#include <dev/sound/pcm/sound.h>
#include "feeder_if.h"
-SND_DECLARE_FILE("$MidnightBSD$");
+SND_DECLARE_FILE("$FreeBSD: src/sys/dev/sound/pcm/feeder_volume.c,v 1.6 2007/06/16 20:36:39 ariff Exp $");
+
+#define FVOL_OSS_SCALE 100
+#define FVOL_RESOLUTION PCM_FXSHIFT
+#define FVOL_CLAMP(val) (((val) << FVOL_RESOLUTION) / FVOL_OSS_SCALE)
+#define FVOL_LEFT(val) FVOL_CLAMP((val) & 0x7f)
+#define FVOL_RIGHT(val) FVOL_LEFT((val) >> 8)
+#define FVOL_MAX (1 << FVOL_RESOLUTION)
+#define FVOL_CALC(sval, vval) (((sval) * (vval)) >> FVOL_RESOLUTION)
+
+typedef uint32_t (*feed_volume_filter)(uint8_t *, int *, uint32_t);
+
+#define FEEDER_VOLUME_FILTER(FMTBIT, VOL_INTCAST, SIGN, SIGNS, ENDIAN, ENDIANS) \
+static uint32_t \
+feed_volume_filter_##SIGNS##FMTBIT##ENDIANS(uint8_t *b, int *vol, \
+ uint32_t count) \
+{ \
+ int32_t j; \
+ int i; \
+ \
+ i = count; \
+ b += i; \
+ \
+ do { \
+ b -= PCM_##FMTBIT##_BPS; \
+ i -= PCM_##FMTBIT##_BPS; \
+ j = PCM_READ_##SIGN##FMTBIT##_##ENDIAN(b); \
+ j = FVOL_CALC((VOL_INTCAST)j, \
+ vol[(i / PCM_##FMTBIT##_BPS) & 1]); \
+ PCM_WRITE_##SIGN##FMTBIT##_##ENDIAN(b, j); \
+ } while (i != 0); \
+ \
+ return (count); \
+}
+
+FEEDER_VOLUME_FILTER(8, int32_t, S, s, NE, ne)
+FEEDER_VOLUME_FILTER(16, int32_t, S, s, LE, le)
+FEEDER_VOLUME_FILTER(24, int32_t, S, s, LE, le)
+FEEDER_VOLUME_FILTER(32, intpcm_t, S, s, LE, le)
+FEEDER_VOLUME_FILTER(16, int32_t, S, s, BE, be)
+FEEDER_VOLUME_FILTER(24, int32_t, S, s, BE, be)
+FEEDER_VOLUME_FILTER(32, intpcm_t, S, s, BE, be)
+FEEDER_VOLUME_FILTER(8, int32_t, U, u, NE, ne)
+FEEDER_VOLUME_FILTER(16, int32_t, U, u, LE, le)
+FEEDER_VOLUME_FILTER(24, int32_t, U, u, LE, le)
+FEEDER_VOLUME_FILTER(32, intpcm_t, U, u, LE, le)
+FEEDER_VOLUME_FILTER(16, int32_t, U, u, BE, be)
+FEEDER_VOLUME_FILTER(24, int32_t, U, u, BE, be)
+FEEDER_VOLUME_FILTER(32, intpcm_t, U, u, BE, be)
+
+struct feed_volume_info {
+ uint32_t format;
+ int bps;
+ feed_volume_filter filter;
+};
+
+static struct feed_volume_info feed_volume_tbl[] = {
+ { AFMT_S8, PCM_8_BPS, feed_volume_filter_s8ne },
+ { AFMT_S16_LE, PCM_16_BPS, feed_volume_filter_s16le },
+ { AFMT_S24_LE, PCM_24_BPS, feed_volume_filter_s24le },
+ { AFMT_S32_LE, PCM_32_BPS, feed_volume_filter_s32le },
+ { AFMT_S16_BE, PCM_16_BPS, feed_volume_filter_s16be },
+ { AFMT_S24_BE, PCM_24_BPS, feed_volume_filter_s24be },
+ { AFMT_S32_BE, PCM_32_BPS, feed_volume_filter_s32be },
+ { AFMT_U8, PCM_8_BPS, feed_volume_filter_u8ne },
+ { AFMT_U16_LE, PCM_16_BPS, feed_volume_filter_u16le },
+ { AFMT_U24_LE, PCM_24_BPS, feed_volume_filter_u24le },
+ { AFMT_U32_LE, PCM_32_BPS, feed_volume_filter_u32le },
+ { AFMT_U16_BE, PCM_16_BPS, feed_volume_filter_u16be },
+ { AFMT_U24_BE, PCM_24_BPS, feed_volume_filter_u24be },
+ { AFMT_U32_BE, PCM_32_BPS, feed_volume_filter_u32be },
+};
+
+#define FVOL_DATA(i, c) ((intptr_t)((((i) & 0x1f) << 4) | ((c) & 0xf)))
+#define FVOL_INFOIDX(m) (((m) >> 4) & 0x1f)
+#define FVOL_CHANNELS(m) ((m) & 0xf)
static int
-feed_volume_s16(struct pcm_feeder *f, struct pcm_channel *c, uint8_t *b,
-uint32_t count, void *source)
+feed_volume_init(struct pcm_feeder *f)
{
-int i, j, k, vol[2];
-int16_t *buf;
+ int i, channels;
-k = FEEDER_FEED(f->source, c, b, count & ~1, source);
-if (k < 2) {
-#if 0
-device_printf(c->dev, "%s: Not enough data (Got: %d bytes)n",
-__func__, k);
-#endif
-return 0;
-}
-#if 0
-if (k & 1)
-device_printf(c->dev, "%s: Bytes not 16bit aligned.n", __func__);
-#endif
-k &= ~1;
-i = k >> 1;
-buf = (int16_t *)b;
-vol[0] = c->volume & 0x7f;
-vol[1] = (c->volume >> 8) & 0x7f;
-while (i > 0) {
-i--;
-j = (vol[i & 1] * buf[i]) / 100;
-if (j > 32767)
-j = 32767;
-if (j < -32768)
-j = -32768;
-buf[i] = j;
+ if (f->desc->in != f->desc->out)
+ return (EINVAL);
+
+ /* For now, this is mandatory! */
+ if (!(f->desc->out & AFMT_STEREO))
+ return (EINVAL);
+
+ channels = 2;
+
+ for (i = 0; i < sizeof(feed_volume_tbl) / sizeof(feed_volume_tbl[0]);
+ i++) {
+ if ((f->desc->out & ~AFMT_STEREO) ==
+ feed_volume_tbl[i].format) {
+ f->data = (void *)FVOL_DATA(i, channels);
+ return (0);
+ }
+ }
+
+ return (-1);
}
-return k;
+
+static int
+feed_volume(struct pcm_feeder *f, struct pcm_channel *c, uint8_t *b,
+ uint32_t count, void *source)
+{
+ struct feed_volume_info *info;
+ int vol[2];
+ int k, smpsz;
+
+ vol[0] = FVOL_LEFT(c->volume);
+ vol[1] = FVOL_RIGHT(c->volume);
+
+ if (vol[0] == FVOL_MAX && vol[1] == FVOL_MAX)
+ return (FEEDER_FEED(f->source, c, b, count, source));
+
+ info = &feed_volume_tbl[FVOL_INFOIDX((intptr_t)f->data)];
+ smpsz = info->bps * FVOL_CHANNELS((intptr_t)f->data);
+ if (count < smpsz)
+ return (0);
+
+ k = FEEDER_FEED(f->source, c, b, count - (count % smpsz), source);
+ if (k < smpsz)
+ return (0);
+
+ k -= k % smpsz;
+ return (info->filter(b, vol, k));
}
-static struct pcm_feederdesc feeder_volume_s16_desc[] = {
-{FEEDER_VOLUME, AFMT_S16_LE|AFMT_STEREO, AFMT_S16_LE|AFMT_STEREO, 0},
-{0, 0, 0, 0},
+static struct pcm_feederdesc feeder_volume_desc[] = {
+ {FEEDER_VOLUME, AFMT_S8 | AFMT_STEREO, AFMT_S8 | AFMT_STEREO, 0},
+ {FEEDER_VOLUME, AFMT_S16_LE | AFMT_STEREO, AFMT_S16_LE | AFMT_STEREO, 0},
+ {FEEDER_VOLUME, AFMT_S24_LE | AFMT_STEREO, AFMT_S24_LE | AFMT_STEREO, 0},
+ {FEEDER_VOLUME, AFMT_S32_LE | AFMT_STEREO, AFMT_S32_LE | AFMT_STEREO, 0},
+ {FEEDER_VOLUME, AFMT_S16_BE | AFMT_STEREO, AFMT_S16_BE | AFMT_STEREO, 0},
+ {FEEDER_VOLUME, AFMT_S24_BE | AFMT_STEREO, AFMT_S24_BE | AFMT_STEREO, 0},
+ {FEEDER_VOLUME, AFMT_S32_BE | AFMT_STEREO, AFMT_S32_BE | AFMT_STEREO, 0},
+ {FEEDER_VOLUME, AFMT_U8 | AFMT_STEREO, AFMT_U8 | AFMT_STEREO, 0},
+ {FEEDER_VOLUME, AFMT_U16_LE | AFMT_STEREO, AFMT_U16_LE | AFMT_STEREO, 0},
+ {FEEDER_VOLUME, AFMT_U24_LE | AFMT_STEREO, AFMT_U24_LE | AFMT_STEREO, 0},
+ {FEEDER_VOLUME, AFMT_U32_LE | AFMT_STEREO, AFMT_U32_LE | AFMT_STEREO, 0},
+ {FEEDER_VOLUME, AFMT_U16_BE | AFMT_STEREO, AFMT_U16_BE | AFMT_STEREO, 0},
+ {FEEDER_VOLUME, AFMT_U24_BE | AFMT_STEREO, AFMT_U24_BE | AFMT_STEREO, 0},
+ {FEEDER_VOLUME, AFMT_U32_BE | AFMT_STEREO, AFMT_U32_BE | AFMT_STEREO, 0},
+ {0, 0, 0, 0},
};
-static kobj_method_t feeder_volume_s16_methods[] = {
-KOBJMETHOD(feeder_feed, feed_volume_s16),
-{0, 0}
+static kobj_method_t feeder_volume_methods[] = {
+ KOBJMETHOD(feeder_init, feed_volume_init),
+ KOBJMETHOD(feeder_feed, feed_volume),
+ {0, 0}
};
-FEEDER_DECLARE(feeder_volume_s16, 2, NULL);
+FEEDER_DECLARE(feeder_volume, 2, NULL);
Index: ac97_patch.h
===================================================================
RCS file: /home/cvs/src/sys/dev/sound/pcm/ac97_patch.h,v
retrieving revision 1.2
retrieving revision 1.3
diff -L sys/dev/sound/pcm/ac97_patch.h -L sys/dev/sound/pcm/ac97_patch.h -u -r1.2 -r1.3
--- sys/dev/sound/pcm/ac97_patch.h
+++ sys/dev/sound/pcm/ac97_patch.h
@@ -1,30 +1,30 @@
/*-
-* Copyright 2003 FreeBSD, Inc. All rights reserved.
-*
-* Redistribution and use in source and binary forms, with or without
-* modification, are permitted provided that the following conditions
-* are met:
-* 1. Redistributions of source code must retain the above copyright
-* notice, this list of conditions and the following disclaimer.
-* 2. Redistributions in binary form must reproduce the above copyright
-* notice, this list of conditions and the following disclaimer in the
-* documentation and/or other materials provided with the distribution.
-*
-* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
-* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
-* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
-* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
-* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
-* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
-* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
-* SUCH DAMAGE.
-*
-* $MidnightBSD$
-* $FreeBSD: src/sys/dev/sound/pcm/ac97_patch.h,v 1.3.2.1 2005/12/30 19:55:54 netchild Exp $
-*/
+ * Copyright (c) 2003 Orion Hodson
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD: src/sys/dev/sound/pcm/ac97_patch.h,v 1.7 2007/04/19 13:54:22 ariff Exp $
+ */
typedef void (*ac97_patch)(struct ac97_info*);
@@ -32,3 +32,4 @@
void ad198x_patch(struct ac97_info*);
void ad1981b_patch(struct ac97_info*);
void cmi9739_patch(struct ac97_info*);
+void alc655_patch(struct ac97_info*);
Index: sound.h
===================================================================
RCS file: /home/cvs/src/sys/dev/sound/pcm/sound.h,v
retrieving revision 1.3
retrieving revision 1.4
diff -L sys/dev/sound/pcm/sound.h -L sys/dev/sound/pcm/sound.h -u -r1.3 -r1.4
--- sys/dev/sound/pcm/sound.h
+++ sys/dev/sound/pcm/sound.h
@@ -1,36 +1,35 @@
/*-
-* Copyright (c) 1999 Cameron Grant <cg at freebsd.org>
-* Copyright by Hannu Savolainen 1995
-* All rights reserved.
-*
-* Redistribution and use in source and binary forms, with or without
-* modification, are permitted provided that the following conditions
-* are met:
-* 1. Redistributions of source code must retain the above copyright
-* notice, this list of conditions and the following disclaimer.
-* 2. Redistributions in binary form must reproduce the above copyright
-* notice, this list of conditions and the following disclaimer in the
-* documentation and/or other materials provided with the distribution.
-*
-* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
-* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
-* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
-* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
-* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
-* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
-* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
-* SUCH DAMAGE.
-*
-* $MidnightBSD$
-* $FreeBSD: src/sys/dev/sound/pcm/sound.h,v 1.63.2.2 2006/04/04 17:43:48 ariff Exp $
-*/
+ * Copyright (c) 1999 Cameron Grant <cg at freebsd.org>
+ * Copyright by Hannu Savolainen 1995
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD: src/sys/dev/sound/pcm/sound.h,v 1.78 2007/06/16 03:37:28 ariff Exp $
+ */
/*
-* first, include kernel header files.
-*/
+ * first, include kernel header files.
+ */
#ifndef _OS_H_
#define _OS_H_
@@ -56,10 +55,10 @@
#if __FreeBSD_version < 500000
#include <sys/buf.h>
#endif
-#include <machine/clock.h> /* for DELAY */
#include <machine/resource.h>
#include <machine/bus.h>
#include <sys/rman.h>
+#include <sys/limits.h>
#include <sys/mman.h>
#include <sys/poll.h>
#include <sys/sbuf.h>
@@ -75,6 +74,7 @@
#if __FreeBSD_version > 500000
#include <sys/lock.h>
#include <sys/mutex.h>
+#include <sys/condvar.h>
#define USING_MUTEX
#define USING_DEVFS
@@ -94,80 +94,366 @@
#include <dev/sound/pcm/channel.h>
#include <dev/sound/pcm/feeder.h>
#include <dev/sound/pcm/mixer.h>
+#include <dev/sound/pcm/dsp.h>
+#include <dev/sound/clone.h>
+#include <dev/sound/unit.h>
#define PCM_SOFTC_SIZE 512
#define SND_STATUSLEN 64
-#define SOUND_MODVER 1
+#define SOUND_MODVER 2
-#define SOUND_MINVER 1
+#define SOUND_MINVER SOUND_MODVER
#define SOUND_PREFVER SOUND_MODVER
-#define SOUND_MAXVER 1
+#define SOUND_MAXVER SOUND_MODVER
/*
-PROPOSAL:
-each unit needs:
-status, mixer, dsp, dspW, audio, sequencer, midi-in, seq2, sndproc = 9 devices
-dspW and audio are deprecated.
-dsp needs min 64 channels, will give it 256
-
-minor = (unit << 20) + (dev << 16) + channel
-currently minor = (channel << 16) + (unit << 4) + dev
-
-nomenclature:
-/dev/pcmX/dsp.(0..255)
-/dev/pcmX/dspW
-/dev/pcmX/audio
-/dev/pcmX/status
-/dev/pcmX/mixer
-[etc.]
-*/
-
-#define PCMMAXCHAN 0xff
-#define PCMMAXDEV 0x0f
-#define PCMMAXUNIT 0x0f
-#define PCMMINOR(x) (minor(x))
-#define PCMCHAN(x) ((PCMMINOR(x) >> 16) & PCMMAXCHAN)
-#define PCMUNIT(x) ((PCMMINOR(x) >> 4) & PCMMAXUNIT)
-#define PCMDEV(x) (PCMMINOR(x) & PCMMAXDEV)
-#define PCMMKMINOR(u, d, c) ((((c) & PCMMAXCHAN) << 16) | (((u) & PCMMAXUNIT) << 4) | ((d) & PCMMAXDEV))
+ * We're abusing the fact that MAXMINOR still have enough room
+ * for our bit twiddling and nobody ever need 512 unique soundcards,
+ * 32 unique device types and 1024 unique cloneable devices for the
+ * next 100 years...
+ */
+
+#define PCMMAXUNIT (snd_max_u())
+#define PCMMAXDEV (snd_max_d())
+#define PCMMAXCHAN (snd_max_c())
+
+#define PCMMAXCLONE PCMMAXCHAN
+
+#define PCMUNIT(x) (snd_unit2u(dev2unit(x)))
+#define PCMDEV(x) (snd_unit2d(dev2unit(x)))
+#define PCMCHAN(x) (snd_unit2c(dev2unit(x)))
+
+/*
+ * By design, limit possible channels for each direction.
+ */
+#define SND_MAXHWCHAN 256
+#define SND_MAXVCHANS SND_MAXHWCHAN
#define SD_F_SIMPLEX 0x00000001
#define SD_F_AUTOVCHAN 0x00000002
#define SD_F_SOFTPCMVOL 0x00000004
+#define SD_F_PSWAPLR 0x00000008
+#define SD_F_RSWAPLR 0x00000010
+#define SD_F_DYING 0x00000020
+#define SD_F_SUICIDE 0x00000040
+#define SD_F_BUSY 0x00000080
+#define SD_F_MPSAFE 0x00000100
+#define SD_F_REGISTERED 0x00000200
+
#define SD_F_PRIO_RD 0x10000000
#define SD_F_PRIO_WR 0x20000000
#define SD_F_PRIO_SET (SD_F_PRIO_RD | SD_F_PRIO_WR)
#define SD_F_DIR_SET 0x40000000
#define SD_F_TRANSIENT 0xf0000000
+#define PCM_ALIVE(x) ((x) != NULL && (x)->lock != NULL && \
+ !((x)->flags & SD_F_DYING))
+#define PCM_REGISTERED(x) (PCM_ALIVE(x) && \
+ ((x)->flags & SD_F_REGISTERED))
+
/* many variables should be reduced to a range. Here define a macro */
-#define RANGE(var, low, high) (var) = (((var)<(low))? (low) : ((var)>(high))? (high) : (var))
+#define RANGE(var, low, high) (var) = \
+ (((var)<(low))? (low) : ((var)>(high))? (high) : (var))
#define DSP_BUFFSIZE (8192)
+/*
+ * Macros for reading/writing PCM sample / int values from bytes array.
+ * Since every process is done using signed integer (and to make our life
+ * less miserable), unsigned sample will be converted to its signed
+ * counterpart and restored during writing back. To avoid overflow,
+ * we truncate 32bit (and only 32bit) samples down to 24bit (see below
+ * for the reason), unless PCM_USE_64BIT_ARITH is defined.
+ */
+
+/*
+ * Automatically turn on 64bit arithmetic on suitable archs
+ * (amd64 64bit, ia64, etc..) for wider 32bit samples / integer processing.
+ */
+#if LONG_BIT >= 64
+#undef PCM_USE_64BIT_ARITH
+#define PCM_USE_64BIT_ARITH 1
+#else
+#if 0
+#undef PCM_USE_64BIT_ARITH
+#define PCM_USE_64BIT_ARITH 1
+#endif
+#endif
+
+#ifdef PCM_USE_64BIT_ARITH
+typedef int64_t intpcm_t;
+#else
+typedef int32_t intpcm_t;
+#endif
+
+/* 32bit fixed point shift */
+#define PCM_FXSHIFT 8
+
+#define PCM_S8_MAX 0x7f
+#define PCM_S8_MIN -0x80
+#define PCM_S16_MAX 0x7fff
+#define PCM_S16_MIN -0x8000
+#define PCM_S24_MAX 0x7fffff
+#define PCM_S24_MIN -0x800000
+#ifdef PCM_USE_64BIT_ARITH
+#if LONG_BIT >= 64
+#define PCM_S32_MAX 0x7fffffffL
+#define PCM_S32_MIN -0x80000000L
+#else
+#define PCM_S32_MAX 0x7fffffffLL
+#define PCM_S32_MIN -0x80000000LL
+#endif
+#else
+#define PCM_S32_MAX 0x7fffffff
+#define PCM_S32_MIN (-0x7fffffff - 1)
+#endif
+
+/* Bytes-per-sample definition */
+#define PCM_8_BPS 1
+#define PCM_16_BPS 2
+#define PCM_24_BPS 3
+#define PCM_32_BPS 4
+
+#if BYTE_ORDER == LITTLE_ENDIAN
+#define PCM_READ_S16_LE(b8) *((int16_t *)(b8))
+#define _PCM_READ_S32_LE(b8) *((int32_t *)(b8))
+#define PCM_READ_S16_BE(b8) \
+ ((int32_t)((b8)[1] | ((int8_t)((b8)[0])) << 8))
+#define _PCM_READ_S32_BE(b8) \
+ ((int32_t)((b8)[3] | (b8)[2] << 8 | (b8)[1] << 16 | \
+ ((int8_t)((b8)[0])) << 24))
+
+#define PCM_WRITE_S16_LE(b8, val) *((int16_t *)(b8)) = (val)
+#define _PCM_WRITE_S32_LE(b8, val) *((int32_t *)(b8)) = (val)
+#define PCM_WRITE_S16_BE(bb8, vval) do { \
+ int32_t val = (vval); \
+ uint8_t *b8 = (bb8); \
+ b8[1] = val; \
+ b8[0] = val >> 8; \
+ } while(0)
+#define _PCM_WRITE_S32_BE(bb8, vval) do { \
+ int32_t val = (vval); \
+ uint8_t *b8 = (bb8); \
+ b8[3] = val; \
+ b8[2] = val >> 8; \
+ b8[1] = val >> 16; \
+ b8[0] = val >> 24; \
+ } while(0)
+
+#define PCM_READ_U16_LE(b8) ((int16_t)(*((uint16_t *)(b8)) ^ 0x8000))
+#define _PCM_READ_U32_LE(b8) ((int32_t)(*((uint32_t *)(b8)) ^ 0x80000000))
+#define PCM_READ_U16_BE(b8) \
+ ((int32_t)((b8)[1] | ((int8_t)((b8)[0] ^ 0x80)) << 8))
+#define _PCM_READ_U32_BE(b8) \
+ ((int32_t)((b8)[3] | (b8)[2] << 8 | (b8)[1] << 16 | \
+ ((int8_t)((b8)[0] ^ 0x80)) << 24))
+
+#define PCM_WRITE_U16_LE(b8, val) *((uint16_t *)(b8)) = (val) ^ 0x8000
+#define _PCM_WRITE_U32_LE(b8, val) *((uint32_t *)(b8)) = (val) ^ 0x80000000
+#define PCM_WRITE_U16_BE(bb8, vval) do { \
+ int32_t val = (vval); \
+ uint8_t *b8 = (bb8); \
+ b8[1] = val; \
+ b8[0] = (val >> 8) ^ 0x80; \
+ } while(0)
+#define _PCM_WRITE_U32_BE(bb8, vval) do { \
+ int32_t val = (vval); \
+ uint8_t *b8 = (bb8); \
+ b8[3] = val; \
+ b8[2] = val >> 8; \
+ b8[1] = val >> 16; \
+ b8[0] = (val >> 24) ^ 0x80; \
+ } while(0)
+#else /* !LITTLE_ENDIAN */
+#define PCM_READ_S16_LE(b8) \
+ ((int32_t)((b8)[0] | ((int8_t)((b8)[1])) << 8))
+#define _PCM_READ_S32_LE(b8) \
+ ((int32_t)((b8)[0] | (b8)[1] << 8 | (b8)[2] << 16 | \
+ ((int8_t)((b8)[3])) << 24))
+#define PCM_READ_S16_BE(b8) *((int16_t *)(b8))
+#define _PCM_READ_S32_BE(b8) *((int32_t *)(b8))
+
+#define PCM_WRITE_S16_LE(bb8, vval) do { \
+ int32_t val = (vval); \
+ uint8_t *b8 = (bb8); \
+ b8[0] = val; \
+ b8[1] = val >> 8; \
+ } while(0)
+#define _PCM_WRITE_S32_LE(bb8, vval) do { \
+ int32_t val = (vval); \
+ uint8_t *b8 = (bb8); \
+ b8[0] = val; \
+ b8[1] = val >> 8; \
+ b8[2] = val >> 16; \
+ b8[3] = val >> 24; \
+ } while(0)
+#define PCM_WRITE_S16_BE(b8, val) *((int16_t *)(b8)) = (val)
+#define _PCM_WRITE_S32_BE(b8, val) *((int32_t *)(b8)) = (val)
+
+#define PCM_READ_U16_LE(b8) \
+ ((int32_t)((b8)[0] | ((int8_t)((b8)[1] ^ 0x80)) << 8))
+#define _PCM_READ_U32_LE(b8) \
+ ((int32_t)((b8)[0] | (b8)[1] << 8 | (b8)[2] << 16 | \
+ ((int8_t)((b8)[3] ^ 0x80)) << 24))
+#define PCM_READ_U16_BE(b8) ((int16_t)(*((uint16_t *)(b8)) ^ 0x8000))
+#define _PCM_READ_U32_BE(b8) ((int32_t)(*((uint32_t *)(b8)) ^ 0x80000000))
+
+#define PCM_WRITE_U16_LE(bb8, vval) do { \
+ int32_t val = (vval); \
+ uint8_t *b8 = (bb8); \
+ b8[0] = val; \
+ b8[1] = (val >> 8) ^ 0x80; \
+ } while(0)
+#define _PCM_WRITE_U32_LE(bb8, vval) do { \
+ int32_t val = (vval); \
+ uint8_t *b8 = (bb8); \
+ b8[0] = val; \
+ b8[1] = val >> 8; \
+ b8[2] = val >> 16; \
+ b8[3] = (val >> 24) ^ 0x80; \
+ } while(0)
+#define PCM_WRITE_U16_BE(b8, val) *((uint16_t *)(b8)) = (val) ^ 0x8000
+#define _PCM_WRITE_U32_BE(b8, val) *((uint32_t *)(b8)) = (val) ^ 0x80000000
+#endif
+
+#define PCM_READ_S24_LE(b8) \
+ ((int32_t)((b8)[0] | (b8)[1] << 8 | ((int8_t)((b8)[2])) << 16))
+#define PCM_READ_S24_BE(b8) \
+ ((int32_t)((b8)[2] | (b8)[1] << 8 | ((int8_t)((b8)[0])) << 16))
+
+#define PCM_WRITE_S24_LE(bb8, vval) do { \
+ int32_t val = (vval); \
+ uint8_t *b8 = (bb8); \
+ b8[0] = val; \
+ b8[1] = val >> 8; \
+ b8[2] = val >> 16; \
+ } while(0)
+#define PCM_WRITE_S24_BE(bb8, vval) do { \
+ int32_t val = (vval); \
+ uint8_t *b8 = (bb8); \
+ b8[2] = val; \
+ b8[1] = val >> 8; \
+ b8[0] = val >> 16; \
+ } while(0)
+
+#define PCM_READ_U24_LE(b8) \
+ ((int32_t)((b8)[0] | (b8)[1] << 8 | \
+ ((int8_t)((b8)[2] ^ 0x80)) << 16))
+#define PCM_READ_U24_BE(b8) \
+ ((int32_t)((b8)[2] | (b8)[1] << 8 | \
+ ((int8_t)((b8)[0] ^ 0x80)) << 16))
+
+#define PCM_WRITE_U24_LE(bb8, vval) do { \
+ int32_t val = (vval); \
+ uint8_t *b8 = (bb8); \
+ b8[0] = val; \
+ b8[1] = val >> 8; \
+ b8[2] = (val >> 16) ^ 0x80; \
+ } while(0)
+#define PCM_WRITE_U24_BE(bb8, vval) do { \
+ int32_t val = (vval); \
+ uint8_t *b8 = (bb8); \
+ b8[2] = val; \
+ b8[1] = val >> 8; \
+ b8[0] = (val >> 16) ^ 0x80; \
+ } while(0)
+
+#ifdef PCM_USE_64BIT_ARITH
+#define PCM_READ_S32_LE(b8) _PCM_READ_S32_LE(b8)
+#define PCM_READ_S32_BE(b8) _PCM_READ_S32_BE(b8)
+#define PCM_WRITE_S32_LE(b8, val) _PCM_WRITE_S32_LE(b8, val)
+#define PCM_WRITE_S32_BE(b8, val) _PCM_WRITE_S32_BE(b8, val)
+
+#define PCM_READ_U32_LE(b8) _PCM_READ_U32_LE(b8)
+#define PCM_READ_U32_BE(b8) _PCM_READ_U32_BE(b8)
+#define PCM_WRITE_U32_LE(b8, val) _PCM_WRITE_U32_LE(b8, val)
+#define PCM_WRITE_U32_BE(b8, val) _PCM_WRITE_U32_BE(b8, val)
+#else /* !PCM_USE_64BIT_ARITH */
+/*
+ * 24bit integer ?!? This is quite unfortunate, eh? Get the fact straight:
+ * Dynamic range for:
+ * 1) Human =~ 140db
+ * 2) 16bit = 96db (close enough)
+ * 3) 24bit = 144db (perfect)
+ * 4) 32bit = 196db (way too much)
+ * 5) Bugs Bunny = Gazillion!@%$Erbzzztt-EINVAL db
+ * Since we're not Bugs Bunny ..uh..err.. avoiding 64bit arithmetic, 24bit
+ * is pretty much sufficient for our signed integer processing.
+ */
+#define PCM_READ_S32_LE(b8) (_PCM_READ_S32_LE(b8) >> PCM_FXSHIFT)
+#define PCM_READ_S32_BE(b8) (_PCM_READ_S32_BE(b8) >> PCM_FXSHIFT)
+#define PCM_WRITE_S32_LE(b8, val) _PCM_WRITE_S32_LE(b8, (val) << PCM_FXSHIFT)
+#define PCM_WRITE_S32_BE(b8, val) _PCM_WRITE_S32_BE(b8, (val) << PCM_FXSHIFT)
+
+#define PCM_READ_U32_LE(b8) (_PCM_READ_U32_LE(b8) >> PCM_FXSHIFT)
+#define PCM_READ_U32_BE(b8) (_PCM_READ_U32_BE(b8) >> PCM_FXSHIFT)
+#define PCM_WRITE_U32_LE(b8, val) _PCM_WRITE_U32_LE(b8, (val) << PCM_FXSHIFT)
+#define PCM_WRITE_U32_BE(b8, val) _PCM_WRITE_U32_BE(b8, (val) << PCM_FXSHIFT)
+#endif
+
+/*
+ * 8bit sample is pretty much useless since it doesn't provide
+ * sufficient dynamic range throughout our filtering process.
+ * For the sake of completeness, declare it anyway.
+ */
+#define PCM_READ_S8(b8) *((int8_t *)(b8))
+#define PCM_READ_S8_NE(b8) PCM_READ_S8(b8)
+#define PCM_READ_U8(b8) ((int8_t)(*((uint8_t *)(b8)) ^ 0x80))
+#define PCM_READ_U8_NE(b8) PCM_READ_U8(b8)
+
+#define PCM_WRITE_S8(b8, val) *((int8_t *)(b8)) = (val)
+#define PCM_WRITE_S8_NE(b8, val) PCM_WRITE_S8(b8, val)
+#define PCM_WRITE_U8(b8, val) *((uint8_t *)(b8)) = (val) ^ 0x80
+#define PCM_WRITE_U8_NE(b8, val) PCM_WRITE_U8(b8, val)
+
+#define PCM_CLAMP_S8(val) \
+ (((val) > PCM_S8_MAX) ? PCM_S8_MAX : \
+ (((val) < PCM_S8_MIN) ? PCM_S8_MIN : (val)))
+#define PCM_CLAMP_S16(val) \
+ (((val) > PCM_S16_MAX) ? PCM_S16_MAX : \
+ (((val) < PCM_S16_MIN) ? PCM_S16_MIN : (val)))
+#define PCM_CLAMP_S24(val) \
+ (((val) > PCM_S24_MAX) ? PCM_S24_MAX : \
+ (((val) < PCM_S24_MIN) ? PCM_S24_MIN : (val)))
+
+#ifdef PCM_USE_64BIT_ARITH
+#define PCM_CLAMP_S32(val) \
+ (((val) > PCM_S32_MAX) ? PCM_S32_MAX : \
+ (((val) < PCM_S32_MIN) ? PCM_S32_MIN : (val)))
+#else
+#define PCM_CLAMP_S32(val) \
+ (((val) > PCM_S24_MAX) ? PCM_S32_MAX : \
+ (((val) < PCM_S24_MIN) ? PCM_S32_MIN : \
+ ((val) << PCM_FXSHIFT)))
+#endif
+
+#define PCM_CLAMP_U8(val) PCM_CLAMP_S8(val)
+#define PCM_CLAMP_U16(val) PCM_CLAMP_S16(val)
+#define PCM_CLAMP_U24(val) PCM_CLAMP_S24(val)
+#define PCM_CLAMP_U32(val) PCM_CLAMP_S32(val)
+
/* make figuring out what a format is easier. got AFMT_STEREO already */
#define AFMT_32BIT (AFMT_S32_LE | AFMT_S32_BE | AFMT_U32_LE | AFMT_U32_BE)
#define AFMT_24BIT (AFMT_S24_LE | AFMT_S24_BE | AFMT_U24_LE | AFMT_U24_BE)
#define AFMT_16BIT (AFMT_S16_LE | AFMT_S16_BE | AFMT_U16_LE | AFMT_U16_BE)
#define AFMT_8BIT (AFMT_MU_LAW | AFMT_A_LAW | AFMT_U8 | AFMT_S8)
-#define AFMT_SIGNED (AFMT_S32_LE | AFMT_S32_BE | AFMT_S24_LE | AFMT_S24_BE | AFMT_S16_LE | AFMT_S16_BE | AFMT_S8)
-#define AFMT_BIGENDIAN (AFMT_S32_BE | AFMT_U32_BE | AFMT_S24_BE | AFMT_U24_BE | AFMT_S16_BE | AFMT_U16_BE)
+#define AFMT_SIGNED (AFMT_S32_LE | AFMT_S32_BE | AFMT_S24_LE | AFMT_S24_BE | \
+ AFMT_S16_LE | AFMT_S16_BE | AFMT_S8)
+#define AFMT_BIGENDIAN (AFMT_S32_BE | AFMT_U32_BE | AFMT_S24_BE | AFMT_U24_BE | \
+ AFMT_S16_BE | AFMT_U16_BE)
struct pcm_channel *fkchan_setup(device_t dev);
int fkchan_kill(struct pcm_channel *c);
-/* XXX Flawed definition. I'll fix it someday. */
-#define SND_MAXVCHANS PCMMAXCHAN
-
/*
-* Minor numbers for the sound driver.
-*
-* Unfortunately Creative called the codec chip of SB as a DSP. For this
-* reason the /dev/dsp is reserved for digitized audio use. There is a
-* device for true DSP processors but it will be called something else.
-* In v3.0 it's /dev/sndproc but this could be a temporary solution.
-*/
+ * Minor numbers for the sound driver.
+ *
+ * Unfortunately Creative called the codec chip of SB as a DSP. For this
+ * reason the /dev/dsp is reserved for digitized audio use. There is a
+ * device for true DSP processors but it will be called something else.
+ * In v3.0 it's /dev/sndproc but this could be a temporary solution.
+ */
#define SND_DEV_CTL 0 /* Control port /dev/mixer */
#define SND_DEV_SEQ 1 /* Sequencer /dev/sequencer */
@@ -176,12 +462,23 @@
#define SND_DEV_AUDIO 4 /* Sparc compatible /dev/audio */
#define SND_DEV_DSP16 5 /* Like /dev/dsp but 16 bits/sample */
#define SND_DEV_STATUS 6 /* /dev/sndstat */
-/* #7 not in use now. */
+ /* #7 not in use now. */
#define SND_DEV_SEQ2 8 /* /dev/sequencer, level 2 interface */
#define SND_DEV_SNDPROC 9 /* /dev/sndproc for programmable devices */
#define SND_DEV_PSS SND_DEV_SNDPROC /* ? */
#define SND_DEV_NORESET 10
-#define SND_DEV_DSPREC 11 /* recording channels */
+
+#define SND_DEV_DSPHW_PLAY 11 /* specific playback channel */
+#define SND_DEV_DSPHW_VPLAY 12 /* specific virtual playback channel */
+#define SND_DEV_DSPHW_REC 13 /* specific record channel */
+#define SND_DEV_DSPHW_VREC 14 /* specific virtual record channel */
+
+#define SND_DEV_DSPHW_CD 15 /* s16le/stereo 44100Hz CD */
+
+#define SND_DEV_DSP_MMAP 16 /* OSSv4 compatible /dev/dsp_mmap */
+
+#define SND_DEV_LAST SND_DEV_DSP_MMAP
+#define SND_DEV_MAX PCMMAXDEV
#define DSP_DEFAULT_SPEED 8000
@@ -190,13 +487,16 @@
extern int pcm_veto_load;
extern int snd_unit;
+extern int snd_maxautovchans;
+extern int snd_verbose;
extern devclass_t pcm_devclass;
+extern struct unrhdr *pcmsg_unrhdr;
/*
-* some macros for debugging purposes
-* DDB/DEB to enable/disable debugging stuff
-* BVDDB to enable debugging when bootverbose
-*/
+ * some macros for debugging purposes
+ * DDB/DEB to enable/disable debugging stuff
+ * BVDDB to enable debugging when bootverbose
+ */
#define BVDDB(x) if (bootverbose) x
#ifndef DEB
@@ -205,22 +505,19 @@
SYSCTL_DECL(_hw_snd);
-struct sysctl_ctx_list *snd_sysctl_tree(device_t dev);
-struct sysctl_oid *snd_sysctl_tree_top(device_t dev);
-
struct pcm_channel *pcm_getfakechan(struct snddev_info *d);
-int pcm_chnalloc(struct snddev_info *d, struct pcm_channel **ch, int direction, pid_t pid, int chnum);
+int pcm_chnalloc(struct snddev_info *d, struct pcm_channel **ch, int direction, pid_t pid, int devunit);
int pcm_chnrelease(struct pcm_channel *c);
int pcm_chnref(struct pcm_channel *c, int ref);
int pcm_inprog(struct snddev_info *d, int delta);
-struct pcm_channel *pcm_chn_create(struct snddev_info *d, struct pcm_channel *parent, kobj_class_t cls, int dir, void *devinfo);
+struct pcm_channel *pcm_chn_create(struct snddev_info *d, struct pcm_channel *parent, kobj_class_t cls, int dir, int num, void *devinfo);
int pcm_chn_destroy(struct pcm_channel *ch);
int pcm_chn_add(struct snddev_info *d, struct pcm_channel *ch);
int pcm_chn_remove(struct snddev_info *d, struct pcm_channel *ch);
int pcm_addchan(device_t dev, int dir, kobj_class_t cls, void *devinfo);
-unsigned int pcm_getbuffersize(device_t dev, unsigned int min, unsigned int deflt, unsigned int max);
+unsigned int pcm_getbuffersize(device_t dev, unsigned int minbufsz, unsigned int deflt, unsigned int maxbufsz);
int pcm_register(device_t dev, void *devinfo, int numplay, int numrec);
int pcm_unregister(device_t dev);
int pcm_setstatus(device_t dev, char *str);
@@ -230,7 +527,7 @@
int snd_setup_intr(device_t dev, struct resource *res, int flags,
-driver_intr_t hand, void *param, void **cookiep);
+ driver_intr_t hand, void *param, void **cookiep);
void *snd_mtxcreate(const char *desc, const char *type);
void snd_mtxfree(void *m);
@@ -241,18 +538,23 @@
int sysctl_hw_snd_vchans(SYSCTL_HANDLER_ARGS);
typedef int (*sndstat_handler)(struct sbuf *s, device_t dev, int verbose);
-int sndstat_acquire(void);
-int sndstat_release(void);
+int sndstat_acquire(struct thread *td);
+int sndstat_release(struct thread *td);
int sndstat_register(device_t dev, char *str, sndstat_handler handler);
int sndstat_registerfile(char *str);
int sndstat_unregister(device_t dev);
int sndstat_unregisterfile(char *str);
-#define SND_DECLARE_FILE(version) _SND_DECLARE_FILE(__LINE__, version)
+#define SND_DECLARE_FILE(version) \
+ _SND_DECLARE_FILE(__LINE__, version)
-#define _SND_DECLARE_FILE(uniq, version) __SND_DECLARE_FILE(uniq, version)
+#define _SND_DECLARE_FILE(uniq, version) \
+ __SND_DECLARE_FILE(uniq, version)
-#define __SND_DECLARE_FILE(uniq, version) static char sndstat_vinfo[] = version; SYSINIT(sdf_ ## uniq, SI_SUB_DRIVERS, SI_ORDER_MIDDLE, sndstat_registerfile, sndstat_vinfo); SYSUNINIT(sdf_ ## uniq, SI_SUB_DRIVERS, SI_ORDER_MIDDLE, sndstat_unregisterfile, sndstat_vinfo);
+#define __SND_DECLARE_FILE(uniq, version) \
+ static char sndstat_vinfo[] = version; \
+ SYSINIT(sdf_ ## uniq, SI_SUB_DRIVERS, SI_ORDER_MIDDLE, sndstat_registerfile, sndstat_vinfo); \
+ SYSUNINIT(sdf_ ## uniq, SI_SUB_DRIVERS, SI_ORDER_MIDDLE, sndstat_unregisterfile, sndstat_vinfo);
/* usage of flags in device config entry (config file) */
#define DV_F_DRQ_MASK 0x00000007 /* mask for secondary drq */
@@ -265,38 +567,41 @@
#define PCM_DEBUG_MTX
/*
-* this is rather kludgey- we need to duplicate these struct def'ns from sound.c
-* so that the macro versions of pcm_{,un}lock can dereference them.
-* we also have to do this now makedev() has gone away.
-*/
-
-struct snddev_channel {
-SLIST_ENTRY(snddev_channel) link;
-struct pcm_channel *channel;
-int chan_num;
-struct cdev *dsp_devt;
-struct cdev *dspW_devt;
-struct cdev *audio_devt;
-struct cdev *dspr_devt;
-};
+ * this is rather kludgey- we need to duplicate these struct def'ns from sound.c
+ * so that the macro versions of pcm_{,un}lock can dereference them.
+ * we also have to do this now makedev() has gone away.
+ */
struct snddev_info {
-SLIST_HEAD(, snddev_channel) channels;
-struct pcm_channel *fakechan;
-unsigned devcount, playcount, reccount, vchancount;
-unsigned flags;
-int inprog;
-unsigned int bufsz;
-void *devinfo;
-device_t dev;
-char status[SND_STATUSLEN];
-struct sysctl_ctx_list sysctl_tree;
-struct sysctl_oid *sysctl_tree_top;
-struct mtx *lock;
-struct cdev *mixer_dev;
-
+ struct {
+ struct {
+ SLIST_HEAD(, pcm_channel) head;
+ struct {
+ SLIST_HEAD(, pcm_channel) head;
+ } busy;
+ } pcm;
+ } channels;
+ TAILQ_HEAD(dsp_cdevinfo_linkhead, dsp_cdevinfo) dsp_cdevinfo_pool;
+ struct snd_clone *clones;
+ struct pcm_channel *fakechan;
+ unsigned devcount, playcount, reccount, pvchancount, rvchancount ;
+ unsigned flags;
+ int inprog;
+ unsigned int bufsz;
+ void *devinfo;
+ device_t dev;
+ char status[SND_STATUSLEN];
+ struct mtx *lock;
+ struct cdev *mixer_dev;
+ uint32_t pvchanrate, pvchanformat;
+ uint32_t rvchanrate, rvchanformat;
+ struct sysctl_ctx_list play_sysctl_ctx, rec_sysctl_ctx;
+ struct sysctl_oid *play_sysctl_tree, *rec_sysctl_tree;
+ struct cv cv;
};
+void sound_oss_sysinfo(oss_sysinfo *);
+
#ifdef PCM_DEBUG_MTX
#define pcm_lock(d) mtx_lock(((struct snddev_info *)(d))->lock)
#define pcm_unlock(d) mtx_unlock(((struct snddev_info *)(d))->lock)
@@ -305,6 +610,196 @@
void pcm_unlock(struct snddev_info *d);
#endif
+/*
+ * For PCM_CV_[WAIT | ACQUIRE | RELEASE], be sure to surround these
+ * with pcm_lock/unlock() sequence, or I'll come to gnaw upon you!
+ */
+#ifdef SND_DIAGNOSTIC
+#define PCM_WAIT(x) do { \
+ if (mtx_owned((x)->lock) == 0) \
+ panic("%s(%d): [PCM WAIT] Mutex not owned!", \
+ __func__, __LINE__); \
+ while ((x)->flags & SD_F_BUSY) { \
+ if (snd_verbose > 3) \
+ device_printf((x)->dev, \
+ "%s(%d): [PCM WAIT] calling cv_wait().\n", \
+ __func__, __LINE__); \
+ cv_wait(&(x)->cv, (x)->lock); \
+ } \
+} while(0)
+
+#define PCM_ACQUIRE(x) do { \
+ if (mtx_owned((x)->lock) == 0) \
+ panic("%s(%d): [PCM ACQUIRE] Mutex not owned!", \
+ __func__, __LINE__); \
+ if ((x)->flags & SD_F_BUSY) \
+ panic("%s(%d): [PCM ACQUIRE] " \
+ "Trying to acquire BUSY cv!", __func__, __LINE__); \
+ (x)->flags |= SD_F_BUSY; \
+} while(0)
+
+#define PCM_RELEASE(x) do { \
+ if (mtx_owned((x)->lock) == 0) \
+ panic("%s(%d): [PCM RELEASE] Mutex not owned!", \
+ __func__, __LINE__); \
+ if ((x)->flags & SD_F_BUSY) { \
+ (x)->flags &= ~SD_F_BUSY; \
+ if ((x)->cv.cv_waiters != 0) { \
+ if ((x)->cv.cv_waiters > 1 && snd_verbose > 3) \
+ device_printf((x)->dev, \
+ "%s(%d): [PCM RELEASE] " \
+ "cv_waiters=%d > 1!\n", \
+ __func__, __LINE__, \
+ (x)->cv.cv_waiters); \
+ cv_broadcast(&(x)->cv); \
+ } \
+ } else \
+ panic("%s(%d): [PCM RELEASE] Releasing non-BUSY cv!", \
+ __func__, __LINE__); \
+} while(0)
+
+/* Quick version, for shorter path. */
+#define PCM_ACQUIRE_QUICK(x) do { \
+ if (mtx_owned((x)->lock) != 0) \
+ panic("%s(%d): [PCM ACQUIRE QUICK] Mutex owned!", \
+ __func__, __LINE__); \
+ pcm_lock(x); \
+ PCM_WAIT(x); \
+ PCM_ACQUIRE(x); \
+ pcm_unlock(x); \
+} while(0)
+
+#define PCM_RELEASE_QUICK(x) do { \
+ if (mtx_owned((x)->lock) != 0) \
+ panic("%s(%d): [PCM RELEASE QUICK] Mutex owned!", \
+ __func__, __LINE__); \
+ pcm_lock(x); \
+ PCM_RELEASE(x); \
+ pcm_unlock(x); \
+} while(0)
+
+#define PCM_BUSYASSERT(x) do { \
+ if (!((x) != NULL && ((x)->flags & SD_F_BUSY))) \
+ panic("%s(%d): [PCM BUSYASSERT] " \
+ "Failed, snddev_info=%p", __func__, __LINE__, x); \
+} while(0)
+
+#define PCM_GIANT_ENTER(x) do { \
+ int _pcm_giant = 0; \
+ if (mtx_owned((x)->lock) != 0) \
+ panic("%s(%d): [GIANT ENTER] PCM lock owned!", \
+ __func__, __LINE__); \
+ if (mtx_owned(&Giant) != 0 && snd_verbose > 3) \
+ device_printf((x)->dev, \
+ "%s(%d): [GIANT ENTER] Giant owned!\n", \
+ __func__, __LINE__); \
+ if (!((x)->flags & SD_F_MPSAFE) && mtx_owned(&Giant) == 0) \
+ do { \
+ mtx_lock(&Giant); \
+ _pcm_giant = 1; \
+ } while(0)
+
+#define PCM_GIANT_EXIT(x) do { \
+ if (mtx_owned((x)->lock) != 0) \
+ panic("%s(%d): [GIANT EXIT] PCM lock owned!", \
+ __func__, __LINE__); \
+ if (!(_pcm_giant == 0 || _pcm_giant == 1)) \
+ panic("%s(%d): [GIANT EXIT] _pcm_giant screwed!", \
+ __func__, __LINE__); \
+ if ((x)->flags & SD_F_MPSAFE) { \
+ if (_pcm_giant == 1) \
+ panic("%s(%d): [GIANT EXIT] MPSAFE Giant?", \
+ __func__, __LINE__); \
+ if (mtx_owned(&Giant) != 0 && snd_verbose > 3) \
+ device_printf((x)->dev, \
+ "%s(%d): [GIANT EXIT] Giant owned!\n", \
+ __func__, __LINE__); \
+ } \
+ if (_pcm_giant != 0) { \
+ if (mtx_owned(&Giant) == 0) \
+ panic("%s(%d): [GIANT EXIT] Giant not owned!", \
+ __func__, __LINE__); \
+ _pcm_giant = 0; \
+ mtx_unlock(&Giant); \
+ } \
+} while(0)
+#else /* SND_DIAGNOSTIC */
+#define PCM_WAIT(x) do { \
+ mtx_assert((x)->lock, MA_OWNED); \
+ while ((x)->flags & SD_F_BUSY) \
+ cv_wait(&(x)->cv, (x)->lock); \
+} while(0)
+
+#define PCM_ACQUIRE(x) do { \
+ mtx_assert((x)->lock, MA_OWNED); \
+ KASSERT(!((x)->flags & SD_F_BUSY), \
+ ("%s(%d): [PCM ACQUIRE] Trying to acquire BUSY cv!", \
+ __func__, __LINE__)); \
+ (x)->flags |= SD_F_BUSY; \
+} while(0)
+
+#define PCM_RELEASE(x) do { \
+ mtx_assert((x)->lock, MA_OWNED); \
+ KASSERT((x)->flags & SD_F_BUSY, \
+ ("%s(%d): [PCM RELEASE] Releasing non-BUSY cv!", \
+ __func__, __LINE__)); \
+ (x)->flags &= ~SD_F_BUSY; \
+ if ((x)->cv.cv_waiters != 0) \
+ cv_broadcast(&(x)->cv); \
+} while(0)
+
+/* Quick version, for shorter path. */
+#define PCM_ACQUIRE_QUICK(x) do { \
+ mtx_assert((x)->lock, MA_NOTOWNED); \
+ pcm_lock(x); \
+ PCM_WAIT(x); \
+ PCM_ACQUIRE(x); \
+ pcm_unlock(x); \
+} while(0)
+
+#define PCM_RELEASE_QUICK(x) do { \
+ mtx_assert((x)->lock, MA_NOTOWNED); \
+ pcm_lock(x); \
+ PCM_RELEASE(x); \
+ pcm_unlock(x); \
+} while(0)
+
+#define PCM_BUSYASSERT(x) KASSERT(x != NULL && \
+ ((x)->flags & SD_F_BUSY), \
+ ("%s(%d): [PCM BUSYASSERT] " \
+ "Failed, snddev_info=%p", \
+ __func__, __LINE__, x))
+
+#define PCM_GIANT_ENTER(x) do { \
+ int _pcm_giant = 0; \
+ mtx_assert((x)->lock, MA_NOTOWNED); \
+ if (!((x)->flags & SD_F_MPSAFE) && mtx_owned(&Giant) == 0) \
+ do { \
+ mtx_lock(&Giant); \
+ _pcm_giant = 1; \
+ } while(0)
+
+#define PCM_GIANT_EXIT(x) do { \
+ mtx_assert((x)->lock, MA_NOTOWNED); \
+ KASSERT(_pcm_giant == 0 || _pcm_giant == 1, \
+ ("%s(%d): [GIANT EXIT] _pcm_giant screwed!", \
+ __func__, __LINE__)); \
+ KASSERT(!((x)->flags & SD_F_MPSAFE) || \
+ (((x)->flags & SD_F_MPSAFE) && _pcm_giant == 0), \
+ ("%s(%d): [GIANT EXIT] MPSAFE Giant?", \
+ __func__, __LINE__)); \
+ if (_pcm_giant != 0) { \
+ mtx_assert(&Giant, MA_OWNED); \
+ _pcm_giant = 0; \
+ mtx_unlock(&Giant); \
+ } \
+} while(0)
+#endif /* !SND_DIAGNOSTIC */
+
+#define PCM_GIANT_LEAVE(x) \
+ PCM_GIANT_EXIT(x); \
+} while(0)
+
#ifdef KLD_MODULE
#define PCM_KLDSTRING(a) ("kld " # a)
#else
Index: channel.c
===================================================================
RCS file: /home/cvs/src/sys/dev/sound/pcm/channel.c,v
retrieving revision 1.3
retrieving revision 1.4
diff -L sys/dev/sound/pcm/channel.c -L sys/dev/sound/pcm/channel.c -u -r1.3 -r1.4
--- sys/dev/sound/pcm/channel.c
+++ sys/dev/sound/pcm/channel.c
@@ -1,29 +1,29 @@
/*-
-* Copyright (c) 1999 Cameron Grant <cg at freebsd.org>
-* Portions Copyright by Luigi Rizzo - 1997-99
-* All rights reserved.
-*
-* Redistribution and use in source and binary forms, with or without
-* modification, are permitted provided that the following conditions
-* are met:
-* 1. Redistributions of source code must retain the above copyright
-* notice, this list of conditions and the following disclaimer.
-* 2. Redistributions in binary form must reproduce the above copyright
-* notice, this list of conditions and the following disclaimer in the
-* documentation and/or other materials provided with the distribution.
-*
-* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
-* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
-* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
-* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
-* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
-* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
-* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
-* SUCH DAMAGE.
-*/
+ * Copyright (c) 1999 Cameron Grant <cg at freebsd.org>
+ * Portions Copyright by Luigi Rizzo - 1997-99
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
#include "opt_isa.h"
@@ -31,408 +31,461 @@
#include "feeder_if.h"
-SND_DECLARE_FILE("$MidnightBSD$");
+SND_DECLARE_FILE("$FreeBSD: src/sys/dev/sound/pcm/channel.c,v 1.121.2.1 2007/12/06 05:21:39 ariff Exp $");
-#define MIN_CHUNK_SIZE 256 /* for uiomove etc. */
-#if 0
-#define DMA_ALIGN_THRESHOLD 4
-#define DMA_ALIGN_MASK (~(DMA_ALIGN_THRESHOLD - 1))
-#endif
+int report_soft_formats = 1;
+SYSCTL_INT(_hw_snd, OID_AUTO, report_soft_formats, CTLFLAG_RW,
+ &report_soft_formats, 1, "report software-emulated formats");
-#define CANCHANGE(c) (!(c->flags & CHN_F_TRIGGERED))
+int chn_latency = CHN_LATENCY_DEFAULT;
+TUNABLE_INT("hw.snd.latency", &chn_latency);
-/*
-#define DEB(x) x
-*/
+static int
+sysctl_hw_snd_latency(SYSCTL_HANDLER_ARGS)
+{
+ int err, val;
+
+ val = chn_latency;
+ err = sysctl_handle_int(oidp, &val, 0, req);
+ if (err != 0 || req->newptr == NULL)
+ return err;
+ if (val < CHN_LATENCY_MIN || val > CHN_LATENCY_MAX)
+ err = EINVAL;
+ else
+ chn_latency = val;
+
+ return err;
+}
+SYSCTL_PROC(_hw_snd, OID_AUTO, latency, CTLTYPE_INT | CTLFLAG_RW,
+ 0, sizeof(int), sysctl_hw_snd_latency, "I",
+ "buffering latency (0=low ... 10=high)");
-static int chn_targetirqrate = 32;
-TUNABLE_INT("hw.snd.targetirqrate", &chn_targetirqrate);
+int chn_latency_profile = CHN_LATENCY_PROFILE_DEFAULT;
+TUNABLE_INT("hw.snd.latency_profile", &chn_latency_profile);
static int
-sysctl_hw_snd_targetirqrate(SYSCTL_HANDLER_ARGS)
+sysctl_hw_snd_latency_profile(SYSCTL_HANDLER_ARGS)
{
-int err, val;
+ int err, val;
-val = chn_targetirqrate;
-err = sysctl_handle_int(oidp, &val, sizeof(val), req);
-if (val < 16 || val > 512)
-err = EINVAL;
-else
-chn_targetirqrate = val;
-
-return err;
-}
-SYSCTL_PROC(_hw_snd, OID_AUTO, targetirqrate, CTLTYPE_INT | CTLFLAG_RW,
-0, sizeof(int), sysctl_hw_snd_targetirqrate, "I", "");
-static int report_soft_formats = 1;
-SYSCTL_INT(_hw_snd, OID_AUTO, report_soft_formats, CTLFLAG_RW,
-&report_soft_formats, 1, "report software-emulated formats");
+ val = chn_latency_profile;
+ err = sysctl_handle_int(oidp, &val, 0, req);
+ if (err != 0 || req->newptr == NULL)
+ return err;
+ if (val < CHN_LATENCY_PROFILE_MIN || val > CHN_LATENCY_PROFILE_MAX)
+ err = EINVAL;
+ else
+ chn_latency_profile = val;
+
+ return err;
+}
+SYSCTL_PROC(_hw_snd, OID_AUTO, latency_profile, CTLTYPE_INT | CTLFLAG_RW,
+ 0, sizeof(int), sysctl_hw_snd_latency_profile, "I",
+ "buffering latency profile (0=aggresive 1=safe)");
+
+static int chn_timeout = CHN_TIMEOUT;
+TUNABLE_INT("hw.snd.timeout", &chn_timeout);
+#ifdef SND_DEBUG
+static int
+sysctl_hw_snd_timeout(SYSCTL_HANDLER_ARGS)
+{
+ int err, val;
+
+ val = chn_timeout;
+ err = sysctl_handle_int(oidp, &val, 0, req);
+ if (err != 0 || req->newptr == NULL)
+ return err;
+ if (val < CHN_TIMEOUT_MIN || val > CHN_TIMEOUT_MAX)
+ err = EINVAL;
+ else
+ chn_timeout = val;
+
+ return err;
+}
+SYSCTL_PROC(_hw_snd, OID_AUTO, timeout, CTLTYPE_INT | CTLFLAG_RW,
+ 0, sizeof(int), sysctl_hw_snd_timeout, "I",
+ "interrupt timeout (1 - 10) seconds");
+#endif
+
+static int chn_usefrags = 0;
+TUNABLE_INT("hw.snd.usefrags", &chn_usefrags);
+static int chn_syncdelay = -1;
+TUNABLE_INT("hw.snd.syncdelay", &chn_syncdelay);
+#ifdef SND_DEBUG
+SYSCTL_INT(_hw_snd, OID_AUTO, usefrags, CTLFLAG_RW,
+ &chn_usefrags, 1, "prefer setfragments() over setblocksize()");
+SYSCTL_INT(_hw_snd, OID_AUTO, syncdelay, CTLFLAG_RW,
+ &chn_syncdelay, 1,
+ "append (0-1000) millisecond trailing buffer delay on each sync");
+#endif
+
+/**
+ * @brief Channel sync group lock
+ *
+ * Clients should acquire this lock @b without holding any channel locks
+ * before touching syncgroups or the main syncgroup list.
+ */
+struct mtx snd_pcm_syncgroups_mtx;
+MTX_SYSINIT(pcm_syncgroup, &snd_pcm_syncgroups_mtx, "PCM channel sync group lock", MTX_DEF);
+/**
+ * @brief syncgroups' master list
+ *
+ * Each time a channel syncgroup is created, it's added to this list. This
+ * list should only be accessed with @sa snd_pcm_syncgroups_mtx held.
+ *
+ * See SNDCTL_DSP_SYNCGROUP for more information.
+ */
+struct pcm_synclist snd_pcm_syncgroups = SLIST_HEAD_INITIALIZER(head);
static int chn_buildfeeder(struct pcm_channel *c);
static void
chn_lockinit(struct pcm_channel *c, int dir)
{
-switch(dir) {
-case PCMDIR_PLAY:
-c->lock = snd_mtxcreate(c->name, "pcm play channel");
-break;
-case PCMDIR_REC:
-c->lock = snd_mtxcreate(c->name, "pcm record channel");
-break;
-case PCMDIR_VIRTUAL:
-c->lock = snd_mtxcreate(c->name, "pcm virtual play channel");
-break;
-case 0:
-c->lock = snd_mtxcreate(c->name, "pcm fake channel");
-break;
-}
+ switch (dir) {
+ case PCMDIR_PLAY:
+ c->lock = snd_mtxcreate(c->name, "pcm play channel");
+ cv_init(&c->intr_cv, "pcmwr");
+ break;
+ case PCMDIR_PLAY_VIRTUAL:
+ c->lock = snd_mtxcreate(c->name, "pcm virtual play channel");
+ cv_init(&c->intr_cv, "pcmwrv");
+ break;
+ case PCMDIR_REC:
+ c->lock = snd_mtxcreate(c->name, "pcm record channel");
+ cv_init(&c->intr_cv, "pcmrd");
+ break;
+ case PCMDIR_REC_VIRTUAL:
+ c->lock = snd_mtxcreate(c->name, "pcm virtual record channel");
+ cv_init(&c->intr_cv, "pcmrdv");
+ break;
+ case 0:
+ c->lock = snd_mtxcreate(c->name, "pcm fake channel");
+ cv_init(&c->intr_cv, "pcmfk");
+ break;
+ }
+
+ cv_init(&c->cv, "pcmchn");
}
static void
chn_lockdestroy(struct pcm_channel *c)
{
-snd_mtxfree(c->lock);
+ CHN_LOCKASSERT(c);
+
+ CHN_BROADCAST(&c->cv);
+ CHN_BROADCAST(&c->intr_cv);
+
+ cv_destroy(&c->cv);
+ cv_destroy(&c->intr_cv);
+
+ snd_mtxfree(c->lock);
}
+/**
+ * @brief Determine channel is ready for I/O
+ *
+ * @retval 1 = ready for I/O
+ * @retval 0 = not ready for I/O
+ */
static int
chn_polltrigger(struct pcm_channel *c)
{
-struct snd_dbuf *bs = c->bufsoft;
-unsigned amt, lim;
+ struct snd_dbuf *bs = c->bufsoft;
+ unsigned amt, lim;
-CHN_LOCKASSERT(c);
-if (c->flags & CHN_F_MAPPED) {
-if (sndbuf_getprevblocks(bs) == 0)
-return 1;
-else
-return (sndbuf_getblocks(bs) > sndbuf_getprevblocks(bs))? 1 : 0;
-} else {
-amt = (c->direction == PCMDIR_PLAY)? sndbuf_getfree(bs) : sndbuf_getready(bs);
+ CHN_LOCKASSERT(c);
+ if (c->flags & CHN_F_MAPPED) {
+ if (sndbuf_getprevblocks(bs) == 0)
+ return 1;
+ else
+ return (sndbuf_getblocks(bs) > sndbuf_getprevblocks(bs))? 1 : 0;
+ } else {
+ amt = (c->direction == PCMDIR_PLAY)? sndbuf_getfree(bs) : sndbuf_getready(bs);
#if 0
-lim = (c->flags & CHN_F_HAS_SIZE)? sndbuf_getblksz(bs) : 1;
+ lim = (c->flags & CHN_F_HAS_SIZE)? sndbuf_getblksz(bs) : 1;
#endif
-lim = 1;
-return (amt >= lim)? 1 : 0;
-}
-return 0;
+ lim = c->lw;
+ return (amt >= lim) ? 1 : 0;
+ }
+ return 0;
}
static int
chn_pollreset(struct pcm_channel *c)
{
-struct snd_dbuf *bs = c->bufsoft;
+ struct snd_dbuf *bs = c->bufsoft;
-CHN_LOCKASSERT(c);
-sndbuf_updateprevtotal(bs);
-return 1;
+ CHN_LOCKASSERT(c);
+ sndbuf_updateprevtotal(bs);
+ return 1;
}
static void
chn_wakeup(struct pcm_channel *c)
{
-struct snd_dbuf *bs = c->bufsoft;
-struct pcmchan_children *pce;
+ struct snd_dbuf *bs;
+ struct pcm_channel *ch;
-CHN_LOCKASSERT(c);
-if (SLIST_EMPTY(&c->children)) {
-if (SEL_WAITING(sndbuf_getsel(bs)) && chn_polltrigger(c))
-selwakeuppri(sndbuf_getsel(bs), PRIBIO);
-} else {
-SLIST_FOREACH(pce, &c->children, link) {
-CHN_LOCK(pce->channel);
-chn_wakeup(pce->channel);
-CHN_UNLOCK(pce->channel);
-}
-}
+ CHN_LOCKASSERT(c);
-wakeup(bs);
+ bs = c->bufsoft;
+
+ if (CHN_EMPTY(c, children.busy)) {
+ if (SEL_WAITING(sndbuf_getsel(bs)) && chn_polltrigger(c))
+ selwakeuppri(sndbuf_getsel(bs), PRIBIO);
+ if (c->flags & CHN_F_SLEEPING) {
+ /*
+ * Ok, I can just panic it right here since it is
+ * quite obvious that we never allow multiple waiters
+ * from userland. I'm too generous...
+ */
+ CHN_BROADCAST(&c->intr_cv);
+ }
+ } else {
+ CHN_FOREACH(ch, c, children.busy) {
+ CHN_LOCK(ch);
+ chn_wakeup(ch);
+ CHN_UNLOCK(ch);
+ }
+ }
}
static int
-chn_sleep(struct pcm_channel *c, char *str, int timeout)
+chn_sleep(struct pcm_channel *c, int timeout)
{
-struct snd_dbuf *bs = c->bufsoft;
-int ret;
+ int ret;
-CHN_LOCKASSERT(c);
-#ifdef USING_MUTEX
-ret = msleep(bs, c->lock, PRIBIO | PCATCH, str, timeout);
-#else
-ret = tsleep(bs, PRIBIO | PCATCH, str, timeout);
-#endif
+ CHN_LOCKASSERT(c);
+
+ if (c->flags & CHN_F_DEAD)
+ return (EINVAL);
-return ret;
+ c->flags |= CHN_F_SLEEPING;
+ ret = cv_timedwait_sig(&c->intr_cv, c->lock, timeout);
+ c->flags &= ~CHN_F_SLEEPING;
+
+ return ((c->flags & CHN_F_DEAD) ? EINVAL : ret);
}
/*
-* chn_dmaupdate() tracks the status of a dma transfer,
-* updating pointers.
-*/
+ * chn_dmaupdate() tracks the status of a dma transfer,
+ * updating pointers.
+ */
static unsigned int
chn_dmaupdate(struct pcm_channel *c)
{
-struct snd_dbuf *b = c->bufhard;
-unsigned int delta, old, hwptr, amt;
+ struct snd_dbuf *b = c->bufhard;
+ unsigned int delta, old, hwptr, amt;
-KASSERT(sndbuf_getsize(b) > 0, ("bufsize == 0"));
-CHN_LOCKASSERT(c);
+ KASSERT(sndbuf_getsize(b) > 0, ("bufsize == 0"));
+ CHN_LOCKASSERT(c);
-old = sndbuf_gethwptr(b);
-hwptr = chn_getptr(c);
-delta = (sndbuf_getsize(b) + hwptr - old) % sndbuf_getsize(b);
-sndbuf_sethwptr(b, hwptr);
-
-DEB(
-if (delta >= ((sndbuf_getsize(b) * 15) / 16)) {
-if (!(c->flags & (CHN_F_CLOSING | CHN_F_ABORTING)))
-device_printf(c->dev, "hwptr went backwards %d -> %dn", old, hwptr);
-}
-);
-
-if (c->direction == PCMDIR_PLAY) {
-amt = MIN(delta, sndbuf_getready(b));
-if (amt > 0)
-sndbuf_dispose(b, NULL, amt);
-} else {
-amt = MIN(delta, sndbuf_getfree(b));
-if (amt > 0)
-sndbuf_acquire(b, NULL, amt);
-}
+ old = sndbuf_gethwptr(b);
+ hwptr = chn_getptr(c);
+ delta = (sndbuf_getsize(b) + hwptr - old) % sndbuf_getsize(b);
+ sndbuf_sethwptr(b, hwptr);
+
+ if (c->direction == PCMDIR_PLAY) {
+ amt = min(delta, sndbuf_getready(b));
+ amt -= amt % sndbuf_getbps(b);
+ if (amt > 0)
+ sndbuf_dispose(b, NULL, amt);
+ } else {
+ amt = min(delta, sndbuf_getfree(b));
+ amt -= amt % sndbuf_getbps(b);
+ if (amt > 0)
+ sndbuf_acquire(b, NULL, amt);
+ }
+ if (snd_verbose > 3 && CHN_STARTED(c) && delta == 0) {
+ device_printf(c->dev, "WARNING: %s DMA completion "
+ "too fast/slow ! hwptr=%u, old=%u "
+ "delta=%u amt=%u ready=%u free=%u\n",
+ CHN_DIRSTR(c), hwptr, old, delta, amt,
+ sndbuf_getready(b), sndbuf_getfree(b));
+ }
-return delta;
+ return delta;
}
void
chn_wrupdate(struct pcm_channel *c)
{
-int ret;
+ int ret;
-CHN_LOCKASSERT(c);
-KASSERT(c->direction == PCMDIR_PLAY, ("chn_wrupdate on bad channel"));
+ CHN_LOCKASSERT(c);
+ KASSERT(c->direction == PCMDIR_PLAY, ("chn_wrupdate on bad channel"));
-if ((c->flags & (CHN_F_MAPPED | CHN_F_VIRTUAL)) || !(c->flags & CHN_F_TRIGGERED))
-return;
-chn_dmaupdate(c);
-ret = chn_wrfeed(c);
-/* tell the driver we've updated the primary buffer */
-chn_trigger(c, PCMTRIG_EMLDMAWR);
-DEB(if (ret)
-printf("chn_wrupdate: chn_wrfeed returned %dn", ret);)
+ if ((c->flags & (CHN_F_MAPPED | CHN_F_VIRTUAL)) || CHN_STOPPED(c))
+ return;
+ chn_dmaupdate(c);
+ ret = chn_wrfeed(c);
+ /* tell the driver we've updated the primary buffer */
+ chn_trigger(c, PCMTRIG_EMLDMAWR);
+ DEB(if (ret)
+ printf("chn_wrupdate: chn_wrfeed returned %d\n", ret);)
}
int
chn_wrfeed(struct pcm_channel *c)
{
-struct snd_dbuf *b = c->bufhard;
-struct snd_dbuf *bs = c->bufsoft;
-unsigned int ret, amt;
+ struct snd_dbuf *b = c->bufhard;
+ struct snd_dbuf *bs = c->bufsoft;
+ unsigned int ret, amt;
-CHN_LOCKASSERT(c);
-#if 0
-DEB(
-if (c->flags & CHN_F_CLOSING) {
-sndbuf_dump(b, "b", 0x02);
-sndbuf_dump(bs, "bs", 0x02);
-})
-#endif
+ CHN_LOCKASSERT(c);
-if (c->flags & CHN_F_MAPPED)
-sndbuf_acquire(bs, NULL, sndbuf_getfree(bs));
+ if ((c->flags & CHN_F_MAPPED) && !(c->flags & CHN_F_CLOSING))
+ sndbuf_acquire(bs, NULL, sndbuf_getfree(bs));
-amt = sndbuf_getfree(b);
-KASSERT(amt <= sndbuf_getsize(bs),
-("%s(%s): amt %d > source size %d, flags 0x%x", __func__, c->name,
-amt, sndbuf_getsize(bs), c->flags));
+ amt = sndbuf_getfree(b);
-ret = (amt > 0) ? sndbuf_feed(bs, b, c, c->feeder, amt) : ENOSPC;
-/*
-* Possible xruns. There should be no empty space left in buffer.
-*/
-if (sndbuf_getfree(b) > 0)
-c->xruns++;
+ ret = (amt > 0) ? sndbuf_feed(bs, b, c, c->feeder, amt) : ENOSPC;
+ /*
+ * Possible xruns. There should be no empty space left in buffer.
+ */
+ if (sndbuf_getfree(b) > 0)
+ c->xruns++;
-if (ret == 0 && sndbuf_getfree(b) < amt)
-chn_wakeup(c);
+ if (sndbuf_getfree(b) < amt)
+ chn_wakeup(c);
-return ret;
+ return ret;
}
static void
chn_wrintr(struct pcm_channel *c)
{
-int ret;
+ int ret;
-CHN_LOCKASSERT(c);
-/* update pointers in primary buffer */
-chn_dmaupdate(c);
-/* ...and feed from secondary to primary */
-ret = chn_wrfeed(c);
-/* tell the driver we've updated the primary buffer */
-chn_trigger(c, PCMTRIG_EMLDMAWR);
-DEB(if (ret)
-printf("chn_wrintr: chn_wrfeed returned %dn", ret);)
+ CHN_LOCKASSERT(c);
+ /* update pointers in primary buffer */
+ chn_dmaupdate(c);
+ /* ...and feed from secondary to primary */
+ ret = chn_wrfeed(c);
+ /* tell the driver we've updated the primary buffer */
+ chn_trigger(c, PCMTRIG_EMLDMAWR);
+ DEB(if (ret)
+ printf("chn_wrintr: chn_wrfeed returned %d\n", ret);)
}
/*
-* user write routine - uiomove data into secondary buffer, trigger if necessary
-* if blocking, sleep, rinse and repeat.
-*
-* called externally, so must handle locking
-*/
+ * user write routine - uiomove data into secondary buffer, trigger if necessary
+ * if blocking, sleep, rinse and repeat.
+ *
+ * called externally, so must handle locking
+ */
int
chn_write(struct pcm_channel *c, struct uio *buf)
{
-int ret, timeout, newsize, count, sz;
-struct snd_dbuf *bs = c->bufsoft;
-void *off;
-int t, x,togo,p;
-
-CHN_LOCKASSERT(c);
-/*
-* XXX Certain applications attempt to write larger size
-* of pcm data than c->blocksize2nd without blocking,
-* resulting partial write. Expand the block size so that
-* the write operation avoids blocking.
-*/
-if ((c->flags & CHN_F_NBIO) && buf->uio_resid > sndbuf_getblksz(bs)) {
-DEB(device_printf(c->dev, "broken app, nbio and tried to write %d bytes with fragsz %dn",
-buf->uio_resid, sndbuf_getblksz(bs)));
-newsize = 16;
-while (newsize < min(buf->uio_resid, CHN_2NDBUFMAXSIZE / 2))
-newsize <<= 1;
-chn_setblocksize(c, sndbuf_getblkcnt(bs), newsize);
-DEB(device_printf(c->dev, "frags reset to %d x %dn", sndbuf_getblkcnt(bs), sndbuf_getblksz(bs)));
-}
-
-ret = 0;
-count = hz;
-while (!ret && (buf->uio_resid > 0) && (count > 0)) {
-sz = sndbuf_getfree(bs);
-if (sz == 0) {
-if (c->flags & CHN_F_NBIO)
-ret = EWOULDBLOCK;
-else {
-timeout = (hz * sndbuf_getblksz(bs)) / (sndbuf_getspd(bs) * sndbuf_getbps(bs));
-if (timeout < 1)
-timeout = 1;
-timeout = 1;
-ret = chn_sleep(c, "pcmwr", timeout);
-if (ret == EWOULDBLOCK) {
-count -= timeout;
-ret = 0;
-} else if (ret == 0)
-count = hz;
-}
-} else {
-sz = MIN(sz, buf->uio_resid);
-KASSERT(sz > 0, ("confusion in chn_write"));
-/* printf("sz: %dn", sz); */
-
-/*
-* The following assumes that the free space in
-* the buffer can never be less around the
-* unlock-uiomove-lock sequence.
-*/
-togo = sz;
-while (ret == 0 && togo> 0) {
-p = sndbuf_getfreeptr(bs);
-t = MIN(togo, sndbuf_getsize(bs) - p);
-off = sndbuf_getbufofs(bs, p);
-CHN_UNLOCK(c);
-ret = uiomove(off, t, buf);
-CHN_LOCK(c);
-togo -= t;
-x = sndbuf_acquire(bs, NULL, t);
-}
-ret = 0;
-if (ret == 0 && !(c->flags & CHN_F_TRIGGERED))
-chn_start(c, 0);
-}
-}
-/* printf("ret: %d left: %dn", ret, buf->uio_resid); */
-
-if (count <= 0) {
-c->flags |= CHN_F_DEAD;
-printf("%s: play interrupt timeout, channel deadn", c->name);
-}
-
-return ret;
-}
-
-#if 0
-static int
-chn_rddump(struct pcm_channel *c, unsigned int cnt)
-{
-struct snd_dbuf *b = c->bufhard;
+ struct snd_dbuf *bs = c->bufsoft;
+ void *off;
+ int ret, timeout, sz, t, p;
+
+ CHN_LOCKASSERT(c);
+
+ ret = 0;
+ timeout = chn_timeout * hz;
+
+ while (ret == 0 && buf->uio_resid > 0) {
+ sz = min(buf->uio_resid, sndbuf_getfree(bs));
+ if (sz > 0) {
+ /*
+ * The following assumes that the free space in
+ * the buffer can never be less around the
+ * unlock-uiomove-lock sequence.
+ */
+ while (ret == 0 && sz > 0) {
+ p = sndbuf_getfreeptr(bs);
+ t = min(sz, sndbuf_getsize(bs) - p);
+ off = sndbuf_getbufofs(bs, p);
+ CHN_UNLOCK(c);
+ ret = uiomove(off, t, buf);
+ CHN_LOCK(c);
+ sz -= t;
+ sndbuf_acquire(bs, NULL, t);
+ }
+ ret = 0;
+ if (CHN_STOPPED(c) && !(c->flags & CHN_F_NOTRIGGER)) {
+ ret = chn_start(c, 0);
+ if (ret != 0)
+ c->flags |= CHN_F_DEAD;
+ }
+ } else if (c->flags & (CHN_F_NBIO | CHN_F_NOTRIGGER)) {
+ /**
+ * @todo Evaluate whether EAGAIN is truly desirable.
+ * 4Front drivers behave like this, but I'm
+ * not sure if it at all violates the "write
+ * should be allowed to block" model.
+ *
+ * The idea is that, while set with CHN_F_NOTRIGGER,
+ * a channel isn't playing, *but* without this we
+ * end up with "interrupt timeout / channel dead".
+ */
+ ret = EAGAIN;
+ } else {
+ ret = chn_sleep(c, timeout);
+ if (ret == EAGAIN) {
+ ret = EINVAL;
+ c->flags |= CHN_F_DEAD;
+ printf("%s: play interrupt timeout, "
+ "channel dead\n", c->name);
+ } else if (ret == ERESTART || ret == EINTR)
+ c->flags |= CHN_F_ABORTING;
+ }
+ }
-CHN_LOCKASSERT(c);
-#if 0
-static uint32_t kk = 0;
-printf("%u: dumping %d bytesn", ++kk, cnt);
-#endif
-c->xruns++;
-sndbuf_setxrun(b, sndbuf_getxrun(b) + cnt);
-return sndbuf_dispose(b, NULL, cnt);
+ return (ret);
}
-#endif
/*
-* Feed new data from the read buffer. Can be called in the bottom half.
-*/
+ * Feed new data from the read buffer. Can be called in the bottom half.
+ */
int
chn_rdfeed(struct pcm_channel *c)
{
-struct snd_dbuf *b = c->bufhard;
-struct snd_dbuf *bs = c->bufsoft;
-unsigned int ret, amt;
-
-CHN_LOCKASSERT(c);
-DEB(
-if (c->flags & CHN_F_CLOSING) {
-sndbuf_dump(b, "b", 0x02);
-sndbuf_dump(bs, "bs", 0x02);
-})
+ struct snd_dbuf *b = c->bufhard;
+ struct snd_dbuf *bs = c->bufsoft;
+ unsigned int ret, amt;
-#if 0
-amt = sndbuf_getready(b);
-if (sndbuf_getfree(bs) < amt) {
-c->xruns++;
-amt = sndbuf_getfree(bs);
-}
-#endif
-amt = sndbuf_getfree(bs);
-ret = (amt > 0)? sndbuf_feed(b, bs, c, c->feeder, amt) : 0;
+ CHN_LOCKASSERT(c);
-amt = sndbuf_getready(b);
-if (amt > 0) {
-c->xruns++;
-sndbuf_dispose(b, NULL, amt);
-}
+ if (c->flags & CHN_F_MAPPED)
+ sndbuf_dispose(bs, NULL, sndbuf_getready(bs));
-chn_wakeup(c);
+ amt = sndbuf_getfree(bs);
+ ret = (amt > 0) ? sndbuf_feed(b, bs, c, c->feeder, amt) : ENOSPC;
-return ret;
+ amt = sndbuf_getready(b);
+ if (amt > 0) {
+ c->xruns++;
+ sndbuf_dispose(b, NULL, amt);
+ }
+
+ if (sndbuf_getready(bs) > 0)
+ chn_wakeup(c);
+
+ return ret;
}
void
chn_rdupdate(struct pcm_channel *c)
{
-int ret;
+ int ret;
-CHN_LOCKASSERT(c);
-KASSERT(c->direction == PCMDIR_REC, ("chn_rdupdate on bad channel"));
+ CHN_LOCKASSERT(c);
+ KASSERT(c->direction == PCMDIR_REC, ("chn_rdupdate on bad channel"));
-if ((c->flags & CHN_F_MAPPED) || !(c->flags & CHN_F_TRIGGERED))
-return;
-chn_trigger(c, PCMTRIG_EMLDMARD);
-chn_dmaupdate(c);
-ret = chn_rdfeed(c);
-DEB(if (ret)
-printf("chn_rdfeed: %dn", ret);)
+ if ((c->flags & (CHN_F_MAPPED | CHN_F_VIRTUAL)) || CHN_STOPPED(c))
+ return;
+ chn_trigger(c, PCMTRIG_EMLDMARD);
+ chn_dmaupdate(c);
+ ret = chn_rdfeed(c);
+ DEB(if (ret)
+ printf("chn_rdfeed: %d\n", ret);)
}
@@ -440,1095 +493,1703 @@
static void
chn_rdintr(struct pcm_channel *c)
{
-int ret;
+ int ret;
-CHN_LOCKASSERT(c);
-/* tell the driver to update the primary buffer if non-dma */
-chn_trigger(c, PCMTRIG_EMLDMARD);
-/* update pointers in primary buffer */
-chn_dmaupdate(c);
-/* ...and feed from primary to secondary */
-ret = chn_rdfeed(c);
+ CHN_LOCKASSERT(c);
+ /* tell the driver to update the primary buffer if non-dma */
+ chn_trigger(c, PCMTRIG_EMLDMARD);
+ /* update pointers in primary buffer */
+ chn_dmaupdate(c);
+ /* ...and feed from primary to secondary */
+ ret = chn_rdfeed(c);
}
/*
-* user read routine - trigger if necessary, uiomove data from secondary buffer
-* if blocking, sleep, rinse and repeat.
-*
-* called externally, so must handle locking
-*/
+ * user read routine - trigger if necessary, uiomove data from secondary buffer
+ * if blocking, sleep, rinse and repeat.
+ *
+ * called externally, so must handle locking
+ */
int
chn_read(struct pcm_channel *c, struct uio *buf)
{
-int ret, timeout, sz, count;
-struct snd_dbuf *bs = c->bufsoft;
-void *off;
-int t, x,togo,p;
-
-CHN_LOCKASSERT(c);
-if (!(c->flags & CHN_F_TRIGGERED))
-chn_start(c, 0);
-
-ret = 0;
-count = hz;
-while (!ret && (buf->uio_resid > 0) && (count > 0)) {
-sz = MIN(buf->uio_resid, sndbuf_getready(bs));
+ struct snd_dbuf *bs = c->bufsoft;
+ void *off;
+ int ret, timeout, sz, t, p;
+
+ CHN_LOCKASSERT(c);
+
+ if (CHN_STOPPED(c) && !(c->flags & CHN_F_NOTRIGGER)) {
+ ret = chn_start(c, 0);
+ if (ret != 0) {
+ c->flags |= CHN_F_DEAD;
+ return (ret);
+ }
+ }
+
+ ret = 0;
+ timeout = chn_timeout * hz;
+
+ while (ret == 0 && buf->uio_resid > 0) {
+ sz = min(buf->uio_resid, sndbuf_getready(bs));
+ if (sz > 0) {
+ /*
+ * The following assumes that the free space in
+ * the buffer can never be less around the
+ * unlock-uiomove-lock sequence.
+ */
+ while (ret == 0 && sz > 0) {
+ p = sndbuf_getreadyptr(bs);
+ t = min(sz, sndbuf_getsize(bs) - p);
+ off = sndbuf_getbufofs(bs, p);
+ CHN_UNLOCK(c);
+ ret = uiomove(off, t, buf);
+ CHN_LOCK(c);
+ sz -= t;
+ sndbuf_dispose(bs, NULL, t);
+ }
+ ret = 0;
+ } else if (c->flags & (CHN_F_NBIO | CHN_F_NOTRIGGER))
+ ret = EAGAIN;
+ else {
+ ret = chn_sleep(c, timeout);
+ if (ret == EAGAIN) {
+ ret = EINVAL;
+ c->flags |= CHN_F_DEAD;
+ printf("%s: record interrupt timeout, "
+ "channel dead\n", c->name);
+ } else if (ret == ERESTART || ret == EINTR)
+ c->flags |= CHN_F_ABORTING;
+ }
+ }
-if (sz > 0) {
-/*
-* The following assumes that the free space in
-* the buffer can never be less around the
-* unlock-uiomove-lock sequence.
-*/
-togo = sz;
-while (ret == 0 && togo> 0) {
-p = sndbuf_getreadyptr(bs);
-t = MIN(togo, sndbuf_getsize(bs) - p);
-off = sndbuf_getbufofs(bs, p);
-CHN_UNLOCK(c);
-ret = uiomove(off, t, buf);
-CHN_LOCK(c);
-togo -= t;
-x = sndbuf_dispose(bs, NULL, t);
-}
-ret = 0;
-} else {
-if (c->flags & CHN_F_NBIO) {
-ret = EWOULDBLOCK;
-} else {
-timeout = (hz * sndbuf_getblksz(bs)) / (sndbuf_getspd(bs) * sndbuf_getbps(bs));
-if (timeout < 1)
-timeout = 1;
-ret = chn_sleep(c, "pcmrd", timeout);
-if (ret == EWOULDBLOCK) {
-count -= timeout;
-ret = 0;
-} else {
-count = hz;
-}
-
-}
-}
-}
-
-if (count <= 0) {
-c->flags |= CHN_F_DEAD;
-printf("%s: record interrupt timeout, channel deadn", c->name);
-}
-
-return ret;
+ return (ret);
}
void
chn_intr(struct pcm_channel *c)
{
-CHN_LOCK(c);
-c->interrupts++;
-if (c->direction == PCMDIR_PLAY)
-chn_wrintr(c);
-else
-chn_rdintr(c);
-CHN_UNLOCK(c);
+ CHN_LOCK(c);
+ c->interrupts++;
+ if (c->direction == PCMDIR_PLAY)
+ chn_wrintr(c);
+ else
+ chn_rdintr(c);
+ CHN_UNLOCK(c);
}
u_int32_t
chn_start(struct pcm_channel *c, int force)
{
-u_int32_t i, j;
-struct snd_dbuf *b = c->bufhard;
-struct snd_dbuf *bs = c->bufsoft;
-
-CHN_LOCKASSERT(c);
-/* if we're running, or if we're prevented from triggering, bail */
-if ((c->flags & CHN_F_TRIGGERED) || ((c->flags & CHN_F_NOTRIGGER) && !force))
-return EINVAL;
-
-i = (c->direction == PCMDIR_PLAY)? sndbuf_getready(bs) : sndbuf_getfree(bs);
-j = (c->direction == PCMDIR_PLAY)? sndbuf_getfree(b) : sndbuf_getready(b);
-if (force || (i >= j)) {
-c->flags |= CHN_F_TRIGGERED;
-/*
-* if we're starting because a vchan started, don't feed any data
-* or it becomes impossible to start vchans synchronised with the
-* first one. the hardbuf should be empty so we top it up with
-* silence to give it something to chew. the real data will be
-* fed at the first irq.
-*/
-if (c->direction == PCMDIR_PLAY) {
-/*
-* Reduce pops during playback startup.
-*/
-sndbuf_fillsilence(b);
-if (SLIST_EMPTY(&c->children))
-chn_wrfeed(c);
-}
-sndbuf_setrun(b, 1);
-c->xruns = 0;
-chn_trigger(c, PCMTRIG_START);
-return 0;
-}
+ u_int32_t i, j;
+ struct snd_dbuf *b = c->bufhard;
+ struct snd_dbuf *bs = c->bufsoft;
+ int err;
+
+ CHN_LOCKASSERT(c);
+ /* if we're running, or if we're prevented from triggering, bail */
+ if (CHN_STARTED(c) || ((c->flags & CHN_F_NOTRIGGER) && !force))
+ return (EINVAL);
+
+ err = 0;
+
+ if (force) {
+ i = 1;
+ j = 0;
+ } else {
+ if (c->direction == PCMDIR_REC) {
+ i = sndbuf_getfree(bs);
+ j = (i > 0) ? 1 : sndbuf_getready(b);
+ } else {
+ if (sndbuf_getfree(bs) == 0) {
+ i = 1;
+ j = 0;
+ } else {
+ struct snd_dbuf *pb;
+
+ pb = CHN_BUF_PARENT(c, b);
+ i = sndbuf_xbytes(sndbuf_getready(bs), bs, pb);
+ j = sndbuf_getbps(pb);
+ }
+ }
+ if (snd_verbose > 3 && CHN_EMPTY(c, children))
+ printf("%s: %s (%s) threshold i=%d j=%d\n",
+ __func__, CHN_DIRSTR(c),
+ (c->flags & CHN_F_VIRTUAL) ? "virtual" : "hardware",
+ i, j);
+ }
+
+ if (i >= j) {
+ c->flags |= CHN_F_TRIGGERED;
+ sndbuf_setrun(b, 1);
+ c->feedcount = (c->flags & CHN_F_CLOSING) ? 2 : 0;
+ c->interrupts = 0;
+ c->xruns = 0;
+ if (c->direction == PCMDIR_PLAY && c->parentchannel == NULL) {
+ sndbuf_fillsilence(b);
+ if (snd_verbose > 3)
+ printf("%s: %s starting! (%s) (ready=%d "
+ "force=%d i=%d j=%d intrtimeout=%u "
+ "latency=%dms)\n",
+ __func__,
+ (c->flags & CHN_F_HAS_VCHAN) ?
+ "VCHAN" : "HW",
+ (c->flags & CHN_F_CLOSING) ? "closing" :
+ "running",
+ sndbuf_getready(b),
+ force, i, j, c->timeout,
+ (sndbuf_getsize(b) * 1000) /
+ (sndbuf_getbps(b) * sndbuf_getspd(b)));
+ }
+ err = chn_trigger(c, PCMTRIG_START);
+ }
-return 0;
+ return (err);
}
void
chn_resetbuf(struct pcm_channel *c)
{
-struct snd_dbuf *b = c->bufhard;
-struct snd_dbuf *bs = c->bufsoft;
+ struct snd_dbuf *b = c->bufhard;
+ struct snd_dbuf *bs = c->bufsoft;
-c->blocks = 0;
-sndbuf_reset(b);
-sndbuf_reset(bs);
+ c->blocks = 0;
+ sndbuf_reset(b);
+ sndbuf_reset(bs);
}
/*
-* chn_sync waits until the space in the given channel goes above
-* a threshold. The threshold is checked against fl or rl respectively.
-* Assume that the condition can become true, do not check here...
-*/
+ * chn_sync waits until the space in the given channel goes above
+ * a threshold. The threshold is checked against fl or rl respectively.
+ * Assume that the condition can become true, do not check here...
+ */
int
chn_sync(struct pcm_channel *c, int threshold)
{
-u_long rdy;
-int ret;
-struct snd_dbuf *bs = c->bufsoft;
-
-CHN_LOCKASSERT(c);
-
-/* if we haven't yet started and nothing is buffered, else start*/
-if (!(c->flags & CHN_F_TRIGGERED)) {
-if (sndbuf_getready(bs) > 0) {
-ret = chn_start(c, 1);
-if (ret)
-return ret;
-} else {
-return 0;
-}
-}
+ struct snd_dbuf *b, *bs;
+ int ret, count, hcount, minflush, resid, residp, syncdelay, blksz;
+ u_int32_t cflag;
+
+ CHN_LOCKASSERT(c);
+
+ if (c->direction != PCMDIR_PLAY)
+ return (EINVAL);
+
+ bs = c->bufsoft;
+
+ if ((c->flags & (CHN_F_DEAD | CHN_F_ABORTING)) ||
+ (threshold < 1 && sndbuf_getready(bs) < 1))
+ return (0);
+
+ /* if we haven't yet started and nothing is buffered, else start*/
+ if (CHN_STOPPED(c)) {
+ if (threshold > 0 || sndbuf_getready(bs) > 0) {
+ ret = chn_start(c, 1);
+ if (ret != 0)
+ return (ret);
+ } else
+ return (0);
+ }
+
+ b = CHN_BUF_PARENT(c, c->bufhard);
+
+ minflush = threshold + sndbuf_xbytes(sndbuf_getready(b), b, bs);
+
+ syncdelay = chn_syncdelay;
+
+ if (syncdelay < 0 && (threshold > 0 || sndbuf_getready(bs) > 0))
+ minflush += sndbuf_xbytes(sndbuf_getsize(b), b, bs);
+
+ /*
+ * Append (0-1000) millisecond trailing buffer (if needed)
+ * for slower / high latency hardwares (notably USB audio)
+ * to avoid audible truncation.
+ */
+ if (syncdelay > 0)
+ minflush += (sndbuf_getbps(bs) * sndbuf_getspd(bs) *
+ ((syncdelay > 1000) ? 1000 : syncdelay)) / 1000;
+
+ minflush -= minflush % sndbuf_getbps(bs);
+
+ if (minflush > 0) {
+ threshold = min(minflush, sndbuf_getfree(bs));
+ sndbuf_clear(bs, threshold);
+ sndbuf_acquire(bs, NULL, threshold);
+ minflush -= threshold;
+ }
+
+ resid = sndbuf_getready(bs);
+ residp = resid;
+ blksz = sndbuf_getblksz(b);
+ if (blksz < 1) {
+ printf("%s: WARNING: blksz < 1 ! maxsize=%d [%d/%d/%d]\n",
+ __func__, sndbuf_getmaxsize(b), sndbuf_getsize(b),
+ sndbuf_getblksz(b), sndbuf_getblkcnt(b));
+ if (sndbuf_getblkcnt(b) > 0)
+ blksz = sndbuf_getsize(b) / sndbuf_getblkcnt(b);
+ if (blksz < 1)
+ blksz = 1;
+ }
+ count = sndbuf_xbytes(minflush + resid, bs, b) / blksz;
+ hcount = count;
+ ret = 0;
+
+ if (snd_verbose > 3)
+ printf("%s: [begin] timeout=%d count=%d "
+ "minflush=%d resid=%d\n", __func__, c->timeout, count,
+ minflush, resid);
+
+ cflag = c->flags & CHN_F_CLOSING;
+ c->flags |= CHN_F_CLOSING;
+ while (count > 0 && (resid > 0 || minflush > 0)) {
+ ret = chn_sleep(c, c->timeout);
+ if (ret == ERESTART || ret == EINTR) {
+ c->flags |= CHN_F_ABORTING;
+ break;
+ } else if (ret == 0 || ret == EAGAIN) {
+ resid = sndbuf_getready(bs);
+ if (resid == residp) {
+ --count;
+ if (snd_verbose > 3)
+ printf("%s: [stalled] timeout=%d "
+ "count=%d hcount=%d "
+ "resid=%d minflush=%d\n",
+ __func__, c->timeout, count,
+ hcount, resid, minflush);
+ } else if (resid < residp && count < hcount) {
+ ++count;
+ if (snd_verbose > 3)
+ printf("%s: [resume] timeout=%d "
+ "count=%d hcount=%d "
+ "resid=%d minflush=%d\n",
+ __func__, c->timeout, count,
+ hcount, resid, minflush);
+ }
+ if (minflush > 0 && sndbuf_getfree(bs) > 0) {
+ threshold = min(minflush,
+ sndbuf_getfree(bs));
+ sndbuf_clear(bs, threshold);
+ sndbuf_acquire(bs, NULL, threshold);
+ resid = sndbuf_getready(bs);
+ minflush -= threshold;
+ }
+ residp = resid;
+ } else
+ break;
+ }
+ c->flags &= ~CHN_F_CLOSING;
+ c->flags |= cflag;
+
+ if (snd_verbose > 3)
+ printf("%s: timeout=%d count=%d hcount=%d resid=%d residp=%d "
+ "minflush=%d ret=%d\n",
+ __func__, c->timeout, count, hcount, resid, residp,
+ minflush, ret);
-for (;;) {
-rdy = (c->direction == PCMDIR_PLAY)? sndbuf_getfree(bs) : sndbuf_getready(bs);
-if (rdy <= threshold) {
-ret = chn_sleep(c, "pcmsyn", 1);
-if (ret == ERESTART || ret == EINTR) {
-DEB(printf("chn_sync: tsleep returns %dn", ret));
-return -1;
-}
-} else
-break;
-}
-return 0;
+ return (0);
}
/* called externally, handle locking */
int
chn_poll(struct pcm_channel *c, int ev, struct thread *td)
{
-struct snd_dbuf *bs = c->bufsoft;
-int ret;
+ struct snd_dbuf *bs = c->bufsoft;
+ int ret;
-CHN_LOCKASSERT(c);
-if (!(c->flags & CHN_F_MAPPED) && !(c->flags & CHN_F_TRIGGERED))
-chn_start(c, 1);
-ret = 0;
-if (chn_polltrigger(c) && chn_pollreset(c))
-ret = ev;
-else
-selrecord(td, sndbuf_getsel(bs));
-return ret;
+ CHN_LOCKASSERT(c);
+ if (!(c->flags & (CHN_F_MAPPED | CHN_F_TRIGGERED))) {
+ ret = chn_start(c, 1);
+ if (ret != 0)
+ return (0);
+ }
+ ret = 0;
+ if (chn_polltrigger(c) && chn_pollreset(c))
+ ret = ev;
+ else
+ selrecord(td, sndbuf_getsel(bs));
+ return (ret);
}
/*
-* chn_abort terminates a running dma transfer. it may sleep up to 200ms.
-* it returns the number of bytes that have not been transferred.
-*
-* called from: dsp_close, dsp_ioctl, with channel locked
-*/
+ * chn_abort terminates a running dma transfer. it may sleep up to 200ms.
+ * it returns the number of bytes that have not been transferred.
+ *
+ * called from: dsp_close, dsp_ioctl, with channel locked
+ */
int
chn_abort(struct pcm_channel *c)
{
-int missing = 0;
-struct snd_dbuf *b = c->bufhard;
-struct snd_dbuf *bs = c->bufsoft;
-
-CHN_LOCKASSERT(c);
-if (!(c->flags & CHN_F_TRIGGERED))
-return 0;
-c->flags |= CHN_F_ABORTING;
-
-c->flags &= ~CHN_F_TRIGGERED;
-/* kill the channel */
-chn_trigger(c, PCMTRIG_ABORT);
-sndbuf_setrun(b, 0);
-if (!(c->flags & CHN_F_VIRTUAL))
-chn_dmaupdate(c);
-missing = sndbuf_getready(bs) + sndbuf_getready(b);
-
-c->flags &= ~CHN_F_ABORTING;
-return missing;
+ int missing = 0;
+ struct snd_dbuf *b = c->bufhard;
+ struct snd_dbuf *bs = c->bufsoft;
+
+ CHN_LOCKASSERT(c);
+ if (CHN_STOPPED(c))
+ return 0;
+ c->flags |= CHN_F_ABORTING;
+
+ c->flags &= ~CHN_F_TRIGGERED;
+ /* kill the channel */
+ chn_trigger(c, PCMTRIG_ABORT);
+ sndbuf_setrun(b, 0);
+ if (!(c->flags & CHN_F_VIRTUAL))
+ chn_dmaupdate(c);
+ missing = sndbuf_getready(bs);
+
+ c->flags &= ~CHN_F_ABORTING;
+ return missing;
}
/*
-* this routine tries to flush the dma transfer. It is called
-* on a close of a playback channel.
-* first, if there is data in the buffer, but the dma has not yet
-* begun, we need to start it.
-* next, we wait for the play buffer to drain
-* finally, we stop the dma.
-*
-* called from: dsp_close, not valid for record channels.
-*/
+ * this routine tries to flush the dma transfer. It is called
+ * on a close of a playback channel.
+ * first, if there is data in the buffer, but the dma has not yet
+ * begun, we need to start it.
+ * next, we wait for the play buffer to drain
+ * finally, we stop the dma.
+ *
+ * called from: dsp_close, not valid for record channels.
+ */
int
chn_flush(struct pcm_channel *c)
{
-int ret, count, resid, resid_p;
-struct snd_dbuf *b = c->bufhard;
-struct snd_dbuf *bs = c->bufsoft;
-
-CHN_LOCKASSERT(c);
-KASSERT(c->direction == PCMDIR_PLAY, ("chn_flush on bad channel"));
-DEB(printf("chn_flush: c->flags 0x%08xn", c->flags));
-
-/* if we haven't yet started and nothing is buffered, else start*/
-if (!(c->flags & CHN_F_TRIGGERED)) {
-if (sndbuf_getready(bs) > 0) {
-ret = chn_start(c, 1);
-if (ret)
-return ret;
-} else {
-return 0;
-}
-}
+ struct snd_dbuf *b = c->bufhard;
-c->flags |= CHN_F_CLOSING;
-resid = sndbuf_getready(bs) + sndbuf_getready(b);
-resid_p = resid;
-count = 10;
-ret = 0;
-while ((count > 0) && (resid > sndbuf_getsize(b)) && (ret == 0)) {
-/* still pending output data. */
-ret = chn_sleep(c, "pcmflu", hz / 10);
-if (ret == EWOULDBLOCK)
-ret = 0;
-if (ret == 0) {
-resid = sndbuf_getready(bs) + sndbuf_getready(b);
-if (resid == resid_p)
-count--;
-if (resid > resid_p)
-DEB(printf("chn_flush: buffer length increasind %d -> %dn", resid_p, resid));
-resid_p = resid;
-}
-}
-if (count == 0)
-DEB(printf("chn_flush: timeout, hw %d, sw %dn",
-sndbuf_getready(b), sndbuf_getready(bs)));
-
-c->flags &= ~CHN_F_TRIGGERED;
-/* kill the channel */
-chn_trigger(c, PCMTRIG_ABORT);
-sndbuf_setrun(b, 0);
+ CHN_LOCKASSERT(c);
+ KASSERT(c->direction == PCMDIR_PLAY, ("chn_flush on bad channel"));
+ DEB(printf("chn_flush: c->flags 0x%08x\n", c->flags));
+
+ c->flags |= CHN_F_CLOSING;
+ chn_sync(c, 0);
+ c->flags &= ~CHN_F_TRIGGERED;
+ /* kill the channel */
+ chn_trigger(c, PCMTRIG_ABORT);
+ sndbuf_setrun(b, 0);
-c->flags &= ~CHN_F_CLOSING;
-return 0;
+ c->flags &= ~CHN_F_CLOSING;
+ return 0;
}
int
fmtvalid(u_int32_t fmt, u_int32_t *fmtlist)
{
-int i;
+ int i;
+
+ for (i = 0; fmtlist[i]; i++)
+ if (fmt == fmtlist[i])
+ return 1;
+ return 0;
+}
+
+static struct afmtstr_table default_afmtstr_table[] = {
+ { "alaw", AFMT_A_LAW }, { "mulaw", AFMT_MU_LAW },
+ { "u8", AFMT_U8 }, { "s8", AFMT_S8 },
+ { "s16le", AFMT_S16_LE }, { "s16be", AFMT_S16_BE },
+ { "u16le", AFMT_U16_LE }, { "u16be", AFMT_U16_BE },
+ { "s24le", AFMT_S24_LE }, { "s24be", AFMT_S24_BE },
+ { "u24le", AFMT_U24_LE }, { "u24be", AFMT_U24_BE },
+ { "s32le", AFMT_S32_LE }, { "s32be", AFMT_S32_BE },
+ { "u32le", AFMT_U32_LE }, { "u32be", AFMT_U32_BE },
+ { NULL, 0 },
+};
-for (i = 0; fmtlist[i]; i++)
-if (fmt == fmtlist[i])
-return 1;
-return 0;
+int
+afmtstr_swap_sign(char *s)
+{
+ if (s == NULL || strlen(s) < 2) /* full length of "s8" */
+ return 0;
+ if (*s == 's')
+ *s = 'u';
+ else if (*s == 'u')
+ *s = 's';
+ else
+ return 0;
+ return 1;
+}
+
+int
+afmtstr_swap_endian(char *s)
+{
+ if (s == NULL || strlen(s) < 5) /* full length of "s16le" */
+ return 0;
+ if (s[3] == 'l')
+ s[3] = 'b';
+ else if (s[3] == 'b')
+ s[3] = 'l';
+ else
+ return 0;
+ return 1;
+}
+
+u_int32_t
+afmtstr2afmt(struct afmtstr_table *tbl, const char *s, int stereo)
+{
+ size_t fsz, sz;
+
+ sz = (s == NULL) ? 0 : strlen(s);
+
+ if (sz > 1) {
+
+ if (tbl == NULL)
+ tbl = default_afmtstr_table;
+
+ for (; tbl->fmtstr != NULL; tbl++) {
+ fsz = strlen(tbl->fmtstr);
+ if (sz < fsz)
+ continue;
+ if (strncmp(s, tbl->fmtstr, fsz) != 0)
+ continue;
+ if (fsz == sz)
+ return tbl->format |
+ ((stereo) ? AFMT_STEREO : 0);
+ if ((sz - fsz) < 2 || s[fsz] != ':')
+ break;
+ /*
+ * For now, just handle mono/stereo.
+ */
+ if ((s[fsz + 2] == '\0' && (s[fsz + 1] == 'm' ||
+ s[fsz + 1] == '1')) ||
+ strcmp(s + fsz + 1, "mono") == 0)
+ return tbl->format;
+ if ((s[fsz + 2] == '\0' && (s[fsz + 1] == 's' ||
+ s[fsz + 1] == '2')) ||
+ strcmp(s + fsz + 1, "stereo") == 0)
+ return tbl->format | AFMT_STEREO;
+ break;
+ }
+ }
+
+ return 0;
+}
+
+u_int32_t
+afmt2afmtstr(struct afmtstr_table *tbl, u_int32_t afmt, char *dst,
+ size_t len, int type, int stereo)
+{
+ u_int32_t fmt = 0;
+ char *fmtstr = NULL, *tag = "";
+
+ if (tbl == NULL)
+ tbl = default_afmtstr_table;
+
+ for (; tbl->format != 0; tbl++) {
+ if (tbl->format == 0)
+ break;
+ if ((afmt & ~AFMT_STEREO) != tbl->format)
+ continue;
+ fmt = afmt;
+ fmtstr = tbl->fmtstr;
+ break;
+ }
+
+ if (fmt != 0 && fmtstr != NULL && dst != NULL && len > 0) {
+ strlcpy(dst, fmtstr, len);
+ switch (type) {
+ case AFMTSTR_SIMPLE:
+ tag = (fmt & AFMT_STEREO) ? ":s" : ":m";
+ break;
+ case AFMTSTR_NUM:
+ tag = (fmt & AFMT_STEREO) ? ":2" : ":1";
+ break;
+ case AFMTSTR_FULL:
+ tag = (fmt & AFMT_STEREO) ? ":stereo" : ":mono";
+ break;
+ case AFMTSTR_NONE:
+ default:
+ break;
+ }
+ if (strlen(tag) > 0 && ((stereo && !(fmt & AFMT_STEREO)) || \
+ (!stereo && (fmt & AFMT_STEREO))))
+ strlcat(dst, tag, len);
+ }
+
+ return fmt;
}
int
chn_reset(struct pcm_channel *c, u_int32_t fmt)
{
-int hwspd, r;
+ int hwspd, r;
-CHN_LOCKASSERT(c);
-c->flags &= CHN_F_RESET;
-c->interrupts = 0;
-c->xruns = 0;
+ CHN_LOCKASSERT(c);
+ c->feedcount = 0;
+ c->flags &= CHN_F_RESET;
+ c->interrupts = 0;
+ c->timeout = 1;
+ c->xruns = 0;
-r = CHANNEL_RESET(c->methods, c->devinfo);
-if (fmt != 0) {
+ r = CHANNEL_RESET(c->methods, c->devinfo);
+ if (fmt != 0) {
#if 0
-hwspd = DSP_DEFAULT_SPEED;
-/* only do this on a record channel until feederbuilder works */
-if (c->direction == PCMDIR_REC)
-RANGE(hwspd, chn_getcaps(c)->minspeed, chn_getcaps(c)->maxspeed);
-c->speed = hwspd;
+ hwspd = DSP_DEFAULT_SPEED;
+ /* only do this on a record channel until feederbuilder works */
+ if (c->direction == PCMDIR_REC)
+ RANGE(hwspd, chn_getcaps(c)->minspeed, chn_getcaps(c)->maxspeed);
+ c->speed = hwspd;
#endif
-hwspd = chn_getcaps(c)->minspeed;
-c->speed = hwspd;
+ hwspd = chn_getcaps(c)->minspeed;
+ c->speed = hwspd;
-if (r == 0)
-r = chn_setformat(c, fmt);
-if (r == 0)
-r = chn_setspeed(c, hwspd);
+ if (r == 0)
+ r = chn_setformat(c, fmt);
+ if (r == 0)
+ r = chn_setspeed(c, hwspd);
#if 0
-if (r == 0)
-r = chn_setvolume(c, 100, 100);
+ if (r == 0)
+ r = chn_setvolume(c, 100, 100);
#endif
-}
-if (r == 0)
-r = chn_setblocksize(c, 0, 0);
-if (r == 0) {
-chn_resetbuf(c);
-r = CHANNEL_RESETDONE(c->methods, c->devinfo);
-}
-return r;
+ }
+ if (r == 0)
+ r = chn_setlatency(c, chn_latency);
+ if (r == 0) {
+ chn_resetbuf(c);
+ r = CHANNEL_RESETDONE(c->methods, c->devinfo);
+ }
+ return r;
}
int
chn_init(struct pcm_channel *c, void *devinfo, int dir, int direction)
{
-struct feeder_class *fc;
-struct snd_dbuf *b, *bs;
-int ret;
-
-chn_lockinit(c, dir);
-
-b = NULL;
-bs = NULL;
-c->devinfo = NULL;
-c->feeder = NULL;
-
-ret = ENOMEM;
-b = sndbuf_create(c->dev, c->name, "primary", c);
-if (b == NULL)
-goto out;
-bs = sndbuf_create(c->dev, c->name, "secondary", c);
-if (bs == NULL)
-goto out;
-
-CHN_LOCK(c);
-
-ret = EINVAL;
-fc = feeder_getclass(NULL);
-if (fc == NULL)
-goto out;
-if (chn_addfeeder(c, fc, NULL))
-goto out;
-
-/*
-* XXX - sndbuf_setup() & sndbuf_resize() expect to be called
-* with the channel unlocked because they are also called
-* from driver methods that don't know about locking
-*/
-CHN_UNLOCK(c);
-sndbuf_setup(bs, NULL, 0);
-CHN_LOCK(c);
-c->bufhard = b;
-c->bufsoft = bs;
-c->flags = 0;
-c->feederflags = 0;
-
-ret = ENODEV;
-CHN_UNLOCK(c); /* XXX - Unlock for CHANNEL_INIT() malloc() call */
-c->devinfo = CHANNEL_INIT(c->methods, devinfo, b, c, direction);
-CHN_LOCK(c);
-if (c->devinfo == NULL)
-goto out;
-
-ret = ENOMEM;
-if ((sndbuf_getsize(b) == 0) && ((c->flags & CHN_F_VIRTUAL) == 0))
-goto out;
-
-ret = chn_setdir(c, direction);
-if (ret)
-goto out;
-
-ret = sndbuf_setfmt(b, AFMT_U8);
-if (ret)
-goto out;
-
-ret = sndbuf_setfmt(bs, AFMT_U8);
-if (ret)
-goto out;
-
+ struct feeder_class *fc;
+ struct snd_dbuf *b, *bs;
+ int ret;
+
+ if (chn_timeout < CHN_TIMEOUT_MIN || chn_timeout > CHN_TIMEOUT_MAX)
+ chn_timeout = CHN_TIMEOUT;
+
+ chn_lockinit(c, dir);
+
+ b = NULL;
+ bs = NULL;
+ CHN_INIT(c, children);
+ CHN_INIT(c, children.busy);
+ c->devinfo = NULL;
+ c->feeder = NULL;
+ c->latency = -1;
+ c->timeout = 1;
+
+ ret = ENOMEM;
+ b = sndbuf_create(c->dev, c->name, "primary", c);
+ if (b == NULL)
+ goto out;
+ bs = sndbuf_create(c->dev, c->name, "secondary", c);
+ if (bs == NULL)
+ goto out;
+
+ CHN_LOCK(c);
+
+ ret = EINVAL;
+ fc = feeder_getclass(NULL);
+ if (fc == NULL)
+ goto out;
+ if (chn_addfeeder(c, fc, NULL))
+ goto out;
+
+ /*
+ * XXX - sndbuf_setup() & sndbuf_resize() expect to be called
+ * with the channel unlocked because they are also called
+ * from driver methods that don't know about locking
+ */
+ CHN_UNLOCK(c);
+ sndbuf_setup(bs, NULL, 0);
+ CHN_LOCK(c);
+ c->bufhard = b;
+ c->bufsoft = bs;
+ c->flags = 0;
+ c->feederflags = 0;
+ c->sm = NULL;
+
+ ret = ENODEV;
+ CHN_UNLOCK(c); /* XXX - Unlock for CHANNEL_INIT() malloc() call */
+ c->devinfo = CHANNEL_INIT(c->methods, devinfo, b, c, direction);
+ CHN_LOCK(c);
+ if (c->devinfo == NULL)
+ goto out;
+
+ ret = ENOMEM;
+ if ((sndbuf_getsize(b) == 0) && ((c->flags & CHN_F_VIRTUAL) == 0))
+ goto out;
+
+ ret = chn_setdir(c, direction);
+ if (ret)
+ goto out;
+
+ ret = sndbuf_setfmt(b, AFMT_U8);
+ if (ret)
+ goto out;
+
+ ret = sndbuf_setfmt(bs, AFMT_U8);
+ if (ret)
+ goto out;
+
+ /**
+ * @todo Should this be moved somewhere else? The primary buffer
+ * is allocated by the driver or via DMA map setup, and tmpbuf
+ * seems to only come into existence in sndbuf_resize().
+ */
+ if (c->direction == PCMDIR_PLAY) {
+ bs->sl = sndbuf_getmaxsize(bs);
+ bs->shadbuf = malloc(bs->sl, M_DEVBUF, M_NOWAIT);
+ if (bs->shadbuf == NULL) {
+ ret = ENOMEM;
+ goto out;
+ }
+ }
out:
-CHN_UNLOCK(c);
-if (ret) {
-if (c->devinfo) {
-if (CHANNEL_FREE(c->methods, c->devinfo))
-sndbuf_free(b);
-}
-if (bs)
-sndbuf_destroy(bs);
-if (b)
-sndbuf_destroy(b);
-c->flags |= CHN_F_DEAD;
-chn_lockdestroy(c);
+ CHN_UNLOCK(c);
+ if (ret) {
+ if (c->devinfo) {
+ if (CHANNEL_FREE(c->methods, c->devinfo))
+ sndbuf_free(b);
+ }
+ if (bs)
+ sndbuf_destroy(bs);
+ if (b)
+ sndbuf_destroy(b);
+ CHN_LOCK(c);
+ c->flags |= CHN_F_DEAD;
+ chn_lockdestroy(c);
-return ret;
-}
+ return ret;
+ }
-return 0;
+ return 0;
}
int
chn_kill(struct pcm_channel *c)
{
-struct snd_dbuf *b = c->bufhard;
-struct snd_dbuf *bs = c->bufsoft;
+ struct snd_dbuf *b = c->bufhard;
+ struct snd_dbuf *bs = c->bufsoft;
+
+ if (CHN_STARTED(c)) {
+ CHN_LOCK(c);
+ chn_trigger(c, PCMTRIG_ABORT);
+ CHN_UNLOCK(c);
+ }
+ while (chn_removefeeder(c) == 0)
+ ;
+ if (CHANNEL_FREE(c->methods, c->devinfo))
+ sndbuf_free(b);
+ sndbuf_destroy(bs);
+ sndbuf_destroy(b);
+ CHN_LOCK(c);
+ c->flags |= CHN_F_DEAD;
+ chn_lockdestroy(c);
-if (c->flags & CHN_F_TRIGGERED)
-chn_trigger(c, PCMTRIG_ABORT);
-while (chn_removefeeder(c) == 0);
-if (CHANNEL_FREE(c->methods, c->devinfo))
-sndbuf_free(b);
-c->flags |= CHN_F_DEAD;
-sndbuf_destroy(bs);
-sndbuf_destroy(b);
-chn_lockdestroy(c);
-return 0;
+ return (0);
}
int
chn_setdir(struct pcm_channel *c, int dir)
{
#ifdef DEV_ISA
-struct snd_dbuf *b = c->bufhard;
+ struct snd_dbuf *b = c->bufhard;
#endif
-int r;
+ int r;
-CHN_LOCKASSERT(c);
-c->direction = dir;
-r = CHANNEL_SETDIR(c->methods, c->devinfo, c->direction);
+ CHN_LOCKASSERT(c);
+ c->direction = dir;
+ r = CHANNEL_SETDIR(c->methods, c->devinfo, c->direction);
#ifdef DEV_ISA
-if (!r && SND_DMA(b))
-sndbuf_dmasetdir(b, c->direction);
+ if (!r && SND_DMA(b))
+ sndbuf_dmasetdir(b, c->direction);
#endif
-return r;
+ return r;
}
int
chn_setvolume(struct pcm_channel *c, int left, int right)
{
-CHN_LOCKASSERT(c);
-/* should add a feeder for volume changing if channel returns -1 */
-if (left > 100)
-left = 100;
-if (left < 0)
-left = 0;
-if (right > 100)
-right = 100;
-if (right < 0)
-right = 0;
-c->volume = left | (right << 8);
-return 0;
+ CHN_LOCKASSERT(c);
+ /* should add a feeder for volume changing if channel returns -1 */
+ if (left > 100)
+ left = 100;
+ if (left < 0)
+ left = 0;
+ if (right > 100)
+ right = 100;
+ if (right < 0)
+ right = 0;
+ c->volume = left | (right << 8);
+ return 0;
+}
+
+static u_int32_t
+round_pow2(u_int32_t v)
+{
+ u_int32_t ret;
+
+ if (v < 2)
+ v = 2;
+ ret = 0;
+ while (v >> ret)
+ ret++;
+ ret = 1 << (ret - 1);
+ while (ret < v)
+ ret <<= 1;
+ return ret;
+}
+
+static u_int32_t
+round_blksz(u_int32_t v, int round)
+{
+ u_int32_t ret, tmp;
+
+ if (round < 1)
+ round = 1;
+
+ ret = min(round_pow2(v), CHN_2NDBUFMAXSIZE >> 1);
+
+ if (ret > v && (ret >> 1) > 0 && (ret >> 1) >= ((v * 3) >> 2))
+ ret >>= 1;
+
+ tmp = ret - (ret % round);
+ while (tmp < 16 || tmp < round) {
+ ret <<= 1;
+ tmp = ret - (ret % round);
+ }
+
+ return ret;
+}
+
+/*
+ * 4Front call it DSP Policy, while we call it "Latency Profile". The idea
+ * is to keep 2nd buffer short so that it doesn't cause long queue during
+ * buffer transfer.
+ *
+ * Latency reference table for 48khz stereo 16bit: (PLAY)
+ *
+ * +---------+------------+-----------+------------+
+ * | Latency | Blockcount | Blocksize | Buffersize |
+ * +---------+------------+-----------+------------+
+ * | 0 | 2 | 64 | 128 |
+ * +---------+------------+-----------+------------+
+ * | 1 | 4 | 128 | 512 |
+ * +---------+------------+-----------+------------+
+ * | 2 | 8 | 512 | 4096 |
+ * +---------+------------+-----------+------------+
+ * | 3 | 16 | 512 | 8192 |
+ * +---------+------------+-----------+------------+
+ * | 4 | 32 | 512 | 16384 |
+ * +---------+------------+-----------+------------+
+ * | 5 | 32 | 1024 | 32768 |
+ * +---------+------------+-----------+------------+
+ * | 6 | 16 | 2048 | 32768 |
+ * +---------+------------+-----------+------------+
+ * | 7 | 8 | 4096 | 32768 |
+ * +---------+------------+-----------+------------+
+ * | 8 | 4 | 8192 | 32768 |
+ * +---------+------------+-----------+------------+
+ * | 9 | 2 | 16384 | 32768 |
+ * +---------+------------+-----------+------------+
+ * | 10 | 2 | 32768 | 65536 |
+ * +---------+------------+-----------+------------+
+ *
+ * Recording need a different reference table. All we care is
+ * gobbling up everything within reasonable buffering threshold.
+ *
+ * Latency reference table for 48khz stereo 16bit: (REC)
+ *
+ * +---------+------------+-----------+------------+
+ * | Latency | Blockcount | Blocksize | Buffersize |
+ * +---------+------------+-----------+------------+
+ * | 0 | 512 | 32 | 16384 |
+ * +---------+------------+-----------+------------+
+ * | 1 | 256 | 64 | 16384 |
+ * +---------+------------+-----------+------------+
+ * | 2 | 128 | 128 | 16384 |
+ * +---------+------------+-----------+------------+
+ * | 3 | 64 | 256 | 16384 |
+ * +---------+------------+-----------+------------+
+ * | 4 | 32 | 512 | 16384 |
+ * +---------+------------+-----------+------------+
+ * | 5 | 32 | 1024 | 32768 |
+ * +---------+------------+-----------+------------+
+ * | 6 | 16 | 2048 | 32768 |
+ * +---------+------------+-----------+------------+
+ * | 7 | 8 | 4096 | 32768 |
+ * +---------+------------+-----------+------------+
+ * | 8 | 4 | 8192 | 32768 |
+ * +---------+------------+-----------+------------+
+ * | 9 | 2 | 16384 | 32768 |
+ * +---------+------------+-----------+------------+
+ * | 10 | 2 | 32768 | 65536 |
+ * +---------+------------+-----------+------------+
+ *
+ * Calculations for other data rate are entirely based on these reference
+ * tables. For normal operation, Latency 5 seems give the best, well
+ * balanced performance for typical workload. Anything below 5 will
+ * eat up CPU to keep up with increasing context switches because of
+ * shorter buffer space and usually require the application to handle it
+ * aggresively through possibly real time programming technique.
+ *
+ */
+#define CHN_LATENCY_PBLKCNT_REF \
+ {{1, 2, 3, 4, 5, 5, 4, 3, 2, 1, 1}, \
+ {1, 2, 3, 4, 5, 5, 4, 3, 2, 1, 1}}
+#define CHN_LATENCY_PBUFSZ_REF \
+ {{7, 9, 12, 13, 14, 15, 15, 15, 15, 15, 16}, \
+ {11, 12, 13, 14, 15, 16, 16, 16, 16, 16, 17}}
+
+#define CHN_LATENCY_RBLKCNT_REF \
+ {{9, 8, 7, 6, 5, 5, 4, 3, 2, 1, 1}, \
+ {9, 8, 7, 6, 5, 5, 4, 3, 2, 1, 1}}
+#define CHN_LATENCY_RBUFSZ_REF \
+ {{14, 14, 14, 14, 14, 15, 15, 15, 15, 15, 16}, \
+ {15, 15, 15, 15, 15, 16, 16, 16, 16, 16, 17}}
+
+#define CHN_LATENCY_DATA_REF 192000 /* 48khz stereo 16bit ~ 48000 x 2 x 2 */
+
+static int
+chn_calclatency(int dir, int latency, int bps, u_int32_t datarate,
+ u_int32_t max, int *rblksz, int *rblkcnt)
+{
+ static int pblkcnts[CHN_LATENCY_PROFILE_MAX + 1][CHN_LATENCY_MAX + 1] =
+ CHN_LATENCY_PBLKCNT_REF;
+ static int pbufszs[CHN_LATENCY_PROFILE_MAX + 1][CHN_LATENCY_MAX + 1] =
+ CHN_LATENCY_PBUFSZ_REF;
+ static int rblkcnts[CHN_LATENCY_PROFILE_MAX + 1][CHN_LATENCY_MAX + 1] =
+ CHN_LATENCY_RBLKCNT_REF;
+ static int rbufszs[CHN_LATENCY_PROFILE_MAX + 1][CHN_LATENCY_MAX + 1] =
+ CHN_LATENCY_RBUFSZ_REF;
+ u_int32_t bufsz;
+ int lprofile, blksz, blkcnt;
+
+ if (latency < CHN_LATENCY_MIN || latency > CHN_LATENCY_MAX ||
+ bps < 1 || datarate < 1 ||
+ !(dir == PCMDIR_PLAY || dir == PCMDIR_REC)) {
+ if (rblksz != NULL)
+ *rblksz = CHN_2NDBUFMAXSIZE >> 1;
+ if (rblkcnt != NULL)
+ *rblkcnt = 2;
+ printf("%s: FAILED dir=%d latency=%d bps=%d "
+ "datarate=%u max=%u\n",
+ __func__, dir, latency, bps, datarate, max);
+ return CHN_2NDBUFMAXSIZE;
+ }
+
+ lprofile = chn_latency_profile;
+
+ if (dir == PCMDIR_PLAY) {
+ blkcnt = pblkcnts[lprofile][latency];
+ bufsz = pbufszs[lprofile][latency];
+ } else {
+ blkcnt = rblkcnts[lprofile][latency];
+ bufsz = rbufszs[lprofile][latency];
+ }
+
+ bufsz = round_pow2(snd_xbytes(1 << bufsz, CHN_LATENCY_DATA_REF,
+ datarate));
+ if (bufsz > max)
+ bufsz = max;
+ blksz = round_blksz(bufsz >> blkcnt, bps);
+
+ if (rblksz != NULL)
+ *rblksz = blksz;
+ if (rblkcnt != NULL)
+ *rblkcnt = 1 << blkcnt;
+
+ return blksz << blkcnt;
}
static int
-chn_tryspeed(struct pcm_channel *c, int speed)
+chn_resizebuf(struct pcm_channel *c, int latency,
+ int blkcnt, int blksz)
{
-struct pcm_feeder *f;
-struct snd_dbuf *b = c->bufhard;
-struct snd_dbuf *bs = c->bufsoft;
-struct snd_dbuf *x;
-int r, delta;
-
-CHN_LOCKASSERT(c);
-DEB(printf("setspeed, channel %sn", c->name));
-DEB(printf("want speed %d, ", speed));
-if (speed <= 0)
-return EINVAL;
-if (CANCHANGE(c)) {
-r = 0;
-c->speed = speed;
-sndbuf_setspd(bs, speed);
-RANGE(speed, chn_getcaps(c)->minspeed, chn_getcaps(c)->maxspeed);
-DEB(printf("try speed %d, ", speed));
-sndbuf_setspd(b, CHANNEL_SETSPEED(c->methods, c->devinfo, speed));
-DEB(printf("got speed %dn", sndbuf_getspd(b)));
-
-delta = sndbuf_getspd(b) - sndbuf_getspd(bs);
-if (delta < 0)
-delta = -delta;
+ struct snd_dbuf *b, *bs, *pb;
+ int sblksz, sblkcnt, hblksz, hblkcnt, limit = 1;
+ int ret;
+
+ CHN_LOCKASSERT(c);
+
+ if ((c->flags & (CHN_F_MAPPED | CHN_F_TRIGGERED)) ||
+ !(c->direction == PCMDIR_PLAY || c->direction == PCMDIR_REC))
+ return EINVAL;
+
+ if (latency == -1) {
+ c->latency = -1;
+ latency = chn_latency;
+ } else if (latency == -2) {
+ latency = c->latency;
+ if (latency < CHN_LATENCY_MIN || latency > CHN_LATENCY_MAX)
+ latency = chn_latency;
+ } else if (latency < CHN_LATENCY_MIN || latency > CHN_LATENCY_MAX)
+ return EINVAL;
+ else {
+ c->latency = latency;
+ limit = 0;
+ }
+
+ bs = c->bufsoft;
+ b = c->bufhard;
+
+ if (!(blksz == 0 || blkcnt == -1) &&
+ (blksz < 16 || blksz < sndbuf_getbps(bs) || blkcnt < 2 ||
+ (blksz * blkcnt) > CHN_2NDBUFMAXSIZE))
+ return EINVAL;
+
+ chn_calclatency(c->direction, latency, sndbuf_getbps(bs),
+ sndbuf_getbps(bs) * sndbuf_getspd(bs), CHN_2NDBUFMAXSIZE,
+ &sblksz, &sblkcnt);
+
+ if (blksz == 0 || blkcnt == -1) {
+ if (blkcnt == -1)
+ c->flags &= ~CHN_F_HAS_SIZE;
+ if (c->flags & CHN_F_HAS_SIZE) {
+ blksz = sndbuf_getblksz(bs);
+ blkcnt = sndbuf_getblkcnt(bs);
+ }
+ } else
+ c->flags |= CHN_F_HAS_SIZE;
+
+ if (c->flags & CHN_F_HAS_SIZE) {
+ /*
+ * The application has requested their own blksz/blkcnt.
+ * Just obey with it, and let them toast alone. We can
+ * clamp it to the nearest latency profile, but that would
+ * defeat the purpose of having custom control. The least
+ * we can do is round it to the nearest ^2 and align it.
+ */
+ sblksz = round_blksz(blksz, sndbuf_getbps(bs));
+ sblkcnt = round_pow2(blkcnt);
+ limit = 0;
+ }
+
+ if (c->parentchannel != NULL) {
+ pb = CHN_BUF_PARENT(c, NULL);
+ CHN_UNLOCK(c);
+ CHN_LOCK(c->parentchannel);
+ chn_notify(c->parentchannel, CHN_N_BLOCKSIZE);
+ CHN_UNLOCK(c->parentchannel);
+ CHN_LOCK(c);
+ limit = (limit != 0 && pb != NULL) ?
+ sndbuf_xbytes(sndbuf_getsize(pb), pb, bs) : 0;
+ c->timeout = c->parentchannel->timeout;
+ } else {
+ hblkcnt = 2;
+ if (c->flags & CHN_F_HAS_SIZE) {
+ hblksz = round_blksz(sndbuf_xbytes(sblksz, bs, b),
+ sndbuf_getbps(b));
+ hblkcnt = round_pow2(sndbuf_getblkcnt(bs));
+ } else
+ chn_calclatency(c->direction, latency,
+ sndbuf_getbps(b),
+ sndbuf_getbps(b) * sndbuf_getspd(b),
+ CHN_2NDBUFMAXSIZE, &hblksz, &hblkcnt);
+
+ if ((hblksz << 1) > sndbuf_getmaxsize(b))
+ hblksz = round_blksz(sndbuf_getmaxsize(b) >> 1,
+ sndbuf_getbps(b));
+
+ while ((hblksz * hblkcnt) > sndbuf_getmaxsize(b)) {
+ if (hblkcnt < 4)
+ hblksz >>= 1;
+ else
+ hblkcnt >>= 1;
+ }
-c->feederflags &= ~(1 << FEEDER_RATE);
-/*
-* Used to be 500. It was too big!
-*/
-if (delta > 25)
-c->feederflags |= 1 << FEEDER_RATE;
-else
-sndbuf_setspd(bs, sndbuf_getspd(b));
-
-r = chn_buildfeeder(c);
-DEB(printf("r = %dn", r));
-if (r)
-goto out;
-
-r = chn_setblocksize(c, 0, 0);
-if (r)
-goto out;
-
-if (!(c->feederflags & (1 << FEEDER_RATE)))
-goto out;
-
-r = EINVAL;
-f = chn_findfeeder(c, FEEDER_RATE);
-DEB(printf("feedrate = %pn", f));
-if (f == NULL)
-goto out;
-
-x = (c->direction == PCMDIR_REC)? b : bs;
-r = FEEDER_SET(f, FEEDRATE_SRC, sndbuf_getspd(x));
-DEB(printf("feeder_set(FEEDRATE_SRC, %d) = %dn", sndbuf_getspd(x), r));
-if (r)
-goto out;
-
-x = (c->direction == PCMDIR_REC)? bs : b;
-r = FEEDER_SET(f, FEEDRATE_DST, sndbuf_getspd(x));
-DEB(printf("feeder_set(FEEDRATE_DST, %d) = %dn", sndbuf_getspd(x), r));
-out:
-if (!r)
-r = CHANNEL_SETFORMAT(c->methods, c->devinfo,
-sndbuf_getfmt(b));
-if (!r)
-sndbuf_setfmt(bs, c->format);
-DEB(printf("setspeed done, r = %dn", r));
-return r;
-} else
-return EINVAL;
+ hblksz -= hblksz % sndbuf_getbps(b);
+
+#if 0
+ hblksz = sndbuf_getmaxsize(b) >> 1;
+ hblksz -= hblksz % sndbuf_getbps(b);
+ hblkcnt = 2;
+#endif
+
+ CHN_UNLOCK(c);
+ if (chn_usefrags == 0 ||
+ CHANNEL_SETFRAGMENTS(c->methods, c->devinfo,
+ hblksz, hblkcnt) < 1)
+ sndbuf_setblksz(b, CHANNEL_SETBLOCKSIZE(c->methods,
+ c->devinfo, hblksz));
+ CHN_LOCK(c);
+
+ if (!CHN_EMPTY(c, children)) {
+ sblksz = round_blksz(
+ sndbuf_xbytes(sndbuf_getsize(b) >> 1, b, bs),
+ sndbuf_getbps(bs));
+ sblkcnt = 2;
+ limit = 0;
+ } else if (limit != 0)
+ limit = sndbuf_xbytes(sndbuf_getsize(b), b, bs);
+
+ /*
+ * Interrupt timeout
+ */
+ c->timeout = ((u_int64_t)hz * sndbuf_getsize(b)) /
+ ((u_int64_t)sndbuf_getspd(b) * sndbuf_getbps(b));
+ if (c->timeout < 1)
+ c->timeout = 1;
+ }
+
+ if (limit > CHN_2NDBUFMAXSIZE)
+ limit = CHN_2NDBUFMAXSIZE;
+
+#if 0
+ while (limit > 0 && (sblksz * sblkcnt) > limit) {
+ if (sblkcnt < 4)
+ break;
+ sblkcnt >>= 1;
+ }
+#endif
+
+ while ((sblksz * sblkcnt) < limit)
+ sblkcnt <<= 1;
+
+ while ((sblksz * sblkcnt) > CHN_2NDBUFMAXSIZE) {
+ if (sblkcnt < 4)
+ sblksz >>= 1;
+ else
+ sblkcnt >>= 1;
+ }
+
+ sblksz -= sblksz % sndbuf_getbps(bs);
+
+ if (sndbuf_getblkcnt(bs) != sblkcnt || sndbuf_getblksz(bs) != sblksz ||
+ sndbuf_getsize(bs) != (sblkcnt * sblksz)) {
+ ret = sndbuf_remalloc(bs, sblkcnt, sblksz);
+ if (ret != 0) {
+ printf("%s: Failed: %d %d\n", __func__,
+ sblkcnt, sblksz);
+ return ret;
+ }
+ }
+
+ /*
+ * OSSv4 docs: "By default OSS will set the low water level equal
+ * to the fragment size which is optimal in most cases."
+ */
+ c->lw = sndbuf_getblksz(bs);
+ chn_resetbuf(c);
+
+ if (snd_verbose > 3)
+ printf("%s: %s (%s) timeout=%u "
+ "b[%d/%d/%d] bs[%d/%d/%d] limit=%d\n",
+ __func__, CHN_DIRSTR(c),
+ (c->flags & CHN_F_VIRTUAL) ? "virtual" : "hardware",
+ c->timeout,
+ sndbuf_getsize(b), sndbuf_getblksz(b),
+ sndbuf_getblkcnt(b),
+ sndbuf_getsize(bs), sndbuf_getblksz(bs),
+ sndbuf_getblkcnt(bs), limit);
+
+ return 0;
}
int
-chn_setspeed(struct pcm_channel *c, int speed)
+chn_setlatency(struct pcm_channel *c, int latency)
{
-int r, oldspeed = c->speed;
-
-r = chn_tryspeed(c, speed);
-if (r) {
-DEB(printf("Failed to set speed %d falling back to %dn", speed, oldspeed));
-r = chn_tryspeed(c, oldspeed);
+ CHN_LOCKASSERT(c);
+ /* Destroy blksz/blkcnt, enforce latency profile. */
+ return chn_resizebuf(c, latency, -1, 0);
}
-return r;
+
+int
+chn_setblocksize(struct pcm_channel *c, int blkcnt, int blksz)
+{
+ CHN_LOCKASSERT(c);
+ /* Destroy latency profile, enforce blksz/blkcnt */
+ return chn_resizebuf(c, -1, blkcnt, blksz);
}
static int
-chn_tryformat(struct pcm_channel *c, u_int32_t fmt)
+chn_tryspeed(struct pcm_channel *c, int speed)
{
-struct snd_dbuf *b = c->bufhard;
-struct snd_dbuf *bs = c->bufsoft;
-int r;
-
-CHN_LOCKASSERT(c);
-if (CANCHANGE(c)) {
-DEB(printf("want format %dn", fmt));
-c->format = fmt;
-r = chn_buildfeeder(c);
-if (r == 0) {
-sndbuf_setfmt(bs, c->format);
-chn_resetbuf(c);
-r = CHANNEL_SETFORMAT(c->methods, c->devinfo, sndbuf_getfmt(b));
-if (r == 0)
-r = chn_tryspeed(c, c->speed);
-}
-return r;
-} else
-return EINVAL;
+ struct pcm_feeder *f;
+ struct snd_dbuf *b = c->bufhard;
+ struct snd_dbuf *bs = c->bufsoft;
+ struct snd_dbuf *x;
+ int r, delta;
+
+ CHN_LOCKASSERT(c);
+ DEB(printf("setspeed, channel %s\n", c->name));
+ DEB(printf("want speed %d, ", speed));
+ if (speed <= 0)
+ return EINVAL;
+ if (CHN_STOPPED(c)) {
+ r = 0;
+ c->speed = speed;
+ sndbuf_setspd(bs, speed);
+ RANGE(speed, chn_getcaps(c)->minspeed, chn_getcaps(c)->maxspeed);
+ DEB(printf("try speed %d, ", speed));
+ sndbuf_setspd(b, CHANNEL_SETSPEED(c->methods, c->devinfo, speed));
+ DEB(printf("got speed %d\n", sndbuf_getspd(b)));
+
+ delta = sndbuf_getspd(b) - sndbuf_getspd(bs);
+ if (delta < 0)
+ delta = -delta;
+
+ c->feederflags &= ~(1 << FEEDER_RATE);
+ /*
+ * Used to be 500. It was too big!
+ */
+ if (delta > feeder_rate_round)
+ c->feederflags |= 1 << FEEDER_RATE;
+ else
+ sndbuf_setspd(bs, sndbuf_getspd(b));
+
+ r = chn_buildfeeder(c);
+ DEB(printf("r = %d\n", r));
+ if (r)
+ goto out;
+
+ if (!(c->feederflags & (1 << FEEDER_RATE)))
+ goto out;
+
+ r = EINVAL;
+ f = chn_findfeeder(c, FEEDER_RATE);
+ DEB(printf("feedrate = %p\n", f));
+ if (f == NULL)
+ goto out;
+
+ x = (c->direction == PCMDIR_REC)? b : bs;
+ r = FEEDER_SET(f, FEEDRATE_SRC, sndbuf_getspd(x));
+ DEB(printf("feeder_set(FEEDRATE_SRC, %d) = %d\n", sndbuf_getspd(x), r));
+ if (r)
+ goto out;
+
+ x = (c->direction == PCMDIR_REC)? bs : b;
+ r = FEEDER_SET(f, FEEDRATE_DST, sndbuf_getspd(x));
+ DEB(printf("feeder_set(FEEDRATE_DST, %d) = %d\n", sndbuf_getspd(x), r));
+out:
+ if (!r)
+ r = CHANNEL_SETFORMAT(c->methods, c->devinfo,
+ sndbuf_getfmt(b));
+ if (!r)
+ sndbuf_setfmt(bs, c->format);
+ if (!r)
+ r = chn_resizebuf(c, -2, 0, 0);
+ DEB(printf("setspeed done, r = %d\n", r));
+ return r;
+ } else
+ return EINVAL;
}
int
-chn_setformat(struct pcm_channel *c, u_int32_t fmt)
+chn_setspeed(struct pcm_channel *c, int speed)
{
-u_int32_t oldfmt = c->format;
-int r;
+ int r, oldspeed = c->speed;
-r = chn_tryformat(c, fmt);
-if (r) {
-DEB(printf("Format change %d failed, reverting to %dn", fmt, oldfmt));
-chn_tryformat(c, oldfmt);
-}
-return r;
+ r = chn_tryspeed(c, speed);
+ if (r) {
+ if (snd_verbose > 3)
+ printf("Failed to set speed %d falling back to %d\n",
+ speed, oldspeed);
+ r = chn_tryspeed(c, oldspeed);
+ }
+ return r;
}
-/*
-* given a bufsz value, round it to a power of 2 in the min-max range
-* XXX only works if min and max are powers of 2
-*/
static int
-round_bufsz(int bufsz, int min, int max)
+chn_tryformat(struct pcm_channel *c, u_int32_t fmt)
{
-int tmp = min * 2;
-
-KASSERT((min & (min-1)) == 0, ("min %d must be power of 2n", min));
-KASSERT((max & (max-1)) == 0, ("max %d must be power of 2n", max));
-while (tmp <= bufsz)
-tmp <<= 1;
-tmp >>= 1;
-if (tmp > max)
-tmp = max;
-return tmp;
+ struct snd_dbuf *b = c->bufhard;
+ struct snd_dbuf *bs = c->bufsoft;
+ int r;
+
+ CHN_LOCKASSERT(c);
+ if (CHN_STOPPED(c)) {
+ DEB(printf("want format %d\n", fmt));
+ c->format = fmt;
+ r = chn_buildfeeder(c);
+ if (r == 0) {
+ sndbuf_setfmt(bs, c->format);
+ chn_resetbuf(c);
+ r = CHANNEL_SETFORMAT(c->methods, c->devinfo, sndbuf_getfmt(b));
+ if (r == 0)
+ r = chn_tryspeed(c, c->speed);
+ }
+ return r;
+ } else
+ return EINVAL;
}
-/*
-* set the channel's blocksize both for soft and hard buffers.
-*
-* blksz should be a power of 2 between 2**4 and 2**16 -- it is useful
-* that it has the same value for both bufsoft and bufhard.
-* blksz == -1 computes values according to a target irq rate.
-* blksz == 0 reuses previous values if available, otherwise
-* behaves as for -1
-*
-* blkcnt is set by the user, between 2 and (2**17)/blksz for bufsoft,
-* but should be a power of 2 for bufhard to simplify life to low
-* level drivers.
-* Note, for the rec channel a large blkcnt is ok,
-* but for the play channel we want blksz as small as possible to keep
-* the delay small, because routines in the write path always try to
-* keep bufhard full.
-*
-* Unless we have good reason to, use the values suggested by the caller.
-*/
int
-chn_setblocksize(struct pcm_channel *c, int blkcnt, int blksz)
+chn_setformat(struct pcm_channel *c, u_int32_t fmt)
{
-struct snd_dbuf *b = c->bufhard;
-struct snd_dbuf *bs = c->bufsoft;
-int irqhz, ret, maxsz, maxsize, reqblksz;
-
-CHN_LOCKASSERT(c);
-if (!CANCHANGE(c) || (c->flags & CHN_F_MAPPED)) {
-KASSERT(sndbuf_getsize(bs) == 0 ||
-sndbuf_getsize(bs) >= sndbuf_getsize(b),
-("%s(%s): bufsoft size %d < bufhard size %d", __func__,
-c->name, sndbuf_getsize(bs), sndbuf_getsize(b)));
-return EINVAL;
-}
-c->flags |= CHN_F_SETBLOCKSIZE;
-
-ret = 0;
-DEB(printf("%s(%d, %d)n", __func__, blkcnt, blksz));
-if (blksz == 0 || blksz == -1) { /* let the driver choose values */
-if (blksz == -1) /* delete previous values */
-c->flags &= ~CHN_F_HAS_SIZE;
-if (!(c->flags & CHN_F_HAS_SIZE)) { /* no previous value */
-/*
-* compute a base blksz according to the target irq
-* rate, then round to a suitable power of 2
-* in the range 16.. 2^17/2.
-* Finally compute a suitable blkcnt.
-*/
-blksz = round_bufsz( (sndbuf_getbps(bs) *
-sndbuf_getspd(bs)) / chn_targetirqrate,
-16, CHN_2NDBUFMAXSIZE / 2);
-blkcnt = CHN_2NDBUFMAXSIZE / blksz;
-} else { /* use previously defined value */
-blkcnt = sndbuf_getblkcnt(bs);
-blksz = sndbuf_getblksz(bs);
-}
-} else {
-/*
-* use supplied values if reasonable. Note that here we
-* might have blksz which is not a power of 2 if the
-* ioctl() to compute it allows such values.
-*/
-ret = EINVAL;
-if ((blksz < 16) || (blkcnt < 2) || (blkcnt * blksz > CHN_2NDBUFMAXSIZE))
-goto out;
-ret = 0;
-c->flags |= CHN_F_HAS_SIZE;
-}
-
-reqblksz = blksz;
-if (reqblksz < sndbuf_getbps(bs))
-reqblksz = sndbuf_getbps(bs);
-if (reqblksz % sndbuf_getbps(bs))
-reqblksz -= reqblksz % sndbuf_getbps(bs);
+ u_int32_t oldfmt = c->format;
+ int r;
-/* adjust for different hw format/speed */
-/*
-* Now compute the approx irq rate for the given (soft) blksz,
-* reduce to the acceptable range and compute a corresponding blksz
-* for the hard buffer. Then set the channel's blocksize and
-* corresponding hardbuf value. The number of blocks used should
-* be set by the device-specific routine. In fact, even the
-* call to sndbuf_setblksz() should not be here! XXX
-*/
-
-irqhz = (sndbuf_getbps(bs) * sndbuf_getspd(bs)) / blksz;
-RANGE(irqhz, 16, 512);
-
-maxsz = sndbuf_getmaxsize(b);
-if (maxsz == 0) /* virtual channels don't appear to allocate bufhard */
-maxsz = CHN_2NDBUFMAXSIZE;
-blksz = round_bufsz( (sndbuf_getbps(b) * sndbuf_getspd(b)) / irqhz,
-16, maxsz / 2);
-
-/* Increase the size of bufsoft if before increasing bufhard. */
-maxsize = sndbuf_getsize(b);
-if (sndbuf_getsize(bs) > maxsize)
-maxsize = sndbuf_getsize(bs);
-if (reqblksz * blkcnt > maxsize)
-maxsize = reqblksz * blkcnt;
-if (sndbuf_getsize(bs) != maxsize || sndbuf_getblksz(bs) != reqblksz) {
-ret = sndbuf_remalloc(bs, maxsize/reqblksz, reqblksz);
-if (ret)
-goto out1;
-}
-
-CHN_UNLOCK(c);
-sndbuf_setblksz(b, CHANNEL_SETBLOCKSIZE(c->methods, c->devinfo, blksz));
-CHN_LOCK(c);
-
-/* Decrease the size of bufsoft after decreasing bufhard. */
-maxsize = sndbuf_getsize(b);
-if (reqblksz * blkcnt > maxsize)
-maxsize = reqblksz * blkcnt;
-if (maxsize > sndbuf_getsize(bs))
-printf("Danger! %s bufsoft size increasing from %d to %d after CHANNEL_SETBLOCKSIZE()n",
-c->name, sndbuf_getsize(bs), maxsize);
-if (sndbuf_getsize(bs) != maxsize || sndbuf_getblksz(bs) != reqblksz) {
-ret = sndbuf_remalloc(bs, maxsize/reqblksz, reqblksz);
-if (ret)
-goto out1;
-}
-
-chn_resetbuf(c);
-out1:
-KASSERT(sndbuf_getsize(bs) == 0 ||
-sndbuf_getsize(bs) >= sndbuf_getsize(b),
-("%s(%s): bufsoft size %d < bufhard size %d, reqblksz=%d blksz=%d maxsize=%d blkcnt=%d",
-__func__, c->name, sndbuf_getsize(bs), sndbuf_getsize(b), reqblksz,
-blksz, maxsize, blkcnt));
-out:
-c->flags &= ~CHN_F_SETBLOCKSIZE;
-#if 0
-if (1) {
-static uint32_t kk = 0;
-printf("%u: b %d/%d/%d : (%d)%d/0x%0x | bs %d/%d/%d : (%d)%d/0x%0xn", ++kk,
-sndbuf_getsize(b), sndbuf_getblksz(b), sndbuf_getblkcnt(b),
-sndbuf_getbps(b),
-sndbuf_getspd(b), sndbuf_getfmt(b),
-sndbuf_getsize(bs), sndbuf_getblksz(bs), sndbuf_getblkcnt(bs),
-sndbuf_getbps(bs),
-sndbuf_getspd(bs), sndbuf_getfmt(bs));
-if (sndbuf_getsize(b) % sndbuf_getbps(b) ||
-sndbuf_getblksz(b) % sndbuf_getbps(b) ||
-sndbuf_getsize(bs) % sndbuf_getbps(bs) ||
-sndbuf_getblksz(b) % sndbuf_getbps(b)) {
-printf("%u: bps/blksz alignment screwed!n", kk);
-}
-}
-#endif
-return ret;
+ r = chn_tryformat(c, fmt);
+ if (r) {
+ if (snd_verbose > 3)
+ printf("Format change 0x%08x failed, reverting to 0x%08x\n",
+ fmt, oldfmt);
+ chn_tryformat(c, oldfmt);
+ }
+ return r;
}
int
chn_trigger(struct pcm_channel *c, int go)
{
#ifdef DEV_ISA
-struct snd_dbuf *b = c->bufhard;
+ struct snd_dbuf *b = c->bufhard;
#endif
-int ret;
+ struct snddev_info *d = c->parentsnddev;
+ int ret;
-CHN_LOCKASSERT(c);
+ CHN_LOCKASSERT(c);
#ifdef DEV_ISA
-if (SND_DMA(b) && (go == PCMTRIG_EMLDMAWR || go == PCMTRIG_EMLDMARD))
-sndbuf_dmabounce(b);
+ if (SND_DMA(b) && (go == PCMTRIG_EMLDMAWR || go == PCMTRIG_EMLDMARD))
+ sndbuf_dmabounce(b);
#endif
-ret = CHANNEL_TRIGGER(c->methods, c->devinfo, go);
+ if (!PCMTRIG_COMMON(go))
+ return (CHANNEL_TRIGGER(c->methods, c->devinfo, go));
-return ret;
-}
+ if (go == c->trigger)
+ return (0);
+ ret = CHANNEL_TRIGGER(c->methods, c->devinfo, go);
+ if (ret != 0)
+ return (ret);
+
+ switch (go) {
+ case PCMTRIG_START:
+ if (snd_verbose > 3)
+ device_printf(c->dev,
+ "%s() %s: calling go=0x%08x , "
+ "prev=0x%08x\n", __func__, c->name, go,
+ c->trigger);
+ if (c->trigger != PCMTRIG_START) {
+ c->trigger = go;
+ CHN_UNLOCK(c);
+ pcm_lock(d);
+ CHN_INSERT_HEAD(d, c, channels.pcm.busy);
+ pcm_unlock(d);
+ CHN_LOCK(c);
+ }
+ break;
+ case PCMTRIG_STOP:
+ case PCMTRIG_ABORT:
+ if (snd_verbose > 3)
+ device_printf(c->dev,
+ "%s() %s: calling go=0x%08x , "
+ "prev=0x%08x\n", __func__, c->name, go,
+ c->trigger);
+ if (c->trigger == PCMTRIG_START) {
+ c->trigger = go;
+ CHN_UNLOCK(c);
+ pcm_lock(d);
+ CHN_REMOVE(d, c, channels.pcm.busy);
+ pcm_unlock(d);
+ CHN_LOCK(c);
+ }
+ break;
+ default:
+ break;
+ }
+
+ return (0);
+}
+
+/**
+ * @brief Queries sound driver for sample-aligned hardware buffer pointer index
+ *
+ * This function obtains the hardware pointer location, then aligns it to
+ * the current bytes-per-sample value before returning. (E.g., a channel
+ * running in 16 bit stereo mode would require 4 bytes per sample, so a
+ * hwptr value ranging from 32-35 would be returned as 32.)
+ *
+ * @param c PCM channel context
+ * @returns sample-aligned hardware buffer pointer index
+ */
int
chn_getptr(struct pcm_channel *c)
{
-#if 0
-int hwptr;
-int a = (1 << c->align) - 1;
+ int hwptr;
-CHN_LOCKASSERT(c);
-hwptr = (c->flags & CHN_F_TRIGGERED)? CHANNEL_GETPTR(c->methods, c->devinfo) : 0;
-/* don't allow unaligned values in the hwa ptr */
-#if 1
-hwptr &= ~a ; /* Apply channel align mask */
-#endif
-hwptr &= DMA_ALIGN_MASK; /* Apply DMA align mask */
-return hwptr;
-#endif
-int hwptr;
-
-CHN_LOCKASSERT(c);
-hwptr = (c->flags & CHN_F_TRIGGERED)? CHANNEL_GETPTR(c->methods, c->devinfo) : 0;
-return (hwptr - (hwptr % sndbuf_getbps(c->bufhard)));
+ CHN_LOCKASSERT(c);
+ hwptr = (CHN_STARTED(c)) ? CHANNEL_GETPTR(c->methods, c->devinfo) : 0;
+ return (hwptr - (hwptr % sndbuf_getbps(c->bufhard)));
}
struct pcmchan_caps *
chn_getcaps(struct pcm_channel *c)
{
-CHN_LOCKASSERT(c);
-return CHANNEL_GETCAPS(c->methods, c->devinfo);
+ CHN_LOCKASSERT(c);
+ return CHANNEL_GETCAPS(c->methods, c->devinfo);
}
u_int32_t
chn_getformats(struct pcm_channel *c)
{
-u_int32_t *fmtlist, fmts;
-int i;
+ u_int32_t *fmtlist, fmts;
+ int i;
-fmtlist = chn_getcaps(c)->fmtlist;
-fmts = 0;
-for (i = 0; fmtlist[i]; i++)
-fmts |= fmtlist[i];
-
-/* report software-supported formats */
-if (report_soft_formats)
-fmts |= AFMT_MU_LAW|AFMT_A_LAW|AFMT_U32_LE|AFMT_U32_BE|
-AFMT_S32_LE|AFMT_S32_BE|AFMT_U24_LE|AFMT_U24_BE|
-AFMT_S24_LE|AFMT_S24_BE|AFMT_U16_LE|AFMT_U16_BE|
-AFMT_S16_LE|AFMT_S16_BE|AFMT_U8|AFMT_S8;
+ fmtlist = chn_getcaps(c)->fmtlist;
+ fmts = 0;
+ for (i = 0; fmtlist[i]; i++)
+ fmts |= fmtlist[i];
+
+ /* report software-supported formats */
+ if (report_soft_formats)
+ fmts |= AFMT_MU_LAW|AFMT_A_LAW|AFMT_U32_LE|AFMT_U32_BE|
+ AFMT_S32_LE|AFMT_S32_BE|AFMT_U24_LE|AFMT_U24_BE|
+ AFMT_S24_LE|AFMT_S24_BE|AFMT_U16_LE|AFMT_U16_BE|
+ AFMT_S16_LE|AFMT_S16_BE|AFMT_U8|AFMT_S8;
-return fmts;
+ return fmts;
}
static int
chn_buildfeeder(struct pcm_channel *c)
{
-struct feeder_class *fc;
-struct pcm_feederdesc desc;
-u_int32_t tmp[2], type, flags, hwfmt, *fmtlist;
-int err;
-
-CHN_LOCKASSERT(c);
-while (chn_removefeeder(c) == 0);
-KASSERT((c->feeder == NULL), ("feeder chain not empty"));
-
-c->align = sndbuf_getalign(c->bufsoft);
+ struct feeder_class *fc;
+ struct pcm_feederdesc desc;
+ struct snd_mixer *m;
+ u_int32_t tmp[2], type, flags, hwfmt, *fmtlist;
+ int err;
+ char fmtstr[AFMTSTR_MAXSZ];
+
+ CHN_LOCKASSERT(c);
+ while (chn_removefeeder(c) == 0)
+ ;
+ KASSERT((c->feeder == NULL), ("feeder chain not empty"));
+
+ c->align = sndbuf_getalign(c->bufsoft);
+
+ if (CHN_EMPTY(c, children) || c->direction == PCMDIR_REC) {
+ /*
+ * Virtual rec need this.
+ */
+ fc = feeder_getclass(NULL);
+ KASSERT(fc != NULL, ("can't find root feeder"));
+
+ err = chn_addfeeder(c, fc, NULL);
+ if (err) {
+ DEB(printf("can't add root feeder, err %d\n", err));
+
+ return err;
+ }
+ c->feeder->desc->out = c->format;
+ } else if (c->direction == PCMDIR_PLAY) {
+ if (c->flags & CHN_F_HAS_VCHAN) {
+ desc.type = FEEDER_MIXER;
+ desc.in = c->format;
+ } else {
+ DEB(printf("can't decide which feeder type to use!\n"));
+ return EOPNOTSUPP;
+ }
+ desc.out = c->format;
+ desc.flags = 0;
+ fc = feeder_getclass(&desc);
+ if (fc == NULL) {
+ DEB(printf("can't find vchan feeder\n"));
+
+ return EOPNOTSUPP;
+ }
+
+ err = chn_addfeeder(c, fc, &desc);
+ if (err) {
+ DEB(printf("can't add vchan feeder, err %d\n", err));
+
+ return err;
+ }
+ } else
+ return EOPNOTSUPP;
+
+ /* XXX These are too much.. */
+ if (c->parentsnddev != NULL && c->parentsnddev->mixer_dev != NULL &&
+ c->parentsnddev->mixer_dev->si_drv1 != NULL)
+ m = c->parentsnddev->mixer_dev->si_drv1;
+ else
+ m = NULL;
+
+ c->feederflags &= ~(1 << FEEDER_VOLUME);
+ if (c->direction == PCMDIR_PLAY && !(c->flags & CHN_F_VIRTUAL) && m &&
+ (c->parentsnddev->flags & SD_F_SOFTPCMVOL))
+ c->feederflags |= 1 << FEEDER_VOLUME;
+
+ if (!(c->flags & CHN_F_VIRTUAL) && c->parentsnddev &&
+ ((c->direction == PCMDIR_PLAY &&
+ (c->parentsnddev->flags & SD_F_PSWAPLR)) ||
+ (c->direction == PCMDIR_REC &&
+ (c->parentsnddev->flags & SD_F_RSWAPLR))))
+ c->feederflags |= 1 << FEEDER_SWAPLR;
+
+ flags = c->feederflags;
+ fmtlist = chn_getcaps(c)->fmtlist;
+
+ DEB(printf("feederflags %x\n", flags));
+
+ for (type = FEEDER_RATE; type < FEEDER_LAST; type++) {
+ if (flags & (1 << type)) {
+ desc.type = type;
+ desc.in = 0;
+ desc.out = 0;
+ desc.flags = 0;
+ DEB(printf("find feeder type %d, ", type));
+ if (type == FEEDER_VOLUME || type == FEEDER_RATE) {
+ if (c->feeder->desc->out & AFMT_32BIT)
+ strlcpy(fmtstr,"s32le", sizeof(fmtstr));
+ else if (c->feeder->desc->out & AFMT_24BIT)
+ strlcpy(fmtstr, "s24le", sizeof(fmtstr));
+ else {
+ /*
+ * 8bit doesn't provide enough headroom
+ * for proper processing without
+ * creating too much noises. Force to
+ * 16bit instead.
+ */
+ strlcpy(fmtstr, "s16le", sizeof(fmtstr));
+ }
+ if (!(c->feeder->desc->out & AFMT_8BIT) &&
+ c->feeder->desc->out & AFMT_BIGENDIAN)
+ afmtstr_swap_endian(fmtstr);
+ if (!(c->feeder->desc->out & (AFMT_A_LAW | AFMT_MU_LAW)) &&
+ !(c->feeder->desc->out & AFMT_SIGNED))
+ afmtstr_swap_sign(fmtstr);
+ desc.in = afmtstr2afmt(NULL, fmtstr, AFMTSTR_MONO_RETURN);
+ if (desc.in == 0)
+ desc.in = AFMT_S16_LE;
+ /* feeder_volume need stereo processing */
+ if (type == FEEDER_VOLUME ||
+ c->feeder->desc->out & AFMT_STEREO)
+ desc.in |= AFMT_STEREO;
+ desc.out = desc.in;
+ } else if (type == FEEDER_SWAPLR) {
+ desc.in = c->feeder->desc->out;
+ desc.in |= AFMT_STEREO;
+ desc.out = desc.in;
+ }
+
+ fc = feeder_getclass(&desc);
+ DEB(printf("got %p\n", fc));
+ if (fc == NULL) {
+ DEB(printf("can't find required feeder type %d\n", type));
+
+ return EOPNOTSUPP;
+ }
+
+ if (desc.in == 0 || desc.out == 0)
+ desc = *fc->desc;
+
+ DEB(printf("build fmtchain from 0x%08x to 0x%08x: ", c->feeder->desc->out, fc->desc->in));
+ tmp[0] = desc.in;
+ tmp[1] = 0;
+ if (chn_fmtchain(c, tmp) == 0) {
+ DEB(printf("failed\n"));
+
+ return ENODEV;
+ }
+ DEB(printf("ok\n"));
+
+ err = chn_addfeeder(c, fc, &desc);
+ if (err) {
+ DEB(printf("can't add feeder %p, output 0x%x, err %d\n", fc, fc->desc->out, err));
+
+ return err;
+ }
+ DEB(printf("added feeder %p, output 0x%x\n", fc, c->feeder->desc->out));
+ }
+ }
+
+ if (c->direction == PCMDIR_REC) {
+ tmp[0] = c->format;
+ tmp[1] = 0;
+ hwfmt = chn_fmtchain(c, tmp);
+ } else
+ hwfmt = chn_fmtchain(c, fmtlist);
+
+ if (hwfmt == 0 || !fmtvalid(hwfmt, fmtlist)) {
+ DEB(printf("Invalid hardware format: 0x%08x\n", hwfmt));
+ return ENODEV;
+ } else if (c->direction == PCMDIR_REC && !CHN_EMPTY(c, children)) {
+ /*
+ * Kind of awkward. This whole "MIXER" concept need a
+ * rethinking, I guess :) . Recording is the inverse
+ * of Playback, which is why we push mixer vchan down here.
+ */
+ if (c->flags & CHN_F_HAS_VCHAN) {
+ desc.type = FEEDER_MIXER;
+ desc.in = c->format;
+ } else
+ return EOPNOTSUPP;
+ desc.out = c->format;
+ desc.flags = 0;
+ fc = feeder_getclass(&desc);
+ if (fc == NULL)
+ return EOPNOTSUPP;
+
+ err = chn_addfeeder(c, fc, &desc);
+ if (err != 0)
+ return err;
+ }
+
+ sndbuf_setfmt(c->bufhard, hwfmt);
+
+ if ((flags & (1 << FEEDER_VOLUME))) {
+ u_int32_t parent;
+ int vol, left, right;
+
+ CHN_UNLOCK(c);
+ vol = mix_get(m, SOUND_MIXER_PCM);
+ if (vol == -1) {
+ device_printf(c->dev,
+ "Soft PCM Volume: Failed to read default value\n");
+ vol = 100 | (100 << 8);
+ }
+ left = vol & 0x7f;
+ right = (vol >> 8) & 0x7f;
+ parent = mix_getparent(m, SOUND_MIXER_PCM);
+ if (parent != SOUND_MIXER_NONE) {
+ vol = mix_get(m, parent);
+ if (vol == -1) {
+ device_printf(c->dev,
+ "Soft Volume: Failed to read parent "
+ "default value\n");
+ vol = 100 | (100 << 8);
+ }
+ left = (left * (vol & 0x7f)) / 100;
+ right = (right * ((vol >> 8) & 0x7f)) / 100;
+ }
+ CHN_LOCK(c);
+ chn_setvolume(c, left, right);
+ }
-if (SLIST_EMPTY(&c->children)) {
-fc = feeder_getclass(NULL);
-KASSERT(fc != NULL, ("can't find root feeder"));
-
-err = chn_addfeeder(c, fc, NULL);
-if (err) {
-DEB(printf("can't add root feeder, err %dn", err));
-
-return err;
-}
-c->feeder->desc->out = c->format;
-} else {
-if (c->flags & CHN_F_HAS_VCHAN) {
-desc.type = FEEDER_MIXER;
-desc.in = 0;
-} else {
-DEB(printf("can't decide which feeder type to use!n"));
-return EOPNOTSUPP;
+ return 0;
}
-desc.out = c->format;
-desc.flags = 0;
-fc = feeder_getclass(&desc);
-if (fc == NULL) {
-DEB(printf("can't find vchan feedern"));
-return EOPNOTSUPP;
-}
-
-err = chn_addfeeder(c, fc, &desc);
-if (err) {
-DEB(printf("can't add vchan feeder, err %dn", err));
-
-return err;
-}
-}
-c->feederflags &= ~(1 << FEEDER_VOLUME);
-if (c->direction == PCMDIR_PLAY &&
-!(c->flags & CHN_F_VIRTUAL) &&
-c->parentsnddev && (c->parentsnddev->flags & SD_F_SOFTPCMVOL) &&
-c->parentsnddev->mixer_dev)
-c->feederflags |= 1 << FEEDER_VOLUME;
-flags = c->feederflags;
-fmtlist = chn_getcaps(c)->fmtlist;
-
-DEB(printf("feederflags %xn", flags));
-
-for (type = FEEDER_RATE; type <= FEEDER_LAST; type++) {
-if (flags & (1 << type)) {
-desc.type = type;
-desc.in = 0;
-desc.out = 0;
-desc.flags = 0;
-DEB(printf("find feeder type %d, ", type));
-fc = feeder_getclass(&desc);
-DEB(printf("got %pn", fc));
-if (fc == NULL) {
-DEB(printf("can't find required feeder type %dn", type));
-
-return EOPNOTSUPP;
-}
+int
+chn_notify(struct pcm_channel *c, u_int32_t flags)
+{
+ int err, run, nrun;
-DEB(printf("build fmtchain from 0x%08x to 0x%08x: ", c->feeder->desc->out, fc->desc->in));
-tmp[0] = fc->desc->in;
-tmp[1] = 0;
-if (chn_fmtchain(c, tmp) == 0) {
-DEB(printf("failedn"));
+ CHN_LOCKASSERT(c);
-return ENODEV;
-}
-DEB(printf("okn"));
+ if (CHN_EMPTY(c, children))
+ return (ENODEV);
-err = chn_addfeeder(c, fc, fc->desc);
-if (err) {
-DEB(printf("can't add feeder %p, output 0x%x, err %dn", fc, fc->desc->out, err));
+ err = 0;
-return err;
-}
-DEB(printf("added feeder %p, output 0x%xn", fc, c->feeder->desc->out));
-}
-}
+ /*
+ * If the hwchan is running, we can't change its rate, format or
+ * blocksize
+ */
+ run = (CHN_STARTED(c)) ? 1 : 0;
+ if (run)
+ flags &= CHN_N_VOLUME | CHN_N_TRIGGER;
+
+ if (flags & CHN_N_RATE) {
+ /* XXX I'll make good use of this someday. */
+ }
+ if (flags & CHN_N_FORMAT) {
+ /* XXX I'll make good use of this someday. */
+ }
+ if (flags & CHN_N_VOLUME) {
+ /* XXX I'll make good use of this someday. */
+ }
+ if (flags & CHN_N_BLOCKSIZE) {
+ /*
+ * Set to default latency profile
+ */
+ chn_setlatency(c, chn_latency);
+ }
+ if (flags & CHN_N_TRIGGER) {
+ nrun = CHN_EMPTY(c, children.busy) ? 0 : 1;
+ if (nrun && !run)
+ err = chn_start(c, 1);
+ if (!nrun && run)
+ chn_abort(c);
+ }
+
+ return (err);
+}
+
+/**
+ * @brief Fetch array of supported discrete sample rates
+ *
+ * Wrapper for CHANNEL_GETRATES. Please see channel_if.m:getrates() for
+ * detailed information.
+ *
+ * @note If the operation isn't supported, this function will just return 0
+ * (no rates in the array), and *rates will be set to NULL. Callers
+ * should examine rates @b only if this function returns non-zero.
+ *
+ * @param c pcm channel to examine
+ * @param rates pointer to array of integers; rate table will be recorded here
+ *
+ * @return number of rates in the array pointed to be @c rates
+ */
+int
+chn_getrates(struct pcm_channel *c, int **rates)
+{
+ KASSERT(rates != NULL, ("rates is null"));
+ CHN_LOCKASSERT(c);
+ return CHANNEL_GETRATES(c->methods, c->devinfo, rates);
+}
+
+/**
+ * @brief Remove channel from a sync group, if there is one.
+ *
+ * This function is initially intended for the following conditions:
+ * - Starting a syncgroup (@c SNDCTL_DSP_SYNCSTART ioctl)
+ * - Closing a device. (A channel can't be destroyed if it's still in use.)
+ *
+ * @note Before calling this function, the syncgroup list mutex must be
+ * held. (Consider pcm_channel::sm protected by the SG list mutex
+ * whether @c c is locked or not.)
+ *
+ * @param c channel device to be started or closed
+ * @returns If this channel was the only member of a group, the group ID
+ * is returned to the caller so that the caller can release it
+ * via free_unr() after giving up the syncgroup lock. Else it
+ * returns 0.
+ */
+int
+chn_syncdestroy(struct pcm_channel *c)
+{
+ struct pcmchan_syncmember *sm;
+ struct pcmchan_syncgroup *sg;
+ int sg_id;
-if (c->direction == PCMDIR_REC) {
-tmp[0] = c->format;
-tmp[1] = 0;
-hwfmt = chn_fmtchain(c, tmp);
-} else
-hwfmt = chn_fmtchain(c, fmtlist);
+ sg_id = 0;
-if (hwfmt == 0 || !fmtvalid(hwfmt, fmtlist)) {
-DEB(printf("Invalid hardware format: 0x%08xn", hwfmt));
-return ENODEV;
-}
+ PCM_SG_LOCKASSERT(MA_OWNED);
-sndbuf_setfmt(c->bufhard, hwfmt);
+ if (c->sm != NULL) {
+ sm = c->sm;
+ sg = sm->parent;
+ c->sm = NULL;
-if ((flags & (1 << FEEDER_VOLUME))) {
-uint32_t parent = SOUND_MIXER_NONE;
-int vol, left, right;
+ KASSERT(sg != NULL, ("syncmember has null parent"));
-vol = 100 | (100 << 8);
+ SLIST_REMOVE(&sg->members, sm, pcmchan_syncmember, link);
+ free(sm, M_DEVBUF);
-CHN_UNLOCK(c);
-/*
-* XXX This is ugly! The way mixer subs being so secretive
-* about its own internals force us to use this silly
-* monkey trick.
-*/
-if (mixer_ioctl(c->parentsnddev->mixer_dev,
-MIXER_READ(SOUND_MIXER_PCM), (caddr_t)&vol, -1, NULL) != 0)
-device_printf(c->dev, "Soft PCM Volume: Failed to read default valuen");
-left = vol & 0x7f;
-right = (vol >> 8) & 0x7f;
-if (c->parentsnddev != NULL &&
-c->parentsnddev->mixer_dev != NULL &&
-c->parentsnddev->mixer_dev->si_drv1 != NULL)
-parent = mix_getparent(
-c->parentsnddev->mixer_dev->si_drv1,
-SOUND_MIXER_PCM);
-if (parent != SOUND_MIXER_NONE) {
-vol = 100 | (100 << 8);
-if (mixer_ioctl(c->parentsnddev->mixer_dev,
-MIXER_READ(parent),
-(caddr_t)&vol, -1, NULL) != 0)
-device_printf(c->dev, "Soft Volume: Failed to read parent default valuen");
-left = (left * (vol & 0x7f)) / 100;
-right = (right * ((vol >> 8) & 0x7f)) / 100;
-}
-CHN_LOCK(c);
-chn_setvolume(c, left, right);
-}
+ if (SLIST_EMPTY(&sg->members)) {
+ SLIST_REMOVE(&snd_pcm_syncgroups, sg, pcmchan_syncgroup, link);
+ sg_id = sg->id;
+ free(sg, M_DEVBUF);
+ }
+ }
-return 0;
-}
-
-int
-chn_notify(struct pcm_channel *c, u_int32_t flags)
-{
-struct pcmchan_children *pce;
-struct pcm_channel *child;
-int run;
-
-CHN_LOCK(c);
-
-if (SLIST_EMPTY(&c->children)) {
-CHN_UNLOCK(c);
-return ENODEV;
-}
-
-run = (c->flags & CHN_F_TRIGGERED)? 1 : 0;
-/*
-* if the hwchan is running, we can't change its rate, format or
-* blocksize
-*/
-if (run)
-flags &= CHN_N_VOLUME | CHN_N_TRIGGER;
-
-if (flags & CHN_N_RATE) {
-/*
-* we could do something here, like scan children and decide on
-* the most appropriate rate to mix at, but we don't for now
-*/
-}
-if (flags & CHN_N_FORMAT) {
-/*
-* we could do something here, like scan children and decide on
-* the most appropriate mixer feeder to use, but we don't for now
-*/
-}
-if (flags & CHN_N_VOLUME) {
-/*
-* we could do something here but we don't for now
-*/
-}
-if (flags & CHN_N_BLOCKSIZE) {
-int blksz;
-/*
-* scan the children, find the lowest blocksize and use that
-* for the hard blocksize
-*/
-blksz = sndbuf_getmaxsize(c->bufhard) / 2;
-SLIST_FOREACH(pce, &c->children, link) {
-child = pce->channel;
-CHN_LOCK(child);
-if (sndbuf_getblksz(child->bufhard) < blksz)
-blksz = sndbuf_getblksz(child->bufhard);
-CHN_UNLOCK(child);
-}
-chn_setblocksize(c, 2, blksz);
-}
-if (flags & CHN_N_TRIGGER) {
-int nrun;
-/*
-* scan the children, and figure out if any are running
-* if so, we need to be running, otherwise we need to be stopped
-* if we aren't in our target sstate, move to it
-*/
-nrun = 0;
-SLIST_FOREACH(pce, &c->children, link) {
-child = pce->channel;
-CHN_LOCK(child);
-if (child->flags & CHN_F_TRIGGERED)
-nrun = 1;
-CHN_UNLOCK(child);
-}
-if (nrun && !run)
-chn_start(c, 1);
-if (!nrun && run)
-chn_abort(c);
-}
-CHN_UNLOCK(c);
-return 0;
+ return sg_id;
}
void
chn_lock(struct pcm_channel *c)
{
-CHN_LOCK(c);
+ CHN_LOCK(c);
}
void
chn_unlock(struct pcm_channel *c)
{
-CHN_UNLOCK(c);
+ CHN_UNLOCK(c);
+}
+
+#ifdef OSSV4_EXPERIMENT
+int
+chn_getpeaks(struct pcm_channel *c, int *lpeak, int *rpeak)
+{
+ CHN_LOCKASSERT(c);
+ return CHANNEL_GETPEAKS(c->methods, c->devinfo, lpeak, rpeak);
}
+#endif
Index: ac97.h
===================================================================
RCS file: /home/cvs/src/sys/dev/sound/pcm/ac97.h,v
retrieving revision 1.2
retrieving revision 1.3
diff -L sys/dev/sound/pcm/ac97.h -L sys/dev/sound/pcm/ac97.h -u -r1.2 -r1.3
--- sys/dev/sound/pcm/ac97.h
+++ sys/dev/sound/pcm/ac97.h
@@ -1,31 +1,30 @@
/*-
-* Copyright (c) 1999 Cameron Grant <cg at freebsd.org>
-* All rights reserved.
-*
-* Redistribution and use in source and binary forms, with or without
-* modification, are permitted provided that the following conditions
-* are met:
-* 1. Redistributions of source code must retain the above copyright
-* notice, this list of conditions and the following disclaimer.
-* 2. Redistributions in binary form must reproduce the above copyright
-* notice, this list of conditions and the following disclaimer in the
-* documentation and/or other materials provided with the distribution.
-*
-* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
-* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
-* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
-* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
-* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
-* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
-* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
-* SUCH DAMAGE.
-*
-* $MidnightBSD$
-* $FreeBSD: src/sys/dev/sound/pcm/ac97.h,v 1.16.2.1 2005/12/30 19:55:54 netchild Exp $
-*/
+ * Copyright (c) 1999 Cameron Grant <cg at freebsd.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD: src/sys/dev/sound/pcm/ac97.h,v 1.20 2007/04/19 13:54:22 ariff Exp $
+ */
#define AC97_MUTE 0x8080
@@ -61,7 +60,8 @@
#define AC97_POWER_DAC (1 << 1)
#define AC97_POWER_ANL (1 << 2)
#define AC97_POWER_REF (1 << 3)
-#define AC97_POWER_STATUS (AC97_POWER_ADC | AC97_POWER_DAC | AC97_POWER_REF | AC97_POWER_ANL )
+#define AC97_POWER_STATUS (AC97_POWER_ADC | AC97_POWER_DAC | \
+ AC97_POWER_REF | AC97_POWER_ANL )
#define AC97_REGEXT_ID 0x28
#define AC97_EXTCAP_VRA (1 << 0)
#define AC97_EXTCAP_DRA (1 << 1)
@@ -82,7 +82,6 @@
#define AC97_F_EAPD_INV 0x00000001
#define AC97_F_RDCD_BUG 0x00000002
-#define AC97_F_SOFTVOL 0x00000004
#define AC97_DECLARE(name) static DEFINE_CLASS(name, name ## _methods, sizeof(struct kobj))
#define AC97_CREATE(dev, devinfo, cls) ac97_create(dev, devinfo, &cls ## _class)
@@ -102,7 +101,7 @@
u_int16_t ac97_getextmode(struct ac97_info *codec);
u_int16_t ac97_getextcaps(struct ac97_info *codec);
u_int16_t ac97_getcaps(struct ac97_info *codec);
+u_int32_t ac97_getsubvendor(struct ac97_info *codec);
u_int16_t ac97_rdcd(struct ac97_info *codec, int reg);
void ac97_wrcd(struct ac97_info *codec, int reg, u_int16_t val);
-
Index: cs4231.c
===================================================================
RCS file: /home/cvs/src/sys/dev/sound/sbus/cs4231.c,v
retrieving revision 1.2
retrieving revision 1.3
diff -L sys/dev/sound/sbus/cs4231.c -L sys/dev/sound/sbus/cs4231.c -u -r1.2 -r1.3
--- sys/dev/sound/sbus/cs4231.c
+++ sys/dev/sound/sbus/cs4231.c
@@ -1,43 +1,43 @@
/*-
-* Copyright (c) 1999 Jason L. Wright (jason at thought.net)
-* Copyright (c) 2004 Pyun YongHyeon
-* All rights reserved.
-*
-* Redistribution and use in source and binary forms, with or without
-* modification, are permitted provided that the following conditions
-* are met:
-* 1. Redistributions of source code must retain the above copyright
-* notice, this list of conditions and the following disclaimer.
-* 2. Redistributions in binary form must reproduce the above copyright
-* notice, this list of conditions and the following disclaimer in the
-* documentation and/or other materials provided with the distribution.
-*
-* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
-* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-* DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
-* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
-* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
-* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
-* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
-* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
-* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-* POSSIBILITY OF SUCH DAMAGE.
-*
-* Effort sponsored in part by the Defense Advanced Research Projects
-* Agency (DARPA) and Air Force Research Laboratory, Air Force
-* Materiel Command, USAF, under agreement number F30602-01-2-0537.
-*
-* from: OpenBSD: cs4231.c,v 1.21 2003/07/03 20:36:07 jason Exp
-*/
+ * Copyright (c) 1999 Jason L. Wright (jason at thought.net)
+ * Copyright (c) 2004 Pyun YongHyeon
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Effort sponsored in part by the Defense Advanced Research Projects
+ * Agency (DARPA) and Air Force Research Laboratory, Air Force
+ * Materiel Command, USAF, under agreement number F30602-01-2-0537.
+ *
+ * from: OpenBSD: cs4231.c,v 1.21 2003/07/03 20:36:07 jason Exp
+ */
/*
-* Driver for CS4231 based audio found in some sun4m systems (cs4231)
-* based on ideas from the S/Linux project and the NetBSD project.
-*/
+ * Driver for CS4231 based audio found in some sun4m systems (cs4231)
+ * based on ideas from the S/Linux project and the NetBSD project.
+ */
#include <sys/cdefs.h>
-__MBSDID("$MidnightBSD$");
+__FBSDID("$FreeBSD: src/sys/dev/sound/sbus/cs4231.c,v 1.9 2007/06/17 06:10:43 ariff Exp $");
#include <sys/param.h>
#include <sys/systm.h>
@@ -60,21 +60,21 @@
#include "mixer_if.h"
/*
-* The driver supports CS4231A audio chips found on Sbus/Ebus based
-* UltraSPARCs. Though, CS4231A says it supports full-duplex mode, I
-* doubt it due to the lack of independent sampling frequency register
-* for playback/capture.
-* Since I couldn't find any documentation for APCDMA programming
-* information, I guessed the usage of APCDMA from that of OpenBSD's
-* driver. The EBDMA infomation of PCIO can be obtained from
-* http://solutions.sun.com/embedded/databook/web/microprocessors/pcio.html
-* And CS4231A datasheet can also be obtained from
-* ftp://ftp.alsa-project.org/pub/manuals/cirrus/4231a.pdf
-*
-* Audio capture(recording) was not tested at all and may have bugs.
-* Sorry, I don't have microphone. Don't try to use full-duplex mode.
-* It wouldn't work.
-*/
+ * The driver supports CS4231A audio chips found on Sbus/Ebus based
+ * UltraSPARCs. Though, CS4231A says it supports full-duplex mode, I
+ * doubt it due to the lack of independent sampling frequency register
+ * for playback/capture.
+ * Since I couldn't find any documentation for APCDMA programming
+ * information, I guessed the usage of APCDMA from that of OpenBSD's
+ * driver. The EBDMA infomation of PCIO can be obtained from
+ * http://solutions.sun.com/embedded/databook/web/microprocessors/pcio.html
+ * And CS4231A datasheet can also be obtained from
+ * ftp://ftp.alsa-project.org/pub/manuals/cirrus/4231a.pdf
+ *
+ * Audio capture(recording) was not tested at all and may have bugs.
+ * Sorry, I don't have microphone. Don't try to use full-duplex mode.
+ * It wouldn't work.
+ */
#define CS_TIMEOUT 90000
#define CS4231_MIN_BUF_SZ (16*1024)
@@ -95,55 +95,55 @@
struct cs4231_softc;
struct cs4231_channel {
-struct cs4231_softc *parent;
-struct pcm_channel *channel;
-struct snd_dbuf *buffer;
-u_int32_t format;
-u_int32_t speed;
-u_int32_t nextaddr;
-u_int32_t togo;
-int dir;
-int locked;
+ struct cs4231_softc *parent;
+ struct pcm_channel *channel;
+ struct snd_dbuf *buffer;
+ u_int32_t format;
+ u_int32_t speed;
+ u_int32_t nextaddr;
+ u_int32_t togo;
+ int dir;
+ int locked;
};
#define CS4231_RES_MEM_MAX 4
#define CS4231_RES_IRQ_MAX 2
struct cs4231_softc {
-struct device *sc_dev;
-int sc_rid[CS4231_RES_MEM_MAX];
-struct resource *sc_res[CS4231_RES_MEM_MAX];
-bus_space_handle_t sc_regh[CS4231_RES_MEM_MAX];
-bus_space_tag_t sc_regt[CS4231_RES_MEM_MAX];
-
-int sc_irqrid[CS4231_RES_IRQ_MAX];
-struct resource *sc_irqres[CS4231_RES_IRQ_MAX];
-void *sc_ih[CS4231_RES_IRQ_MAX];
-bus_dma_tag_t sc_dmat[CS4231_RES_IRQ_MAX];
-int sc_burst;
-
-u_int32_t sc_bufsz;
-struct cs4231_channel sc_pch;
-struct cs4231_channel sc_rch;
-int sc_enabled;
-int sc_nmres;
-int sc_nires;
-int sc_codecv;
-int sc_chipvid;
-int sc_flags;
+ struct device *sc_dev;
+ int sc_rid[CS4231_RES_MEM_MAX];
+ struct resource *sc_res[CS4231_RES_MEM_MAX];
+ bus_space_handle_t sc_regh[CS4231_RES_MEM_MAX];
+ bus_space_tag_t sc_regt[CS4231_RES_MEM_MAX];
+
+ int sc_irqrid[CS4231_RES_IRQ_MAX];
+ struct resource *sc_irqres[CS4231_RES_IRQ_MAX];
+ void *sc_ih[CS4231_RES_IRQ_MAX];
+ bus_dma_tag_t sc_dmat[CS4231_RES_IRQ_MAX];
+ int sc_burst;
+
+ u_int32_t sc_bufsz;
+ struct cs4231_channel sc_pch;
+ struct cs4231_channel sc_rch;
+ int sc_enabled;
+ int sc_nmres;
+ int sc_nires;
+ int sc_codecv;
+ int sc_chipvid;
+ int sc_flags;
#define CS4231_SBUS 0x01
#define CS4231_EBUS 0x02
-struct mtx *sc_lock;
+ struct mtx *sc_lock;
};
struct mix_table {
-u_int32_t reg:8;
-u_int32_t bits:8;
-u_int32_t mute:8;
-u_int32_t shift:4;
-u_int32_t neg:1;
-u_int32_t avail:1;
-u_int32_t recdev:1;
+ u_int32_t reg:8;
+ u_int32_t bits:8;
+ u_int32_t mute:8;
+ u_int32_t shift:4;
+ u_int32_t neg:1;
+ u_int32_t avail:1;
+ u_int32_t recdev:1;
};
static int cs4231_bus_probe(device_t);
@@ -166,12 +166,12 @@
static void cs4231_ebus_cintr(void *arg);
static int cs4231_mixer_init(struct snd_mixer *);
static void cs4231_mixer_set_value(struct cs4231_softc *,
-const struct mix_table *, u_int8_t);
+ const struct mix_table *, u_int8_t);
static int cs4231_mixer_set(struct snd_mixer *, u_int32_t, u_int32_t,
-u_int32_t);
+ u_int32_t);
static int cs4231_mixer_setrecsrc(struct snd_mixer *, u_int32_t);
static void *cs4231_chan_init(kobj_t, void *, struct snd_dbuf *,
-struct pcm_channel *, int);
+ struct pcm_channel *, int);
static int cs4231_chan_setformat(kobj_t, void *, u_int32_t);
static int cs4231_chan_setspeed(kobj_t, void *, u_int32_t);
static void cs4231_chan_fs(struct cs4231_softc *, int, u_int8_t);
@@ -179,69 +179,79 @@
static int cs4231_chan_trigger(kobj_t, void *, int);
static int cs4231_chan_getptr(kobj_t, void *);
static struct pcmchan_caps *
-cs4231_chan_getcaps(kobj_t, void *);
+ cs4231_chan_getcaps(kobj_t, void *);
static void cs4231_trigger(struct cs4231_channel *);
static void cs4231_apcdma_trigger(struct cs4231_softc *,
-struct cs4231_channel *);
+ struct cs4231_channel *);
static void cs4231_ebdma_trigger(struct cs4231_softc *,
-struct cs4231_channel *);
+ struct cs4231_channel *);
static void cs4231_halt(struct cs4231_channel *);
#define CS4231_LOCK(sc) snd_mtxlock(sc->sc_lock)
#define CS4231_UNLOCK(sc) snd_mtxunlock(sc->sc_lock)
#define CS4231_LOCK_ASSERT(sc) snd_mtxassert(sc->sc_lock)
-#define CS_WRITE(sc,r,v) bus_space_write_1((sc)->sc_regt[0], (sc)->sc_regh[0], (r) << 2, (v))
-#define CS_READ(sc,r) bus_space_read_1((sc)->sc_regt[0], (sc)->sc_regh[0], (r) << 2)
-
-#define APC_WRITE(sc,r,v) bus_space_write_4(sc->sc_regt[0], sc->sc_regh[0], r, v)
-#define APC_READ(sc,r) bus_space_read_4(sc->sc_regt[0], sc->sc_regh[0], r)
-
-#define EBDMA_P_WRITE(sc,r,v) bus_space_write_4((sc)->sc_regt[1], (sc)->sc_regh[1], (r), (v))
-#define EBDMA_P_READ(sc,r) bus_space_read_4((sc)->sc_regt[1], (sc)->sc_regh[1], (r))
-
-#define EBDMA_C_WRITE(sc,r,v) bus_space_write_4((sc)->sc_regt[2], (sc)->sc_regh[2], (r), (v))
-#define EBDMA_C_READ(sc,r) bus_space_read_4((sc)->sc_regt[2], (sc)->sc_regh[2], (r))
+#define CS_WRITE(sc,r,v) \
+ bus_space_write_1((sc)->sc_regt[0], (sc)->sc_regh[0], (r) << 2, (v))
+#define CS_READ(sc,r) \
+ bus_space_read_1((sc)->sc_regt[0], (sc)->sc_regh[0], (r) << 2)
+
+#define APC_WRITE(sc,r,v) \
+ bus_space_write_4(sc->sc_regt[0], sc->sc_regh[0], r, v)
+#define APC_READ(sc,r) \
+ bus_space_read_4(sc->sc_regt[0], sc->sc_regh[0], r)
+
+#define EBDMA_P_WRITE(sc,r,v) \
+ bus_space_write_4((sc)->sc_regt[1], (sc)->sc_regh[1], (r), (v))
+#define EBDMA_P_READ(sc,r) \
+ bus_space_read_4((sc)->sc_regt[1], (sc)->sc_regh[1], (r))
+
+#define EBDMA_C_WRITE(sc,r,v) \
+ bus_space_write_4((sc)->sc_regt[2], (sc)->sc_regh[2], (r), (v))
+#define EBDMA_C_READ(sc,r) \
+ bus_space_read_4((sc)->sc_regt[2], (sc)->sc_regh[2], (r))
#define AUXIO_CODEC 0x00
-#define AUXIO_WRITE(sc,r,v) bus_space_write_4((sc)->sc_regt[3], (sc)->sc_regh[3], (r), (v))
-#define AUXIO_READ(sc,r) bus_space_read_4((sc)->sc_regt[3], (sc)->sc_regh[3], (r))
+#define AUXIO_WRITE(sc,r,v) \
+ bus_space_write_4((sc)->sc_regt[3], (sc)->sc_regh[3], (r), (v))
+#define AUXIO_READ(sc,r) \
+ bus_space_read_4((sc)->sc_regt[3], (sc)->sc_regh[3], (r))
#define CODEC_WARM_RESET 0
#define CODEC_COLD_RESET 1
/* SBus */
static device_method_t cs4231_sbus_methods[] = {
-DEVMETHOD(device_probe, cs4231_bus_probe),
-DEVMETHOD(device_attach, cs4231_sbus_attach),
-DEVMETHOD(device_detach, cs4231_bus_detach),
-DEVMETHOD(device_suspend, cs4231_bus_suspend),
-DEVMETHOD(device_resume, cs4231_bus_resume),
-{0, 0}
+ DEVMETHOD(device_probe, cs4231_bus_probe),
+ DEVMETHOD(device_attach, cs4231_sbus_attach),
+ DEVMETHOD(device_detach, cs4231_bus_detach),
+ DEVMETHOD(device_suspend, cs4231_bus_suspend),
+ DEVMETHOD(device_resume, cs4231_bus_resume),
+ {0, 0}
};
static driver_t cs4231_sbus_driver = {
-"pcm",
-cs4231_sbus_methods,
-PCM_SOFTC_SIZE
+ "pcm",
+ cs4231_sbus_methods,
+ PCM_SOFTC_SIZE
};
DRIVER_MODULE(snd_audiocs, sbus, cs4231_sbus_driver, pcm_devclass, 0, 0);
/* EBus */
static device_method_t cs4231_ebus_methods[] = {
-DEVMETHOD(device_probe, cs4231_bus_probe),
-DEVMETHOD(device_attach, cs4231_ebus_attach),
-DEVMETHOD(device_detach, cs4231_bus_detach),
-DEVMETHOD(device_suspend, cs4231_bus_suspend),
-DEVMETHOD(device_resume, cs4231_bus_resume),
-{0, 0}
+ DEVMETHOD(device_probe, cs4231_bus_probe),
+ DEVMETHOD(device_attach, cs4231_ebus_attach),
+ DEVMETHOD(device_detach, cs4231_bus_detach),
+ DEVMETHOD(device_suspend, cs4231_bus_suspend),
+ DEVMETHOD(device_resume, cs4231_bus_resume),
+ {0, 0}
};
static driver_t cs4231_ebus_driver = {
-"pcm",
-cs4231_ebus_methods,
-PCM_SOFTC_SIZE
+ "pcm",
+ cs4231_ebus_methods,
+ PCM_SOFTC_SIZE
};
DRIVER_MODULE(snd_audiocs, ebus, cs4231_ebus_driver, pcm_devclass, 0, 0);
@@ -250,1311 +260,1300 @@
static u_int32_t cs4231_fmt[] = {
-AFMT_U8,
-AFMT_STEREO | AFMT_U8,
-AFMT_MU_LAW,
-AFMT_STEREO | AFMT_MU_LAW,
-AFMT_A_LAW,
-AFMT_STEREO | AFMT_A_LAW,
-AFMT_IMA_ADPCM,
-AFMT_STEREO | AFMT_IMA_ADPCM,
-AFMT_S16_LE,
-AFMT_STEREO | AFMT_S16_LE,
-AFMT_S16_BE,
-AFMT_STEREO | AFMT_S16_BE,
-0
+ AFMT_U8,
+ AFMT_STEREO | AFMT_U8,
+ AFMT_MU_LAW,
+ AFMT_STEREO | AFMT_MU_LAW,
+ AFMT_A_LAW,
+ AFMT_STEREO | AFMT_A_LAW,
+ AFMT_IMA_ADPCM,
+ AFMT_STEREO | AFMT_IMA_ADPCM,
+ AFMT_S16_LE,
+ AFMT_STEREO | AFMT_S16_LE,
+ AFMT_S16_BE,
+ AFMT_STEREO | AFMT_S16_BE,
+ 0
};
static struct pcmchan_caps cs4231_caps = {5510, 48000, cs4231_fmt, 0};
/*
-* sound(4) channel interface
-*/
+ * sound(4) channel interface
+ */
static kobj_method_t cs4231_chan_methods[] = {
-KOBJMETHOD(channel_init, cs4231_chan_init),
-KOBJMETHOD(channel_setformat, cs4231_chan_setformat),
-KOBJMETHOD(channel_setspeed, cs4231_chan_setspeed),
-KOBJMETHOD(channel_setblocksize, cs4231_chan_setblocksize),
-KOBJMETHOD(channel_trigger, cs4231_chan_trigger),
-KOBJMETHOD(channel_getptr, cs4231_chan_getptr),
-KOBJMETHOD(channel_getcaps, cs4231_chan_getcaps),
-{ 0, 0 }
+ KOBJMETHOD(channel_init, cs4231_chan_init),
+ KOBJMETHOD(channel_setformat, cs4231_chan_setformat),
+ KOBJMETHOD(channel_setspeed, cs4231_chan_setspeed),
+ KOBJMETHOD(channel_setblocksize, cs4231_chan_setblocksize),
+ KOBJMETHOD(channel_trigger, cs4231_chan_trigger),
+ KOBJMETHOD(channel_getptr, cs4231_chan_getptr),
+ KOBJMETHOD(channel_getcaps, cs4231_chan_getcaps),
+ { 0, 0 }
};
CHANNEL_DECLARE(cs4231_chan);
/*
-* sound(4) mixer interface
-*/
+ * sound(4) mixer interface
+ */
static kobj_method_t cs4231_mixer_methods[] = {
-KOBJMETHOD(mixer_init, cs4231_mixer_init),
-KOBJMETHOD(mixer_set, cs4231_mixer_set),
-KOBJMETHOD(mixer_setrecsrc, cs4231_mixer_setrecsrc),
-{ 0, 0 }
+ KOBJMETHOD(mixer_init, cs4231_mixer_init),
+ KOBJMETHOD(mixer_set, cs4231_mixer_set),
+ KOBJMETHOD(mixer_setrecsrc, cs4231_mixer_setrecsrc),
+ { 0, 0 }
};
MIXER_DECLARE(cs4231_mixer);
static int
cs4231_bus_probe(device_t dev)
{
-const char *name;
+ const char *compat, *name;
-name = ofw_bus_get_name(dev);
-if (strcmp("SUNW,CS4231", name) == 0) {
-device_set_desc(dev, "Sun Audiocs");
-return (BUS_PROBE_DEFAULT);
-}
-return (ENXIO);
+ compat = ofw_bus_get_compat(dev);
+ name = ofw_bus_get_name(dev);
+ if (strcmp("SUNW,CS4231", name) == 0 ||
+ (compat != NULL && strcmp("SUNW,CS4231", compat) == 0)) {
+ device_set_desc(dev, "Sun Audiocs");
+ return (BUS_PROBE_DEFAULT);
+ }
+ return (ENXIO);
}
static int
cs4231_sbus_attach(device_t dev)
{
-struct snddev_info *d;
-struct cs4231_softc *sc;
-int burst;
-
-d = device_get_softc(dev);
-sc = malloc(sizeof(struct cs4231_softc), M_DEVBUF, M_NOWAIT | M_ZERO);
-if (sc == NULL) {
-device_printf(dev, "cannot allocate softcn");
-return (ENOMEM);
-}
-sc->sc_dev = dev;
-/*
-* XXX
-* No public documentation exists on programming burst size of APCDMA.
-*/
-burst = sbus_get_burstsz(sc->sc_dev);
-if ((burst & SBUS_BURST_64))
-sc->sc_burst = 64;
-else if ((burst & SBUS_BURST_32))
-sc->sc_burst = 32;
-else if ((burst & SBUS_BURST_16))
-sc->sc_burst = 16;
-else
-sc->sc_burst = 0;
-sc->sc_flags = CS4231_SBUS;
-sc->sc_nmres = 1;
-sc->sc_nires = 1;
-return cs4231_attach_common(sc);
+ struct cs4231_softc *sc;
+ int burst;
+
+ sc = malloc(sizeof(*sc), M_DEVBUF, M_WAITOK | M_ZERO);
+ sc->sc_dev = dev;
+ /*
+ * XXX
+ * No public documentation exists on programming burst size of APCDMA.
+ */
+ burst = sbus_get_burstsz(sc->sc_dev);
+ if ((burst & SBUS_BURST_64))
+ sc->sc_burst = 64;
+ else if ((burst & SBUS_BURST_32))
+ sc->sc_burst = 32;
+ else if ((burst & SBUS_BURST_16))
+ sc->sc_burst = 16;
+ else
+ sc->sc_burst = 0;
+ sc->sc_flags = CS4231_SBUS;
+ sc->sc_nmres = 1;
+ sc->sc_nires = 1;
+ return cs4231_attach_common(sc);
}
static int
cs4231_ebus_attach(device_t dev)
{
-struct snddev_info *d;
-struct cs4231_softc *sc;
+ struct cs4231_softc *sc;
-d = device_get_softc(dev);
-sc = malloc(sizeof(struct cs4231_softc), M_DEVBUF, M_NOWAIT | M_ZERO);
-if (sc == NULL) {
-device_printf(dev, "cannot allocate softcn");
-return (ENOMEM);
-}
-sc->sc_dev = dev;
-sc->sc_burst = EBDCSR_BURST_1;
-sc->sc_nmres = CS4231_RES_MEM_MAX;
-sc->sc_nires = CS4231_RES_IRQ_MAX;
-sc->sc_flags = CS4231_EBUS;
-return cs4231_attach_common(sc);
+ sc = malloc(sizeof(struct cs4231_softc), M_DEVBUF, M_NOWAIT | M_ZERO);
+ if (sc == NULL) {
+ device_printf(dev, "cannot allocate softc\n");
+ return (ENOMEM);
+ }
+ sc->sc_dev = dev;
+ sc->sc_burst = EBDCSR_BURST_1;
+ sc->sc_nmres = CS4231_RES_MEM_MAX;
+ sc->sc_nires = CS4231_RES_IRQ_MAX;
+ sc->sc_flags = CS4231_EBUS;
+ return cs4231_attach_common(sc);
}
static int
cs4231_attach_common(struct cs4231_softc *sc)
{
-char status[SND_STATUSLEN];
-driver_intr_t *ihandler;
-int i;
-
-sc->sc_lock = snd_mtxcreate(device_get_nameunit(sc->sc_dev),
-"sound softc");
-if (sc->sc_lock == NULL) {
-device_printf(sc->sc_dev, "cannot create mutexn");
-free(sc, M_DEVBUF);
-return (ENXIO);
-}
-
-for (i = 0; i < sc->sc_nmres; i++) {
-sc->sc_rid[i] = i;
-if ((sc->sc_res[i] = bus_alloc_resource_any(sc->sc_dev,
-SYS_RES_MEMORY, &sc->sc_rid[i], RF_ACTIVE)) == NULL) {
-device_printf(sc->sc_dev,
-"cannot map register %dn", i);
-goto fail;
-}
-sc->sc_regt[i] = rman_get_bustag(sc->sc_res[i]);
-sc->sc_regh[i] = rman_get_bushandle(sc->sc_res[i]);
-}
-for (i = 0; i < sc->sc_nires; i++) {
-sc->sc_irqrid[i] = i;
-if ((sc->sc_irqres[i] = bus_alloc_resource_any(sc->sc_dev,
-SYS_RES_IRQ, &sc->sc_irqrid[i], RF_SHAREABLE | RF_ACTIVE))
-== NULL) {
-if ((sc->sc_flags & CS4231_SBUS) != 0)
-device_printf(sc->sc_dev,
-"cannot allocate interruptn");
-else
-device_printf(sc->sc_dev, "cannot allocate %s "
-"interruptn", i == 0 ? "capture" :
-"playback");
-goto fail;
-}
-}
-
-ihandler = cs4231_sbus_intr;
-for (i = 0; i < sc->sc_nires; i++) {
-if ((sc->sc_flags & CS4231_EBUS) != 0) {
-if (i == 0)
-ihandler = cs4231_ebus_cintr;
-else
-ihandler = cs4231_ebus_pintr;
-}
-if (snd_setup_intr(sc->sc_dev, sc->sc_irqres[i], INTR_MPSAFE,
-ihandler, sc, &sc->sc_ih[i])) {
-if ((sc->sc_flags & CS4231_SBUS) != 0)
-device_printf(sc->sc_dev,
-"cannot set up interruptn");
-else
-device_printf(sc->sc_dev, "cannot set up %s "
-" interruptn", i == 0 ? "capture" :
-"playback");
-goto fail;
-}
-}
-
-sc->sc_bufsz = pcm_getbuffersize(sc->sc_dev, CS4231_MIN_BUF_SZ,
-CS4231_DEFAULT_BUF_SZ, CS4231_MAX_BUF_SZ);
-for (i = 0; i < sc->sc_nires; i++) {
-if (bus_dma_tag_create(
-NULL, /* parent */
-64, 0, /* alignment, boundary */
-BUS_SPACE_MAXADDR_32BIT, /* lowaddr */
-BUS_SPACE_MAXADDR, /* highaddr */
-NULL, NULL, /* filtfunc, filtfuncarg */
-sc->sc_bufsz, /* maxsize */
-1, /* nsegments */
-sc->sc_bufsz, /* maxsegsz */
-BUS_DMA_ALLOCNOW, /* flags */
-NULL, /* lockfunc */
-NULL, /* lockfuncarg */
-&sc->sc_dmat[i])) {
-if ((sc->sc_flags & CS4231_SBUS) != 0)
-device_printf(sc->sc_dev,
-"cannot allocate DMA tagn");
-else
-device_printf(sc->sc_dev, "cannot allocate %s "
-"DMA tagn", i == 0 ? "capture" :
-"playback");
-goto fail;
-}
-}
-cs4231_enable(sc, CODEC_WARM_RESET);
-cs4231_getversion(sc);
-if (mixer_init(sc->sc_dev, &cs4231_mixer_class, sc) != 0)
-goto fail;
-if (pcm_register(sc->sc_dev, sc, 1, 1)) {
-device_printf(sc->sc_dev, "cannot register to pcmn");
-goto fail;
-}
-if (pcm_addchan(sc->sc_dev, PCMDIR_REC, &cs4231_chan_class, sc) != 0)
-goto chan_fail;
-if (pcm_addchan(sc->sc_dev, PCMDIR_PLAY, &cs4231_chan_class, sc) != 0)
-goto chan_fail;
-if ((sc->sc_flags & CS4231_SBUS) != 0)
-snprintf(status, SND_STATUSLEN, "at mem 0x%lx irq %ld bufsz %u",
-rman_get_start(sc->sc_res[0]),
-rman_get_start(sc->sc_irqres[0]), sc->sc_bufsz);
-else
-snprintf(status, SND_STATUSLEN, "at io 0x%lx 0x%lx 0x%lx 0x%lx "
-"irq %ld %ld bufsz %u", rman_get_start(sc->sc_res[0]),
-rman_get_start(sc->sc_res[1]),
-rman_get_start(sc->sc_res[2]),
-rman_get_start(sc->sc_res[3]),
-rman_get_start(sc->sc_irqres[0]),
-rman_get_start(sc->sc_irqres[1]), sc->sc_bufsz);
-pcm_setstatus(sc->sc_dev, status);
-return (0);
+ char status[SND_STATUSLEN];
+ driver_intr_t *ihandler;
+ int i;
+
+ sc->sc_lock = snd_mtxcreate(device_get_nameunit(sc->sc_dev),
+ "snd_cs4231 softc");
+
+ for (i = 0; i < sc->sc_nmres; i++) {
+ sc->sc_rid[i] = i;
+ if ((sc->sc_res[i] = bus_alloc_resource_any(sc->sc_dev,
+ SYS_RES_MEMORY, &sc->sc_rid[i], RF_ACTIVE)) == NULL) {
+ device_printf(sc->sc_dev,
+ "cannot map register %d\n", i);
+ goto fail;
+ }
+ sc->sc_regt[i] = rman_get_bustag(sc->sc_res[i]);
+ sc->sc_regh[i] = rman_get_bushandle(sc->sc_res[i]);
+ }
+ for (i = 0; i < sc->sc_nires; i++) {
+ sc->sc_irqrid[i] = i;
+ if ((sc->sc_irqres[i] = bus_alloc_resource_any(sc->sc_dev,
+ SYS_RES_IRQ, &sc->sc_irqrid[i], RF_SHAREABLE | RF_ACTIVE))
+ == NULL) {
+ if ((sc->sc_flags & CS4231_SBUS) != 0)
+ device_printf(sc->sc_dev,
+ "cannot allocate interrupt\n");
+ else
+ device_printf(sc->sc_dev, "cannot allocate %s "
+ "interrupt\n", i == 0 ? "capture" :
+ "playback");
+ goto fail;
+ }
+ }
+
+ ihandler = cs4231_sbus_intr;
+ for (i = 0; i < sc->sc_nires; i++) {
+ if ((sc->sc_flags & CS4231_EBUS) != 0) {
+ if (i == 0)
+ ihandler = cs4231_ebus_cintr;
+ else
+ ihandler = cs4231_ebus_pintr;
+ }
+ if (snd_setup_intr(sc->sc_dev, sc->sc_irqres[i], INTR_MPSAFE,
+ ihandler, sc, &sc->sc_ih[i])) {
+ if ((sc->sc_flags & CS4231_SBUS) != 0)
+ device_printf(sc->sc_dev,
+ "cannot set up interrupt\n");
+ else
+ device_printf(sc->sc_dev, "cannot set up %s "
+ " interrupt\n", i == 0 ? "capture" :
+ "playback");
+ goto fail;
+ }
+ }
+
+ sc->sc_bufsz = pcm_getbuffersize(sc->sc_dev, CS4231_MIN_BUF_SZ,
+ CS4231_DEFAULT_BUF_SZ, CS4231_MAX_BUF_SZ);
+ for (i = 0; i < sc->sc_nires; i++) {
+ if (bus_dma_tag_create(
+ bus_get_dma_tag(sc->sc_dev),/* parent */
+ 64, 0, /* alignment, boundary */
+ BUS_SPACE_MAXADDR_32BIT, /* lowaddr */
+ BUS_SPACE_MAXADDR, /* highaddr */
+ NULL, NULL, /* filtfunc, filtfuncarg */
+ sc->sc_bufsz, /* maxsize */
+ 1, /* nsegments */
+ sc->sc_bufsz, /* maxsegsz */
+ BUS_DMA_ALLOCNOW, /* flags */
+ NULL, /* lockfunc */
+ NULL, /* lockfuncarg */
+ &sc->sc_dmat[i])) {
+ if ((sc->sc_flags & CS4231_SBUS) != 0)
+ device_printf(sc->sc_dev,
+ "cannot allocate DMA tag\n");
+ else
+ device_printf(sc->sc_dev, "cannot allocate %s "
+ "DMA tag\n", i == 0 ? "capture" :
+ "playback");
+ goto fail;
+ }
+ }
+ cs4231_enable(sc, CODEC_WARM_RESET);
+ cs4231_getversion(sc);
+ if (mixer_init(sc->sc_dev, &cs4231_mixer_class, sc) != 0)
+ goto fail;
+ if (pcm_register(sc->sc_dev, sc, 1, 1)) {
+ device_printf(sc->sc_dev, "cannot register to pcm\n");
+ goto fail;
+ }
+ if (pcm_addchan(sc->sc_dev, PCMDIR_REC, &cs4231_chan_class, sc) != 0)
+ goto chan_fail;
+ if (pcm_addchan(sc->sc_dev, PCMDIR_PLAY, &cs4231_chan_class, sc) != 0)
+ goto chan_fail;
+ if ((sc->sc_flags & CS4231_SBUS) != 0)
+ snprintf(status, SND_STATUSLEN, "at mem 0x%lx irq %ld bufsz %u",
+ rman_get_start(sc->sc_res[0]),
+ rman_get_start(sc->sc_irqres[0]), sc->sc_bufsz);
+ else
+ snprintf(status, SND_STATUSLEN, "at io 0x%lx 0x%lx 0x%lx 0x%lx "
+ "irq %ld %ld bufsz %u", rman_get_start(sc->sc_res[0]),
+ rman_get_start(sc->sc_res[1]),
+ rman_get_start(sc->sc_res[2]),
+ rman_get_start(sc->sc_res[3]),
+ rman_get_start(sc->sc_irqres[0]),
+ rman_get_start(sc->sc_irqres[1]), sc->sc_bufsz);
+ pcm_setstatus(sc->sc_dev, status);
+ return (0);
chan_fail:
-pcm_unregister(sc->sc_dev);
+ pcm_unregister(sc->sc_dev);
fail:
-cs4231_free_resource(sc);
-return (ENXIO);
+ cs4231_free_resource(sc);
+ return (ENXIO);
}
static int
cs4231_bus_detach(device_t dev)
{
-struct cs4231_softc *sc;
-struct cs4231_channel *pch, *rch;
-int error;
-
-sc = pcm_getdevinfo(dev);
-CS4231_LOCK(sc);
-pch = &sc->sc_pch;
-rch = &sc->sc_pch;
-if (pch->locked || rch->locked) {
-CS4231_UNLOCK(sc);
-return (EBUSY);
-}
-/*
-* Since EBDMA requires valid DMA buffer to drain its FIFO, we need
-* real DMA buffer for draining.
-*/
-if ((sc->sc_flags & CS4231_EBUS) != 0)
-cs4231_ebdma_reset(sc);
-CS4231_UNLOCK(sc);
-error = pcm_unregister(dev);
-if (error)
-return (error);
-cs4231_free_resource(sc);
-return (0);
+ struct cs4231_softc *sc;
+ struct cs4231_channel *pch, *rch;
+ int error;
+
+ sc = pcm_getdevinfo(dev);
+ CS4231_LOCK(sc);
+ pch = &sc->sc_pch;
+ rch = &sc->sc_pch;
+ if (pch->locked || rch->locked) {
+ CS4231_UNLOCK(sc);
+ return (EBUSY);
+ }
+ /*
+ * Since EBDMA requires valid DMA buffer to drain its FIFO, we need
+ * real DMA buffer for draining.
+ */
+ if ((sc->sc_flags & CS4231_EBUS) != 0)
+ cs4231_ebdma_reset(sc);
+ CS4231_UNLOCK(sc);
+ error = pcm_unregister(dev);
+ if (error)
+ return (error);
+ cs4231_free_resource(sc);
+ return (0);
}
static int
cs4231_bus_suspend(device_t dev)
{
-return (ENXIO);
+ return (ENXIO);
}
static int
cs4231_bus_resume(device_t dev)
{
-return (ENXIO);
+ return (ENXIO);
}
static void
cs4231_getversion(struct cs4231_softc *sc)
{
-u_int8_t v;
+ u_int8_t v;
-v = cs4231_read(sc, CS_MISC_INFO);
-sc->sc_codecv = v & CS_CODEC_ID_MASK;
-v = cs4231_read(sc, CS_VERSION_ID);
-v &= (CS_VERSION_NUMBER | CS_VERSION_CHIPID);
-sc->sc_chipvid = v;
-switch(v) {
-case 0x80:
-device_printf(sc->sc_dev, "<CS4231 Codec Id. %d>n",
-sc->sc_codecv);
-break;
-case 0xa0:
-device_printf(sc->sc_dev, "<CS4231A Codec Id. %d>n",
-sc->sc_codecv);
-break;
-case 0x82:
-device_printf(sc->sc_dev, "<CS4232 Codec Id. %d>n",
-sc->sc_codecv);
-break;
-default:
-device_printf(sc->sc_dev,
-"<Unknown 0x%x Codec Id. %dn", v, sc->sc_codecv);
-break;
-}
+ v = cs4231_read(sc, CS_MISC_INFO);
+ sc->sc_codecv = v & CS_CODEC_ID_MASK;
+ v = cs4231_read(sc, CS_VERSION_ID);
+ v &= (CS_VERSION_NUMBER | CS_VERSION_CHIPID);
+ sc->sc_chipvid = v;
+ switch(v) {
+ case 0x80:
+ device_printf(sc->sc_dev, "<CS4231 Codec Id. %d>\n",
+ sc->sc_codecv);
+ break;
+ case 0xa0:
+ device_printf(sc->sc_dev, "<CS4231A Codec Id. %d>\n",
+ sc->sc_codecv);
+ break;
+ case 0x82:
+ device_printf(sc->sc_dev, "<CS4232 Codec Id. %d>\n",
+ sc->sc_codecv);
+ break;
+ default:
+ device_printf(sc->sc_dev,
+ "<Unknown 0x%x Codec Id. %d\n", v, sc->sc_codecv);
+ break;
+ }
}
static void
cs4231_ebdma_reset(struct cs4231_softc *sc)
{
-int i;
+ int i;
-/* playback */
-EBDMA_P_WRITE(sc, EBDMA_DCSR,
-EBDMA_P_READ(sc, EBDMA_DCSR) & ~(EBDCSR_INTEN | EBDCSR_NEXTEN));
-EBDMA_P_WRITE(sc, EBDMA_DCSR, EBDCSR_RESET);
-for (i = CS_TIMEOUT;
-i && EBDMA_P_READ(sc, EBDMA_DCSR) & EBDCSR_DRAIN; i--)
-DELAY(1);
-if (i == 0)
-device_printf(sc->sc_dev,
-"timeout waiting for playback DMA resetn");
-EBDMA_P_WRITE(sc, EBDMA_DCSR, sc->sc_burst);
-/* capture */
-EBDMA_C_WRITE(sc, EBDMA_DCSR,
-EBDMA_C_READ(sc, EBDMA_DCSR) & ~(EBDCSR_INTEN | EBDCSR_NEXTEN));
-EBDMA_C_WRITE(sc, EBDMA_DCSR, EBDCSR_RESET);
-for (i = CS_TIMEOUT;
-i && EBDMA_C_READ(sc, EBDMA_DCSR) & EBDCSR_DRAIN; i--)
-DELAY(1);
-if (i == 0)
-device_printf(sc->sc_dev,
-"timeout waiting for capture DMA resetn");
-EBDMA_C_WRITE(sc, EBDMA_DCSR, sc->sc_burst);
+ /* playback */
+ EBDMA_P_WRITE(sc, EBDMA_DCSR,
+ EBDMA_P_READ(sc, EBDMA_DCSR) & ~(EBDCSR_INTEN | EBDCSR_NEXTEN));
+ EBDMA_P_WRITE(sc, EBDMA_DCSR, EBDCSR_RESET);
+ for (i = CS_TIMEOUT;
+ i && EBDMA_P_READ(sc, EBDMA_DCSR) & EBDCSR_DRAIN; i--)
+ DELAY(1);
+ if (i == 0)
+ device_printf(sc->sc_dev,
+ "timeout waiting for playback DMA reset\n");
+ EBDMA_P_WRITE(sc, EBDMA_DCSR, sc->sc_burst);
+ /* capture */
+ EBDMA_C_WRITE(sc, EBDMA_DCSR,
+ EBDMA_C_READ(sc, EBDMA_DCSR) & ~(EBDCSR_INTEN | EBDCSR_NEXTEN));
+ EBDMA_C_WRITE(sc, EBDMA_DCSR, EBDCSR_RESET);
+ for (i = CS_TIMEOUT;
+ i && EBDMA_C_READ(sc, EBDMA_DCSR) & EBDCSR_DRAIN; i--)
+ DELAY(1);
+ if (i == 0)
+ device_printf(sc->sc_dev,
+ "timeout waiting for capture DMA reset\n");
+ EBDMA_C_WRITE(sc, EBDMA_DCSR, sc->sc_burst);
}
static void
cs4231_power_reset(struct cs4231_softc *sc, int how)
{
-u_int32_t v;
-int i;
+ u_int32_t v;
+ int i;
-if ((sc->sc_flags & CS4231_SBUS) != 0) {
-APC_WRITE(sc, APC_CSR, APC_CSR_RESET);
-DELAY(10);
-APC_WRITE(sc, APC_CSR, 0);
-DELAY(10);
-APC_WRITE(sc,
-APC_CSR, APC_READ(sc, APC_CSR) | APC_CSR_CODEC_RESET);
-DELAY(20);
-APC_WRITE(sc,
-APC_CSR, APC_READ(sc, APC_CSR) & (~APC_CSR_CODEC_RESET));
-} else {
-v = AUXIO_READ(sc, AUXIO_CODEC);
-if (how == CODEC_WARM_RESET && v != 0) {
-AUXIO_WRITE(sc, AUXIO_CODEC, 0);
-DELAY(20);
-} else if (how == CODEC_COLD_RESET){
-AUXIO_WRITE(sc, AUXIO_CODEC, 1);
-DELAY(20);
-AUXIO_WRITE(sc, AUXIO_CODEC, 0);
-DELAY(20);
-}
-cs4231_ebdma_reset(sc);
-}
-
-for (i = CS_TIMEOUT;
-i && CS_READ(sc, CS4231_IADDR) == CS_IN_INIT; i--)
-DELAY(10);
-if (i == 0)
-device_printf(sc->sc_dev, "timeout waiting for resetn");
-
-/* turn on cs4231 mode */
-cs4231_write(sc, CS_MISC_INFO,
-cs4231_read(sc, CS_MISC_INFO) | CS_MODE2);
-/* enable interupts & clear CSR */
-cs4231_write(sc, CS_PIN_CONTROL,
-cs4231_read(sc, CS_PIN_CONTROL) | INTERRUPT_ENABLE);
-CS_WRITE(sc, CS4231_STATUS, 0);
-/* enable DAC output */
-cs4231_write(sc, CS_LEFT_OUTPUT_CONTROL,
-cs4231_read(sc, CS_LEFT_OUTPUT_CONTROL) & ~OUTPUT_MUTE);
-cs4231_write(sc, CS_RIGHT_OUTPUT_CONTROL,
-cs4231_read(sc, CS_RIGHT_OUTPUT_CONTROL) & ~OUTPUT_MUTE);
-/* mute AUX1 since it generates noises */
-cs4231_write(sc, CS_LEFT_AUX1_CONTROL,
-cs4231_read(sc, CS_LEFT_AUX1_CONTROL) | AUX_INPUT_MUTE);
-cs4231_write(sc, CS_RIGHT_AUX1_CONTROL,
-cs4231_read(sc, CS_RIGHT_AUX1_CONTROL) | AUX_INPUT_MUTE);
-/* protect buffer underrun and set output level to 0dB */
-cs4231_write(sc, CS_ALT_FEATURE1,
-cs4231_read(sc, CS_ALT_FEATURE1) | CS_DAC_ZERO | CS_OUTPUT_LVL);
-/* enable high pass filter, dual xtal was disabled due to noises */
-cs4231_write(sc, CS_ALT_FEATURE2,
-cs4231_read(sc, CS_ALT_FEATURE2) | CS_HPF_ENABLE);
+ if ((sc->sc_flags & CS4231_SBUS) != 0) {
+ APC_WRITE(sc, APC_CSR, APC_CSR_RESET);
+ DELAY(10);
+ APC_WRITE(sc, APC_CSR, 0);
+ DELAY(10);
+ APC_WRITE(sc,
+ APC_CSR, APC_READ(sc, APC_CSR) | APC_CSR_CODEC_RESET);
+ DELAY(20);
+ APC_WRITE(sc,
+ APC_CSR, APC_READ(sc, APC_CSR) & (~APC_CSR_CODEC_RESET));
+ } else {
+ v = AUXIO_READ(sc, AUXIO_CODEC);
+ if (how == CODEC_WARM_RESET && v != 0) {
+ AUXIO_WRITE(sc, AUXIO_CODEC, 0);
+ DELAY(20);
+ } else if (how == CODEC_COLD_RESET){
+ AUXIO_WRITE(sc, AUXIO_CODEC, 1);
+ DELAY(20);
+ AUXIO_WRITE(sc, AUXIO_CODEC, 0);
+ DELAY(20);
+ }
+ cs4231_ebdma_reset(sc);
+ }
+
+ for (i = CS_TIMEOUT;
+ i && CS_READ(sc, CS4231_IADDR) == CS_IN_INIT; i--)
+ DELAY(10);
+ if (i == 0)
+ device_printf(sc->sc_dev, "timeout waiting for reset\n");
+
+ /* turn on cs4231 mode */
+ cs4231_write(sc, CS_MISC_INFO,
+ cs4231_read(sc, CS_MISC_INFO) | CS_MODE2);
+ /* enable interupts & clear CSR */
+ cs4231_write(sc, CS_PIN_CONTROL,
+ cs4231_read(sc, CS_PIN_CONTROL) | INTERRUPT_ENABLE);
+ CS_WRITE(sc, CS4231_STATUS, 0);
+ /* enable DAC output */
+ cs4231_write(sc, CS_LEFT_OUTPUT_CONTROL,
+ cs4231_read(sc, CS_LEFT_OUTPUT_CONTROL) & ~OUTPUT_MUTE);
+ cs4231_write(sc, CS_RIGHT_OUTPUT_CONTROL,
+ cs4231_read(sc, CS_RIGHT_OUTPUT_CONTROL) & ~OUTPUT_MUTE);
+ /* mute AUX1 since it generates noises */
+ cs4231_write(sc, CS_LEFT_AUX1_CONTROL,
+ cs4231_read(sc, CS_LEFT_AUX1_CONTROL) | AUX_INPUT_MUTE);
+ cs4231_write(sc, CS_RIGHT_AUX1_CONTROL,
+ cs4231_read(sc, CS_RIGHT_AUX1_CONTROL) | AUX_INPUT_MUTE);
+ /* protect buffer underrun and set output level to 0dB */
+ cs4231_write(sc, CS_ALT_FEATURE1,
+ cs4231_read(sc, CS_ALT_FEATURE1) | CS_DAC_ZERO | CS_OUTPUT_LVL);
+ /* enable high pass filter, dual xtal was disabled due to noises */
+ cs4231_write(sc, CS_ALT_FEATURE2,
+ cs4231_read(sc, CS_ALT_FEATURE2) | CS_HPF_ENABLE);
}
static int
cs4231_enable(struct cs4231_softc *sc, int how)
{
-cs4231_power_reset(sc, how);
-sc->sc_enabled = 1;
-return (0);
+ cs4231_power_reset(sc, how);
+ sc->sc_enabled = 1;
+ return (0);
}
static void
cs4231_disable(struct cs4231_softc *sc)
{
-u_int8_t v;
+ u_int8_t v;
-CS4231_LOCK_ASSERT(sc);
+ CS4231_LOCK_ASSERT(sc);
-if (sc->sc_enabled == 0)
-return;
-sc->sc_enabled = 0;
-CS4231_UNLOCK(sc);
-cs4231_halt(&sc->sc_pch);
-cs4231_halt(&sc->sc_rch);
-CS4231_LOCK(sc);
-v = cs4231_read(sc, CS_PIN_CONTROL) & ~INTERRUPT_ENABLE;
-cs4231_write(sc, CS_PIN_CONTROL, v);
-
-if ((sc->sc_flags & CS4231_SBUS) != 0) {
-APC_WRITE(sc, APC_CSR, APC_CSR_RESET);
-DELAY(10);
-APC_WRITE(sc, APC_CSR, 0);
-DELAY(10);
-} else
-cs4231_ebdma_reset(sc);
+ if (sc->sc_enabled == 0)
+ return;
+ sc->sc_enabled = 0;
+ CS4231_UNLOCK(sc);
+ cs4231_halt(&sc->sc_pch);
+ cs4231_halt(&sc->sc_rch);
+ CS4231_LOCK(sc);
+ v = cs4231_read(sc, CS_PIN_CONTROL) & ~INTERRUPT_ENABLE;
+ cs4231_write(sc, CS_PIN_CONTROL, v);
+
+ if ((sc->sc_flags & CS4231_SBUS) != 0) {
+ APC_WRITE(sc, APC_CSR, APC_CSR_RESET);
+ DELAY(10);
+ APC_WRITE(sc, APC_CSR, 0);
+ DELAY(10);
+ } else
+ cs4231_ebdma_reset(sc);
}
static void
cs4231_free_resource(struct cs4231_softc *sc)
{
-int i;
+ int i;
-CS4231_LOCK(sc);
-cs4231_disable(sc);
-CS4231_UNLOCK(sc);
-for (i = 0; i < sc->sc_nires; i++) {
-if (sc->sc_irqres[i]) {
-if (sc->sc_ih[i]) {
-bus_teardown_intr(sc->sc_dev, sc->sc_irqres[i],
-sc->sc_ih[i]);
-sc->sc_ih[i] = NULL;
-}
-bus_release_resource(sc->sc_dev, SYS_RES_IRQ,
-sc->sc_irqrid[i], sc->sc_irqres[i]);
-sc->sc_irqres[i] = NULL;
-}
-}
-for (i = 0; i < sc->sc_nires; i++) {
-if (sc->sc_dmat[i])
-bus_dma_tag_destroy(sc->sc_dmat[i]);
-}
-for (i = 0; i < sc->sc_nmres; i++) {
-if (sc->sc_res[i])
-bus_release_resource(sc->sc_dev, SYS_RES_MEMORY,
-sc->sc_rid[i], sc->sc_res[i]);
-}
-snd_mtxfree(sc->sc_lock);
-free(sc, M_DEVBUF);
+ CS4231_LOCK(sc);
+ cs4231_disable(sc);
+ CS4231_UNLOCK(sc);
+ for (i = 0; i < sc->sc_nires; i++) {
+ if (sc->sc_irqres[i]) {
+ if (sc->sc_ih[i]) {
+ bus_teardown_intr(sc->sc_dev, sc->sc_irqres[i],
+ sc->sc_ih[i]);
+ sc->sc_ih[i] = NULL;
+ }
+ bus_release_resource(sc->sc_dev, SYS_RES_IRQ,
+ sc->sc_irqrid[i], sc->sc_irqres[i]);
+ sc->sc_irqres[i] = NULL;
+ }
+ }
+ for (i = 0; i < sc->sc_nires; i++) {
+ if (sc->sc_dmat[i])
+ bus_dma_tag_destroy(sc->sc_dmat[i]);
+ }
+ for (i = 0; i < sc->sc_nmres; i++) {
+ if (sc->sc_res[i])
+ bus_release_resource(sc->sc_dev, SYS_RES_MEMORY,
+ sc->sc_rid[i], sc->sc_res[i]);
+ }
+ snd_mtxfree(sc->sc_lock);
+ free(sc, M_DEVBUF);
}
static void
cs4231_write(struct cs4231_softc *sc, u_int8_t r, u_int8_t v)
{
-CS_WRITE(sc, CS4231_IADDR, r);
-CS_WRITE(sc, CS4231_IDATA, v);
+ CS_WRITE(sc, CS4231_IADDR, r);
+ CS_WRITE(sc, CS4231_IDATA, v);
}
static u_int8_t
cs4231_read(struct cs4231_softc *sc, u_int8_t r)
{
-CS_WRITE(sc, CS4231_IADDR, r);
-return (CS_READ(sc, CS4231_IDATA));
+ CS_WRITE(sc, CS4231_IADDR, r);
+ return (CS_READ(sc, CS4231_IDATA));
}
static void
cs4231_sbus_intr(void *arg)
{
-struct cs4231_softc *sc;
-struct cs4231_channel *pch, *rch;
-u_int32_t csr;
-u_int8_t status;
-
-sc = arg;
-CS4231_LOCK(sc);
-
-csr = APC_READ(sc, APC_CSR);
-if ((csr & APC_CSR_GI) == 0) {
-CS4231_UNLOCK(sc);
-return;
-}
-APC_WRITE(sc, APC_CSR, csr);
-
-if ((csr & APC_CSR_EIE) && (csr & APC_CSR_EI)) {
-status = cs4231_read(sc, CS_TEST_AND_INIT);
-device_printf(sc->sc_dev,
-"apc error interrupt : stat = 0x%xn", status);
-}
-
-pch = rch = NULL;
-if ((csr & APC_CSR_PMIE) && (csr & APC_CSR_PMI)) {
-u_long nextaddr, saddr;
-u_int32_t togo;
-
-pch = &sc->sc_pch;
-togo = pch->togo;
-saddr = sndbuf_getbufaddr(pch->buffer);
-nextaddr = pch->nextaddr + togo;
-if (nextaddr >= saddr + sndbuf_getsize(pch->buffer))
-nextaddr = saddr;
-APC_WRITE(sc, APC_PNVA, nextaddr);
-APC_WRITE(sc, APC_PNC, togo);
-pch->nextaddr = nextaddr;
-}
-
-if ((csr & APC_CSR_CIE) && (csr & APC_CSR_CI) && (csr & APC_CSR_CD)) {
-u_long nextaddr, saddr;
-u_int32_t togo;
-
-rch = &sc->sc_rch;
-togo = rch->togo;
-saddr = sndbuf_getbufaddr(rch->buffer);
-nextaddr = rch->nextaddr + togo;
-if (nextaddr >= saddr + sndbuf_getsize(rch->buffer))
-nextaddr = saddr;
-APC_WRITE(sc, APC_CNVA, nextaddr);
-APC_WRITE(sc, APC_CNC, togo);
-rch->nextaddr = nextaddr;
-}
-CS4231_UNLOCK(sc);
-if (pch)
-chn_intr(pch->channel);
-if (rch)
-chn_intr(rch->channel);
+ struct cs4231_softc *sc;
+ struct cs4231_channel *pch, *rch;
+ u_int32_t csr;
+ u_int8_t status;
+
+ sc = arg;
+ CS4231_LOCK(sc);
+
+ csr = APC_READ(sc, APC_CSR);
+ if ((csr & APC_CSR_GI) == 0) {
+ CS4231_UNLOCK(sc);
+ return;
+ }
+ APC_WRITE(sc, APC_CSR, csr);
+
+ if ((csr & APC_CSR_EIE) && (csr & APC_CSR_EI)) {
+ status = cs4231_read(sc, CS_TEST_AND_INIT);
+ device_printf(sc->sc_dev,
+ "apc error interrupt : stat = 0x%x\n", status);
+ }
+
+ pch = rch = NULL;
+ if ((csr & APC_CSR_PMIE) && (csr & APC_CSR_PMI)) {
+ u_long nextaddr, saddr;
+ u_int32_t togo;
+
+ pch = &sc->sc_pch;
+ togo = pch->togo;
+ saddr = sndbuf_getbufaddr(pch->buffer);
+ nextaddr = pch->nextaddr + togo;
+ if (nextaddr >= saddr + sndbuf_getsize(pch->buffer))
+ nextaddr = saddr;
+ APC_WRITE(sc, APC_PNVA, nextaddr);
+ APC_WRITE(sc, APC_PNC, togo);
+ pch->nextaddr = nextaddr;
+ }
+
+ if ((csr & APC_CSR_CIE) && (csr & APC_CSR_CI) && (csr & APC_CSR_CD)) {
+ u_long nextaddr, saddr;
+ u_int32_t togo;
+
+ rch = &sc->sc_rch;
+ togo = rch->togo;
+ saddr = sndbuf_getbufaddr(rch->buffer);
+ nextaddr = rch->nextaddr + togo;
+ if (nextaddr >= saddr + sndbuf_getsize(rch->buffer))
+ nextaddr = saddr;
+ APC_WRITE(sc, APC_CNVA, nextaddr);
+ APC_WRITE(sc, APC_CNC, togo);
+ rch->nextaddr = nextaddr;
+ }
+ CS4231_UNLOCK(sc);
+ if (pch)
+ chn_intr(pch->channel);
+ if (rch)
+ chn_intr(rch->channel);
}
/* playback interrupt handler */
static void
cs4231_ebus_pintr(void *arg)
{
-struct cs4231_softc *sc;
-struct cs4231_channel *ch;
-u_int32_t csr;
-u_int8_t status;
-
-sc = arg;
-CS4231_LOCK(sc);
-
-csr = EBDMA_P_READ(sc, EBDMA_DCSR);
-if ((csr & EBDCSR_INT) == 0) {
-CS4231_UNLOCK(sc);
-return;
-}
-
-if ((csr & EBDCSR_ERR)) {
-status = cs4231_read(sc, CS_TEST_AND_INIT);
-device_printf(sc->sc_dev,
-"ebdma error interrupt : stat = 0x%xn", status);
-}
-EBDMA_P_WRITE(sc, EBDMA_DCSR, csr | EBDCSR_TC);
-
-ch = NULL;
-if (csr & EBDCSR_TC) {
-u_long nextaddr, saddr;
-u_int32_t togo;
-
-ch = &sc->sc_pch;
-togo = ch->togo;
-saddr = sndbuf_getbufaddr(ch->buffer);
-nextaddr = ch->nextaddr + togo;
-if (nextaddr >= saddr + sndbuf_getsize(ch->buffer))
-nextaddr = saddr;
-/*
-* EBDMA_DCNT is loaded automatically
-* EBDMA_P_WRITE(sc, EBDMA_DCNT, togo);
-*/
-EBDMA_P_WRITE(sc, EBDMA_DADDR, nextaddr);
-ch->nextaddr = nextaddr;
-}
-CS4231_UNLOCK(sc);
-if (ch)
-chn_intr(ch->channel);
+ struct cs4231_softc *sc;
+ struct cs4231_channel *ch;
+ u_int32_t csr;
+ u_int8_t status;
+
+ sc = arg;
+ CS4231_LOCK(sc);
+
+ csr = EBDMA_P_READ(sc, EBDMA_DCSR);
+ if ((csr & EBDCSR_INT) == 0) {
+ CS4231_UNLOCK(sc);
+ return;
+ }
+
+ if ((csr & EBDCSR_ERR)) {
+ status = cs4231_read(sc, CS_TEST_AND_INIT);
+ device_printf(sc->sc_dev,
+ "ebdma error interrupt : stat = 0x%x\n", status);
+ }
+ EBDMA_P_WRITE(sc, EBDMA_DCSR, csr | EBDCSR_TC);
+
+ ch = NULL;
+ if (csr & EBDCSR_TC) {
+ u_long nextaddr, saddr;
+ u_int32_t togo;
+
+ ch = &sc->sc_pch;
+ togo = ch->togo;
+ saddr = sndbuf_getbufaddr(ch->buffer);
+ nextaddr = ch->nextaddr + togo;
+ if (nextaddr >= saddr + sndbuf_getsize(ch->buffer))
+ nextaddr = saddr;
+ /*
+ * EBDMA_DCNT is loaded automatically
+ * EBDMA_P_WRITE(sc, EBDMA_DCNT, togo);
+ */
+ EBDMA_P_WRITE(sc, EBDMA_DADDR, nextaddr);
+ ch->nextaddr = nextaddr;
+ }
+ CS4231_UNLOCK(sc);
+ if (ch)
+ chn_intr(ch->channel);
}
/* capture interrupt handler */
static void
cs4231_ebus_cintr(void *arg)
{
-struct cs4231_softc *sc;
-struct cs4231_channel *ch;
-u_int32_t csr;
-u_int8_t status;
-
-sc = arg;
-CS4231_LOCK(sc);
-
-csr = EBDMA_C_READ(sc, EBDMA_DCSR);
-if ((csr & EBDCSR_INT) == 0) {
-CS4231_UNLOCK(sc);
-return;
-}
-if ((csr & EBDCSR_ERR)) {
-status = cs4231_read(sc, CS_TEST_AND_INIT);
-device_printf(sc->sc_dev,
-"dma error interrupt : stat = 0x%xn", status);
-}
-EBDMA_C_WRITE(sc, EBDMA_DCSR, csr | EBDCSR_TC);
-
-ch = NULL;
-if (csr & EBDCSR_TC) {
-u_long nextaddr, saddr;
-u_int32_t togo;
-
-ch = &sc->sc_rch;
-togo = ch->togo;
-saddr = sndbuf_getbufaddr(ch->buffer);
-nextaddr = ch->nextaddr + togo;
-if (nextaddr >= saddr + sndbuf_getblksz(ch->buffer))
-nextaddr = saddr;
-/*
-* EBDMA_DCNT is loaded automatically
-* EBDMA_C_WRITE(sc, EBDMA_DCNT, togo);
-*/
-EBDMA_C_WRITE(sc, EBDMA_DADDR, nextaddr);
-ch->nextaddr = nextaddr;
-}
-CS4231_UNLOCK(sc);
-if (ch)
-chn_intr(ch->channel);
+ struct cs4231_softc *sc;
+ struct cs4231_channel *ch;
+ u_int32_t csr;
+ u_int8_t status;
+
+ sc = arg;
+ CS4231_LOCK(sc);
+
+ csr = EBDMA_C_READ(sc, EBDMA_DCSR);
+ if ((csr & EBDCSR_INT) == 0) {
+ CS4231_UNLOCK(sc);
+ return;
+ }
+ if ((csr & EBDCSR_ERR)) {
+ status = cs4231_read(sc, CS_TEST_AND_INIT);
+ device_printf(sc->sc_dev,
+ "dma error interrupt : stat = 0x%x\n", status);
+ }
+ EBDMA_C_WRITE(sc, EBDMA_DCSR, csr | EBDCSR_TC);
+
+ ch = NULL;
+ if (csr & EBDCSR_TC) {
+ u_long nextaddr, saddr;
+ u_int32_t togo;
+
+ ch = &sc->sc_rch;
+ togo = ch->togo;
+ saddr = sndbuf_getbufaddr(ch->buffer);
+ nextaddr = ch->nextaddr + togo;
+ if (nextaddr >= saddr + sndbuf_getblksz(ch->buffer))
+ nextaddr = saddr;
+ /*
+ * EBDMA_DCNT is loaded automatically
+ * EBDMA_C_WRITE(sc, EBDMA_DCNT, togo);
+ */
+ EBDMA_C_WRITE(sc, EBDMA_DADDR, nextaddr);
+ ch->nextaddr = nextaddr;
+ }
+ CS4231_UNLOCK(sc);
+ if (ch)
+ chn_intr(ch->channel);
}
static const struct mix_table cs4231_mix_table[SOUND_MIXER_NRDEVICES][2] = {
-[SOUND_MIXER_PCM] = {
-{ CS_LEFT_OUTPUT_CONTROL, 6, OUTPUT_MUTE, 0, 1, 1, 0 },
-{ CS_RIGHT_OUTPUT_CONTROL, 6, OUTPUT_MUTE, 0, 1, 1, 0 }
-},
-[SOUND_MIXER_SPEAKER] = {
-{ CS_MONO_IO_CONTROL, 4, MONO_OUTPUT_MUTE, 0, 1, 1, 0 },
-{ CS_REG_NONE, 0, 0, 0, 0, 1, 0 }
-},
-[SOUND_MIXER_LINE] = {
-{ CS_LEFT_LINE_CONTROL, 5, LINE_INPUT_MUTE, 0, 1, 1, 1 },
-{ CS_RIGHT_LINE_CONTROL, 5, LINE_INPUT_MUTE, 0, 1, 1, 1 }
-},
-/*
-* AUX1 : removed intentionally since it generates noises
-* AUX2 : Ultra1/Ultra2 has no internal CD-ROM audio in
-*/
-[SOUND_MIXER_CD] = {
-{ CS_LEFT_AUX2_CONTROL, 5, LINE_INPUT_MUTE, 0, 1, 1, 1 },
-{ CS_RIGHT_AUX2_CONTROL, 5, LINE_INPUT_MUTE, 0, 1, 1, 1 }
-},
-[SOUND_MIXER_MIC] = {
-{ CS_LEFT_INPUT_CONTROL, 4, 0, 0, 0, 1, 1 },
-{ CS_RIGHT_INPUT_CONTROL, 4, 0, 0, 0, 1, 1 }
-},
-[SOUND_MIXER_IGAIN] = {
-{ CS_LEFT_INPUT_CONTROL, 4, 0, 0, 1, 0 },
-{ CS_RIGHT_INPUT_CONTROL, 4, 0, 0, 1, 0 }
-}
+ [SOUND_MIXER_PCM] = {
+ { CS_LEFT_OUTPUT_CONTROL, 6, OUTPUT_MUTE, 0, 1, 1, 0 },
+ { CS_RIGHT_OUTPUT_CONTROL, 6, OUTPUT_MUTE, 0, 1, 1, 0 }
+ },
+ [SOUND_MIXER_SPEAKER] = {
+ { CS_MONO_IO_CONTROL, 4, MONO_OUTPUT_MUTE, 0, 1, 1, 0 },
+ { CS_REG_NONE, 0, 0, 0, 0, 1, 0 }
+ },
+ [SOUND_MIXER_LINE] = {
+ { CS_LEFT_LINE_CONTROL, 5, LINE_INPUT_MUTE, 0, 1, 1, 1 },
+ { CS_RIGHT_LINE_CONTROL, 5, LINE_INPUT_MUTE, 0, 1, 1, 1 }
+ },
+ /*
+ * AUX1 : removed intentionally since it generates noises
+ * AUX2 : Ultra1/Ultra2 has no internal CD-ROM audio in
+ */
+ [SOUND_MIXER_CD] = {
+ { CS_LEFT_AUX2_CONTROL, 5, LINE_INPUT_MUTE, 0, 1, 1, 1 },
+ { CS_RIGHT_AUX2_CONTROL, 5, LINE_INPUT_MUTE, 0, 1, 1, 1 }
+ },
+ [SOUND_MIXER_MIC] = {
+ { CS_LEFT_INPUT_CONTROL, 4, 0, 0, 0, 1, 1 },
+ { CS_RIGHT_INPUT_CONTROL, 4, 0, 0, 0, 1, 1 }
+ },
+ [SOUND_MIXER_IGAIN] = {
+ { CS_LEFT_INPUT_CONTROL, 4, 0, 0, 1, 0 },
+ { CS_RIGHT_INPUT_CONTROL, 4, 0, 0, 1, 0 }
+ }
};
static int
cs4231_mixer_init(struct snd_mixer *m)
{
-u_int32_t v;
-int i;
+ u_int32_t v;
+ int i;
-v = 0;
-for (i = 0; i < SOUND_MIXER_NRDEVICES; i++)
-if (cs4231_mix_table[i][0].avail != 0)
-v |= (1 << i);
-mix_setdevs(m, v);
-v = 0;
-for (i = 0; i < SOUND_MIXER_NRDEVICES; i++)
-if (cs4231_mix_table[i][0].recdev != 0)
-v |= (1 << i);
-mix_setrecdevs(m, v);
-return (0);
+ v = 0;
+ for (i = 0; i < SOUND_MIXER_NRDEVICES; i++)
+ if (cs4231_mix_table[i][0].avail != 0)
+ v |= (1 << i);
+ mix_setdevs(m, v);
+ v = 0;
+ for (i = 0; i < SOUND_MIXER_NRDEVICES; i++)
+ if (cs4231_mix_table[i][0].recdev != 0)
+ v |= (1 << i);
+ mix_setrecdevs(m, v);
+ return (0);
}
static void
cs4231_mixer_set_value(struct cs4231_softc *sc, const struct mix_table *mt,
-u_int8_t v)
+ u_int8_t v)
{
-u_int8_t mask, reg;
-u_int8_t old, shift, val;
+ u_int8_t mask, reg;
+ u_int8_t old, shift, val;
-if (mt->avail == 0 || mt->reg == CS_REG_NONE)
-return;
-reg = mt->reg;
-if (mt->neg != 0)
-val = 100 - v;
-else
-val = v;
-mask = (1 << mt->bits) - 1;
-val = ((val * mask) + 50) / 100;
-shift = mt->shift;
-val <<= shift;
-if (v == 0)
-val |= mt->mute;
-old = cs4231_read(sc, reg);
-old &= ~(mt->mute | (mask << shift));
-val |= old;
-if (reg == CS_LEFT_INPUT_CONTROL || reg == CS_RIGHT_INPUT_CONTROL) {
-if ((val & (mask << shift)) != 0)
-val |= ADC_INPUT_GAIN_ENABLE;
-else
-val &= ~ADC_INPUT_GAIN_ENABLE;
-}
-cs4231_write(sc, reg, val);
+ if (mt->avail == 0 || mt->reg == CS_REG_NONE)
+ return;
+ reg = mt->reg;
+ if (mt->neg != 0)
+ val = 100 - v;
+ else
+ val = v;
+ mask = (1 << mt->bits) - 1;
+ val = ((val * mask) + 50) / 100;
+ shift = mt->shift;
+ val <<= shift;
+ if (v == 0)
+ val |= mt->mute;
+ old = cs4231_read(sc, reg);
+ old &= ~(mt->mute | (mask << shift));
+ val |= old;
+ if (reg == CS_LEFT_INPUT_CONTROL || reg == CS_RIGHT_INPUT_CONTROL) {
+ if ((val & (mask << shift)) != 0)
+ val |= ADC_INPUT_GAIN_ENABLE;
+ else
+ val &= ~ADC_INPUT_GAIN_ENABLE;
+ }
+ cs4231_write(sc, reg, val);
}
static int
cs4231_mixer_set(struct snd_mixer *m, u_int32_t dev, u_int32_t left,
-u_int32_t right)
+ u_int32_t right)
{
-struct cs4231_softc *sc;
+ struct cs4231_softc *sc;
-sc = mix_getdevinfo(m);
-CS4231_LOCK(sc);
-cs4231_mixer_set_value(sc, &cs4231_mix_table[dev][0], left);
-cs4231_mixer_set_value(sc, &cs4231_mix_table[dev][1], right);
-CS4231_UNLOCK(sc);
+ sc = mix_getdevinfo(m);
+ CS4231_LOCK(sc);
+ cs4231_mixer_set_value(sc, &cs4231_mix_table[dev][0], left);
+ cs4231_mixer_set_value(sc, &cs4231_mix_table[dev][1], right);
+ CS4231_UNLOCK(sc);
-return (left | (right << 8));
+ return (left | (right << 8));
}
static int
cs4231_mixer_setrecsrc(struct snd_mixer *m, u_int32_t src)
{
-struct cs4231_softc *sc;
-u_int8_t v;
+ struct cs4231_softc *sc;
+ u_int8_t v;
-sc = mix_getdevinfo(m);
-switch (src) {
-case SOUND_MASK_LINE:
-v = CS_IN_LINE;
-break;
-
-case SOUND_MASK_CD:
-v = CS_IN_DAC;
-break;
-
-case SOUND_MASK_MIC:
-default:
-v = CS_IN_MIC;
-src = SOUND_MASK_MIC;
-break;
-}
-CS4231_LOCK(sc);
-cs4231_write(sc, CS_LEFT_INPUT_CONTROL,
-(cs4231_read(sc, CS_LEFT_INPUT_CONTROL) & CS_IN_MASK) | v);
-cs4231_write(sc, CS_RIGHT_INPUT_CONTROL,
-(cs4231_read(sc, CS_RIGHT_INPUT_CONTROL) & CS_IN_MASK) | v);
-CS4231_UNLOCK(sc);
+ sc = mix_getdevinfo(m);
+ switch (src) {
+ case SOUND_MASK_LINE:
+ v = CS_IN_LINE;
+ break;
+
+ case SOUND_MASK_CD:
+ v = CS_IN_DAC;
+ break;
+
+ case SOUND_MASK_MIC:
+ default:
+ v = CS_IN_MIC;
+ src = SOUND_MASK_MIC;
+ break;
+ }
+ CS4231_LOCK(sc);
+ cs4231_write(sc, CS_LEFT_INPUT_CONTROL,
+ (cs4231_read(sc, CS_LEFT_INPUT_CONTROL) & CS_IN_MASK) | v);
+ cs4231_write(sc, CS_RIGHT_INPUT_CONTROL,
+ (cs4231_read(sc, CS_RIGHT_INPUT_CONTROL) & CS_IN_MASK) | v);
+ CS4231_UNLOCK(sc);
-return (src);
+ return (src);
}
static void *
cs4231_chan_init(kobj_t obj, void *dev, struct snd_dbuf *b,
-struct pcm_channel *c, int dir)
+ struct pcm_channel *c, int dir)
{
-struct cs4231_softc *sc;
-struct cs4231_channel *ch;
-bus_dma_tag_t dmat;
-
-sc = dev;
-ch = (dir == PCMDIR_PLAY) ? &sc->sc_pch : &sc->sc_rch;
-ch->parent = sc;
-ch->channel = c;
-ch->dir = dir;
-ch->buffer = b;
-if ((sc->sc_flags & CS4231_SBUS) != 0)
-dmat = sc->sc_dmat[0];
-else {
-if (dir == PCMDIR_PLAY)
-dmat = sc->sc_dmat[1];
-else
-dmat = sc->sc_dmat[0];
-}
-if (sndbuf_alloc(ch->buffer, dmat, sc->sc_bufsz) != 0)
-return (NULL);
-DPRINTF(("%s channel addr: 0x%lxn", dir == PCMDIR_PLAY ? "playback" :
-"capture", sndbuf_getbufaddr(ch->buffer)));
+ struct cs4231_softc *sc;
+ struct cs4231_channel *ch;
+ bus_dma_tag_t dmat;
+
+ sc = dev;
+ ch = (dir == PCMDIR_PLAY) ? &sc->sc_pch : &sc->sc_rch;
+ ch->parent = sc;
+ ch->channel = c;
+ ch->dir = dir;
+ ch->buffer = b;
+ if ((sc->sc_flags & CS4231_SBUS) != 0)
+ dmat = sc->sc_dmat[0];
+ else {
+ if (dir == PCMDIR_PLAY)
+ dmat = sc->sc_dmat[1];
+ else
+ dmat = sc->sc_dmat[0];
+ }
+ if (sndbuf_alloc(ch->buffer, dmat, 0, sc->sc_bufsz) != 0)
+ return (NULL);
+ DPRINTF(("%s channel addr: 0x%lx\n", dir == PCMDIR_PLAY ? "playback" :
+ "capture", sndbuf_getbufaddr(ch->buffer)));
-return (ch);
+ return (ch);
}
static int
cs4231_chan_setformat(kobj_t obj, void *data, u_int32_t format)
{
-struct cs4231_softc *sc;
-struct cs4231_channel *ch;
-u_int32_t encoding;
-u_int8_t fs, v;
-
-ch = data;
-sc = ch->parent;
-
-CS4231_LOCK(sc);
-if (ch->format == format) {
-CS4231_UNLOCK(sc);
-return (0);
-}
-
-encoding = format & ~AFMT_STEREO;
-fs = 0;
-switch (encoding) {
-case AFMT_U8:
-fs = CS_AFMT_U8;
-break;
-case AFMT_MU_LAW:
-fs = CS_AFMT_MU_LAW;
-break;
-case AFMT_S16_LE:
-fs = CS_AFMT_S16_LE;
-break;
-case AFMT_A_LAW:
-fs = CS_AFMT_A_LAW;
-break;
-case AFMT_IMA_ADPCM:
-fs = CS_AFMT_IMA_ADPCM;
-break;
-case AFMT_S16_BE:
-fs = CS_AFMT_S16_BE;
-break;
-default:
-fs = CS_AFMT_U8;
-format = AFMT_U8;
-break;
-}
-
-if (format & AFMT_STEREO)
-fs |= CS_AFMT_STEREO;
-
-DPRINTF(("FORMAT: %s : 0x%xn", ch->dir == PCMDIR_PLAY ? "playback" :
-"capture", format));
-v = cs4231_read(sc, CS_CLOCK_DATA_FORMAT);
-v &= CS_CLOCK_DATA_FORMAT_MASK;
-fs |= v;
-cs4231_chan_fs(sc, ch->dir, fs);
-ch->format = format;
-CS4231_UNLOCK(sc);
+ struct cs4231_softc *sc;
+ struct cs4231_channel *ch;
+ u_int32_t encoding;
+ u_int8_t fs, v;
+
+ ch = data;
+ sc = ch->parent;
+
+ CS4231_LOCK(sc);
+ if (ch->format == format) {
+ CS4231_UNLOCK(sc);
+ return (0);
+ }
+
+ encoding = format & ~AFMT_STEREO;
+ fs = 0;
+ switch (encoding) {
+ case AFMT_U8:
+ fs = CS_AFMT_U8;
+ break;
+ case AFMT_MU_LAW:
+ fs = CS_AFMT_MU_LAW;
+ break;
+ case AFMT_S16_LE:
+ fs = CS_AFMT_S16_LE;
+ break;
+ case AFMT_A_LAW:
+ fs = CS_AFMT_A_LAW;
+ break;
+ case AFMT_IMA_ADPCM:
+ fs = CS_AFMT_IMA_ADPCM;
+ break;
+ case AFMT_S16_BE:
+ fs = CS_AFMT_S16_BE;
+ break;
+ default:
+ fs = CS_AFMT_U8;
+ format = AFMT_U8;
+ break;
+ }
+
+ if (format & AFMT_STEREO)
+ fs |= CS_AFMT_STEREO;
+
+ DPRINTF(("FORMAT: %s : 0x%x\n", ch->dir == PCMDIR_PLAY ? "playback" :
+ "capture", format));
+ v = cs4231_read(sc, CS_CLOCK_DATA_FORMAT);
+ v &= CS_CLOCK_DATA_FORMAT_MASK;
+ fs |= v;
+ cs4231_chan_fs(sc, ch->dir, fs);
+ ch->format = format;
+ CS4231_UNLOCK(sc);
-return (0);
+ return (0);
}
static int
cs4231_chan_setspeed(kobj_t obj, void *data, u_int32_t speed)
{
-typedef struct {
-u_int32_t speed;
-u_int8_t bits;
-} speed_struct;
-
-const static speed_struct speed_table[] = {
-{5510, (0 << 1) | CLOCK_XTAL2},
-{5510, (0 << 1) | CLOCK_XTAL2},
-{6620, (7 << 1) | CLOCK_XTAL2},
-{8000, (0 << 1) | CLOCK_XTAL1},
-{9600, (7 << 1) | CLOCK_XTAL1},
-{11025, (1 << 1) | CLOCK_XTAL2},
-{16000, (1 << 1) | CLOCK_XTAL1},
-{18900, (2 << 1) | CLOCK_XTAL2},
-{22050, (3 << 1) | CLOCK_XTAL2},
-{27420, (2 << 1) | CLOCK_XTAL1},
-{32000, (3 << 1) | CLOCK_XTAL1},
-{33075, (6 << 1) | CLOCK_XTAL2},
-{33075, (4 << 1) | CLOCK_XTAL2},
-{44100, (5 << 1) | CLOCK_XTAL2},
-{48000, (6 << 1) | CLOCK_XTAL1},
-};
-
-struct cs4231_softc *sc;
-struct cs4231_channel *ch;
-int i, n, sel;
-u_int8_t fs;
-
-ch = data;
-sc = ch->parent;
-CS4231_LOCK(sc);
-if (ch->speed == speed) {
-CS4231_UNLOCK(sc);
-return (speed);
-}
-n = sizeof(speed_table) / sizeof(speed_struct);
-
-for (i = 1, sel =0; i < n - 1; i++)
-if (abs(speed - speed_table[i].speed) <
-abs(speed - speed_table[sel].speed))
-sel = i;
-DPRINTF(("SPEED: %s : %dHz -> %dHzn", ch->dir == PCMDIR_PLAY ?
-"playback" : "capture", speed, speed_table[sel].speed));
-speed = speed_table[sel].speed;
-
-fs = cs4231_read(sc, CS_CLOCK_DATA_FORMAT);
-fs &= ~CS_CLOCK_DATA_FORMAT_MASK;
-fs |= speed_table[sel].bits;
-cs4231_chan_fs(sc, ch->dir, fs);
-ch->speed = speed;
-CS4231_UNLOCK(sc);
+ typedef struct {
+ u_int32_t speed;
+ u_int8_t bits;
+ } speed_struct;
+
+ const static speed_struct speed_table[] = {
+ {5510, (0 << 1) | CLOCK_XTAL2},
+ {5510, (0 << 1) | CLOCK_XTAL2},
+ {6620, (7 << 1) | CLOCK_XTAL2},
+ {8000, (0 << 1) | CLOCK_XTAL1},
+ {9600, (7 << 1) | CLOCK_XTAL1},
+ {11025, (1 << 1) | CLOCK_XTAL2},
+ {16000, (1 << 1) | CLOCK_XTAL1},
+ {18900, (2 << 1) | CLOCK_XTAL2},
+ {22050, (3 << 1) | CLOCK_XTAL2},
+ {27420, (2 << 1) | CLOCK_XTAL1},
+ {32000, (3 << 1) | CLOCK_XTAL1},
+ {33075, (6 << 1) | CLOCK_XTAL2},
+ {33075, (4 << 1) | CLOCK_XTAL2},
+ {44100, (5 << 1) | CLOCK_XTAL2},
+ {48000, (6 << 1) | CLOCK_XTAL1},
+ };
+
+ struct cs4231_softc *sc;
+ struct cs4231_channel *ch;
+ int i, n, sel;
+ u_int8_t fs;
+
+ ch = data;
+ sc = ch->parent;
+ CS4231_LOCK(sc);
+ if (ch->speed == speed) {
+ CS4231_UNLOCK(sc);
+ return (speed);
+ }
+ n = sizeof(speed_table) / sizeof(speed_struct);
+
+ for (i = 1, sel =0; i < n - 1; i++)
+ if (abs(speed - speed_table[i].speed) <
+ abs(speed - speed_table[sel].speed))
+ sel = i;
+ DPRINTF(("SPEED: %s : %dHz -> %dHz\n", ch->dir == PCMDIR_PLAY ?
+ "playback" : "capture", speed, speed_table[sel].speed));
+ speed = speed_table[sel].speed;
+
+ fs = cs4231_read(sc, CS_CLOCK_DATA_FORMAT);
+ fs &= ~CS_CLOCK_DATA_FORMAT_MASK;
+ fs |= speed_table[sel].bits;
+ cs4231_chan_fs(sc, ch->dir, fs);
+ ch->speed = speed;
+ CS4231_UNLOCK(sc);
-return (speed);
+ return (speed);
}
static void
cs4231_chan_fs(struct cs4231_softc *sc, int dir, u_int8_t fs)
{
-int i, doreset;
+ int i, doreset;
#ifdef CS4231_AUTO_CALIBRATION
-u_int8_t v;
+ u_int8_t v;
#endif
-CS4231_LOCK_ASSERT(sc);
+ CS4231_LOCK_ASSERT(sc);
-/* set autocalibration */
-doreset = 0;
+ /* set autocalibration */
+ doreset = 0;
#ifdef CS4231_AUTO_CALIBRATION
-v = cs4231_read(sc, CS_INTERFACE_CONFIG) | AUTO_CAL_ENABLE;
-CS_WRITE(sc, CS4231_IADDR, MODE_CHANGE_ENABLE);
-CS_WRITE(sc, CS4231_IADDR, MODE_CHANGE_ENABLE | CS_INTERFACE_CONFIG);
-CS_WRITE(sc, CS4231_IDATA, v);
+ v = cs4231_read(sc, CS_INTERFACE_CONFIG) | AUTO_CAL_ENABLE;
+ CS_WRITE(sc, CS4231_IADDR, MODE_CHANGE_ENABLE);
+ CS_WRITE(sc, CS4231_IADDR, MODE_CHANGE_ENABLE | CS_INTERFACE_CONFIG);
+ CS_WRITE(sc, CS4231_IDATA, v);
#endif
-/*
-* We always need to write CS_CLOCK_DATA_FORMAT register since
-* the clock frequency is shared with playback/capture.
-*/
-CS_WRITE(sc, CS4231_IADDR, MODE_CHANGE_ENABLE | CS_CLOCK_DATA_FORMAT);
-CS_WRITE(sc, CS4231_IDATA, fs);
-CS_READ(sc, CS4231_IDATA);
-CS_READ(sc, CS4231_IDATA);
-for (i = CS_TIMEOUT;
-i && CS_READ(sc, CS4231_IADDR) == CS_IN_INIT; i--)
-DELAY(10);
-if (i == 0) {
-device_printf(sc->sc_dev, "timeout setting playback speedn");
-doreset++;
-}
-
-/*
-* capture channel
-* cs4231 doesn't allow seperate fs setup for playback/capture.
-* I believe this will break full-duplex operation.
-*/
-if (dir == PCMDIR_REC) {
-CS_WRITE(sc, CS4231_IADDR, MODE_CHANGE_ENABLE | CS_REC_FORMAT);
-CS_WRITE(sc, CS4231_IDATA, fs);
-CS_READ(sc, CS4231_IDATA);
-CS_READ(sc, CS4231_IDATA);
-for (i = CS_TIMEOUT;
-i && CS_READ(sc, CS4231_IADDR) == CS_IN_INIT; i--)
-DELAY(10);
-if (i == 0) {
-device_printf(sc->sc_dev,
-"timeout setting capture formatn");
-doreset++;
-}
-}
-
-CS_WRITE(sc, CS4231_IADDR, 0);
-for (i = CS_TIMEOUT;
-i && CS_READ(sc, CS4231_IADDR) == CS_IN_INIT; i--)
-DELAY(10);
-if (i == 0) {
-device_printf(sc->sc_dev, "timeout waiting for !MCEn");
-doreset++;
-}
+ /*
+ * We always need to write CS_CLOCK_DATA_FORMAT register since
+ * the clock frequency is shared with playback/capture.
+ */
+ CS_WRITE(sc, CS4231_IADDR, MODE_CHANGE_ENABLE | CS_CLOCK_DATA_FORMAT);
+ CS_WRITE(sc, CS4231_IDATA, fs);
+ CS_READ(sc, CS4231_IDATA);
+ CS_READ(sc, CS4231_IDATA);
+ for (i = CS_TIMEOUT;
+ i && CS_READ(sc, CS4231_IADDR) == CS_IN_INIT; i--)
+ DELAY(10);
+ if (i == 0) {
+ device_printf(sc->sc_dev, "timeout setting playback speed\n");
+ doreset++;
+ }
+
+ /*
+ * capture channel
+ * cs4231 doesn't allow seperate fs setup for playback/capture.
+ * I believe this will break full-duplex operation.
+ */
+ if (dir == PCMDIR_REC) {
+ CS_WRITE(sc, CS4231_IADDR, MODE_CHANGE_ENABLE | CS_REC_FORMAT);
+ CS_WRITE(sc, CS4231_IDATA, fs);
+ CS_READ(sc, CS4231_IDATA);
+ CS_READ(sc, CS4231_IDATA);
+ for (i = CS_TIMEOUT;
+ i && CS_READ(sc, CS4231_IADDR) == CS_IN_INIT; i--)
+ DELAY(10);
+ if (i == 0) {
+ device_printf(sc->sc_dev,
+ "timeout setting capture format\n");
+ doreset++;
+ }
+ }
+
+ CS_WRITE(sc, CS4231_IADDR, 0);
+ for (i = CS_TIMEOUT;
+ i && CS_READ(sc, CS4231_IADDR) == CS_IN_INIT; i--)
+ DELAY(10);
+ if (i == 0) {
+ device_printf(sc->sc_dev, "timeout waiting for !MCE\n");
+ doreset++;
+ }
#ifdef CS4231_AUTO_CALIBRATION
-CS_WRITE(sc, CS4231_IADDR, CS_TEST_AND_INIT);
-for (i = CS_TIMEOUT;
-i && CS_READ(sc, CS4231_IDATA) & AUTO_CAL_IN_PROG; i--)
-DELAY(10);
-if (i == 0) {
-device_printf(sc->sc_dev,
-"timeout waiting for autocalibrationn");
-doreset++;
-}
+ CS_WRITE(sc, CS4231_IADDR, CS_TEST_AND_INIT);
+ for (i = CS_TIMEOUT;
+ i && CS_READ(sc, CS4231_IDATA) & AUTO_CAL_IN_PROG; i--)
+ DELAY(10);
+ if (i == 0) {
+ device_printf(sc->sc_dev,
+ "timeout waiting for autocalibration\n");
+ doreset++;
+ }
#endif
-if (doreset) {
-/*
-* Maybe the last resort to avoid a dreadful message like
-* "pcm0:play:0: play interrupt timeout, channel dead" would
-* be hardware reset.
-*/
-device_printf(sc->sc_dev, "trying to hardware resetn");
-cs4231_disable(sc);
-cs4231_enable(sc, CODEC_COLD_RESET);
-CS4231_UNLOCK(sc); /* XXX */
-if (mixer_reinit(sc->sc_dev) != 0)
-device_printf(sc->sc_dev,
-"unable to reinitialize the mixern");
-CS4231_LOCK(sc);
-}
+ if (doreset) {
+ /*
+ * Maybe the last resort to avoid a dreadful message like
+ * "pcm0:play:0: play interrupt timeout, channel dead" would
+ * be hardware reset.
+ */
+ device_printf(sc->sc_dev, "trying to hardware reset\n");
+ cs4231_disable(sc);
+ cs4231_enable(sc, CODEC_COLD_RESET);
+ CS4231_UNLOCK(sc); /* XXX */
+ if (mixer_reinit(sc->sc_dev) != 0)
+ device_printf(sc->sc_dev,
+ "unable to reinitialize the mixer\n");
+ CS4231_LOCK(sc);
+ }
}
static int
cs4231_chan_setblocksize(kobj_t obj, void *data, u_int32_t blocksize)
{
-struct cs4231_softc *sc;
-struct cs4231_channel *ch;
-int nblks, error;
-
-ch = data;
-sc = ch->parent;
-
-if (blocksize > CS4231_MAX_BLK_SZ)
-blocksize = CS4231_MAX_BLK_SZ;
-nblks = sc->sc_bufsz / blocksize;
-error = sndbuf_resize(ch->buffer, nblks, blocksize);
-if (error != 0)
-device_printf(sc->sc_dev,
-"unable to block size, blksz = %d, error = %dn",
-blocksize, error);
+ struct cs4231_softc *sc;
+ struct cs4231_channel *ch;
+ int nblks, error;
+
+ ch = data;
+ sc = ch->parent;
+
+ if (blocksize > CS4231_MAX_BLK_SZ)
+ blocksize = CS4231_MAX_BLK_SZ;
+ nblks = sc->sc_bufsz / blocksize;
+ error = sndbuf_resize(ch->buffer, nblks, blocksize);
+ if (error != 0)
+ device_printf(sc->sc_dev,
+ "unable to block size, blksz = %d, error = %d\n",
+ blocksize, error);
-return (blocksize);
+ return (blocksize);
}
static int
cs4231_chan_trigger(kobj_t obj, void *data, int go)
{
-struct cs4231_channel *ch;
+ struct cs4231_channel *ch;
-ch = data;
-switch (go) {
-case PCMTRIG_EMLDMAWR:
-case PCMTRIG_EMLDMARD:
-break;
-case PCMTRIG_START:
-cs4231_trigger(ch);
-break;
-case PCMTRIG_ABORT:
-case PCMTRIG_STOP:
-cs4231_halt(ch);
-break;
-default:
-break;
-}
+ ch = data;
+ switch (go) {
+ case PCMTRIG_EMLDMAWR:
+ case PCMTRIG_EMLDMARD:
+ break;
+ case PCMTRIG_START:
+ cs4231_trigger(ch);
+ break;
+ case PCMTRIG_ABORT:
+ case PCMTRIG_STOP:
+ cs4231_halt(ch);
+ break;
+ default:
+ break;
+ }
-return (0);
+ return (0);
}
static int
cs4231_chan_getptr(kobj_t obj, void *data)
{
-struct cs4231_softc *sc;
-struct cs4231_channel *ch;
-u_int32_t cur;
-int ptr, sz;
-
-ch = data;
-sc = ch->parent;
-
-CS4231_LOCK(sc);
-if ((sc->sc_flags & CS4231_SBUS) != 0)
-cur = (ch->dir == PCMDIR_PLAY) ? APC_READ(sc, APC_PVA) :
-APC_READ(sc, APC_CVA);
-else
-cur = (ch->dir == PCMDIR_PLAY) ? EBDMA_P_READ(sc, EBDMA_DADDR) :
-EBDMA_C_READ(sc, EBDMA_DADDR);
-sz = sndbuf_getsize(ch->buffer);
-ptr = cur - sndbuf_getbufaddr(ch->buffer) + sz;
-CS4231_UNLOCK(sc);
+ struct cs4231_softc *sc;
+ struct cs4231_channel *ch;
+ u_int32_t cur;
+ int ptr, sz;
+
+ ch = data;
+ sc = ch->parent;
+
+ CS4231_LOCK(sc);
+ if ((sc->sc_flags & CS4231_SBUS) != 0)
+ cur = (ch->dir == PCMDIR_PLAY) ? APC_READ(sc, APC_PVA) :
+ APC_READ(sc, APC_CVA);
+ else
+ cur = (ch->dir == PCMDIR_PLAY) ? EBDMA_P_READ(sc, EBDMA_DADDR) :
+ EBDMA_C_READ(sc, EBDMA_DADDR);
+ sz = sndbuf_getsize(ch->buffer);
+ ptr = cur - sndbuf_getbufaddr(ch->buffer) + sz;
+ CS4231_UNLOCK(sc);
-ptr %= sz;
-return (ptr);
+ ptr %= sz;
+ return (ptr);
}
static struct pcmchan_caps *
cs4231_chan_getcaps(kobj_t obj, void *data)
{
-return (&cs4231_caps);
+ return (&cs4231_caps);
}
static void
cs4231_trigger(struct cs4231_channel *ch)
{
-struct cs4231_softc *sc;
+ struct cs4231_softc *sc;
-sc = ch->parent;
-if ((sc->sc_flags & CS4231_SBUS) != 0)
-cs4231_apcdma_trigger(sc, ch);
-else
-cs4231_ebdma_trigger(sc, ch);
+ sc = ch->parent;
+ if ((sc->sc_flags & CS4231_SBUS) != 0)
+ cs4231_apcdma_trigger(sc, ch);
+ else
+ cs4231_ebdma_trigger(sc, ch);
}
static void
cs4231_apcdma_trigger(struct cs4231_softc *sc, struct cs4231_channel *ch)
{
-u_int32_t csr, togo;
-u_int32_t nextaddr;
+ u_int32_t csr, togo;
+ u_int32_t nextaddr;
-CS4231_LOCK(sc);
-if (ch->locked) {
-device_printf(sc->sc_dev, "%s channel already triggeredn",
-ch->dir == PCMDIR_PLAY ? "playback" : "capture");
-CS4231_UNLOCK(sc);
-return;
-}
-
-nextaddr = sndbuf_getbufaddr(ch->buffer);
-togo = sndbuf_getsize(ch->buffer) / 2;
-if (togo > CS4231_MAX_APC_DMA_SZ)
-togo = CS4231_MAX_APC_DMA_SZ;
-ch->togo = togo;
-if (ch->dir == PCMDIR_PLAY) {
-DPRINTF(("TRG: PNVA = 0x%x, togo = 0x%xn", nextaddr, togo));
-
-cs4231_read(sc, CS_TEST_AND_INIT); /* clear pending error */
-csr = APC_READ(sc, APC_CSR);
-APC_WRITE(sc, APC_PNVA, nextaddr);
-APC_WRITE(sc, APC_PNC, togo);
-
-if ((csr & APC_CSR_PDMA_GO) == 0 ||
-(csr & APC_CSR_PPAUSE) != 0) {
-APC_WRITE(sc, APC_CSR, APC_READ(sc, APC_CSR) &
-~(APC_CSR_PIE | APC_CSR_PPAUSE));
-APC_WRITE(sc, APC_CSR, APC_READ(sc, APC_CSR) |
-APC_CSR_GIE | APC_CSR_PIE | APC_CSR_EIE |
-APC_CSR_EI | APC_CSR_PMIE | APC_CSR_PDMA_GO);
-cs4231_write(sc, CS_INTERFACE_CONFIG,
-cs4231_read(sc, CS_INTERFACE_CONFIG) |
-PLAYBACK_ENABLE);
-}
-/* load next address */
-if (APC_READ(sc, APC_CSR) & APC_CSR_PD) {
-nextaddr += togo;
-APC_WRITE(sc, APC_PNVA, nextaddr);
-APC_WRITE(sc, APC_PNC, togo);
-}
-} else {
-DPRINTF(("TRG: CNVA = 0x%x, togo = 0x%xn", nextaddr, togo));
-
-cs4231_read(sc, CS_TEST_AND_INIT); /* clear pending error */
-APC_WRITE(sc, APC_CNVA, nextaddr);
-APC_WRITE(sc, APC_CNC, togo);
-csr = APC_READ(sc, APC_CSR);
-if ((csr & APC_CSR_CDMA_GO) == 0 ||
-(csr & APC_CSR_CPAUSE) != 0) {
-csr &= APC_CSR_CPAUSE;
-csr |= APC_CSR_GIE | APC_CSR_CMIE | APC_CSR_CIE |
-APC_CSR_EI | APC_CSR_CDMA_GO;
-APC_WRITE(sc, APC_CSR, csr);
-cs4231_write(sc, CS_INTERFACE_CONFIG,
-cs4231_read(sc, CS_INTERFACE_CONFIG) |
-CAPTURE_ENABLE);
-}
-/* load next address */
-if (APC_READ(sc, APC_CSR) & APC_CSR_CD) {
-nextaddr += togo;
-APC_WRITE(sc, APC_CNVA, nextaddr);
-APC_WRITE(sc, APC_CNC, togo);
-}
-}
-ch->nextaddr = nextaddr;
-ch->locked = 1;
-CS4231_UNLOCK(sc);
+ CS4231_LOCK(sc);
+ if (ch->locked) {
+ device_printf(sc->sc_dev, "%s channel already triggered\n",
+ ch->dir == PCMDIR_PLAY ? "playback" : "capture");
+ CS4231_UNLOCK(sc);
+ return;
+ }
+
+ nextaddr = sndbuf_getbufaddr(ch->buffer);
+ togo = sndbuf_getsize(ch->buffer) / 2;
+ if (togo > CS4231_MAX_APC_DMA_SZ)
+ togo = CS4231_MAX_APC_DMA_SZ;
+ ch->togo = togo;
+ if (ch->dir == PCMDIR_PLAY) {
+ DPRINTF(("TRG: PNVA = 0x%x, togo = 0x%x\n", nextaddr, togo));
+
+ cs4231_read(sc, CS_TEST_AND_INIT); /* clear pending error */
+ csr = APC_READ(sc, APC_CSR);
+ APC_WRITE(sc, APC_PNVA, nextaddr);
+ APC_WRITE(sc, APC_PNC, togo);
+
+ if ((csr & APC_CSR_PDMA_GO) == 0 ||
+ (csr & APC_CSR_PPAUSE) != 0) {
+ APC_WRITE(sc, APC_CSR, APC_READ(sc, APC_CSR) &
+ ~(APC_CSR_PIE | APC_CSR_PPAUSE));
+ APC_WRITE(sc, APC_CSR, APC_READ(sc, APC_CSR) |
+ APC_CSR_GIE | APC_CSR_PIE | APC_CSR_EIE |
+ APC_CSR_EI | APC_CSR_PMIE | APC_CSR_PDMA_GO);
+ cs4231_write(sc, CS_INTERFACE_CONFIG,
+ cs4231_read(sc, CS_INTERFACE_CONFIG) |
+ PLAYBACK_ENABLE);
+ }
+ /* load next address */
+ if (APC_READ(sc, APC_CSR) & APC_CSR_PD) {
+ nextaddr += togo;
+ APC_WRITE(sc, APC_PNVA, nextaddr);
+ APC_WRITE(sc, APC_PNC, togo);
+ }
+ } else {
+ DPRINTF(("TRG: CNVA = 0x%x, togo = 0x%x\n", nextaddr, togo));
+
+ cs4231_read(sc, CS_TEST_AND_INIT); /* clear pending error */
+ APC_WRITE(sc, APC_CNVA, nextaddr);
+ APC_WRITE(sc, APC_CNC, togo);
+ csr = APC_READ(sc, APC_CSR);
+ if ((csr & APC_CSR_CDMA_GO) == 0 ||
+ (csr & APC_CSR_CPAUSE) != 0) {
+ csr &= APC_CSR_CPAUSE;
+ csr |= APC_CSR_GIE | APC_CSR_CMIE | APC_CSR_CIE |
+ APC_CSR_EI | APC_CSR_CDMA_GO;
+ APC_WRITE(sc, APC_CSR, csr);
+ cs4231_write(sc, CS_INTERFACE_CONFIG,
+ cs4231_read(sc, CS_INTERFACE_CONFIG) |
+ CAPTURE_ENABLE);
+ }
+ /* load next address */
+ if (APC_READ(sc, APC_CSR) & APC_CSR_CD) {
+ nextaddr += togo;
+ APC_WRITE(sc, APC_CNVA, nextaddr);
+ APC_WRITE(sc, APC_CNC, togo);
+ }
+ }
+ ch->nextaddr = nextaddr;
+ ch->locked = 1;
+ CS4231_UNLOCK(sc);
}
static void
cs4231_ebdma_trigger(struct cs4231_softc *sc, struct cs4231_channel *ch)
{
-u_int32_t csr, togo;
-u_int32_t nextaddr;
+ u_int32_t csr, togo;
+ u_int32_t nextaddr;
-CS4231_LOCK(sc);
-if (ch->locked) {
-device_printf(sc->sc_dev, "%s channel already triggeredn",
-ch->dir == PCMDIR_PLAY ? "playback" : "capture");
-CS4231_UNLOCK(sc);
-return;
-}
-
-nextaddr = sndbuf_getbufaddr(ch->buffer);
-togo = sndbuf_getsize(ch->buffer) / 2;
-if (togo % 64 == 0)
-sc->sc_burst = EBDCSR_BURST_16;
-else if (togo % 32 == 0)
-sc->sc_burst = EBDCSR_BURST_8;
-else if (togo % 16 == 0)
-sc->sc_burst = EBDCSR_BURST_4;
-else
-sc->sc_burst = EBDCSR_BURST_1;
-ch->togo = togo;
-DPRINTF(("TRG: DNAR = 0x%x, togo = 0x%xn", nextaddr, togo));
-if (ch->dir == PCMDIR_PLAY) {
-cs4231_read(sc, CS_TEST_AND_INIT); /* clear pending error */
-csr = EBDMA_P_READ(sc, EBDMA_DCSR);
-
-if (csr & EBDCSR_DMAEN) {
-EBDMA_P_WRITE(sc, EBDMA_DCNT, togo);
-EBDMA_P_WRITE(sc, EBDMA_DADDR, nextaddr);
-} else {
-EBDMA_P_WRITE(sc, EBDMA_DCSR, EBDCSR_RESET);
-EBDMA_P_WRITE(sc, EBDMA_DCSR, sc->sc_burst);
-EBDMA_P_WRITE(sc, EBDMA_DCNT, togo);
-EBDMA_P_WRITE(sc, EBDMA_DADDR, nextaddr);
-
-EBDMA_P_WRITE(sc, EBDMA_DCSR, sc->sc_burst |
-EBDCSR_DMAEN | EBDCSR_INTEN | EBDCSR_CNTEN |
-EBDCSR_NEXTEN);
-cs4231_write(sc, CS_INTERFACE_CONFIG,
-cs4231_read(sc, CS_INTERFACE_CONFIG) |
-PLAYBACK_ENABLE);
-}
-/* load next address */
-if (EBDMA_P_READ(sc, EBDMA_DCSR) & EBDCSR_A_LOADED) {
-nextaddr += togo;
-EBDMA_P_WRITE(sc, EBDMA_DCNT, togo);
-EBDMA_P_WRITE(sc, EBDMA_DADDR, nextaddr);
-}
-} else {
-cs4231_read(sc, CS_TEST_AND_INIT); /* clear pending error */
-csr = EBDMA_C_READ(sc, EBDMA_DCSR);
-
-if (csr & EBDCSR_DMAEN) {
-EBDMA_C_WRITE(sc, EBDMA_DCNT, togo);
-EBDMA_C_WRITE(sc, EBDMA_DADDR, nextaddr);
-} else {
-EBDMA_C_WRITE(sc, EBDMA_DCSR, EBDCSR_RESET);
-EBDMA_C_WRITE(sc, EBDMA_DCSR, sc->sc_burst);
-EBDMA_C_WRITE(sc, EBDMA_DCNT, togo);
-EBDMA_C_WRITE(sc, EBDMA_DADDR, nextaddr);
-
-EBDMA_C_WRITE(sc, EBDMA_DCSR, sc->sc_burst |
-EBDCSR_WRITE | EBDCSR_DMAEN | EBDCSR_INTEN |
-EBDCSR_CNTEN | EBDCSR_NEXTEN);
-cs4231_write(sc, CS_INTERFACE_CONFIG,
-cs4231_read(sc, CS_INTERFACE_CONFIG) |
-CAPTURE_ENABLE);
-}
-/* load next address */
-if (EBDMA_C_READ(sc, EBDMA_DCSR) & EBDCSR_A_LOADED) {
-nextaddr += togo;
-EBDMA_C_WRITE(sc, EBDMA_DCNT, togo);
-EBDMA_C_WRITE(sc, EBDMA_DADDR, nextaddr);
-}
-}
-ch->nextaddr = nextaddr;
-ch->locked = 1;
-CS4231_UNLOCK(sc);
+ CS4231_LOCK(sc);
+ if (ch->locked) {
+ device_printf(sc->sc_dev, "%s channel already triggered\n",
+ ch->dir == PCMDIR_PLAY ? "playback" : "capture");
+ CS4231_UNLOCK(sc);
+ return;
+ }
+
+ nextaddr = sndbuf_getbufaddr(ch->buffer);
+ togo = sndbuf_getsize(ch->buffer) / 2;
+ if (togo % 64 == 0)
+ sc->sc_burst = EBDCSR_BURST_16;
+ else if (togo % 32 == 0)
+ sc->sc_burst = EBDCSR_BURST_8;
+ else if (togo % 16 == 0)
+ sc->sc_burst = EBDCSR_BURST_4;
+ else
+ sc->sc_burst = EBDCSR_BURST_1;
+ ch->togo = togo;
+ DPRINTF(("TRG: DNAR = 0x%x, togo = 0x%x\n", nextaddr, togo));
+ if (ch->dir == PCMDIR_PLAY) {
+ cs4231_read(sc, CS_TEST_AND_INIT); /* clear pending error */
+ csr = EBDMA_P_READ(sc, EBDMA_DCSR);
+
+ if (csr & EBDCSR_DMAEN) {
+ EBDMA_P_WRITE(sc, EBDMA_DCNT, togo);
+ EBDMA_P_WRITE(sc, EBDMA_DADDR, nextaddr);
+ } else {
+ EBDMA_P_WRITE(sc, EBDMA_DCSR, EBDCSR_RESET);
+ EBDMA_P_WRITE(sc, EBDMA_DCSR, sc->sc_burst);
+ EBDMA_P_WRITE(sc, EBDMA_DCNT, togo);
+ EBDMA_P_WRITE(sc, EBDMA_DADDR, nextaddr);
+
+ EBDMA_P_WRITE(sc, EBDMA_DCSR, sc->sc_burst |
+ EBDCSR_DMAEN | EBDCSR_INTEN | EBDCSR_CNTEN |
+ EBDCSR_NEXTEN);
+ cs4231_write(sc, CS_INTERFACE_CONFIG,
+ cs4231_read(sc, CS_INTERFACE_CONFIG) |
+ PLAYBACK_ENABLE);
+ }
+ /* load next address */
+ if (EBDMA_P_READ(sc, EBDMA_DCSR) & EBDCSR_A_LOADED) {
+ nextaddr += togo;
+ EBDMA_P_WRITE(sc, EBDMA_DCNT, togo);
+ EBDMA_P_WRITE(sc, EBDMA_DADDR, nextaddr);
+ }
+ } else {
+ cs4231_read(sc, CS_TEST_AND_INIT); /* clear pending error */
+ csr = EBDMA_C_READ(sc, EBDMA_DCSR);
+
+ if (csr & EBDCSR_DMAEN) {
+ EBDMA_C_WRITE(sc, EBDMA_DCNT, togo);
+ EBDMA_C_WRITE(sc, EBDMA_DADDR, nextaddr);
+ } else {
+ EBDMA_C_WRITE(sc, EBDMA_DCSR, EBDCSR_RESET);
+ EBDMA_C_WRITE(sc, EBDMA_DCSR, sc->sc_burst);
+ EBDMA_C_WRITE(sc, EBDMA_DCNT, togo);
+ EBDMA_C_WRITE(sc, EBDMA_DADDR, nextaddr);
+
+ EBDMA_C_WRITE(sc, EBDMA_DCSR, sc->sc_burst |
+ EBDCSR_WRITE | EBDCSR_DMAEN | EBDCSR_INTEN |
+ EBDCSR_CNTEN | EBDCSR_NEXTEN);
+ cs4231_write(sc, CS_INTERFACE_CONFIG,
+ cs4231_read(sc, CS_INTERFACE_CONFIG) |
+ CAPTURE_ENABLE);
+ }
+ /* load next address */
+ if (EBDMA_C_READ(sc, EBDMA_DCSR) & EBDCSR_A_LOADED) {
+ nextaddr += togo;
+ EBDMA_C_WRITE(sc, EBDMA_DCNT, togo);
+ EBDMA_C_WRITE(sc, EBDMA_DADDR, nextaddr);
+ }
+ }
+ ch->nextaddr = nextaddr;
+ ch->locked = 1;
+ CS4231_UNLOCK(sc);
}
static void
cs4231_halt(struct cs4231_channel *ch)
{
-struct cs4231_softc *sc;
-u_int8_t status;
-int i;
-
-sc = ch->parent;
-CS4231_LOCK(sc);
-if (ch->locked == 0) {
-CS4231_UNLOCK(sc);
-return;
-}
-
-if (ch->dir == PCMDIR_PLAY ) {
-if ((sc->sc_flags & CS4231_SBUS) != 0) {
-/* XXX Kills some capture bits */
-APC_WRITE(sc, APC_CSR, APC_READ(sc, APC_CSR) &
-~(APC_CSR_EI | APC_CSR_GIE | APC_CSR_PIE |
-APC_CSR_EIE | APC_CSR_PDMA_GO | APC_CSR_PMIE));
-} else {
-EBDMA_P_WRITE(sc, EBDMA_DCSR,
-EBDMA_P_READ(sc, EBDMA_DCSR) & ~EBDCSR_DMAEN);
-}
-/* Waiting for playback FIFO to empty */
-status = cs4231_read(sc, CS_TEST_AND_INIT);
-for (i = CS_TIMEOUT;
-i && (status & PLAYBACK_UNDERRUN) == 0; i--) {
-DELAY(5);
-status = cs4231_read(sc, CS_TEST_AND_INIT);
-}
-if (i == 0)
-device_printf(sc->sc_dev, "timeout waiting for "
-"playback FIFO drainn");
-cs4231_write(sc, CS_INTERFACE_CONFIG,
-cs4231_read(sc, CS_INTERFACE_CONFIG) & (~PLAYBACK_ENABLE));
-} else {
-if ((sc->sc_flags & CS4231_SBUS) != 0) {
-/* XXX Kills some playback bits */
-APC_WRITE(sc, APC_CSR, APC_CSR_CAPTURE_PAUSE);
-} else {
-EBDMA_C_WRITE(sc, EBDMA_DCSR,
-EBDMA_C_READ(sc, EBDMA_DCSR) & ~EBDCSR_DMAEN);
-}
-/* Waiting for capture FIFO to empty */
-status = cs4231_read(sc, CS_TEST_AND_INIT);
-for (i = CS_TIMEOUT;
-i && (status & CAPTURE_OVERRUN) == 0; i--) {
-DELAY(5);
-status = cs4231_read(sc, CS_TEST_AND_INIT);
-}
-if (i == 0)
-device_printf(sc->sc_dev, "timeout waiting for "
-"capture FIFO drainn");
-cs4231_write(sc, CS_INTERFACE_CONFIG,
-cs4231_read(sc, CS_INTERFACE_CONFIG) & (~CAPTURE_ENABLE));
-}
-ch->locked = 0;
-CS4231_UNLOCK(sc);
+ struct cs4231_softc *sc;
+ u_int8_t status;
+ int i;
+
+ sc = ch->parent;
+ CS4231_LOCK(sc);
+ if (ch->locked == 0) {
+ CS4231_UNLOCK(sc);
+ return;
+ }
+
+ if (ch->dir == PCMDIR_PLAY ) {
+ if ((sc->sc_flags & CS4231_SBUS) != 0) {
+ /* XXX Kills some capture bits */
+ APC_WRITE(sc, APC_CSR, APC_READ(sc, APC_CSR) &
+ ~(APC_CSR_EI | APC_CSR_GIE | APC_CSR_PIE |
+ APC_CSR_EIE | APC_CSR_PDMA_GO | APC_CSR_PMIE));
+ } else {
+ EBDMA_P_WRITE(sc, EBDMA_DCSR,
+ EBDMA_P_READ(sc, EBDMA_DCSR) & ~EBDCSR_DMAEN);
+ }
+ /* Waiting for playback FIFO to empty */
+ status = cs4231_read(sc, CS_TEST_AND_INIT);
+ for (i = CS_TIMEOUT;
+ i && (status & PLAYBACK_UNDERRUN) == 0; i--) {
+ DELAY(5);
+ status = cs4231_read(sc, CS_TEST_AND_INIT);
+ }
+ if (i == 0)
+ device_printf(sc->sc_dev, "timeout waiting for "
+ "playback FIFO drain\n");
+ cs4231_write(sc, CS_INTERFACE_CONFIG,
+ cs4231_read(sc, CS_INTERFACE_CONFIG) & (~PLAYBACK_ENABLE));
+ } else {
+ if ((sc->sc_flags & CS4231_SBUS) != 0) {
+ /* XXX Kills some playback bits */
+ APC_WRITE(sc, APC_CSR, APC_CSR_CAPTURE_PAUSE);
+ } else {
+ EBDMA_C_WRITE(sc, EBDMA_DCSR,
+ EBDMA_C_READ(sc, EBDMA_DCSR) & ~EBDCSR_DMAEN);
+ }
+ /* Waiting for capture FIFO to empty */
+ status = cs4231_read(sc, CS_TEST_AND_INIT);
+ for (i = CS_TIMEOUT;
+ i && (status & CAPTURE_OVERRUN) == 0; i--) {
+ DELAY(5);
+ status = cs4231_read(sc, CS_TEST_AND_INIT);
+ }
+ if (i == 0)
+ device_printf(sc->sc_dev, "timeout waiting for "
+ "capture FIFO drain\n");
+ cs4231_write(sc, CS_INTERFACE_CONFIG,
+ cs4231_read(sc, CS_INTERFACE_CONFIG) & (~CAPTURE_ENABLE));
+ }
+ ch->locked = 0;
+ CS4231_UNLOCK(sc);
}
Index: cs4231.h
===================================================================
RCS file: /home/cvs/src/sys/dev/sound/sbus/cs4231.h,v
retrieving revision 1.2
retrieving revision 1.3
diff -L sys/dev/sound/sbus/cs4231.h -L sys/dev/sound/sbus/cs4231.h -u -r1.2 -r1.3
--- sys/dev/sound/sbus/cs4231.h
+++ sys/dev/sound/sbus/cs4231.h
@@ -1,87 +1,86 @@
-/* $MidnightBSD$ */
/* $FreeBSD: src/sys/dev/sound/sbus/cs4231.h,v 1.2 2005/01/06 01:43:22 imp Exp $ */
/*-
-* Copyright (c) 1996 The NetBSD Foundation, Inc.
-* All rights reserved.
-*
-* This code is derived from software contributed to The NetBSD Foundation
-* by Ken Hornstein and John Kohl.
-*
-* Redistribution and use in source and binary forms, with or without
-* modification, are permitted provided that the following conditions
-* are met:
-* 1. Redistributions of source code must retain the above copyright
-* notice, this list of conditions and the following disclaimer.
-* 2. Redistributions in binary form must reproduce the above copyright
-* notice, this list of conditions and the following disclaimer in the
-* documentation and/or other materials provided with the distribution.
-* 3. All advertising materials mentioning features or use of this software
-* must display the following acknowledgement:
-* This product includes software developed by the NetBSD
-* Foundation, Inc. and its contributors.
-* 4. Neither the name of The NetBSD Foundation nor the names of its
-* contributors may be used to endorse or promote products derived
-* from this software without specific prior written permission.
-*
-* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
-* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
-* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
-* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE
-* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-* POSSIBILITY OF SUCH DAMAGE.
-*/
+ * Copyright (c) 1996 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Ken Hornstein and John Kohl.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the NetBSD
+ * Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
/**
-* Register defs for Crystal Semiconductor CS4231 Audio Codec/mixer
-* chip, used on Gravis UltraSound MAX cards.
-*
-* Block diagram:
-* +----------------------------------------------------+
-* | |
-* | +----------------------------------------------+ |
-* | |mixed in +-+ | |
-* | +------------>--| | | |
-* | mic in | | | |
-* Mic --+-->| --------- GAIN ->-| | | |
-* | | AUX 1 in |M| | |
-* GF1 --)-->| -------------+-->-|U| | |
-* | | Line in | |X|---- GAIN ----------+ | |
-* Line --)-->| ---------+---)-->-| | | | |
-* | | | | | | | | |
-* | | | | +-+ ADC | |
-* | | | | | | |
-* | | | | | | |
-* | | | +--- L/M -- | | | AMP-->
-* | | | | | | |
-* | | | | | | |
-* | | +---- L/M -------O-->--+--------)-------+-|--+-> line
-* | | mono in /| | | |
-* +---|-->------------ L/M -----/ | | | |
-* | AUX 2 in | | | |
-* CD --------|-->------------ L/M -------+ L/M | |
-* | | v |
-* | | | |
-* | DAC | |
-* | | | |
-* +----------------------------------------------------+
-* | |
-* | |
-* v v
-* Pc BUS (DISK) ???
-*
-* Documentation for this chip can be found at:
-* http://www.cirrus.com/products/overviews/cs4231.html
-*/
+ * Register defs for Crystal Semiconductor CS4231 Audio Codec/mixer
+ * chip, used on Gravis UltraSound MAX cards.
+ *
+ * Block diagram:
+ * +----------------------------------------------------+
+ * | |
+ * | +----------------------------------------------+ |
+ * | |mixed in +-+ | |
+ * | +------------>--| | | |
+ * | mic in | | | |
+ * Mic --+-->| --------- GAIN ->-| | | |
+ * | | AUX 1 in |M| | |
+ * GF1 --)-->| -------------+-->-|U| | |
+ * | | Line in | |X|---- GAIN ----------+ | |
+ * Line --)-->| ---------+---)-->-| | | | |
+ * | | | | | | | | |
+ * | | | | +-+ ADC | |
+ * | | | | | | |
+ * | | | | | | |
+ * | | | +--- L/M --\ | | | AMP-->
+ * | | | \ | | | |
+ * | | | \ | | | |
+ * | | +---- L/M -------O-->--+--------)-------+-|--+-> line
+ * | | mono in /| | | |
+ * +---|-->------------ L/M -----/ | | | |
+ * | AUX 2 in | | | |
+ * CD --------|-->------------ L/M -------+ L/M | |
+ * | | v |
+ * | | | |
+ * | DAC | |
+ * | | | |
+ * +----------------------------------------------------+
+ * | |
+ * | |
+ * v v
+ * Pc BUS (DISK) ???
+ *
+ * Documentation for this chip can be found at:
+ * http://www.cirrus.com/products/overviews/cs4231.html
+ */
/*
-* This file was merged from two header files.(ad1848reg.h and cs4231reg.h)
-* And the suffix AD1848 and SP was changed to CS4231 and CS respectively.
-*/
+ * This file was merged from two header files.(ad1848reg.h and cs4231reg.h)
+ * And the suffix AD1848 and SP was changed to CS4231 and CS respectively.
+ */
/* CS4231 direct registers */
#define CS4231_IADDR 0x00
#define CS4231_IDATA 0x01
@@ -157,7 +156,7 @@
#define ADC_INPUT_GAIN_ENABLE 0x20
/* Aux input control - registers I2 (channel 1,left); I3 (channel 1,right)
-I4 (channel 2,left); I5 (channel 2,right) */
+ I4 (channel 2,left); I5 (channel 2,right) */
#define AUX_INPUT_ATTEN_BITS 0x1f
#define AUX_INPUT_ATTEN_MASK 0xe0
#define AUX_INPUT_MUTE 0x80
Index: apcdmareg.h
===================================================================
RCS file: /home/cvs/src/sys/dev/sound/sbus/apcdmareg.h,v
retrieving revision 1.2
retrieving revision 1.3
diff -L sys/dev/sound/sbus/apcdmareg.h -L sys/dev/sound/sbus/apcdmareg.h -u -r1.2 -r1.3
--- sys/dev/sound/sbus/apcdmareg.h
+++ sys/dev/sound/sbus/apcdmareg.h
@@ -1,36 +1,35 @@
-/* $MidnightBSD$ */
/* $FreeBSD: src/sys/dev/sound/sbus/apcdmareg.h,v 1.2 2005/01/06 01:43:22 imp Exp $ */
/* $OpenBSD: apcdmareg.h,v 1.2 2003/06/02 18:53:18 jason Exp $ */
/*-
-* Copyright (c) 2001 Jason L. Wright (jason at thought.net)
-* All rights reserved.
-*
-* Redistribution and use in source and binary forms, with or without
-* modification, are permitted provided that the following conditions
-* are met:
-* 1. Redistributions of source code must retain the above copyright
-* notice, this list of conditions and the following disclaimer.
-* 2. Redistributions in binary form must reproduce the above copyright
-* notice, this list of conditions and the following disclaimer in the
-* documentation and/or other materials provided with the distribution.
-*
-* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
-* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-* DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
-* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
-* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
-* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
-* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
-* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
-* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-* POSSIBILITY OF SUCH DAMAGE.
-*/
+ * Copyright (c) 2001 Jason L. Wright (jason at thought.net)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
/*
-* Definitions for Sun APC DMA controller.
-*/
+ * Definitions for Sun APC DMA controller.
+ */
/* APC DMA registers */
#define APC_CSR 0x0010 /* control/status */
@@ -44,8 +43,8 @@
#define APC_PNC 0x003c /* playback next count */
/*
-* APC DMA Register definitions
-*/
+ * APC DMA Register definitions
+ */
#define APC_CSR_RESET 0x00000001 /* reset */
#define APC_CSR_CDMA_GO 0x00000004 /* capture dma go */
#define APC_CSR_PDMA_GO 0x00000008 /* playback dma go */
@@ -69,12 +68,47 @@
#define APC_CSR_PI 0x00400000 /* playback interrupt */
#define APC_CSR_GI 0x00800000 /* general interrupt */
-#define APC_CSR_PLAY ( APC_CSR_EI | APC_CSR_GIE | APC_CSR_PIE | APC_CSR_EIE | APC_CSR_PDMA_GO | APC_CSR_PMIE )
-
-#define APC_CSR_CAPTURE ( APC_CSR_EI | APC_CSR_GIE | APC_CSR_CIE | APC_CSR_EIE | APC_CSR_CDMA_GO )
-
-#define APC_CSR_PLAY_PAUSE (~( APC_CSR_PPAUSE | APC_CSR_GI | APC_CSR_PI | APC_CSR_CI | APC_CSR_EI | APC_CSR_PMI | APC_CSR_PMIE | APC_CSR_CMI | APC_CSR_CMIE ) )
-
-#define APC_CSR_CAPTURE_PAUSE (~( APC_CSR_PPAUSE | APC_CSR_GI | APC_CSR_PI | APC_CSR_CI | APC_CSR_EI | APC_CSR_PMI | APC_CSR_PMIE | APC_CSR_CMI | APC_CSR_CMIE ) )
-
-#define APC_CSR_INTR_MASK ( APC_CSR_GI | APC_CSR_PI | APC_CSR_CI | APC_CSR_EI | APC_CSR_PMI | APC_CSR_CMI )
+#define APC_CSR_PLAY ( \
+ APC_CSR_EI | \
+ APC_CSR_GIE | \
+ APC_CSR_PIE | \
+ APC_CSR_EIE | \
+ APC_CSR_PDMA_GO | \
+ APC_CSR_PMIE )
+
+#define APC_CSR_CAPTURE ( \
+ APC_CSR_EI | \
+ APC_CSR_GIE | \
+ APC_CSR_CIE | \
+ APC_CSR_EIE | \
+ APC_CSR_CDMA_GO )
+
+#define APC_CSR_PLAY_PAUSE (~( \
+ APC_CSR_PPAUSE | \
+ APC_CSR_GI | \
+ APC_CSR_PI | \
+ APC_CSR_CI | \
+ APC_CSR_EI | \
+ APC_CSR_PMI | \
+ APC_CSR_PMIE | \
+ APC_CSR_CMI | \
+ APC_CSR_CMIE ) )
+
+#define APC_CSR_CAPTURE_PAUSE (~( \
+ APC_CSR_PPAUSE | \
+ APC_CSR_GI | \
+ APC_CSR_PI | \
+ APC_CSR_CI | \
+ APC_CSR_EI | \
+ APC_CSR_PMI | \
+ APC_CSR_PMIE | \
+ APC_CSR_CMI | \
+ APC_CSR_CMIE ) )
+
+#define APC_CSR_INTR_MASK ( \
+ APC_CSR_GI | \
+ APC_CSR_PI | \
+ APC_CSR_CI | \
+ APC_CSR_EI | \
+ APC_CSR_PMI | \
+ APC_CSR_CMI )
Index: uaudio_pcm.c
===================================================================
RCS file: /home/cvs/src/sys/dev/sound/usb/uaudio_pcm.c,v
retrieving revision 1.2
retrieving revision 1.3
diff -L sys/dev/sound/usb/uaudio_pcm.c -L sys/dev/sound/usb/uaudio_pcm.c -u -r1.2 -r1.3
--- sys/dev/sound/usb/uaudio_pcm.c
+++ sys/dev/sound/usb/uaudio_pcm.c
@@ -1,30 +1,29 @@
-/* $MidnightBSD$ */
-/* $FreeBSD: src/sys/dev/sound/usb/uaudio_pcm.c,v 1.15.2.1 2005/12/30 19:55:54 netchild Exp $ */
+/* $FreeBSD: src/sys/dev/sound/usb/uaudio_pcm.c,v 1.24 2007/06/17 06:10:43 ariff Exp $ */
/*-
-* Copyright (c) 2000-2002 Hiroyuki Aizu <aizu at navi.org>
-*
-* Redistribution and use in source and binary forms, with or without
-* modification, are permitted provided that the following conditions
-* are met:
-* 1. Redistributions of source code must retain the above copyright
-* notice, this list of conditions and the following disclaimer.
-* 2. Redistributions in binary form must reproduce the above copyright
-* notice, this list of conditions and the following disclaimer in the
-* documentation and/or other materials provided with the distribution.
-*
-* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
-* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
-* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
-* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
-* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
-* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
-* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
-* SUCH DAMAGE.
-*/
+ * Copyright (c) 2000-2002 Hiroyuki Aizu <aizu at navi.org>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
#include <sys/soundcard.h>
@@ -38,195 +37,233 @@
struct ua_info;
struct ua_chinfo {
-struct ua_info *parent;
-struct pcm_channel *channel;
-struct snd_dbuf *buffer;
-u_char *buf;
-int dir, hwch;
-u_int32_t fmt, spd, blksz; /* XXXXX */
+ struct ua_info *parent;
+ struct pcm_channel *channel;
+ struct snd_dbuf *buffer;
+ u_char *buf;
+ int dir, hwch;
+ u_int32_t fmt, spd, blksz; /* XXXXX */
};
struct ua_info {
-device_t sc_dev;
-u_int32_t bufsz;
-struct ua_chinfo pch, rch;
+ device_t sc_dev;
+ u_int32_t bufsz;
+ struct ua_chinfo pch, rch;
#define FORMAT_NUM 32
-u_int32_t ua_playfmt[FORMAT_NUM*2+1]; /* FORMAT_NUM format * (stereo or mono) + endptr */
-u_int32_t ua_recfmt[FORMAT_NUM*2+1]; /* FORMAT_NUM format * (stereo or mono) + endptr */
-struct pcmchan_caps ua_playcaps;
-struct pcmchan_caps ua_reccaps;
+ u_int32_t ua_playfmt[FORMAT_NUM*2+1]; /* FORMAT_NUM format * (stereo or mono) + endptr */
+ u_int32_t ua_recfmt[FORMAT_NUM*2+1]; /* FORMAT_NUM format * (stereo or mono) + endptr */
+ struct pcmchan_caps ua_playcaps;
+ struct pcmchan_caps ua_reccaps;
+ int vendor, product, release;
};
#define UAUDIO_DEFAULT_BUFSZ 16*1024
+static const struct {
+ int vendor;
+ int product;
+ int release;
+ uint32_t dflags;
+} ua_quirks[] = {
+ { 0x1130, 0xf211, 0x0101, SD_F_PSWAPLR },
+};
+
/************************************************************/
static void *
ua_chan_init(kobj_t obj, void *devinfo, struct snd_dbuf *b, struct pcm_channel *c, int dir)
{
-device_t pa_dev;
+ device_t pa_dev;
-struct ua_info *sc = devinfo;
-struct ua_chinfo *ch = (dir == PCMDIR_PLAY)? &sc->pch : &sc->rch;
+ struct ua_info *sc = devinfo;
+ struct ua_chinfo *ch = (dir == PCMDIR_PLAY)? &sc->pch : &sc->rch;
-ch->parent = sc;
-ch->channel = c;
-ch->buffer = b;
-ch->dir = dir;
-
-pa_dev = device_get_parent(sc->sc_dev);
-
-ch->buf = malloc(sc->bufsz, M_DEVBUF, M_NOWAIT);
-if (ch->buf == NULL)
-return NULL;
-if (sndbuf_setup(b, ch->buf, sc->bufsz) != 0) {
-free(ch->buf, M_DEVBUF);
-return NULL;
-}
-uaudio_chan_set_param_pcm_dma_buff(pa_dev, ch->buf, ch->buf+sc->bufsz, ch->channel, dir);
-if (bootverbose)
-device_printf(pa_dev, "%s buf %pn", (dir == PCMDIR_PLAY)?
-"play" : "rec", sndbuf_getbuf(ch->buffer));
+ ch->parent = sc;
+ ch->channel = c;
+ ch->buffer = b;
+ ch->dir = dir;
+
+ pa_dev = device_get_parent(sc->sc_dev);
+
+ ch->buf = malloc(sc->bufsz, M_DEVBUF, M_NOWAIT);
+ if (ch->buf == NULL)
+ return NULL;
+ if (sndbuf_setup(b, ch->buf, sc->bufsz) != 0) {
+ free(ch->buf, M_DEVBUF);
+ return NULL;
+ }
+ uaudio_chan_set_param_pcm_dma_buff(pa_dev, ch->buf, ch->buf+sc->bufsz, ch->channel, dir);
+ if (bootverbose)
+ device_printf(pa_dev, "%s buf %p\n", (dir == PCMDIR_PLAY)?
+ "play" : "rec", sndbuf_getbuf(ch->buffer));
-ch->dir = dir;
+ ch->dir = dir;
#ifndef NO_RECORDING
-ch->hwch = 1;
-if (dir == PCMDIR_PLAY)
-ch->hwch = 2;
+ ch->hwch = 1;
+ if (dir == PCMDIR_PLAY)
+ ch->hwch = 2;
#else
-ch->hwch = 2;
+ ch->hwch = 2;
#endif
-return ch;
+ return ch;
}
static int
ua_chan_free(kobj_t obj, void *data)
{
-struct ua_chinfo *ua = data;
+ struct ua_chinfo *ua = data;
-if (ua->buf != NULL)
-free(ua->buf, M_DEVBUF);
-return 0;
+ if (ua->buf != NULL)
+ free(ua->buf, M_DEVBUF);
+ return 0;
}
static int
ua_chan_setformat(kobj_t obj, void *data, u_int32_t format)
{
-device_t pa_dev;
-struct ua_info *ua;
+ device_t pa_dev;
+ struct ua_info *ua;
-struct ua_chinfo *ch = data;
+ struct ua_chinfo *ch = data;
-/*
-* At this point, no need to query as we shouldn't select an unsorted format
-*/
-ua = ch->parent;
-pa_dev = device_get_parent(ua->sc_dev);
-uaudio_chan_set_param_format(pa_dev, format, ch->dir);
+ /*
+ * At this point, no need to query as we shouldn't select an unsorted format
+ */
+ ua = ch->parent;
+ pa_dev = device_get_parent(ua->sc_dev);
+ uaudio_chan_set_param_format(pa_dev, format, ch->dir);
-ch->fmt = format;
-return 0;
+ ch->fmt = format;
+ return 0;
}
static int
ua_chan_setspeed(kobj_t obj, void *data, u_int32_t speed)
{
-struct ua_chinfo *ch;
-device_t pa_dev;
-int bestspeed;
+ struct ua_chinfo *ch;
+ device_t pa_dev;
+ int bestspeed;
-ch = data;
-pa_dev = device_get_parent(ch->parent->sc_dev);
+ ch = data;
+ pa_dev = device_get_parent(ch->parent->sc_dev);
-if ((bestspeed = uaudio_chan_set_param_speed(pa_dev, speed, ch->dir)))
-ch->spd = bestspeed;
+ if ((bestspeed = uaudio_chan_set_param_speed(pa_dev, speed, ch->dir)))
+ ch->spd = bestspeed;
-return ch->spd;
+ return ch->spd;
}
static int
-ua_chan_setblocksize(kobj_t obj, void *data, u_int32_t blocksize)
+ua_chan_setfragments(kobj_t obj, void *data, u_int32_t blksz, u_int32_t blkcnt)
{
-device_t pa_dev;
-struct ua_chinfo *ch = data;
-struct ua_info *ua = ch->parent;
+ device_t pa_dev;
+ struct ua_chinfo *ch = data;
+ struct ua_info *ua = ch->parent;
-if (blocksize) {
-RANGE(blocksize, 128, ua->bufsz / 2);
-if (sndbuf_resize(ch->buffer, ua->bufsz/blocksize, blocksize) != 0) {
-ch->blksz = blocksize;
-}
+ RANGE(blksz, 128, sndbuf_getmaxsize(ch->buffer) / 2);
+ RANGE(blkcnt, 2, 512);
+
+ while ((blksz * blkcnt) > sndbuf_getmaxsize(ch->buffer)) {
+ if ((blkcnt >> 1) >= 2)
+ blkcnt >>= 1;
+ else if ((blksz >> 1) >= 128)
+ blksz >>= 1;
+ else
+ break;
+ }
+
+ if ((sndbuf_getblksz(ch->buffer) != blksz ||
+ sndbuf_getblkcnt(ch->buffer) != blkcnt) &&
+ sndbuf_resize(ch->buffer, blkcnt, blksz) != 0)
+ device_printf(ua->sc_dev, "%s: failed blksz=%u blkcnt=%u\n",
+ __func__, blksz, blkcnt);
+
+ ch->blksz = sndbuf_getblksz(ch->buffer);
+
+ pa_dev = device_get_parent(ua->sc_dev);
+ uaudio_chan_set_param_pcm_dma_buff(pa_dev, ch->buf,
+ ch->buf + sndbuf_getsize(ch->buffer), ch->channel, ch->dir);
+ uaudio_chan_set_param_blocksize(pa_dev, ch->blksz, ch->dir);
+
+ return 1;
}
-pa_dev = device_get_parent(ua->sc_dev);
-uaudio_chan_set_param_blocksize(pa_dev, blocksize, ch->dir);
-return ch->blksz;
+static int
+ua_chan_setblocksize(kobj_t obj, void *data, u_int32_t blksz)
+{
+ struct ua_chinfo *ch = data;
+
+ ua_chan_setfragments(obj, data, blksz,
+ sndbuf_getmaxsize(ch->buffer) / blksz);
+
+ return ch->blksz;
}
static int
ua_chan_trigger(kobj_t obj, void *data, int go)
{
-device_t pa_dev;
-struct ua_info *ua;
-struct ua_chinfo *ch = data;
-
-if (go == PCMTRIG_EMLDMAWR || go == PCMTRIG_EMLDMARD)
-return 0;
-
-ua = ch->parent;
-pa_dev = device_get_parent(ua->sc_dev);
-
-/* XXXXX */
-if (ch->dir == PCMDIR_PLAY) {
-if (go == PCMTRIG_START) {
-uaudio_trigger_output(pa_dev);
-} else {
-uaudio_halt_out_dma(pa_dev);
-}
-} else {
+ device_t pa_dev;
+ struct ua_info *ua;
+ struct ua_chinfo *ch = data;
+
+ if (!PCMTRIG_COMMON(go))
+ return 0;
+
+ ua = ch->parent;
+ pa_dev = device_get_parent(ua->sc_dev);
+
+ /* XXXXX */
+ if (ch->dir == PCMDIR_PLAY) {
+ if (go == PCMTRIG_START) {
+ uaudio_trigger_output(pa_dev);
+ } else {
+ uaudio_halt_out_dma(pa_dev);
+ }
+ } else {
#ifndef NO_RECORDING
-if (go == PCMTRIG_START)
-uaudio_trigger_input(pa_dev);
-else
-uaudio_halt_in_dma(pa_dev);
+ if (go == PCMTRIG_START)
+ uaudio_trigger_input(pa_dev);
+ else
+ uaudio_halt_in_dma(pa_dev);
#endif
-}
+ }
-return 0;
+ return 0;
}
static int
ua_chan_getptr(kobj_t obj, void *data)
{
-device_t pa_dev;
-struct ua_info *ua;
-struct ua_chinfo *ch = data;
+ device_t pa_dev;
+ struct ua_info *ua;
+ struct ua_chinfo *ch = data;
-ua = ch->parent;
-pa_dev = device_get_parent(ua->sc_dev);
+ ua = ch->parent;
+ pa_dev = device_get_parent(ua->sc_dev);
-return uaudio_chan_getptr(pa_dev, ch->dir);
+ return uaudio_chan_getptr(pa_dev, ch->dir);
}
static struct pcmchan_caps *
ua_chan_getcaps(kobj_t obj, void *data)
{
-struct ua_chinfo *ch;
+ struct ua_chinfo *ch;
-ch = data;
-return (ch->dir == PCMDIR_PLAY) ? &(ch->parent->ua_playcaps) : &(ch->parent->ua_reccaps);
+ ch = data;
+ return (ch->dir == PCMDIR_PLAY) ? &(ch->parent->ua_playcaps) : &(ch->parent->ua_reccaps);
}
static kobj_method_t ua_chan_methods[] = {
-KOBJMETHOD(channel_init, ua_chan_init),
-KOBJMETHOD(channel_free, ua_chan_free),
-KOBJMETHOD(channel_setformat, ua_chan_setformat),
-KOBJMETHOD(channel_setspeed, ua_chan_setspeed),
-KOBJMETHOD(channel_setblocksize, ua_chan_setblocksize),
-KOBJMETHOD(channel_trigger, ua_chan_trigger),
-KOBJMETHOD(channel_getptr, ua_chan_getptr),
-KOBJMETHOD(channel_getcaps, ua_chan_getcaps),
-{ 0, 0 }
+ KOBJMETHOD(channel_init, ua_chan_init),
+ KOBJMETHOD(channel_free, ua_chan_free),
+ KOBJMETHOD(channel_setformat, ua_chan_setformat),
+ KOBJMETHOD(channel_setspeed, ua_chan_setspeed),
+ KOBJMETHOD(channel_setblocksize, ua_chan_setblocksize),
+ KOBJMETHOD(channel_setfragments, ua_chan_setfragments),
+ KOBJMETHOD(channel_trigger, ua_chan_trigger),
+ KOBJMETHOD(channel_getptr, ua_chan_getptr),
+ KOBJMETHOD(channel_getcaps, ua_chan_getcaps),
+ { 0, 0 }
};
CHANNEL_DECLARE(ua_chan);
@@ -235,66 +272,61 @@
static int
ua_mixer_init(struct snd_mixer *m)
{
-u_int32_t mask;
-device_t pa_dev;
-struct snddev_info *d;
-struct ua_info *ua = mix_getdevinfo(m);
-
-pa_dev = device_get_parent(ua->sc_dev);
-d = device_get_softc(ua->sc_dev);
-
-mask = uaudio_query_mix_info(pa_dev);
-if (d != NULL) {
-if (!(mask & SOUND_MASK_PCM)) {
-/*
-* Emulate missing pcm mixer controller
-* through FEEDER_VOLUME
-*/
-d->flags |= SD_F_SOFTPCMVOL;
-}
-if (!(mask & SOUND_MASK_VOLUME)) {
-mix_setparentchild(m, SOUND_MIXER_VOLUME,
-SOUND_MASK_PCM);
-mix_setrealdev(m, SOUND_MIXER_VOLUME,
-SOUND_MIXER_NONE);
-}
-}
-mix_setdevs(m, mask);
+ u_int32_t mask;
+ device_t pa_dev;
+ struct ua_info *ua = mix_getdevinfo(m);
+
+ pa_dev = device_get_parent(ua->sc_dev);
+
+ mask = uaudio_query_mix_info(pa_dev);
+ if (!(mask & SOUND_MASK_PCM)) {
+ /*
+ * Emulate missing pcm mixer controller
+ * through FEEDER_VOLUME
+ */
+ pcm_setflags(ua->sc_dev, pcm_getflags(ua->sc_dev) |
+ SD_F_SOFTPCMVOL);
+ }
+ if (!(mask & SOUND_MASK_VOLUME)) {
+ mix_setparentchild(m, SOUND_MIXER_VOLUME, SOUND_MASK_PCM);
+ mix_setrealdev(m, SOUND_MIXER_VOLUME, SOUND_MIXER_NONE);
+ }
+ mix_setdevs(m, mask);
-mask = uaudio_query_recsrc_info(pa_dev);
-mix_setrecdevs(m, mask);
+ mask = uaudio_query_recsrc_info(pa_dev);
+ mix_setrecdevs(m, mask);
-return 0;
+ return 0;
}
static int
ua_mixer_set(struct snd_mixer *m, unsigned type, unsigned left, unsigned right)
{
-device_t pa_dev;
-struct ua_info *ua = mix_getdevinfo(m);
+ device_t pa_dev;
+ struct ua_info *ua = mix_getdevinfo(m);
-pa_dev = device_get_parent(ua->sc_dev);
-uaudio_mixer_set(pa_dev, type, left, right);
+ pa_dev = device_get_parent(ua->sc_dev);
+ uaudio_mixer_set(pa_dev, type, left, right);
-return left | (right << 8);
+ return left | (right << 8);
}
static int
ua_mixer_setrecsrc(struct snd_mixer *m, u_int32_t src)
{
-device_t pa_dev;
-struct ua_info *ua = mix_getdevinfo(m);
+ device_t pa_dev;
+ struct ua_info *ua = mix_getdevinfo(m);
-pa_dev = device_get_parent(ua->sc_dev);
-return uaudio_mixer_setrecsrc(pa_dev, src);
+ pa_dev = device_get_parent(ua->sc_dev);
+ return uaudio_mixer_setrecsrc(pa_dev, src);
}
static kobj_method_t ua_mixer_methods[] = {
-KOBJMETHOD(mixer_init, ua_mixer_init),
-KOBJMETHOD(mixer_set, ua_mixer_set),
-KOBJMETHOD(mixer_setrecsrc, ua_mixer_setrecsrc),
+ KOBJMETHOD(mixer_init, ua_mixer_init),
+ KOBJMETHOD(mixer_set, ua_mixer_set),
+ KOBJMETHOD(mixer_setrecsrc, ua_mixer_setrecsrc),
-{ 0, 0 }
+ { 0, 0 }
};
MIXER_DECLARE(ua_mixer);
/************************************************************/
@@ -303,116 +335,143 @@
static int
ua_probe(device_t dev)
{
-char *s;
-struct sndcard_func *func;
+ char *s;
+ struct sndcard_func *func;
-/* The parent device has already been probed. */
+ /* The parent device has already been probed. */
-func = device_get_ivars(dev);
-if (func == NULL || func->func != SCF_PCM)
-return (ENXIO);
+ func = device_get_ivars(dev);
+ if (func == NULL || func->func != SCF_PCM)
+ return (ENXIO);
-s = "USB Audio";
+ s = "USB Audio";
-device_set_desc(dev, s);
-return BUS_PROBE_DEFAULT;
+ device_set_desc(dev, s);
+ return BUS_PROBE_DEFAULT;
}
static int
ua_attach(device_t dev)
{
-struct ua_info *ua;
-char status[SND_STATUSLEN];
-device_t pa_dev;
-u_int32_t nplay, nrec;
-int i;
-
-ua = (struct ua_info *)malloc(sizeof *ua, M_DEVBUF, M_ZERO | M_NOWAIT);
-if (ua == NULL)
-return ENXIO;
-
-ua->sc_dev = dev;
-
-pa_dev = device_get_parent(dev);
-
-ua->bufsz = pcm_getbuffersize(dev, 4096, UAUDIO_DEFAULT_BUFSZ, 65536);
-if (bootverbose)
-device_printf(dev, "using a default buffer size of %jdn", (intmax_t)ua->bufsz);
-
-if (mixer_init(dev, &ua_mixer_class, ua)) {
-goto bad;
-}
-
-snprintf(status, SND_STATUSLEN, "at ? %s", PCM_KLDSTRING(snd_uaudio));
-
-ua->ua_playcaps.fmtlist = ua->ua_playfmt;
-ua->ua_reccaps.fmtlist = ua->ua_recfmt;
-nplay = uaudio_query_formats(pa_dev, PCMDIR_PLAY, FORMAT_NUM * 2, &ua->ua_playcaps);
-nrec = uaudio_query_formats(pa_dev, PCMDIR_REC, FORMAT_NUM * 2, &ua->ua_reccaps);
-
-if (nplay > 1)
-nplay = 1;
-if (nrec > 1)
-nrec = 1;
+ struct ua_info *ua;
+ struct sndcard_func *func;
+ char status[SND_STATUSLEN];
+ device_t pa_dev;
+ u_int32_t nplay, nrec, flags;
+ int i;
+
+ ua = malloc(sizeof(*ua), M_DEVBUF, M_WAITOK | M_ZERO);
+ ua->sc_dev = dev;
+
+ /* Mark for existence */
+ func = device_get_ivars(dev);
+ if (func != NULL)
+ func->varinfo = (void *)ua;
+
+ pa_dev = device_get_parent(dev);
+ ua->vendor = uaudio_get_vendor(pa_dev);
+ ua->product = uaudio_get_product(pa_dev);
+ ua->release = uaudio_get_release(pa_dev);
+
+ if (bootverbose)
+ device_printf(dev,
+ "USB Audio: "
+ "vendor=0x%04x, product=0x%04x, release=0x%04x\n",
+ ua->vendor, ua->product, ua->release);
+
+ ua->bufsz = pcm_getbuffersize(dev, 4096, UAUDIO_DEFAULT_BUFSZ, 65536);
+ if (bootverbose)
+ device_printf(dev, "using a default buffer size of %jd\n", (intmax_t)ua->bufsz);
+
+ if (mixer_init(dev, &ua_mixer_class, ua)) {
+ goto bad;
+ }
+
+ snprintf(status, SND_STATUSLEN, "at ? %s", PCM_KLDSTRING(snd_uaudio));
+
+ ua->ua_playcaps.fmtlist = ua->ua_playfmt;
+ ua->ua_reccaps.fmtlist = ua->ua_recfmt;
+ nplay = uaudio_query_formats(pa_dev, PCMDIR_PLAY, FORMAT_NUM * 2, &ua->ua_playcaps);
+ nrec = uaudio_query_formats(pa_dev, PCMDIR_REC, FORMAT_NUM * 2, &ua->ua_reccaps);
+
+ if (nplay > 1)
+ nplay = 1;
+ if (nrec > 1)
+ nrec = 1;
+
+ flags = pcm_getflags(dev);
+ for (i = 0; i < (sizeof(ua_quirks) / sizeof(ua_quirks[0])); i++) {
+ if (ua->vendor == ua_quirks[i].vendor &&
+ ua->product == ua_quirks[i].product &&
+ ua->release == ua_quirks[i].release)
+ flags |= ua_quirks[i].dflags;
+ }
+ pcm_setflags(dev, flags);
#ifndef NO_RECORDING
-if (pcm_register(dev, ua, nplay, nrec)) {
+ if (pcm_register(dev, ua, nplay, nrec)) {
#else
-if (pcm_register(dev, ua, nplay, 0)) {
+ if (pcm_register(dev, ua, nplay, 0)) {
#endif
-goto bad;
-}
+ goto bad;
+ }
-sndstat_unregister(dev);
-uaudio_sndstat_register(dev);
+ sndstat_unregister(dev);
+ uaudio_sndstat_register(dev);
-for (i = 0; i < nplay; i++) {
-pcm_addchan(dev, PCMDIR_PLAY, &ua_chan_class, ua);
-}
+ for (i = 0; i < nplay; i++) {
+ pcm_addchan(dev, PCMDIR_PLAY, &ua_chan_class, ua);
+ }
#ifndef NO_RECORDING
-for (i = 0; i < nrec; i++) {
-pcm_addchan(dev, PCMDIR_REC, &ua_chan_class, ua);
-}
+ for (i = 0; i < nrec; i++) {
+ pcm_addchan(dev, PCMDIR_REC, &ua_chan_class, ua);
+ }
#endif
-pcm_setstatus(dev, status);
+ pcm_setstatus(dev, status);
-return 0;
+ return 0;
bad: free(ua, M_DEVBUF);
-return ENXIO;
+ return ENXIO;
}
static int
ua_detach(device_t dev)
{
-int r;
-struct ua_info *sc;
-
-r = pcm_unregister(dev);
-if (r)
-return r;
-
-sc = pcm_getdevinfo(dev);
-free(sc, M_DEVBUF);
+ struct ua_info *sc;
+ struct sndcard_func *func;
+ int r;
+
+ r = pcm_unregister(dev);
+ if (r)
+ return r;
+
+ sc = pcm_getdevinfo(dev);
+ free(sc, M_DEVBUF);
+
+ /* Mark for deletion */
+ func = device_get_ivars(dev);
+ if (func != NULL)
+ func->varinfo = NULL;
-return 0;
+ return 0;
}
/************************************************************/
static device_method_t ua_pcm_methods[] = {
-/* Device interface */
-DEVMETHOD(device_probe, ua_probe),
-DEVMETHOD(device_attach, ua_attach),
-DEVMETHOD(device_detach, ua_detach),
+ /* Device interface */
+ DEVMETHOD(device_probe, ua_probe),
+ DEVMETHOD(device_attach, ua_attach),
+ DEVMETHOD(device_detach, ua_detach),
-{ 0, 0 }
+ { 0, 0 }
};
static driver_t ua_pcm_driver = {
-"pcm",
-ua_pcm_methods,
-PCM_SOFTC_SIZE,
+ "pcm",
+ ua_pcm_methods,
+ PCM_SOFTC_SIZE,
};
Index: uaudio.c
===================================================================
RCS file: /home/cvs/src/sys/dev/sound/usb/uaudio.c,v
retrieving revision 1.3
retrieving revision 1.4
diff -L sys/dev/sound/usb/uaudio.c -L sys/dev/sound/usb/uaudio.c -u -r1.3 -r1.4
--- sys/dev/sound/usb/uaudio.c
+++ sys/dev/sound/usb/uaudio.c
@@ -1,49 +1,48 @@
/* $NetBSD: uaudio.c,v 1.91 2004/11/05 17:46:14 kent Exp $ */
-/* $MidnightBSD$ */
-/* $FreeBSD: src/sys/dev/sound/usb/uaudio.c,v 1.14.2.2 2006/04/04 17:34:10 ariff Exp $ */
+/* $FreeBSD: src/sys/dev/sound/usb/uaudio.c,v 1.36 2007/06/20 05:11:37 imp Exp $ */
/*-
-* Copyright (c) 1999 The NetBSD Foundation, Inc.
-* All rights reserved.
-*
-* This code is derived from software contributed to The NetBSD Foundation
-* by Lennart Augustsson (lennart at augustsson.net) at
-* Carlstedt Research & Technology.
-*
-* Redistribution and use in source and binary forms, with or without
-* modification, are permitted provided that the following conditions
-* are met:
-* 1. Redistributions of source code must retain the above copyright
-* notice, this list of conditions and the following disclaimer.
-* 2. Redistributions in binary form must reproduce the above copyright
-* notice, this list of conditions and the following disclaimer in the
-* documentation and/or other materials provided with the distribution.
-* 3. All advertising materials mentioning features or use of this software
-* must display the following acknowledgement:
-* This product includes software developed by the NetBSD
-* Foundation, Inc. and its contributors.
-* 4. Neither the name of The NetBSD Foundation nor the names of its
-* contributors may be used to endorse or promote products derived
-* from this software without specific prior written permission.
-*
-* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
-* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
-* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
-* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
-* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-* POSSIBILITY OF SUCH DAMAGE.
-*/
+ * Copyright (c) 1999 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Lennart Augustsson (lennart at augustsson.net) at
+ * Carlstedt Research & Technology.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the NetBSD
+ * Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
/*
-* USB audio specs: http://www.usb.org/developers/devclass_docs/audio10.pdf
-* http://www.usb.org/developers/devclass_docs/frmts10.pdf
-* http://www.usb.org/developers/devclass_docs/termt10.pdf
-*/
+ * USB audio specs: http://www.usb.org/developers/devclass_docs/audio10.pdf
+ * http://www.usb.org/developers/devclass_docs/frmts10.pdf
+ * http://www.usb.org/developers/devclass_docs/termt10.pdf
+ */
#include <sys/cdefs.h>
#if defined(__NetBSD__) || defined(__OpenBSD__)
@@ -51,12 +50,15 @@
#endif
/*
-* Also merged:
-* $NetBSD: uaudio.c,v 1.94 2005/01/15 15:19:53 kent Exp $
-* $NetBSD: uaudio.c,v 1.95 2005/01/16 06:02:19 dsainty Exp $
-* $NetBSD: uaudio.c,v 1.96 2005/01/16 12:46:00 kent Exp $
-* $NetBSD: uaudio.c,v 1.97 2005/02/24 08:19:38 martin Exp $
-*/
+ * Also merged:
+ * $NetBSD: uaudio.c,v 1.94 2005/01/15 15:19:53 kent Exp $
+ * $NetBSD: uaudio.c,v 1.95 2005/01/16 06:02:19 dsainty Exp $
+ * $NetBSD: uaudio.c,v 1.96 2005/01/16 12:46:00 kent Exp $
+ * $NetBSD: uaudio.c,v 1.97 2005/02/24 08:19:38 martin Exp $
+ * $NetBSD: uaudio.c,v 1.102 2006/04/14 17:00:55 christos Exp $
+ * $NetBSD: uaudio.c,v 1.103 2006/05/11 19:09:25 mrg Exp $
+ * $NetBSD: uaudio.c,v 1.105 2006/10/04 16:00:15 christos Exp $
+ */
#include <sys/param.h>
#include <sys/systm.h>
@@ -96,6 +98,7 @@
#include "feeder_if.h"
#endif
+#include <dev/usb/usb_port.h>
#include <dev/usb/usb.h>
#include <dev/usb/usbdi.h>
#include <dev/usb/usbdi_util.h>
@@ -115,13 +118,13 @@
#endif
/* #define UAUDIO_MULTIPLE_ENDPOINTS */
#ifdef USB_DEBUG
-#define DPRINTF(x) do { if (uaudiodebug) logprintf x; } while (0)
-#define DPRINTFN(n,x) do { if (uaudiodebug>(n)) logprintf x; } while (0)
+#define DPRINTF(x) do { if (uaudiodebug) printf x; } while (0)
+#define DPRINTFN(n,x) do { if (uaudiodebug>(n)) printf x; } while (0)
int uaudiodebug = 0;
#if defined(__FreeBSD__)
SYSCTL_NODE(_hw_usb, OID_AUTO, uaudio, CTLFLAG_RW, 0, "USB uaudio");
SYSCTL_INT(_hw_usb_uaudio, OID_AUTO, debug, CTLFLAG_RW,
-&uaudiodebug, 0, "uaudio debug level");
+ &uaudiodebug, 0, "uaudio debug level");
#endif
#else
#define DPRINTF(x)
@@ -138,10 +141,10 @@
#define MIX_MAX_CHAN 8
struct mixerctl {
-uint16_t wValue[MIX_MAX_CHAN]; /* using nchan */
-uint16_t wIndex;
-uint8_t nchan;
-uint8_t type;
+ uint16_t wValue[MIX_MAX_CHAN]; /* using nchan */
+ uint16_t wIndex;
+ uint8_t nchan;
+ uint8_t type;
#define MIX_ON_OFF 1
#define MIX_SIGNED_16 2
#define MIX_UNSIGNED_16 3
@@ -149,90 +152,90 @@
#define MIX_SELECTOR 5
#define MIX_SIZE(n) ((n) == MIX_SIGNED_16 || (n) == MIX_UNSIGNED_16 ? 2 : 1)
#define MIX_UNSIGNED(n) ((n) == MIX_UNSIGNED_16)
-int minval, maxval;
-u_int delta;
-u_int mul;
+ int minval, maxval;
+ u_int delta;
+ u_int mul;
#if defined(__FreeBSD__) /* XXXXX */
-unsigned ctl;
+ unsigned ctl;
#define MAX_SELECTOR_INPUT_PIN 256
-uint8_t slctrtype[MAX_SELECTOR_INPUT_PIN];
+ uint8_t slctrtype[MAX_SELECTOR_INPUT_PIN];
#endif
-uint8_t class;
+ uint8_t class;
#if !defined(__FreeBSD__)
-char ctlname[MAX_AUDIO_DEV_LEN];
-char *ctlunit;
+ char ctlname[MAX_AUDIO_DEV_LEN];
+ char *ctlunit;
#endif
};
#define MAKE(h,l) (((h) << 8) | (l))
struct as_info {
-uint8_t alt;
-uint8_t encoding;
-uint8_t attributes; /* Copy of bmAttributes of
-* usb_audio_streaming_endpoint_descriptor
-*/
-usbd_interface_handle ifaceh;
-const usb_interface_descriptor_t *idesc;
-const usb_endpoint_descriptor_audio_t *edesc;
-const usb_endpoint_descriptor_audio_t *edesc1;
-const struct usb_audio_streaming_type1_descriptor *asf1desc;
-int sc_busy; /* currently used */
+ uint8_t alt;
+ uint8_t encoding;
+ uint8_t attributes; /* Copy of bmAttributes of
+ * usb_audio_streaming_endpoint_descriptor
+ */
+ usbd_interface_handle ifaceh;
+ const usb_interface_descriptor_t *idesc;
+ const usb_endpoint_descriptor_audio_t *edesc;
+ const usb_endpoint_descriptor_audio_t *edesc1;
+ const struct usb_audio_streaming_type1_descriptor *asf1desc;
+ int sc_busy; /* currently used */
};
struct chan {
#if defined(__NetBSD__) || defined(__OpenBSD__)
-void (*intr)(void *); /* DMA completion intr handler */
-void *arg; /* arg for intr() */
+ void (*intr)(void *); /* DMA completion intr handler */
+ void *arg; /* arg for intr() */
#else
-struct pcm_channel *pcm_ch;
+ struct pcm_channel *pcm_ch;
#endif
-usbd_pipe_handle pipe;
-usbd_pipe_handle sync_pipe;
+ usbd_pipe_handle pipe;
+ usbd_pipe_handle sync_pipe;
-u_int sample_size;
-u_int sample_rate;
-u_int bytes_per_frame;
-u_int fraction; /* fraction/1000 is the extra samples/frame */
-u_int residue; /* accumulates the fractional samples */
-
-u_char *start; /* upper layer buffer start */
-u_char *end; /* upper layer buffer end */
-u_char *cur; /* current position in upper layer buffer */
-int blksize; /* chunk size to report up */
-int transferred; /* transferred bytes not reported up */
-
-int altidx; /* currently used altidx */
-
-int curchanbuf;
-struct chanbuf {
-struct chan *chan;
-usbd_xfer_handle xfer;
-u_char *buffer;
-u_int16_t sizes[UAUDIO_NFRAMES];
-u_int16_t offsets[UAUDIO_NFRAMES];
-u_int16_t size;
-} chanbufs[UAUDIO_NCHANBUFS];
-
-struct uaudio_softc *sc; /* our softc */
-#if defined(__FreeBSD__)
-u_int32_t format;
-int precision;
-int channels;
+ u_int sample_size;
+ u_int sample_rate;
+ u_int bytes_per_frame;
+ u_int fraction; /* fraction/1000 is the extra samples/frame */
+ u_int residue; /* accumulates the fractional samples */
+
+ u_char *start; /* upper layer buffer start */
+ u_char *end; /* upper layer buffer end */
+ u_char *cur; /* current position in upper layer buffer */
+ int blksize; /* chunk size to report up */
+ int transferred; /* transferred bytes not reported up */
+
+ int altidx; /* currently used altidx */
+
+ int curchanbuf;
+ struct chanbuf {
+ struct chan *chan;
+ usbd_xfer_handle xfer;
+ u_char *buffer;
+ u_int16_t sizes[UAUDIO_NFRAMES];
+ u_int16_t offsets[UAUDIO_NFRAMES];
+ u_int16_t size;
+ } chanbufs[UAUDIO_NCHANBUFS];
+
+ struct uaudio_softc *sc; /* our softc */
+#if defined(__FreeBSD__)
+ u_int32_t format;
+ int precision;
+ int channels;
#endif
};
struct uaudio_softc {
-USBBASEDEVICE sc_dev; /* base device */
-usbd_device_handle sc_udev; /* USB device */
-int sc_ac_iface; /* Audio Control interface */
-usbd_interface_handle sc_ac_ifaceh;
-struct chan sc_playchan; /* play channel */
-struct chan sc_recchan; /* record channel */
-int sc_nullalt;
-int sc_audio_rev;
-struct as_info *sc_alts; /* alternate settings */
-int sc_nalts; /* # of alternate settings */
-int sc_altflags;
+ device_t sc_dev; /* base device */
+ usbd_device_handle sc_udev; /* USB device */
+ int sc_ac_iface; /* Audio Control interface */
+ usbd_interface_handle sc_ac_ifaceh;
+ struct chan sc_playchan; /* play channel */
+ struct chan sc_recchan; /* record channel */
+ int sc_nullalt;
+ int sc_audio_rev;
+ struct as_info *sc_alts; /* alternate settings */
+ int sc_nalts; /* # of alternate settings */
+ int sc_altflags;
#define HAS_8 0x01
#define HAS_16 0x02
#define HAS_8U 0x04
@@ -241,38 +244,43 @@
#define UA_NOFRAC 0x20 /* don't do sample rate adjustment */
#define HAS_24 0x40
#define HAS_32 0x80
-int sc_mode; /* play/record capability */
-struct mixerctl *sc_ctls; /* mixer controls */
-int sc_nctls; /* # of mixer controls */
-device_ptr_t sc_audiodev;
-char sc_dying;
+ int sc_mode; /* play/record capability */
+ struct mixerctl *sc_ctls; /* mixer controls */
+ int sc_nctls; /* # of mixer controls */
+ device_t sc_audiodev;
+ char sc_dying;
#if defined(__FreeBSD__)
-struct sbuf uaudio_sndstat;
-int uaudio_sndstat_flag;
-#endif
+ struct sbuf uaudio_sndstat;
+ int uaudio_sndstat_flag;
+ int async;
+#endif
+ int sc_vendor;
+ int sc_product;
+ int sc_release;
};
struct terminal_list {
-int size;
-uint16_t terminals[1];
+ int size;
+ uint16_t terminals[1];
};
-#define TERMINAL_LIST_SIZE(N) (offsetof(struct terminal_list, terminals) + sizeof(uint16_t) * (N))
+#define TERMINAL_LIST_SIZE(N) (offsetof(struct terminal_list, terminals) \
+ + sizeof(uint16_t) * (N))
struct io_terminal {
-union {
-const usb_descriptor_t *desc;
-const struct usb_audio_input_terminal *it;
-const struct usb_audio_output_terminal *ot;
-const struct usb_audio_mixer_unit *mu;
-const struct usb_audio_selector_unit *su;
-const struct usb_audio_feature_unit *fu;
-const struct usb_audio_processing_unit *pu;
-const struct usb_audio_extension_unit *eu;
-} d;
-int inputs_size;
-struct terminal_list **inputs; /* list of source input terminals */
-struct terminal_list *output; /* list of destination output terminals */
-int direct; /* directly connected to an output terminal */
+ union {
+ const usb_descriptor_t *desc;
+ const struct usb_audio_input_terminal *it;
+ const struct usb_audio_output_terminal *ot;
+ const struct usb_audio_mixer_unit *mu;
+ const struct usb_audio_selector_unit *su;
+ const struct usb_audio_feature_unit *fu;
+ const struct usb_audio_processing_unit *pu;
+ const struct usb_audio_extension_unit *eu;
+ } d;
+ int inputs_size;
+ struct terminal_list **inputs; /* list of source input terminals */
+ struct terminal_list *output; /* list of destination output terminals */
+ int direct; /* directly connected to an output terminal */
};
#define UAC_OUTPUT 0
@@ -287,178 +295,178 @@
#define AudioCrecord "record"
#define AudioCequalization "equalization"
#endif
-Static const char *uac_names[] = {
-AudioCoutputs, AudioCinputs, AudioCequalization, AudioCrecord,
+static const char *uac_names[] = {
+ AudioCoutputs, AudioCinputs, AudioCequalization, AudioCrecord,
};
#endif
-Static usbd_status uaudio_identify_ac
-(struct uaudio_softc *, const usb_config_descriptor_t *);
-Static usbd_status uaudio_identify_as
-(struct uaudio_softc *, const usb_config_descriptor_t *);
-Static usbd_status uaudio_process_as
-(struct uaudio_softc *, const char *, int *, int,
-const usb_interface_descriptor_t *);
+static usbd_status uaudio_identify_ac
+ (struct uaudio_softc *, const usb_config_descriptor_t *);
+static usbd_status uaudio_identify_as
+ (struct uaudio_softc *, const usb_config_descriptor_t *);
+static usbd_status uaudio_process_as
+ (struct uaudio_softc *, const char *, int *, int,
+ const usb_interface_descriptor_t *);
-Static void uaudio_add_alt(struct uaudio_softc *, const struct as_info *);
+static void uaudio_add_alt(struct uaudio_softc *, const struct as_info *);
-Static const usb_interface_descriptor_t *uaudio_find_iface
-(const char *, int, int *, int);
+static const usb_interface_descriptor_t *uaudio_find_iface
+ (const char *, int, int *, int);
-Static void uaudio_mixer_add_ctl(struct uaudio_softc *, struct mixerctl *);
+static void uaudio_mixer_add_ctl(struct uaudio_softc *, struct mixerctl *);
#if defined(__NetBSD__) || defined(__OpenBSD__)
-Static char *uaudio_id_name
-(struct uaudio_softc *, const struct io_terminal *, int);
+static char *uaudio_id_name
+ (struct uaudio_softc *, const struct io_terminal *, int);
#endif
#ifdef USB_DEBUG
-Static void uaudio_dump_cluster(const struct usb_audio_cluster *);
+static void uaudio_dump_cluster(const struct usb_audio_cluster *);
#endif
-Static struct usb_audio_cluster uaudio_get_cluster
-(int, const struct io_terminal *);
-Static void uaudio_add_input
-(struct uaudio_softc *, const struct io_terminal *, int);
-Static void uaudio_add_output
-(struct uaudio_softc *, const struct io_terminal *, int);
-Static void uaudio_add_mixer
-(struct uaudio_softc *, const struct io_terminal *, int);
-Static void uaudio_add_selector
-(struct uaudio_softc *, const struct io_terminal *, int);
+static struct usb_audio_cluster uaudio_get_cluster
+ (int, const struct io_terminal *);
+static void uaudio_add_input
+ (struct uaudio_softc *, const struct io_terminal *, int);
+static void uaudio_add_output
+ (struct uaudio_softc *, const struct io_terminal *, int);
+static void uaudio_add_mixer
+ (struct uaudio_softc *, const struct io_terminal *, int);
+static void uaudio_add_selector
+ (struct uaudio_softc *, const struct io_terminal *, int);
#ifdef USB_DEBUG
-Static const char *uaudio_get_terminal_name(int);
+static const char *uaudio_get_terminal_name(int);
#endif
-Static int uaudio_determine_class
-(const struct io_terminal *, struct mixerctl *);
+static int uaudio_determine_class
+ (const struct io_terminal *, struct mixerctl *);
#if defined(__FreeBSD__)
-Static const int uaudio_feature_name(const struct io_terminal *,
-struct mixerctl *);
+static int uaudio_feature_name(const struct io_terminal *,
+ struct mixerctl *);
#else
-Static const char *uaudio_feature_name
-(const struct io_terminal *, struct mixerctl *);
+static const char *uaudio_feature_name
+ (const struct io_terminal *, struct mixerctl *);
#endif
-Static void uaudio_add_feature
-(struct uaudio_softc *, const struct io_terminal *, int);
-Static void uaudio_add_processing_updown
-(struct uaudio_softc *, const struct io_terminal *, int);
-Static void uaudio_add_processing
-(struct uaudio_softc *, const struct io_terminal *, int);
-Static void uaudio_add_extension
-(struct uaudio_softc *, const struct io_terminal *, int);
-Static struct terminal_list *uaudio_merge_terminal_list
-(const struct io_terminal *);
-Static struct terminal_list *uaudio_io_terminaltype
-(int, struct io_terminal *, int);
-Static usbd_status uaudio_identify
-(struct uaudio_softc *, const usb_config_descriptor_t *);
+static void uaudio_add_feature
+ (struct uaudio_softc *, const struct io_terminal *, int);
+static void uaudio_add_processing_updown
+ (struct uaudio_softc *, const struct io_terminal *, int);
+static void uaudio_add_processing
+ (struct uaudio_softc *, const struct io_terminal *, int);
+static void uaudio_add_extension
+ (struct uaudio_softc *, const struct io_terminal *, int);
+static struct terminal_list *uaudio_merge_terminal_list
+ (const struct io_terminal *);
+static struct terminal_list *uaudio_io_terminaltype
+ (int, struct io_terminal *, int);
+static usbd_status uaudio_identify
+ (struct uaudio_softc *, const usb_config_descriptor_t *);
-Static int uaudio_signext(int, int);
+static int uaudio_signext(int, int);
#if defined(__NetBSD__) || defined(__OpenBSD__)
-Static int uaudio_value2bsd(struct mixerctl *, int);
+static int uaudio_value2bsd(struct mixerctl *, int);
#endif
-Static int uaudio_bsd2value(struct mixerctl *, int);
-Static int uaudio_get(struct uaudio_softc *, int, int, int, int, int);
+static int uaudio_bsd2value(struct mixerctl *, int);
+static int uaudio_get(struct uaudio_softc *, int, int, int, int, int);
#if defined(__NetBSD__) || defined(__OpenBSD__)
-Static int uaudio_ctl_get
-(struct uaudio_softc *, int, struct mixerctl *, int);
+static int uaudio_ctl_get
+ (struct uaudio_softc *, int, struct mixerctl *, int);
#endif
-Static void uaudio_set
-(struct uaudio_softc *, int, int, int, int, int, int);
-Static void uaudio_ctl_set
-(struct uaudio_softc *, int, struct mixerctl *, int, int);
-
-Static usbd_status uaudio_set_speed(struct uaudio_softc *, int, u_int);
-
-Static usbd_status uaudio_chan_open(struct uaudio_softc *, struct chan *);
-Static void uaudio_chan_close(struct uaudio_softc *, struct chan *);
-Static usbd_status uaudio_chan_alloc_buffers
-(struct uaudio_softc *, struct chan *);
-Static void uaudio_chan_free_buffers(struct uaudio_softc *, struct chan *);
+static void uaudio_set
+ (struct uaudio_softc *, int, int, int, int, int, int);
+static void uaudio_ctl_set
+ (struct uaudio_softc *, int, struct mixerctl *, int, int);
+
+static usbd_status uaudio_set_speed(struct uaudio_softc *, int, u_int);
+
+static usbd_status uaudio_chan_open(struct uaudio_softc *, struct chan *);
+static void uaudio_chan_close(struct uaudio_softc *, struct chan *);
+static usbd_status uaudio_chan_alloc_buffers
+ (struct uaudio_softc *, struct chan *);
+static void uaudio_chan_free_buffers(struct uaudio_softc *, struct chan *);
#if defined(__NetBSD__) || defined(__OpenBSD__)
-Static void uaudio_chan_init
-(struct chan *, int, const struct audio_params *, int);
-Static void uaudio_chan_set_param(struct chan *, u_char *, u_char *, int);
+static void uaudio_chan_init
+ (struct chan *, int, const struct audio_params *, int);
+static void uaudio_chan_set_param(struct chan *, u_char *, u_char *, int);
#endif
-Static void uaudio_chan_ptransfer(struct chan *);
-Static void uaudio_chan_pintr
-(usbd_xfer_handle, usbd_private_handle, usbd_status);
-
-Static void uaudio_chan_rtransfer(struct chan *);
-Static void uaudio_chan_rintr
-(usbd_xfer_handle, usbd_private_handle, usbd_status);
+static void uaudio_chan_ptransfer(struct chan *);
+static void uaudio_chan_pintr
+ (usbd_xfer_handle, usbd_private_handle, usbd_status);
+
+static void uaudio_chan_rtransfer(struct chan *);
+static void uaudio_chan_rintr
+ (usbd_xfer_handle, usbd_private_handle, usbd_status);
#if defined(__NetBSD__) || defined(__OpenBSD__)
-Static int uaudio_open(void *, int);
-Static void uaudio_close(void *);
-Static int uaudio_drain(void *);
-Static int uaudio_query_encoding(void *, struct audio_encoding *);
-Static void uaudio_get_minmax_rates
-(int, const struct as_info *, const struct audio_params *,
-int, u_long *, u_long *);
-Static int uaudio_match_alt_sub
-(int, const struct as_info *, const struct audio_params *, int, u_long);
-Static int uaudio_match_alt_chan
-(int, const struct as_info *, struct audio_params *, int);
-Static int uaudio_match_alt
-(int, const struct as_info *, struct audio_params *, int);
-Static int uaudio_set_params
-(void *, int, int, struct audio_params *, struct audio_params *);
-Static int uaudio_round_blocksize(void *, int);
-Static int uaudio_trigger_output
-(void *, void *, void *, int, void (*)(void *), void *,
-struct audio_params *);
-Static int uaudio_trigger_input
-(void *, void *, void *, int, void (*)(void *), void *,
-struct audio_params *);
-Static int uaudio_halt_in_dma(void *);
-Static int uaudio_halt_out_dma(void *);
-Static int uaudio_getdev(void *, struct audio_device *);
-Static int uaudio_mixer_set_port(void *, mixer_ctrl_t *);
-Static int uaudio_mixer_get_port(void *, mixer_ctrl_t *);
-Static int uaudio_query_devinfo(void *, mixer_devinfo_t *);
-Static int uaudio_get_props(void *);
-
-Static const struct audio_hw_if uaudio_hw_if = {
-uaudio_open,
-uaudio_close,
-uaudio_drain,
-uaudio_query_encoding,
-uaudio_set_params,
-uaudio_round_blocksize,
-NULL,
-NULL,
-NULL,
-NULL,
-NULL,
-uaudio_halt_out_dma,
-uaudio_halt_in_dma,
-NULL,
-uaudio_getdev,
-NULL,
-uaudio_mixer_set_port,
-uaudio_mixer_get_port,
-uaudio_query_devinfo,
-NULL,
-NULL,
-NULL,
-NULL,
-uaudio_get_props,
-uaudio_trigger_output,
-uaudio_trigger_input,
-NULL,
+static int uaudio_open(void *, int);
+static void uaudio_close(void *);
+static int uaudio_drain(void *);
+static int uaudio_query_encoding(void *, struct audio_encoding *);
+static void uaudio_get_minmax_rates
+ (int, const struct as_info *, const struct audio_params *,
+ int, u_long *, u_long *);
+static int uaudio_match_alt_sub
+ (int, const struct as_info *, const struct audio_params *, int, u_long);
+static int uaudio_match_alt_chan
+ (int, const struct as_info *, struct audio_params *, int);
+static int uaudio_match_alt
+ (int, const struct as_info *, struct audio_params *, int);
+static int uaudio_set_params
+ (void *, int, int, struct audio_params *, struct audio_params *);
+static int uaudio_round_blocksize(void *, int);
+static int uaudio_trigger_output
+ (void *, void *, void *, int, void (*)(void *), void *,
+ struct audio_params *);
+static int uaudio_trigger_input
+ (void *, void *, void *, int, void (*)(void *), void *,
+ struct audio_params *);
+static int uaudio_halt_in_dma(void *);
+static int uaudio_halt_out_dma(void *);
+static int uaudio_getdev(void *, struct audio_device *);
+static int uaudio_mixer_set_port(void *, mixer_ctrl_t *);
+static int uaudio_mixer_get_port(void *, mixer_ctrl_t *);
+static int uaudio_query_devinfo(void *, mixer_devinfo_t *);
+static int uaudio_get_props(void *);
+
+static const struct audio_hw_if uaudio_hw_if = {
+ uaudio_open,
+ uaudio_close,
+ uaudio_drain,
+ uaudio_query_encoding,
+ uaudio_set_params,
+ uaudio_round_blocksize,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ uaudio_halt_out_dma,
+ uaudio_halt_in_dma,
+ NULL,
+ uaudio_getdev,
+ NULL,
+ uaudio_mixer_set_port,
+ uaudio_mixer_get_port,
+ uaudio_query_devinfo,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ uaudio_get_props,
+ uaudio_trigger_output,
+ uaudio_trigger_input,
+ NULL,
};
-Static struct audio_device uaudio_device = {
-"USB audio",
-"",
-"uaudio"
+static struct audio_device uaudio_device = {
+ "USB audio",
+ "",
+ "uaudio"
};
#elif defined(__FreeBSD__)
-Static int audio_attach_mi(device_t);
-Static int uaudio_init_params(struct uaudio_softc * sc, struct chan *ch, int mode);
+static int audio_attach_mi(device_t);
+static int uaudio_init_params(struct uaudio_softc * sc, struct chan *ch, int mode);
static int uaudio_sndstat_prepare_pcm(struct sbuf *s, device_t dev, int verbose);
/* for NetBSD compatibirity */
@@ -484,3252 +492,3334 @@
#elif defined(__FreeBSD__)
USB_DECLARE_DRIVER_INIT(uaudio,
-DEVMETHOD(device_suspend, bus_generic_suspend),
-DEVMETHOD(device_resume, bus_generic_resume),
-DEVMETHOD(device_shutdown, bus_generic_shutdown),
-DEVMETHOD(bus_print_child, bus_generic_print_child)
-);
+ DEVMETHOD(device_suspend, bus_generic_suspend),
+ DEVMETHOD(device_resume, bus_generic_resume),
+ DEVMETHOD(device_shutdown, bus_generic_shutdown),
+ DEVMETHOD(bus_print_child, bus_generic_print_child)
+ );
#endif
USB_MATCH(uaudio)
{
-USB_MATCH_START(uaudio, uaa);
-usb_interface_descriptor_t *id;
+ USB_MATCH_START(uaudio, uaa);
+ usb_interface_descriptor_t *id;
-if (uaa->iface == NULL)
-return UMATCH_NONE;
+ if (uaa->iface == NULL)
+ return UMATCH_NONE;
-id = usbd_get_interface_descriptor(uaa->iface);
-/* Trigger on the control interface. */
-if (id == NULL ||
-id->bInterfaceClass != UICLASS_AUDIO ||
-id->bInterfaceSubClass != UISUBCLASS_AUDIOCONTROL ||
-(usbd_get_quirks(uaa->device)->uq_flags & UQ_BAD_AUDIO))
-return UMATCH_NONE;
+ id = usbd_get_interface_descriptor(uaa->iface);
+ /* Trigger on the control interface. */
+ if (id == NULL ||
+ id->bInterfaceClass != UICLASS_AUDIO ||
+ id->bInterfaceSubClass != UISUBCLASS_AUDIOCONTROL ||
+ (usbd_get_quirks(uaa->device)->uq_flags & UQ_BAD_AUDIO))
+ return UMATCH_NONE;
-return UMATCH_IFACECLASS_IFACESUBCLASS;
+ return UMATCH_IFACECLASS_IFACESUBCLASS;
}
USB_ATTACH(uaudio)
{
-USB_ATTACH_START(uaudio, sc, uaa);
-usb_interface_descriptor_t *id;
-usb_config_descriptor_t *cdesc;
-char devinfo[1024];
-usbd_status err;
-int i, j, found;
+ USB_ATTACH_START(uaudio, sc, uaa);
+ usb_interface_descriptor_t *id;
+ usb_config_descriptor_t *cdesc;
+#if !defined(__FreeBSD__)
+ char devinfo[1024];
+#endif
+ usbd_status err;
+ int i, j, found;
#if defined(__FreeBSD__)
-usbd_devinfo(uaa->device, 0, devinfo);
-USB_ATTACH_SETUP;
+ sc->sc_dev = self;
#else
-usbd_devinfo(uaa->device, 0, devinfo, sizeof(devinfo));
-printf(": %sn", devinfo);
+ usbd_devinfo(uaa->device, 0, devinfo, sizeof(devinfo));
+ printf(": %s\n", devinfo);
#endif
-sc->sc_udev = uaa->device;
-
-cdesc = usbd_get_config_descriptor(sc->sc_udev);
-if (cdesc == NULL) {
-printf("%s: failed to get configuration descriptorn",
-USBDEVNAME(sc->sc_dev));
-USB_ATTACH_ERROR_RETURN;
-}
-
-err = uaudio_identify(sc, cdesc);
-if (err) {
-printf("%s: audio descriptors make no sense, error=%dn",
-USBDEVNAME(sc->sc_dev), err);
-USB_ATTACH_ERROR_RETURN;
-}
-
-sc->sc_ac_ifaceh = uaa->iface;
-/* Pick up the AS interface. */
-for (i = 0; i < uaa->nifaces; i++) {
-if (uaa->ifaces[i] == NULL)
-continue;
-id = usbd_get_interface_descriptor(uaa->ifaces[i]);
-if (id == NULL)
-continue;
-found = 0;
-for (j = 0; j < sc->sc_nalts; j++) {
-if (id->bInterfaceNumber ==
-sc->sc_alts[j].idesc->bInterfaceNumber) {
-sc->sc_alts[j].ifaceh = uaa->ifaces[i];
-found = 1;
-}
-}
-if (found)
-uaa->ifaces[i] = NULL;
-}
-
-for (j = 0; j < sc->sc_nalts; j++) {
-if (sc->sc_alts[j].ifaceh == NULL) {
-printf("%s: alt %d missing AS interface(s)n",
-USBDEVNAME(sc->sc_dev), j);
-USB_ATTACH_ERROR_RETURN;
-}
-}
-
-printf("%s: audio rev %d.%02xn", USBDEVNAME(sc->sc_dev),
-sc->sc_audio_rev >> 8, sc->sc_audio_rev & 0xff);
-
-sc->sc_playchan.sc = sc->sc_recchan.sc = sc;
-sc->sc_playchan.altidx = -1;
-sc->sc_recchan.altidx = -1;
+ sc->sc_udev = uaa->device;
+ sc->sc_vendor = uaa->vendor;
+ sc->sc_product = uaa->product;
+ sc->sc_release = uaa->release;
+#if defined(__FreeBSD__)
+ if (resource_int_value(device_get_name(sc->sc_dev),
+ device_get_unit(sc->sc_dev), "async", &i) == 0 && i != 0)
+ sc->async = 1;
+ else
+ sc->async = 0;
+#endif
+
+ cdesc = usbd_get_config_descriptor(sc->sc_udev);
+ if (cdesc == NULL) {
+ printf("%s: failed to get configuration descriptor\n",
+ device_get_nameunit(sc->sc_dev));
+ return ENXIO;
+ }
+
+ err = uaudio_identify(sc, cdesc);
+ if (err) {
+ printf("%s: audio descriptors make no sense, error=%d\n",
+ device_get_nameunit(sc->sc_dev), err);
+ return ENXIO;
+ }
+
+ sc->sc_ac_ifaceh = uaa->iface;
+ /* Pick up the AS interface. */
+ for (i = 0; i < uaa->nifaces; i++) {
+ if (uaa->ifaces[i] == NULL)
+ continue;
+ id = usbd_get_interface_descriptor(uaa->ifaces[i]);
+ if (id == NULL)
+ continue;
+ found = 0;
+ for (j = 0; j < sc->sc_nalts; j++) {
+ if (id->bInterfaceNumber ==
+ sc->sc_alts[j].idesc->bInterfaceNumber) {
+ sc->sc_alts[j].ifaceh = uaa->ifaces[i];
+ found = 1;
+ }
+ }
+ if (found)
+ uaa->ifaces[i] = NULL;
+ }
+
+ for (j = 0; j < sc->sc_nalts; j++) {
+ if (sc->sc_alts[j].ifaceh == NULL) {
+ printf("%s: alt %d missing AS interface(s)\n",
+ device_get_nameunit(sc->sc_dev), j);
+ return ENXIO;
+ }
+ }
+
+ printf("%s: audio rev %d.%02x\n", device_get_nameunit(sc->sc_dev),
+ sc->sc_audio_rev >> 8, sc->sc_audio_rev & 0xff);
+
+ sc->sc_playchan.sc = sc->sc_recchan.sc = sc;
+ sc->sc_playchan.altidx = -1;
+ sc->sc_recchan.altidx = -1;
-if (usbd_get_quirks(sc->sc_udev)->uq_flags & UQ_AU_NO_FRAC)
-sc->sc_altflags |= UA_NOFRAC;
+ if (usbd_get_quirks(sc->sc_udev)->uq_flags & UQ_AU_NO_FRAC)
+ sc->sc_altflags |= UA_NOFRAC;
#ifndef USB_DEBUG
-if (bootverbose)
+ if (bootverbose)
#endif
-printf("%s: %d mixer controlsn", USBDEVNAME(sc->sc_dev),
-sc->sc_nctls);
+ printf("%s: %d mixer controls\n", device_get_nameunit(sc->sc_dev),
+ sc->sc_nctls);
#if !defined(__FreeBSD__)
-usbd_add_drv_event(USB_EVENT_DRIVER_ATTACH, sc->sc_udev,
-USBDEV(sc->sc_dev));
+ usbd_add_drv_event(USB_EVENT_DRIVER_ATTACH, sc->sc_udev,
+ USBDEV(sc->sc_dev));
#endif
-DPRINTF(("uaudio_attach: doing audio_attach_min"));
+ DPRINTF(("uaudio_attach: doing audio_attach_mi\n"));
#if defined(__OpenBSD__)
-audio_attach_mi(&uaudio_hw_if, sc, &sc->sc_dev);
+ audio_attach_mi(&uaudio_hw_if, sc, &sc->sc_dev);
#elif defined(__NetBSD__)
-sc->sc_audiodev = audio_attach_mi(&uaudio_hw_if, sc, &sc->sc_dev);
+ sc->sc_audiodev = audio_attach_mi(&uaudio_hw_if, sc, &sc->sc_dev);
#elif defined(__FreeBSD__)
-sc->sc_dying = 0;
-if (audio_attach_mi(sc->sc_dev)) {
-printf("audio_attach_mi failedn");
-USB_ATTACH_ERROR_RETURN;
-}
+ sc->sc_dying = 0;
+ if (audio_attach_mi(sc->sc_dev)) {
+ printf("audio_attach_mi failed\n");
+ return ENXIO;
+ }
#endif
-USB_ATTACH_SUCCESS_RETURN;
+#if defined(__FreeBSD__)
+ SYSCTL_ADD_INT(device_get_sysctl_ctx(sc->sc_dev),
+ SYSCTL_CHILDREN(device_get_sysctl_tree(sc->sc_dev)),
+ OID_AUTO, "async", CTLFLAG_RW, &sc->async, 0,
+ "Asynchronous USB request");
+#endif
+ return 0;
}
#if defined(__NetBSD__) || defined(__OpenBSD__)
int
-uaudio_activate(device_ptr_t self, enum devact act)
+uaudio_activate(device_t self, enum devact act)
{
-struct uaudio_softc *sc;
-int rv;
+ struct uaudio_softc *sc;
+ int rv;
-sc = (struct uaudio_softc *)self;
-rv = 0;
-switch (act) {
-case DVACT_ACTIVATE:
-return EOPNOTSUPP;
-
-case DVACT_DEACTIVATE:
-if (sc->sc_audiodev != NULL)
-rv = config_deactivate(sc->sc_audiodev);
-sc->sc_dying = 1;
-break;
-}
-return rv;
+ sc = (struct uaudio_softc *)self;
+ rv = 0;
+ switch (act) {
+ case DVACT_ACTIVATE:
+ return EOPNOTSUPP;
+
+ case DVACT_DEACTIVATE:
+ if (sc->sc_audiodev != NULL)
+ rv = config_deactivate(sc->sc_audiodev);
+ sc->sc_dying = 1;
+ break;
+ }
+ return rv;
}
#endif
#if defined(__NetBSD__) || defined(__OpenBSD__)
int
-uaudio_detach(device_ptr_t self, int flags)
+uaudio_detach(device_t self, int flags)
{
-struct uaudio_softc *sc;
-int rv;
+ struct uaudio_softc *sc;
+ int rv;
-sc = (struct uaudio_softc *)self;
-rv = 0;
-/* Wait for outstanding requests to complete. */
-usbd_delay_ms(sc->sc_udev, UAUDIO_NCHANBUFS * UAUDIO_NFRAMES);
+ sc = (struct uaudio_softc *)self;
+ rv = 0;
+ /* Wait for outstanding requests to complete. */
+ usbd_delay_ms(sc->sc_udev, UAUDIO_NCHANBUFS * UAUDIO_NFRAMES);
-if (sc->sc_audiodev != NULL)
-rv = config_detach(sc->sc_audiodev, flags);
+ if (sc->sc_audiodev != NULL)
+ rv = config_detach(sc->sc_audiodev, flags);
-usbd_add_drv_event(USB_EVENT_DRIVER_DETACH, sc->sc_udev,
-USBDEV(sc->sc_dev));
+ usbd_add_drv_event(USB_EVENT_DRIVER_DETACH, sc->sc_udev,
+ USBDEV(sc->sc_dev));
-return rv;
+ return rv;
}
#elif defined(__FreeBSD__)
USB_DETACH(uaudio)
{
-USB_DETACH_START(uaudio, sc);
+ struct sndcard_func *func;
+ device_t *devlist = NULL;
+ int err, i, devcount;
+
+ USB_DETACH_START(uaudio, sc);
-sbuf_delete(&(sc->uaudio_sndstat));
-sc->uaudio_sndstat_flag = 0;
+ sbuf_delete(&(sc->uaudio_sndstat));
+ sc->uaudio_sndstat_flag = 0;
-sc->sc_dying = 1;
+ sc->sc_dying = 1;
#if 0 /* XXX */
-/* Wait for outstanding requests to complete. */
-usbd_delay_ms(sc->sc_udev, UAUDIO_NCHANBUFS * UAUDIO_NFRAMES);
+ /* Wait for outstanding requests to complete. */
+ usbd_delay_ms(sc->sc_udev, UAUDIO_NCHANBUFS * UAUDIO_NFRAMES);
#endif
-/* do nothing ? */
-return bus_generic_detach(sc->sc_dev);
+ err = bus_generic_detach(sc->sc_dev);
+
+ if (err == 0) {
+ device_get_children(sc->sc_dev, &devlist, &devcount);
+ for (i = 0; devlist != NULL && i < devcount; i++) {
+ func = device_get_ivars(devlist[i]);
+ if (func != NULL && func->func == SCF_PCM &&
+ func->varinfo == NULL) {
+ device_set_ivars(devlist[i], NULL);
+ free(func, M_DEVBUF);
+ device_delete_child(sc->sc_dev, devlist[i]);
+ }
+ }
+ if (devlist != NULL)
+ free(devlist, M_TEMP);
+ }
+
+ return err;
}
#endif
#if defined(__NetBSD__) || defined(__OpenBSD__)
-Static int
+static int
uaudio_query_encoding(void *addr, struct audio_encoding *fp)
{
-struct uaudio_softc *sc;
-int flags;
-int idx;
-
-sc = addr;
-flags = sc->sc_altflags;
-if (sc->sc_dying)
-return EIO;
-
-if (sc->sc_nalts == 0 || flags == 0)
-return ENXIO;
-
-idx = fp->index;
-switch (idx) {
-case 0:
-strlcpy(fp->name, AudioEulinear, sizeof(fp->name));
-fp->encoding = AUDIO_ENCODING_ULINEAR;
-fp->precision = 8;
-fp->flags = flags&HAS_8U ? 0 : AUDIO_ENCODINGFLAG_EMULATED;
-return (0);
-case 1:
-strlcpy(fp->name, AudioEmulaw, sizeof(fp->name));
-fp->encoding = AUDIO_ENCODING_ULAW;
-fp->precision = 8;
-fp->flags = flags&HAS_MULAW ? 0 : AUDIO_ENCODINGFLAG_EMULATED;
-return (0);
-case 2:
-strlcpy(fp->name, AudioEalaw, sizeof(fp->name));
-fp->encoding = AUDIO_ENCODING_ALAW;
-fp->precision = 8;
-fp->flags = flags&HAS_ALAW ? 0 : AUDIO_ENCODINGFLAG_EMULATED;
-return (0);
-case 3:
-strlcpy(fp->name, AudioEslinear, sizeof(fp->name));
-fp->encoding = AUDIO_ENCODING_SLINEAR;
-fp->precision = 8;
-fp->flags = flags&HAS_8 ? 0 : AUDIO_ENCODINGFLAG_EMULATED;
-return (0);
-case 4:
-strlcpy(fp->name, AudioEslinear_le, sizeof(fp->name));
-fp->encoding = AUDIO_ENCODING_SLINEAR_LE;
-fp->precision = 16;
-fp->flags = 0;
-return (0);
-case 5:
-strlcpy(fp->name, AudioEulinear_le, sizeof(fp->name));
-fp->encoding = AUDIO_ENCODING_ULINEAR_LE;
-fp->precision = 16;
-fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
-return (0);
-case 6:
-strlcpy(fp->name, AudioEslinear_be, sizeof(fp->name));
-fp->encoding = AUDIO_ENCODING_SLINEAR_BE;
-fp->precision = 16;
-fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
-return (0);
-case 7:
-strlcpy(fp->name, AudioEulinear_be, sizeof(fp->name));
-fp->encoding = AUDIO_ENCODING_ULINEAR_BE;
-fp->precision = 16;
-fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
-return (0);
-default:
-return (EINVAL);
-}
+ struct uaudio_softc *sc;
+ int flags;
+ int idx;
+
+ sc = addr;
+ flags = sc->sc_altflags;
+ if (sc->sc_dying)
+ return EIO;
+
+ if (sc->sc_nalts == 0 || flags == 0)
+ return ENXIO;
+
+ idx = fp->index;
+ switch (idx) {
+ case 0:
+ strlcpy(fp->name, AudioEulinear, sizeof(fp->name));
+ fp->encoding = AUDIO_ENCODING_ULINEAR;
+ fp->precision = 8;
+ fp->flags = flags&HAS_8U ? 0 : AUDIO_ENCODINGFLAG_EMULATED;
+ return (0);
+ case 1:
+ strlcpy(fp->name, AudioEmulaw, sizeof(fp->name));
+ fp->encoding = AUDIO_ENCODING_ULAW;
+ fp->precision = 8;
+ fp->flags = flags&HAS_MULAW ? 0 : AUDIO_ENCODINGFLAG_EMULATED;
+ return (0);
+ case 2:
+ strlcpy(fp->name, AudioEalaw, sizeof(fp->name));
+ fp->encoding = AUDIO_ENCODING_ALAW;
+ fp->precision = 8;
+ fp->flags = flags&HAS_ALAW ? 0 : AUDIO_ENCODINGFLAG_EMULATED;
+ return (0);
+ case 3:
+ strlcpy(fp->name, AudioEslinear, sizeof(fp->name));
+ fp->encoding = AUDIO_ENCODING_SLINEAR;
+ fp->precision = 8;
+ fp->flags = flags&HAS_8 ? 0 : AUDIO_ENCODINGFLAG_EMULATED;
+ return (0);
+ case 4:
+ strlcpy(fp->name, AudioEslinear_le, sizeof(fp->name));
+ fp->encoding = AUDIO_ENCODING_SLINEAR_LE;
+ fp->precision = 16;
+ fp->flags = 0;
+ return (0);
+ case 5:
+ strlcpy(fp->name, AudioEulinear_le, sizeof(fp->name));
+ fp->encoding = AUDIO_ENCODING_ULINEAR_LE;
+ fp->precision = 16;
+ fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
+ return (0);
+ case 6:
+ strlcpy(fp->name, AudioEslinear_be, sizeof(fp->name));
+ fp->encoding = AUDIO_ENCODING_SLINEAR_BE;
+ fp->precision = 16;
+ fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
+ return (0);
+ case 7:
+ strlcpy(fp->name, AudioEulinear_be, sizeof(fp->name));
+ fp->encoding = AUDIO_ENCODING_ULINEAR_BE;
+ fp->precision = 16;
+ fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
+ return (0);
+ default:
+ return (EINVAL);
+ }
}
#endif
-Static const usb_interface_descriptor_t *
+static const usb_interface_descriptor_t *
uaudio_find_iface(const char *buf, int size, int *offsp, int subtype)
{
-const usb_interface_descriptor_t *d;
+ const usb_interface_descriptor_t *d;
-while (*offsp < size) {
-d = (const void *)(buf + *offsp);
-*offsp += d->bLength;
-if (d->bDescriptorType == UDESC_INTERFACE &&
-d->bInterfaceClass == UICLASS_AUDIO &&
-d->bInterfaceSubClass == subtype)
-return d;
-}
-return NULL;
+ while (*offsp < size) {
+ d = (const void *)(buf + *offsp);
+ *offsp += d->bLength;
+ if (d->bDescriptorType == UDESC_INTERFACE &&
+ d->bInterfaceClass == UICLASS_AUDIO &&
+ d->bInterfaceSubClass == subtype)
+ return d;
+ }
+ return NULL;
}
-Static void
+static void
uaudio_mixer_add_ctl(struct uaudio_softc *sc, struct mixerctl *mc)
{
-int res;
-size_t len;
-struct mixerctl *nmc;
+ int res;
+ size_t len;
+ struct mixerctl *nmc;
#if defined(__FreeBSD__)
-if (mc->class < UAC_NCLASSES) {
-DPRINTF(("%s: adding %s.%dn",
-__func__, uac_names[mc->class], mc->ctl));
-} else {
-DPRINTF(("%s: adding %dn", __func__, mc->ctl));
-}
+ if (mc->class < UAC_NCLASSES) {
+ DPRINTF(("%s: adding %s.%d\n",
+ __func__, uac_names[mc->class], mc->ctl));
+ } else {
+ DPRINTF(("%s: adding %d\n", __func__, mc->ctl));
+ }
#else
-if (mc->class < UAC_NCLASSES) {
-DPRINTF(("%s: adding %s.%sn",
-__func__, uac_names[mc->class], mc->ctlname));
-} else {
-DPRINTF(("%s: adding %sn", __func__, mc->ctlname));
-}
-#endif
-len = sizeof(*mc) * (sc->sc_nctls + 1);
-nmc = malloc(len, M_USBDEV, M_NOWAIT);
-if (nmc == NULL) {
-printf("uaudio_mixer_add_ctl: no memoryn");
-return;
-}
-/* Copy old data, if there was any */
-if (sc->sc_nctls != 0) {
-memcpy(nmc, sc->sc_ctls, sizeof(*mc) * (sc->sc_nctls));
-free(sc->sc_ctls, M_USBDEV);
-}
-sc->sc_ctls = nmc;
-
-mc->delta = 0;
-if (mc->type == MIX_ON_OFF) {
-mc->minval = 0;
-mc->maxval = 1;
-} else if (mc->type == MIX_SELECTOR) {
-;
-} else {
-/* Determine min and max values. */
-mc->minval = uaudio_signext(mc->type,
-uaudio_get(sc, GET_MIN, UT_READ_CLASS_INTERFACE,
-mc->wValue[0], mc->wIndex,
-MIX_SIZE(mc->type)));
-mc->maxval = 1 + uaudio_signext(mc->type,
-uaudio_get(sc, GET_MAX, UT_READ_CLASS_INTERFACE,
-mc->wValue[0], mc->wIndex,
-MIX_SIZE(mc->type)));
-mc->mul = mc->maxval - mc->minval;
-if (mc->mul == 0)
-mc->mul = 1;
-res = uaudio_get(sc, GET_RES, UT_READ_CLASS_INTERFACE,
-mc->wValue[0], mc->wIndex,
-MIX_SIZE(mc->type));
-if (res > 0)
-mc->delta = (res * 255 + mc->mul/2) / mc->mul;
-}
+ if (mc->class < UAC_NCLASSES) {
+ DPRINTF(("%s: adding %s.%s\n",
+ __func__, uac_names[mc->class], mc->ctlname));
+ } else {
+ DPRINTF(("%s: adding %s\n", __func__, mc->ctlname));
+ }
+#endif
+ len = sizeof(*mc) * (sc->sc_nctls + 1);
+ nmc = malloc(len, M_USBDEV, M_NOWAIT);
+ if (nmc == NULL) {
+ printf("uaudio_mixer_add_ctl: no memory\n");
+ return;
+ }
+ /* Copy old data, if there was any */
+ if (sc->sc_nctls != 0) {
+ memcpy(nmc, sc->sc_ctls, sizeof(*mc) * (sc->sc_nctls));
+ free(sc->sc_ctls, M_USBDEV);
+ }
+ sc->sc_ctls = nmc;
+
+ mc->delta = 0;
+ if (mc->type == MIX_ON_OFF) {
+ mc->minval = 0;
+ mc->maxval = 1;
+ } else if (mc->type == MIX_SELECTOR) {
+ ;
+ } else {
+ /* Determine min and max values. */
+ mc->minval = uaudio_signext(mc->type,
+ uaudio_get(sc, GET_MIN, UT_READ_CLASS_INTERFACE,
+ mc->wValue[0], mc->wIndex,
+ MIX_SIZE(mc->type)));
+ mc->maxval = 1 + uaudio_signext(mc->type,
+ uaudio_get(sc, GET_MAX, UT_READ_CLASS_INTERFACE,
+ mc->wValue[0], mc->wIndex,
+ MIX_SIZE(mc->type)));
+ mc->mul = mc->maxval - mc->minval;
+ if (mc->mul == 0)
+ mc->mul = 1;
+ res = uaudio_get(sc, GET_RES, UT_READ_CLASS_INTERFACE,
+ mc->wValue[0], mc->wIndex,
+ MIX_SIZE(mc->type));
+ if (res > 0)
+ mc->delta = (res * 255 + mc->mul/2) / mc->mul;
+ }
-sc->sc_ctls[sc->sc_nctls++] = *mc;
+ sc->sc_ctls[sc->sc_nctls++] = *mc;
#ifdef USB_DEBUG
-if (uaudiodebug > 2) {
-int i;
-DPRINTF(("uaudio_mixer_add_ctl: wValue=%04x",mc->wValue[0]));
-for (i = 1; i < mc->nchan; i++)
-DPRINTF((",%04x", mc->wValue[i]));
-#if defined(__FreeBSD__)
-DPRINTF((" wIndex=%04x type=%d ctl='%d' "
-"min=%d max=%dn",
-mc->wIndex, mc->type, mc->ctl,
-mc->minval, mc->maxval));
+ if (uaudiodebug > 2) {
+ int i;
+ DPRINTF(("uaudio_mixer_add_ctl: wValue=%04x",mc->wValue[0]));
+ for (i = 1; i < mc->nchan; i++)
+ DPRINTF((",%04x", mc->wValue[i]));
+#if defined(__FreeBSD__)
+ DPRINTF((" wIndex=%04x type=%d ctl='%d' "
+ "min=%d max=%d\n",
+ mc->wIndex, mc->type, mc->ctl,
+ mc->minval, mc->maxval));
#else
-DPRINTF((" wIndex=%04x type=%d name='%s' unit='%s' "
-"min=%d max=%dn",
-mc->wIndex, mc->type, mc->ctlname, mc->ctlunit,
-mc->minval, mc->maxval));
+ DPRINTF((" wIndex=%04x type=%d name='%s' unit='%s' "
+ "min=%d max=%d\n",
+ mc->wIndex, mc->type, mc->ctlname, mc->ctlunit,
+ mc->minval, mc->maxval));
#endif
-}
+ }
#endif
}
#if defined(__NetBSD__) || defined(__OpenBSD__)
-Static char *
+static char *
uaudio_id_name(struct uaudio_softc *sc, const struct io_terminal *iot, int id)
{
-static char buf[32];
+ static char buf[32];
-snprintf(buf, sizeof(buf), "i%d", id);
-return buf;
+ snprintf(buf, sizeof(buf), "i%d", id);
+ return buf;
}
#endif
#ifdef USB_DEBUG
-Static void
+static void
uaudio_dump_cluster(const struct usb_audio_cluster *cl)
{
-static const char *channel_names[16] = {
-"LEFT", "RIGHT", "CENTER", "LFE",
-"LEFT_SURROUND", "RIGHT_SURROUND", "LEFT_CENTER", "RIGHT_CENTER",
-"SURROUND", "LEFT_SIDE", "RIGHT_SIDE", "TOP",
-"RESERVED12", "RESERVED13", "RESERVED14", "RESERVED15",
-};
-int cc, i, first;
-
-cc = UGETW(cl->wChannelConfig);
-logprintf("cluster: bNrChannels=%u wChannelConfig=0x%.4x",
-cl->bNrChannels, cc);
-first = TRUE;
-for (i = 0; cc != 0; i++) {
-if (cc & 1) {
-logprintf("%c%s", first ? '<' : ',', channel_names[i]);
-first = FALSE;
-}
-cc = cc >> 1;
-}
-logprintf("> iChannelNames=%u", cl->iChannelNames);
+ static const char *channel_names[16] = {
+ "LEFT", "RIGHT", "CENTER", "LFE",
+ "LEFT_SURROUND", "RIGHT_SURROUND", "LEFT_CENTER", "RIGHT_CENTER",
+ "SURROUND", "LEFT_SIDE", "RIGHT_SIDE", "TOP",
+ "RESERVED12", "RESERVED13", "RESERVED14", "RESERVED15",
+ };
+ int cc, i, first;
+
+ cc = UGETW(cl->wChannelConfig);
+ printf("cluster: bNrChannels=%u wChannelConfig=0x%.4x",
+ cl->bNrChannels, cc);
+ first = TRUE;
+ for (i = 0; cc != 0; i++) {
+ if (cc & 1) {
+ printf("%c%s", first ? '<' : ',', channel_names[i]);
+ first = FALSE;
+ }
+ cc = cc >> 1;
+ }
+ printf("> iChannelNames=%u", cl->iChannelNames);
}
#endif
-Static struct usb_audio_cluster
+static struct usb_audio_cluster
uaudio_get_cluster(int id, const struct io_terminal *iot)
{
-struct usb_audio_cluster r;
-const usb_descriptor_t *dp;
-int i;
-
-for (i = 0; i < 25; i++) { /* avoid infinite loops */
-dp = iot[id].d.desc;
-if (dp == 0)
-goto bad;
-switch (dp->bDescriptorSubtype) {
-case UDESCSUB_AC_INPUT:
-r.bNrChannels = iot[id].d.it->bNrChannels;
-USETW(r.wChannelConfig, UGETW(iot[id].d.it->wChannelConfig));
-r.iChannelNames = iot[id].d.it->iChannelNames;
-return r;
-case UDESCSUB_AC_OUTPUT:
-id = iot[id].d.ot->bSourceId;
-break;
-case UDESCSUB_AC_MIXER:
-r = *(const struct usb_audio_cluster *)
-&iot[id].d.mu->baSourceId[iot[id].d.mu->bNrInPins];
-return r;
-case UDESCSUB_AC_SELECTOR:
-/* XXX This is not really right */
-id = iot[id].d.su->baSourceId[0];
-break;
-case UDESCSUB_AC_FEATURE:
-id = iot[id].d.fu->bSourceId;
-break;
-case UDESCSUB_AC_PROCESSING:
-r = *(const struct usb_audio_cluster *)
-&iot[id].d.pu->baSourceId[iot[id].d.pu->bNrInPins];
-return r;
-case UDESCSUB_AC_EXTENSION:
-r = *(const struct usb_audio_cluster *)
-&iot[id].d.eu->baSourceId[iot[id].d.eu->bNrInPins];
-return r;
-default:
-goto bad;
-}
-}
-bad:
-printf("uaudio_get_cluster: bad datan");
-memset(&r, 0, sizeof r);
-return r;
+ struct usb_audio_cluster r;
+ const usb_descriptor_t *dp;
+ int i;
+
+ for (i = 0; i < 25; i++) { /* avoid infinite loops */
+ dp = iot[id].d.desc;
+ if (dp == 0)
+ goto bad;
+ switch (dp->bDescriptorSubtype) {
+ case UDESCSUB_AC_INPUT:
+ r.bNrChannels = iot[id].d.it->bNrChannels;
+ USETW(r.wChannelConfig, UGETW(iot[id].d.it->wChannelConfig));
+ r.iChannelNames = iot[id].d.it->iChannelNames;
+ return r;
+ case UDESCSUB_AC_OUTPUT:
+ id = iot[id].d.ot->bSourceId;
+ break;
+ case UDESCSUB_AC_MIXER:
+ r = *(const struct usb_audio_cluster *)
+ &iot[id].d.mu->baSourceId[iot[id].d.mu->bNrInPins];
+ return r;
+ case UDESCSUB_AC_SELECTOR:
+ /* XXX This is not really right */
+ id = iot[id].d.su->baSourceId[0];
+ break;
+ case UDESCSUB_AC_FEATURE:
+ id = iot[id].d.fu->bSourceId;
+ break;
+ case UDESCSUB_AC_PROCESSING:
+ r = *(const struct usb_audio_cluster *)
+ &iot[id].d.pu->baSourceId[iot[id].d.pu->bNrInPins];
+ return r;
+ case UDESCSUB_AC_EXTENSION:
+ r = *(const struct usb_audio_cluster *)
+ &iot[id].d.eu->baSourceId[iot[id].d.eu->bNrInPins];
+ return r;
+ default:
+ goto bad;
+ }
+ }
+ bad:
+ printf("uaudio_get_cluster: bad data\n");
+ memset(&r, 0, sizeof r);
+ return r;
}
-Static void
+static void
uaudio_add_input(struct uaudio_softc *sc, const struct io_terminal *iot, int id)
{
#ifdef USB_DEBUG
-const struct usb_audio_input_terminal *d = iot[id].d.it;
+ const struct usb_audio_input_terminal *d = iot[id].d.it;
-DPRINTFN(2,("uaudio_add_input: bTerminalId=%d wTerminalType=0x%04x "
-"bAssocTerminal=%d bNrChannels=%d wChannelConfig=%d "
-"iChannelNames=%d iTerminal=%dn",
-d->bTerminalId, UGETW(d->wTerminalType), d->bAssocTerminal,
-d->bNrChannels, UGETW(d->wChannelConfig),
-d->iChannelNames, d->iTerminal));
+ DPRINTFN(2,("uaudio_add_input: bTerminalId=%d wTerminalType=0x%04x "
+ "bAssocTerminal=%d bNrChannels=%d wChannelConfig=%d "
+ "iChannelNames=%d iTerminal=%d\n",
+ d->bTerminalId, UGETW(d->wTerminalType), d->bAssocTerminal,
+ d->bNrChannels, UGETW(d->wChannelConfig),
+ d->iChannelNames, d->iTerminal));
#endif
}
-Static void
+static void
uaudio_add_output(struct uaudio_softc *sc, const struct io_terminal *iot, int id)
{
#ifdef USB_DEBUG
-const struct usb_audio_output_terminal *d;
+ const struct usb_audio_output_terminal *d;
-d = iot[id].d.ot;
-DPRINTFN(2,("uaudio_add_output: bTerminalId=%d wTerminalType=0x%04x "
-"bAssocTerminal=%d bSourceId=%d iTerminal=%dn",
-d->bTerminalId, UGETW(d->wTerminalType), d->bAssocTerminal,
-d->bSourceId, d->iTerminal));
+ d = iot[id].d.ot;
+ DPRINTFN(2,("uaudio_add_output: bTerminalId=%d wTerminalType=0x%04x "
+ "bAssocTerminal=%d bSourceId=%d iTerminal=%d\n",
+ d->bTerminalId, UGETW(d->wTerminalType), d->bAssocTerminal,
+ d->bSourceId, d->iTerminal));
#endif
}
-Static void
+static void
uaudio_add_mixer(struct uaudio_softc *sc, const struct io_terminal *iot, int id)
{
-const struct usb_audio_mixer_unit *d = iot[id].d.mu;
-const struct usb_audio_mixer_unit_1 *d1;
-int c, chs, ichs, ochs, i, o, bno, p, mo, mc, k;
-const uByte *bm;
-struct mixerctl mix;
-
-DPRINTFN(2,("uaudio_add_mixer: bUnitId=%d bNrInPins=%dn",
-d->bUnitId, d->bNrInPins));
-
-/* Compute the number of input channels */
-ichs = 0;
-for (i = 0; i < d->bNrInPins; i++)
-ichs += uaudio_get_cluster(d->baSourceId[i], iot).bNrChannels;
-
-/* and the number of output channels */
-d1 = (const struct usb_audio_mixer_unit_1 *)&d->baSourceId[d->bNrInPins];
-ochs = d1->bNrChannels;
-DPRINTFN(2,("uaudio_add_mixer: ichs=%d ochs=%dn", ichs, ochs));
-
-bm = d1->bmControls;
-mix.wIndex = MAKE(d->bUnitId, sc->sc_ac_iface);
-uaudio_determine_class(&iot[id], &mix);
-mix.type = MIX_SIGNED_16;
+ const struct usb_audio_mixer_unit *d = iot[id].d.mu;
+ const struct usb_audio_mixer_unit_1 *d1;
+ int c, chs, ichs, ochs, i, o, bno, p, mo, mc, k;
+ const uByte *bm;
+ struct mixerctl mix;
+
+ DPRINTFN(2,("uaudio_add_mixer: bUnitId=%d bNrInPins=%d\n",
+ d->bUnitId, d->bNrInPins));
+
+ /* Compute the number of input channels */
+ ichs = 0;
+ for (i = 0; i < d->bNrInPins; i++)
+ ichs += uaudio_get_cluster(d->baSourceId[i], iot).bNrChannels;
+
+ /* and the number of output channels */
+ d1 = (const struct usb_audio_mixer_unit_1 *)&d->baSourceId[d->bNrInPins];
+ ochs = d1->bNrChannels;
+ DPRINTFN(2,("uaudio_add_mixer: ichs=%d ochs=%d\n", ichs, ochs));
+
+ bm = d1->bmControls;
+ mix.wIndex = MAKE(d->bUnitId, sc->sc_ac_iface);
+ uaudio_determine_class(&iot[id], &mix);
+ mix.type = MIX_SIGNED_16;
#if !defined(__FreeBSD__) /* XXXXX */
-mix.ctlunit = AudioNvolume;
+ mix.ctlunit = AudioNvolume;
#endif
#define BIT(bno) ((bm[bno / 8] >> (7 - bno % 8)) & 1)
-for (p = i = 0; i < d->bNrInPins; i++) {
-chs = uaudio_get_cluster(d->baSourceId[i], iot).bNrChannels;
-mc = 0;
-for (c = 0; c < chs; c++) {
-mo = 0;
-for (o = 0; o < ochs; o++) {
-bno = (p + c) * ochs + o;
-if (BIT(bno))
-mo++;
-}
-if (mo == 1)
-mc++;
-}
-if (mc == chs && chs <= MIX_MAX_CHAN) {
-k = 0;
-for (c = 0; c < chs; c++)
-for (o = 0; o < ochs; o++) {
-bno = (p + c) * ochs + o;
-if (BIT(bno))
-mix.wValue[k++] =
-MAKE(p+c+1, o+1);
-}
+ for (p = i = 0; i < d->bNrInPins; i++) {
+ chs = uaudio_get_cluster(d->baSourceId[i], iot).bNrChannels;
+ mc = 0;
+ for (c = 0; c < chs; c++) {
+ mo = 0;
+ for (o = 0; o < ochs; o++) {
+ bno = (p + c) * ochs + o;
+ if (BIT(bno))
+ mo++;
+ }
+ if (mo == 1)
+ mc++;
+ }
+ if (mc == chs && chs <= MIX_MAX_CHAN) {
+ k = 0;
+ for (c = 0; c < chs; c++)
+ for (o = 0; o < ochs; o++) {
+ bno = (p + c) * ochs + o;
+ if (BIT(bno))
+ mix.wValue[k++] =
+ MAKE(p+c+1, o+1);
+ }
#if !defined(__FreeBSD__)
-snprintf(mix.ctlname, sizeof(mix.ctlname), "mix%d-%s",
-d->bUnitId, uaudio_id_name(sc, iot,
-d->baSourceId[i]));
-#endif
-mix.nchan = chs;
-uaudio_mixer_add_ctl(sc, &mix);
-} else {
-/* XXX */
-}
+ snprintf(mix.ctlname, sizeof(mix.ctlname), "mix%d-%s",
+ d->bUnitId, uaudio_id_name(sc, iot,
+ d->baSourceId[i]));
+#endif
+ mix.nchan = chs;
+ uaudio_mixer_add_ctl(sc, &mix);
+ } else {
+ /* XXX */
+ }
#undef BIT
-p += chs;
-}
+ p += chs;
+ }
}
-Static void
+static void
uaudio_add_selector(struct uaudio_softc *sc, const struct io_terminal *iot, int id)
{
-const struct usb_audio_selector_unit *d;
-struct mixerctl mix;
+ const struct usb_audio_selector_unit *d;
+ struct mixerctl mix;
#if !defined(__FreeBSD__)
-int i, wp;
+ int i, wp;
#else
-int i;
-struct mixerctl dummy;
+ int i;
+ struct mixerctl dummy;
#endif
-d = iot[id].d.su;
-DPRINTFN(2,("uaudio_add_selector: bUnitId=%d bNrInPins=%dn",
-d->bUnitId, d->bNrInPins));
-mix.wIndex = MAKE(d->bUnitId, sc->sc_ac_iface);
-mix.wValue[0] = MAKE(0, 0);
-uaudio_determine_class(&iot[id], &mix);
-mix.nchan = 1;
-mix.type = MIX_SELECTOR;
-#if defined(__FreeBSD__)
-mix.ctl = SOUND_MIXER_NRDEVICES; /* XXXXX */
-mix.minval = 1;
-mix.maxval = d->bNrInPins;
-mix.mul = mix.maxval - mix.minval;
-for (i = 0; i < MAX_SELECTOR_INPUT_PIN; i++) {
-mix.slctrtype[i] = SOUND_MIXER_NRDEVICES;
-}
-for (i = mix.minval; i <= mix.maxval; i++) {
-mix.slctrtype[i - 1] = uaudio_feature_name(&iot[d->baSourceId[i - 1]], &dummy);
-}
+ d = iot[id].d.su;
+ DPRINTFN(2,("uaudio_add_selector: bUnitId=%d bNrInPins=%d\n",
+ d->bUnitId, d->bNrInPins));
+ mix.wIndex = MAKE(d->bUnitId, sc->sc_ac_iface);
+ mix.wValue[0] = MAKE(0, 0);
+ uaudio_determine_class(&iot[id], &mix);
+ mix.nchan = 1;
+ mix.type = MIX_SELECTOR;
+#if defined(__FreeBSD__)
+ mix.ctl = SOUND_MIXER_NRDEVICES; /* XXXXX */
+ mix.minval = 1;
+ mix.maxval = d->bNrInPins;
+ mix.mul = mix.maxval - mix.minval;
+ for (i = 0; i < MAX_SELECTOR_INPUT_PIN; i++) {
+ mix.slctrtype[i] = SOUND_MIXER_NRDEVICES;
+ }
+ for (i = mix.minval; i <= mix.maxval; i++) {
+ mix.slctrtype[i - 1] = uaudio_feature_name(&iot[d->baSourceId[i - 1]], &dummy);
+ }
#else
-mix.ctlunit = "";
-mix.minval = 1;
-mix.maxval = d->bNrInPins;
-mix.mul = mix.maxval - mix.minval;
-wp = snprintf(mix.ctlname, MAX_AUDIO_DEV_LEN, "sel%d-", d->bUnitId);
-for (i = 1; i <= d->bNrInPins; i++) {
-wp += snprintf(mix.ctlname + wp, MAX_AUDIO_DEV_LEN - wp,
-"i%d", d->baSourceId[i - 1]);
-if (wp > MAX_AUDIO_DEV_LEN - 1)
-break;
-}
+ mix.ctlunit = "";
+ mix.minval = 1;
+ mix.maxval = d->bNrInPins;
+ mix.mul = mix.maxval - mix.minval;
+ wp = snprintf(mix.ctlname, MAX_AUDIO_DEV_LEN, "sel%d-", d->bUnitId);
+ for (i = 1; i <= d->bNrInPins; i++) {
+ wp += snprintf(mix.ctlname + wp, MAX_AUDIO_DEV_LEN - wp,
+ "i%d", d->baSourceId[i - 1]);
+ if (wp > MAX_AUDIO_DEV_LEN - 1)
+ break;
+ }
#endif
-uaudio_mixer_add_ctl(sc, &mix);
+ uaudio_mixer_add_ctl(sc, &mix);
}
#ifdef USB_DEBUG
-Static const char *
+static const char *
uaudio_get_terminal_name(int terminal_type)
{
-static char buf[100];
+ static char buf[100];
-switch (terminal_type) {
-/* USB terminal types */
-case UAT_UNDEFINED: return "UAT_UNDEFINED";
-case UAT_STREAM: return "UAT_STREAM";
-case UAT_VENDOR: return "UAT_VENDOR";
-/* input terminal types */
-case UATI_UNDEFINED: return "UATI_UNDEFINED";
-case UATI_MICROPHONE: return "UATI_MICROPHONE";
-case UATI_DESKMICROPHONE: return "UATI_DESKMICROPHONE";
-case UATI_PERSONALMICROPHONE: return "UATI_PERSONALMICROPHONE";
-case UATI_OMNIMICROPHONE: return "UATI_OMNIMICROPHONE";
-case UATI_MICROPHONEARRAY: return "UATI_MICROPHONEARRAY";
-case UATI_PROCMICROPHONEARR: return "UATI_PROCMICROPHONEARR";
-/* output terminal types */
-case UATO_UNDEFINED: return "UATO_UNDEFINED";
-case UATO_SPEAKER: return "UATO_SPEAKER";
-case UATO_HEADPHONES: return "UATO_HEADPHONES";
-case UATO_DISPLAYAUDIO: return "UATO_DISPLAYAUDIO";
-case UATO_DESKTOPSPEAKER: return "UATO_DESKTOPSPEAKER";
-case UATO_ROOMSPEAKER: return "UATO_ROOMSPEAKER";
-case UATO_COMMSPEAKER: return "UATO_COMMSPEAKER";
-case UATO_SUBWOOFER: return "UATO_SUBWOOFER";
-/* bidir terminal types */
-case UATB_UNDEFINED: return "UATB_UNDEFINED";
-case UATB_HANDSET: return "UATB_HANDSET";
-case UATB_HEADSET: return "UATB_HEADSET";
-case UATB_SPEAKERPHONE: return "UATB_SPEAKERPHONE";
-case UATB_SPEAKERPHONEESUP: return "UATB_SPEAKERPHONEESUP";
-case UATB_SPEAKERPHONEECANC: return "UATB_SPEAKERPHONEECANC";
-/* telephony terminal types */
-case UATT_UNDEFINED: return "UATT_UNDEFINED";
-case UATT_PHONELINE: return "UATT_PHONELINE";
-case UATT_TELEPHONE: return "UATT_TELEPHONE";
-case UATT_DOWNLINEPHONE: return "UATT_DOWNLINEPHONE";
-/* external terminal types */
-case UATE_UNDEFINED: return "UATE_UNDEFINED";
-case UATE_ANALOGCONN: return "UATE_ANALOGCONN";
-case UATE_LINECONN: return "UATE_LINECONN";
-case UATE_LEGACYCONN: return "UATE_LEGACYCONN";
-case UATE_DIGITALAUIFC: return "UATE_DIGITALAUIFC";
-case UATE_SPDIF: return "UATE_SPDIF";
-case UATE_1394DA: return "UATE_1394DA";
-case UATE_1394DV: return "UATE_1394DV";
-/* embedded function terminal types */
-case UATF_UNDEFINED: return "UATF_UNDEFINED";
-case UATF_CALIBNOISE: return "UATF_CALIBNOISE";
-case UATF_EQUNOISE: return "UATF_EQUNOISE";
-case UATF_CDPLAYER: return "UATF_CDPLAYER";
-case UATF_DAT: return "UATF_DAT";
-case UATF_DCC: return "UATF_DCC";
-case UATF_MINIDISK: return "UATF_MINIDISK";
-case UATF_ANALOGTAPE: return "UATF_ANALOGTAPE";
-case UATF_PHONOGRAPH: return "UATF_PHONOGRAPH";
-case UATF_VCRAUDIO: return "UATF_VCRAUDIO";
-case UATF_VIDEODISCAUDIO: return "UATF_VIDEODISCAUDIO";
-case UATF_DVDAUDIO: return "UATF_DVDAUDIO";
-case UATF_TVTUNERAUDIO: return "UATF_TVTUNERAUDIO";
-case UATF_SATELLITE: return "UATF_SATELLITE";
-case UATF_CABLETUNER: return "UATF_CABLETUNER";
-case UATF_DSS: return "UATF_DSS";
-case UATF_RADIORECV: return "UATF_RADIORECV";
-case UATF_RADIOXMIT: return "UATF_RADIOXMIT";
-case UATF_MULTITRACK: return "UATF_MULTITRACK";
-case UATF_SYNTHESIZER: return "UATF_SYNTHESIZER";
-default:
-snprintf(buf, sizeof(buf), "unknown type (0x%.4x)", terminal_type);
-return buf;
-}
+ switch (terminal_type) {
+ /* USB terminal types */
+ case UAT_UNDEFINED: return "UAT_UNDEFINED";
+ case UAT_STREAM: return "UAT_STREAM";
+ case UAT_VENDOR: return "UAT_VENDOR";
+ /* input terminal types */
+ case UATI_UNDEFINED: return "UATI_UNDEFINED";
+ case UATI_MICROPHONE: return "UATI_MICROPHONE";
+ case UATI_DESKMICROPHONE: return "UATI_DESKMICROPHONE";
+ case UATI_PERSONALMICROPHONE: return "UATI_PERSONALMICROPHONE";
+ case UATI_OMNIMICROPHONE: return "UATI_OMNIMICROPHONE";
+ case UATI_MICROPHONEARRAY: return "UATI_MICROPHONEARRAY";
+ case UATI_PROCMICROPHONEARR: return "UATI_PROCMICROPHONEARR";
+ /* output terminal types */
+ case UATO_UNDEFINED: return "UATO_UNDEFINED";
+ case UATO_SPEAKER: return "UATO_SPEAKER";
+ case UATO_HEADPHONES: return "UATO_HEADPHONES";
+ case UATO_DISPLAYAUDIO: return "UATO_DISPLAYAUDIO";
+ case UATO_DESKTOPSPEAKER: return "UATO_DESKTOPSPEAKER";
+ case UATO_ROOMSPEAKER: return "UATO_ROOMSPEAKER";
+ case UATO_COMMSPEAKER: return "UATO_COMMSPEAKER";
+ case UATO_SUBWOOFER: return "UATO_SUBWOOFER";
+ /* bidir terminal types */
+ case UATB_UNDEFINED: return "UATB_UNDEFINED";
+ case UATB_HANDSET: return "UATB_HANDSET";
+ case UATB_HEADSET: return "UATB_HEADSET";
+ case UATB_SPEAKERPHONE: return "UATB_SPEAKERPHONE";
+ case UATB_SPEAKERPHONEESUP: return "UATB_SPEAKERPHONEESUP";
+ case UATB_SPEAKERPHONEECANC: return "UATB_SPEAKERPHONEECANC";
+ /* telephony terminal types */
+ case UATT_UNDEFINED: return "UATT_UNDEFINED";
+ case UATT_PHONELINE: return "UATT_PHONELINE";
+ case UATT_TELEPHONE: return "UATT_TELEPHONE";
+ case UATT_DOWNLINEPHONE: return "UATT_DOWNLINEPHONE";
+ /* external terminal types */
+ case UATE_UNDEFINED: return "UATE_UNDEFINED";
+ case UATE_ANALOGCONN: return "UATE_ANALOGCONN";
+ case UATE_LINECONN: return "UATE_LINECONN";
+ case UATE_LEGACYCONN: return "UATE_LEGACYCONN";
+ case UATE_DIGITALAUIFC: return "UATE_DIGITALAUIFC";
+ case UATE_SPDIF: return "UATE_SPDIF";
+ case UATE_1394DA: return "UATE_1394DA";
+ case UATE_1394DV: return "UATE_1394DV";
+ /* embedded function terminal types */
+ case UATF_UNDEFINED: return "UATF_UNDEFINED";
+ case UATF_CALIBNOISE: return "UATF_CALIBNOISE";
+ case UATF_EQUNOISE: return "UATF_EQUNOISE";
+ case UATF_CDPLAYER: return "UATF_CDPLAYER";
+ case UATF_DAT: return "UATF_DAT";
+ case UATF_DCC: return "UATF_DCC";
+ case UATF_MINIDISK: return "UATF_MINIDISK";
+ case UATF_ANALOGTAPE: return "UATF_ANALOGTAPE";
+ case UATF_PHONOGRAPH: return "UATF_PHONOGRAPH";
+ case UATF_VCRAUDIO: return "UATF_VCRAUDIO";
+ case UATF_VIDEODISCAUDIO: return "UATF_VIDEODISCAUDIO";
+ case UATF_DVDAUDIO: return "UATF_DVDAUDIO";
+ case UATF_TVTUNERAUDIO: return "UATF_TVTUNERAUDIO";
+ case UATF_SATELLITE: return "UATF_SATELLITE";
+ case UATF_CABLETUNER: return "UATF_CABLETUNER";
+ case UATF_DSS: return "UATF_DSS";
+ case UATF_RADIORECV: return "UATF_RADIORECV";
+ case UATF_RADIOXMIT: return "UATF_RADIOXMIT";
+ case UATF_MULTITRACK: return "UATF_MULTITRACK";
+ case UATF_SYNTHESIZER: return "UATF_SYNTHESIZER";
+ default:
+ snprintf(buf, sizeof(buf), "unknown type (0x%.4x)", terminal_type);
+ return buf;
+ }
}
#endif
-Static int
+static int
uaudio_determine_class(const struct io_terminal *iot, struct mixerctl *mix)
{
-int terminal_type;
+ int terminal_type;
-if (iot == NULL || iot->output == NULL) {
-mix->class = UAC_OUTPUT;
-return 0;
-}
-terminal_type = 0;
-if (iot->output->size == 1)
-terminal_type = iot->output->terminals[0];
-/*
-* If the only output terminal is USB,
-* the class is UAC_RECORD.
-*/
-if ((terminal_type & 0xff00) == (UAT_UNDEFINED & 0xff00)) {
-mix->class = UAC_RECORD;
-if (iot->inputs_size == 1
-&& iot->inputs[0] != NULL
-&& iot->inputs[0]->size == 1)
-return iot->inputs[0]->terminals[0];
-else
-return 0;
-}
-/*
-* If the ultimate destination of the unit is just one output
-* terminal and the unit is connected to the output terminal
-* directly, the class is UAC_OUTPUT.
-*/
-if (terminal_type != 0 && iot->direct) {
-mix->class = UAC_OUTPUT;
-return terminal_type;
-}
-/*
-* If the unit is connected to just one input terminal,
-* the class is UAC_INPUT.
-*/
-if (iot->inputs_size == 1 && iot->inputs[0] != NULL
-&& iot->inputs[0]->size == 1) {
-mix->class = UAC_INPUT;
-return iot->inputs[0]->terminals[0];
-}
-/*
-* Otherwise, the class is UAC_OUTPUT.
-*/
-mix->class = UAC_OUTPUT;
-return terminal_type;
+ if (iot == NULL || iot->output == NULL) {
+ mix->class = UAC_OUTPUT;
+ return 0;
+ }
+ terminal_type = 0;
+ if (iot->output->size == 1)
+ terminal_type = iot->output->terminals[0];
+ /*
+ * If the only output terminal is USB,
+ * the class is UAC_RECORD.
+ */
+ if ((terminal_type & 0xff00) == (UAT_UNDEFINED & 0xff00)) {
+ mix->class = UAC_RECORD;
+ if (iot->inputs_size == 1
+ && iot->inputs[0] != NULL
+ && iot->inputs[0]->size == 1)
+ return iot->inputs[0]->terminals[0];
+ else
+ return 0;
+ }
+ /*
+ * If the ultimate destination of the unit is just one output
+ * terminal and the unit is connected to the output terminal
+ * directly, the class is UAC_OUTPUT.
+ */
+ if (terminal_type != 0 && iot->direct) {
+ mix->class = UAC_OUTPUT;
+ return terminal_type;
+ }
+ /*
+ * If the unit is connected to just one input terminal,
+ * the class is UAC_INPUT.
+ */
+ if (iot->inputs_size == 1 && iot->inputs[0] != NULL
+ && iot->inputs[0]->size == 1) {
+ mix->class = UAC_INPUT;
+ return iot->inputs[0]->terminals[0];
+ }
+ /*
+ * Otherwise, the class is UAC_OUTPUT.
+ */
+ mix->class = UAC_OUTPUT;
+ return terminal_type;
}
#if defined(__FreeBSD__)
-const int
+static int
uaudio_feature_name(const struct io_terminal *iot, struct mixerctl *mix)
{
-int terminal_type;
+ int terminal_type;
-terminal_type = uaudio_determine_class(iot, mix);
-if (mix->class == UAC_RECORD && terminal_type == 0)
-return SOUND_MIXER_IMIX;
-DPRINTF(("%s: terminal_type=%sn", __func__,
-uaudio_get_terminal_name(terminal_type)));
-switch (terminal_type) {
-case UAT_STREAM:
-return SOUND_MIXER_PCM;
-
-case UATI_MICROPHONE:
-case UATI_DESKMICROPHONE:
-case UATI_PERSONALMICROPHONE:
-case UATI_OMNIMICROPHONE:
-case UATI_MICROPHONEARRAY:
-case UATI_PROCMICROPHONEARR:
-return SOUND_MIXER_MIC;
-
-case UATO_SPEAKER:
-case UATO_DESKTOPSPEAKER:
-case UATO_ROOMSPEAKER:
-case UATO_COMMSPEAKER:
-return SOUND_MIXER_SPEAKER;
-
-case UATE_ANALOGCONN:
-case UATE_LINECONN:
-case UATE_LEGACYCONN:
-return SOUND_MIXER_LINE;
-
-case UATE_DIGITALAUIFC:
-case UATE_SPDIF:
-case UATE_1394DA:
-case UATE_1394DV:
-return SOUND_MIXER_ALTPCM;
-
-case UATF_CDPLAYER:
-return SOUND_MIXER_CD;
-
-case UATF_SYNTHESIZER:
-return SOUND_MIXER_SYNTH;
-
-case UATF_VIDEODISCAUDIO:
-case UATF_DVDAUDIO:
-case UATF_TVTUNERAUDIO:
-return SOUND_MIXER_VIDEO;
+ terminal_type = uaudio_determine_class(iot, mix);
+ if (mix->class == UAC_RECORD && terminal_type == 0)
+ return SOUND_MIXER_IMIX;
+ DPRINTF(("%s: terminal_type=%s\n", __func__,
+ uaudio_get_terminal_name(terminal_type)));
+ switch (terminal_type) {
+ case UAT_STREAM:
+ return SOUND_MIXER_PCM;
+
+ case UATI_MICROPHONE:
+ case UATI_DESKMICROPHONE:
+ case UATI_PERSONALMICROPHONE:
+ case UATI_OMNIMICROPHONE:
+ case UATI_MICROPHONEARRAY:
+ case UATI_PROCMICROPHONEARR:
+ return SOUND_MIXER_MIC;
+
+ case UATO_SPEAKER:
+ case UATO_DESKTOPSPEAKER:
+ case UATO_ROOMSPEAKER:
+ case UATO_COMMSPEAKER:
+ return SOUND_MIXER_SPEAKER;
+
+ case UATE_ANALOGCONN:
+ case UATE_LINECONN:
+ case UATE_LEGACYCONN:
+ return SOUND_MIXER_LINE;
+
+ case UATE_DIGITALAUIFC:
+ case UATE_SPDIF:
+ case UATE_1394DA:
+ case UATE_1394DV:
+ return SOUND_MIXER_ALTPCM;
+
+ case UATF_CDPLAYER:
+ return SOUND_MIXER_CD;
+
+ case UATF_SYNTHESIZER:
+ return SOUND_MIXER_SYNTH;
+
+ case UATF_VIDEODISCAUDIO:
+ case UATF_DVDAUDIO:
+ case UATF_TVTUNERAUDIO:
+ return SOUND_MIXER_VIDEO;
/* telephony terminal types */
-case UATT_UNDEFINED:
-case UATT_PHONELINE:
-case UATT_TELEPHONE:
-case UATT_DOWNLINEPHONE:
-return SOUND_MIXER_PHONEIN;
+ case UATT_UNDEFINED:
+ case UATT_PHONELINE:
+ case UATT_TELEPHONE:
+ case UATT_DOWNLINEPHONE:
+ return SOUND_MIXER_PHONEIN;
/* return SOUND_MIXER_PHONEOUT;*/
-case UATF_RADIORECV:
-case UATF_RADIOXMIT:
-return SOUND_MIXER_RADIO;
-
-case UAT_UNDEFINED:
-case UAT_VENDOR:
-case UATI_UNDEFINED:
+ case UATF_RADIORECV:
+ case UATF_RADIOXMIT:
+ return SOUND_MIXER_RADIO;
+
+ case UAT_UNDEFINED:
+ case UAT_VENDOR:
+ case UATI_UNDEFINED:
/* output terminal types */
-case UATO_UNDEFINED:
-case UATO_DISPLAYAUDIO:
-case UATO_SUBWOOFER:
-case UATO_HEADPHONES:
+ case UATO_UNDEFINED:
+ case UATO_DISPLAYAUDIO:
+ case UATO_SUBWOOFER:
+ case UATO_HEADPHONES:
/* bidir terminal types */
-case UATB_UNDEFINED:
-case UATB_HANDSET:
-case UATB_HEADSET:
-case UATB_SPEAKERPHONE:
-case UATB_SPEAKERPHONEESUP:
-case UATB_SPEAKERPHONEECANC:
+ case UATB_UNDEFINED:
+ case UATB_HANDSET:
+ case UATB_HEADSET:
+ case UATB_SPEAKERPHONE:
+ case UATB_SPEAKERPHONEESUP:
+ case UATB_SPEAKERPHONEECANC:
/* external terminal types */
-case UATE_UNDEFINED:
+ case UATE_UNDEFINED:
/* embedded function terminal types */
-case UATF_UNDEFINED:
-case UATF_CALIBNOISE:
-case UATF_EQUNOISE:
-case UATF_DAT:
-case UATF_DCC:
-case UATF_MINIDISK:
-case UATF_ANALOGTAPE:
-case UATF_PHONOGRAPH:
-case UATF_VCRAUDIO:
-case UATF_SATELLITE:
-case UATF_CABLETUNER:
-case UATF_DSS:
-case UATF_MULTITRACK:
-case 0xffff:
-default:
-DPRINTF(("%s: 'master' for 0x%.4xn", __func__, terminal_type));
-return SOUND_MIXER_VOLUME;
-}
-return SOUND_MIXER_VOLUME;
+ case UATF_UNDEFINED:
+ case UATF_CALIBNOISE:
+ case UATF_EQUNOISE:
+ case UATF_DAT:
+ case UATF_DCC:
+ case UATF_MINIDISK:
+ case UATF_ANALOGTAPE:
+ case UATF_PHONOGRAPH:
+ case UATF_VCRAUDIO:
+ case UATF_SATELLITE:
+ case UATF_CABLETUNER:
+ case UATF_DSS:
+ case UATF_MULTITRACK:
+ case 0xffff:
+ default:
+ DPRINTF(("%s: 'master' for 0x%.4x\n", __func__, terminal_type));
+ return SOUND_MIXER_VOLUME;
+ }
+ return SOUND_MIXER_VOLUME;
}
#else
-Static const char *
+static const char *
uaudio_feature_name(const struct io_terminal *iot, struct mixerctl *mix)
{
-int terminal_type;
-
-terminal_type = uaudio_determine_class(iot, mix);
-if (mix->class == UAC_RECORD && terminal_type == 0)
-return AudioNmixerout;
-DPRINTF(("%s: terminal_type=%sn", __func__,
-uaudio_get_terminal_name(terminal_type)));
-switch (terminal_type) {
-case UAT_STREAM:
-return AudioNdac;
-
-case UATI_MICROPHONE:
-case UATI_DESKMICROPHONE:
-case UATI_PERSONALMICROPHONE:
-case UATI_OMNIMICROPHONE:
-case UATI_MICROPHONEARRAY:
-case UATI_PROCMICROPHONEARR:
-return AudioNmicrophone;
-
-case UATO_SPEAKER:
-case UATO_DESKTOPSPEAKER:
-case UATO_ROOMSPEAKER:
-case UATO_COMMSPEAKER:
-return AudioNspeaker;
-
-case UATO_HEADPHONES:
-return AudioNheadphone;
+ int terminal_type;
-case UATO_SUBWOOFER:
-return AudioNlfe;
-
-/* telephony terminal types */
-case UATT_UNDEFINED:
-case UATT_PHONELINE:
-case UATT_TELEPHONE:
-case UATT_DOWNLINEPHONE:
-return "phone";
-
-case UATE_ANALOGCONN:
-case UATE_LINECONN:
-case UATE_LEGACYCONN:
-return AudioNline;
-
-case UATE_DIGITALAUIFC:
-case UATE_SPDIF:
-case UATE_1394DA:
-case UATE_1394DV:
-return AudioNaux;
-
-case UATF_CDPLAYER:
-return AudioNcd;
-
-case UATF_SYNTHESIZER:
-return AudioNfmsynth;
-
-case UATF_VIDEODISCAUDIO:
-case UATF_DVDAUDIO:
-case UATF_TVTUNERAUDIO:
-return AudioNvideo;
-
-case UAT_UNDEFINED:
-case UAT_VENDOR:
-case UATI_UNDEFINED:
+ terminal_type = uaudio_determine_class(iot, mix);
+ if (mix->class == UAC_RECORD && terminal_type == 0)
+ return AudioNmixerout;
+ DPRINTF(("%s: terminal_type=%s\n", __func__,
+ uaudio_get_terminal_name(terminal_type)));
+ switch (terminal_type) {
+ case UAT_STREAM:
+ return AudioNdac;
+
+ case UATI_MICROPHONE:
+ case UATI_DESKMICROPHONE:
+ case UATI_PERSONALMICROPHONE:
+ case UATI_OMNIMICROPHONE:
+ case UATI_MICROPHONEARRAY:
+ case UATI_PROCMICROPHONEARR:
+ return AudioNmicrophone;
+
+ case UATO_SPEAKER:
+ case UATO_DESKTOPSPEAKER:
+ case UATO_ROOMSPEAKER:
+ case UATO_COMMSPEAKER:
+ return AudioNspeaker;
+
+ case UATO_HEADPHONES:
+ return AudioNheadphone;
+
+ case UATO_SUBWOOFER:
+ return AudioNlfe;
+
+ /* telephony terminal types */
+ case UATT_UNDEFINED:
+ case UATT_PHONELINE:
+ case UATT_TELEPHONE:
+ case UATT_DOWNLINEPHONE:
+ return "phone";
+
+ case UATE_ANALOGCONN:
+ case UATE_LINECONN:
+ case UATE_LEGACYCONN:
+ return AudioNline;
+
+ case UATE_DIGITALAUIFC:
+ case UATE_SPDIF:
+ case UATE_1394DA:
+ case UATE_1394DV:
+ return AudioNaux;
+
+ case UATF_CDPLAYER:
+ return AudioNcd;
+
+ case UATF_SYNTHESIZER:
+ return AudioNfmsynth;
+
+ case UATF_VIDEODISCAUDIO:
+ case UATF_DVDAUDIO:
+ case UATF_TVTUNERAUDIO:
+ return AudioNvideo;
+
+ case UAT_UNDEFINED:
+ case UAT_VENDOR:
+ case UATI_UNDEFINED:
/* output terminal types */
-case UATO_UNDEFINED:
-case UATO_DISPLAYAUDIO:
+ case UATO_UNDEFINED:
+ case UATO_DISPLAYAUDIO:
/* bidir terminal types */
-case UATB_UNDEFINED:
-case UATB_HANDSET:
-case UATB_HEADSET:
-case UATB_SPEAKERPHONE:
-case UATB_SPEAKERPHONEESUP:
-case UATB_SPEAKERPHONEECANC:
+ case UATB_UNDEFINED:
+ case UATB_HANDSET:
+ case UATB_HEADSET:
+ case UATB_SPEAKERPHONE:
+ case UATB_SPEAKERPHONEESUP:
+ case UATB_SPEAKERPHONEECANC:
/* external terminal types */
-case UATE_UNDEFINED:
+ case UATE_UNDEFINED:
/* embedded function terminal types */
-case UATF_UNDEFINED:
-case UATF_CALIBNOISE:
-case UATF_EQUNOISE:
-case UATF_DAT:
-case UATF_DCC:
-case UATF_MINIDISK:
-case UATF_ANALOGTAPE:
-case UATF_PHONOGRAPH:
-case UATF_VCRAUDIO:
-case UATF_SATELLITE:
-case UATF_CABLETUNER:
-case UATF_DSS:
-case UATF_RADIORECV:
-case UATF_RADIOXMIT:
-case UATF_MULTITRACK:
-case 0xffff:
-default:
-DPRINTF(("%s: 'master' for 0x%.4xn", __func__, terminal_type));
-return AudioNmaster;
-}
-return AudioNmaster;
+ case UATF_UNDEFINED:
+ case UATF_CALIBNOISE:
+ case UATF_EQUNOISE:
+ case UATF_DAT:
+ case UATF_DCC:
+ case UATF_MINIDISK:
+ case UATF_ANALOGTAPE:
+ case UATF_PHONOGRAPH:
+ case UATF_VCRAUDIO:
+ case UATF_SATELLITE:
+ case UATF_CABLETUNER:
+ case UATF_DSS:
+ case UATF_RADIORECV:
+ case UATF_RADIOXMIT:
+ case UATF_MULTITRACK:
+ case 0xffff:
+ default:
+ DPRINTF(("%s: 'master' for 0x%.4x\n", __func__, terminal_type));
+ return AudioNmaster;
+ }
+ return AudioNmaster;
}
#endif
-Static void
+static void
uaudio_add_feature(struct uaudio_softc *sc, const struct io_terminal *iot, int id)
{
-const struct usb_audio_feature_unit *d;
-const uByte *ctls;
-int ctlsize;
-int nchan;
-u_int fumask, mmask, cmask;
-struct mixerctl mix;
-int chan, ctl, i, unit;
+ const struct usb_audio_feature_unit *d;
+ const uByte *ctls;
+ int ctlsize;
+ int nchan;
+ u_int fumask, mmask, cmask;
+ struct mixerctl mix;
+ int chan, ctl, i, unit;
#if defined(__FreeBSD__)
-int mixernumber;
+ int mixernumber;
#else
-const char *mixername;
+ const char *mixername;
#endif
-#define GET(i) (ctls[(i)*ctlsize] | (ctlsize > 1 ? ctls[(i)*ctlsize+1] << 8 : 0))
-d = iot[id].d.fu;
-ctls = d->bmaControls;
-ctlsize = d->bControlSize;
-nchan = (d->bLength - 7) / ctlsize;
-mmask = GET(0);
-/* Figure out what we can control */
-for (cmask = 0, chan = 1; chan < nchan; chan++) {
-DPRINTFN(9,("uaudio_add_feature: chan=%d mask=%xn",
-chan, GET(chan)));
-cmask |= GET(chan);
-}
+#define GET(i) (ctls[(i)*ctlsize] | \
+ (ctlsize > 1 ? ctls[(i)*ctlsize+1] << 8 : 0))
+ d = iot[id].d.fu;
+ ctls = d->bmaControls;
+ ctlsize = d->bControlSize;
+ nchan = (d->bLength - 7) / ctlsize;
+ mmask = GET(0);
+ /* Figure out what we can control */
+ for (cmask = 0, chan = 1; chan < nchan; chan++) {
+ DPRINTFN(9,("uaudio_add_feature: chan=%d mask=%x\n",
+ chan, GET(chan)));
+ cmask |= GET(chan);
+ }
#if !defined(__FreeBSD__)
-DPRINTFN(1,("uaudio_add_feature: bUnitId=%d, "
-"%d channels, mmask=0x%04x, cmask=0x%04xn",
-d->bUnitId, nchan, mmask, cmask));
-#endif
-
-if (nchan > MIX_MAX_CHAN)
-nchan = MIX_MAX_CHAN;
-unit = d->bUnitId;
-mix.wIndex = MAKE(unit, sc->sc_ac_iface);
-for (ctl = MUTE_CONTROL; ctl < LOUDNESS_CONTROL; ctl++) {
-fumask = FU_MASK(ctl);
-DPRINTFN(4,("uaudio_add_feature: ctl=%d fumask=0x%04xn",
-ctl, fumask));
-if (mmask & fumask) {
-mix.nchan = 1;
-mix.wValue[0] = MAKE(ctl, 0);
-} else if (cmask & fumask) {
-mix.nchan = nchan - 1;
-for (i = 1; i < nchan; i++) {
-if (GET(i) & fumask)
-mix.wValue[i-1] = MAKE(ctl, i);
-else
-mix.wValue[i-1] = -1;
-}
-} else {
-continue;
-}
+ DPRINTFN(1,("uaudio_add_feature: bUnitId=%d, "
+ "%d channels, mmask=0x%04x, cmask=0x%04x\n",
+ d->bUnitId, nchan, mmask, cmask));
+#endif
+
+ if (nchan > MIX_MAX_CHAN)
+ nchan = MIX_MAX_CHAN;
+ unit = d->bUnitId;
+ mix.wIndex = MAKE(unit, sc->sc_ac_iface);
+ for (ctl = MUTE_CONTROL; ctl < LOUDNESS_CONTROL; ctl++) {
+ fumask = FU_MASK(ctl);
+ DPRINTFN(4,("uaudio_add_feature: ctl=%d fumask=0x%04x\n",
+ ctl, fumask));
+ if (mmask & fumask) {
+ mix.nchan = 1;
+ mix.wValue[0] = MAKE(ctl, 0);
+ } else if (cmask & fumask) {
+ mix.nchan = nchan - 1;
+ for (i = 1; i < nchan; i++) {
+ if (GET(i) & fumask)
+ mix.wValue[i-1] = MAKE(ctl, i);
+ else
+ mix.wValue[i-1] = -1;
+ }
+ } else {
+ continue;
+ }
#undef GET
#if defined(__FreeBSD__)
-mixernumber = uaudio_feature_name(&iot[id], &mix);
+ mixernumber = uaudio_feature_name(&iot[id], &mix);
#else
-mixername = uaudio_feature_name(&iot[id], &mix);
+ mixername = uaudio_feature_name(&iot[id], &mix);
#endif
-switch (ctl) {
-case MUTE_CONTROL:
-mix.type = MIX_ON_OFF;
+ switch (ctl) {
+ case MUTE_CONTROL:
+ mix.type = MIX_ON_OFF;
#if defined(__FreeBSD__)
-mix.ctl = SOUND_MIXER_NRDEVICES;
+ mix.ctl = SOUND_MIXER_NRDEVICES;
#else
-mix.ctlunit = "";
-snprintf(mix.ctlname, sizeof(mix.ctlname),
-"%s.%s", mixername, AudioNmute);
-#endif
-break;
-case VOLUME_CONTROL:
-mix.type = MIX_SIGNED_16;
+ mix.ctlunit = "";
+ snprintf(mix.ctlname, sizeof(mix.ctlname),
+ "%s.%s", mixername, AudioNmute);
+#endif
+ break;
+ case VOLUME_CONTROL:
+ mix.type = MIX_SIGNED_16;
#if defined(__FreeBSD__)
-mix.ctl = mixernumber;
+ mix.ctl = mixernumber;
#else
-mix.ctlunit = AudioNvolume;
-strlcpy(mix.ctlname, mixername, sizeof(mix.ctlname));
+ mix.ctlunit = AudioNvolume;
+ strlcpy(mix.ctlname, mixername, sizeof(mix.ctlname));
#endif
-break;
-case BASS_CONTROL:
-mix.type = MIX_SIGNED_8;
+ break;
+ case BASS_CONTROL:
+ mix.type = MIX_SIGNED_8;
#if defined(__FreeBSD__)
-mix.ctl = SOUND_MIXER_BASS;
+ mix.ctl = SOUND_MIXER_BASS;
#else
-mix.ctlunit = AudioNbass;
-snprintf(mix.ctlname, sizeof(mix.ctlname),
-"%s.%s", mixername, AudioNbass);
-#endif
-break;
-case MID_CONTROL:
-mix.type = MIX_SIGNED_8;
+ mix.ctlunit = AudioNbass;
+ snprintf(mix.ctlname, sizeof(mix.ctlname),
+ "%s.%s", mixername, AudioNbass);
+#endif
+ break;
+ case MID_CONTROL:
+ mix.type = MIX_SIGNED_8;
#if defined(__FreeBSD__)
-mix.ctl = SOUND_MIXER_NRDEVICES; /* XXXXX */
+ mix.ctl = SOUND_MIXER_NRDEVICES; /* XXXXX */
#else
-mix.ctlunit = AudioNmid;
-snprintf(mix.ctlname, sizeof(mix.ctlname),
-"%s.%s", mixername, AudioNmid);
-#endif
-break;
-case TREBLE_CONTROL:
-mix.type = MIX_SIGNED_8;
+ mix.ctlunit = AudioNmid;
+ snprintf(mix.ctlname, sizeof(mix.ctlname),
+ "%s.%s", mixername, AudioNmid);
+#endif
+ break;
+ case TREBLE_CONTROL:
+ mix.type = MIX_SIGNED_8;
#if defined(__FreeBSD__)
-mix.ctl = SOUND_MIXER_TREBLE;
+ mix.ctl = SOUND_MIXER_TREBLE;
#else
-mix.ctlunit = AudioNtreble;
-snprintf(mix.ctlname, sizeof(mix.ctlname),
-"%s.%s", mixername, AudioNtreble);
-#endif
-break;
-case GRAPHIC_EQUALIZER_CONTROL:
-continue; /* XXX don't add anything */
-break;
-case AGC_CONTROL:
-mix.type = MIX_ON_OFF;
+ mix.ctlunit = AudioNtreble;
+ snprintf(mix.ctlname, sizeof(mix.ctlname),
+ "%s.%s", mixername, AudioNtreble);
+#endif
+ break;
+ case GRAPHIC_EQUALIZER_CONTROL:
+ continue; /* XXX don't add anything */
+ break;
+ case AGC_CONTROL:
+ mix.type = MIX_ON_OFF;
#if defined(__FreeBSD__)
-mix.ctl = SOUND_MIXER_NRDEVICES; /* XXXXX */
+ mix.ctl = SOUND_MIXER_NRDEVICES; /* XXXXX */
#else
-mix.ctlunit = "";
-snprintf(mix.ctlname, sizeof(mix.ctlname), "%s.%s",
-mixername, AudioNagc);
-#endif
-break;
-case DELAY_CONTROL:
-mix.type = MIX_UNSIGNED_16;
+ mix.ctlunit = "";
+ snprintf(mix.ctlname, sizeof(mix.ctlname), "%s.%s",
+ mixername, AudioNagc);
+#endif
+ break;
+ case DELAY_CONTROL:
+ mix.type = MIX_UNSIGNED_16;
#if defined(__FreeBSD__)
-mix.ctl = SOUND_MIXER_NRDEVICES; /* XXXXX */
+ mix.ctl = SOUND_MIXER_NRDEVICES; /* XXXXX */
#else
-mix.ctlunit = "4 ms";
-snprintf(mix.ctlname, sizeof(mix.ctlname),
-"%s.%s", mixername, AudioNdelay);
-#endif
-break;
-case BASS_BOOST_CONTROL:
-mix.type = MIX_ON_OFF;
+ mix.ctlunit = "4 ms";
+ snprintf(mix.ctlname, sizeof(mix.ctlname),
+ "%s.%s", mixername, AudioNdelay);
+#endif
+ break;
+ case BASS_BOOST_CONTROL:
+ mix.type = MIX_ON_OFF;
#if defined(__FreeBSD__)
-mix.ctl = SOUND_MIXER_NRDEVICES; /* XXXXX */
+ mix.ctl = SOUND_MIXER_NRDEVICES; /* XXXXX */
#else
-mix.ctlunit = "";
-snprintf(mix.ctlname, sizeof(mix.ctlname),
-"%s.%s", mixername, AudioNbassboost);
-#endif
-break;
-case LOUDNESS_CONTROL:
-mix.type = MIX_ON_OFF;
+ mix.ctlunit = "";
+ snprintf(mix.ctlname, sizeof(mix.ctlname),
+ "%s.%s", mixername, AudioNbassboost);
+#endif
+ break;
+ case LOUDNESS_CONTROL:
+ mix.type = MIX_ON_OFF;
#if defined(__FreeBSD__)
-mix.ctl = SOUND_MIXER_LOUD; /* Is this correct ? */
+ mix.ctl = SOUND_MIXER_LOUD; /* Is this correct ? */
#else
-mix.ctlunit = "";
-snprintf(mix.ctlname, sizeof(mix.ctlname),
-"%s.%s", mixername, AudioNloudness);
+ mix.ctlunit = "";
+ snprintf(mix.ctlname, sizeof(mix.ctlname),
+ "%s.%s", mixername, AudioNloudness);
#endif
-break;
-}
-uaudio_mixer_add_ctl(sc, &mix);
-}
+ break;
+ }
+ uaudio_mixer_add_ctl(sc, &mix);
+ }
}
-Static void
+static void
uaudio_add_processing_updown(struct uaudio_softc *sc,
-const struct io_terminal *iot, int id)
+ const struct io_terminal *iot, int id)
{
-const struct usb_audio_processing_unit *d;
-const struct usb_audio_processing_unit_1 *d1;
-const struct usb_audio_processing_unit_updown *ud;
-struct mixerctl mix;
-int i;
-
-d = iot[id].d.pu;
-d1 = (const struct usb_audio_processing_unit_1 *)
-&d->baSourceId[d->bNrInPins];
-ud = (const struct usb_audio_processing_unit_updown *)
-&d1->bmControls[d1->bControlSize];
-DPRINTFN(2,("uaudio_add_processing_updown: bUnitId=%d bNrModes=%dn",
-d->bUnitId, ud->bNrModes));
-
-if (!(d1->bmControls[0] & UA_PROC_MASK(UD_MODE_SELECT_CONTROL))) {
-DPRINTF(("uaudio_add_processing_updown: no mode selectn"));
-return;
-}
-
-mix.wIndex = MAKE(d->bUnitId, sc->sc_ac_iface);
-mix.nchan = 1;
-mix.wValue[0] = MAKE(UD_MODE_SELECT_CONTROL, 0);
-uaudio_determine_class(&iot[id], &mix);
-mix.type = MIX_ON_OFF; /* XXX */
+ const struct usb_audio_processing_unit *d;
+ const struct usb_audio_processing_unit_1 *d1;
+ const struct usb_audio_processing_unit_updown *ud;
+ struct mixerctl mix;
+ int i;
+
+ d = iot[id].d.pu;
+ d1 = (const struct usb_audio_processing_unit_1 *)
+ &d->baSourceId[d->bNrInPins];
+ ud = (const struct usb_audio_processing_unit_updown *)
+ &d1->bmControls[d1->bControlSize];
+ DPRINTFN(2,("uaudio_add_processing_updown: bUnitId=%d bNrModes=%d\n",
+ d->bUnitId, ud->bNrModes));
+
+ if (!(d1->bmControls[0] & UA_PROC_MASK(UD_MODE_SELECT_CONTROL))) {
+ DPRINTF(("uaudio_add_processing_updown: no mode select\n"));
+ return;
+ }
+
+ mix.wIndex = MAKE(d->bUnitId, sc->sc_ac_iface);
+ mix.nchan = 1;
+ mix.wValue[0] = MAKE(UD_MODE_SELECT_CONTROL, 0);
+ uaudio_determine_class(&iot[id], &mix);
+ mix.type = MIX_ON_OFF; /* XXX */
#if !defined(__FreeBSD__)
-mix.ctlunit = "";
-snprintf(mix.ctlname, sizeof(mix.ctlname), "pro%d-mode", d->bUnitId);
+ mix.ctlunit = "";
+ snprintf(mix.ctlname, sizeof(mix.ctlname), "pro%d-mode", d->bUnitId);
#endif
-for (i = 0; i < ud->bNrModes; i++) {
-DPRINTFN(2,("uaudio_add_processing_updown: i=%d bm=0x%xn",
-i, UGETW(ud->waModes[i])));
-/* XXX */
-}
-uaudio_mixer_add_ctl(sc, &mix);
+ for (i = 0; i < ud->bNrModes; i++) {
+ DPRINTFN(2,("uaudio_add_processing_updown: i=%d bm=0x%x\n",
+ i, UGETW(ud->waModes[i])));
+ /* XXX */
+ }
+ uaudio_mixer_add_ctl(sc, &mix);
}
-Static void
+static void
uaudio_add_processing(struct uaudio_softc *sc, const struct io_terminal *iot, int id)
{
-const struct usb_audio_processing_unit *d;
-const struct usb_audio_processing_unit_1 *d1;
-int ptype;
-struct mixerctl mix;
-
-d = iot[id].d.pu;
-d1 = (const struct usb_audio_processing_unit_1 *)
-&d->baSourceId[d->bNrInPins];
-ptype = UGETW(d->wProcessType);
-DPRINTFN(2,("uaudio_add_processing: wProcessType=%d bUnitId=%d "
-"bNrInPins=%dn", ptype, d->bUnitId, d->bNrInPins));
-
-if (d1->bmControls[0] & UA_PROC_ENABLE_MASK) {
-mix.wIndex = MAKE(d->bUnitId, sc->sc_ac_iface);
-mix.nchan = 1;
-mix.wValue[0] = MAKE(XX_ENABLE_CONTROL, 0);
-uaudio_determine_class(&iot[id], &mix);
-mix.type = MIX_ON_OFF;
+ const struct usb_audio_processing_unit *d;
+ const struct usb_audio_processing_unit_1 *d1;
+ int ptype;
+ struct mixerctl mix;
+
+ d = iot[id].d.pu;
+ d1 = (const struct usb_audio_processing_unit_1 *)
+ &d->baSourceId[d->bNrInPins];
+ ptype = UGETW(d->wProcessType);
+ DPRINTFN(2,("uaudio_add_processing: wProcessType=%d bUnitId=%d "
+ "bNrInPins=%d\n", ptype, d->bUnitId, d->bNrInPins));
+
+ if (d1->bmControls[0] & UA_PROC_ENABLE_MASK) {
+ mix.wIndex = MAKE(d->bUnitId, sc->sc_ac_iface);
+ mix.nchan = 1;
+ mix.wValue[0] = MAKE(XX_ENABLE_CONTROL, 0);
+ uaudio_determine_class(&iot[id], &mix);
+ mix.type = MIX_ON_OFF;
#if !defined(__FreeBSD__)
-mix.ctlunit = "";
-snprintf(mix.ctlname, sizeof(mix.ctlname), "pro%d.%d-enable",
-d->bUnitId, ptype);
-#endif
-uaudio_mixer_add_ctl(sc, &mix);
-}
-
-switch(ptype) {
-case UPDOWNMIX_PROCESS:
-uaudio_add_processing_updown(sc, iot, id);
-break;
-case DOLBY_PROLOGIC_PROCESS:
-case P3D_STEREO_EXTENDER_PROCESS:
-case REVERBATION_PROCESS:
-case CHORUS_PROCESS:
-case DYN_RANGE_COMP_PROCESS:
-default:
+ mix.ctlunit = "";
+ snprintf(mix.ctlname, sizeof(mix.ctlname), "pro%d.%d-enable",
+ d->bUnitId, ptype);
+#endif
+ uaudio_mixer_add_ctl(sc, &mix);
+ }
+
+ switch(ptype) {
+ case UPDOWNMIX_PROCESS:
+ uaudio_add_processing_updown(sc, iot, id);
+ break;
+ case DOLBY_PROLOGIC_PROCESS:
+ case P3D_STEREO_EXTENDER_PROCESS:
+ case REVERBATION_PROCESS:
+ case CHORUS_PROCESS:
+ case DYN_RANGE_COMP_PROCESS:
+ default:
#ifdef USB_DEBUG
-printf("uaudio_add_processing: unit %d, type=%d not impl.n",
-d->bUnitId, ptype);
+ printf("uaudio_add_processing: unit %d, type=%d not impl.\n",
+ d->bUnitId, ptype);
#endif
-break;
-}
+ break;
+ }
}
-Static void
+static void
uaudio_add_extension(struct uaudio_softc *sc, const struct io_terminal *iot, int id)
{
-const struct usb_audio_extension_unit *d;
-const struct usb_audio_extension_unit_1 *d1;
-struct mixerctl mix;
-
-d = iot[id].d.eu;
-d1 = (const struct usb_audio_extension_unit_1 *)
-&d->baSourceId[d->bNrInPins];
-DPRINTFN(2,("uaudio_add_extension: bUnitId=%d bNrInPins=%dn",
-d->bUnitId, d->bNrInPins));
-
-if (usbd_get_quirks(sc->sc_udev)->uq_flags & UQ_AU_NO_XU)
-return;
-
-if (d1->bmControls[0] & UA_EXT_ENABLE_MASK) {
-mix.wIndex = MAKE(d->bUnitId, sc->sc_ac_iface);
-mix.nchan = 1;
-mix.wValue[0] = MAKE(UA_EXT_ENABLE, 0);
-uaudio_determine_class(&iot[id], &mix);
-mix.type = MIX_ON_OFF;
+ const struct usb_audio_extension_unit *d;
+ const struct usb_audio_extension_unit_1 *d1;
+ struct mixerctl mix;
+
+ d = iot[id].d.eu;
+ d1 = (const struct usb_audio_extension_unit_1 *)
+ &d->baSourceId[d->bNrInPins];
+ DPRINTFN(2,("uaudio_add_extension: bUnitId=%d bNrInPins=%d\n",
+ d->bUnitId, d->bNrInPins));
+
+ if (usbd_get_quirks(sc->sc_udev)->uq_flags & UQ_AU_NO_XU)
+ return;
+
+ if (d1->bmControls[0] & UA_EXT_ENABLE_MASK) {
+ mix.wIndex = MAKE(d->bUnitId, sc->sc_ac_iface);
+ mix.nchan = 1;
+ mix.wValue[0] = MAKE(UA_EXT_ENABLE, 0);
+ uaudio_determine_class(&iot[id], &mix);
+ mix.type = MIX_ON_OFF;
#if !defined(__FreeBSD__)
-mix.ctlunit = "";
-snprintf(mix.ctlname, sizeof(mix.ctlname), "ext%d-enable",
-d->bUnitId);
+ mix.ctlunit = "";
+ snprintf(mix.ctlname, sizeof(mix.ctlname), "ext%d-enable",
+ d->bUnitId);
#endif
-uaudio_mixer_add_ctl(sc, &mix);
-}
+ uaudio_mixer_add_ctl(sc, &mix);
+ }
}
-Static struct terminal_list*
+static struct terminal_list*
uaudio_merge_terminal_list(const struct io_terminal *iot)
{
-struct terminal_list *tml;
-uint16_t *ptm;
-int i, len;
-
-len = 0;
-if (iot->inputs == NULL)
-return NULL;
-for (i = 0; i < iot->inputs_size; i++) {
-if (iot->inputs[i] != NULL)
-len += iot->inputs[i]->size;
-}
-tml = malloc(TERMINAL_LIST_SIZE(len), M_TEMP, M_NOWAIT);
-if (tml == NULL) {
-printf("uaudio_merge_terminal_list: no memoryn");
-return NULL;
-}
-tml->size = 0;
-ptm = tml->terminals;
-for (i = 0; i < iot->inputs_size; i++) {
-if (iot->inputs[i] == NULL)
-continue;
-if (iot->inputs[i]->size > len)
-break;
-memcpy(ptm, iot->inputs[i]->terminals,
-iot->inputs[i]->size * sizeof(uint16_t));
-tml->size += iot->inputs[i]->size;
-ptm += iot->inputs[i]->size;
-len -= iot->inputs[i]->size;
-}
-return tml;
+ struct terminal_list *tml;
+ uint16_t *ptm;
+ int i, len;
+
+ len = 0;
+ if (iot->inputs == NULL)
+ return NULL;
+ for (i = 0; i < iot->inputs_size; i++) {
+ if (iot->inputs[i] != NULL)
+ len += iot->inputs[i]->size;
+ }
+ tml = malloc(TERMINAL_LIST_SIZE(len), M_TEMP, M_NOWAIT);
+ if (tml == NULL) {
+ printf("uaudio_merge_terminal_list: no memory\n");
+ return NULL;
+ }
+ tml->size = 0;
+ ptm = tml->terminals;
+ for (i = 0; i < iot->inputs_size; i++) {
+ if (iot->inputs[i] == NULL)
+ continue;
+ if (iot->inputs[i]->size > len)
+ break;
+ memcpy(ptm, iot->inputs[i]->terminals,
+ iot->inputs[i]->size * sizeof(uint16_t));
+ tml->size += iot->inputs[i]->size;
+ ptm += iot->inputs[i]->size;
+ len -= iot->inputs[i]->size;
+ }
+ return tml;
}
-Static struct terminal_list *
+static struct terminal_list *
uaudio_io_terminaltype(int outtype, struct io_terminal *iot, int id)
{
-struct terminal_list *tml;
-struct io_terminal *it;
-int src_id, i;
-
-it = &iot[id];
-if (it->output != NULL) {
-/* already has outtype? */
-for (i = 0; i < it->output->size; i++)
-if (it->output->terminals[i] == outtype)
-return uaudio_merge_terminal_list(it);
-tml = malloc(TERMINAL_LIST_SIZE(it->output->size + 1),
-M_TEMP, M_NOWAIT);
-if (tml == NULL) {
-printf("uaudio_io_terminaltype: no memoryn");
-return uaudio_merge_terminal_list(it);
-}
-memcpy(tml, it->output, TERMINAL_LIST_SIZE(it->output->size));
-tml->terminals[it->output->size] = outtype;
-tml->size++;
-free(it->output, M_TEMP);
-it->output = tml;
-if (it->inputs != NULL) {
-for (i = 0; i < it->inputs_size; i++)
-if (it->inputs[i] != NULL)
-free(it->inputs[i], M_TEMP);
-free(it->inputs, M_TEMP);
-}
-it->inputs_size = 0;
-it->inputs = NULL;
-} else { /* end `iot[id] != NULL' */
-it->inputs_size = 0;
-it->inputs = NULL;
-it->output = malloc(TERMINAL_LIST_SIZE(1), M_TEMP, M_NOWAIT);
-if (it->output == NULL) {
-printf("uaudio_io_terminaltype: no memoryn");
-return NULL;
-}
-it->output->terminals[0] = outtype;
-it->output->size = 1;
-it->direct = FALSE;
-}
-
-switch (it->d.desc->bDescriptorSubtype) {
-case UDESCSUB_AC_INPUT:
-it->inputs = malloc(sizeof(struct terminal_list *), M_TEMP, M_NOWAIT);
-if (it->inputs == NULL) {
-printf("uaudio_io_terminaltype: no memoryn");
-return NULL;
-}
-tml = malloc(TERMINAL_LIST_SIZE(1), M_TEMP, M_NOWAIT);
-if (tml == NULL) {
-printf("uaudio_io_terminaltype: no memoryn");
-free(it->inputs, M_TEMP);
-it->inputs = NULL;
-return NULL;
-}
-it->inputs[0] = tml;
-tml->terminals[0] = UGETW(it->d.it->wTerminalType);
-tml->size = 1;
-it->inputs_size = 1;
-return uaudio_merge_terminal_list(it);
-case UDESCSUB_AC_FEATURE:
-src_id = it->d.fu->bSourceId;
-it->inputs = malloc(sizeof(struct terminal_list *), M_TEMP, M_NOWAIT);
-if (it->inputs == NULL) {
-printf("uaudio_io_terminaltype: no memoryn");
-return uaudio_io_terminaltype(outtype, iot, src_id);
-}
-it->inputs[0] = uaudio_io_terminaltype(outtype, iot, src_id);
-it->inputs_size = 1;
-return uaudio_merge_terminal_list(it);
-case UDESCSUB_AC_OUTPUT:
-it->inputs = malloc(sizeof(struct terminal_list *), M_TEMP, M_NOWAIT);
-if (it->inputs == NULL) {
-printf("uaudio_io_terminaltype: no memoryn");
-return NULL;
-}
-src_id = it->d.ot->bSourceId;
-it->inputs[0] = uaudio_io_terminaltype(outtype, iot, src_id);
-it->inputs_size = 1;
-iot[src_id].direct = TRUE;
-return NULL;
-case UDESCSUB_AC_MIXER:
-it->inputs_size = 0;
-it->inputs = malloc(sizeof(struct terminal_list *)
-* it->d.mu->bNrInPins, M_TEMP, M_NOWAIT);
-if (it->inputs == NULL) {
-printf("uaudio_io_terminaltype: no memoryn");
-return NULL;
-}
-for (i = 0; i < it->d.mu->bNrInPins; i++) {
-src_id = it->d.mu->baSourceId[i];
-it->inputs[i] = uaudio_io_terminaltype(outtype, iot,
-src_id);
-it->inputs_size++;
-}
-return uaudio_merge_terminal_list(it);
-case UDESCSUB_AC_SELECTOR:
-it->inputs_size = 0;
-it->inputs = malloc(sizeof(struct terminal_list *)
-* it->d.su->bNrInPins, M_TEMP, M_NOWAIT);
-if (it->inputs == NULL) {
-printf("uaudio_io_terminaltype: no memoryn");
-return NULL;
-}
-for (i = 0; i < it->d.su->bNrInPins; i++) {
-src_id = it->d.su->baSourceId[i];
-it->inputs[i] = uaudio_io_terminaltype(outtype, iot,
-src_id);
-it->inputs_size++;
-}
-return uaudio_merge_terminal_list(it);
-case UDESCSUB_AC_PROCESSING:
-it->inputs_size = 0;
-it->inputs = malloc(sizeof(struct terminal_list *)
-* it->d.pu->bNrInPins, M_TEMP, M_NOWAIT);
-if (it->inputs == NULL) {
-printf("uaudio_io_terminaltype: no memoryn");
-return NULL;
-}
-for (i = 0; i < it->d.pu->bNrInPins; i++) {
-src_id = it->d.pu->baSourceId[i];
-it->inputs[i] = uaudio_io_terminaltype(outtype, iot,
-src_id);
-it->inputs_size++;
-}
-return uaudio_merge_terminal_list(it);
-case UDESCSUB_AC_EXTENSION:
-it->inputs_size = 0;
-it->inputs = malloc(sizeof(struct terminal_list *)
-* it->d.eu->bNrInPins, M_TEMP, M_NOWAIT);
-if (it->inputs == NULL) {
-printf("uaudio_io_terminaltype: no memoryn");
-return NULL;
-}
-for (i = 0; i < it->d.eu->bNrInPins; i++) {
-src_id = it->d.eu->baSourceId[i];
-it->inputs[i] = uaudio_io_terminaltype(outtype, iot,
-src_id);
-it->inputs_size++;
-}
-return uaudio_merge_terminal_list(it);
-case UDESCSUB_AC_HEADER:
-default:
-return NULL;
-}
+ struct terminal_list *tml;
+ struct io_terminal *it;
+ int src_id, i;
+
+ it = &iot[id];
+ if (it->output != NULL) {
+ /* already has outtype? */
+ for (i = 0; i < it->output->size; i++)
+ if (it->output->terminals[i] == outtype)
+ return uaudio_merge_terminal_list(it);
+ tml = malloc(TERMINAL_LIST_SIZE(it->output->size + 1),
+ M_TEMP, M_NOWAIT);
+ if (tml == NULL) {
+ printf("uaudio_io_terminaltype: no memory\n");
+ return uaudio_merge_terminal_list(it);
+ }
+ memcpy(tml, it->output, TERMINAL_LIST_SIZE(it->output->size));
+ tml->terminals[it->output->size] = outtype;
+ tml->size++;
+ free(it->output, M_TEMP);
+ it->output = tml;
+ if (it->inputs != NULL) {
+ for (i = 0; i < it->inputs_size; i++)
+ if (it->inputs[i] != NULL)
+ free(it->inputs[i], M_TEMP);
+ free(it->inputs, M_TEMP);
+ }
+ it->inputs_size = 0;
+ it->inputs = NULL;
+ } else { /* end `iot[id] != NULL' */
+ it->inputs_size = 0;
+ it->inputs = NULL;
+ it->output = malloc(TERMINAL_LIST_SIZE(1), M_TEMP, M_NOWAIT);
+ if (it->output == NULL) {
+ printf("uaudio_io_terminaltype: no memory\n");
+ return NULL;
+ }
+ it->output->terminals[0] = outtype;
+ it->output->size = 1;
+ it->direct = FALSE;
+ }
+
+ switch (it->d.desc->bDescriptorSubtype) {
+ case UDESCSUB_AC_INPUT:
+ it->inputs = malloc(sizeof(struct terminal_list *), M_TEMP, M_NOWAIT);
+ if (it->inputs == NULL) {
+ printf("uaudio_io_terminaltype: no memory\n");
+ return NULL;
+ }
+ tml = malloc(TERMINAL_LIST_SIZE(1), M_TEMP, M_NOWAIT);
+ if (tml == NULL) {
+ printf("uaudio_io_terminaltype: no memory\n");
+ free(it->inputs, M_TEMP);
+ it->inputs = NULL;
+ return NULL;
+ }
+ it->inputs[0] = tml;
+ tml->terminals[0] = UGETW(it->d.it->wTerminalType);
+ tml->size = 1;
+ it->inputs_size = 1;
+ return uaudio_merge_terminal_list(it);
+ case UDESCSUB_AC_FEATURE:
+ src_id = it->d.fu->bSourceId;
+ it->inputs = malloc(sizeof(struct terminal_list *), M_TEMP, M_NOWAIT);
+ if (it->inputs == NULL) {
+ printf("uaudio_io_terminaltype: no memory\n");
+ return uaudio_io_terminaltype(outtype, iot, src_id);
+ }
+ it->inputs[0] = uaudio_io_terminaltype(outtype, iot, src_id);
+ it->inputs_size = 1;
+ return uaudio_merge_terminal_list(it);
+ case UDESCSUB_AC_OUTPUT:
+ it->inputs = malloc(sizeof(struct terminal_list *), M_TEMP, M_NOWAIT);
+ if (it->inputs == NULL) {
+ printf("uaudio_io_terminaltype: no memory\n");
+ return NULL;
+ }
+ src_id = it->d.ot->bSourceId;
+ it->inputs[0] = uaudio_io_terminaltype(outtype, iot, src_id);
+ it->inputs_size = 1;
+ iot[src_id].direct = TRUE;
+ return NULL;
+ case UDESCSUB_AC_MIXER:
+ it->inputs_size = 0;
+ it->inputs = malloc(sizeof(struct terminal_list *)
+ * it->d.mu->bNrInPins, M_TEMP, M_NOWAIT);
+ if (it->inputs == NULL) {
+ printf("uaudio_io_terminaltype: no memory\n");
+ return NULL;
+ }
+ for (i = 0; i < it->d.mu->bNrInPins; i++) {
+ src_id = it->d.mu->baSourceId[i];
+ it->inputs[i] = uaudio_io_terminaltype(outtype, iot,
+ src_id);
+ it->inputs_size++;
+ }
+ return uaudio_merge_terminal_list(it);
+ case UDESCSUB_AC_SELECTOR:
+ it->inputs_size = 0;
+ it->inputs = malloc(sizeof(struct terminal_list *)
+ * it->d.su->bNrInPins, M_TEMP, M_NOWAIT);
+ if (it->inputs == NULL) {
+ printf("uaudio_io_terminaltype: no memory\n");
+ return NULL;
+ }
+ for (i = 0; i < it->d.su->bNrInPins; i++) {
+ src_id = it->d.su->baSourceId[i];
+ it->inputs[i] = uaudio_io_terminaltype(outtype, iot,
+ src_id);
+ it->inputs_size++;
+ }
+ return uaudio_merge_terminal_list(it);
+ case UDESCSUB_AC_PROCESSING:
+ it->inputs_size = 0;
+ it->inputs = malloc(sizeof(struct terminal_list *)
+ * it->d.pu->bNrInPins, M_TEMP, M_NOWAIT);
+ if (it->inputs == NULL) {
+ printf("uaudio_io_terminaltype: no memory\n");
+ return NULL;
+ }
+ for (i = 0; i < it->d.pu->bNrInPins; i++) {
+ src_id = it->d.pu->baSourceId[i];
+ it->inputs[i] = uaudio_io_terminaltype(outtype, iot,
+ src_id);
+ it->inputs_size++;
+ }
+ return uaudio_merge_terminal_list(it);
+ case UDESCSUB_AC_EXTENSION:
+ it->inputs_size = 0;
+ it->inputs = malloc(sizeof(struct terminal_list *)
+ * it->d.eu->bNrInPins, M_TEMP, M_NOWAIT);
+ if (it->inputs == NULL) {
+ printf("uaudio_io_terminaltype: no memory\n");
+ return NULL;
+ }
+ for (i = 0; i < it->d.eu->bNrInPins; i++) {
+ src_id = it->d.eu->baSourceId[i];
+ it->inputs[i] = uaudio_io_terminaltype(outtype, iot,
+ src_id);
+ it->inputs_size++;
+ }
+ return uaudio_merge_terminal_list(it);
+ case UDESCSUB_AC_HEADER:
+ default:
+ return NULL;
+ }
}
-Static usbd_status
+static usbd_status
uaudio_identify(struct uaudio_softc *sc, const usb_config_descriptor_t *cdesc)
{
-usbd_status err;
+ usbd_status err;
-err = uaudio_identify_ac(sc, cdesc);
-if (err)
-return err;
-return uaudio_identify_as(sc, cdesc);
+ err = uaudio_identify_ac(sc, cdesc);
+ if (err)
+ return err;
+ return uaudio_identify_as(sc, cdesc);
}
-Static void
+static void
uaudio_add_alt(struct uaudio_softc *sc, const struct as_info *ai)
{
-size_t len;
-struct as_info *nai;
+ size_t len;
+ struct as_info *nai;
-len = sizeof(*ai) * (sc->sc_nalts + 1);
-nai = malloc(len, M_USBDEV, M_NOWAIT);
-if (nai == NULL) {
-printf("uaudio_add_alt: no memoryn");
-return;
-}
-/* Copy old data, if there was any */
-if (sc->sc_nalts != 0) {
-memcpy(nai, sc->sc_alts, sizeof(*ai) * (sc->sc_nalts));
-free(sc->sc_alts, M_USBDEV);
-}
-sc->sc_alts = nai;
-DPRINTFN(2,("uaudio_add_alt: adding alt=%d, enc=%dn",
-ai->alt, ai->encoding));
-sc->sc_alts[sc->sc_nalts++] = *ai;
+ len = sizeof(*ai) * (sc->sc_nalts + 1);
+ nai = malloc(len, M_USBDEV, M_NOWAIT);
+ if (nai == NULL) {
+ printf("uaudio_add_alt: no memory\n");
+ return;
+ }
+ /* Copy old data, if there was any */
+ if (sc->sc_nalts != 0) {
+ memcpy(nai, sc->sc_alts, sizeof(*ai) * (sc->sc_nalts));
+ free(sc->sc_alts, M_USBDEV);
+ }
+ sc->sc_alts = nai;
+ DPRINTFN(2,("uaudio_add_alt: adding alt=%d, enc=%d\n",
+ ai->alt, ai->encoding));
+ sc->sc_alts[sc->sc_nalts++] = *ai;
}
-Static usbd_status
+static usbd_status
uaudio_process_as(struct uaudio_softc *sc, const char *buf, int *offsp,
-int size, const usb_interface_descriptor_t *id)
+ int size, const usb_interface_descriptor_t *id)
#define offs (*offsp)
{
-const struct usb_audio_streaming_interface_descriptor *asid;
-const struct usb_audio_streaming_type1_descriptor *asf1d;
-const usb_endpoint_descriptor_audio_t *ed;
-const usb_endpoint_descriptor_audio_t *epdesc1;
-const struct usb_audio_streaming_endpoint_descriptor *sed;
-int format, chan, prec, enc;
-int dir, type, sync;
-struct as_info ai;
-const char *format_str;
-
-asid = (const void *)(buf + offs);
-
-if (asid->bDescriptorType != UDESC_CS_INTERFACE ||
-asid->bDescriptorSubtype != AS_GENERAL)
-return USBD_INVAL;
-DPRINTF(("uaudio_process_as: asid: bTerminakLink=%d wFormatTag=%dn",
-asid->bTerminalLink, UGETW(asid->wFormatTag)));
-offs += asid->bLength;
-if (offs > size)
-return USBD_INVAL;
-
-asf1d = (const void *)(buf + offs);
-if (asf1d->bDescriptorType != UDESC_CS_INTERFACE ||
-asf1d->bDescriptorSubtype != FORMAT_TYPE)
-return USBD_INVAL;
-offs += asf1d->bLength;
-if (offs > size)
-return USBD_INVAL;
-
-if (asf1d->bFormatType != FORMAT_TYPE_I) {
-printf("%s: ignored setting with type %d formatn",
-USBDEVNAME(sc->sc_dev), UGETW(asid->wFormatTag));
-return USBD_NORMAL_COMPLETION;
-}
-
-ed = (const void *)(buf + offs);
-if (ed->bDescriptorType != UDESC_ENDPOINT)
-return USBD_INVAL;
-DPRINTF(("uaudio_process_as: endpoint[0] bLength=%d bDescriptorType=%d "
-"bEndpointAddress=%d bmAttributes=0x%x wMaxPacketSize=%d "
-"bInterval=%d bRefresh=%d bSynchAddress=%dn",
-ed->bLength, ed->bDescriptorType, ed->bEndpointAddress,
-ed->bmAttributes, UGETW(ed->wMaxPacketSize),
-ed->bInterval, ed->bRefresh, ed->bSynchAddress));
-offs += ed->bLength;
-if (offs > size)
-return USBD_INVAL;
-if (UE_GET_XFERTYPE(ed->bmAttributes) != UE_ISOCHRONOUS)
-return USBD_INVAL;
-
-dir = UE_GET_DIR(ed->bEndpointAddress);
-type = UE_GET_ISO_TYPE(ed->bmAttributes);
-if ((usbd_get_quirks(sc->sc_udev)->uq_flags & UQ_AU_INP_ASYNC) &&
-dir == UE_DIR_IN && type == UE_ISO_ADAPT)
-type = UE_ISO_ASYNC;
-
-/* We can't handle endpoints that need a sync pipe yet. */
-sync = FALSE;
-if (dir == UE_DIR_IN && type == UE_ISO_ADAPT) {
-sync = TRUE;
+ const struct usb_audio_streaming_interface_descriptor *asid;
+ const struct usb_audio_streaming_type1_descriptor *asf1d;
+ const usb_endpoint_descriptor_audio_t *ed;
+ const usb_endpoint_descriptor_audio_t *epdesc1;
+ const struct usb_audio_streaming_endpoint_descriptor *sed;
+ int format, chan, prec, enc;
+ int dir, type, sync;
+ struct as_info ai;
+ const char *format_str;
+
+ asid = (const void *)(buf + offs);
+
+ if (asid->bDescriptorType != UDESC_CS_INTERFACE ||
+ asid->bDescriptorSubtype != AS_GENERAL)
+ return USBD_INVAL;
+ DPRINTF(("uaudio_process_as: asid: bTerminakLink=%d wFormatTag=%d\n",
+ asid->bTerminalLink, UGETW(asid->wFormatTag)));
+ offs += asid->bLength;
+ if (offs > size)
+ return USBD_INVAL;
+
+ asf1d = (const void *)(buf + offs);
+ if (asf1d->bDescriptorType != UDESC_CS_INTERFACE ||
+ asf1d->bDescriptorSubtype != FORMAT_TYPE)
+ return USBD_INVAL;
+ offs += asf1d->bLength;
+ if (offs > size)
+ return USBD_INVAL;
+
+ if (asf1d->bFormatType != FORMAT_TYPE_I) {
+ printf("%s: ignored setting with type %d format\n",
+ device_get_nameunit(sc->sc_dev), UGETW(asid->wFormatTag));
+ return USBD_NORMAL_COMPLETION;
+ }
+
+ ed = (const void *)(buf + offs);
+ if (ed->bDescriptorType != UDESC_ENDPOINT)
+ return USBD_INVAL;
+ DPRINTF(("uaudio_process_as: endpoint[0] bLength=%d bDescriptorType=%d "
+ "bEndpointAddress=%d bmAttributes=0x%x wMaxPacketSize=%d "
+ "bInterval=%d bRefresh=%d bSynchAddress=%d\n",
+ ed->bLength, ed->bDescriptorType, ed->bEndpointAddress,
+ ed->bmAttributes, UGETW(ed->wMaxPacketSize),
+ ed->bInterval, ed->bRefresh, ed->bSynchAddress));
+ offs += ed->bLength;
+ if (offs > size)
+ return USBD_INVAL;
+ if (UE_GET_XFERTYPE(ed->bmAttributes) != UE_ISOCHRONOUS)
+ return USBD_INVAL;
+
+ dir = UE_GET_DIR(ed->bEndpointAddress);
+ type = UE_GET_ISO_TYPE(ed->bmAttributes);
+ if ((usbd_get_quirks(sc->sc_udev)->uq_flags & UQ_AU_INP_ASYNC) &&
+ dir == UE_DIR_IN && type == UE_ISO_ADAPT)
+ type = UE_ISO_ASYNC;
+
+ /* We can't handle endpoints that need a sync pipe yet. */
+ sync = FALSE;
+ if (dir == UE_DIR_IN && type == UE_ISO_ADAPT) {
+ sync = TRUE;
#ifndef UAUDIO_MULTIPLE_ENDPOINTS
-printf("%s: ignored input endpoint of type adaptiven",
-USBDEVNAME(sc->sc_dev));
-return USBD_NORMAL_COMPLETION;
-#endif
-}
-if (dir != UE_DIR_IN && type == UE_ISO_ASYNC) {
-sync = TRUE;
+ printf("%s: ignored input endpoint of type adaptive\n",
+ device_get_nameunit(sc->sc_dev));
+ return USBD_NORMAL_COMPLETION;
+#endif
+ }
+ if (dir != UE_DIR_IN && type == UE_ISO_ASYNC) {
+ sync = TRUE;
#ifndef UAUDIO_MULTIPLE_ENDPOINTS
-printf("%s: ignored output endpoint of type asyncn",
-USBDEVNAME(sc->sc_dev));
-return USBD_NORMAL_COMPLETION;
-#endif
-}
-
-sed = (const void *)(buf + offs);
-if (sed->bDescriptorType != UDESC_CS_ENDPOINT ||
-sed->bDescriptorSubtype != AS_GENERAL)
-return USBD_INVAL;
-DPRINTF((" streadming_endpoint: offset=%d bLength=%dn", offs, sed->bLength));
-offs += sed->bLength;
-if (offs > size)
-return USBD_INVAL;
-
-if (sync && id->bNumEndpoints <= 1) {
-printf("%s: a sync-pipe endpoint but no other endpointn",
-USBDEVNAME(sc->sc_dev));
-return USBD_INVAL;
-}
-if (!sync && id->bNumEndpoints > 1) {
-printf("%s: non sync-pipe endpoint but multiple endpointsn",
-USBDEVNAME(sc->sc_dev));
-return USBD_INVAL;
-}
-epdesc1 = NULL;
-if (id->bNumEndpoints > 1) {
-epdesc1 = (const void*)(buf + offs);
-if (epdesc1->bDescriptorType != UDESC_ENDPOINT)
-return USBD_INVAL;
-DPRINTF(("uaudio_process_as: endpoint[1] bLength=%d "
-"bDescriptorType=%d bEndpointAddress=%d "
-"bmAttributes=0x%x wMaxPacketSize=%d bInterval=%d "
-"bRefresh=%d bSynchAddress=%dn",
-epdesc1->bLength, epdesc1->bDescriptorType,
-epdesc1->bEndpointAddress, epdesc1->bmAttributes,
-UGETW(epdesc1->wMaxPacketSize), epdesc1->bInterval,
-epdesc1->bRefresh, epdesc1->bSynchAddress));
-offs += epdesc1->bLength;
-if (offs > size)
-return USBD_INVAL;
-if (epdesc1->bSynchAddress != 0) {
-printf("%s: invalid endpoint: bSynchAddress=0n",
-USBDEVNAME(sc->sc_dev));
-return USBD_INVAL;
-}
-if (UE_GET_XFERTYPE(epdesc1->bmAttributes) != UE_ISOCHRONOUS) {
-printf("%s: invalid endpoint: bmAttributes=0x%xn",
-USBDEVNAME(sc->sc_dev), epdesc1->bmAttributes);
-return USBD_INVAL;
-}
-if (epdesc1->bEndpointAddress != ed->bSynchAddress) {
-printf("%s: invalid endpoint addresses: "
-"ep[0]->bSynchAddress=0x%x "
-"ep[1]->bEndpointAddress=0x%xn",
-USBDEVNAME(sc->sc_dev), ed->bSynchAddress,
-epdesc1->bEndpointAddress);
-return USBD_INVAL;
-}
-/* UE_GET_ADDR(epdesc1->bEndpointAddress), and epdesc1->bRefresh */
-}
-
-format = UGETW(asid->wFormatTag);
-chan = asf1d->bNrChannels;
-prec = asf1d->bBitResolution;
-if (prec != 8 && prec != 16 && prec != 24 && prec != 32) {
-printf("%s: ignored setting with precision %dn",
-USBDEVNAME(sc->sc_dev), prec);
-return USBD_NORMAL_COMPLETION;
-}
-switch (format) {
-case UA_FMT_PCM:
-if (prec == 8) {
-sc->sc_altflags |= HAS_8;
-} else if (prec == 16) {
-sc->sc_altflags |= HAS_16;
-} else if (prec == 24) {
-sc->sc_altflags |= HAS_24;
-} else if (prec == 32) {
-sc->sc_altflags |= HAS_32;
-}
-enc = AUDIO_ENCODING_SLINEAR_LE;
-format_str = "pcm";
-break;
-case UA_FMT_PCM8:
-enc = AUDIO_ENCODING_ULINEAR_LE;
-sc->sc_altflags |= HAS_8U;
-format_str = "pcm8";
-break;
-case UA_FMT_ALAW:
-enc = AUDIO_ENCODING_ALAW;
-sc->sc_altflags |= HAS_ALAW;
-format_str = "alaw";
-break;
-case UA_FMT_MULAW:
-enc = AUDIO_ENCODING_ULAW;
-sc->sc_altflags |= HAS_MULAW;
-format_str = "mulaw";
-break;
-case UA_FMT_IEEE_FLOAT:
-default:
-printf("%s: ignored setting with format %dn",
-USBDEVNAME(sc->sc_dev), format);
-return USBD_NORMAL_COMPLETION;
-}
+ printf("%s: ignored output endpoint of type async\n",
+ device_get_nameunit(sc->sc_dev));
+ return USBD_NORMAL_COMPLETION;
+#endif
+ }
+
+ sed = (const void *)(buf + offs);
+ if (sed->bDescriptorType != UDESC_CS_ENDPOINT ||
+ sed->bDescriptorSubtype != AS_GENERAL)
+ return USBD_INVAL;
+ DPRINTF((" streadming_endpoint: offset=%d bLength=%d\n", offs, sed->bLength));
+ offs += sed->bLength;
+ if (offs > size)
+ return USBD_INVAL;
+
+#ifdef UAUDIO_MULTIPLE_ENDPOINTS
+ if (sync && id->bNumEndpoints <= 1) {
+ printf("%s: a sync-pipe endpoint but no other endpoint\n",
+ device_get_nameunit(sc->sc_dev));
+ return USBD_INVAL;
+ }
+#endif
+ if (!sync && id->bNumEndpoints > 1) {
+ printf("%s: non sync-pipe endpoint but multiple endpoints\n",
+ device_get_nameunit(sc->sc_dev));
+ return USBD_INVAL;
+ }
+ epdesc1 = NULL;
+ if (id->bNumEndpoints > 1) {
+ epdesc1 = (const void*)(buf + offs);
+ if (epdesc1->bDescriptorType != UDESC_ENDPOINT)
+ return USBD_INVAL;
+ DPRINTF(("uaudio_process_as: endpoint[1] bLength=%d "
+ "bDescriptorType=%d bEndpointAddress=%d "
+ "bmAttributes=0x%x wMaxPacketSize=%d bInterval=%d "
+ "bRefresh=%d bSynchAddress=%d\n",
+ epdesc1->bLength, epdesc1->bDescriptorType,
+ epdesc1->bEndpointAddress, epdesc1->bmAttributes,
+ UGETW(epdesc1->wMaxPacketSize), epdesc1->bInterval,
+ epdesc1->bRefresh, epdesc1->bSynchAddress));
+ offs += epdesc1->bLength;
+ if (offs > size)
+ return USBD_INVAL;
+ if (epdesc1->bSynchAddress != 0) {
+ printf("%s: invalid endpoint: bSynchAddress=0\n",
+ device_get_nameunit(sc->sc_dev));
+ return USBD_INVAL;
+ }
+ if (UE_GET_XFERTYPE(epdesc1->bmAttributes) != UE_ISOCHRONOUS) {
+ printf("%s: invalid endpoint: bmAttributes=0x%x\n",
+ device_get_nameunit(sc->sc_dev), epdesc1->bmAttributes);
+ return USBD_INVAL;
+ }
+ if (epdesc1->bEndpointAddress != ed->bSynchAddress) {
+ printf("%s: invalid endpoint addresses: "
+ "ep[0]->bSynchAddress=0x%x "
+ "ep[1]->bEndpointAddress=0x%x\n",
+ device_get_nameunit(sc->sc_dev), ed->bSynchAddress,
+ epdesc1->bEndpointAddress);
+ return USBD_INVAL;
+ }
+ /* UE_GET_ADDR(epdesc1->bEndpointAddress), and epdesc1->bRefresh */
+ }
+
+ format = UGETW(asid->wFormatTag);
+ chan = asf1d->bNrChannels;
+ prec = asf1d->bBitResolution;
+ if (prec != 8 && prec != 16 && prec != 24 && prec != 32) {
+ printf("%s: ignored setting with precision %d\n",
+ device_get_nameunit(sc->sc_dev), prec);
+ return USBD_NORMAL_COMPLETION;
+ }
+ switch (format) {
+ case UA_FMT_PCM:
+ if (prec == 8) {
+ sc->sc_altflags |= HAS_8;
+ } else if (prec == 16) {
+ sc->sc_altflags |= HAS_16;
+ } else if (prec == 24) {
+ sc->sc_altflags |= HAS_24;
+ } else if (prec == 32) {
+ sc->sc_altflags |= HAS_32;
+ }
+ enc = AUDIO_ENCODING_SLINEAR_LE;
+ format_str = "pcm";
+ break;
+ case UA_FMT_PCM8:
+ enc = AUDIO_ENCODING_ULINEAR_LE;
+ sc->sc_altflags |= HAS_8U;
+ format_str = "pcm8";
+ break;
+ case UA_FMT_ALAW:
+ enc = AUDIO_ENCODING_ALAW;
+ sc->sc_altflags |= HAS_ALAW;
+ format_str = "alaw";
+ break;
+ case UA_FMT_MULAW:
+ enc = AUDIO_ENCODING_ULAW;
+ sc->sc_altflags |= HAS_MULAW;
+ format_str = "mulaw";
+ break;
+ case UA_FMT_IEEE_FLOAT:
+ default:
+ printf("%s: ignored setting with format %d\n",
+ device_get_nameunit(sc->sc_dev), format);
+ return USBD_NORMAL_COMPLETION;
+ }
#ifdef USB_DEBUG
-printf("%s: %s: %dch, %d/%dbit, %s,", USBDEVNAME(sc->sc_dev),
-dir == UE_DIR_IN ? "recording" : "playback",
-chan, prec, asf1d->bSubFrameSize * 8, format_str);
-if (asf1d->bSamFreqType == UA_SAMP_CONTNUOUS) {
-printf(" %d-%dHzn", UA_SAMP_LO(asf1d), UA_SAMP_HI(asf1d));
-} else {
-int r;
-printf(" %d", UA_GETSAMP(asf1d, 0));
-for (r = 1; r < asf1d->bSamFreqType; r++)
-printf(",%d", UA_GETSAMP(asf1d, r));
-printf("Hzn");
-}
+ printf("%s: %s: %dch, %d/%dbit, %s,", device_get_nameunit(sc->sc_dev),
+ dir == UE_DIR_IN ? "recording" : "playback",
+ chan, prec, asf1d->bSubFrameSize * 8, format_str);
+ if (asf1d->bSamFreqType == UA_SAMP_CONTNUOUS) {
+ printf(" %d-%dHz\n", UA_SAMP_LO(asf1d), UA_SAMP_HI(asf1d));
+ } else {
+ int r;
+ printf(" %d", UA_GETSAMP(asf1d, 0));
+ for (r = 1; r < asf1d->bSamFreqType; r++)
+ printf(",%d", UA_GETSAMP(asf1d, r));
+ printf("Hz\n");
+ }
#endif
#if defined(__FreeBSD__)
-if (sc->uaudio_sndstat_flag != 0) {
-sbuf_printf(&(sc->uaudio_sndstat), "nt");
-sbuf_printf(&(sc->uaudio_sndstat),
-"mode %d:(%s) %dch, %d/%dbit, %s,",
-id->bAlternateSetting,
-dir == UE_DIR_IN ? "input" : "output",
-chan, prec, asf1d->bSubFrameSize * 8, format_str);
-if (asf1d->bSamFreqType == UA_SAMP_CONTNUOUS) {
-sbuf_printf(&(sc->uaudio_sndstat), " %d-%dHz",
-UA_SAMP_LO(asf1d), UA_SAMP_HI(asf1d));
-} else {
-int r;
-sbuf_printf(&(sc->uaudio_sndstat),
-" %d", UA_GETSAMP(asf1d, 0));
-for (r = 1; r < asf1d->bSamFreqType; r++)
-sbuf_printf(&(sc->uaudio_sndstat),
-",%d", UA_GETSAMP(asf1d, r));
-sbuf_printf(&(sc->uaudio_sndstat), "Hz");
-}
-}
-#endif
-ai.alt = id->bAlternateSetting;
-ai.encoding = enc;
-ai.attributes = sed->bmAttributes;
-ai.idesc = id;
-ai.edesc = ed;
-ai.edesc1 = epdesc1;
-ai.asf1desc = asf1d;
-ai.sc_busy = 0;
-uaudio_add_alt(sc, &ai);
+ if (sc->uaudio_sndstat_flag != 0) {
+ sbuf_printf(&(sc->uaudio_sndstat), "\n\t");
+ sbuf_printf(&(sc->uaudio_sndstat),
+ "mode %d:(%s) %dch, %d/%dbit, %s,",
+ id->bAlternateSetting,
+ dir == UE_DIR_IN ? "input" : "output",
+ chan, prec, asf1d->bSubFrameSize * 8, format_str);
+ if (asf1d->bSamFreqType == UA_SAMP_CONTNUOUS) {
+ sbuf_printf(&(sc->uaudio_sndstat), " %d-%dHz",
+ UA_SAMP_LO(asf1d), UA_SAMP_HI(asf1d));
+ } else {
+ int r;
+ sbuf_printf(&(sc->uaudio_sndstat),
+ " %d", UA_GETSAMP(asf1d, 0));
+ for (r = 1; r < asf1d->bSamFreqType; r++)
+ sbuf_printf(&(sc->uaudio_sndstat),
+ ",%d", UA_GETSAMP(asf1d, r));
+ sbuf_printf(&(sc->uaudio_sndstat), "Hz");
+ }
+ }
+#endif
+ ai.alt = id->bAlternateSetting;
+ ai.encoding = enc;
+ ai.attributes = sed->bmAttributes;
+ ai.idesc = id;
+ ai.edesc = ed;
+ ai.edesc1 = epdesc1;
+ ai.asf1desc = asf1d;
+ ai.sc_busy = 0;
+ ai.ifaceh = NULL;
+ uaudio_add_alt(sc, &ai);
#ifdef USB_DEBUG
-if (ai.attributes & UA_SED_FREQ_CONTROL)
-DPRINTFN(1, ("uaudio_process_as: FREQ_CONTROLn"));
-if (ai.attributes & UA_SED_PITCH_CONTROL)
-DPRINTFN(1, ("uaudio_process_as: PITCH_CONTROLn"));
+ if (ai.attributes & UA_SED_FREQ_CONTROL)
+ DPRINTFN(1, ("uaudio_process_as: FREQ_CONTROL\n"));
+ if (ai.attributes & UA_SED_PITCH_CONTROL)
+ DPRINTFN(1, ("uaudio_process_as: PITCH_CONTROL\n"));
#endif
-sc->sc_mode |= (dir == UE_DIR_OUT) ? AUMODE_PLAY : AUMODE_RECORD;
+ sc->sc_mode |= (dir == UE_DIR_OUT) ? AUMODE_PLAY : AUMODE_RECORD;
-return USBD_NORMAL_COMPLETION;
+ return USBD_NORMAL_COMPLETION;
}
#undef offs
-Static usbd_status
+static usbd_status
uaudio_identify_as(struct uaudio_softc *sc,
-const usb_config_descriptor_t *cdesc)
+ const usb_config_descriptor_t *cdesc)
{
-const usb_interface_descriptor_t *id;
-const char *buf;
-int size, offs;
-
-size = UGETW(cdesc->wTotalLength);
-buf = (const char *)cdesc;
-
-/* Locate the AudioStreaming interface descriptor. */
-offs = 0;
-id = uaudio_find_iface(buf, size, &offs, UISUBCLASS_AUDIOSTREAM);
-if (id == NULL)
-return USBD_INVAL;
-
-#if defined(__FreeBSD__)
-sc->uaudio_sndstat_flag = 0;
-if (sbuf_new(&(sc->uaudio_sndstat), NULL, 4096, SBUF_AUTOEXTEND) != NULL)
-sc->uaudio_sndstat_flag = 1;
-#endif
-/* Loop through all the alternate settings. */
-while (offs <= size) {
-DPRINTFN(2, ("uaudio_identify: interface=%d offset=%dn",
-id->bInterfaceNumber, offs));
-switch (id->bNumEndpoints) {
-case 0:
-DPRINTFN(2, ("uaudio_identify: AS null alt=%dn",
-id->bAlternateSetting));
-sc->sc_nullalt = id->bAlternateSetting;
-break;
-case 1:
+ const usb_interface_descriptor_t *id;
+ const char *buf;
+ int size, offs;
+
+ size = UGETW(cdesc->wTotalLength);
+ buf = (const char *)cdesc;
+
+ /* Locate the AudioStreaming interface descriptor. */
+ offs = 0;
+ id = uaudio_find_iface(buf, size, &offs, UISUBCLASS_AUDIOSTREAM);
+ if (id == NULL)
+ return USBD_INVAL;
+
+#if defined(__FreeBSD__)
+ sc->uaudio_sndstat_flag = 0;
+ if (sbuf_new(&(sc->uaudio_sndstat), NULL, 4096, SBUF_AUTOEXTEND) != NULL)
+ sc->uaudio_sndstat_flag = 1;
+#endif
+ /* Loop through all the alternate settings. */
+ while (offs <= size) {
+ DPRINTFN(2, ("uaudio_identify: interface=%d offset=%d\n",
+ id->bInterfaceNumber, offs));
+ switch (id->bNumEndpoints) {
+ case 0:
+ DPRINTFN(2, ("uaudio_identify: AS null alt=%d\n",
+ id->bAlternateSetting));
+ sc->sc_nullalt = id->bAlternateSetting;
+ break;
+ case 1:
#ifdef UAUDIO_MULTIPLE_ENDPOINTS
-case 2:
+ case 2:
#endif
-uaudio_process_as(sc, buf, &offs, size, id);
-break;
-default:
-printf("%s: ignored audio interface with %d "
-"endpointsn",
-USBDEVNAME(sc->sc_dev), id->bNumEndpoints);
-break;
-}
-id = uaudio_find_iface(buf, size, &offs,UISUBCLASS_AUDIOSTREAM);
-if (id == NULL)
-break;
-}
+ uaudio_process_as(sc, buf, &offs, size, id);
+ break;
+ default:
+ printf("%s: ignored audio interface with %d "
+ "endpoints\n",
+ device_get_nameunit(sc->sc_dev), id->bNumEndpoints);
+ break;
+ }
+ id = uaudio_find_iface(buf, size, &offs,UISUBCLASS_AUDIOSTREAM);
+ if (id == NULL)
+ break;
+ }
#if defined(__FreeBSD__)
-sbuf_finish(&(sc->uaudio_sndstat));
+ sbuf_finish(&(sc->uaudio_sndstat));
#endif
-if (offs > size)
-return USBD_INVAL;
-DPRINTF(("uaudio_identify_as: %d alts availablen", sc->sc_nalts));
+ if (offs > size)
+ return USBD_INVAL;
+ DPRINTF(("uaudio_identify_as: %d alts available\n", sc->sc_nalts));
-if (sc->sc_mode == 0) {
-printf("%s: no usable endpoint foundn",
-USBDEVNAME(sc->sc_dev));
-return USBD_INVAL;
-}
+ if (sc->sc_mode == 0) {
+ printf("%s: no usable endpoint found\n",
+ device_get_nameunit(sc->sc_dev));
+ return USBD_INVAL;
+ }
-return USBD_NORMAL_COMPLETION;
+ return USBD_NORMAL_COMPLETION;
}
-Static usbd_status
+static usbd_status
uaudio_identify_ac(struct uaudio_softc *sc, const usb_config_descriptor_t *cdesc)
{
-struct io_terminal* iot;
-const usb_interface_descriptor_t *id;
-const struct usb_audio_control_descriptor *acdp;
-const usb_descriptor_t *dp;
-const struct usb_audio_output_terminal *pot;
-struct terminal_list *tml;
-const char *buf, *ibuf, *ibufend;
-int size, offs, aclen, ndps, i, j;
-
-size = UGETW(cdesc->wTotalLength);
-buf = (const char *)cdesc;
-
-/* Locate the AudioControl interface descriptor. */
-offs = 0;
-id = uaudio_find_iface(buf, size, &offs, UISUBCLASS_AUDIOCONTROL);
-if (id == NULL)
-return USBD_INVAL;
-if (offs + sizeof *acdp > size)
-return USBD_INVAL;
-sc->sc_ac_iface = id->bInterfaceNumber;
-DPRINTFN(2,("uaudio_identify_ac: AC interface is %dn", sc->sc_ac_iface));
-
-/* A class-specific AC interface header should follow. */
-ibuf = buf + offs;
-acdp = (const struct usb_audio_control_descriptor *)ibuf;
-if (acdp->bDescriptorType != UDESC_CS_INTERFACE ||
-acdp->bDescriptorSubtype != UDESCSUB_AC_HEADER)
-return USBD_INVAL;
-aclen = UGETW(acdp->wTotalLength);
-if (offs + aclen > size)
-return USBD_INVAL;
-
-if (!(usbd_get_quirks(sc->sc_udev)->uq_flags & UQ_BAD_ADC) &&
-UGETW(acdp->bcdADC) != UAUDIO_VERSION)
-return USBD_INVAL;
-
-sc->sc_audio_rev = UGETW(acdp->bcdADC);
-DPRINTFN(2,("uaudio_identify_ac: found AC header, vers=%03x, len=%dn",
-sc->sc_audio_rev, aclen));
-
-sc->sc_nullalt = -1;
-
-/* Scan through all the AC specific descriptors */
-ibufend = ibuf + aclen;
-dp = (const usb_descriptor_t *)ibuf;
-ndps = 0;
-iot = malloc(sizeof(struct io_terminal) * 256, M_TEMP, M_NOWAIT | M_ZERO);
-if (iot == NULL) {
-printf("%s: no memoryn", __func__);
-return USBD_NOMEM;
-}
-for (;;) {
-ibuf += dp->bLength;
-if (ibuf >= ibufend)
-break;
-dp = (const usb_descriptor_t *)ibuf;
-if (ibuf + dp->bLength > ibufend) {
-free(iot, M_TEMP);
-return USBD_INVAL;
-}
-if (dp->bDescriptorType != UDESC_CS_INTERFACE) {
-printf("uaudio_identify_ac: skip desc type=0x%02xn",
-dp->bDescriptorType);
-continue;
-}
-i = ((const struct usb_audio_input_terminal *)dp)->bTerminalId;
-iot[i].d.desc = dp;
-if (i > ndps)
-ndps = i;
-}
-ndps++;
-
-/* construct io_terminal */
-for (i = 0; i < ndps; i++) {
-dp = iot[i].d.desc;
-if (dp == NULL)
-continue;
-if (dp->bDescriptorSubtype != UDESCSUB_AC_OUTPUT)
-continue;
-pot = iot[i].d.ot;
-tml = uaudio_io_terminaltype(UGETW(pot->wTerminalType), iot, i);
-if (tml != NULL)
-free(tml, M_TEMP);
-}
+ struct io_terminal* iot;
+ const usb_interface_descriptor_t *id;
+ const struct usb_audio_control_descriptor *acdp;
+ const usb_descriptor_t *dp;
+ const struct usb_audio_output_terminal *pot;
+ struct terminal_list *tml;
+ const char *buf, *ibuf, *ibufend;
+ int size, offs, aclen, ndps, i, j;
+
+ size = UGETW(cdesc->wTotalLength);
+ buf = (const char *)cdesc;
+
+ /* Locate the AudioControl interface descriptor. */
+ offs = 0;
+ id = uaudio_find_iface(buf, size, &offs, UISUBCLASS_AUDIOCONTROL);
+ if (id == NULL)
+ return USBD_INVAL;
+ if (offs + sizeof *acdp > size)
+ return USBD_INVAL;
+ sc->sc_ac_iface = id->bInterfaceNumber;
+ DPRINTFN(2,("uaudio_identify_ac: AC interface is %d\n", sc->sc_ac_iface));
+
+ /* A class-specific AC interface header should follow. */
+ ibuf = buf + offs;
+ acdp = (const struct usb_audio_control_descriptor *)ibuf;
+ if (acdp->bDescriptorType != UDESC_CS_INTERFACE ||
+ acdp->bDescriptorSubtype != UDESCSUB_AC_HEADER)
+ return USBD_INVAL;
+ aclen = UGETW(acdp->wTotalLength);
+ if (offs + aclen > size)
+ return USBD_INVAL;
+
+ if (!(usbd_get_quirks(sc->sc_udev)->uq_flags & UQ_BAD_ADC) &&
+ UGETW(acdp->bcdADC) != UAUDIO_VERSION)
+ return USBD_INVAL;
+
+ sc->sc_audio_rev = UGETW(acdp->bcdADC);
+ DPRINTFN(2,("uaudio_identify_ac: found AC header, vers=%03x, len=%d\n",
+ sc->sc_audio_rev, aclen));
+
+ sc->sc_nullalt = -1;
+
+ /* Scan through all the AC specific descriptors */
+ ibufend = ibuf + aclen;
+ dp = (const usb_descriptor_t *)ibuf;
+ ndps = 0;
+ iot = malloc(sizeof(struct io_terminal) * 256, M_TEMP, M_NOWAIT | M_ZERO);
+ if (iot == NULL) {
+ printf("%s: no memory\n", __func__);
+ return USBD_NOMEM;
+ }
+ for (;;) {
+ ibuf += dp->bLength;
+ if (ibuf >= ibufend)
+ break;
+ dp = (const usb_descriptor_t *)ibuf;
+ if (ibuf + dp->bLength > ibufend) {
+ free(iot, M_TEMP);
+ return USBD_INVAL;
+ }
+ if (dp->bDescriptorType != UDESC_CS_INTERFACE) {
+ printf("uaudio_identify_ac: skip desc type=0x%02x\n",
+ dp->bDescriptorType);
+ continue;
+ }
+ i = ((const struct usb_audio_input_terminal *)dp)->bTerminalId;
+ iot[i].d.desc = dp;
+ if (i > ndps)
+ ndps = i;
+ }
+ ndps++;
+
+ /* construct io_terminal */
+ for (i = 0; i < ndps; i++) {
+ dp = iot[i].d.desc;
+ if (dp == NULL)
+ continue;
+ if (dp->bDescriptorSubtype != UDESCSUB_AC_OUTPUT)
+ continue;
+ pot = iot[i].d.ot;
+ tml = uaudio_io_terminaltype(UGETW(pot->wTerminalType), iot, i);
+ if (tml != NULL)
+ free(tml, M_TEMP);
+ }
#ifdef USB_DEBUG
-for (i = 0; i < 256; i++) {
-struct usb_audio_cluster cluster;
+ for (i = 0; i < 256; i++) {
+ struct usb_audio_cluster cluster;
-if (iot[i].d.desc == NULL)
-continue;
-logprintf("id %d:t", i);
-switch (iot[i].d.desc->bDescriptorSubtype) {
-case UDESCSUB_AC_INPUT:
-logprintf("AC_INPUT type=%sn", uaudio_get_terminal_name
-(UGETW(iot[i].d.it->wTerminalType)));
-logprintf("t");
-cluster = uaudio_get_cluster(i, iot);
-uaudio_dump_cluster(&cluster);
-logprintf("n");
-break;
-case UDESCSUB_AC_OUTPUT:
-logprintf("AC_OUTPUT type=%s ", uaudio_get_terminal_name
-(UGETW(iot[i].d.ot->wTerminalType)));
-logprintf("src=%dn", iot[i].d.ot->bSourceId);
-break;
-case UDESCSUB_AC_MIXER:
-logprintf("AC_MIXER src=");
-for (j = 0; j < iot[i].d.mu->bNrInPins; j++)
-logprintf("%d ", iot[i].d.mu->baSourceId[j]);
-logprintf("nt");
-cluster = uaudio_get_cluster(i, iot);
-uaudio_dump_cluster(&cluster);
-logprintf("n");
-break;
-case UDESCSUB_AC_SELECTOR:
-logprintf("AC_SELECTOR src=");
-for (j = 0; j < iot[i].d.su->bNrInPins; j++)
-logprintf("%d ", iot[i].d.su->baSourceId[j]);
-logprintf("n");
-break;
-case UDESCSUB_AC_FEATURE:
-logprintf("AC_FEATURE src=%dn", iot[i].d.fu->bSourceId);
-break;
-case UDESCSUB_AC_PROCESSING:
-logprintf("AC_PROCESSING src=");
-for (j = 0; j < iot[i].d.pu->bNrInPins; j++)
-logprintf("%d ", iot[i].d.pu->baSourceId[j]);
-logprintf("nt");
-cluster = uaudio_get_cluster(i, iot);
-uaudio_dump_cluster(&cluster);
-logprintf("n");
-break;
-case UDESCSUB_AC_EXTENSION:
-logprintf("AC_EXTENSION src=");
-for (j = 0; j < iot[i].d.eu->bNrInPins; j++)
-logprintf("%d ", iot[i].d.eu->baSourceId[j]);
-logprintf("nt");
-cluster = uaudio_get_cluster(i, iot);
-uaudio_dump_cluster(&cluster);
-logprintf("n");
-break;
-default:
-logprintf("unknown audio control (subtype=%d)n",
-iot[i].d.desc->bDescriptorSubtype);
-}
-for (j = 0; j < iot[i].inputs_size; j++) {
-int k;
-logprintf("tinput%d: ", j);
-tml = iot[i].inputs[j];
-if (tml == NULL) {
-logprintf("NULLn");
-continue;
-}
-for (k = 0; k < tml->size; k++)
-logprintf("%s ", uaudio_get_terminal_name
-(tml->terminals[k]));
-logprintf("n");
-}
-logprintf("toutput: ");
-tml = iot[i].output;
-for (j = 0; j < tml->size; j++)
-logprintf("%s ", uaudio_get_terminal_name(tml->terminals[j]));
-logprintf("n");
-}
-#endif
-
-for (i = 0; i < ndps; i++) {
-dp = iot[i].d.desc;
-if (dp == NULL)
-continue;
-DPRINTF(("uaudio_identify_ac: id=%d subtype=%dn",
-i, dp->bDescriptorSubtype));
-switch (dp->bDescriptorSubtype) {
-case UDESCSUB_AC_HEADER:
-printf("uaudio_identify_ac: unexpected AC headern");
-break;
-case UDESCSUB_AC_INPUT:
-uaudio_add_input(sc, iot, i);
-break;
-case UDESCSUB_AC_OUTPUT:
-uaudio_add_output(sc, iot, i);
-break;
-case UDESCSUB_AC_MIXER:
-uaudio_add_mixer(sc, iot, i);
-break;
-case UDESCSUB_AC_SELECTOR:
-uaudio_add_selector(sc, iot, i);
-break;
-case UDESCSUB_AC_FEATURE:
-uaudio_add_feature(sc, iot, i);
-break;
-case UDESCSUB_AC_PROCESSING:
-uaudio_add_processing(sc, iot, i);
-break;
-case UDESCSUB_AC_EXTENSION:
-uaudio_add_extension(sc, iot, i);
-break;
-default:
-printf("uaudio_identify_ac: bad AC desc subtype=0x%02xn",
-dp->bDescriptorSubtype);
-break;
-}
-}
-
-/* delete io_terminal */
-for (i = 0; i < 256; i++) {
-if (iot[i].d.desc == NULL)
-continue;
-if (iot[i].inputs != NULL) {
-for (j = 0; j < iot[i].inputs_size; j++) {
-if (iot[i].inputs[j] != NULL)
-free(iot[i].inputs[j], M_TEMP);
-}
-free(iot[i].inputs, M_TEMP);
-}
-if (iot[i].output != NULL)
-free(iot[i].output, M_TEMP);
-iot[i].d.desc = NULL;
-}
-free(iot, M_TEMP);
+ if (iot[i].d.desc == NULL)
+ continue;
+ printf("id %d:\t", i);
+ switch (iot[i].d.desc->bDescriptorSubtype) {
+ case UDESCSUB_AC_INPUT:
+ printf("AC_INPUT type=%s\n", uaudio_get_terminal_name
+ (UGETW(iot[i].d.it->wTerminalType)));
+ printf("\t");
+ cluster = uaudio_get_cluster(i, iot);
+ uaudio_dump_cluster(&cluster);
+ printf("\n");
+ break;
+ case UDESCSUB_AC_OUTPUT:
+ printf("AC_OUTPUT type=%s ", uaudio_get_terminal_name
+ (UGETW(iot[i].d.ot->wTerminalType)));
+ printf("src=%d\n", iot[i].d.ot->bSourceId);
+ break;
+ case UDESCSUB_AC_MIXER:
+ printf("AC_MIXER src=");
+ for (j = 0; j < iot[i].d.mu->bNrInPins; j++)
+ printf("%d ", iot[i].d.mu->baSourceId[j]);
+ printf("\n\t");
+ cluster = uaudio_get_cluster(i, iot);
+ uaudio_dump_cluster(&cluster);
+ printf("\n");
+ break;
+ case UDESCSUB_AC_SELECTOR:
+ printf("AC_SELECTOR src=");
+ for (j = 0; j < iot[i].d.su->bNrInPins; j++)
+ printf("%d ", iot[i].d.su->baSourceId[j]);
+ printf("\n");
+ break;
+ case UDESCSUB_AC_FEATURE:
+ printf("AC_FEATURE src=%d\n", iot[i].d.fu->bSourceId);
+ break;
+ case UDESCSUB_AC_PROCESSING:
+ printf("AC_PROCESSING src=");
+ for (j = 0; j < iot[i].d.pu->bNrInPins; j++)
+ printf("%d ", iot[i].d.pu->baSourceId[j]);
+ printf("\n\t");
+ cluster = uaudio_get_cluster(i, iot);
+ uaudio_dump_cluster(&cluster);
+ printf("\n");
+ break;
+ case UDESCSUB_AC_EXTENSION:
+ printf("AC_EXTENSION src=");
+ for (j = 0; j < iot[i].d.eu->bNrInPins; j++)
+ printf("%d ", iot[i].d.eu->baSourceId[j]);
+ printf("\n\t");
+ cluster = uaudio_get_cluster(i, iot);
+ uaudio_dump_cluster(&cluster);
+ printf("\n");
+ break;
+ default:
+ printf("unknown audio control (subtype=%d)\n",
+ iot[i].d.desc->bDescriptorSubtype);
+ }
+ for (j = 0; j < iot[i].inputs_size; j++) {
+ int k;
+ printf("\tinput%d: ", j);
+ tml = iot[i].inputs[j];
+ if (tml == NULL) {
+ printf("NULL\n");
+ continue;
+ }
+ for (k = 0; k < tml->size; k++)
+ printf("%s ", uaudio_get_terminal_name
+ (tml->terminals[k]));
+ printf("\n");
+ }
+ printf("\toutput: ");
+ tml = iot[i].output;
+ for (j = 0; j < tml->size; j++)
+ printf("%s ", uaudio_get_terminal_name(tml->terminals[j]));
+ printf("\n");
+ }
+#endif
+
+ for (i = 0; i < ndps; i++) {
+ dp = iot[i].d.desc;
+ if (dp == NULL)
+ continue;
+ DPRINTF(("uaudio_identify_ac: id=%d subtype=%d\n",
+ i, dp->bDescriptorSubtype));
+ switch (dp->bDescriptorSubtype) {
+ case UDESCSUB_AC_HEADER:
+ printf("uaudio_identify_ac: unexpected AC header\n");
+ break;
+ case UDESCSUB_AC_INPUT:
+ uaudio_add_input(sc, iot, i);
+ break;
+ case UDESCSUB_AC_OUTPUT:
+ uaudio_add_output(sc, iot, i);
+ break;
+ case UDESCSUB_AC_MIXER:
+ uaudio_add_mixer(sc, iot, i);
+ break;
+ case UDESCSUB_AC_SELECTOR:
+ uaudio_add_selector(sc, iot, i);
+ break;
+ case UDESCSUB_AC_FEATURE:
+ uaudio_add_feature(sc, iot, i);
+ break;
+ case UDESCSUB_AC_PROCESSING:
+ uaudio_add_processing(sc, iot, i);
+ break;
+ case UDESCSUB_AC_EXTENSION:
+ uaudio_add_extension(sc, iot, i);
+ break;
+ default:
+ printf("uaudio_identify_ac: bad AC desc subtype=0x%02x\n",
+ dp->bDescriptorSubtype);
+ break;
+ }
+ }
+
+ /* delete io_terminal */
+ for (i = 0; i < 256; i++) {
+ if (iot[i].d.desc == NULL)
+ continue;
+ if (iot[i].inputs != NULL) {
+ for (j = 0; j < iot[i].inputs_size; j++) {
+ if (iot[i].inputs[j] != NULL)
+ free(iot[i].inputs[j], M_TEMP);
+ }
+ free(iot[i].inputs, M_TEMP);
+ }
+ if (iot[i].output != NULL)
+ free(iot[i].output, M_TEMP);
+ iot[i].d.desc = NULL;
+ }
+ free(iot, M_TEMP);
-return USBD_NORMAL_COMPLETION;
+ return USBD_NORMAL_COMPLETION;
}
#if defined(__NetBSD__) || defined(__OpenBSD__)
-Static int
+static int
uaudio_query_devinfo(void *addr, mixer_devinfo_t *mi)
{
-struct uaudio_softc *sc;
-struct mixerctl *mc;
-int n, nctls, i;
-
-sc = addr;
-DPRINTFN(2,("uaudio_query_devinfo: index=%dn", mi->index));
-if (sc->sc_dying)
-return EIO;
-
-n = mi->index;
-nctls = sc->sc_nctls;
-
-switch (n) {
-case UAC_OUTPUT:
-mi->type = AUDIO_MIXER_CLASS;
-mi->mixer_class = UAC_OUTPUT;
-mi->next = mi->prev = AUDIO_MIXER_LAST;
-strlcpy(mi->label.name, AudioCoutputs, sizeof(mi->label.name));
-return 0;
-case UAC_INPUT:
-mi->type = AUDIO_MIXER_CLASS;
-mi->mixer_class = UAC_INPUT;
-mi->next = mi->prev = AUDIO_MIXER_LAST;
-strlcpy(mi->label.name, AudioCinputs, sizeof(mi->label.name));
-return 0;
-case UAC_EQUAL:
-mi->type = AUDIO_MIXER_CLASS;
-mi->mixer_class = UAC_EQUAL;
-mi->next = mi->prev = AUDIO_MIXER_LAST;
-strlcpy(mi->label.name, AudioCequalization,
-sizeof(mi->label.name));
-return 0;
-case UAC_RECORD:
-mi->type = AUDIO_MIXER_CLASS;
-mi->mixer_class = UAC_RECORD;
-mi->next = mi->prev = AUDIO_MIXER_LAST;
-strlcpy(mi->label.name, AudioCrecord, sizeof(mi->label.name));
-return 0;
-default:
-break;
-}
-
-n -= UAC_NCLASSES;
-if (n < 0 || n >= nctls)
-return ENXIO;
-
-mc = &sc->sc_ctls[n];
-strlcpy(mi->label.name, mc->ctlname, sizeof(mi->label.name));
-mi->mixer_class = mc->class;
-mi->next = mi->prev = AUDIO_MIXER_LAST; /* XXX */
-switch (mc->type) {
-case MIX_ON_OFF:
-mi->type = AUDIO_MIXER_ENUM;
-mi->un.e.num_mem = 2;
-strlcpy(mi->un.e.member[0].label.name, AudioNoff,
-sizeof(mi->un.e.member[0].label.name));
-mi->un.e.member[0].ord = 0;
-strlcpy(mi->un.e.member[1].label.name, AudioNon,
-sizeof(mi->un.e.member[1].label.name));
-mi->un.e.member[1].ord = 1;
-break;
-case MIX_SELECTOR:
-mi->type = AUDIO_MIXER_ENUM;
-mi->un.e.num_mem = mc->maxval - mc->minval + 1;
-for (i = 0; i <= mc->maxval - mc->minval; i++) {
-snprintf(mi->un.e.member[i].label.name,
-sizeof(mi->un.e.member[i].label.name),
-"%d", i + mc->minval);
-mi->un.e.member[i].ord = i + mc->minval;
-}
-break;
-default:
-mi->type = AUDIO_MIXER_VALUE;
-strncpy(mi->un.v.units.name, mc->ctlunit, MAX_AUDIO_DEV_LEN);
-mi->un.v.num_channels = mc->nchan;
-mi->un.v.delta = mc->delta;
-break;
-}
-return 0;
+ struct uaudio_softc *sc;
+ struct mixerctl *mc;
+ int n, nctls, i;
+
+ sc = addr;
+ DPRINTFN(2,("uaudio_query_devinfo: index=%d\n", mi->index));
+ if (sc->sc_dying)
+ return EIO;
+
+ n = mi->index;
+ nctls = sc->sc_nctls;
+
+ switch (n) {
+ case UAC_OUTPUT:
+ mi->type = AUDIO_MIXER_CLASS;
+ mi->mixer_class = UAC_OUTPUT;
+ mi->next = mi->prev = AUDIO_MIXER_LAST;
+ strlcpy(mi->label.name, AudioCoutputs, sizeof(mi->label.name));
+ return 0;
+ case UAC_INPUT:
+ mi->type = AUDIO_MIXER_CLASS;
+ mi->mixer_class = UAC_INPUT;
+ mi->next = mi->prev = AUDIO_MIXER_LAST;
+ strlcpy(mi->label.name, AudioCinputs, sizeof(mi->label.name));
+ return 0;
+ case UAC_EQUAL:
+ mi->type = AUDIO_MIXER_CLASS;
+ mi->mixer_class = UAC_EQUAL;
+ mi->next = mi->prev = AUDIO_MIXER_LAST;
+ strlcpy(mi->label.name, AudioCequalization,
+ sizeof(mi->label.name));
+ return 0;
+ case UAC_RECORD:
+ mi->type = AUDIO_MIXER_CLASS;
+ mi->mixer_class = UAC_RECORD;
+ mi->next = mi->prev = AUDIO_MIXER_LAST;
+ strlcpy(mi->label.name, AudioCrecord, sizeof(mi->label.name));
+ return 0;
+ default:
+ break;
+ }
+
+ n -= UAC_NCLASSES;
+ if (n < 0 || n >= nctls)
+ return ENXIO;
+
+ mc = &sc->sc_ctls[n];
+ strlcpy(mi->label.name, mc->ctlname, sizeof(mi->label.name));
+ mi->mixer_class = mc->class;
+ mi->next = mi->prev = AUDIO_MIXER_LAST; /* XXX */
+ switch (mc->type) {
+ case MIX_ON_OFF:
+ mi->type = AUDIO_MIXER_ENUM;
+ mi->un.e.num_mem = 2;
+ strlcpy(mi->un.e.member[0].label.name, AudioNoff,
+ sizeof(mi->un.e.member[0].label.name));
+ mi->un.e.member[0].ord = 0;
+ strlcpy(mi->un.e.member[1].label.name, AudioNon,
+ sizeof(mi->un.e.member[1].label.name));
+ mi->un.e.member[1].ord = 1;
+ break;
+ case MIX_SELECTOR:
+ mi->type = AUDIO_MIXER_ENUM;
+ mi->un.e.num_mem = mc->maxval - mc->minval + 1;
+ for (i = 0; i <= mc->maxval - mc->minval; i++) {
+ snprintf(mi->un.e.member[i].label.name,
+ sizeof(mi->un.e.member[i].label.name),
+ "%d", i + mc->minval);
+ mi->un.e.member[i].ord = i + mc->minval;
+ }
+ break;
+ default:
+ mi->type = AUDIO_MIXER_VALUE;
+ strlcpy(mi->un.v.units.name, mc->ctlunit, MAX_AUDIO_DEV_LEN);
+ mi->un.v.num_channels = mc->nchan;
+ mi->un.v.delta = mc->delta;
+ break;
+ }
+ return 0;
}
-Static int
+static int
uaudio_open(void *addr, int flags)
{
-struct uaudio_softc *sc;
+ struct uaudio_softc *sc;
-sc = addr;
-DPRINTF(("uaudio_open: sc=%pn", sc));
-if (sc->sc_dying)
-return EIO;
-
-if ((flags & FWRITE) && !(sc->sc_mode & AUMODE_PLAY))
-return EACCES;
-if ((flags & FREAD) && !(sc->sc_mode & AUMODE_RECORD))
-return EACCES;
+ sc = addr;
+ DPRINTF(("uaudio_open: sc=%p\n", sc));
+ if (sc->sc_dying)
+ return EIO;
+
+ if ((flags & FWRITE) && !(sc->sc_mode & AUMODE_PLAY))
+ return EACCES;
+ if ((flags & FREAD) && !(sc->sc_mode & AUMODE_RECORD))
+ return EACCES;
-return 0;
+ return 0;
}
/*
-* Close function is called at splaudio().
-*/
-Static void
+ * Close function is called at splaudio().
+ */
+static void
uaudio_close(void *addr)
{
}
-Static int
+static int
uaudio_drain(void *addr)
{
-struct uaudio_softc *sc;
+ struct uaudio_softc *sc;
-sc = addr;
-usbd_delay_ms(sc->sc_udev, UAUDIO_NCHANBUFS * UAUDIO_NFRAMES);
+ sc = addr;
+ usbd_delay_ms(sc->sc_udev, UAUDIO_NCHANBUFS * UAUDIO_NFRAMES);
-return 0;
+ return 0;
}
-Static int
+static int
uaudio_halt_out_dma(void *addr)
{
-struct uaudio_softc *sc;
+ struct uaudio_softc *sc;
-sc = addr;
-if (sc->sc_dying)
-return EIO;
-
-DPRINTF(("uaudio_halt_out_dma: entern"));
-if (sc->sc_playchan.pipe != NULL) {
-uaudio_chan_close(sc, &sc->sc_playchan);
-sc->sc_playchan.pipe = NULL;
-uaudio_chan_free_buffers(sc, &sc->sc_playchan);
-sc->sc_playchan.intr = NULL;
-}
-return 0;
+ sc = addr;
+ if (sc->sc_dying)
+ return EIO;
+
+ DPRINTF(("uaudio_halt_out_dma: enter\n"));
+ if (sc->sc_playchan.pipe != NULL) {
+ uaudio_chan_close(sc, &sc->sc_playchan);
+ sc->sc_playchan.pipe = NULL;
+ uaudio_chan_free_buffers(sc, &sc->sc_playchan);
+ sc->sc_playchan.intr = NULL;
+ }
+ return 0;
}
-Static int
+static int
uaudio_halt_in_dma(void *addr)
{
-struct uaudio_softc *sc;
+ struct uaudio_softc *sc;
-DPRINTF(("uaudio_halt_in_dma: entern"));
-sc = addr;
-if (sc->sc_recchan.pipe != NULL) {
-uaudio_chan_close(sc, &sc->sc_recchan);
-sc->sc_recchan.pipe = NULL;
-uaudio_chan_free_buffers(sc, &sc->sc_recchan);
-sc->sc_recchan.intr = NULL;
-}
-return 0;
+ DPRINTF(("uaudio_halt_in_dma: enter\n"));
+ sc = addr;
+ if (sc->sc_recchan.pipe != NULL) {
+ uaudio_chan_close(sc, &sc->sc_recchan);
+ sc->sc_recchan.pipe = NULL;
+ uaudio_chan_free_buffers(sc, &sc->sc_recchan);
+ sc->sc_recchan.intr = NULL;
+ }
+ return 0;
}
-Static int
+static int
uaudio_getdev(void *addr, struct audio_device *retp)
{
-struct uaudio_softc *sc;
+ struct uaudio_softc *sc;
-DPRINTF(("uaudio_mixer_getdev:n"));
-sc = addr;
-if (sc->sc_dying)
-return EIO;
+ DPRINTF(("uaudio_mixer_getdev:\n"));
+ sc = addr;
+ if (sc->sc_dying)
+ return EIO;
-*retp = uaudio_device;
-return 0;
+ *retp = uaudio_device;
+ return 0;
}
/*
-* Make sure the block size is large enough to hold all outstanding transfers.
-*/
-Static int
+ * Make sure the block size is large enough to hold all outstanding transfers.
+ */
+static int
uaudio_round_blocksize(void *addr, int blk)
{
-struct uaudio_softc *sc;
-int b;
+ struct uaudio_softc *sc;
+ int b;
-sc = addr;
-DPRINTF(("uaudio_round_blocksize: blk=%d mode=%sn", blk,
-mode == AUMODE_PLAY ? "AUMODE_PLAY" : "AUMODE_RECORD"));
-
-/* chan.bytes_per_frame can be 0. */
-if (mode == AUMODE_PLAY || sc->sc_recchan.bytes_per_frame <= 0) {
-b = param->sample_rate * UAUDIO_NFRAMES * UAUDIO_NCHANBUFS;
-
-/*
-* This does not make accurate value in the case
-* of b % USB_FRAMES_PER_SECOND != 0
-*/
-b /= USB_FRAMES_PER_SECOND;
-
-b *= param->precision / 8 * param->channels;
-} else {
-/*
-* use wMaxPacketSize in bytes_per_frame.
-* See uaudio_set_params() and uaudio_chan_init()
-*/
-b = sc->sc_recchan.bytes_per_frame
-* UAUDIO_NFRAMES * UAUDIO_NCHANBUFS;
-}
-
-if (b <= 0)
-b = 1;
-blk = blk <= b ? b : blk / b * b;
+ sc = addr;
+ DPRINTF(("uaudio_round_blocksize: blk=%d mode=%s\n", blk,
+ mode == AUMODE_PLAY ? "AUMODE_PLAY" : "AUMODE_RECORD"));
+
+ /* chan.bytes_per_frame can be 0. */
+ if (mode == AUMODE_PLAY || sc->sc_recchan.bytes_per_frame <= 0) {
+ b = param->sample_rate * UAUDIO_NFRAMES * UAUDIO_NCHANBUFS;
+
+ /*
+ * This does not make accurate value in the case
+ * of b % USB_FRAMES_PER_SECOND != 0
+ */
+ b /= USB_FRAMES_PER_SECOND;
+
+ b *= param->precision / 8 * param->channels;
+ } else {
+ /*
+ * use wMaxPacketSize in bytes_per_frame.
+ * See uaudio_set_params() and uaudio_chan_init()
+ */
+ b = sc->sc_recchan.bytes_per_frame
+ * UAUDIO_NFRAMES * UAUDIO_NCHANBUFS;
+ }
+
+ if (b <= 0)
+ b = 1;
+ blk = blk <= b ? b : blk / b * b;
#ifdef DIAGNOSTIC
-if (blk <= 0) {
-printf("uaudio_round_blocksize: blk=%dn", blk);
-blk = 512;
-}
+ if (blk <= 0) {
+ printf("uaudio_round_blocksize: blk=%d\n", blk);
+ blk = 512;
+ }
#endif
-DPRINTF(("uaudio_round_blocksize: resultant blk=%dn", blk));
-return blk;
+ DPRINTF(("uaudio_round_blocksize: resultant blk=%d\n", blk));
+ return blk;
}
-Static int
+static int
uaudio_get_props(void *addr)
{
-return AUDIO_PROP_FULLDUPLEX | AUDIO_PROP_INDEPENDENT;
+ return AUDIO_PROP_FULLDUPLEX | AUDIO_PROP_INDEPENDENT;
}
#endif /* NetBSD or OpenBSD */
-Static int
+static int
uaudio_get(struct uaudio_softc *sc, int which, int type, int wValue,
-int wIndex, int len)
+ int wIndex, int len)
{
-usb_device_request_t req;
-uint8_t data[4];
-usbd_status err;
-int val;
-
-#if defined(__FreeBSD__)
-if (sc->sc_dying)
-return EIO;
-#endif
-
-if (wValue == -1)
-return 0;
-
-req.bmRequestType = type;
-req.bRequest = which;
-USETW(req.wValue, wValue);
-USETW(req.wIndex, wIndex);
-USETW(req.wLength, len);
-DPRINTFN(2,("uaudio_get: type=0x%02x req=0x%02x wValue=0x%04x "
-"wIndex=0x%04x len=%dn",
-type, which, wValue, wIndex, len));
-err = usbd_do_request(sc->sc_udev, &req, data);
-if (err) {
-DPRINTF(("uaudio_get: err=%sn", usbd_errstr(err)));
-return -1;
-}
-switch (len) {
-case 1:
-val = data[0];
-break;
-case 2:
-val = data[0] | (data[1] << 8);
-break;
-default:
-DPRINTF(("uaudio_get: bad length=%dn", len));
-return -1;
-}
-DPRINTFN(2,("uaudio_get: val=%dn", val));
-return val;
+ usb_device_request_t req;
+ uint8_t data[4];
+ usbd_status err;
+ int val;
+
+#if defined(__FreeBSD__)
+ if (sc->sc_dying)
+ return EIO;
+#endif
+
+ if (wValue == -1)
+ return 0;
+
+ req.bmRequestType = type;
+ req.bRequest = which;
+ USETW(req.wValue, wValue);
+ USETW(req.wIndex, wIndex);
+ USETW(req.wLength, len);
+ DPRINTFN(2,("uaudio_get: type=0x%02x req=0x%02x wValue=0x%04x "
+ "wIndex=0x%04x len=%d\n",
+ type, which, wValue, wIndex, len));
+#if defined(__FreeBSD__)
+ if (sc->async != 0)
+ err = usbd_do_request_async(sc->sc_udev, &req, data);
+ else
+#endif
+ err = usbd_do_request(sc->sc_udev, &req, data);
+ if (err) {
+ DPRINTF(("uaudio_get: err=%s\n", usbd_errstr(err)));
+ return -1;
+ }
+ switch (len) {
+ case 1:
+ val = data[0];
+ break;
+ case 2:
+ val = data[0] | (data[1] << 8);
+ break;
+ default:
+ DPRINTF(("uaudio_get: bad length=%d\n", len));
+ return -1;
+ }
+ DPRINTFN(2,("uaudio_get: val=%d\n", val));
+ return val;
}
-Static void
+static void
uaudio_set(struct uaudio_softc *sc, int which, int type, int wValue,
-int wIndex, int len, int val)
+ int wIndex, int len, int val)
{
-usb_device_request_t req;
-uint8_t data[4];
-usbd_status err;
-
-#if defined(__FreeBSD__)
-if (sc->sc_dying)
-return;
-#endif
-
-if (wValue == -1)
-return;
-
-req.bmRequestType = type;
-req.bRequest = which;
-USETW(req.wValue, wValue);
-USETW(req.wIndex, wIndex);
-USETW(req.wLength, len);
-switch (len) {
-case 1:
-data[0] = val;
-break;
-case 2:
-data[0] = val;
-data[1] = val >> 8;
-break;
-default:
-return;
-}
-DPRINTFN(2,("uaudio_set: type=0x%02x req=0x%02x wValue=0x%04x "
-"wIndex=0x%04x len=%d, val=%dn",
-type, which, wValue, wIndex, len, val & 0xffff));
-err = usbd_do_request(sc->sc_udev, &req, data);
+ usb_device_request_t req;
+ uint8_t data[4];
+ usbd_status err;
+
+#if defined(__FreeBSD__)
+ if (sc->sc_dying)
+ return;
+#endif
+
+ if (wValue == -1)
+ return;
+
+ req.bmRequestType = type;
+ req.bRequest = which;
+ USETW(req.wValue, wValue);
+ USETW(req.wIndex, wIndex);
+ USETW(req.wLength, len);
+ switch (len) {
+ case 1:
+ data[0] = val;
+ break;
+ case 2:
+ data[0] = val;
+ data[1] = val >> 8;
+ break;
+ default:
+ return;
+ }
+ DPRINTFN(2,("uaudio_set: type=0x%02x req=0x%02x wValue=0x%04x "
+ "wIndex=0x%04x len=%d, val=%d\n",
+ type, which, wValue, wIndex, len, val & 0xffff));
+#if defined(__FreeBSD__)
+ if (sc->async != 0)
+ err = usbd_do_request_async(sc->sc_udev, &req, data);
+ else
+#endif
+ err = usbd_do_request(sc->sc_udev, &req, data);
#ifdef USB_DEBUG
-if (err)
-DPRINTF(("uaudio_set: err=%dn", err));
+ if (err)
+ DPRINTF(("uaudio_set: err=%d\n", err));
#endif
}
-Static int
+static int
uaudio_signext(int type, int val)
{
-if (!MIX_UNSIGNED(type)) {
-if (MIX_SIZE(type) == 2)
-val = (int16_t)val;
-else
-val = (int8_t)val;
-}
-return val;
+ if (!MIX_UNSIGNED(type)) {
+ if (MIX_SIZE(type) == 2)
+ val = (int16_t)val;
+ else
+ val = (int8_t)val;
+ }
+ return val;
}
#if defined(__NetBSD__) || defined(__OpenBSD__)
-Static int
+static int
uaudio_value2bsd(struct mixerctl *mc, int val)
{
-DPRINTFN(5, ("uaudio_value2bsd: type=%03x val=%d min=%d max=%d ",
-mc->type, val, mc->minval, mc->maxval));
-if (mc->type == MIX_ON_OFF) {
-val = (val != 0);
-} else if (mc->type == MIX_SELECTOR) {
-if (val < mc->minval || val > mc->maxval)
-val = mc->minval;
-} else
-val = ((uaudio_signext(mc->type, val) - mc->minval) * 255
-+ mc->mul/2) / mc->mul;
-DPRINTFN(5, ("val'=%dn", val));
-return val;
+ DPRINTFN(5, ("uaudio_value2bsd: type=%03x val=%d min=%d max=%d ",
+ mc->type, val, mc->minval, mc->maxval));
+ if (mc->type == MIX_ON_OFF) {
+ val = (val != 0);
+ } else if (mc->type == MIX_SELECTOR) {
+ if (val < mc->minval || val > mc->maxval)
+ val = mc->minval;
+ } else
+ val = ((uaudio_signext(mc->type, val) - mc->minval) * 255
+ + mc->mul/2) / mc->mul;
+ DPRINTFN(5, ("val'=%d\n", val));
+ return val;
}
#endif
int
uaudio_bsd2value(struct mixerctl *mc, int val)
{
-DPRINTFN(5,("uaudio_bsd2value: type=%03x val=%d min=%d max=%d ",
-mc->type, val, mc->minval, mc->maxval));
-if (mc->type == MIX_ON_OFF) {
-val = (val != 0);
-} else if (mc->type == MIX_SELECTOR) {
-if (val < mc->minval || val > mc->maxval)
-val = mc->minval;
-} else
-val = (val + mc->delta/2) * mc->mul / 255 + mc->minval;
-DPRINTFN(5, ("val'=%dn", val));
-return val;
+ DPRINTFN(5,("uaudio_bsd2value: type=%03x val=%d min=%d max=%d ",
+ mc->type, val, mc->minval, mc->maxval));
+ if (mc->type == MIX_ON_OFF) {
+ val = (val != 0);
+ } else if (mc->type == MIX_SELECTOR) {
+ if (val < mc->minval || val > mc->maxval)
+ val = mc->minval;
+ } else
+ val = (val + mc->delta/2) * mc->mul / 255 + mc->minval;
+ DPRINTFN(5, ("val'=%d\n", val));
+ return val;
}
#if defined(__NetBSD__) || defined(__OpenBSD__)
-Static int
+static int
uaudio_ctl_get(struct uaudio_softc *sc, int which, struct mixerctl *mc,
-int chan)
+ int chan)
{
-int val;
+ int val;
-DPRINTFN(5,("uaudio_ctl_get: which=%d chan=%dn", which, chan));
-val = uaudio_get(sc, which, UT_READ_CLASS_INTERFACE, mc->wValue[chan],
-mc->wIndex, MIX_SIZE(mc->type));
-return uaudio_value2bsd(mc, val);
+ DPRINTFN(5,("uaudio_ctl_get: which=%d chan=%d\n", which, chan));
+ val = uaudio_get(sc, which, UT_READ_CLASS_INTERFACE, mc->wValue[chan],
+ mc->wIndex, MIX_SIZE(mc->type));
+ return uaudio_value2bsd(mc, val);
}
#endif
-Static void
+static void
uaudio_ctl_set(struct uaudio_softc *sc, int which, struct mixerctl *mc,
-int chan, int val)
+ int chan, int val)
{
-val = uaudio_bsd2value(mc, val);
-uaudio_set(sc, which, UT_WRITE_CLASS_INTERFACE, mc->wValue[chan],
-mc->wIndex, MIX_SIZE(mc->type), val);
+ val = uaudio_bsd2value(mc, val);
+ uaudio_set(sc, which, UT_WRITE_CLASS_INTERFACE, mc->wValue[chan],
+ mc->wIndex, MIX_SIZE(mc->type), val);
}
#if defined(__NetBSD__) || defined(__OpenBSD__)
-Static int
+static int
uaudio_mixer_get_port(void *addr, mixer_ctrl_t *cp)
{
-struct uaudio_softc *sc;
-struct mixerctl *mc;
-int i, n, vals[MIX_MAX_CHAN], val;
-
-DPRINTFN(2,("uaudio_mixer_get_port: index=%dn", cp->dev));
-sc = addr;
-if (sc->sc_dying)
-return EIO;
-
-n = cp->dev - UAC_NCLASSES;
-if (n < 0 || n >= sc->sc_nctls)
-return ENXIO;
-mc = &sc->sc_ctls[n];
-
-if (mc->type == MIX_ON_OFF) {
-if (cp->type != AUDIO_MIXER_ENUM)
-return EINVAL;
-cp->un.ord = uaudio_ctl_get(sc, GET_CUR, mc, 0);
-} else if (mc->type == MIX_SELECTOR) {
-if (cp->type != AUDIO_MIXER_ENUM)
-return EINVAL;
-cp->un.ord = uaudio_ctl_get(sc, GET_CUR, mc, 0);
-} else {
-if (cp->type != AUDIO_MIXER_VALUE)
-return (EINVAL);
-if (cp->un.value.num_channels != 1 &&
-cp->un.value.num_channels != mc->nchan)
-return EINVAL;
-for (i = 0; i < mc->nchan; i++)
-vals[i] = uaudio_ctl_get(sc, GET_CUR, mc, i);
-if (cp->un.value.num_channels == 1 && mc->nchan != 1) {
-for (val = 0, i = 0; i < mc->nchan; i++)
-val += vals[i];
-vals[0] = val / mc->nchan;
-}
-for (i = 0; i < cp->un.value.num_channels; i++)
-cp->un.value.level[i] = vals[i];
-}
+ struct uaudio_softc *sc;
+ struct mixerctl *mc;
+ int i, n, vals[MIX_MAX_CHAN], val;
+
+ DPRINTFN(2,("uaudio_mixer_get_port: index=%d\n", cp->dev));
+ sc = addr;
+ if (sc->sc_dying)
+ return EIO;
+
+ n = cp->dev - UAC_NCLASSES;
+ if (n < 0 || n >= sc->sc_nctls)
+ return ENXIO;
+ mc = &sc->sc_ctls[n];
+
+ if (mc->type == MIX_ON_OFF) {
+ if (cp->type != AUDIO_MIXER_ENUM)
+ return EINVAL;
+ cp->un.ord = uaudio_ctl_get(sc, GET_CUR, mc, 0);
+ } else if (mc->type == MIX_SELECTOR) {
+ if (cp->type != AUDIO_MIXER_ENUM)
+ return EINVAL;
+ cp->un.ord = uaudio_ctl_get(sc, GET_CUR, mc, 0);
+ } else {
+ if (cp->type != AUDIO_MIXER_VALUE)
+ return (EINVAL);
+ if (cp->un.value.num_channels != 1 &&
+ cp->un.value.num_channels != mc->nchan)
+ return EINVAL;
+ for (i = 0; i < mc->nchan; i++)
+ vals[i] = uaudio_ctl_get(sc, GET_CUR, mc, i);
+ if (cp->un.value.num_channels == 1 && mc->nchan != 1) {
+ for (val = 0, i = 0; i < mc->nchan; i++)
+ val += vals[i];
+ vals[0] = val / mc->nchan;
+ }
+ for (i = 0; i < cp->un.value.num_channels; i++)
+ cp->un.value.level[i] = vals[i];
+ }
-return 0;
+ return 0;
}
-Static int
+static int
uaudio_mixer_set_port(void *addr, mixer_ctrl_t *cp)
{
-struct uaudio_softc *sc;
-struct mixerctl *mc;
-int i, n, vals[MIX_MAX_CHAN];
-
-DPRINTFN(2,("uaudio_mixer_set_port: index = %dn", cp->dev));
-sc = addr;
-if (sc->sc_dying)
-return EIO;
-
-n = cp->dev - UAC_NCLASSES;
-if (n < 0 || n >= sc->sc_nctls)
-return ENXIO;
-mc = &sc->sc_ctls[n];
-
-if (mc->type == MIX_ON_OFF) {
-if (cp->type != AUDIO_MIXER_ENUM)
-return EINVAL;
-uaudio_ctl_set(sc, SET_CUR, mc, 0, cp->un.ord);
-} else if (mc->type == MIX_SELECTOR) {
-if (cp->type != AUDIO_MIXER_ENUM)
-return EINVAL;
-uaudio_ctl_set(sc, SET_CUR, mc, 0, cp->un.ord);
-} else {
-if (cp->type != AUDIO_MIXER_VALUE)
-return EINVAL;
-if (cp->un.value.num_channels == 1)
-for (i = 0; i < mc->nchan; i++)
-vals[i] = cp->un.value.level[0];
-else if (cp->un.value.num_channels == mc->nchan)
-for (i = 0; i < mc->nchan; i++)
-vals[i] = cp->un.value.level[i];
-else
-return EINVAL;
-for (i = 0; i < mc->nchan; i++)
-uaudio_ctl_set(sc, SET_CUR, mc, i, vals[i]);
-}
-return 0;
+ struct uaudio_softc *sc;
+ struct mixerctl *mc;
+ int i, n, vals[MIX_MAX_CHAN];
+
+ DPRINTFN(2,("uaudio_mixer_set_port: index = %d\n", cp->dev));
+ sc = addr;
+ if (sc->sc_dying)
+ return EIO;
+
+ n = cp->dev - UAC_NCLASSES;
+ if (n < 0 || n >= sc->sc_nctls)
+ return ENXIO;
+ mc = &sc->sc_ctls[n];
+
+ if (mc->type == MIX_ON_OFF) {
+ if (cp->type != AUDIO_MIXER_ENUM)
+ return EINVAL;
+ uaudio_ctl_set(sc, SET_CUR, mc, 0, cp->un.ord);
+ } else if (mc->type == MIX_SELECTOR) {
+ if (cp->type != AUDIO_MIXER_ENUM)
+ return EINVAL;
+ uaudio_ctl_set(sc, SET_CUR, mc, 0, cp->un.ord);
+ } else {
+ if (cp->type != AUDIO_MIXER_VALUE)
+ return EINVAL;
+ if (cp->un.value.num_channels == 1)
+ for (i = 0; i < mc->nchan; i++)
+ vals[i] = cp->un.value.level[0];
+ else if (cp->un.value.num_channels == mc->nchan)
+ for (i = 0; i < mc->nchan; i++)
+ vals[i] = cp->un.value.level[i];
+ else
+ return EINVAL;
+ for (i = 0; i < mc->nchan; i++)
+ uaudio_ctl_set(sc, SET_CUR, mc, i, vals[i]);
+ }
+ return 0;
}
-Static int
+static int
uaudio_trigger_input(void *addr, void *start, void *end, int blksize,
-void (*intr)(void *), void *arg,
-struct audio_params *param)
+ void (*intr)(void *), void *arg,
+ struct audio_params *param)
{
-struct uaudio_softc *sc;
-struct chan *ch;
-usbd_status err;
-int i, s;
-
-sc = addr;
-if (sc->sc_dying)
-return EIO;
-
-DPRINTFN(3,("uaudio_trigger_input: sc=%p start=%p end=%p "
-"blksize=%dn", sc, start, end, blksize));
-ch = &sc->sc_recchan;
-uaudio_chan_set_param(ch, start, end, blksize);
-DPRINTFN(3,("uaudio_trigger_input: sample_size=%d bytes/frame=%d "
-"fraction=0.%03dn", ch->sample_size, ch->bytes_per_frame,
-ch->fraction));
-
-err = uaudio_chan_alloc_buffers(sc, ch);
-if (err)
-return EIO;
-
-err = uaudio_chan_open(sc, ch);
-if (err) {
-uaudio_chan_free_buffers(sc, ch);
-return EIO;
-}
-
-ch->intr = intr;
-ch->arg = arg;
-
-s = splusb();
-for (i = 0; i < UAUDIO_NCHANBUFS-1; i++) /* XXX -1 shouldn't be needed */
-uaudio_chan_rtransfer(ch);
-splx(s);
+ struct uaudio_softc *sc;
+ struct chan *ch;
+ usbd_status err;
+ int i, s;
+
+ sc = addr;
+ if (sc->sc_dying)
+ return EIO;
+
+ DPRINTFN(3,("uaudio_trigger_input: sc=%p start=%p end=%p "
+ "blksize=%d\n", sc, start, end, blksize));
+ ch = &sc->sc_recchan;
+ uaudio_chan_set_param(ch, start, end, blksize);
+ DPRINTFN(3,("uaudio_trigger_input: sample_size=%d bytes/frame=%d "
+ "fraction=0.%03d\n", ch->sample_size, ch->bytes_per_frame,
+ ch->fraction));
+
+ err = uaudio_chan_alloc_buffers(sc, ch);
+ if (err)
+ return EIO;
+
+ err = uaudio_chan_open(sc, ch);
+ if (err) {
+ uaudio_chan_free_buffers(sc, ch);
+ return EIO;
+ }
+
+ ch->intr = intr;
+ ch->arg = arg;
+
+ s = splusb();
+ for (i = 0; i < UAUDIO_NCHANBUFS-1; i++) /* XXX -1 shouldn't be needed */
+ uaudio_chan_rtransfer(ch);
+ splx(s);
-return 0;
+ return 0;
}
-Static int
+static int
uaudio_trigger_output(void *addr, void *start, void *end, int blksize,
-void (*intr)(void *), void *arg,
-struct audio_params *param)
+ void (*intr)(void *), void *arg,
+ struct audio_params *param)
{
-struct uaudio_softc *sc;
-struct chan *ch;
-usbd_status err;
-int i, s;
-
-sc = addr;
-if (sc->sc_dying)
-return EIO;
-
-DPRINTFN(3,("uaudio_trigger_output: sc=%p start=%p end=%p "
-"blksize=%dn", sc, start, end, blksize));
-ch = &sc->sc_playchan;
-uaudio_chan_set_param(ch, start, end, blksize);
-DPRINTFN(3,("uaudio_trigger_output: sample_size=%d bytes/frame=%d "
-"fraction=0.%03dn", ch->sample_size, ch->bytes_per_frame,
-ch->fraction));
-
-err = uaudio_chan_alloc_buffers(sc, ch);
-if (err)
-return EIO;
-
-err = uaudio_chan_open(sc, ch);
-if (err) {
-uaudio_chan_free_buffers(sc, ch);
-return EIO;
-}
-
-ch->intr = intr;
-ch->arg = arg;
-
-s = splusb();
-for (i = 0; i < UAUDIO_NCHANBUFS-1; i++) /* XXX */
-uaudio_chan_ptransfer(ch);
-splx(s);
+ struct uaudio_softc *sc;
+ struct chan *ch;
+ usbd_status err;
+ int i, s;
+
+ sc = addr;
+ if (sc->sc_dying)
+ return EIO;
+
+ DPRINTFN(3,("uaudio_trigger_output: sc=%p start=%p end=%p "
+ "blksize=%d\n", sc, start, end, blksize));
+ ch = &sc->sc_playchan;
+ uaudio_chan_set_param(ch, start, end, blksize);
+ DPRINTFN(3,("uaudio_trigger_output: sample_size=%d bytes/frame=%d "
+ "fraction=0.%03d\n", ch->sample_size, ch->bytes_per_frame,
+ ch->fraction));
+
+ err = uaudio_chan_alloc_buffers(sc, ch);
+ if (err)
+ return EIO;
+
+ err = uaudio_chan_open(sc, ch);
+ if (err) {
+ uaudio_chan_free_buffers(sc, ch);
+ return EIO;
+ }
+
+ ch->intr = intr;
+ ch->arg = arg;
+
+ s = splusb();
+ for (i = 0; i < UAUDIO_NCHANBUFS-1; i++) /* XXX */
+ uaudio_chan_ptransfer(ch);
+ splx(s);
-return 0;
+ return 0;
}
#endif /* NetBSD or OpenBSD */
/* Set up a pipe for a channel. */
-Static usbd_status
+static usbd_status
uaudio_chan_open(struct uaudio_softc *sc, struct chan *ch)
{
-struct as_info *as;
-int endpt;
-usbd_status err;
+ struct as_info *as;
+ int endpt;
+#if defined(__FreeBSD__)
+ int locked;
+#endif
+ usbd_status err;
#if defined(__FreeBSD__)
-if (sc->sc_dying)
-return EIO;
+ if (sc->sc_dying)
+ return EIO;
#endif
-as = &sc->sc_alts[ch->altidx];
-endpt = as->edesc->bEndpointAddress;
-DPRINTF(("uaudio_chan_open: endpt=0x%02x, speed=%d, alt=%dn",
-endpt, ch->sample_rate, as->alt));
+ as = &sc->sc_alts[ch->altidx];
+ endpt = as->edesc->bEndpointAddress;
+ DPRINTF(("uaudio_chan_open: endpt=0x%02x, speed=%d, alt=%d\n",
+ endpt, ch->sample_rate, as->alt));
-/* Set alternate interface corresponding to the mode. */
-err = usbd_set_interface(as->ifaceh, as->alt);
-if (err)
-return err;
+#if defined(__FreeBSD__)
+ locked = (ch->pcm_ch != NULL && mtx_owned(ch->pcm_ch->lock)) ? 1 : 0;
+ if (locked)
+ CHN_UNLOCK(ch->pcm_ch);
+#endif
+ /* Set alternate interface corresponding to the mode. */
+ err = usbd_set_interface(as->ifaceh, as->alt);
+#if defined(__FreeBSD__)
+ if (locked)
+ CHN_LOCK(ch->pcm_ch);
+#endif
+ if (err)
+ return err;
-/*
-* If just one sampling rate is supported,
-* no need to call uaudio_set_speed().
-* Roland SD-90 freezes by a SAMPLING_FREQ_CONTROL request.
-*/
-if (as->asf1desc->bSamFreqType != 1) {
-err = uaudio_set_speed(sc, endpt, ch->sample_rate);
-if (err)
-DPRINTF(("uaudio_chan_open: set_speed failed err=%sn",
-usbd_errstr(err)));
-}
-
-ch->pipe = 0;
-ch->sync_pipe = 0;
-DPRINTF(("uaudio_chan_open: create pipe to 0x%02xn", endpt));
-err = usbd_open_pipe(as->ifaceh, endpt, 0, &ch->pipe);
-if (err)
-return err;
-if (as->edesc1 != NULL) {
-endpt = as->edesc1->bEndpointAddress;
-DPRINTF(("uaudio_chan_open: create sync-pipe to 0x%02xn", endpt));
-err = usbd_open_pipe(as->ifaceh, endpt, 0, &ch->sync_pipe);
-}
-return err;
+ /*
+ * If just one sampling rate is supported,
+ * no need to call uaudio_set_speed().
+ * Roland SD-90 freezes by a SAMPLING_FREQ_CONTROL request.
+ */
+ if (as->asf1desc->bSamFreqType != 1) {
+ err = uaudio_set_speed(sc, endpt, ch->sample_rate);
+ if (err) {
+ DPRINTF(("uaudio_chan_open: set_speed failed err=%s\n",
+ usbd_errstr(err)));
+ }
+ }
+
+ ch->pipe = 0;
+ ch->sync_pipe = 0;
+ DPRINTF(("uaudio_chan_open: create pipe to 0x%02x\n", endpt));
+ err = usbd_open_pipe(as->ifaceh, endpt, 0, &ch->pipe);
+ if (err)
+ return err;
+ if (as->edesc1 != NULL) {
+ endpt = as->edesc1->bEndpointAddress;
+ DPRINTF(("uaudio_chan_open: create sync-pipe to 0x%02x\n", endpt));
+ err = usbd_open_pipe(as->ifaceh, endpt, 0, &ch->sync_pipe);
+ }
+ return err;
}
-Static void
+static void
uaudio_chan_close(struct uaudio_softc *sc, struct chan *ch)
{
-struct as_info *as;
-
+ struct as_info *as;
#if defined(__FreeBSD__)
-if (sc->sc_dying)
-return ;
+ int locked;
+
+ if (sc->sc_dying)
+ return ;
#endif
-as = &sc->sc_alts[ch->altidx];
-as->sc_busy = 0;
-if (sc->sc_nullalt >= 0) {
-DPRINTF(("uaudio_chan_close: set null alt=%dn",
-sc->sc_nullalt));
-usbd_set_interface(as->ifaceh, sc->sc_nullalt);
-}
-if (ch->pipe) {
-usbd_abort_pipe(ch->pipe);
-usbd_close_pipe(ch->pipe);
-}
-if (ch->sync_pipe) {
-usbd_abort_pipe(ch->sync_pipe);
-usbd_close_pipe(ch->sync_pipe);
-}
+ as = &sc->sc_alts[ch->altidx];
+ as->sc_busy = 0;
+#if defined(__FreeBSD__)
+ locked = (ch->pcm_ch != NULL && mtx_owned(ch->pcm_ch->lock)) ? 1 : 0;
+ if (locked)
+ CHN_UNLOCK(ch->pcm_ch);
+#endif
+ if (sc->sc_nullalt >= 0) {
+ DPRINTF(("uaudio_chan_close: set null alt=%d\n",
+ sc->sc_nullalt));
+ /*
+ * The interface will be initialized later again, so an
+ * error does not hurt.
+ */
+ (void)usbd_set_interface(as->ifaceh, sc->sc_nullalt);
+ }
+ if (ch->pipe) {
+ usbd_abort_pipe(ch->pipe);
+ usbd_close_pipe(ch->pipe);
+ }
+ if (ch->sync_pipe) {
+ usbd_abort_pipe(ch->sync_pipe);
+ usbd_close_pipe(ch->sync_pipe);
+ }
+#if defined(__FreeBSD__)
+ if (locked)
+ CHN_LOCK(ch->pcm_ch);
+#endif
}
-Static usbd_status
+static usbd_status
uaudio_chan_alloc_buffers(struct uaudio_softc *sc, struct chan *ch)
{
-usbd_xfer_handle xfer;
-void *buf;
-int i, size;
-
-size = (ch->bytes_per_frame + ch->sample_size) * UAUDIO_NFRAMES;
-for (i = 0; i < UAUDIO_NCHANBUFS; i++) {
-xfer = usbd_alloc_xfer(sc->sc_udev);
-if (xfer == 0)
-goto bad;
-ch->chanbufs[i].xfer = xfer;
-buf = usbd_alloc_buffer(xfer, size);
-if (buf == 0) {
-i++;
-goto bad;
-}
-ch->chanbufs[i].buffer = buf;
-ch->chanbufs[i].chan = ch;
-}
+ usbd_xfer_handle xfer;
+ void *buf;
+ int i, size;
+
+ size = (ch->bytes_per_frame + ch->sample_size) * UAUDIO_NFRAMES;
+ for (i = 0; i < UAUDIO_NCHANBUFS; i++) {
+ xfer = usbd_alloc_xfer(sc->sc_udev);
+ if (xfer == 0)
+ goto bad;
+ ch->chanbufs[i].xfer = xfer;
+ buf = usbd_alloc_buffer(xfer, size);
+ if (buf == 0) {
+ i++;
+ goto bad;
+ }
+ ch->chanbufs[i].buffer = buf;
+ ch->chanbufs[i].chan = ch;
+ }
-return USBD_NORMAL_COMPLETION;
+ return USBD_NORMAL_COMPLETION;
bad:
-while (--i >= 0)
-/* implicit buffer free */
-usbd_free_xfer(ch->chanbufs[i].xfer);
-return USBD_NOMEM;
+ while (--i >= 0)
+ /* implicit buffer free */
+ usbd_free_xfer(ch->chanbufs[i].xfer);
+ return USBD_NOMEM;
}
-Static void
+static void
uaudio_chan_free_buffers(struct uaudio_softc *sc, struct chan *ch)
{
-int i;
+ int i;
-for (i = 0; i < UAUDIO_NCHANBUFS; i++)
-usbd_free_xfer(ch->chanbufs[i].xfer);
+ for (i = 0; i < UAUDIO_NCHANBUFS; i++)
+ usbd_free_xfer(ch->chanbufs[i].xfer);
}
/* Called at splusb() */
-Static void
+static void
uaudio_chan_ptransfer(struct chan *ch)
{
-struct chanbuf *cb;
-int i, n, size, residue, total;
+ struct chanbuf *cb;
+ int i, n, size, residue, total;
-if (ch->sc->sc_dying)
-return;
-
-/* Pick the next channel buffer. */
-cb = &ch->chanbufs[ch->curchanbuf];
-if (++ch->curchanbuf >= UAUDIO_NCHANBUFS)
-ch->curchanbuf = 0;
-
-/* Compute the size of each frame in the next transfer. */
-residue = ch->residue;
-total = 0;
-for (i = 0; i < UAUDIO_NFRAMES; i++) {
-size = ch->bytes_per_frame;
-residue += ch->fraction;
-if (residue >= USB_FRAMES_PER_SECOND) {
-if ((ch->sc->sc_altflags & UA_NOFRAC) == 0)
-size += ch->sample_size;
-residue -= USB_FRAMES_PER_SECOND;
-}
-cb->sizes[i] = size;
-total += size;
-}
-ch->residue = residue;
-cb->size = total;
+ if (ch->sc->sc_dying)
+ return;
-/*
-* Transfer data from upper layer buffer to channel buffer, taking
-* care of wrapping the upper layer buffer.
-*/
-n = min(total, ch->end - ch->cur);
-memcpy(cb->buffer, ch->cur, n);
-ch->cur += n;
-if (ch->cur >= ch->end)
-ch->cur = ch->start;
-if (total > n) {
-total -= n;
-memcpy(cb->buffer + n, ch->cur, total);
-ch->cur += total;
-}
+ /* Pick the next channel buffer. */
+ cb = &ch->chanbufs[ch->curchanbuf];
+ if (++ch->curchanbuf >= UAUDIO_NCHANBUFS)
+ ch->curchanbuf = 0;
+
+ /* Compute the size of each frame in the next transfer. */
+ residue = ch->residue;
+ total = 0;
+ for (i = 0; i < UAUDIO_NFRAMES; i++) {
+ size = ch->bytes_per_frame;
+ residue += ch->fraction;
+ if (residue >= USB_FRAMES_PER_SECOND) {
+ if ((ch->sc->sc_altflags & UA_NOFRAC) == 0)
+ size += ch->sample_size;
+ residue -= USB_FRAMES_PER_SECOND;
+ }
+ cb->sizes[i] = size;
+ total += size;
+ }
+ ch->residue = residue;
+ cb->size = total;
+
+ /*
+ * Transfer data from upper layer buffer to channel buffer, taking
+ * care of wrapping the upper layer buffer.
+ */
+ n = min(total, ch->end - ch->cur);
+ memcpy(cb->buffer, ch->cur, n);
+ ch->cur += n;
+ if (ch->cur >= ch->end)
+ ch->cur = ch->start;
+ if (total > n) {
+ total -= n;
+ memcpy(cb->buffer + n, ch->cur, total);
+ ch->cur += total;
+ }
#ifdef USB_DEBUG
-if (uaudiodebug > 8) {
-DPRINTF(("uaudio_chan_ptransfer: buffer=%p, residue=0.%03dn",
-cb->buffer, ch->residue));
-for (i = 0; i < UAUDIO_NFRAMES; i++) {
-DPRINTF((" [%d] length %dn", i, cb->sizes[i]));
-}
-}
+ if (uaudiodebug > 8) {
+ DPRINTF(("uaudio_chan_ptransfer: buffer=%p, residue=0.%03d\n",
+ cb->buffer, ch->residue));
+ for (i = 0; i < UAUDIO_NFRAMES; i++) {
+ DPRINTF((" [%d] length %d\n", i, cb->sizes[i]));
+ }
+ }
#endif
-DPRINTFN(5,("uaudio_chan_transfer: ptransfer xfer=%pn", cb->xfer));
-/* Fill the request */
-usbd_setup_isoc_xfer(cb->xfer, ch->pipe, cb, cb->sizes,
-UAUDIO_NFRAMES, USBD_NO_COPY,
-uaudio_chan_pintr);
+ DPRINTFN(5,("uaudio_chan_transfer: ptransfer xfer=%p\n", cb->xfer));
+ /* Fill the request */
+ usbd_setup_isoc_xfer(cb->xfer, ch->pipe, cb, cb->sizes,
+ UAUDIO_NFRAMES, USBD_NO_COPY,
+ uaudio_chan_pintr);
-(void)usbd_transfer(cb->xfer);
+ (void)usbd_transfer(cb->xfer);
}
-Static void
+static void
uaudio_chan_pintr(usbd_xfer_handle xfer, usbd_private_handle priv,
-usbd_status status)
+ usbd_status status)
{
-struct chanbuf *cb;
-struct chan *ch;
-u_int32_t count;
-int s;
-
-cb = priv;
-ch = cb->chan;
-/* Return if we are aborting. */
-if (status == USBD_CANCELLED)
-return;
-
-usbd_get_xfer_status(xfer, NULL, NULL, &count, NULL);
-DPRINTFN(5,("uaudio_chan_pintr: count=%d, transferred=%dn",
-count, ch->transferred));
+ struct chanbuf *cb;
+ struct chan *ch;
+ u_int32_t count;
+ int s;
+
+ cb = priv;
+ ch = cb->chan;
+ /* Return if we are aborting. */
+ if (status == USBD_CANCELLED)
+ return;
+
+ usbd_get_xfer_status(xfer, NULL, NULL, &count, NULL);
+ DPRINTFN(5,("uaudio_chan_pintr: count=%d, transferred=%d\n",
+ count, ch->transferred));
#ifdef DIAGNOSTIC
-if (count != cb->size) {
-printf("uaudio_chan_pintr: count(%d) != size(%d)n",
-count, cb->size);
-}
+ if (count != cb->size) {
+ printf("uaudio_chan_pintr: count(%d) != size(%d)\n",
+ count, cb->size);
+ }
#endif
-ch->transferred += cb->size;
+ ch->transferred += cb->size;
#if defined(__FreeBSD__)
-/* s = spltty(); */
-s = splhigh();
-chn_intr(ch->pcm_ch);
-splx(s);
+ /* s = spltty(); */
+ s = splhigh();
+ chn_intr(ch->pcm_ch);
+ splx(s);
#else
-s = splaudio();
-/* Call back to upper layer */
-while (ch->transferred >= ch->blksize) {
-ch->transferred -= ch->blksize;
-DPRINTFN(5,("uaudio_chan_pintr: call %p(%p)n",
-ch->intr, ch->arg));
-ch->intr(ch->arg);
-}
-splx(s);
+ s = splaudio();
+ /* Call back to upper layer */
+ while (ch->transferred >= ch->blksize) {
+ ch->transferred -= ch->blksize;
+ DPRINTFN(5,("uaudio_chan_pintr: call %p(%p)\n",
+ ch->intr, ch->arg));
+ ch->intr(ch->arg);
+ }
+ splx(s);
#endif
-/* start next transfer */
-uaudio_chan_ptransfer(ch);
+ /* start next transfer */
+ uaudio_chan_ptransfer(ch);
}
/* Called at splusb() */
-Static void
+static void
uaudio_chan_rtransfer(struct chan *ch)
{
-struct chanbuf *cb;
-int i, size, residue, total;
+ struct chanbuf *cb;
+ int i, size, residue, total;
-if (ch->sc->sc_dying)
-return;
+ if (ch->sc->sc_dying)
+ return;
-/* Pick the next channel buffer. */
-cb = &ch->chanbufs[ch->curchanbuf];
-if (++ch->curchanbuf >= UAUDIO_NCHANBUFS)
-ch->curchanbuf = 0;
-
-/* Compute the size of each frame in the next transfer. */
-residue = ch->residue;
-total = 0;
-for (i = 0; i < UAUDIO_NFRAMES; i++) {
-size = ch->bytes_per_frame;
-cb->sizes[i] = size;
-cb->offsets[i] = total;
-total += size;
-}
-ch->residue = residue;
-cb->size = total;
+ /* Pick the next channel buffer. */
+ cb = &ch->chanbufs[ch->curchanbuf];
+ if (++ch->curchanbuf >= UAUDIO_NCHANBUFS)
+ ch->curchanbuf = 0;
+
+ /* Compute the size of each frame in the next transfer. */
+ residue = ch->residue;
+ total = 0;
+ for (i = 0; i < UAUDIO_NFRAMES; i++) {
+ size = ch->bytes_per_frame;
+ cb->sizes[i] = size;
+ cb->offsets[i] = total;
+ total += size;
+ }
+ ch->residue = residue;
+ cb->size = total;
#ifdef USB_DEBUG
-if (uaudiodebug > 8) {
-DPRINTF(("uaudio_chan_rtransfer: buffer=%p, residue=0.%03dn",
-cb->buffer, ch->residue));
-for (i = 0; i < UAUDIO_NFRAMES; i++) {
-DPRINTF((" [%d] length %dn", i, cb->sizes[i]));
-}
-}
+ if (uaudiodebug > 8) {
+ DPRINTF(("uaudio_chan_rtransfer: buffer=%p, residue=0.%03d\n",
+ cb->buffer, ch->residue));
+ for (i = 0; i < UAUDIO_NFRAMES; i++) {
+ DPRINTF((" [%d] length %d\n", i, cb->sizes[i]));
+ }
+ }
#endif
-DPRINTFN(5,("uaudio_chan_rtransfer: transfer xfer=%pn", cb->xfer));
-/* Fill the request */
-usbd_setup_isoc_xfer(cb->xfer, ch->pipe, cb, cb->sizes,
-UAUDIO_NFRAMES, USBD_NO_COPY,
-uaudio_chan_rintr);
+ DPRINTFN(5,("uaudio_chan_rtransfer: transfer xfer=%p\n", cb->xfer));
+ /* Fill the request */
+ usbd_setup_isoc_xfer(cb->xfer, ch->pipe, cb, cb->sizes,
+ UAUDIO_NFRAMES, USBD_NO_COPY,
+ uaudio_chan_rintr);
-(void)usbd_transfer(cb->xfer);
+ (void)usbd_transfer(cb->xfer);
}
-Static void
+static void
uaudio_chan_rintr(usbd_xfer_handle xfer, usbd_private_handle priv,
-usbd_status status)
+ usbd_status status)
{
-struct chanbuf *cb = priv;
-struct chan *ch = cb->chan;
-u_int32_t count;
-int s, i, n, frsize;
-
-/* Return if we are aborting. */
-if (status == USBD_CANCELLED)
-return;
-
-usbd_get_xfer_status(xfer, NULL, NULL, &count, NULL);
-DPRINTFN(5,("uaudio_chan_rintr: count=%d, transferred=%dn",
-count, ch->transferred));
+ struct chanbuf *cb = priv;
+ struct chan *ch = cb->chan;
+ u_int32_t count;
+ int s, i, n, frsize;
+
+ /* Return if we are aborting. */
+ if (status == USBD_CANCELLED)
+ return;
+
+ usbd_get_xfer_status(xfer, NULL, NULL, &count, NULL);
+ DPRINTFN(5,("uaudio_chan_rintr: count=%d, transferred=%d\n",
+ count, ch->transferred));
-/* count < cb->size is normal for asynchronous source */
+ /* count < cb->size is normal for asynchronous source */
#ifdef DIAGNOSTIC
-if (count > cb->size) {
-printf("uaudio_chan_rintr: count(%d) > size(%d)n",
-count, cb->size);
-}
-#endif
+ if (count > cb->size) {
+ printf("uaudio_chan_rintr: count(%d) > size(%d)\n",
+ count, cb->size);
+ }
+#endif
+
+ /*
+ * Transfer data from channel buffer to upper layer buffer, taking
+ * care of wrapping the upper layer buffer.
+ */
+ for(i = 0; i < UAUDIO_NFRAMES; i++) {
+ frsize = cb->sizes[i];
+ n = min(frsize, ch->end - ch->cur);
+ memcpy(ch->cur, cb->buffer + cb->offsets[i], n);
+ ch->cur += n;
+ if (ch->cur >= ch->end)
+ ch->cur = ch->start;
+ if (frsize > n) {
+ memcpy(ch->cur, cb->buffer + cb->offsets[i] + n,
+ frsize - n);
+ ch->cur += frsize - n;
+ }
+ }
-/*
-* Transfer data from channel buffer to upper layer buffer, taking
-* care of wrapping the upper layer buffer.
-*/
-for(i = 0; i < UAUDIO_NFRAMES; i++) {
-frsize = cb->sizes[i];
-n = min(frsize, ch->end - ch->cur);
-memcpy(ch->cur, cb->buffer + cb->offsets[i], n);
-ch->cur += n;
-if (ch->cur >= ch->end)
-ch->cur = ch->start;
-if (frsize > n) {
-memcpy(ch->cur, cb->buffer + cb->offsets[i] + n,
-frsize - n);
-ch->cur += frsize - n;
-}
-}
-
-/* Call back to upper layer */
-ch->transferred += count;
-#if defined(__FreeBSD__)
-s = spltty();
-chn_intr(ch->pcm_ch);
-splx(s);
+ /* Call back to upper layer */
+ ch->transferred += count;
+#if defined(__FreeBSD__)
+ s = spltty();
+ chn_intr(ch->pcm_ch);
+ splx(s);
#else
-s = splaudio();
-while (ch->transferred >= ch->blksize) {
-ch->transferred -= ch->blksize;
-DPRINTFN(5,("uaudio_chan_rintr: call %p(%p)n",
-ch->intr, ch->arg));
-ch->intr(ch->arg);
-}
-splx(s);
+ s = splaudio();
+ while (ch->transferred >= ch->blksize) {
+ ch->transferred -= ch->blksize;
+ DPRINTFN(5,("uaudio_chan_rintr: call %p(%p)\n",
+ ch->intr, ch->arg));
+ ch->intr(ch->arg);
+ }
+ splx(s);
#endif
-/* start next transfer */
-uaudio_chan_rtransfer(ch);
+ /* start next transfer */
+ uaudio_chan_rtransfer(ch);
}
#if defined(__NetBSD__) || defined(__OpenBSD__)
-Static void
+static void
uaudio_chan_init(struct chan *ch, int altidx, const struct audio_params *param,
-int maxpktsize)
+ int maxpktsize)
{
-int samples_per_frame, sample_size;
+ int samples_per_frame, sample_size;
-ch->altidx = altidx;
-sample_size = param->precision * param->factor * param->hw_channels / 8;
-samples_per_frame = param->hw_sample_rate / USB_FRAMES_PER_SECOND;
-ch->sample_size = sample_size;
-ch->sample_rate = param->hw_sample_rate;
-if (maxpktsize == 0) {
-ch->fraction = param->hw_sample_rate % USB_FRAMES_PER_SECOND;
-ch->bytes_per_frame = samples_per_frame * sample_size;
-} else {
-ch->fraction = 0;
-ch->bytes_per_frame = maxpktsize;
-}
-ch->residue = 0;
+ ch->altidx = altidx;
+ sample_size = param->precision * param->factor * param->hw_channels / 8;
+ samples_per_frame = param->hw_sample_rate / USB_FRAMES_PER_SECOND;
+ ch->sample_size = sample_size;
+ ch->sample_rate = param->hw_sample_rate;
+ if (maxpktsize == 0) {
+ ch->fraction = param->hw_sample_rate % USB_FRAMES_PER_SECOND;
+ ch->bytes_per_frame = samples_per_frame * sample_size;
+ } else {
+ ch->fraction = 0;
+ ch->bytes_per_frame = maxpktsize;
+ }
+ ch->residue = 0;
}
-Static void
+static void
uaudio_chan_set_param(struct chan *ch, u_char *start, u_char *end, int blksize)
{
-ch->start = start;
-ch->end = end;
-ch->cur = start;
-ch->blksize = blksize;
-ch->transferred = 0;
-ch->curchanbuf = 0;
+ ch->start = start;
+ ch->end = end;
+ ch->cur = start;
+ ch->blksize = blksize;
+ ch->transferred = 0;
+ ch->curchanbuf = 0;
}
-Static void
+static void
uaudio_get_minmax_rates(int nalts, const struct as_info *alts,
-const struct audio_params *p, int mode,
-u_long *min, u_long *max)
+ const struct audio_params *p, int mode,
+ u_long *min, u_long *max)
{
-const struct usb_audio_streaming_type1_descriptor *a1d;
-int i, j;
+ const struct usb_audio_streaming_type1_descriptor *a1d;
+ int i, j;
-*min = ULONG_MAX;
-*max = 0;
-for (i = 0; i < nalts; i++) {
-a1d = alts[i].asf1desc;
-if (alts[i].sc_busy)
-continue;
-if (p->hw_channels != a1d->bNrChannels)
-continue;
-if (p->hw_precision != a1d->bBitResolution)
-continue;
-if (p->hw_encoding != alts[i].encoding)
-continue;
-if (mode != UE_GET_DIR(alts[i].edesc->bEndpointAddress))
-continue;
-if (a1d->bSamFreqType == UA_SAMP_CONTNUOUS) {
-DPRINTFN(2,("uaudio_get_minmax_rates: cont %d-%dn",
-UA_SAMP_LO(a1d), UA_SAMP_HI(a1d)));
-if (UA_SAMP_LO(a1d) < *min)
-*min = UA_SAMP_LO(a1d);
-if (UA_SAMP_HI(a1d) > *max)
-*max = UA_SAMP_HI(a1d);
-} else {
-for (j = 0; j < a1d->bSamFreqType; j++) {
-DPRINTFN(2,("uaudio_get_minmax_rates: disc #%d: %dn",
-j, UA_GETSAMP(a1d, j)));
-if (UA_GETSAMP(a1d, j) < *min)
-*min = UA_GETSAMP(a1d, j);
-if (UA_GETSAMP(a1d, j) > *max)
-*max = UA_GETSAMP(a1d, j);
-}
-}
-}
+ *min = ULONG_MAX;
+ *max = 0;
+ for (i = 0; i < nalts; i++) {
+ a1d = alts[i].asf1desc;
+ if (alts[i].sc_busy)
+ continue;
+ if (p->hw_channels != a1d->bNrChannels)
+ continue;
+ if (p->hw_precision != a1d->bBitResolution)
+ continue;
+ if (p->hw_encoding != alts[i].encoding)
+ continue;
+ if (mode != UE_GET_DIR(alts[i].edesc->bEndpointAddress))
+ continue;
+ if (a1d->bSamFreqType == UA_SAMP_CONTNUOUS) {
+ DPRINTFN(2,("uaudio_get_minmax_rates: cont %d-%d\n",
+ UA_SAMP_LO(a1d), UA_SAMP_HI(a1d)));
+ if (UA_SAMP_LO(a1d) < *min)
+ *min = UA_SAMP_LO(a1d);
+ if (UA_SAMP_HI(a1d) > *max)
+ *max = UA_SAMP_HI(a1d);
+ } else {
+ for (j = 0; j < a1d->bSamFreqType; j++) {
+ DPRINTFN(2,("uaudio_get_minmax_rates: disc #%d: %d\n",
+ j, UA_GETSAMP(a1d, j)));
+ if (UA_GETSAMP(a1d, j) < *min)
+ *min = UA_GETSAMP(a1d, j);
+ if (UA_GETSAMP(a1d, j) > *max)
+ *max = UA_GETSAMP(a1d, j);
+ }
+ }
+ }
}
-Static int
+static int
uaudio_match_alt_sub(int nalts, const struct as_info *alts,
-const struct audio_params *p, int mode, u_long rate)
+ const struct audio_params *p, int mode, u_long rate)
{
-const struct usb_audio_streaming_type1_descriptor *a1d;
-int i, j;
+ const struct usb_audio_streaming_type1_descriptor *a1d;
+ int i, j;
-DPRINTF(("uaudio_match_alt_sub: search for %luHz %dchn",
-rate, p->hw_channels));
-for (i = 0; i < nalts; i++) {
-a1d = alts[i].asf1desc;
-if (alts[i].sc_busy)
-continue;
-if (p->hw_channels != a1d->bNrChannels)
-continue;
-if (p->hw_precision != a1d->bBitResolution)
-continue;
-if (p->hw_encoding != alts[i].encoding)
-continue;
-if (mode != UE_GET_DIR(alts[i].edesc->bEndpointAddress))
-continue;
-if (a1d->bSamFreqType == UA_SAMP_CONTNUOUS) {
-DPRINTFN(3,("uaudio_match_alt_sub: cont %d-%dn",
-UA_SAMP_LO(a1d), UA_SAMP_HI(a1d)));
-if (UA_SAMP_LO(a1d) <= rate && rate <= UA_SAMP_HI(a1d))
-return i;
-} else {
-for (j = 0; j < a1d->bSamFreqType; j++) {
-DPRINTFN(3,("uaudio_match_alt_sub: disc #%d: %dn",
-j, UA_GETSAMP(a1d, j)));
-/* XXX allow for some slack */
-if (UA_GETSAMP(a1d, j) == rate)
-return i;
-}
-}
-}
-return -1;
+ DPRINTF(("uaudio_match_alt_sub: search for %luHz %dch\n",
+ rate, p->hw_channels));
+ for (i = 0; i < nalts; i++) {
+ a1d = alts[i].asf1desc;
+ if (alts[i].sc_busy)
+ continue;
+ if (p->hw_channels != a1d->bNrChannels)
+ continue;
+ if (p->hw_precision != a1d->bBitResolution)
+ continue;
+ if (p->hw_encoding != alts[i].encoding)
+ continue;
+ if (mode != UE_GET_DIR(alts[i].edesc->bEndpointAddress))
+ continue;
+ if (a1d->bSamFreqType == UA_SAMP_CONTNUOUS) {
+ DPRINTFN(3,("uaudio_match_alt_sub: cont %d-%d\n",
+ UA_SAMP_LO(a1d), UA_SAMP_HI(a1d)));
+ if (UA_SAMP_LO(a1d) <= rate && rate <= UA_SAMP_HI(a1d))
+ return i;
+ } else {
+ for (j = 0; j < a1d->bSamFreqType; j++) {
+ DPRINTFN(3,("uaudio_match_alt_sub: disc #%d: %d\n",
+ j, UA_GETSAMP(a1d, j)));
+ /* XXX allow for some slack */
+ if (UA_GETSAMP(a1d, j) == rate)
+ return i;
+ }
+ }
+ }
+ return -1;
}
-Static int
+static int
uaudio_match_alt_chan(int nalts, const struct as_info *alts,
-struct audio_params *p, int mode)
+ struct audio_params *p, int mode)
{
-int i, n;
-u_long min, max;
-u_long rate;
-
-/* Exact match */
-DPRINTF(("uaudio_match_alt_chan: examine %ldHz %dch %dbit.n",
-p->sample_rate, p->hw_channels, p->hw_precision));
-i = uaudio_match_alt_sub(nalts, alts, p, mode, p->sample_rate);
-if (i >= 0)
-return i;
-
-uaudio_get_minmax_rates(nalts, alts, p, mode, &min, &max);
-DPRINTF(("uaudio_match_alt_chan: min=%lu max=%lun", min, max));
-if (max <= 0)
-return -1;
-/* Search for biggers */
-n = 2;
-while ((rate = p->sample_rate * n++) <= max) {
-i = uaudio_match_alt_sub(nalts, alts, p, mode, rate);
-if (i >= 0) {
-p->hw_sample_rate = rate;
-return i;
-}
-}
-if (p->sample_rate >= min) {
-i = uaudio_match_alt_sub(nalts, alts, p, mode, max);
-if (i >= 0) {
-p->hw_sample_rate = max;
-return i;
-}
-} else {
-i = uaudio_match_alt_sub(nalts, alts, p, mode, min);
-if (i >= 0) {
-p->hw_sample_rate = min;
-return i;
-}
-}
-return -1;
+ int i, n;
+ u_long min, max;
+ u_long rate;
+
+ /* Exact match */
+ DPRINTF(("uaudio_match_alt_chan: examine %ldHz %dch %dbit.\n",
+ p->sample_rate, p->hw_channels, p->hw_precision));
+ i = uaudio_match_alt_sub(nalts, alts, p, mode, p->sample_rate);
+ if (i >= 0)
+ return i;
+
+ uaudio_get_minmax_rates(nalts, alts, p, mode, &min, &max);
+ DPRINTF(("uaudio_match_alt_chan: min=%lu max=%lu\n", min, max));
+ if (max <= 0)
+ return -1;
+ /* Search for biggers */
+ n = 2;
+ while ((rate = p->sample_rate * n++) <= max) {
+ i = uaudio_match_alt_sub(nalts, alts, p, mode, rate);
+ if (i >= 0) {
+ p->hw_sample_rate = rate;
+ return i;
+ }
+ }
+ if (p->sample_rate >= min) {
+ i = uaudio_match_alt_sub(nalts, alts, p, mode, max);
+ if (i >= 0) {
+ p->hw_sample_rate = max;
+ return i;
+ }
+ } else {
+ i = uaudio_match_alt_sub(nalts, alts, p, mode, min);
+ if (i >= 0) {
+ p->hw_sample_rate = min;
+ return i;
+ }
+ }
+ return -1;
}
-Static int
+static int
uaudio_match_alt(int nalts, const struct as_info *alts,
-struct audio_params *p, int mode)
+ struct audio_params *p, int mode)
{
-int i, n;
-
-mode = mode == AUMODE_PLAY ? UE_DIR_OUT : UE_DIR_IN;
-i = uaudio_match_alt_chan(nalts, alts, p, mode);
-if (i >= 0)
-return i;
-
-for (n = p->channels + 1; n <= AUDIO_MAX_CHANNELS; n++) {
-p->hw_channels = n;
-i = uaudio_match_alt_chan(nalts, alts, p, mode);
-if (i >= 0)
-return i;
-}
+ int i, n;
-if (p->channels != 2)
-return -1;
-p->hw_channels = 1;
-return uaudio_match_alt_chan(nalts, alts, p, mode);
+ mode = mode == AUMODE_PLAY ? UE_DIR_OUT : UE_DIR_IN;
+ i = uaudio_match_alt_chan(nalts, alts, p, mode);
+ if (i >= 0)
+ return i;
+
+ for (n = p->channels + 1; n <= AUDIO_MAX_CHANNELS; n++) {
+ p->hw_channels = n;
+ i = uaudio_match_alt_chan(nalts, alts, p, mode);
+ if (i >= 0)
+ return i;
+ }
+
+ if (p->channels != 2)
+ return -1;
+ p->hw_channels = 1;
+ return uaudio_match_alt_chan(nalts, alts, p, mode);
}
-Static int
+static int
uaudio_set_params(void *addr, int setmode, int usemode,
-struct audio_params *play, struct audio_params *rec)
+ struct audio_params *play, struct audio_params *rec)
{
-struct uaudio_softc *sc;
-int flags;
-int factor;
-int enc, i;
-int paltidx, raltidx;
-void (*swcode)(void *, u_char *buf, int cnt);
-struct audio_params *p;
-int mode;
-
-sc = addr;
-flags = sc->sc_altflags;
-paltidx = -1;
-raltidx = -1;
-if (sc->sc_dying)
-return EIO;
-
-if (((usemode & AUMODE_PLAY) && sc->sc_playchan.pipe != NULL) ||
-((usemode & AUMODE_RECORD) && sc->sc_recchan.pipe != NULL))
-return EBUSY;
-
-if ((usemode & AUMODE_PLAY) && sc->sc_playchan.altidx != -1)
-sc->sc_alts[sc->sc_playchan.altidx].sc_busy = 0;
-if ((usemode & AUMODE_RECORD) && sc->sc_recchan.altidx != -1)
-sc->sc_alts[sc->sc_recchan.altidx].sc_busy = 0;
-
-/* Some uaudio devices are unidirectional. Don't try to find a
-matching mode for the unsupported direction. */
-setmode &= sc->sc_mode;
-
-for (mode = AUMODE_RECORD; mode != -1;
-mode = mode == AUMODE_RECORD ? AUMODE_PLAY : -1) {
-if ((setmode & mode) == 0)
-continue;
-
-p = (mode == AUMODE_PLAY) ? play : rec;
-
-factor = 1;
-swcode = 0;
-enc = p->encoding;
-switch (enc) {
-case AUDIO_ENCODING_SLINEAR_BE:
-/* FALLTHROUGH */
-case AUDIO_ENCODING_SLINEAR_LE:
-if (enc == AUDIO_ENCODING_SLINEAR_BE
-&& p->precision == 16 && (flags & HAS_16)) {
-swcode = swap_bytes;
-enc = AUDIO_ENCODING_SLINEAR_LE;
-} else if (p->precision == 8) {
-if (flags & HAS_8) {
-/* No conversion */
-} else if (flags & HAS_8U) {
-swcode = change_sign8;
-enc = AUDIO_ENCODING_ULINEAR_LE;
-} else if (flags & HAS_16) {
-factor = 2;
-p->hw_precision = 16;
-if (mode == AUMODE_PLAY)
-swcode = linear8_to_linear16_le;
-else
-swcode = linear16_to_linear8_le;
-}
-}
-break;
-case AUDIO_ENCODING_ULINEAR_BE:
-/* FALLTHROUGH */
-case AUDIO_ENCODING_ULINEAR_LE:
-if (p->precision == 16) {
-if (enc == AUDIO_ENCODING_ULINEAR_LE)
-swcode = change_sign16_le;
-else if (mode == AUMODE_PLAY)
-swcode = swap_bytes_change_sign16_le;
-else
-swcode = change_sign16_swap_bytes_le;
-enc = AUDIO_ENCODING_SLINEAR_LE;
-} else if (p->precision == 8) {
-if (flags & HAS_8U) {
-/* No conversion */
-} else if (flags & HAS_8) {
-swcode = change_sign8;
-enc = AUDIO_ENCODING_SLINEAR_LE;
-} else if (flags & HAS_16) {
-factor = 2;
-p->hw_precision = 16;
-enc = AUDIO_ENCODING_SLINEAR_LE;
-if (mode == AUMODE_PLAY)
-swcode = ulinear8_to_slinear16_le;
-else
-swcode = slinear16_to_ulinear8_le;
-}
-}
-break;
-case AUDIO_ENCODING_ULAW:
-if (flags & HAS_MULAW)
-break;
-if (flags & HAS_16) {
-if (mode == AUMODE_PLAY)
-swcode = mulaw_to_slinear16_le;
-else
-swcode = slinear16_to_mulaw_le;
-factor = 2;
-enc = AUDIO_ENCODING_SLINEAR_LE;
-p->hw_precision = 16;
-} else if (flags & HAS_8U) {
-if (mode == AUMODE_PLAY)
-swcode = mulaw_to_ulinear8;
-else
-swcode = ulinear8_to_mulaw;
-enc = AUDIO_ENCODING_ULINEAR_LE;
-} else if (flags & HAS_8) {
-if (mode == AUMODE_PLAY)
-swcode = mulaw_to_slinear8;
-else
-swcode = slinear8_to_mulaw;
-enc = AUDIO_ENCODING_SLINEAR_LE;
-} else
-return (EINVAL);
-break;
-case AUDIO_ENCODING_ALAW:
-if (flags & HAS_ALAW)
-break;
-if (mode == AUMODE_PLAY && (flags & HAS_16)) {
-swcode = alaw_to_slinear16_le;
-factor = 2;
-enc = AUDIO_ENCODING_SLINEAR_LE;
-p->hw_precision = 16;
-} else if (flags & HAS_8U) {
-if (mode == AUMODE_PLAY)
-swcode = alaw_to_ulinear8;
-else
-swcode = ulinear8_to_alaw;
-enc = AUDIO_ENCODING_ULINEAR_LE;
-} else if (flags & HAS_8) {
-if (mode == AUMODE_PLAY)
-swcode = alaw_to_slinear8;
-else
-swcode = slinear8_to_alaw;
-enc = AUDIO_ENCODING_SLINEAR_LE;
-} else
-return (EINVAL);
-break;
-default:
-return (EINVAL);
-}
-/* XXX do some other conversions... */
-
-DPRINTF(("uaudio_set_params: chan=%d prec=%d enc=%d rate=%ldn",
-p->channels, p->hw_precision, enc, p->sample_rate));
-
-p->hw_encoding = enc;
-i = uaudio_match_alt(sc->sc_nalts, sc->sc_alts, p, mode);
-if (i < 0)
-return (EINVAL);
-
-p->sw_code = swcode;
-p->factor = factor;
-
-if (mode == AUMODE_PLAY)
-paltidx = i;
-else
-raltidx = i;
-}
-
-if ((setmode & AUMODE_PLAY)) {
-/* XXX abort transfer if currently happening? */
-uaudio_chan_init(&sc->sc_playchan, paltidx, play, 0);
-}
-if ((setmode & AUMODE_RECORD)) {
-/* XXX abort transfer if currently happening? */
-uaudio_chan_init(&sc->sc_recchan, raltidx, rec,
-UGETW(sc->sc_alts[raltidx].edesc->wMaxPacketSize));
-}
-
-if ((usemode & AUMODE_PLAY) && sc->sc_playchan.altidx != -1)
-sc->sc_alts[sc->sc_playchan.altidx].sc_busy = 1;
-if ((usemode & AUMODE_RECORD) && sc->sc_recchan.altidx != -1)
-sc->sc_alts[sc->sc_recchan.altidx].sc_busy = 1;
-
-DPRINTF(("uaudio_set_params: use altidx=p%d/r%d, altno=p%d/r%dn",
-sc->sc_playchan.altidx, sc->sc_recchan.altidx,
-(sc->sc_playchan.altidx >= 0)
-?sc->sc_alts[sc->sc_playchan.altidx].idesc->bAlternateSetting
-: -1,
-(sc->sc_recchan.altidx >= 0)
-? sc->sc_alts[sc->sc_recchan.altidx].idesc->bAlternateSetting
-: -1));
+ struct uaudio_softc *sc;
+ int flags;
+ int factor;
+ int enc, i;
+ int paltidx, raltidx;
+ void (*swcode)(void *, u_char *buf, int cnt);
+ struct audio_params *p;
+ int mode;
+
+ sc = addr;
+ flags = sc->sc_altflags;
+ paltidx = -1;
+ raltidx = -1;
+ if (sc->sc_dying)
+ return EIO;
+
+ if (((usemode & AUMODE_PLAY) && sc->sc_playchan.pipe != NULL) ||
+ ((usemode & AUMODE_RECORD) && sc->sc_recchan.pipe != NULL))
+ return EBUSY;
+
+ if ((usemode & AUMODE_PLAY) && sc->sc_playchan.altidx != -1)
+ sc->sc_alts[sc->sc_playchan.altidx].sc_busy = 0;
+ if ((usemode & AUMODE_RECORD) && sc->sc_recchan.altidx != -1)
+ sc->sc_alts[sc->sc_recchan.altidx].sc_busy = 0;
+
+ /* Some uaudio devices are unidirectional. Don't try to find a
+ matching mode for the unsupported direction. */
+ setmode &= sc->sc_mode;
+
+ for (mode = AUMODE_RECORD; mode != -1;
+ mode = mode == AUMODE_RECORD ? AUMODE_PLAY : -1) {
+ if ((setmode & mode) == 0)
+ continue;
+
+ p = (mode == AUMODE_PLAY) ? play : rec;
+
+ factor = 1;
+ swcode = 0;
+ enc = p->encoding;
+ switch (enc) {
+ case AUDIO_ENCODING_SLINEAR_BE:
+ /* FALLTHROUGH */
+ case AUDIO_ENCODING_SLINEAR_LE:
+ if (enc == AUDIO_ENCODING_SLINEAR_BE
+ && p->precision == 16 && (flags & HAS_16)) {
+ swcode = swap_bytes;
+ enc = AUDIO_ENCODING_SLINEAR_LE;
+ } else if (p->precision == 8) {
+ if (flags & HAS_8) {
+ /* No conversion */
+ } else if (flags & HAS_8U) {
+ swcode = change_sign8;
+ enc = AUDIO_ENCODING_ULINEAR_LE;
+ } else if (flags & HAS_16) {
+ factor = 2;
+ p->hw_precision = 16;
+ if (mode == AUMODE_PLAY)
+ swcode = linear8_to_linear16_le;
+ else
+ swcode = linear16_to_linear8_le;
+ }
+ }
+ break;
+ case AUDIO_ENCODING_ULINEAR_BE:
+ /* FALLTHROUGH */
+ case AUDIO_ENCODING_ULINEAR_LE:
+ if (p->precision == 16) {
+ if (enc == AUDIO_ENCODING_ULINEAR_LE)
+ swcode = change_sign16_le;
+ else if (mode == AUMODE_PLAY)
+ swcode = swap_bytes_change_sign16_le;
+ else
+ swcode = change_sign16_swap_bytes_le;
+ enc = AUDIO_ENCODING_SLINEAR_LE;
+ } else if (p->precision == 8) {
+ if (flags & HAS_8U) {
+ /* No conversion */
+ } else if (flags & HAS_8) {
+ swcode = change_sign8;
+ enc = AUDIO_ENCODING_SLINEAR_LE;
+ } else if (flags & HAS_16) {
+ factor = 2;
+ p->hw_precision = 16;
+ enc = AUDIO_ENCODING_SLINEAR_LE;
+ if (mode == AUMODE_PLAY)
+ swcode = ulinear8_to_slinear16_le;
+ else
+ swcode = slinear16_to_ulinear8_le;
+ }
+ }
+ break;
+ case AUDIO_ENCODING_ULAW:
+ if (flags & HAS_MULAW)
+ break;
+ if (flags & HAS_16) {
+ if (mode == AUMODE_PLAY)
+ swcode = mulaw_to_slinear16_le;
+ else
+ swcode = slinear16_to_mulaw_le;
+ factor = 2;
+ enc = AUDIO_ENCODING_SLINEAR_LE;
+ p->hw_precision = 16;
+ } else if (flags & HAS_8U) {
+ if (mode == AUMODE_PLAY)
+ swcode = mulaw_to_ulinear8;
+ else
+ swcode = ulinear8_to_mulaw;
+ enc = AUDIO_ENCODING_ULINEAR_LE;
+ } else if (flags & HAS_8) {
+ if (mode == AUMODE_PLAY)
+ swcode = mulaw_to_slinear8;
+ else
+ swcode = slinear8_to_mulaw;
+ enc = AUDIO_ENCODING_SLINEAR_LE;
+ } else
+ return (EINVAL);
+ break;
+ case AUDIO_ENCODING_ALAW:
+ if (flags & HAS_ALAW)
+ break;
+ if (mode == AUMODE_PLAY && (flags & HAS_16)) {
+ swcode = alaw_to_slinear16_le;
+ factor = 2;
+ enc = AUDIO_ENCODING_SLINEAR_LE;
+ p->hw_precision = 16;
+ } else if (flags & HAS_8U) {
+ if (mode == AUMODE_PLAY)
+ swcode = alaw_to_ulinear8;
+ else
+ swcode = ulinear8_to_alaw;
+ enc = AUDIO_ENCODING_ULINEAR_LE;
+ } else if (flags & HAS_8) {
+ if (mode == AUMODE_PLAY)
+ swcode = alaw_to_slinear8;
+ else
+ swcode = slinear8_to_alaw;
+ enc = AUDIO_ENCODING_SLINEAR_LE;
+ } else
+ return (EINVAL);
+ break;
+ default:
+ return (EINVAL);
+ }
+ /* XXX do some other conversions... */
+
+ DPRINTF(("uaudio_set_params: chan=%d prec=%d enc=%d rate=%ld\n",
+ p->channels, p->hw_precision, enc, p->sample_rate));
+
+ p->hw_encoding = enc;
+ i = uaudio_match_alt(sc->sc_nalts, sc->sc_alts, p, mode);
+ if (i < 0)
+ return (EINVAL);
+
+ p->sw_code = swcode;
+ p->factor = factor;
+
+ if (mode == AUMODE_PLAY)
+ paltidx = i;
+ else
+ raltidx = i;
+ }
+
+ if ((setmode & AUMODE_PLAY)) {
+ /* XXX abort transfer if currently happening? */
+ uaudio_chan_init(&sc->sc_playchan, paltidx, play, 0);
+ }
+ if ((setmode & AUMODE_RECORD)) {
+ /* XXX abort transfer if currently happening? */
+ uaudio_chan_init(&sc->sc_recchan, raltidx, rec,
+ UGETW(sc->sc_alts[raltidx].edesc->wMaxPacketSize));
+ }
+
+ if ((usemode & AUMODE_PLAY) && sc->sc_playchan.altidx != -1)
+ sc->sc_alts[sc->sc_playchan.altidx].sc_busy = 1;
+ if ((usemode & AUMODE_RECORD) && sc->sc_recchan.altidx != -1)
+ sc->sc_alts[sc->sc_recchan.altidx].sc_busy = 1;
+
+ DPRINTF(("uaudio_set_params: use altidx=p%d/r%d, altno=p%d/r%d\n",
+ sc->sc_playchan.altidx, sc->sc_recchan.altidx,
+ (sc->sc_playchan.altidx >= 0)
+ ?sc->sc_alts[sc->sc_playchan.altidx].idesc->bAlternateSetting
+ : -1,
+ (sc->sc_recchan.altidx >= 0)
+ ? sc->sc_alts[sc->sc_recchan.altidx].idesc->bAlternateSetting
+ : -1));
-return 0;
+ return 0;
}
#endif /* NetBSD or OpenBSD */
-Static usbd_status
+static usbd_status
uaudio_set_speed(struct uaudio_softc *sc, int endpt, u_int speed)
{
-usb_device_request_t req;
-uint8_t data[3];
+ usb_device_request_t req;
+ uint8_t data[3];
-DPRINTFN(5,("uaudio_set_speed: endpt=%d speed=%un", endpt, speed));
-req.bmRequestType = UT_WRITE_CLASS_ENDPOINT;
-req.bRequest = SET_CUR;
-USETW2(req.wValue, SAMPLING_FREQ_CONTROL, 0);
-USETW(req.wIndex, endpt);
-USETW(req.wLength, 3);
-data[0] = speed;
-data[1] = speed >> 8;
-data[2] = speed >> 16;
+ DPRINTFN(5,("uaudio_set_speed: endpt=%d speed=%u\n", endpt, speed));
+ req.bmRequestType = UT_WRITE_CLASS_ENDPOINT;
+ req.bRequest = SET_CUR;
+ USETW2(req.wValue, SAMPLING_FREQ_CONTROL, 0);
+ USETW(req.wIndex, endpt);
+ USETW(req.wLength, 3);
+ data[0] = speed;
+ data[1] = speed >> 8;
+ data[2] = speed >> 16;
-return usbd_do_request(sc->sc_udev, &req, data);
+#if defined(__FreeBSD__)
+ if (sc->async != 0)
+ return usbd_do_request_async(sc->sc_udev, &req, data);
+#endif
+ return usbd_do_request(sc->sc_udev, &req, data);
}
@@ -3738,806 +3828,833 @@
int
uaudio_init_params(struct uaudio_softc *sc, struct chan *ch, int mode)
{
-int i, j, enc;
-int samples_per_frame, sample_size;
+ int i, j, enc;
+ int samples_per_frame, sample_size;
-if ((sc->sc_playchan.pipe != NULL) || (sc->sc_recchan.pipe != NULL))
-return (-1);
+ if ((sc->sc_playchan.pipe != NULL) || (sc->sc_recchan.pipe != NULL))
+ return (-1);
-switch(ch->format & 0x000FFFFF) {
-case AFMT_U8:
-enc = AUDIO_ENCODING_ULINEAR_LE;
-ch->precision = 8;
-break;
-case AFMT_S8:
-enc = AUDIO_ENCODING_SLINEAR_LE;
-ch->precision = 8;
-break;
-case AFMT_A_LAW: /* ? */
-enc = AUDIO_ENCODING_ALAW;
-ch->precision = 8;
-break;
-case AFMT_MU_LAW: /* ? */
-enc = AUDIO_ENCODING_ULAW;
-ch->precision = 8;
-break;
-case AFMT_S16_LE:
-enc = AUDIO_ENCODING_SLINEAR_LE;
-ch->precision = 16;
-break;
-case AFMT_S16_BE:
-enc = AUDIO_ENCODING_SLINEAR_BE;
-ch->precision = 16;
-break;
-case AFMT_U16_LE:
-enc = AUDIO_ENCODING_ULINEAR_LE;
-ch->precision = 16;
-break;
-case AFMT_U16_BE:
-enc = AUDIO_ENCODING_ULINEAR_BE;
-ch->precision = 16;
-break;
-case AFMT_S24_LE:
-enc = AUDIO_ENCODING_SLINEAR_LE;
-ch->precision = 24;
-break;
-case AFMT_S24_BE:
-enc = AUDIO_ENCODING_SLINEAR_BE;
-ch->precision = 24;
-break;
-case AFMT_U24_LE:
-enc = AUDIO_ENCODING_ULINEAR_LE;
-ch->precision = 24;
-break;
-case AFMT_U24_BE:
-enc = AUDIO_ENCODING_ULINEAR_BE;
-ch->precision = 24;
-break;
-case AFMT_S32_LE:
-enc = AUDIO_ENCODING_SLINEAR_LE;
-ch->precision = 32;
-break;
-case AFMT_S32_BE:
-enc = AUDIO_ENCODING_SLINEAR_BE;
-ch->precision = 32;
-break;
-case AFMT_U32_LE:
-enc = AUDIO_ENCODING_ULINEAR_LE;
-ch->precision = 32;
-break;
-case AFMT_U32_BE:
-enc = AUDIO_ENCODING_ULINEAR_BE;
-ch->precision = 32;
-break;
-default:
-enc = 0;
-ch->precision = 16;
-printf("Unknown format %xn", ch->format);
-}
-
-if (ch->format & AFMT_STEREO) {
-ch->channels = 2;
-} else {
-ch->channels = 1;
-}
+ switch(ch->format & 0x000FFFFF) {
+ case AFMT_U8:
+ enc = AUDIO_ENCODING_ULINEAR_LE;
+ ch->precision = 8;
+ break;
+ case AFMT_S8:
+ enc = AUDIO_ENCODING_SLINEAR_LE;
+ ch->precision = 8;
+ break;
+ case AFMT_A_LAW: /* ? */
+ enc = AUDIO_ENCODING_ALAW;
+ ch->precision = 8;
+ break;
+ case AFMT_MU_LAW: /* ? */
+ enc = AUDIO_ENCODING_ULAW;
+ ch->precision = 8;
+ break;
+ case AFMT_S16_LE:
+ enc = AUDIO_ENCODING_SLINEAR_LE;
+ ch->precision = 16;
+ break;
+ case AFMT_S16_BE:
+ enc = AUDIO_ENCODING_SLINEAR_BE;
+ ch->precision = 16;
+ break;
+ case AFMT_U16_LE:
+ enc = AUDIO_ENCODING_ULINEAR_LE;
+ ch->precision = 16;
+ break;
+ case AFMT_U16_BE:
+ enc = AUDIO_ENCODING_ULINEAR_BE;
+ ch->precision = 16;
+ break;
+ case AFMT_S24_LE:
+ enc = AUDIO_ENCODING_SLINEAR_LE;
+ ch->precision = 24;
+ break;
+ case AFMT_S24_BE:
+ enc = AUDIO_ENCODING_SLINEAR_BE;
+ ch->precision = 24;
+ break;
+ case AFMT_U24_LE:
+ enc = AUDIO_ENCODING_ULINEAR_LE;
+ ch->precision = 24;
+ break;
+ case AFMT_U24_BE:
+ enc = AUDIO_ENCODING_ULINEAR_BE;
+ ch->precision = 24;
+ break;
+ case AFMT_S32_LE:
+ enc = AUDIO_ENCODING_SLINEAR_LE;
+ ch->precision = 32;
+ break;
+ case AFMT_S32_BE:
+ enc = AUDIO_ENCODING_SLINEAR_BE;
+ ch->precision = 32;
+ break;
+ case AFMT_U32_LE:
+ enc = AUDIO_ENCODING_ULINEAR_LE;
+ ch->precision = 32;
+ break;
+ case AFMT_U32_BE:
+ enc = AUDIO_ENCODING_ULINEAR_BE;
+ ch->precision = 32;
+ break;
+ default:
+ enc = 0;
+ ch->precision = 16;
+ printf("Unknown format %x\n", ch->format);
+ }
+
+ if (ch->format & AFMT_STEREO) {
+ ch->channels = 2;
+ } else {
+ ch->channels = 1;
+ }
/* for (mode = ...... */
-for (i = 0; i < sc->sc_nalts; i++) {
-const struct usb_audio_streaming_type1_descriptor *a1d =
-sc->sc_alts[i].asf1desc;
-if (ch->channels == a1d->bNrChannels &&
-ch->precision == a1d->bBitResolution &&
+ for (i = 0; i < sc->sc_nalts; i++) {
+ const struct usb_audio_streaming_type1_descriptor *a1d =
+ sc->sc_alts[i].asf1desc;
+ if (ch->channels == a1d->bNrChannels &&
+ ch->precision == a1d->bBitResolution &&
#if 0
-enc == sc->sc_alts[i].encoding) {
+ enc == sc->sc_alts[i].encoding) {
#else
-enc == sc->sc_alts[i].encoding &&
-(mode == AUMODE_PLAY ? UE_DIR_OUT : UE_DIR_IN) ==
-UE_GET_DIR(sc->sc_alts[i].edesc->bEndpointAddress)) {
-#endif
-if (a1d->bSamFreqType == UA_SAMP_CONTNUOUS) {
-DPRINTFN(2,("uaudio_set_params: cont %d-%dn",
-UA_SAMP_LO(a1d), UA_SAMP_HI(a1d)));
-if (UA_SAMP_LO(a1d) <= ch->sample_rate &&
-ch->sample_rate <= UA_SAMP_HI(a1d)) {
-if (mode == AUMODE_PLAY)
-sc->sc_playchan.altidx = i;
-else
-sc->sc_recchan.altidx = i;
-goto found;
-}
-} else {
-for (j = 0; j < a1d->bSamFreqType; j++) {
-DPRINTFN(2,("uaudio_set_params: disc #"
-"%d: %dn", j, UA_GETSAMP(a1d, j)));
-/* XXX allow for some slack */
-if (UA_GETSAMP(a1d, j) ==
-ch->sample_rate) {
-if (mode == AUMODE_PLAY)
-sc->sc_playchan.altidx = i;
-else
-sc->sc_recchan.altidx = i;
-goto found;
-}
-}
-}
-}
-}
-/* return (EINVAL); */
-if (mode == AUMODE_PLAY)
-printf("uaudio: This device can't play in rate=%d.n", ch->sample_rate);
-else
-printf("uaudio: This device can't record in rate=%d.n", ch->sample_rate);
-return (-1);
+ enc == sc->sc_alts[i].encoding &&
+ (mode == AUMODE_PLAY ? UE_DIR_OUT : UE_DIR_IN) ==
+ UE_GET_DIR(sc->sc_alts[i].edesc->bEndpointAddress)) {
+#endif
+ if (a1d->bSamFreqType == UA_SAMP_CONTNUOUS) {
+ DPRINTFN(2,("uaudio_set_params: cont %d-%d\n",
+ UA_SAMP_LO(a1d), UA_SAMP_HI(a1d)));
+ if (UA_SAMP_LO(a1d) <= ch->sample_rate &&
+ ch->sample_rate <= UA_SAMP_HI(a1d)) {
+ if (mode == AUMODE_PLAY)
+ sc->sc_playchan.altidx = i;
+ else
+ sc->sc_recchan.altidx = i;
+ goto found;
+ }
+ } else {
+ for (j = 0; j < a1d->bSamFreqType; j++) {
+ DPRINTFN(2,("uaudio_set_params: disc #"
+ "%d: %d\n", j, UA_GETSAMP(a1d, j)));
+ /* XXX allow for some slack */
+ if (UA_GETSAMP(a1d, j) ==
+ ch->sample_rate) {
+ if (mode == AUMODE_PLAY)
+ sc->sc_playchan.altidx = i;
+ else
+ sc->sc_recchan.altidx = i;
+ goto found;
+ }
+ }
+ }
+ }
+ }
+ /* return (EINVAL); */
+ if (mode == AUMODE_PLAY)
+ printf("uaudio: This device can't play in rate=%d.\n", ch->sample_rate);
+ else
+ printf("uaudio: This device can't record in rate=%d.\n", ch->sample_rate);
+ return (-1);
-found:
+ found:
#if 0 /* XXX */
-p->sw_code = swcode;
-p->factor = factor;
-if (usemode == mode)
-sc->sc_curaltidx = i;
+ p->sw_code = swcode;
+ p->factor = factor;
+ if (usemode == mode)
+ sc->sc_curaltidx = i;
#endif
/* } */
-sample_size = ch->precision * ch->channels / 8;
-samples_per_frame = ch->sample_rate / USB_FRAMES_PER_SECOND;
-ch->fraction = ch->sample_rate % USB_FRAMES_PER_SECOND;
-ch->sample_size = sample_size;
-ch->bytes_per_frame = samples_per_frame * sample_size;
-ch->residue = 0;
-
-ch->cur = ch->start;
-ch->transferred = 0;
-ch->curchanbuf = 0;
-return (0);
+ sample_size = ch->precision * ch->channels / 8;
+ samples_per_frame = ch->sample_rate / USB_FRAMES_PER_SECOND;
+ ch->fraction = ch->sample_rate % USB_FRAMES_PER_SECOND;
+ ch->sample_size = sample_size;
+ ch->bytes_per_frame = samples_per_frame * sample_size;
+ ch->residue = 0;
+
+ ch->cur = ch->start;
+ ch->transferred = 0;
+ ch->curchanbuf = 0;
+ return (0);
}
struct uaudio_conversion {
-uint8_t uaudio_fmt;
-uint8_t uaudio_prec;
-uint32_t freebsd_fmt;
+ uint8_t uaudio_fmt;
+ uint8_t uaudio_prec;
+ uint32_t freebsd_fmt;
};
const struct uaudio_conversion const accepted_conversion[] = {
-{AUDIO_ENCODING_ULINEAR_LE, 8, AFMT_U8},
-{AUDIO_ENCODING_ULINEAR_LE, 16, AFMT_U16_LE},
-{AUDIO_ENCODING_ULINEAR_LE, 24, AFMT_U24_LE},
-{AUDIO_ENCODING_ULINEAR_LE, 32, AFMT_U32_LE},
-{AUDIO_ENCODING_ULINEAR_BE, 16, AFMT_U16_BE},
-{AUDIO_ENCODING_ULINEAR_BE, 24, AFMT_U24_BE},
-{AUDIO_ENCODING_ULINEAR_BE, 32, AFMT_U32_BE},
-{AUDIO_ENCODING_SLINEAR_LE, 8, AFMT_S8},
-{AUDIO_ENCODING_SLINEAR_LE, 16, AFMT_S16_LE},
-{AUDIO_ENCODING_SLINEAR_LE, 24, AFMT_S24_LE},
-{AUDIO_ENCODING_SLINEAR_LE, 32, AFMT_S32_LE},
-{AUDIO_ENCODING_SLINEAR_BE, 16, AFMT_S16_BE},
-{AUDIO_ENCODING_SLINEAR_BE, 24, AFMT_S24_BE},
-{AUDIO_ENCODING_SLINEAR_BE, 32, AFMT_S32_BE},
-{AUDIO_ENCODING_ALAW, 8, AFMT_A_LAW},
-{AUDIO_ENCODING_ULAW, 8, AFMT_MU_LAW},
-{0,0,0}
+ {AUDIO_ENCODING_ULINEAR_LE, 8, AFMT_U8},
+ {AUDIO_ENCODING_ULINEAR_LE, 16, AFMT_U16_LE},
+ {AUDIO_ENCODING_ULINEAR_LE, 24, AFMT_U24_LE},
+ {AUDIO_ENCODING_ULINEAR_LE, 32, AFMT_U32_LE},
+ {AUDIO_ENCODING_ULINEAR_BE, 16, AFMT_U16_BE},
+ {AUDIO_ENCODING_ULINEAR_BE, 24, AFMT_U24_BE},
+ {AUDIO_ENCODING_ULINEAR_BE, 32, AFMT_U32_BE},
+ {AUDIO_ENCODING_SLINEAR_LE, 8, AFMT_S8},
+ {AUDIO_ENCODING_SLINEAR_LE, 16, AFMT_S16_LE},
+ {AUDIO_ENCODING_SLINEAR_LE, 24, AFMT_S24_LE},
+ {AUDIO_ENCODING_SLINEAR_LE, 32, AFMT_S32_LE},
+ {AUDIO_ENCODING_SLINEAR_BE, 16, AFMT_S16_BE},
+ {AUDIO_ENCODING_SLINEAR_BE, 24, AFMT_S24_BE},
+ {AUDIO_ENCODING_SLINEAR_BE, 32, AFMT_S32_BE},
+ {AUDIO_ENCODING_ALAW, 8, AFMT_A_LAW},
+ {AUDIO_ENCODING_ULAW, 8, AFMT_MU_LAW},
+ {0,0,0}
};
unsigned
uaudio_query_formats(device_t dev, int reqdir, unsigned maxfmt, struct pcmchan_caps *cap)
{
-struct uaudio_softc *sc;
-const struct usb_audio_streaming_type1_descriptor *asf1d;
-const struct uaudio_conversion *iterator;
-unsigned fmtcount, foundcount;
-u_int32_t fmt;
-uint8_t format, numchan, subframesize, prec, dir, iscontinuous;
-int freq, freq_min, freq_max;
-char *numchannel_descr;
-char freq_descr[64];
-int i,r;
-
-sc = device_get_softc(dev);
-if (sc == NULL)
-return 0;
-
-cap->minspeed = cap->maxspeed = 0;
-foundcount = fmtcount = 0;
-
-for (i = 0; i < sc->sc_nalts; i++) {
-dir = UE_GET_DIR(sc->sc_alts[i].edesc->bEndpointAddress);
-
-if ((dir == UE_DIR_OUT) != (reqdir == PCMDIR_PLAY))
-continue;
-
-asf1d = sc->sc_alts[i].asf1desc;
-format = sc->sc_alts[i].encoding;
-
-numchan = asf1d->bNrChannels;
-subframesize = asf1d->bSubFrameSize;
-prec = asf1d->bBitResolution; /* precision */
-iscontinuous = asf1d->bSamFreqType == UA_SAMP_CONTNUOUS;
-
-if (iscontinuous)
-snprintf(freq_descr, sizeof(freq_descr), "continous min %d max %d", UA_SAMP_LO(asf1d), UA_SAMP_HI(asf1d));
-else
-snprintf(freq_descr, sizeof(freq_descr), "fixed frequency (%d listed formats)", asf1d->bSamFreqType);
-
-if (numchan == 1)
-numchannel_descr = " (mono)";
-else if (numchan == 2)
-numchannel_descr = " (stereo)";
-else
-numchannel_descr = "";
-
-if (bootverbose) {
-device_printf(dev, "uaudio_query_formats: found a native %s channel%s %s %dbit %dbytes/subframe X %d channels = %d bytes per samplen",
-(dir==UE_DIR_OUT)?"playback":"record",
-numchannel_descr, freq_descr,
-prec, subframesize, numchan, subframesize*numchan);
-}
-/*
-* Now start rejecting the ones that don't map to FreeBSD
-*/
-
-if (numchan != 1 && numchan != 2)
-continue;
-
-for (iterator = accepted_conversion ; iterator->uaudio_fmt != 0 ; iterator++)
-if (iterator->uaudio_fmt == format && iterator->uaudio_prec == prec)
-break;
-
-if (iterator->uaudio_fmt == 0)
-continue;
-
-fmt = iterator->freebsd_fmt;
-
-if (numchan == 2)
-fmt |= AFMT_STEREO;
-
-foundcount++;
-
-if (fmtcount >= maxfmt)
-continue;
-
-cap->fmtlist[fmtcount++] = fmt;
-
-if (iscontinuous) {
-freq_min = UA_SAMP_LO(asf1d);
-freq_max = UA_SAMP_HI(asf1d);
-
-if (cap->minspeed == 0 || freq_min < cap->minspeed)
-cap->minspeed = freq_min;
-if (cap->maxspeed == 0)
-cap->maxspeed = cap->minspeed;
-if (freq_max > cap->maxspeed)
-cap->maxspeed = freq_max;
-} else {
-for (r = 0; r < asf1d->bSamFreqType; r++) {
-freq = UA_GETSAMP(asf1d, r);
-if (cap->minspeed == 0 || freq < cap->minspeed)
-cap->minspeed = freq;
-if (cap->maxspeed == 0)
-cap->maxspeed = cap->minspeed;
-if (freq > cap->maxspeed)
-cap->maxspeed = freq;
-}
-}
-}
-cap->fmtlist[fmtcount] = 0;
-return foundcount;
+ struct uaudio_softc *sc;
+ const struct usb_audio_streaming_type1_descriptor *asf1d;
+ const struct uaudio_conversion *iterator;
+ unsigned fmtcount, foundcount;
+ u_int32_t fmt;
+ uint8_t format, numchan, subframesize, prec, dir, iscontinuous;
+ int freq, freq_min, freq_max;
+ char *numchannel_descr;
+ char freq_descr[64];
+ int i,r;
+
+ sc = device_get_softc(dev);
+ if (sc == NULL)
+ return 0;
+
+ cap->minspeed = cap->maxspeed = 0;
+ foundcount = fmtcount = 0;
+
+ for (i = 0; i < sc->sc_nalts; i++) {
+ dir = UE_GET_DIR(sc->sc_alts[i].edesc->bEndpointAddress);
+
+ if ((dir == UE_DIR_OUT) != (reqdir == PCMDIR_PLAY))
+ continue;
+
+ asf1d = sc->sc_alts[i].asf1desc;
+ format = sc->sc_alts[i].encoding;
+
+ numchan = asf1d->bNrChannels;
+ subframesize = asf1d->bSubFrameSize;
+ prec = asf1d->bBitResolution; /* precision */
+ iscontinuous = asf1d->bSamFreqType == UA_SAMP_CONTNUOUS;
+
+ if (iscontinuous)
+ snprintf(freq_descr, sizeof(freq_descr), "continous min %d max %d", UA_SAMP_LO(asf1d), UA_SAMP_HI(asf1d));
+ else
+ snprintf(freq_descr, sizeof(freq_descr), "fixed frequency (%d listed formats)", asf1d->bSamFreqType);
+
+ if (numchan == 1)
+ numchannel_descr = " (mono)";
+ else if (numchan == 2)
+ numchannel_descr = " (stereo)";
+ else
+ numchannel_descr = "";
+
+ if (bootverbose) {
+ device_printf(dev, "uaudio_query_formats: found a native %s channel%s %s %dbit %dbytes/subframe X %d channels = %d bytes per sample\n",
+ (dir==UE_DIR_OUT)?"playback":"record",
+ numchannel_descr, freq_descr,
+ prec, subframesize, numchan, subframesize*numchan);
+ }
+ /*
+ * Now start rejecting the ones that don't map to FreeBSD
+ */
+
+ if (numchan != 1 && numchan != 2)
+ continue;
+
+ for (iterator = accepted_conversion ; iterator->uaudio_fmt != 0 ; iterator++)
+ if (iterator->uaudio_fmt == format && iterator->uaudio_prec == prec)
+ break;
+
+ if (iterator->uaudio_fmt == 0)
+ continue;
+
+ fmt = iterator->freebsd_fmt;
+
+ if (numchan == 2)
+ fmt |= AFMT_STEREO;
+
+ foundcount++;
+
+ if (fmtcount >= maxfmt)
+ continue;
+
+ cap->fmtlist[fmtcount++] = fmt;
+
+ if (iscontinuous) {
+ freq_min = UA_SAMP_LO(asf1d);
+ freq_max = UA_SAMP_HI(asf1d);
+
+ if (cap->minspeed == 0 || freq_min < cap->minspeed)
+ cap->minspeed = freq_min;
+ if (cap->maxspeed == 0)
+ cap->maxspeed = cap->minspeed;
+ if (freq_max > cap->maxspeed)
+ cap->maxspeed = freq_max;
+ } else {
+ for (r = 0; r < asf1d->bSamFreqType; r++) {
+ freq = UA_GETSAMP(asf1d, r);
+ if (cap->minspeed == 0 || freq < cap->minspeed)
+ cap->minspeed = freq;
+ if (cap->maxspeed == 0)
+ cap->maxspeed = cap->minspeed;
+ if (freq > cap->maxspeed)
+ cap->maxspeed = freq;
+ }
+ }
+ }
+ cap->fmtlist[fmtcount] = 0;
+ return foundcount;
}
void
uaudio_chan_set_param_pcm_dma_buff(device_t dev, u_char *start, u_char *end,
-struct pcm_channel *pc, int dir)
+ struct pcm_channel *pc, int dir)
{
-struct uaudio_softc *sc;
-struct chan *ch;
+ struct uaudio_softc *sc;
+ struct chan *ch;
-sc = device_get_softc(dev);
+ sc = device_get_softc(dev);
#ifndef NO_RECORDING
-if (dir == PCMDIR_PLAY)
-ch = &sc->sc_playchan;
-else
-ch = &sc->sc_recchan;
+ if (dir == PCMDIR_PLAY)
+ ch = &sc->sc_playchan;
+ else
+ ch = &sc->sc_recchan;
#else
-ch = &sc->sc_playchan;
+ ch = &sc->sc_playchan;
#endif
-ch->start = start;
-ch->end = end;
+ ch->start = start;
+ ch->end = end;
-ch->pcm_ch = pc;
+ ch->pcm_ch = pc;
-return;
+ return;
}
void
uaudio_chan_set_param_blocksize(device_t dev, u_int32_t blocksize, int dir)
{
-struct uaudio_softc *sc;
-struct chan *ch;
+ struct uaudio_softc *sc;
+ struct chan *ch;
-sc = device_get_softc(dev);
+ sc = device_get_softc(dev);
#ifndef NO_RECORDING
-if (dir == PCMDIR_PLAY)
-ch = &sc->sc_playchan;
-else
-ch = &sc->sc_recchan;
+ if (dir == PCMDIR_PLAY)
+ ch = &sc->sc_playchan;
+ else
+ ch = &sc->sc_recchan;
#else
-ch = &sc->sc_playchan;
+ ch = &sc->sc_playchan;
#endif
-ch->blksize = blocksize;
+ ch->blksize = blocksize;
-return;
+ return;
}
int
uaudio_chan_set_param_speed(device_t dev, u_int32_t speed, int reqdir)
{
-const struct uaudio_conversion *iterator;
-struct uaudio_softc *sc;
-struct chan *ch;
-int i, r, score, hiscore, bestspeed;
+ const struct uaudio_conversion *iterator;
+ struct uaudio_softc *sc;
+ struct chan *ch;
+ int i, r, score, hiscore, bestspeed;
-sc = device_get_softc(dev);
+ sc = device_get_softc(dev);
#ifndef NO_RECORDING
-if (reqdir == PCMDIR_PLAY)
-ch = &sc->sc_playchan;
-else
-ch = &sc->sc_recchan;
+ if (reqdir == PCMDIR_PLAY)
+ ch = &sc->sc_playchan;
+ else
+ ch = &sc->sc_recchan;
#else
-ch = &sc->sc_playchan;
+ ch = &sc->sc_playchan;
#endif
-/*
-* We are successful if we find an endpoint that matches our selected format and it
-* supports the requested speed.
-*/
-hiscore = 0;
-bestspeed = 1;
-for (i = 0; i < sc->sc_nalts; i++) {
-int dir = UE_GET_DIR(sc->sc_alts[i].edesc->bEndpointAddress);
-int format = sc->sc_alts[i].encoding;
-const struct usb_audio_streaming_type1_descriptor *asf1d = sc->sc_alts[i].asf1desc;
-int iscontinuous = asf1d->bSamFreqType == UA_SAMP_CONTNUOUS;
-
-if ((dir == UE_DIR_OUT) != (reqdir == PCMDIR_PLAY))
-continue;
-
-for (iterator = accepted_conversion ; iterator->uaudio_fmt != 0 ; iterator++)
-if (iterator->uaudio_fmt != format || iterator->freebsd_fmt != (ch->format&0xfffffff))
-continue;
-if (iscontinuous) {
-if (speed >= UA_SAMP_LO(asf1d) && speed <= UA_SAMP_HI(asf1d)) {
-ch->sample_rate = speed;
-return speed;
-} else if (speed < UA_SAMP_LO(asf1d)) {
-score = 0xfff * speed / UA_SAMP_LO(asf1d);
-if (score > hiscore) {
-bestspeed = UA_SAMP_LO(asf1d);
-hiscore = score;
-}
-} else if (speed < UA_SAMP_HI(asf1d)) {
-score = 0xfff * UA_SAMP_HI(asf1d) / speed;
-if (score > hiscore) {
-bestspeed = UA_SAMP_HI(asf1d);
-hiscore = score;
-}
-}
-continue;
-}
-for (r = 0; r < asf1d->bSamFreqType; r++) {
-if (speed == UA_GETSAMP(asf1d, r)) {
-ch->sample_rate = speed;
-return speed;
-}
-if (speed > UA_GETSAMP(asf1d, r))
-score = 0xfff * UA_GETSAMP(asf1d, r) / speed;
-else
-score = 0xfff * speed / UA_GETSAMP(asf1d, r);
-if (score > hiscore) {
-bestspeed = UA_GETSAMP(asf1d, r);
-hiscore = score;
-}
-}
-}
-if (bestspeed != 1) {
-ch->sample_rate = bestspeed;
-return bestspeed;
-}
+ /*
+ * We are successful if we find an endpoint that matches our selected format and it
+ * supports the requested speed.
+ */
+ hiscore = 0;
+ bestspeed = 1;
+ for (i = 0; i < sc->sc_nalts; i++) {
+ int dir = UE_GET_DIR(sc->sc_alts[i].edesc->bEndpointAddress);
+ int format = sc->sc_alts[i].encoding;
+ const struct usb_audio_streaming_type1_descriptor *asf1d = sc->sc_alts[i].asf1desc;
+ int iscontinuous = asf1d->bSamFreqType == UA_SAMP_CONTNUOUS;
+
+ if ((dir == UE_DIR_OUT) != (reqdir == PCMDIR_PLAY))
+ continue;
+
+ for (iterator = accepted_conversion ; iterator->uaudio_fmt != 0 ; iterator++)
+ if (iterator->uaudio_fmt != format || iterator->freebsd_fmt != (ch->format&0xfffffff))
+ continue;
+ if (iscontinuous) {
+ if (speed >= UA_SAMP_LO(asf1d) && speed <= UA_SAMP_HI(asf1d)) {
+ ch->sample_rate = speed;
+ return speed;
+ } else if (speed < UA_SAMP_LO(asf1d)) {
+ score = 0xfff * speed / UA_SAMP_LO(asf1d);
+ if (score > hiscore) {
+ bestspeed = UA_SAMP_LO(asf1d);
+ hiscore = score;
+ }
+ } else if (speed > UA_SAMP_HI(asf1d)) {
+ score = 0xfff * UA_SAMP_HI(asf1d) / speed;
+ if (score > hiscore) {
+ bestspeed = UA_SAMP_HI(asf1d);
+ hiscore = score;
+ }
+ }
+ continue;
+ }
+ for (r = 0; r < asf1d->bSamFreqType; r++) {
+ if (speed == UA_GETSAMP(asf1d, r)) {
+ ch->sample_rate = speed;
+ return speed;
+ }
+ if (speed > UA_GETSAMP(asf1d, r))
+ score = 0xfff * UA_GETSAMP(asf1d, r) / speed;
+ else
+ score = 0xfff * speed / UA_GETSAMP(asf1d, r);
+ if (score > hiscore) {
+ bestspeed = UA_GETSAMP(asf1d, r);
+ hiscore = score;
+ }
+ }
+ }
+ if (bestspeed != 1) {
+ ch->sample_rate = bestspeed;
+ return bestspeed;
+ }
-return 0;
+ return 0;
}
int
uaudio_chan_getptr(device_t dev, int dir)
{
-struct uaudio_softc *sc;
-struct chan *ch;
-int ptr;
+ struct uaudio_softc *sc;
+ struct chan *ch;
+ int ptr;
-sc = device_get_softc(dev);
+ sc = device_get_softc(dev);
#ifndef NO_RECORDING
-if (dir == PCMDIR_PLAY)
-ch = &sc->sc_playchan;
-else
-ch = &sc->sc_recchan;
+ if (dir == PCMDIR_PLAY)
+ ch = &sc->sc_playchan;
+ else
+ ch = &sc->sc_recchan;
#else
-ch = &sc->sc_playchan;
+ ch = &sc->sc_playchan;
#endif
-ptr = ch->cur - ch->start;
+ ptr = ch->cur - ch->start;
-return ptr;
+ return ptr;
}
void
uaudio_chan_set_param_format(device_t dev, u_int32_t format, int dir)
{
-struct uaudio_softc *sc;
-struct chan *ch;
+ struct uaudio_softc *sc;
+ struct chan *ch;
-sc = device_get_softc(dev);
+ sc = device_get_softc(dev);
#ifndef NO_RECORDING
-if (dir == PCMDIR_PLAY)
-ch = &sc->sc_playchan;
-else
-ch = &sc->sc_recchan;
+ if (dir == PCMDIR_PLAY)
+ ch = &sc->sc_playchan;
+ else
+ ch = &sc->sc_recchan;
#else
-ch = &sc->sc_playchan;
+ ch = &sc->sc_playchan;
#endif
-ch->format = format;
+ ch->format = format;
-return;
+ return;
}
int
uaudio_halt_out_dma(device_t dev)
{
-struct uaudio_softc *sc;
+ struct uaudio_softc *sc;
-sc = device_get_softc(dev);
+ sc = device_get_softc(dev);
-DPRINTF(("uaudio_halt_out_dma: entern"));
-if (sc->sc_playchan.pipe != NULL) {
-uaudio_chan_close(sc, &sc->sc_playchan);
-sc->sc_playchan.pipe = 0;
-uaudio_chan_free_buffers(sc, &sc->sc_playchan);
-}
-return (0);
+ DPRINTF(("uaudio_halt_out_dma: enter\n"));
+ if (sc->sc_playchan.pipe != NULL) {
+ uaudio_chan_close(sc, &sc->sc_playchan);
+ sc->sc_playchan.pipe = 0;
+ uaudio_chan_free_buffers(sc, &sc->sc_playchan);
+ }
+ return (0);
}
int
uaudio_halt_in_dma(device_t dev)
{
-struct uaudio_softc *sc;
+ struct uaudio_softc *sc;
-sc = device_get_softc(dev);
+ sc = device_get_softc(dev);
-if (sc->sc_dying)
-return (EIO);
+ if (sc->sc_dying)
+ return (EIO);
-DPRINTF(("uaudio_halt_in_dma: entern"));
-if (sc->sc_recchan.pipe != NULL) {
-uaudio_chan_close(sc, &sc->sc_recchan);
-sc->sc_recchan.pipe = NULL;
-uaudio_chan_free_buffers(sc, &sc->sc_recchan);
+ DPRINTF(("uaudio_halt_in_dma: enter\n"));
+ if (sc->sc_recchan.pipe != NULL) {
+ uaudio_chan_close(sc, &sc->sc_recchan);
+ sc->sc_recchan.pipe = NULL;
+ uaudio_chan_free_buffers(sc, &sc->sc_recchan);
/* sc->sc_recchan.intr = NULL; */
-}
-return (0);
+ }
+ return (0);
}
int
uaudio_trigger_input(device_t dev)
{
-struct uaudio_softc *sc;
-struct chan *ch;
-usbd_status err;
-int i, s;
+ struct uaudio_softc *sc;
+ struct chan *ch;
+ usbd_status err;
+ int i, s;
-sc = device_get_softc(dev);
-ch = &sc->sc_recchan;
+ sc = device_get_softc(dev);
+ ch = &sc->sc_recchan;
-if (sc->sc_dying)
-return (EIO);
+ if (sc->sc_dying)
+ return (EIO);
/* uaudio_chan_set_param(ch, start, end, blksize) */
-if (uaudio_init_params(sc, ch, AUMODE_RECORD))
-return (EIO);
+ if (uaudio_init_params(sc, ch, AUMODE_RECORD))
+ return (EIO);
-err = uaudio_chan_alloc_buffers(sc, ch);
-if (err)
-return (EIO);
-
-err = uaudio_chan_open(sc, ch);
-if (err) {
-uaudio_chan_free_buffers(sc, ch);
-return (EIO);
-}
+ err = uaudio_chan_alloc_buffers(sc, ch);
+ if (err)
+ return (EIO);
+
+ err = uaudio_chan_open(sc, ch);
+ if (err) {
+ uaudio_chan_free_buffers(sc, ch);
+ return (EIO);
+ }
/* ch->intr = intr;
-ch->arg = arg; */
+ ch->arg = arg; */
-s = splusb();
-for (i = 0; i < UAUDIO_NCHANBUFS-1; i++) /* XXX -1 shouldn't be needed */
-uaudio_chan_rtransfer(ch);
-splx(s);
+ s = splusb();
+ for (i = 0; i < UAUDIO_NCHANBUFS-1; i++) /* XXX -1 shouldn't be needed */
+ uaudio_chan_rtransfer(ch);
+ splx(s);
-return (0);
+ return (0);
}
int
uaudio_trigger_output(device_t dev)
{
-struct uaudio_softc *sc;
-struct chan *ch;
-usbd_status err;
-int i, s;
-
-sc = device_get_softc(dev);
-ch = &sc->sc_playchan;
-
-if (sc->sc_dying)
-return (EIO);
+ struct uaudio_softc *sc;
+ struct chan *ch;
+ usbd_status err;
+ int i, s;
+
+ sc = device_get_softc(dev);
+ ch = &sc->sc_playchan;
+
+ if (sc->sc_dying)
+ return (EIO);
+
+ if (uaudio_init_params(sc, ch, AUMODE_PLAY))
+ return (EIO);
+
+ err = uaudio_chan_alloc_buffers(sc, ch);
+ if (err)
+ return (EIO);
+
+ err = uaudio_chan_open(sc, ch);
+ if (err) {
+ uaudio_chan_free_buffers(sc, ch);
+ return (EIO);
+ }
+
+ s = splusb();
+ for (i = 0; i < UAUDIO_NCHANBUFS-1; i++) /* XXX */
+ uaudio_chan_ptransfer(ch);
+ splx(s);
-if (uaudio_init_params(sc, ch, AUMODE_PLAY))
-return (EIO);
-
-err = uaudio_chan_alloc_buffers(sc, ch);
-if (err)
-return (EIO);
-
-err = uaudio_chan_open(sc, ch);
-if (err) {
-uaudio_chan_free_buffers(sc, ch);
-return (EIO);
-}
-
-s = splusb();
-for (i = 0; i < UAUDIO_NCHANBUFS-1; i++) /* XXX */
-uaudio_chan_ptransfer(ch);
-splx(s);
-
-return (0);
+ return (0);
}
u_int32_t
uaudio_query_mix_info(device_t dev)
{
-int i;
-u_int32_t mask = 0;
-struct uaudio_softc *sc;
-struct mixerctl *mc;
-
-sc = device_get_softc(dev);
-for (i=0; i < sc->sc_nctls; i++) {
-mc = &sc->sc_ctls[i];
-if (mc->ctl != SOUND_MIXER_NRDEVICES) {
-/* Set device mask bits.
-See /usr/include/machine/soundcard.h */
-mask |= (1 << mc->ctl);
-}
-}
-return mask;
+ int i;
+ u_int32_t mask = 0;
+ struct uaudio_softc *sc;
+ struct mixerctl *mc;
+
+ sc = device_get_softc(dev);
+ for (i=0; i < sc->sc_nctls; i++) {
+ mc = &sc->sc_ctls[i];
+ if (mc->ctl != SOUND_MIXER_NRDEVICES) {
+ /* Set device mask bits.
+ See /usr/include/machine/soundcard.h */
+ mask |= (1 << mc->ctl);
+ }
+ }
+ return mask;
}
u_int32_t
uaudio_query_recsrc_info(device_t dev)
{
-int i, rec_selector_id;
-u_int32_t mask = 0;
-struct uaudio_softc *sc;
-struct mixerctl *mc;
-
-sc = device_get_softc(dev);
-rec_selector_id = -1;
-for (i=0; i < sc->sc_nctls; i++) {
-mc = &sc->sc_ctls[i];
-if (mc->ctl == SOUND_MIXER_NRDEVICES &&
-mc->type == MIX_SELECTOR && mc->class == UAC_RECORD) {
-if (rec_selector_id == -1) {
-rec_selector_id = i;
-} else {
-printf("There are many selectors. Can't recognize which selector is a record source selector.n");
-return mask;
-}
-}
-}
-if (rec_selector_id == -1)
-return mask;
-mc = &sc->sc_ctls[rec_selector_id];
-for (i = mc->minval; i <= mc->maxval; i++) {
-if (mc->slctrtype[i - 1] == SOUND_MIXER_NRDEVICES)
-continue;
-mask |= 1 << mc->slctrtype[i - 1];
-}
-return mask;
+ int i, rec_selector_id;
+ u_int32_t mask = 0;
+ struct uaudio_softc *sc;
+ struct mixerctl *mc;
+
+ sc = device_get_softc(dev);
+ rec_selector_id = -1;
+ for (i=0; i < sc->sc_nctls; i++) {
+ mc = &sc->sc_ctls[i];
+ if (mc->ctl == SOUND_MIXER_NRDEVICES &&
+ mc->type == MIX_SELECTOR && mc->class == UAC_RECORD) {
+ if (rec_selector_id == -1) {
+ rec_selector_id = i;
+ } else {
+ printf("There are many selectors. Can't recognize which selector is a record source selector.\n");
+ return mask;
+ }
+ }
+ }
+ if (rec_selector_id == -1)
+ return mask;
+ mc = &sc->sc_ctls[rec_selector_id];
+ for (i = mc->minval; i <= mc->maxval; i++) {
+ if (mc->slctrtype[i - 1] == SOUND_MIXER_NRDEVICES)
+ continue;
+ mask |= 1 << mc->slctrtype[i - 1];
+ }
+ return mask;
}
void
uaudio_mixer_set(device_t dev, unsigned type, unsigned left, unsigned right)
{
-int i;
-struct uaudio_softc *sc;
-struct mixerctl *mc;
-
-sc = device_get_softc(dev);
-for (i=0; i < sc->sc_nctls; i++) {
-mc = &sc->sc_ctls[i];
-if (mc->ctl == type) {
-if (mc->nchan == 2) {
-/* set Right */
-uaudio_ctl_set(sc, SET_CUR, mc, 1, (int)(right*255)/100);
-}
-/* set Left or Mono */
-uaudio_ctl_set(sc, SET_CUR, mc, 0, (int)(left*255)/100);
-}
-}
-return;
+ int i;
+ struct uaudio_softc *sc;
+ struct mixerctl *mc;
+
+ sc = device_get_softc(dev);
+ for (i=0; i < sc->sc_nctls; i++) {
+ mc = &sc->sc_ctls[i];
+ if (mc->ctl == type) {
+ if (mc->nchan == 2) {
+ /* set Right */
+ uaudio_ctl_set(sc, SET_CUR, mc, 1, (int)(right*255)/100);
+ }
+ /* set Left or Mono */
+ uaudio_ctl_set(sc, SET_CUR, mc, 0, (int)(left*255)/100);
+ }
+ }
+ return;
}
u_int32_t
uaudio_mixer_setrecsrc(device_t dev, u_int32_t src)
{
-int i, rec_selector_id;
-struct uaudio_softc *sc;
-struct mixerctl *mc;
-
-sc = device_get_softc(dev);
-rec_selector_id = -1;
-for (i=0; i < sc->sc_nctls; i++) {
-mc = &sc->sc_ctls[i];
-if (mc->ctl == SOUND_MIXER_NRDEVICES &&
-mc->type == MIX_SELECTOR && mc->class == UAC_RECORD) {
-if (rec_selector_id == -1) {
-rec_selector_id = i;
-} else {
-return src; /* Can't recognize which selector is record source selector */
-}
-}
-}
-if (rec_selector_id == -1)
-return src;
-mc = &sc->sc_ctls[rec_selector_id];
-for (i = mc->minval; i <= mc->maxval; i++) {
-if (src != (1 << mc->slctrtype[i - 1]))
-continue;
-uaudio_ctl_set(sc, SET_CUR, mc, 0, i);
-return (1 << mc->slctrtype[i - 1]);
-}
-uaudio_ctl_set(sc, SET_CUR, mc, 0, mc->minval);
-return (1 << mc->slctrtype[mc->minval - 1]);
+ int i, rec_selector_id;
+ struct uaudio_softc *sc;
+ struct mixerctl *mc;
+
+ sc = device_get_softc(dev);
+ rec_selector_id = -1;
+ for (i=0; i < sc->sc_nctls; i++) {
+ mc = &sc->sc_ctls[i];
+ if (mc->ctl == SOUND_MIXER_NRDEVICES &&
+ mc->type == MIX_SELECTOR && mc->class == UAC_RECORD) {
+ if (rec_selector_id == -1) {
+ rec_selector_id = i;
+ } else {
+ return src; /* Can't recognize which selector is record source selector */
+ }
+ }
+ }
+ if (rec_selector_id == -1)
+ return src;
+ mc = &sc->sc_ctls[rec_selector_id];
+ for (i = mc->minval; i <= mc->maxval; i++) {
+ if (src != (1 << mc->slctrtype[i - 1]))
+ continue;
+ uaudio_ctl_set(sc, SET_CUR, mc, 0, i);
+ return (1 << mc->slctrtype[i - 1]);
+ }
+ uaudio_ctl_set(sc, SET_CUR, mc, 0, mc->minval);
+ return (1 << mc->slctrtype[mc->minval - 1]);
}
static int
uaudio_sndstat_prepare_pcm(struct sbuf *s, device_t dev, int verbose)
{
-struct snddev_info *d;
-struct snddev_channel *sce;
-struct pcm_channel *c;
-struct pcm_feeder *f;
-int pc, rc, vc;
-device_t pa_dev = device_get_parent(dev);
-struct uaudio_softc *sc = device_get_softc(pa_dev);
-
-if (verbose < 1)
-return 0;
-
-d = device_get_softc(dev);
-if (!d)
-return ENXIO;
-
-snd_mtxlock(d->lock);
-if (SLIST_EMPTY(&d->channels)) {
-sbuf_printf(s, " (mixer only)");
-snd_mtxunlock(d->lock);
-return 0;
-}
-pc = rc = vc = 0;
-SLIST_FOREACH(sce, &d->channels, link) {
-c = sce->channel;
-if (c->direction == PCMDIR_PLAY) {
-if (c->flags & CHN_F_VIRTUAL)
-vc++;
-else
-pc++;
-} else
-rc++;
-}
-sbuf_printf(s, " (%dp/%dr/%dv channels%s%s)",
-d->playcount, d->reccount, d->vchancount,
-(d->flags & SD_F_SIMPLEX)? "" : " duplex",
+ struct snddev_info *d;
+ struct pcm_channel *c;
+ struct pcm_feeder *f;
+ device_t pa_dev = device_get_parent(dev);
+ struct uaudio_softc *sc = device_get_softc(pa_dev);
+
+ if (verbose < 1)
+ return 0;
+
+ d = device_get_softc(dev);
+ if (!d)
+ return ENXIO;
+
+ PCM_BUSYASSERT(d);
+
+ if (CHN_EMPTY(d, channels.pcm)) {
+ sbuf_printf(s, " (mixer only)");
+ return 0;
+ }
+
+ sbuf_printf(s, " (%dp:%dv/%dr:%dv channels%s%s)",
+ d->playcount, d->pvchancount,
+ d->reccount, d->rvchancount,
+ (d->flags & SD_F_SIMPLEX)? "" : " duplex",
#ifdef USING_DEVFS
-(device_get_unit(dev) == snd_unit)? " default" : ""
+ (device_get_unit(dev) == snd_unit)? " default" : ""
#else
-""
+ ""
#endif
-);
+ );
+
+ if (sc->uaudio_sndstat_flag != 0) {
+ sbuf_cat(s, sbuf_data(&(sc->uaudio_sndstat)));
+ }
+
+ if (verbose <= 1)
+ return 0;
+
+ CHN_FOREACH(c, d, channels.pcm) {
+
+ KASSERT(c->bufhard != NULL && c->bufsoft != NULL,
+ ("hosed pcm channel setup"));
+
+ sbuf_printf(s, "\n\t");
+
+ /* it would be better to indent child channels */
+ sbuf_printf(s, "%s[%s]: ", c->parentchannel? c->parentchannel->name : "", c->name);
+ sbuf_printf(s, "spd %d", c->speed);
+ if (c->speed != sndbuf_getspd(c->bufhard))
+ sbuf_printf(s, "/%d", sndbuf_getspd(c->bufhard));
+ sbuf_printf(s, ", fmt 0x%08x", c->format);
+ if (c->format != sndbuf_getfmt(c->bufhard))
+ sbuf_printf(s, "/0x%08x", sndbuf_getfmt(c->bufhard));
+ sbuf_printf(s, ", flags 0x%08x, 0x%08x", c->flags, c->feederflags);
+ if (c->pid != -1)
+ sbuf_printf(s, ", pid %d", c->pid);
+ sbuf_printf(s, "\n\t");
+
+ sbuf_printf(s, "interrupts %d, ", c->interrupts);
+ if (c->direction == PCMDIR_REC)
+ sbuf_printf(s, "overruns %d, feed %u, hfree %d, sfree %d [b:%d/%d/%d|bs:%d/%d/%d]",
+ c->xruns, c->feedcount, sndbuf_getfree(c->bufhard), sndbuf_getfree(c->bufsoft),
+ sndbuf_getsize(c->bufhard), sndbuf_getblksz(c->bufhard),
+ sndbuf_getblkcnt(c->bufhard),
+ sndbuf_getsize(c->bufsoft), sndbuf_getblksz(c->bufsoft),
+ sndbuf_getblkcnt(c->bufsoft));
+ else
+ sbuf_printf(s, "underruns %d, feed %u, ready %d [b:%d/%d/%d|bs:%d/%d/%d]",
+ c->xruns, c->feedcount, sndbuf_getready(c->bufsoft),
+ sndbuf_getsize(c->bufhard), sndbuf_getblksz(c->bufhard),
+ sndbuf_getblkcnt(c->bufhard),
+ sndbuf_getsize(c->bufsoft), sndbuf_getblksz(c->bufsoft),
+ sndbuf_getblkcnt(c->bufsoft));
+ sbuf_printf(s, "\n\t");
+
+ sbuf_printf(s, "{%s}", (c->direction == PCMDIR_REC)? "hardware" : "userland");
+ sbuf_printf(s, " -> ");
+ f = c->feeder;
+ while (f->source != NULL)
+ f = f->source;
+ while (f != NULL) {
+ sbuf_printf(s, "%s", f->class->name);
+ if (f->desc->type == FEEDER_FMT)
+ sbuf_printf(s, "(0x%08x -> 0x%08x)", f->desc->in, f->desc->out);
+ if (f->desc->type == FEEDER_RATE)
+ sbuf_printf(s, "(%d -> %d)", FEEDER_GET(f, FEEDRATE_SRC), FEEDER_GET(f, FEEDRATE_DST));
+ if (f->desc->type == FEEDER_ROOT || f->desc->type == FEEDER_MIXER ||
+ f->desc->type == FEEDER_VOLUME)
+ sbuf_printf(s, "(0x%08x)", f->desc->out);
+ sbuf_printf(s, " -> ");
+ f = f->parent;
+ }
+ sbuf_printf(s, "{%s}", (c->direction == PCMDIR_REC)? "userland" : "hardware");
+ }
-if (sc->uaudio_sndstat_flag != 0) {
-sbuf_cat(s, sbuf_data(&(sc->uaudio_sndstat)));
+ return 0;
}
-if (verbose <= 1) {
-snd_mtxunlock(d->lock);
-return 0;
-}
-
-SLIST_FOREACH(sce, &d->channels, link) {
-c = sce->channel;
-sbuf_printf(s, "nt");
-
-KASSERT(c->bufhard != NULL && c->bufsoft != NULL,
-("hosed pcm channel setup"));
-
-/* it would be better to indent child channels */
-sbuf_printf(s, "%s[%s]: ", c->parentchannel? c->parentchannel->name : "", c->name);
-sbuf_printf(s, "spd %d", c->speed);
-if (c->speed != sndbuf_getspd(c->bufhard))
-sbuf_printf(s, "/%d", sndbuf_getspd(c->bufhard));
-sbuf_printf(s, ", fmt 0x%08x", c->format);
-if (c->format != sndbuf_getfmt(c->bufhard))
-sbuf_printf(s, "/0x%08x", sndbuf_getfmt(c->bufhard));
-sbuf_printf(s, ", flags 0x%08x, 0x%08x", c->flags, c->feederflags);
-if (c->pid != -1)
-sbuf_printf(s, ", pid %d", c->pid);
-sbuf_printf(s, "nt");
-
-sbuf_printf(s, "interrupts %d, ", c->interrupts);
-if (c->direction == PCMDIR_REC)
-sbuf_printf(s, "overruns %d, hfree %d, sfree %d",
-c->xruns, sndbuf_getfree(c->bufhard), sndbuf_getfree(c->bufsoft));
-else
-sbuf_printf(s, "underruns %d, ready %d",
-c->xruns, sndbuf_getready(c->bufsoft));
-sbuf_printf(s, "nt");
-
-sbuf_printf(s, "{%s}", (c->direction == PCMDIR_REC)? "hardware" : "userland");
-sbuf_printf(s, " -> ");
-f = c->feeder;
-while (f->source != NULL)
-f = f->source;
-while (f != NULL) {
-sbuf_printf(s, "%s", f->class->name);
-if (f->desc->type == FEEDER_FMT)
-sbuf_printf(s, "(0x%08x -> 0x%08x)", f->desc->in, f->desc->out);
-if (f->desc->type == FEEDER_RATE)
-sbuf_printf(s, "(%d -> %d)", FEEDER_GET(f, FEEDRATE_SRC), FEEDER_GET(f, FEEDRATE_DST));
-if (f->desc->type == FEEDER_ROOT || f->desc->type == FEEDER_MIXER)
-sbuf_printf(s, "(0x%08x)", f->desc->out);
-sbuf_printf(s, " -> ");
-f = f->parent;
+void
+uaudio_sndstat_register(device_t dev)
+{
+ struct snddev_info *d = device_get_softc(dev);
+ sndstat_register(dev, d->status, uaudio_sndstat_prepare_pcm);
}
-sbuf_printf(s, "{%s}", (c->direction == PCMDIR_REC)? "userland" : "hardware");
+
+int
+uaudio_get_vendor(device_t dev)
+{
+ struct uaudio_softc *sc = device_get_softc(dev);
+
+ if (sc == NULL)
+ return 0;
+
+ return sc->sc_vendor;
}
-snd_mtxunlock(d->lock);
-return 0;
+int
+uaudio_get_product(device_t dev)
+{
+ struct uaudio_softc *sc = device_get_softc(dev);
+
+ if (sc == NULL)
+ return 0;
+
+ return sc->sc_product;
}
-void
-uaudio_sndstat_register(device_t dev)
+int
+uaudio_get_release(device_t dev)
{
-struct snddev_info *d = device_get_softc(dev);
-sndstat_register(dev, d->status, uaudio_sndstat_prepare_pcm);
+ struct uaudio_softc *sc = device_get_softc(dev);
+
+ if (sc == NULL)
+ return 0;
+
+ return sc->sc_release;
}
-Static int
+static int
audio_attach_mi(device_t dev)
{
-device_t child;
-struct sndcard_func *func;
+ device_t child;
+ struct sndcard_func *func;
-/* Attach the children. */
-/* PCM Audio */
-func = malloc(sizeof(struct sndcard_func), M_DEVBUF, M_NOWAIT);
-if (func == NULL)
-return (ENOMEM);
-bzero(func, sizeof(*func));
-func->func = SCF_PCM;
-child = device_add_child(dev, "pcm", -1);
-device_set_ivars(child, func);
+ /* Attach the children. */
+ /* PCM Audio */
+ func = malloc(sizeof(struct sndcard_func), M_DEVBUF, M_NOWAIT | M_ZERO);
+ if (func == NULL)
+ return (ENOMEM);
+ func->func = SCF_PCM;
+ child = device_add_child(dev, "pcm", -1);
+ device_set_ivars(child, func);
-bus_generic_attach(dev);
+ bus_generic_attach(dev);
-return 0; /* XXXXX */
+ return 0; /* XXXXX */
}
DRIVER_MODULE(uaudio, uhub, uaudio_driver, uaudio_devclass, usbd_driver_load, 0);
Index: uaudio.h
===================================================================
RCS file: /home/cvs/src/sys/dev/sound/usb/uaudio.h,v
retrieving revision 1.2
retrieving revision 1.3
diff -L sys/dev/sound/usb/uaudio.h -L sys/dev/sound/usb/uaudio.h -u -r1.2 -r1.3
--- sys/dev/sound/usb/uaudio.h
+++ sys/dev/sound/usb/uaudio.h
@@ -1,30 +1,29 @@
-/* $MidnightBSD$ */
-/* $FreeBSD: src/sys/dev/sound/usb/uaudio.h,v 1.6.2.1 2005/12/30 19:55:54 netchild Exp $ */
+/* $FreeBSD: src/sys/dev/sound/usb/uaudio.h,v 1.8 2007/03/16 17:19:03 ariff Exp $ */
/*-
-* Copyright (c) 2000-2002 Hiroyuki Aizu <aizu at navi.org>
-*
-* Redistribution and use in source and binary forms, with or without
-* modification, are permitted provided that the following conditions
-* are met:
-* 1. Redistributions of source code must retain the above copyright
-* notice, this list of conditions and the following disclaimer.
-* 2. Redistributions in binary form must reproduce the above copyright
-* notice, this list of conditions and the following disclaimer in the
-* documentation and/or other materials provided with the distribution.
-*
-* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
-* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
-* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
-* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
-* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
-* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
-* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
-* SUCH DAMAGE.
-*/
+ * Copyright (c) 2000-2002 Hiroyuki Aizu <aizu at navi.org>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
#if 0
#define NO_RECORDING /* XXX: some routines missing from uaudio.c */
@@ -33,7 +32,7 @@
/* Defined in uaudio.c, used in uaudio_pcm,c */
void uaudio_chan_set_param_pcm_dma_buff(device_t dev, u_char *start,
-u_char *end, struct pcm_channel *pc, int dir);
+ u_char *end, struct pcm_channel *pc, int dir);
int uaudio_trigger_output(device_t dev);
int uaudio_halt_out_dma(device_t dev);
#ifndef NO_RECORDING
@@ -46,9 +45,12 @@
void uaudio_chan_set_param_format(device_t dev, u_int32_t format,int dir);
int uaudio_chan_getptr(device_t dev, int);
void uaudio_mixer_set(device_t dev, unsigned type, unsigned left,
-unsigned right);
+ unsigned right);
u_int32_t uaudio_mixer_setrecsrc(device_t dev, u_int32_t src);
u_int32_t uaudio_query_mix_info(device_t dev);
u_int32_t uaudio_query_recsrc_info(device_t dev);
unsigned uaudio_query_formats(device_t dev, int dir, unsigned maxfmt, struct pcmchan_caps *fmt);
void uaudio_sndstat_register(device_t dev);
+int uaudio_get_vendor(device_t dev);
+int uaudio_get_product(device_t dev);
+int uaudio_get_release(device_t dev);
Index: uaudioreg.h
===================================================================
RCS file: /home/cvs/src/sys/dev/sound/usb/uaudioreg.h,v
retrieving revision 1.2
retrieving revision 1.3
diff -L sys/dev/sound/usb/uaudioreg.h -L sys/dev/sound/usb/uaudioreg.h -u -r1.2 -r1.3
--- sys/dev/sound/usb/uaudioreg.h
+++ sys/dev/sound/usb/uaudioreg.h
@@ -1,43 +1,42 @@
/* $NetBSD: uaudioreg.h,v 1.12 2004/11/05 19:08:29 kent Exp $ */
-/* $MidnightBSD$ */
/* $FreeBSD: src/sys/dev/sound/usb/uaudioreg.h,v 1.4 2005/01/06 01:43:22 imp Exp $ */
/*-
-* Copyright (c) 1999 The NetBSD Foundation, Inc.
-* All rights reserved.
-*
-* This code is derived from software contributed to The NetBSD Foundation
-* by Lennart Augustsson (lennart at augustsson.net) at
-* Carlstedt Research & Technology.
-*
-* Redistribution and use in source and binary forms, with or without
-* modification, are permitted provided that the following conditions
-* are met:
-* 1. Redistributions of source code must retain the above copyright
-* notice, this list of conditions and the following disclaimer.
-* 2. Redistributions in binary form must reproduce the above copyright
-* notice, this list of conditions and the following disclaimer in the
-* documentation and/or other materials provided with the distribution.
-* 3. All advertising materials mentioning features or use of this software
-* must display the following acknowledgement:
-* This product includes software developed by the NetBSD
-* Foundation, Inc. and its contributors.
-* 4. Neither the name of The NetBSD Foundation nor the names of its
-* contributors may be used to endorse or promote products derived
-* from this software without specific prior written permission.
-*
-* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
-* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
-* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
-* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
-* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-* POSSIBILITY OF SUCH DAMAGE.
-*/
+ * Copyright (c) 1999 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Lennart Augustsson (lennart at augustsson.net) at
+ * Carlstedt Research & Technology.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the NetBSD
+ * Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
#define UAUDIO_VERSION 0x100
@@ -57,73 +56,73 @@
/* The first fields are identical to usb_endpoint_descriptor_t */
typedef struct {
-uByte bLength;
-uByte bDescriptorType;
-uByte bEndpointAddress;
-uByte bmAttributes;
-uWord wMaxPacketSize;
-uByte bInterval;
-/*
-* The following two entries are only used by the Audio Class.
-* And according to the specs the Audio Class is the only one
-* allowed to extend the endpoint descriptor.
-* Who knows what goes on in the minds of the people in the USB
-* standardization? :-(
-*/
-uByte bRefresh;
-uByte bSynchAddress;
+ uByte bLength;
+ uByte bDescriptorType;
+ uByte bEndpointAddress;
+ uByte bmAttributes;
+ uWord wMaxPacketSize;
+ uByte bInterval;
+ /*
+ * The following two entries are only used by the Audio Class.
+ * And according to the specs the Audio Class is the only one
+ * allowed to extend the endpoint descriptor.
+ * Who knows what goes on in the minds of the people in the USB
+ * standardization? :-(
+ */
+ uByte bRefresh;
+ uByte bSynchAddress;
} UPACKED usb_endpoint_descriptor_audio_t;
struct usb_audio_control_descriptor {
-uByte bLength;
-uByte bDescriptorType;
-uByte bDescriptorSubtype;
-uWord bcdADC;
-uWord wTotalLength;
-uByte bInCollection;
-uByte baInterfaceNr[1];
+ uByte bLength;
+ uByte bDescriptorType;
+ uByte bDescriptorSubtype;
+ uWord bcdADC;
+ uWord wTotalLength;
+ uByte bInCollection;
+ uByte baInterfaceNr[1];
} UPACKED;
struct usb_audio_streaming_interface_descriptor {
-uByte bLength;
-uByte bDescriptorType;
-uByte bDescriptorSubtype;
-uByte bTerminalLink;
-uByte bDelay;
-uWord wFormatTag;
+ uByte bLength;
+ uByte bDescriptorType;
+ uByte bDescriptorSubtype;
+ uByte bTerminalLink;
+ uByte bDelay;
+ uWord wFormatTag;
} UPACKED;
struct usb_audio_streaming_endpoint_descriptor {
-uByte bLength;
-uByte bDescriptorType;
-uByte bDescriptorSubtype;
-uByte bmAttributes;
+ uByte bLength;
+ uByte bDescriptorType;
+ uByte bDescriptorSubtype;
+ uByte bmAttributes;
#define UA_SED_FREQ_CONTROL 0x01
#define UA_SED_PITCH_CONTROL 0x02
#define UA_SED_MAXPACKETSONLY 0x80
-uByte bLockDelayUnits;
-uWord wLockDelay;
+ uByte bLockDelayUnits;
+ uWord wLockDelay;
} UPACKED;
struct usb_audio_streaming_type1_descriptor {
-uByte bLength;
-uByte bDescriptorType;
-uByte bDescriptorSubtype;
-uByte bFormatType;
-uByte bNrChannels;
-uByte bSubFrameSize;
-uByte bBitResolution;
-uByte bSamFreqType;
+ uByte bLength;
+ uByte bDescriptorType;
+ uByte bDescriptorSubtype;
+ uByte bFormatType;
+ uByte bNrChannels;
+ uByte bSubFrameSize;
+ uByte bBitResolution;
+ uByte bSamFreqType;
#define UA_SAMP_CONTNUOUS 0
-uByte tSamFreq[3*2]; /* room for low and high */
+ uByte tSamFreq[3*2]; /* room for low and high */
#define UA_GETSAMP(p, n) ((p)->tSamFreq[(n)*3+0] | ((p)->tSamFreq[(n)*3+1] << 8) | ((p)->tSamFreq[(n)*3+2] << 16))
#define UA_SAMP_LO(p) UA_GETSAMP(p, 0)
#define UA_SAMP_HI(p) UA_GETSAMP(p, 1)
} UPACKED;
struct usb_audio_cluster {
-uByte bNrChannels;
-uWord wChannelConfig;
+ uByte bNrChannels;
+ uWord wChannelConfig;
#define UA_CHANNEL_LEFT 0x0001
#define UA_CHANNEL_RIGHT 0x0002
#define UA_CHANNEL_CENTER 0x0004
@@ -136,130 +135,130 @@
#define UA_CHANNEL_L_SIDE 0x0200
#define UA_CHANNEL_R_SIDE 0x0400
#define UA_CHANNEL_TOP 0x0800
-uByte iChannelNames;
+ uByte iChannelNames;
} UPACKED;
/* Shared by all units and terminals */
struct usb_audio_unit {
-uByte bLength;
-uByte bDescriptorType;
-uByte bDescriptorSubtype;
-uByte bUnitId;
+ uByte bLength;
+ uByte bDescriptorType;
+ uByte bDescriptorSubtype;
+ uByte bUnitId;
};
/* UDESCSUB_AC_INPUT */
struct usb_audio_input_terminal {
-uByte bLength;
-uByte bDescriptorType;
-uByte bDescriptorSubtype;
-uByte bTerminalId;
-uWord wTerminalType;
-uByte bAssocTerminal;
-uByte bNrChannels;
-uWord wChannelConfig;
-uByte iChannelNames;
-uByte iTerminal;
+ uByte bLength;
+ uByte bDescriptorType;
+ uByte bDescriptorSubtype;
+ uByte bTerminalId;
+ uWord wTerminalType;
+ uByte bAssocTerminal;
+ uByte bNrChannels;
+ uWord wChannelConfig;
+ uByte iChannelNames;
+ uByte iTerminal;
} UPACKED;
/* UDESCSUB_AC_OUTPUT */
struct usb_audio_output_terminal {
-uByte bLength;
-uByte bDescriptorType;
-uByte bDescriptorSubtype;
-uByte bTerminalId;
-uWord wTerminalType;
-uByte bAssocTerminal;
-uByte bSourceId;
-uByte iTerminal;
+ uByte bLength;
+ uByte bDescriptorType;
+ uByte bDescriptorSubtype;
+ uByte bTerminalId;
+ uWord wTerminalType;
+ uByte bAssocTerminal;
+ uByte bSourceId;
+ uByte iTerminal;
} UPACKED;
/* UDESCSUB_AC_MIXER */
struct usb_audio_mixer_unit {
-uByte bLength;
-uByte bDescriptorType;
-uByte bDescriptorSubtype;
-uByte bUnitId;
-uByte bNrInPins;
-uByte baSourceId[255]; /* [bNrInPins] */
-/* struct usb_audio_mixer_unit_1 */
+ uByte bLength;
+ uByte bDescriptorType;
+ uByte bDescriptorSubtype;
+ uByte bUnitId;
+ uByte bNrInPins;
+ uByte baSourceId[255]; /* [bNrInPins] */
+ /* struct usb_audio_mixer_unit_1 */
} UPACKED;
struct usb_audio_mixer_unit_1 {
-uByte bNrChannels;
-uWord wChannelConfig;
-uByte iChannelNames;
-uByte bmControls[255]; /* [bNrChannels] */
-/*uByte iMixer;*/
+ uByte bNrChannels;
+ uWord wChannelConfig;
+ uByte iChannelNames;
+ uByte bmControls[255]; /* [bNrChannels] */
+ /*uByte iMixer;*/
} UPACKED;
/* UDESCSUB_AC_SELECTOR */
struct usb_audio_selector_unit {
-uByte bLength;
-uByte bDescriptorType;
-uByte bDescriptorSubtype;
-uByte bUnitId;
-uByte bNrInPins;
-uByte baSourceId[255]; /* [bNrInPins] */
-/* uByte iSelector; */
+ uByte bLength;
+ uByte bDescriptorType;
+ uByte bDescriptorSubtype;
+ uByte bUnitId;
+ uByte bNrInPins;
+ uByte baSourceId[255]; /* [bNrInPins] */
+ /* uByte iSelector; */
} UPACKED;
/* UDESCSUB_AC_FEATURE */
struct usb_audio_feature_unit {
-uByte bLength;
-uByte bDescriptorType;
-uByte bDescriptorSubtype;
-uByte bUnitId;
-uByte bSourceId;
-uByte bControlSize;
-uByte bmaControls[255]; /* size for more than enough */
-/* uByte iFeature; */
+ uByte bLength;
+ uByte bDescriptorType;
+ uByte bDescriptorSubtype;
+ uByte bUnitId;
+ uByte bSourceId;
+ uByte bControlSize;
+ uByte bmaControls[255]; /* size for more than enough */
+ /* uByte iFeature; */
} UPACKED;
/* UDESCSUB_AC_PROCESSING */
struct usb_audio_processing_unit {
-uByte bLength;
-uByte bDescriptorType;
-uByte bDescriptorSubtype;
-uByte bUnitId;
-uWord wProcessType;
-uByte bNrInPins;
-uByte baSourceId[255]; /* [bNrInPins] */
-/* struct usb_audio_processing_unit_1 */
+ uByte bLength;
+ uByte bDescriptorType;
+ uByte bDescriptorSubtype;
+ uByte bUnitId;
+ uWord wProcessType;
+ uByte bNrInPins;
+ uByte baSourceId[255]; /* [bNrInPins] */
+ /* struct usb_audio_processing_unit_1 */
} UPACKED;
struct usb_audio_processing_unit_1{
-uByte bNrChannels;
-uWord wChannelConfig;
-uByte iChannelNames;
-uByte bControlSize;
-uByte bmControls[255]; /* [bControlSize] */
+ uByte bNrChannels;
+ uWord wChannelConfig;
+ uByte iChannelNames;
+ uByte bControlSize;
+ uByte bmControls[255]; /* [bControlSize] */
#define UA_PROC_ENABLE_MASK 1
} UPACKED;
struct usb_audio_processing_unit_updown {
-uByte iProcessing;
-uByte bNrModes;
-uWord waModes[255]; /* [bNrModes] */
+ uByte iProcessing;
+ uByte bNrModes;
+ uWord waModes[255]; /* [bNrModes] */
} UPACKED;
/* UDESCSUB_AC_EXTENSION */
struct usb_audio_extension_unit {
-uByte bLength;
-uByte bDescriptorType;
-uByte bDescriptorSubtype;
-uByte bUnitId;
-uWord wExtensionCode;
-uByte bNrInPins;
-uByte baSourceId[255]; /* [bNrInPins] */
-/* struct usb_audio_extension_unit_1 */
+ uByte bLength;
+ uByte bDescriptorType;
+ uByte bDescriptorSubtype;
+ uByte bUnitId;
+ uWord wExtensionCode;
+ uByte bNrInPins;
+ uByte baSourceId[255]; /* [bNrInPins] */
+ /* struct usb_audio_extension_unit_1 */
} UPACKED;
struct usb_audio_extension_unit_1 {
-uByte bNrChannels;
-uWord wChannelConfig;
-uByte iChannelNames;
-uByte bControlSize;
-uByte bmControls[255]; /* [bControlSize] */
+ uByte bNrChannels;
+ uWord wChannelConfig;
+ uByte iChannelNames;
+ uByte bControlSize;
+ uByte bmControls[255]; /* [bControlSize] */
#define UA_EXT_ENABLE_MASK 1
#define UA_EXT_ENABLE 1
-/*uByte iExtension;*/
+ /*uByte iExtension;*/
} UPACKED;
/* USB terminal types */
More information about the Midnightbsd-cvs
mailing list