diff options
Diffstat (limited to 'sys/dev/sound/pci')
39 files changed, 30641 insertions, 0 deletions
diff --git a/sys/dev/sound/pci/als4000.c b/sys/dev/sound/pci/als4000.c new file mode 100644 index 0000000..3007736 --- /dev/null +++ b/sys/dev/sound/pci/als4000.c @@ -0,0 +1,902 @@ +/* + * Copyright (c) 2001 Orion Hodson <oho@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. + */ + +#include <dev/sound/pcm/sound.h> +#include <dev/sound/isa/sb.h> +#include <dev/sound/pci/als4000.h> + +#include <pci/pcireg.h> +#include <pci/pcivar.h> + +#include "mixer_if.h" + +SND_DECLARE_FILE("$FreeBSD$"); + +/* Debugging macro's */ +#undef DEB +#ifndef DEB +#define DEB(x) /* x */ +#endif /* DEB */ + +#define ALS_DEFAULT_BUFSZ 16384 + +/* ------------------------------------------------------------------------- */ +/* Structures */ + +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 { + 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; + + 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 +}; + +static struct pcmchan_caps als_caps = { 4000, 48000, als_format, 0 }; + +/* ------------------------------------------------------------------------- */ +/* Register Utilities */ + +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); +} + +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); +} + +static u_int8_t +als_intr_rd(struct sc_info *sc) +{ + 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); +} + +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); +} + +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); +} + +static void +als_esp_wr(struct sc_info *sc, u_int8_t data) +{ + 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); + + if (tries == 0) + device_printf(sc->dev, "als_esp_wr timeout"); + + 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; + + 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; +} + +/* ------------------------------------------------------------------------- */ +/* Common pcm channel implementation */ + +static void * +alschan_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; + + 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; + if (sndbuf_alloc(ch->buffer, sc->parent_dmat, sc->bufsz) != 0) { + return NULL; + } + return ch; +} + +static int +alschan_setformat(kobj_t obj, void *data, u_int32_t format) +{ + struct sc_chinfo *ch = data; + + 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; + + 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; + } + + 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; + + 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; + int32_t pos, sz; + + pos = als_gcr_rd(ch->parent, ch->gcr_fifo_status) & 0xffff; + 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; +} + +static void +als_set_speed(struct sc_chinfo *ch) +{ + 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)); + } +} + +/* ------------------------------------------------------------------------- */ +/* Playback channel implementation */ + +#define ALS_8BIT_CMD(x, y) { (x), (y), DSP_DMA8, DSP_CMD_DMAPAUSE_8 } +#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 */ +} 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), +}; + +static const struct playback_command* +als_get_playback_command(u_int32_t format) +{ + 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%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); + + 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; +} + +static int +alspchan_trigger(kobj_t obj, void *data, int go) +{ + struct sc_chinfo *ch = data; + + switch(go) { + case PCMTRIG_START: + als_playback_start(ch); + break; + case PCMTRIG_ABORT: + als_playback_stop(ch); + break; + } + 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 } +}; +CHANNEL_DECLARE(alspchan); + +/* ------------------------------------------------------------------------- */ +/* Capture channel implementation */ + +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%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; + + 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_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); + + 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; +} + +static int +als_capture_stop(struct sc_chinfo *ch) +{ + 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; +} + +static int +alsrchan_trigger(kobj_t obj, void *data, int go) +{ + struct sc_chinfo *ch = data; + + switch(go) { + case PCMTRIG_START: + als_capture_start(ch); + break; + case PCMTRIG_ABORT: + als_capture_stop(ch); + break; + } + 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 } +}; +CHANNEL_DECLARE(alsrchan); + +/* ------------------------------------------------------------------------- */ +/* Mixer related */ + +/* + * 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 */ +} 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 } +}; + +static int +alsmix_init(struct snd_mixer *m) +{ + 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; +} + +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; + + /* 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; +} + +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; + + for (i = l = r = 0; i < SOUND_MIXER_NRDEVICES; i++) { + if (src & (1 << i)) { + 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 } +}; +MIXER_DECLARE(als_mixer); + +/* ------------------------------------------------------------------------- */ +/* Interrupt Handler */ + +static void +als_intr(void *p) +{ + struct sc_info *sc = (struct sc_info *)p; + u_int8_t intr, sb_status; + + intr = als_intr_rd(sc); + + if (intr & 0x80) + chn_intr(sc->pch.channel); + + if (intr & 0x40) + chn_intr(sc->rch.channel); + + /* 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); + return; +} + +/* ------------------------------------------------------------------------- */ +/* H/W initialization */ + +static int +als_init(struct sc_info *sc) +{ + 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%08x\n", v)); + return 0; +} + +static void +als_uninit(struct sc_info *sc) +{ + /* Disable interrupts */ + als_gcr_wr(sc, ALS_GCR_MISC, 0); +} + +/* ------------------------------------------------------------------------- */ +/* Probe and attach card */ + +static int +als_pci_probe(device_t dev) +{ + if (pci_get_devid(dev) == ALS_PCI_ID0) { + device_set_desc(dev, "Avance Logic ALS4000"); + return 0; + } + 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; + } +} + +static int +als_resource_grab(device_t dev, struct sc_info *sc) +{ + sc->regid = PCIR_MAPS; + 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(dev, SYS_RES_IRQ, &sc->irqid, 0, ~0, 1, + RF_ACTIVE | RF_SHAREABLE); + if (sc->irq == 0) { + device_printf(dev, "unable to allocate interrupt\n"); + goto bad; + } + + if (bus_setup_intr(dev, sc->irq, INTR_TYPE_AV, 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*/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, &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 softc\n"); + return ENXIO; + } + + 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 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 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 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", + rman_get_start(sc->reg), rman_get_start(sc->irq)); + 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; + + 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); + + sc->pch.dma_was_active = als_playback_stop(&sc->pch); + sc->rch.dma_was_active = als_capture_stop(&sc->rch); + als_uninit(sc); + return 0; +} + +static int +als_pci_resume(device_t dev) +{ + struct sc_info *sc = pcm_getdevinfo(dev); + + if (als_init(sc) != 0) { + device_printf(dev, "unable to reinitialize the card\n"); + return ENXIO; + } + + if (mixer_reinit(dev) != 0) { + device_printf(dev, "unable to reinitialize the mixer\n"); + return ENXIO; + } + + if (sc->pch.dma_was_active) { + als_playback_start(&sc->pch); + } + + if (sc->rch.dma_was_active) { + als_capture_start(&sc->rch); + } + 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 } +}; + +static driver_t als_driver = { + "pcm", + als_methods, + PCM_SOFTC_SIZE, +}; + +DRIVER_MODULE(snd_als4000, pci, als_driver, pcm_devclass, 0, 0); +MODULE_DEPEND(snd_als4000, snd_pcm, PCM_MINVER, PCM_PREFVER, PCM_MAXVER); +MODULE_VERSION(snd_als4000, 1); diff --git a/sys/dev/sound/pci/als4000.h b/sys/dev/sound/pci/als4000.h new file mode 100644 index 0000000..a6a67df --- /dev/null +++ b/sys/dev/sound/pci/als4000.h @@ -0,0 +1,95 @@ +/* + * Copyright (c) 2001 Orion Hodson <O.Hodson@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$ + */ + +#define ALS_PCI_ID0 0x40004005 +#define ALS_PCI_POWERREG 0xe0 + +#define ALS_CONFIG_SPACE_BYTES 128 + +#define ALS_GCR_DATA 0x08 +#define ALS_GCR_INDEX 0x0c +# define ALS_GCR_MISC 0x8c +# define ALS_GCR_TEST 0x90 +# define ALS_GCR_DMA0_START 0x91 +# define ALS_GCR_DMA0_MODE 0x92 +# define ALS_GCR_DMA1_START 0x93 +# define ALS_GCR_DMA1_MODE 0x94 +# define ALS_GCR_DMA3_START 0x95 +# define ALS_GCR_DMA3_MODE 0x96 +# define ALS_GCR_DMA_EMULATION 0x99 +# define ALS_GCR_FIFO0_CURRENT 0xa0 +# define ALS_GCR_FIFO0_STATUS 0xa1 +# define ALS_GCR_FIFO1_START 0xa2 +# define ALS_GCR_FIFO1_COUNT 0xa3 +# define ALS_GCR_FIFO1_CURRENT 0xa4 +# define ALS_GCR_FIFO1_STATUS 0xa5 +# define ALS_GCR_POWER 0xa6 +# define ALS_GCR_PIC_ACCESS 0xa7 + +#define ALS_SB_MPU_IRQ 0x0e + +#define ALS_MIXER_DATA 0x15 +#define ALS_MIXER_INDEX 0x14 +# define ALS_SB16_RESET 0x00 +# define ALS_SB16_DMA_SETUP 0x81 +# define ALS_CONTROL 0xc0 +# define ALS_SB16_CONFIG ALS_CONTROL + 0x00 +# define ALS_MISC_CONTROL ALS_CONTROL + 0x02 +# define ALS_FIFO1_LENGTH_LO ALS_CONTROL + 0x1c +# define ALS_FIFO1_LENGTH_HI ALS_CONTROL + 0x1d +# define ALS_FIFO1_CONTROL ALS_CONTROL + 0x1e +# define ALS_FIFO1_STOP 0x00 +# define ALS_FIFO1_RUN 0x80 +# define ALS_FIFO1_PAUSE 0x40 +# define ALS_FIFO1_STEREO 0x20 +# define ALS_FIFO1_SIGNED 0x10 +# define ALS_FIFO1_8BIT 0x04 + +#define ALS_ESP_RST 0x16 +#define ALS_CR1E_ACK_PORT 0x16 + +#define ALS_ESP_RD_DATA 0x1a +#define ALS_ESP_WR_DATA 0x1c +#define ALS_ESP_WR_STATUS 0x1c +#define ALS_ESP_RD_STATUS8 0x1e +#define ALS_ESP_RD_STATUS16 0x1f +# define ALS_ESP_SAMPLE_RATE 0x41 + +#define ALS_MIDI_DATA 0x30 +#define ALS_MIDI_STATUS 0x31 + +/* Interrupt masks */ +#define ALS_IRQ_STATUS8 0x01 +#define ALS_IRQ_STATUS16 0x02 +#define ALS_IRQ_MPUIN 0x04 +#define ALS_IRQ_CR1E 0x20 + +/* Sample Rate Locks */ +#define ALS_RATE_LOCK_PLAYBACK 0x01 +#define ALS_RATE_LOCK_CAPTURE 0x02 +#define ALS_RATE_LOCK 0x03 diff --git a/sys/dev/sound/pci/au88x0.c b/sys/dev/sound/pci/au88x0.c new file mode 100644 index 0000000..3bf227b --- /dev/null +++ b/sys/dev/sound/pci/au88x0.c @@ -0,0 +1,637 @@ +/*- + * 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$ + */ + +#include <dev/sound/pcm/sound.h> +#include <dev/sound/pcm/ac97.h> +#include <dev/sound/pci/au88x0.h> + +#include <machine/bus.h> + +#include <pci/pcireg.h> +#include <pci/pcivar.h> + + +/***************************************************************************\ + * * + * FORMATS AND CAPABILITIES * + * * +\***************************************************************************/ + +static u_int32_t au88x0_formats[] = { + 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 */ +}; + + +/***************************************************************************\ + * * + * CODEC INTERFACE * + * * +\***************************************************************************/ + +/* + * 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)) +#else +static uint32_t +au88x0_read(struct au88x0_info *aui, int reg, int size) +{ + 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); +} + +/* + * 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); + } +} +#endif + +/* + * Reset and initialize the codec + */ +static void +au88x0_codec_init(struct au88x0_info *aui) +{ + 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); +} + +/* + * 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; + + 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 + */ +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); +} + +/* + * 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; + + 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 + */ +static kobj_method_t au88x0_ac97_methods[] = { + 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] + + +/***************************************************************************\ + * * + * CHANNEL INTERFACE * + * * +\***************************************************************************/ + +/* + * 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 au88x0_info *aui = arg; + struct au88x0_chan_info *auci = au88x0_channel(aui, dir); + + if (sndbuf_alloc(buf, aui->aui_dmat, aui->aui_bufsize) == -1) + 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 + */ +static int +au88x0_chan_setformat(kobj_t obj, void *arg, u_int32_t format) +{ + + /* XXX */ + return (ENXIO); +} + +/* + * 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); +} + +/* + * 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); +} + +/* + * Initiate a data transfer + */ +static int +au88x0_chan_trigger(kobj_t obj, void *arg, int trigger) +{ + struct au88x0_chan_info *auci = arg; + + (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); +} + +/* + * Return the capabilities of a PCM channel + */ +static struct pcmchan_caps * +au88x0_chan_getcaps(kobj_t obj, void *arg) +{ + + return (&au88x0_capabilities); +} + +/* + * 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 } +}; +CHANNEL_DECLARE(au88x0_chan); + + +/***************************************************************************\ + * * + * INTERRUPT HANDLER * + * * +\***************************************************************************/ + +static void +au88x0_intr(void *arg) +{ + struct au88x0_info *aui = arg; + int pending, source; + + pending = au88x0_read(aui, AU88X0_IRQ_PENDING, 4); + if ((pending & AU88X0_IRQ_PENDING_BIT) == 0) + return; + source = au88x0_read(aui, AU88X0_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, AU88X0_IRQ_SOURCE, source, 4); + au88x0_read(aui, AU88X0_IRQ_SOURCE, 4); +} + + +/***************************************************************************\ + * * + * INITIALIZATION * + * * +\***************************************************************************/ + +/* + * 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) +{ + int i; + + /* reset, then clear the ADB FIFOs */ + for (i = 0; i < AU88X0_ADB_FIFOS; ++i) + au88x0_write(aui, AU88X0_ADB_FIFO_CTL + i * 4, 0x42000, 4); + for (i = 0; i < AU88X0_ADB_FIFOS * AU88X0_ADB_FIFO_SIZE; ++i) + au88x0_write(aui, AU88X0_ADB_FIFO_BASE + i * 4, 0, 4); + + /* reset, then clear the WT FIFOs */ + for (i = 0; i < AU88X0_WT_FIFOS; ++i) + au88x0_write(aui, AU88X0_WT_FIFO_CTL + i * 4, 0x42000, 4); + for (i = 0; i < AU88X0_WT_FIFOS * AU88X0_WT_FIFO_SIZE; ++i) + au88x0_write(aui, AU88X0_WT_FIFO_BASE + i * 4, 0, 4); +} + +/* + * Hardware initialization + */ +static void +au88x0_init(struct au88x0_info *aui) +{ + + /* reset the chip */ + au88x0_write(aui, AU88X0_CONTROL, 0xffffffff, 4); + DELAY(10000); + + /* clear all interrupts */ + au88x0_write(aui, AU88X0_IRQ_SOURCE, 0xffffffff, 4); + au88x0_read(aui, AU88X0_IRQ_SOURCE, 4); + au88x0_read(aui, AU88X0_IRQ_STATUS, 4); + + /* initialize the codec */ + au88x0_codec_init(aui); + + /* initialize the fifos */ + au88x0_fifo_init(aui); + + /* initialize the DMA engine */ + /* XXX chicken-waving! */ + au88x0_write(aui, AU88X0_DMA_CONTROL, 0x1380000, 4); +} + +/* + * Construct and set status string + */ +static void +au88x0_set_status(device_t dev) +{ + char status[SND_STATUSLEN]; + struct au88x0_info *aui; + + aui = pcm_getdevinfo(dev); + snprintf(status, sizeof status, "at %s 0x%lx irq %ld", + (aui->aui_regtype == SYS_RES_IOPORT)? "io" : "memory", + rman_get_start(aui->aui_reg), rman_get_start(aui->aui_irq)); + pcm_setstatus(dev, status); +} + + +/***************************************************************************\ + * * + * PCI INTERFACE * + * * +\***************************************************************************/ + +/* + * Probe + */ +static int +au88x0_pci_probe(device_t dev) +{ + + switch (pci_get_devid(dev)) { + case AUREAL_VORTEX_2: + device_set_desc(dev, "Aureal Vortex 2"); + return (0); + case AUREAL_VORTEX_ADVANTAGE: + device_set_desc(dev, "Aureal Vortex Advantage"); + return (0); + default: + return (ENXIO); + } + return (0); +} + +/* + * Attach + */ +static int +au88x0_pci_attach(device_t dev) +{ + 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 softc\n"); + return (ENXIO); + } + aui->aui_dev = dev; + + /* Model-specific parameters */ + aui->aui_model = pci_get_devid(dev); + switch (aui->aui_model) { + case AUREAL_VORTEX_1: + break; + case AUREAL_VORTEX_2: + case AUREAL_VORTEX_ADVANTAGE: + break; + default: + 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_MAPS; + aui->aui_regtype = SYS_RES_MEMORY; + aui->aui_reg = bus_alloc_resource(dev, aui->aui_regtype, + &aui->aui_regid, 0, ~0, 1, RF_ACTIVE); + } + if (aui->aui_reg == NULL && (config & PCIM_CMD_PORTEN)) { + /* fall back on port I/O */ + aui->aui_regid = PCIR_MAPS; + aui->aui_regtype = SYS_RES_IOPORT; + aui->aui_reg = bus_alloc_resource(dev, aui->aui_regtype, + &aui->aui_regid, 0, ~0, 1, 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(dev, aui->aui_irqtype, + &aui->aui_irqid, 0, ~0, 1, 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(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, &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; +#if 0 + pcm_addchan(dev, PCMDIR_PLAY, &au88x0_chan_class, aui); + pcm_addchan(dev, PCMDIR_REC, &au88x0_chan_class, aui); +#endif + au88x0_set_status(dev); + + 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); +} + +/* + * Detach + */ +static int +au88x0_pci_detach(device_t dev) +{ + struct au88x0_info *aui; + int 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); + + return (0); +} + +/* + * 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 } +}; + +static driver_t au88x0_driver = { + "pcm", + au88x0_methods, + PCM_SOFTC_SIZE, +}; + +DRIVER_MODULE(snd_au88x0, pci, au88x0_driver, pcm_devclass, 0, 0); +MODULE_DEPEND(snd_au88x0, snd_pcm, PCM_MINVER, PCM_PREFVER, PCM_MAXVER); +MODULE_VERSION(snd_au88x0, 1); diff --git a/sys/dev/sound/pci/au88x0.h b/sys/dev/sound/pci/au88x0.h new file mode 100644 index 0000000..4b442ee --- /dev/null +++ b/sys/dev/sound/pci/au88x0.h @@ -0,0 +1,174 @@ +/*- + * 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$ + */ + +#ifndef _AU88X0_H_INCLUDED +#define _AU88X0_H_INCLUDED + +/* + * Channel information + */ +struct au88x0_chan_info { + struct au88x0_info *auci_aui; + struct pcm_channel *auci_pcmchan; + struct snd_dbuf *auci_buf; + int auci_dir; +}; + +/* + * Device information + */ +struct au88x0_info { + /* the device we're associated with */ + device_t aui_dev; + uint32_t aui_model; + + /* parameters */ + bus_size_t aui_bufsize; + + /* 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; + + /* codec */ + struct ac97_info *aui_ac97i; + + /* channels */ + struct au88x0_chan_info aui_chan[2]; +}; + +/* + * PCI IDs of supported cards + */ +#define AUREAL_VORTEX_1 0x000112eb /* 8820 (not supported) */ +#define AUREAL_VORTEX_2 0x000212eb /* 8830 */ +#define AUREAL_VORTEX_ADVANTAGE 0x000312eb /* 8810 */ + +/* + * Common parameters + */ +#define AU88X0_SETTLE_DELAY 1000 +#define AU88X0_RETRY_COUNT 10 +#define AU88X0_BUFSIZE_MIN 0x1000 +#define AU88X0_BUFSIZE_DFLT 0x4000 +#define AU88X0_BUFSIZE_MAX 0x4000 + +/* + * General control registers + */ +#define AU88X0_CONTROL 0x2a00c +#define AU88X0_CTL_MIDI_ENABLE 0x0001 +#define AU88X0_CTL_GAME_ENABLE 0x0008 +#define AU88X0_CTL_IRQ_ENABLE 0x4000 + +#define AU88X0_IRQ_SOURCE 0x2a000 +#define AU88X0_IRQ_MASK 0x2a004 +#define AU88X0_IRQ_FATAL_ERR 0x0001 +#define AU88X0_IRQ_PARITY_ERR 0x0002 +#define AU88X0_IRQ_REG_ERR 0x0004 +#define AU88X0_IRQ_FIFO_ERR 0x0008 +#define AU88X0_IRQ_DMA_ERR 0x0010 +#define AU88X0_IRQ_PCMOUT 0x0020 +#define AU88X0_IRQ_TIMER 0x1000 +#define AU88X0_IRQ_MIDI 0x2000 +#define AU88X0_IRQ_MODEM 0x4000 +#define AU88X0_IRQ_PENDING 0x2a008 +#define AU88X0_IRQ_PENDING_BIT 0x0001 +#define AU88X0_IRQ_STATUS 0x2919c +#define AU88X0_DMA_CONTROL 0x27ae8 + +/* + * 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 +#define AU88X0_CODEC_IO 0x29188 +#define AU88X0_CDIO_DATA_SHIFT 0 +#define AU88X0_CDIO_DATA_MASK 0x0000ffff +#define AU88X0_CDIO_ADDR_SHIFT 16 +#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_CODEC_ENABLE 0x29190 + +/* + * FIFO and DMA contorl registers + * + * There are two sets of these, one for PCM audio (ADB) and one for + * wavetables (WT). + */ +#define AU88X0_ADB_FIFOS 32 +#define AU88X0_ADB_FIFO_CTL 0x16100 +#define AU88X0_ADB_FIFO_BASE 0x14000 +#define AU88X0_ADB_FIFO_SIZE 0x40 +#define AU8810_ADB_DMA_CTL 0x27180 +#define AU8820_ADB_DMA_CTL 0x10580 +#define AU8830_ADB_DMA_CTL 0x27a00 + +#define AU88X0_WT_FIFOS 32 +#define AU88X0_WT_FIFO_CTL 0x16000 +#define AU88X0_WT_FIFO_BASE 0x10000 +#define AU88X0_WT_FIFO_SIZE 0x40 +#define AU8810_WT_DMA_CTL 0x27fd8 +#define AU8820_WT_DMA_CTL 0x10500 +#define AU8830_WT_DMA_CTL 0x27900 + +#endif diff --git a/sys/dev/sound/pci/aureal.c b/sys/dev/sound/pci/aureal.c new file mode 100644 index 0000000..d301fd8 --- /dev/null +++ b/sys/dev/sound/pci/aureal.c @@ -0,0 +1,685 @@ +/* + * Copyright (c) 1999 Cameron Grant <gandalf@vilnya.demon.co.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. + */ + +#include <dev/sound/pcm/sound.h> +#include <dev/sound/pcm/ac97.h> +#include <dev/sound/pci/aureal.h> + +#include <pci/pcireg.h> +#include <pci/pcivar.h> + +SND_DECLARE_FILE("$FreeBSD$"); + +/* 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 +}; +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 +}; +static struct pcmchan_caps au_reccaps = {4000, 48000, au_recfmt, 0}; + +/* -------------------------------------------------------------------- */ + +struct au_info; + +struct au_chinfo { + struct au_info *parent; + struct pcm_channel *channel; + struct snd_dbuf *buffer; + int dir; +}; + +struct au_info { + int unit; + + bus_space_tag_t st[3]; + bus_space_handle_t sh[3]; + + 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; +}; + +static int au_init(device_t dev, struct au_info *au); +static void au_intr(void *); + +/* -------------------------------------------------------------------- */ + +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; + } +} + +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; + } +} + +/* -------------------------------------------------------------------- */ + +static int +au_rdcd(kobj_t obj, void *arg, int regno) +{ + 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; +} + +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 %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); +*/ tries++; + } while (0); /* (i != data && tries < 3); */ + /* + if (tries == 3) printf("giving up writing 0x%4x to codec reg %2x\n", data, regno); + */ + + return 0; +} + +static kobj_method_t au_ac97_methods[] = { + KOBJMETHOD(ac97_read, au_rdcd), + KOBJMETHOD(ac97_write, au_wrcd), + { 0, 0 } +}; +AC97_DECLARE(au_ac97); + +/* -------------------------------------------------------------------- */ + +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); +} + +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); + + 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]; + + 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); +} + +static void +au_clrfifo(struct au_info *au, u_int32_t c) +{ + u_int32_t i; + + 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; + + 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); + + 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_addroute(au, 0x11, 0, 0x58); + au_addroute(au, 0x11, stereo? 0 : 1, 0x59); +} + +/* -------------------------------------------------------------------- */ +/* channel interface */ +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; + + ch->parent = au; + ch->channel = c; + ch->buffer = b; + ch->dir = dir; + if (sndbuf_alloc(ch->buffer, au->parent_dmat, AU_BUFFSIZE) == -1) return NULL; + return ch; +} + +static int +auchan_setformat(kobj_t obj, void *data, u_int32_t format) +{ + struct au_chinfo *ch = data; + + 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; +} + +static int +auchan_setblocksize(kobj_t obj, void *data, u_int32_t 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; + + if (go == PCMTRIG_EMLDMAWR || go == PCMTRIG_EMLDMARD) + 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; +} + +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; + } +} + +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; +} + +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 } +}; +CHANNEL_DECLARE(auchan); + +/* -------------------------------------------------------------------- */ +/* The interrupt handler */ +static void +au_intr (void *p) +{ + 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 %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); + } + } +*/ + au_wr(au, 0, AU_REG_IRQSRC, intsrc & 0x7ff, 4); + au_rd(au, 0, AU_REG_IRQSRC, 4); +} + + +/* -------------------------------------------------------------------- */ + +/* Probe and attach the card */ + +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); + + /* 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); +} + +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 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 0; + } + + 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 softc\n"); + 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++) { +#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); + } +#endif + regid[j] = PCIR_MAPS + i*4; + type[j] = SYS_RES_MEMORY; + reg[j] = bus_alloc_resource(dev, type[j], ®id[j], + 0, ~0, 1, RF_ACTIVE); + if (!reg[j]) { + type[j] = SYS_RES_IOPORT; + reg[j] = bus_alloc_resource(dev, type[j], ®id[j], + 0, ~0, 1, 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("%s\n", mapped? "ok" : "failed"); +#endif + 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 resource\n", unit); + free(au, M_DEVBUF); + return; + } +#endif + + au_wr(au, 0, AU_REG_IRQEN, 0, 4); + + irqid = 0; + irq = bus_alloc_resource(dev, SYS_RES_IRQ, &irqid, + 0, ~0, 1, 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*/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, &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", + (type[0] == SYS_RES_IOPORT)? "io" : "memory", + rman_get_start(reg[0]), rman_get_start(irq)); + + 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), + + { 0, 0 } +}; + +static driver_t au_driver = { + "pcm", + au_methods, + PCM_SOFTC_SIZE, +}; + +DRIVER_MODULE(snd_aureal, pci, au_driver, pcm_devclass, 0, 0); +MODULE_DEPEND(snd_aureal, snd_pcm, PCM_MINVER, PCM_PREFVER, PCM_MAXVER); +MODULE_VERSION(snd_aureal, 1); diff --git a/sys/dev/sound/pci/aureal.h b/sys/dev/sound/pci/aureal.h new file mode 100644 index 0000000..a89e4c9 --- /dev/null +++ b/sys/dev/sound/pci/aureal.h @@ -0,0 +1,99 @@ +/* + * Copyright (c) 1999 Cameron Grant <gandalf@vilnya.demon.co.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$ + */ + +#ifndef _AU8820_REG_H +#define _AU8820_REG_H + +#define AU_BUFFSIZE 0x4000 + +#define AU_REG_FIFOBASE 0x0e000 + +#define AU_REG_UNK2 0x105c0 +#define AU_REG_UNK3 0x10600 +#define AU_REG_UNK4 0x10604 +#define AU_REG_UNK5 0x10608 + +#define AU_REG_RTBASE 0x10800 + +#define AU_REG_ADB 0x10a00 + +#define AU_REG_CODECCHN 0x11880 + +#define AU_REG_CODECST 0x11984 +#define AU_CDC_RUN 0x00000040 +#define AU_CDC_WROK 0x00000100 +#define AU_CDC_RESET 0x00008000 + +#define AU_REG_CODECIO 0x11988 +#define AU_CDC_DATAMASK 0x0000ffff +#define AU_CDC_REGMASK 0x007f0000 +#define AU_CDC_REGSET 0x00800000 +#define AU_CDC_READY 0x04000000 + +#define AU_REG_CODECEN 0x11990 +#define AU_CDC_CHAN1EN 0x00000100 +#define AU_CDC_CHAN2EN 0x00000200 + +#define AU_REG_UNK1 0x1199c + +#define AU_REG_IRQSRC 0x12800 +#define AU_IRQ_FATAL 0x0001 +#define AU_IRQ_PARITY 0x0002 +#define AU_IRQ_PCMOUT 0x0020 +#define AU_IRQ_UNKNOWN 0x1000 +#define AU_IRQ_MIDI 0x2000 +#define AU_REG_IRQEN 0x12804 + +#define AU_REG_IRQGLOB 0x1280c +#define AU_IRQ_ENABLE 0x4000 + +#define AC97_MUTE 0x8000 +#define AC97_REG_RESET 0x00 +#define AC97_MIX_MASTER 0x02 +#define AC97_MIX_PHONES 0x04 +#define AC97_MIX_MONO 0x06 +#define AC97_MIX_TONE 0x08 +#define AC97_MIX_BEEP 0x0a +#define AC97_MIX_PHONE 0x0c +#define AC97_MIX_MIC 0x0e +#define AC97_MIX_LINE 0x10 +#define AC97_MIX_CD 0x12 +#define AC97_MIX_VIDEO 0x14 +#define AC97_MIX_AUX 0x16 +#define AC97_MIX_PCM 0x18 +#define AC97_REG_RECSEL 0x1a +#define AC97_MIX_RGAIN 0x1c +#define AC97_MIX_MGAIN 0x1e +#define AC97_REG_GEN 0x20 +#define AC97_REG_3D 0x22 +#define AC97_REG_POWER 0x26 +#define AC97_REG_ID1 0x7c +#define AC97_REG_ID2 0x7e + + +#endif diff --git a/sys/dev/sound/pci/cmi.c b/sys/dev/sound/pci/cmi.c new file mode 100644 index 0000000..14c6c8e --- /dev/null +++ b/sys/dev/sound/pci/cmi.c @@ -0,0 +1,1010 @@ +/* + * Copyright (c) 2000 Orion Hodson <O.Hodson@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@imou.to>. Chen-Li Tien + * <cltien@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@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> +#include <dev/sound/isa/sb.h> + +#include <pci/pcireg.h> +#include <pci/pcivar.h> + +#include <sys/sysctl.h> + +#include "mixer_if.h" + +SND_DECLARE_FILE("$FreeBSD$"); + +/* Supported chip ID's */ +#define CMI8338A_PCI_ID 0x010013f6 +#define CMI8338B_PCI_ID 0x010113f6 +#define CMI8738_PCI_ID 0x011113f6 +#define CMI8738B_PCI_ID 0x011213f6 + +/* Buffer size max is 64k for permitted DMA boundaries */ +#define CMI_DEFAULT_BUFSZ 16384 + +/* Interrupts per length of buffer */ +#define CMI_INTR_PER_BUFFER 2 + +/* Clarify meaning of named defines in cmireg.h */ +#define CMPCI_REG_DMA0_MAX_SAMPLES CMPCI_REG_DMA0_BYTES +#define CMPCI_REG_DMA0_INTR_SAMPLES CMPCI_REG_DMA0_SAMPLES +#define CMPCI_REG_DMA1_MAX_SAMPLES CMPCI_REG_DMA1_BYTES +#define CMPCI_REG_DMA1_INTR_SAMPLES CMPCI_REG_DMA1_SAMPLES + +/* Our indication of custom mixer control */ +#define CMPCI_NON_SB16_CONTROL 0xff + +/* Debugging macro's */ +#undef DEB +#ifndef DEB +#define DEB(x) /* x */ +#endif /* DEB */ + +#ifndef DEBMIX +#define DEBMIX(x) /* x */ +#endif /* DEBMIX */ + +/* ------------------------------------------------------------------------- */ +/* Structures */ + +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 { + 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; +}; + +/* Channel caps */ + +static u_int32_t cmi_fmt[] = { + 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}; + +/* ------------------------------------------------------------------------- */ +/* Register Utilities */ + +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 %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; + } +} + +static void +cmi_partial_wr4(struct sc_info *sc, + int reg, int shift, u_int32_t mask, u_int32_t val) +{ + u_int32_t r; + + 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; + + 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; + + 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}; +#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 */ + +static u_int32_t +cmpci_rate_to_regvalue(int rate) +{ + int i, r; + + 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 -> %d\n", rate, cmi_rates[i])); + + r = ((i >> 1) | (i << 2)) & 0x07; + return r; +} + +static int +cmpci_regvalue_to_rate(u_int32_t r) +{ + int 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. */ + +static void +cmi_dma_prog(struct sc_info *sc, struct sc_chinfo *ch, u_int32_t base) +{ + u_int32_t s, i, sz; + + ch->phys_buf = sndbuf_getbufaddr(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); + + 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_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; +} + +static u_int32_t +cmi_ch0_stop(struct sc_info *sc, struct sc_chinfo *ch) +{ + 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; +} + +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 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; + + 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; + + 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); +} + +/* ------------------------------------------------------------------------- */ +/* Channel Interface implementation */ + +static void * +cmichan_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; + + 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 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; +} + +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; + + 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))); + + 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; + + /* 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; +} + +static int +cmichan_trigger(kobj_t obj, void *data, int go) +{ + 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; +} + +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); + + sz = sndbuf_getsize(ch->buffer); + bufptr = (physptr - ch->phys_buf + sz - ch->bps) % sz; + + return bufptr; +} + +static void +cmi_intr(void *data) +{ + struct sc_info *sc = data; + u_int32_t intrstat; + + snd_mtxlock(sc->lock); + intrstat = cmi_rd(sc, CMPCI_REG_INTR_STATUS, 4); + if ((intrstat & CMPCI_REG_ANY_INTR) == 0) { + goto out; + } + + /* Disable interrupts */ + if (intrstat & CMPCI_REG_CH0_INTR) { + cmi_clr4(sc, CMPCI_REG_INTR_CTRL, CMPCI_REG_CH0_INTR_ENABLE); + } + + if (intrstat & CMPCI_REG_CH1_INTR) { + cmi_clr4(sc, CMPCI_REG_INTR_CTRL, CMPCI_REG_CH1_INTR_ENABLE); + } + + /* 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); + } + + /* Enable interrupts */ + if (intrstat & CMPCI_REG_CH0_INTR) { + cmi_set4(sc, CMPCI_REG_INTR_CTRL, CMPCI_REG_CH0_INTR_ENABLE); + } + + if (intrstat & CMPCI_REG_CH1_INTR) { + cmi_set4(sc, CMPCI_REG_INTR_CTRL, CMPCI_REG_CH1_INTR_ENABLE); + } + +out: + snd_mtxunlock(sc->lock); + return; +} + +static struct pcmchan_caps * +cmichan_getcaps(kobj_t obj, void *data) +{ + 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 } +}; +CHANNEL_DECLARE(cmichan); + +/* ------------------------------------------------------------------------- */ +/* Mixer - sb16 with kinks */ + +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); +} + +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); +} + +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 */ +} 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}, +}; + +#define MIXER_GAIN_REG_RTOL(r) (r - 1) + +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); + + 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%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; +} + +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; + + 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; +} + +/* Optional SPDIF support. */ + +static int +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"); +#endif /* SND_DYNSYSCTL */ + 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 } +}; +MIXER_DECLARE(cmi_mixer); + +/* ------------------------------------------------------------------------- */ +/* 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; + } +} + +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); + + 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); +} + +/* ------------------------------------------------------------------------- */ +/* Bus and device registration */ +static int +cmi_probe(device_t dev) +{ + switch(pci_get_devid(dev)) { + case CMI8338A_PCI_ID: + device_set_desc(dev, "CMedia CMI8338A"); + return 0; + case CMI8338B_PCI_ID: + device_set_desc(dev, "CMedia CMI8338B"); + return 0; + case CMI8738_PCI_ID: + device_set_desc(dev, "CMedia CMI8738"); + return 0; + case CMI8738B_PCI_ID: + device_set_desc(dev, "CMedia CMI8738B"); + return 0; + default: + return ENXIO; + } +} + +static int +cmi_attach(device_t dev) +{ + struct snddev_info *d; + struct sc_info *sc; + u_int32_t data; + char status[SND_STATUSLEN]; + + d = device_get_softc(dev); + sc = malloc(sizeof(struct sc_info), M_DEVBUF, M_NOWAIT | M_ZERO); + if (sc == NULL) { + device_printf(dev, "cannot allocate softc\n"); + 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_MAPS; + sc->reg = bus_alloc_resource(dev, SYS_RES_IOPORT, &sc->regid, + 0, BUS_SPACE_UNRESTRICTED, 1, 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); + + 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, 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*/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, + &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", + rman_get_start(sc->reg), rman_get_start(sc->irq)); + 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; +} + +static int +cmi_detach(device_t dev) +{ + struct sc_info *sc; + int 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); + + return 0; +} + +static int +cmi_suspend(device_t 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; +} + +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 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 } +}; + +static driver_t cmi_driver = { + "pcm", + cmi_methods, + PCM_SOFTC_SIZE +}; + +DRIVER_MODULE(snd_cmi, pci, cmi_driver, pcm_devclass, 0, 0); +MODULE_DEPEND(snd_cmi, snd_pcm, PCM_MINVER, PCM_PREFVER, PCM_MAXVER); +MODULE_VERSION(snd_cmi, 1); diff --git a/sys/dev/sound/pci/cmireg.h b/sys/dev/sound/pci/cmireg.h new file mode 100644 index 0000000..9e838a6 --- /dev/null +++ b/sys/dev/sound/pci/cmireg.h @@ -0,0 +1,210 @@ +/* + * 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@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$ + */ + +/* C-Media CMI8x38 Audio Chip Support */ + +#ifndef _DEV_PCI_CMPCIREG_H_ +#define _DEV_PCI_CMPCIREG_H_ (1) + +/* + * PCI Configuration Registers + */ + +#define CMPCI_PCI_IOBASEREG (PCI_MAPREG_START) + +/* + * I/O Space + */ + +#define CMPCI_REG_FUNC_0 0x00 +# define CMPCI_REG_CH0_DIR 0x00000001 +# define CMPCI_REG_CH1_DIR 0x00000002 +# define CMPCI_REG_CH0_PAUSE 0x00000004 +# define CMPCI_REG_CH1_PAUSE 0x00000008 +# define CMPCI_REG_CH0_ENABLE 0x00010000 +# define CMPCI_REG_CH1_ENABLE 0x00020000 +# define CMPCI_REG_CH0_RESET 0x00040000 +# define CMPCI_REG_CH1_RESET 0x00080000 + +#define CMPCI_REG_FUNC_1 0x04 +# define CMPCI_REG_JOY_ENABLE 0x00000002 +# define CMPCI_REG_UART_ENABLE 0x00000004 +# define CMPCI_REG_LEGACY_ENABLE 0x00000008 +# define CMPCI_REG_BREQ 0x00000010 +# define CMPCI_REG_MCBINTR_ENABLE 0x00000020 +# define CMPCI_REG_SPDIFOUT_DAC 0x00000040 +# define CMPCI_REG_SPDIF_LOOP 0x00000080 +# define CMPCI_REG_SPDIF0_ENABLE 0x00000100 +# define CMPCI_REG_SPDIF1_ENABLE 0x00000200 +# define CMPCI_REG_DAC_FS_SHIFT 10 +# define CMPCI_REG_DAC_FS_MASK 0x00000007 +# define CMPCI_REG_ADC_FS_SHIFT 13 +# define CMPCI_REG_ADC_FS_MASK 0x00000007 + +#define CMPCI_REG_CHANNEL_FORMAT 0x08 +# define CMPCI_REG_CH0_FORMAT_SHIFT 0 +# define CMPCI_REG_CH0_FORMAT_MASK 0x00000003 +# define CMPCI_REG_CH1_FORMAT_SHIFT 2 +# define CMPCI_REG_CH1_FORMAT_MASK 0x00000003 +# define CMPCI_REG_FORMAT_MONO 0x00000000 +# define CMPCI_REG_FORMAT_STEREO 0x00000001 +# define CMPCI_REG_FORMAT_8BIT 0x00000000 +# define CMPCI_REG_FORMAT_16BIT 0x00000002 + +#define CMPCI_REG_INTR_CTRL 0x0c +# define CMPCI_REG_CH0_INTR_ENABLE 0x00010000 +# define CMPCI_REG_CH1_INTR_ENABLE 0x00020000 +# define CMPCI_REG_TDMA_INTR_ENABLE 0x00040000 + +#define CMPCI_REG_INTR_STATUS 0x10 +# define CMPCI_REG_CH0_INTR 0x00000001 +# define CMPCI_REG_CH1_INTR 0x00000002 +# define CMPCI_REG_CH0_BUSY 0x00000004 +# define CMPCI_REG_CH1_BUSY 0x00000008 +# define CMPCI_REG_LEGACY_STEREO 0x00000010 +# define CMPCI_REG_LEGACY_HDMA 0x00000020 +# define CMPCI_REG_DMASTAT 0x00000040 +# define CMPCI_REG_XDO46 0x00000080 +# define CMPCI_REG_HTDMA_INTR 0x00004000 +# define CMPCI_REG_LTDMA_INTR 0x00008000 +# define CMPCI_REG_UART_INTR 0x00010000 +# define CMPCI_REG_MCB_INTR 0x04000000 +# define CMPCI_REG_VCO 0x08000000 +# define CMPCI_REG_ANY_INTR 0x80000000 + +#define CMPCI_REG_LEGACY_CTRL 0x14 +# define CMPCI_REG_LEGACY_SPDIF_ENABLE 0x00200000 +# define CMPCI_REG_SPDIF_COPYRIGHT 0x00400000 +# define CMPCI_REG_XSPDIF_ENABLE 0x00800000 +# define CMPCI_REG_FMSEL_SHIFT 24 +# define CMPCI_REG_FMSEL_MASK 0x00000003 +# define CMPCI_REG_VSBSEL_SHIFT 26 +# define CMPCI_REG_VSBSEL_MASK 0x00000003 +# define CMPCI_REG_VMPUSEL_SHIFT 29 +# define CMPCI_REG_VMPUSEL_MASK 0x00000003 + +#define CMPCI_REG_MISC 0x18 +# define CMPCI_REG_POWER_DOWN 0x80000000 +# define CMPCI_REG_BUS_AND_DSP_RESET 0x40000000 +# define CMPCI_REG_N4SPK3D 0x04000000 +# define CMPCI_REG_W_SPDIF_48L 0x01000000 +# define CMPCI_REG_XCHGDAC 0x00400000 +# define CMPCI_REG_FM_ENABLE 0x00080000 +# define CMPCI_REG_SPDIF_48K 0x00008000 + +#define CMPCI_REG_SBDATA 0x22 +#define CMPCI_REG_SBADDR 0x23 +# define CMPCI_SB16_MIXER_RESET 0x00 +# define CMPCI_SB16_MIXER_MASTER_L 0x30 +# define CMPCI_SB16_MIXER_MASTER_R 0x31 +# define CMPCI_SB16_MIXER_VOICE_L 0x32 +# define CMPCI_SB16_MIXER_VOICE_R 0x33 +# define CMPCI_SB16_MIXER_FM_L 0x34 +# define CMPCI_SB16_MIXER_FM_R 0x35 +# define CMPCI_SB16_MIXER_CDDA_L 0x36 +# define CMPCI_SB16_MIXER_CDDA_R 0x37 +# define CMPCI_SB16_MIXER_LINE_L 0x38 +# define CMPCI_SB16_MIXER_LINE_R 0x39 +# define CMPCI_SB16_MIXER_MIC 0x3A +# define CMPCI_SB16_MIXER_SPEAKER 0x3B +# define CMPCI_SB16_MIXER_OUTMIX 0x3C +# define CMPCI_SB16_SW_MIC 0x01 +# define CMPCI_SB16_SW_CD_R 0x02 +# define CMPCI_SB16_SW_CD_L 0x04 +# define CMPCI_SB16_SW_CD (CMPCI_SB16_SW_CD_L|CMPCI_SB16_SW_CD_R) +# define CMPCI_SB16_SW_LINE_R 0x08 +# define CMPCI_SB16_SW_LINE_L 0x10 +# define CMPCI_SB16_SW_LINE (CMPCI_SB16_SW_LINE_L|CMPCI_SB16_SW_LINE_R) +# define CMPCI_SB16_SW_FM_R 0x20 +# define CMPCI_SB16_SW_FM_L 0x40 +# define CMPCI_SB16_SW_FM (CMPCI_SB16_SW_FM_L|CMPCI_SB16_SW_FM_R) +# define CMPCI_SB16_MIXER_ADCMIX_L 0x3D +# define CMPCI_SB16_MIXER_ADCMIX_R 0x3E +# define CMPCI_SB16_MIXER_FM_SRC_R 0x20 +# define CMPCI_SB16_MIXER_LINE_SRC_R 0x08 +# define CMPCI_SB16_MIXER_CD_SRC_R 0x02 +# define CMPCI_SB16_MIXER_MIC_SRC 0x01 +# define CMPCI_SB16_MIXER_SRC_R_TO_L(v) ((v) << 1) + +# define CMPCI_SB16_MIXER_INGAIN_L 0x3F +# define CMPCI_SB16_MIXER_INGAIN_R 0x40 +# define CMPCI_SB16_MIXER_OUTGAIN_L 0x41 +# define CMPCI_SB16_MIXER_OUTGAIN_R 0x42 +# define CMPCI_SB16_MIXER_AGC 0x43 +# define CMPCI_SB16_MIXER_TREBLE_L 0x44 +# define CMPCI_SB16_MIXER_TREBLE_R 0x45 +# define CMPCI_SB16_MIXER_BASS_L 0x46 +# define CMPCI_SB16_MIXER_BASS_R 0x47 +# define CMPCI_SB16_MIXER_L_TO_R(addr) ((addr)+1) + +# define CMPCI_ADJUST_MIC_GAIN(sc, x) cmpci_adjust((x), 0xf8) +# define CMPCI_ADJUST_GAIN(sc, x) cmpci_adjust((x), 0xf8) +# define CMPCI_ADJUST_2_GAIN(sc, x) cmpci_adjust((x), 0xc0) + +#define CMPCI_REG_MIXER1 0x24 +# define CMPCI_SPK4 0x20 +# define CMPCI_REAR2FRONT 0x10 +# define CMPCI_X3DEN 0x02 + +#define CMPCI_REG_MPU_BASE 0x40 +#define CMPCI_REG_MPU_SIZE 0x10 +#define CMPCI_REG_FM_BASE 0x50 +#define CMPCI_REG_FM_SIZE 0x10 + +#define CMPCI_REG_AUX_MIC 0x25 +# define CMPCI_AUX_SELECT_R 0x80 +# define CMPCI_AUX_SELECT_L 0x40 +# define CMPCI_AUX_MUTE_R 0x20 +# define CMPCI_AUX_MUTE_L 0x10 +# define CMPCI_VAD_MIC 0x0e +# define CMPCI_MIC_QUIET 0x01 + +#define CMPCI_REG_DMA0_BASE 0x80 +#define CMPCI_REG_DMA0_BYTES 0x84 +#define CMPCI_REG_DMA0_SAMPLES 0x86 +#define CMPCI_REG_DMA1_BASE 0x88 +#define CMPCI_REG_DMA1_BYTES 0x8C +#define CMPCI_REG_DMA1_SAMPLES 0x8E + +/* sample rate */ +#define CMPCI_REG_RATE_5512 0 +#define CMPCI_REG_RATE_11025 1 +#define CMPCI_REG_RATE_22050 2 +#define CMPCI_REG_RATE_44100 3 +#define CMPCI_REG_RATE_8000 4 +#define CMPCI_REG_RATE_16000 5 +#define CMPCI_REG_RATE_32000 6 +#define CMPCI_REG_RATE_48000 7 +#define CMPCI_REG_NUMRATE 8 + +#endif /* _DEV_PCI_CMPCIREG_H_ */ + +/* end of file */ diff --git a/sys/dev/sound/pci/cs4281.c b/sys/dev/sound/pci/cs4281.c new file mode 100644 index 0000000..a700394 --- /dev/null +++ b/sys/dev/sound/pci/cs4281.c @@ -0,0 +1,979 @@ +/* + * Copyright (c) 2000 Orion Hodson <O.Hodson@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@crystal.cirrus.com), tom + * woller (twoller@crystal.cirrus.com). Shingo Watanabe (nabe@nabechan.org) + * contributed towards power management. + */ + +#include <dev/sound/pcm/sound.h> +#include <dev/sound/pcm/ac97.h> + +#include <pci/pcireg.h> +#include <pci/pcivar.h> + +#include <dev/sound/pci/cs4281.h> + +SND_DECLARE_FILE("$FreeBSD$"); + +#define CS4281_DEFAULT_BUFSZ 16384 + +/* Max fifo size for full duplex is 64 */ +#define CS4281_FIFO_SIZE 15 + +/* DMA Engine Indices */ +#define CS4281_DMA_PLAY 0 +#define CS4281_DMA_REC 1 + +/* Misc */ + +#define inline __inline + +#ifndef DEB +#define DEB(x) /* x */ +#endif /* DEB */ + +/* ------------------------------------------------------------------------- */ +/* Structures */ + +struct sc_info; + +/* channel registers */ +struct sc_chinfo { + struct sc_info *parent; + + struct snd_dbuf *buffer; + struct pcm_channel *channel; + + u_int32_t spd, fmt, bps, blksz; + + int dma_setup, dma_active, dma_chan; +}; + +/* device private data */ +struct sc_info { + 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; +}; + +/* -------------------------------------------------------------------- */ +/* prototypes */ + +/* ADC/DAC control */ +static u_int32_t adcdac_go(struct sc_chinfo *ch, u_int32_t go); +static void adcdac_prog(struct sc_chinfo *ch); + +/* power management and interrupt control */ +static void cs4281_intr(void *); +static int cs4281_power(struct sc_info *, int); +static int cs4281_init(struct sc_info *); + +/* talk to the card */ +static u_int32_t cs4281_rd(struct sc_info *, int); +static void cs4281_wr(struct sc_info *, int, u_int32_t); + +/* misc */ +static u_int8_t cs4281_rate_to_rv(u_int32_t); +static u_int32_t cs4281_format_to_dmr(u_int32_t); +static u_int32_t cs4281_format_to_bps(u_int32_t); + +/* -------------------------------------------------------------------- */ +/* 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 +}; + +static struct pcmchan_caps cs4281_caps = {6024, 48000, cs4281_fmts, 0}; + +/* -------------------------------------------------------------------- */ +/* Hardware */ + +static inline u_int32_t +cs4281_rd(struct sc_info *sc, int 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); +} + +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); +} + +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); +} + +static int +cs4281_waitset(struct sc_info *sc, int regno, u_int32_t mask, int tries) +{ + u_int32_t v; + + 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; + + while(tries > 0) { + DELAY(100); + v = ~ cs4281_rd(sc, regno); + if (v & mask) break; + tries --; + } + return tries; +} + +/* ------------------------------------------------------------------------- */ +/* Register value mapping functions */ + +static u_int32_t cs4281_rates[] = {48000, 44100, 22050, 16000, 11025, 8000}; +#define CS4281_NUM_RATES sizeof(cs4281_rates)/sizeof(cs4281_rates[0]) + +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; + } + + 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; + + 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; +} + +static inline u_int32_t +cs4281_format_to_bps(u_int32_t format) +{ + return ((AFMT_8BIT & format) ? 1 : 2) * ((AFMT_STEREO & format) ? 2 : 1); +} + +/* -------------------------------------------------------------------- */ +/* ac97 codec */ + +static u_int32_t +cs4281_rdcd(kobj_t obj, void *devinfo, int regno) +{ + struct sc_info *sc = (struct sc_info *)devinfo; + int codecno; + + codecno = regno >> 8; + regno &= 0xff; + + /* 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); + + /* 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; + } + + 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; + + 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 } +}; +AC97_DECLARE(cs4281_ac97); + +/* ------------------------------------------------------------------------- */ +/* shared rec/play channel interface */ + +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; + + 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->dma_chan = (dir == PCMDIR_PLAY) ? CS4281_DMA_PLAY : CS4281_DMA_REC; + ch->dma_setup = 0; + + adcdac_go(ch, 0); + adcdac_prog(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); + + DEB(printf("cs4281chan_setblocksize: blksz %d Setting %d\n", blocksize, 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 */ + + 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; + + 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; + + return ptr; +} + +static int +cs4281chan_trigger(kobj_t obj, void *data, int go) +{ + 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; + } + + /* return 0 if ok */ + return 0; +} + +static struct pcmchan_caps * +cs4281chan_getcaps(kobj_t obj, void *data) +{ + 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 } +}; +CHANNEL_DECLARE(cs4281chan); + +/* -------------------------------------------------------------------- */ +/* ADC/DAC control */ + +/* adcdac_go enables/disable DMA channel, returns non-zero if DMA was + * 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; + + 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); + + cs4281_wr(sc, CS4281PCI_HICR, CS4281PCI_HICR_EOI); + + return going; +} + +static void +adcdac_prog(struct sc_chinfo *ch) +{ + 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); + } +} + +/* -------------------------------------------------------------------- */ +/* The interrupt handler */ + +static void +cs4281_intr(void *p) +{ + struct sc_info *sc = (struct sc_info *)p; + u_int32_t hisr; + + hisr = cs4281_rd(sc, CS4281PCI_HISR); + + 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_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); +} + +/* -------------------------------------------------------------------- */ +/* power management related */ + +static int +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; + } + + DEB(printf("cs4281_power %d -> %d\n", sc->power, state)); + sc->power = state; + + return 0; +} + +static int +cs4281_init(struct sc_info *sc) +{ + 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 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; +} + +/* -------------------------------------------------------------------- */ +/* Probe and attach the card */ + +static int +cs4281_pci_probe(device_t dev) +{ + 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 ? 0 : 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 softc\n"); + 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); + +#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 D0\n", pci_get_powerstate(dev)); + + 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 D0\n", + data & CS4281PCI_PMCS_PS_MASK); + pci_write_config(dev, CS4281PCI_PMCS_OFFSET, + data & ~CS4281PCI_PMCS_PS_MASK, 4); + } +#endif + + sc->regid = PCIR_MAPS; + 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_MAPS + 4; + 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(dev, SYS_RES_IRQ, &sc->irqid, + 0, ~0, 1, 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*/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, &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", + (sc->regtype == SYS_RES_IOPORT)? "io" : "memory", + rman_get_start(sc->reg), rman_get_start(sc->irq)); + 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; +} + +static int +cs4281_pci_detach(device_t dev) +{ + 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); + + return 0; +} + +static int +cs4281_pci_suspend(device_t dev) +{ + struct sc_info *sc; + + sc = pcm_getdevinfo(dev); + + sc->rch.dma_active = adcdac_go(&sc->rch, 0); + sc->pch.dma_active = adcdac_go(&sc->pch, 0); + + cs4281_power(sc, 3); + + return 0; +} + +static int +cs4281_pci_resume(device_t dev) +{ + struct sc_info *sc; + + sc = pcm_getdevinfo(dev); + + /* power up */ + cs4281_power(sc, 0); + + /* 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; +} + +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 } +}; + +static driver_t cs4281_driver = { + "pcm", + cs4281_methods, + PCM_SOFTC_SIZE, +}; + +DRIVER_MODULE(snd_cs4281, pci, cs4281_driver, pcm_devclass, 0, 0); +MODULE_DEPEND(snd_cs4281, snd_pcm, PCM_MINVER, PCM_PREFVER, PCM_MAXVER); +MODULE_VERSION(snd_cs4281, 1); diff --git a/sys/dev/sound/pci/cs4281.h b/sys/dev/sound/pci/cs4281.h new file mode 100644 index 0000000..68a71e7 --- /dev/null +++ b/sys/dev/sound/pci/cs4281.h @@ -0,0 +1,205 @@ +/* + * Copyright (c) 2000 Orion Hodson <O.Hodson@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$ + */ + +#ifndef _CS4281_H_ +#define _CS4281_H_ + +#define CS4281_PCI_ID 0x60051013 + +/* Ball Parks */ +#define CS4281PCI_BA0_SIZE 4096 +#define CS4281PCI_BA1_SIZE 65536 + +/* Register values */ +#define CS4281PCI_HISR 0x000 +# define CS4281PCI_HISR_DMAI 0x00040000 +# define CS4281PCI_HISR_DMA(x) (0x0100 << (x)) + +#define CS4281PCI_HICR 0x008 +# define CS4281PCI_HICR_EOI 0x00000003 + +#define CS4281PCI_HIMR 0x00c +# define CS4281PCI_HIMR_DMAI 0x00040000 +# define CS4281PCI_HIMR_DMA(x) (0x0100 << (x)) + +#define CS4281PCI_IIER 0x010 + +#define CS4281PCI_HDSR(x) (0x0f0 + (x)*0x004) +# define CS4281PCI_HDSR_CH1P 0x02000000 +# define CS4281PCI_HDSR_CH2P 0x01000000 +# define CS4281PCI_HDSR_HDTC 0x00020000 +# define CS4281PCI_HDSR_DTC 0x00010000 +# define CS4281PCI_HDSR_DRUN 0x00008000 +# define CS4281PCI_HDSR_RQ 0x00000080 + +#define CS4281PCI_DCA(x) (0x110 + (x) * 0x010) +#define CS4281PCI_DCC(x) (0x114 + (x) * 0x010) +#define CS4281PCI_DBA(x) (0x118 + (x) * 0x010) +#define CS4281PCI_DBC(x) (0x11c + (x) * 0x010) + +#define CS4281PCI_DMR(x) (0x150 + (x) * 0x008) +# define CS4281PCI_DMR_DMA 0x20000000 +# define CS4281PCI_DMR_POLL 0x10000000 +# define CS4281PCI_DMR_TBC 0x02000000 +# define CS4281PCI_DMR_CBC 0x01000000 +# define CS4281PCI_DMR_SWAPC 0x00400000 +# define CS4281PCI_DMR_SIZE20 0x00100000 +# define CS4281PCI_DMR_USIGN 0x00080000 +# define CS4281PCI_DMR_BEND 0x00040000 +# define CS4281PCI_DMR_MONO 0x00020000 +# define CS4281PCI_DMR_SIZE8 0x00010000 +# define CS4281PCI_DMR_TYPE_DEMAND 0x00000000 +# define CS4281PCI_DMR_TYPE_SINGLE 0x00000040 +# define CS4281PCI_DMR_TYPE_BLOCK 0x00000080 +# define CS4281PCI_DMR_TYPE_CASCADE 0x000000c0 +# define CS4281PCI_DMR_DEC 0x00000020 +# define CS4281PCI_DMR_AUTO 0x00000010 +# define CS4281PCI_DMR_TR_PLAY 0x00000008 +# define CS4281PCI_DMR_TR_REC 0x00000004 + +#define CS4281PCI_DCR(x) (0x154 + (x) * 0x008) +# define CS4281PCI_DCR_HTCIE 0x00020000 +# define CS4281PCI_DCR_TCIE 0x00010000 +# define CS4281PCI_DCR_MSK 0x00000001 + +#define CS4281PCI_FCR(x) (0x180 + (x) * 0x004) +# define CS4281PCI_FCR_FEN 0x80000000 +# define CS4281PCI_FCR_DACZ 0x40000000 +# define CS4281PCI_FCR_PSH 0x20000000 +# define CS4281PCI_FCR_RS(x) ((x) << 24) +# define CS4281PCI_FCR_LS(x) ((x) << 16) +# define CS4281PCI_FCR_SZ(x) ((x) << 8) +# define CS4281PCI_FCR_OF(x) (x) + +#define CS4281PCI_FPDR(x) (0x190 + (x) * 0x004) + +#define CS4281PCI_FCHS 0x20c +#define CS4281PCI_FSIC(x) (0x210 + (x) * 0x004) + +#define CS4281PCI_PMCS 0x344 +# define CS4281PCI_PMCS_PS_MASK 0x00000003 +#define CS4281PCI_PMCS_OFFSET (CS4281PCI_PMCS - 0x300) + +#define CS4281PCI_CWPR 0x3e0 +# define CS4281PCI_CWPR_MAGIC 0x00004281 + +#define CS4281PCI_EPPMC 0x3e4 +# define CS4281PCI_EPPMC_FPDN 0x00004000 +#define CS4281PCI_GPIOR 0x3e8 + +#define CS4281PCI_SPMC 0x3ec +# define CS4281PCI_SPMC_RSTN 0x00000001 +# define CS4281PCI_SPMC_ASYN 0x00000002 +# define CS4281PCI_SPMC_WUP1 0x00000004 +# define CS4281PCI_SPMC_WUP2 0x00000008 +# define CS4281PCI_SPMC_ASDO 0x00000080 +# define CS4281PCI_SPMC_ASDI2E 0x00000100 +# define CS4281PCI_SPMC_EESPD 0x00000200 +# define CS4281PCI_SPMC_GISPEN 0x00004000 +# define CS4281PCI_SPMC_GIPPEN 0x00008000 + +#define CS4281PCI_CFLR 0x3f0 +#define CS4281PCI_IISR 0x3f4 +#define CS4281PCI_TMS 0x3f8 +#define CS4281PCI_SSVID 0x3fc + +#define CS4281PCI_CLKCR1 0x400 +# define CS_4281PCI_CLKCR1_DLLSS_MASK 0x0000000c +# define CS_4281PCI_CLKCR1_DLLSS_AC97 0x00000004 +# define CS4281PCI_CLKCR1_DLLP 0x00000010 +# define CS4281PCI_CLKCR1_SWCE 0x00000020 +# define CS4281PCI_CLKCR1_DLLOS 0x00000040 +# define CS4281PCI_CLKCR1_CKRA 0x00010000 +# define CS4281PCI_CLKCR1_DLLRDY 0x01000000 +# define CS4281PCI_CLKCR1_CLKON 0x02000000 + +#define CS4281PCI_FRR 0x410 + +#define CS4281PCI_SLT12O 0x41c +#define CS4281PCI_SERMC 0x420 +# define CS4281PCI_SERMC_PTC_AC97 0x00000002 +# define CS4281PCI_SERMC_PTC_MASK 0x0000000e +# define CS4281PCI_SERMC_ODSEN1 0x01000000 +# define CS4281PCI_SERMC_ODSEN2 0x02000000 +#define CS4281PCI_SERC1 0x428 +#define CS4281PCI_SERC2 0x42c + +#define CS4281PCI_SLT12M 0x45c +#define CS4281PCI_ACCTL 0x460 +# define CS4281PCI_ACCTL_ESYN 0x00000002 +# define CS4281PCI_ACCTL_VFRM 0x00000004 +# define CS4281PCI_ACCTL_DCV 0x00000008 +# define CS4281PCI_ACCTL_CRW 0x00000010 +# define CS4281PCI_ACCTL_TC 0x00000040 + +#define CS4281PCI_ACSTS 0x464 +# define CS4281PCI_ACSTS_CRDY 0x00000001 +# define CS4281PCI_ACSTS_VSTS 0x00000002 + +#define CS4281PCI_ACOSV 0x468 +# define CS4281PCI_ACOSV_SLV(x) (1 << (x - 3)) +#define CS4281PCI_ACCAD 0x46c +#define CS4281PCI_ACCDA 0x470 +#define CS4281PCI_ACISV 0x474 +# define CS4281PCI_ACISV_ISV(x) (1 << (x - 3)) +#define CS4281PCI_ACSAD 0x478 +#define CS4281PCI_ACSDA 0x47c +#define CS4281PCI_JSPT 0x480 +#define CS4281PCI_JSCTL 0x484 + +#define CS4281PCI_SSPM 0x740 +# define CS4281PCI_SSPM_MIXEN 0x00000040 +# define CS4281PCI_SSPM_CSRCEN 0x00000020 +# define CS4281PCI_SSPM_PSRCEN 0x00000010 +# define CS4281PCI_SSPM_JSEN 0x00000008 +# define CS4281PCI_SSPM_ACLEN 0x00000004 +# define CS4281PCI_SSPM_FMEN 0x00000002 + +#define CS4281PCI_DACSR 0x744 +#define CS4281PCI_ADCSR 0x748 +#define CS4281PCI_SSCR 0x74c + +#define CS4281PCI_SRCSA 0x75c +# define CS4281PCI_SRCSA_PLSS(x) (x) +# define CS4281PCI_SRCSA_PRSS(x) ((x) << 8) +# define CS4281PCI_SRCSA_CLSS(x) ((x) << 16) +# define CS4281PCI_SRCSA_CRSS(x) ((x) << 24) + +#define CS4281PCI_PPLVC 0x760 +#define CS4281PCI_PPRVC 0x764 + +/* Slot definitions (minimal) */ +#define CS4281PCI_LPCM_PLAY_SLOT 0x00 +#define CS4281PCI_RPCM_PLAY_SLOT 0x01 + +#define CS4281PCI_LPCM_REC_SLOT 0x0a +#define CS4281PCI_RPCM_REC_SLOT 0x0b + +#define CS4281PCI_DISABLED_SLOT 0x1f + +#endif /* _CS4281_H_ */ diff --git a/sys/dev/sound/pci/csa.c b/sys/dev/sound/pci/csa.c new file mode 100644 index 0000000..6361f3e --- /dev/null +++ b/sys/dev/sound/pci/csa.c @@ -0,0 +1,1060 @@ +/* + * 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> +#include <sys/kernel.h> +#include <sys/bus.h> +#include <sys/malloc.h> +#include <sys/module.h> +#include <machine/resource.h> +#include <machine/bus.h> +#include <sys/rman.h> +#include <sys/soundcard.h> +#include <dev/sound/pcm/sound.h> +#include <dev/sound/chip.h> +#include <dev/sound/pci/csareg.h> +#include <dev/sound/pci/csavar.h> + +#include <pci/pcireg.h> +#include <pci/pcivar.h> + +#include <gnu/dev/sound/pci/csaimg.h> + +SND_DECLARE_FILE("$FreeBSD$"); + +/* This is the pci device id. */ +#define CS4610_PCI_ID 0x60011013 +#define CS4614_PCI_ID 0x60031013 +#define CS4615_PCI_ID 0x60041013 + +/* Here is the parameter structure per a device. */ +struct csa_softc { + 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 */ + + struct csa_card *card; + struct csa_bridgeinfo binfo; /* The state of this bridge. */ +}; + +typedef struct csa_softc *sc_p; + +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); +static int csa_release_resource(device_t bus, device_t child, int type, int rid, + 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); +static int csa_teardown_intr(device_t bus, device_t child, + struct resource *irq, void *cookie); +static driver_intr_t csa_intr; +static int csa_initialize(sc_p scp); +static void csa_resetdsp(csa_res *resp); +static int csa_downloadimage(csa_res *resp); + +static devclass_t csa_devclass; + +static void +amp_none(void) +{ +} + +static void +amp_voyetra(void) +{ +} + +static int +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); + } + + free(pci_devices, M_TEMP); + return ENXIO; +#else + return 0; +#endif +} + +static struct csa_card cards_4610[] = { + {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}, +}; + +static struct csa_card cards_4615[] = { + {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; +}; + +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}, +}; + +static struct card_type * +csa_findcard(device_t dev) +{ + int i; + + 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]; +} + +static int +csa_probe(device_t dev) +{ + struct card_type *card; + + card = csa_findcard(dev); + if (card) { + device_set_desc(dev, card->name); + return 0; + } + 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 %s\n", scp->card->name); + resp->io_rid = PCIR_MAPS; + resp->io = bus_alloc_resource(dev, SYS_RES_MEMORY, &resp->io_rid, 0, ~0, 1, RF_ACTIVE); + if (resp->io == NULL) + return (ENXIO); + resp->mem_rid = PCIR_MAPS + 4; + resp->mem = bus_alloc_resource(dev, SYS_RES_MEMORY, &resp->mem_rid, 0, ~0, 1, RF_ACTIVE); + if (resp->mem == NULL) + goto err_io; + resp->irq_rid = 0; + resp->irq = bus_alloc_resource(dev, SYS_RES_IRQ, &resp->irq_rid, 0, ~0, 1, RF_ACTIVE | RF_SHAREABLE); + if (resp->irq == NULL) + goto err_mem; + + /* Enable interrupt. */ + if (snd_setup_intr(dev, resp->irq, INTR_MPSAFE, 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); +#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); + + bus_generic_attach(dev); + + return (0); + +err_teardown: + bus_teardown_intr(dev, resp->irq, scp->ih); +err_intr: + 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); +err_io: + 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); + + return bus_generic_detach(dev); +} + +static int +csa_resume(device_t dev) +{ + csa_detach(dev); + csa_attach(dev); + + return 0; +} + +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) +{ + 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_MAPS: + res = resp->io; + break; + case PCIR_MAPS + 4: + res = resp->mem; + break; + default: + return (NULL); + } + break; + default: + return (NULL); + } + + return res; +} + +static int +csa_release_resource(device_t bus, device_t child, int type, int rid, + struct resource *r) +{ + 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. + */ + +static int +csa_setup_intr(device_t bus, device_t child, + struct resource *irq, int flags, + 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; + + /* + * 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); +} + +static int +csa_teardown_intr(device_t bus, device_t child, + 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; + + default: + return (EINVAL); + } + + 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; + } + + /* 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. + */ +#if 1 + 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 */ +#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. + */ +#if notdef + 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. + */ +#if notdef + DELAY(10000000L); /* clw */ +#else + 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. + */ +#if notdef + 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. + */ +#if notdef + clkcr1 = csa_readio(resp, BA0_CLKCR1) & ~CLKCR1_SWCE; + csa_writeio(resp, BA0_CLKCR1, clkcr1); +#endif /* notdef */ + + /* + * Enable interrupts on the part. + */ +#if 0 + csa_writeio(resp, BA0_HICR, HICR_IEV | HICR_CHGM); +#endif /* notdef */ + + return (0); +} + +void +csa_clearserialfifos(csa_res *resp) +{ + 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); +} + +static void +csa_resetdsp(csa_res *resp) +{ + int i; + + /* + * 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; + + 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++; + } + } + + 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); + + /* + * 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); + + 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 + */ + + /* + * 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); + + return (0); +} + +u_int32_t +csa_readio(csa_res *resp, u_long offset) +{ + 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); + } +} + +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); +} + +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); +} + +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); +} + +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), + + { 0, 0 } +}; + +static driver_t csa_driver = { + "csa", + csa_methods, + sizeof(struct csa_softc), +}; + +/* + * csa can be attached to a pci bus. + */ +DRIVER_MODULE(snd_csa, pci, csa_driver, csa_devclass, 0, 0); +MODULE_DEPEND(snd_csa, snd_pcm, PCM_MINVER, PCM_PREFVER, PCM_MAXVER); +MODULE_VERSION(snd_csa, 1); diff --git a/sys/dev/sound/pci/csamidi.c b/sys/dev/sound/pci/csamidi.c new file mode 100644 index 0000000..be36048 --- /dev/null +++ b/sys/dev/sound/pci/csamidi.c @@ -0,0 +1,583 @@ +/*- + * 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$ + */ + +#include <dev/sound/midi/midi.h> +#include <dev/sound/chip.h> +#include <dev/sound/pci/csareg.h> +#include <machine/cpufunc.h> + +#include <pci/pcireg.h> +#include <pci/pcivar.h> + +static devclass_t midi_devclass; + +#ifndef DDB +#undef DDB +#define DDB(x) +#endif /* DDB */ + +#define CSAMIDI_RESET 0xff +#define CSAMIDI_UART 0x3f +#define CSAMIDI_ACK 0xfe + +#define CSAMIDI_STATMASK 0xc0 +#define CSAMIDI_OUTPUTBUSY 0x40 +#define CSAMIDI_INPUTBUSY 0x80 + +#define CSAMIDI_TRYDATA 50 +#define CSAMIDI_DELAY 25000 + +extern synthdev_info midisynth_op_desc; + +/* These are the synthesizer and the midi interface information. */ +static struct synth_info csamidi_synthinfo = { + "CS461x MIDI", + 0, + SYNTH_TYPE_MIDI, + 0, + 0, + 128, + 128, + 128, + SYNTH_CAP_INPUT, +}; + +static struct midi_info csamidi_midiinfo = { + "CS461x MIDI", + 0, + 0, + 0, +}; + +/* + * These functions goes into csamidi_op_desc to get called + * from sound.c. + */ + +static int csamidi_probe(device_t dev); +static int csamidi_attach(device_t dev); + +static d_ioctl_t csamidi_ioctl; +static driver_intr_t csamidi_intr; +static midi_callback_t csamidi_callback; + +/* Here is the parameter structure per a device. */ +struct csamidi_softc { + device_t dev; /* device information */ + mididev_info *devinfo; /* midi device information */ + struct csa_bridgeinfo *binfo; /* The state of the parent. */ + + struct mtx mtx; /* Mutex to protect the device. */ + + struct resource *io; /* Base of io map */ + int io_rid; /* Io map resource ID */ + struct resource *mem; /* Base of memory map */ + int mem_rid; /* Memory map resource ID */ + struct resource *irq; /* Irq */ + int irq_rid; /* Irq resource ID */ + void *ih; /* Interrupt cookie */ + + int fflags; /* File flags */ +}; + +typedef struct csamidi_softc *sc_p; + +/* These functions are local. */ +static void csamidi_startplay(sc_p scp); +static void csamidi_xmit(sc_p scp); +static int csamidi_reset(sc_p scp); +static int csamidi_status(sc_p scp); +static int csamidi_command(sc_p scp, u_int32_t value); +static int csamidi_readdata(sc_p scp, u_int8_t *value); +static int csamidi_writedata(sc_p scp, u_int32_t value); +static u_int32_t csamidi_readio(sc_p scp, u_long offset); +static void csamidi_writeio(sc_p scp, u_long offset, u_int32_t data); +/* Not used in this file. */ +#if notdef +static u_int32_t csamidi_readmem(sc_p scp, u_long offset); +static void csamidi_writemem(sc_p scp, u_long offset, u_int32_t data); +#endif /* notdef */ +static int csamidi_allocres(sc_p scp, device_t dev); +static void csamidi_releaseres(sc_p scp, device_t dev); + +/* + * This is the device descriptor for the midi device. + */ +static mididev_info csamidi_op_desc = { + "CS461x midi", + + SNDCARD_MPU401, + + NULL, + NULL, + csamidi_ioctl, + + csamidi_callback, + + MIDI_BUFFSIZE, /* Queue Length */ + + 0, /* XXX This is not an *audio* device! */ +}; + +/* + * Here are the main functions to interact to the user process. + */ + +static int +csamidi_probe(device_t dev) +{ + char *s; + sc_p scp; + struct sndcard_func *func; + + /* The parent device has already been probed. */ + + func = device_get_ivars(dev); + if (func == NULL || func->func != SCF_MIDI) + return (ENXIO); + + s = "CS461x Midi Interface"; + + scp = device_get_softc(dev); + bzero(scp, sizeof(*scp)); + scp->io_rid = PCIR_MAPS; + scp->mem_rid = PCIR_MAPS + 4; + scp->irq_rid = 0; + + device_set_desc(dev, s); + return (0); +} + +static int +csamidi_attach(device_t dev) +{ + sc_p scp; + mididev_info *devinfo; + struct sndcard_func *func; + + scp = device_get_softc(dev); + func = device_get_ivars(dev); + scp->binfo = func->varinfo; + + /* Allocate the resources. */ + if (csamidi_allocres(scp, dev)) { + csamidi_releaseres(scp, dev); + return (ENXIO); + } + + /* Fill the softc. */ + scp->dev = dev; + mtx_init(&scp->mtx, "csamid", NULL, MTX_DEF); + scp->devinfo = devinfo = create_mididev_info_unit(MDT_MIDI, &csamidi_op_desc, &midisynth_op_desc); + + /* Fill the midi info. */ + snprintf(devinfo->midistat, sizeof(devinfo->midistat), "at irq %d", + (int)rman_get_start(scp->irq)); + + midiinit(devinfo, dev); + + /* Enable interrupt. */ + if (bus_setup_intr(dev, scp->irq, INTR_TYPE_AV, csamidi_intr, scp, &scp->ih)) { + csamidi_releaseres(scp, dev); + return (ENXIO); + } + + /* Reset the interface. */ + csamidi_reset(scp); + + return (0); +} + +static int +csamidi_ioctl(dev_t i_dev, u_long cmd, caddr_t arg, int mode, struct thread *td) +{ + sc_p scp; + mididev_info *devinfo; + int unit; + struct synth_info *synthinfo; + struct midi_info *midiinfo; + + unit = MIDIUNIT(i_dev); + + MIDI_DEBUG(printf("csamidi_ioctl: unit %d, cmd %s.\n", unit, midi_cmdname(cmd, cmdtab_midiioctl))); + + devinfo = get_mididev_info(i_dev, &unit); + if (devinfo == NULL) { + MIDI_DEBUG(printf("csamidi_ioctl: unit %d is not configured.\n", unit)); + return (ENXIO); + } + scp = devinfo->softc; + + switch (cmd) { + case SNDCTL_SYNTH_INFO: + synthinfo = (struct synth_info *)arg; + if (synthinfo->device != unit) + return (ENXIO); + bcopy(&csamidi_synthinfo, synthinfo, sizeof(csamidi_synthinfo)); + synthinfo->device = unit; + return (0); + break; + case SNDCTL_MIDI_INFO: + midiinfo = (struct midi_info *)arg; + if (midiinfo->device != unit) + return (ENXIO); + bcopy(&csamidi_midiinfo, midiinfo, sizeof(csamidi_midiinfo)); + midiinfo->device = unit; + return (0); + break; + default: + return (ENOSYS); + } + /* NOTREACHED */ + return (EINVAL); +} + +static void +csamidi_intr(void *arg) +{ + sc_p scp; + u_char c; + mididev_info *devinfo; + int leni; + + scp = (sc_p)arg; + devinfo = scp->devinfo; + + mtx_lock(&devinfo->flagqueue_mtx); + mtx_lock(&scp->mtx); + + /* Read the received data. */ + while ((csamidi_status(scp) & MIDSR_RBE) == 0) { + /* Receive the data. */ + csamidi_readdata(scp, &c); + mtx_unlock(&scp->mtx); + + /* Queue into the passthru buffer and start transmitting if we can. */ + if ((devinfo->flags & MIDI_F_PASSTHRU) != 0 && ((devinfo->flags & MIDI_F_BUSY) == 0 || (devinfo->fflags & FWRITE) == 0)) { + midibuf_input_intr(&devinfo->midi_dbuf_passthru, &c, sizeof(c), &leni); + devinfo->callback(devinfo, MIDI_CB_START | MIDI_CB_WR); + } + /* Queue if we are reading. Discard an active sensing. */ + if ((devinfo->flags & MIDI_F_READING) != 0 && c != 0xfe) { + midibuf_input_intr(&devinfo->midi_dbuf_in, &c, sizeof(c), &leni); + } + mtx_lock(&scp->mtx); + } + mtx_unlock(&scp->mtx); + + /* Transmit out data. */ + if ((devinfo->flags & MIDI_F_WRITING) != 0 && (csamidi_status(scp) & MIDSR_TBF) == 0) + csamidi_xmit(scp); + + mtx_unlock(&devinfo->flagqueue_mtx); + + /* Invoke the upper layer. */ + midi_intr(devinfo); +} + +static int +csamidi_callback(void *di, int reason) +{ + int unit; + sc_p scp; + mididev_info *d; + + d = (mididev_info *)di; + + mtx_assert(&d->flagqueue_mtx, MA_OWNED); + + if (d == NULL) { + MIDI_DEBUG(printf("csamidi_callback: device not configured.\n")); + return (ENXIO); + } + + unit = d->unit; + scp = d->softc; + + switch (reason & MIDI_CB_REASON_MASK) { + case MIDI_CB_START: + if ((reason & MIDI_CB_RD) != 0 && (d->flags & MIDI_F_READING) == 0) + /* Begin recording. */ + d->flags |= MIDI_F_READING; + if ((reason & MIDI_CB_WR) != 0 && (d->flags & MIDI_F_WRITING) == 0) + /* Start playing. */ + csamidi_startplay(scp); + break; + case MIDI_CB_STOP: + case MIDI_CB_ABORT: + if ((reason & MIDI_CB_RD) != 0 && (d->flags & MIDI_F_READING) != 0) + /* Stop recording. */ + d->flags &= ~MIDI_F_READING; + if ((reason & MIDI_CB_WR) != 0 && (d->flags & MIDI_F_WRITING) != 0) + /* Stop Playing. */ + d->flags &= ~MIDI_F_WRITING; + break; + } + + return (0); +} + +/* + * The functions below here are the libraries for the above ones. + */ + +/* + * Starts to play the data in the output queue. + */ +static void +csamidi_startplay(sc_p scp) +{ + mididev_info *devinfo; + + devinfo = scp->devinfo; + + mtx_assert(&devinfo->flagqueue_mtx, MA_OWNED); + + /* Can we play now? */ + if (devinfo->midi_dbuf_out.rl == 0) + return; + + devinfo->flags |= MIDI_F_WRITING; + csamidi_xmit(scp); +} + +static void +csamidi_xmit(sc_p scp) +{ + register mididev_info *devinfo; + register midi_dbuf *dbuf; + u_char c; + int leno; + + devinfo = scp->devinfo; + + mtx_assert(&devinfo->flagqueue_mtx, MA_OWNED); + + /* See which source to use. */ + if ((devinfo->flags & MIDI_F_PASSTHRU) == 0 || ((devinfo->flags & MIDI_F_BUSY) != 0 && (devinfo->fflags & FWRITE) != 0)) + dbuf = &devinfo->midi_dbuf_out; + else + dbuf = &devinfo->midi_dbuf_passthru; + + /* Transmit the data in the queue. */ + while ((devinfo->flags & MIDI_F_WRITING) != 0) { + /* Do we have the data to transmit? */ + if (dbuf->rl == 0) { + /* Stop playing. */ + devinfo->flags &= ~MIDI_F_WRITING; + break; + } else { + mtx_lock(&scp->mtx); + if ((csamidi_status(scp) & MIDSR_TBF) != 0) { + mtx_unlock(&scp->mtx); + break; + } + /* Send the data. */ + midibuf_output_intr(dbuf, &c, sizeof(c), &leno); + csamidi_writedata(scp, c); + /* We are playing now. */ + devinfo->flags |= MIDI_F_WRITING; + mtx_unlock(&scp->mtx); + } + } +} + +/* Reset midi. */ +static int +csamidi_reset(sc_p scp) +{ + int i, resp; + + mtx_lock(&scp->mtx); + + /* Reset the midi. */ + resp = 0; + for (i = 0 ; i < CSAMIDI_TRYDATA ; i++) { + resp = csamidi_command(scp, MIDCR_MRST); + if (resp == 0) + break; + } + if (resp != 0) { + mtx_unlock(&scp->mtx); + return (1); + } + for (i = 0 ; i < CSAMIDI_TRYDATA ; i++) { + resp = csamidi_command(scp, MIDCR_TXE | MIDCR_RXE | MIDCR_RIE | MIDCR_TIE); + if (resp == 0) + break; + } + if (resp != 0) + return (1); + + mtx_unlock(&scp->mtx); + + DELAY(CSAMIDI_DELAY); + + return (0); +} + +/* Reads the status. */ +static int +csamidi_status(sc_p scp) +{ + return csamidi_readio(scp, BA0_MIDSR); +} + +/* Writes a command. */ +static int +csamidi_command(sc_p scp, u_int32_t value) +{ + csamidi_writeio(scp, BA0_MIDCR, value); + + return (0); +} + +/* Reads a byte of data. */ +static int +csamidi_readdata(sc_p scp, u_int8_t *value) +{ + u_int status; + + if (value == NULL) + return (EINVAL); + + /* Is the interface ready to read? */ + status = csamidi_status(scp); + if ((status & MIDSR_RBE) != 0) + /* The interface is busy. */ + return (EAGAIN); + + *value = (u_int8_t)(csamidi_readio(scp, BA0_MIDRP) & 0xff); + + return (0); +} + +/* Writes a byte of data. */ +static int +csamidi_writedata(sc_p scp, u_int32_t value) +{ + u_int status; + + /* Is the interface ready to write? */ + status = csamidi_status(scp); + if ((status & MIDSR_TBF) != 0) + /* The interface is busy. */ + return (EAGAIN); + + csamidi_writeio(scp, BA0_MIDWP, value & 0xff); + + return (0); +} + +static u_int32_t +csamidi_readio(sc_p scp, u_long offset) +{ + if (offset < BA0_AC97_RESET) + return bus_space_read_4(rman_get_bustag(scp->io), rman_get_bushandle(scp->io), offset) & 0xffffffff; + else + return (0); +} + +static void +csamidi_writeio(sc_p scp, u_long offset, u_int32_t data) +{ + if (offset < BA0_AC97_RESET) + bus_space_write_4(rman_get_bustag(scp->io), rman_get_bushandle(scp->io), offset, data); +} + +/* Not used in this file. */ +#if notdef +static u_int32_t +csamidi_readmem(sc_p scp, u_long offset) +{ + return bus_space_read_4(rman_get_bustag(scp->mem), rman_get_bushandle(scp->mem), offset) & 0xffffffff; +} + +static void +csamidi_writemem(sc_p scp, u_long offset, u_int32_t data) +{ + bus_space_write_4(rman_get_bustag(scp->mem), rman_get_bushandle(scp->mem), offset, data); +} +#endif /* notdef */ + +/* Allocates resources. */ +static int +csamidi_allocres(sc_p scp, device_t dev) +{ + if (scp->io == NULL) { + scp->io = bus_alloc_resource(dev, SYS_RES_MEMORY, &scp->io_rid, 0, ~0, 1, RF_ACTIVE); + if (scp->io == NULL) + return (1); + } + if (scp->mem == NULL) { + scp->mem = bus_alloc_resource(dev, SYS_RES_MEMORY, &scp->mem_rid, 0, ~0, 1, RF_ACTIVE); + if (scp->mem == NULL) + return (1); + } + if (scp->irq == NULL) { + scp->irq = bus_alloc_resource(dev, SYS_RES_IRQ, &scp->irq_rid, 0, ~0, 1, RF_ACTIVE | RF_SHAREABLE); + if (scp->irq == NULL) + return (1); + } + + return (0); +} + +/* Releases resources. */ +static void +csamidi_releaseres(sc_p scp, device_t dev) +{ + if (scp->irq != NULL) { + bus_release_resource(dev, SYS_RES_IRQ, scp->irq_rid, scp->irq); + scp->irq = NULL; + } + if (scp->io != NULL) { + bus_release_resource(dev, SYS_RES_MEMORY, scp->io_rid, scp->io); + scp->io = NULL; + } + if (scp->mem != NULL) { + bus_release_resource(dev, SYS_RES_MEMORY, scp->mem_rid, scp->mem); + scp->mem = NULL; + } +} + +static device_method_t csamidi_methods[] = { + /* Device interface */ + DEVMETHOD(device_probe , csamidi_probe ), + DEVMETHOD(device_attach, csamidi_attach), + + { 0, 0 }, +}; + +static driver_t csamidi_driver = { + "midi", + csamidi_methods, + sizeof(struct csamidi_softc), +}; + +DRIVER_MODULE(csamidi, csa, csamidi_driver, midi_devclass, 0, 0); diff --git a/sys/dev/sound/pci/csapcm.c b/sys/dev/sound/pci/csapcm.c new file mode 100644 index 0000000..b445e48 --- /dev/null +++ b/sys/dev/sound/pci/csapcm.c @@ -0,0 +1,848 @@ +/* + * 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> +#include <dev/sound/pcm/ac97.h> +#include <dev/sound/chip.h> +#include <dev/sound/pci/csareg.h> +#include <dev/sound/pci/csavar.h> + +#include <pci/pcireg.h> +#include <pci/pcivar.h> + +SND_DECLARE_FILE("$FreeBSD$"); + +/* Buffer size on dma transfer. Fixed for CS416x. */ +#define CS461x_BUFFSIZE (4 * 1024) + +#define GOF_PER_SEC 200 + +/* device private data */ +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 { + 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; +}; + +/* -------------------------------------------------------------------- */ + +/* prototypes */ +static int csa_init(struct csa_info *); +static void csa_intr(void *); +static void csa_setplaysamplerate(csa_res *resp, u_long ulInRate); +static void csa_setcapturesamplerate(csa_res *resp, u_long ulOutRate); +static void csa_startplaydma(struct csa_info *csa); +static void csa_startcapturedma(struct csa_info *csa); +static void csa_stopplaydma(struct csa_info *csa); +static void csa_stopcapturedma(struct csa_info *csa); +static int csa_startdsp(csa_res *resp); +static int csa_allocres(struct csa_info *scp, device_t dev); +static void csa_releaseres(struct csa_info *scp, device_t dev); + +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 +}; +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 +}; +static struct pcmchan_caps csa_reccaps = {11025, 48000, csa_recfmt, 0}; + +/* -------------------------------------------------------------------- */ + +static int +csa_active(struct csa_info *csa, int run) +{ + int old, go; + + old = csa->active; + csa->active += run; + + if ((csa->active == 0 && old == 1) || (csa->active == 1 && old == 0)) { + go = csa->active; + if (csa->card->active) + return csa->card->active(go); + } + return 0; +} + +/* -------------------------------------------------------------------- */ +/* ac97 codec */ + +static int +csa_rdcd(kobj_t obj, void *devinfo, int regno) +{ + 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); + + 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; + + csa_active(csa, 1); + csa_writecodec(&csa->res, regno + BA0_AC97_RESET, data); + csa_active(csa, -1); + + return 0; +} + +static kobj_method_t csa_ac97_methods[] = { + 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); +} + +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); +} + +static void +csa_startplaydma(struct csa_info *csa) +{ + 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; + } +} + +static void +csa_startcapturedma(struct csa_info *csa) +{ + 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; + } +} + +static void +csa_stopplaydma(struct csa_info *csa) +{ + 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); + } + } +} + +static void +csa_stopcapturedma(struct csa_info *csa) +{ + 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); + } + } +} + +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); + + /* + * 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); +} + +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; +} + +/* -------------------------------------------------------------------- */ +/* channel interface */ + +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; + + ch->parent = csa; + ch->channel = c; + ch->buffer = b; + ch->dir = dir; + if (sndbuf_alloc(ch->buffer, csa->parent_dmat, CS461x_BUFFSIZE) == -1) return NULL; + return ch; +} + +static int +csachan_setformat(kobj_t obj, void *data, u_int32_t format) +{ + struct csa_chinfo *ch = data; + + ch->fmt = format; + return 0; +} + +static int +csachan_setspeed(kobj_t obj, void *data, u_int32_t speed) +{ + struct csa_chinfo *ch = data; + + 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; +} + +static int +csachan_trigger(kobj_t obj, void *data, int go) +{ + struct csa_chinfo *ch = data; + struct csa_info *csa = ch->parent; + + if (go == PCMTRIG_EMLDMAWR || go == PCMTRIG_EMLDMARD) + 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; + } + + 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; +} + +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 } +}; +CHANNEL_DECLARE(csachan); + +/* -------------------------------------------------------------------- */ +/* The interrupt handler */ +static void +csa_intr(void *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); +} + +/* -------------------------------------------------------------------- */ + +/* + * Probe and attach the card + */ + +static int +csa_init(struct csa_info *csa) +{ + csa_res *resp; + + 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); + + return 0; +} + +/* Allocates resources. */ +static int +csa_allocres(struct csa_info *csa, device_t dev) +{ + csa_res *resp; + + resp = &csa->res; + if (resp->io == NULL) { + resp->io = bus_alloc_resource(dev, SYS_RES_MEMORY, &resp->io_rid, 0, ~0, 1, RF_ACTIVE); + if (resp->io == NULL) + return (1); + } + if (resp->mem == NULL) { + resp->mem = bus_alloc_resource(dev, SYS_RES_MEMORY, &resp->mem_rid, 0, ~0, 1, RF_ACTIVE); + if (resp->mem == NULL) + return (1); + } + if (resp->irq == NULL) { + resp->irq = bus_alloc_resource(dev, SYS_RES_IRQ, &resp->irq_rid, 0, ~0, 1, 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, &csa->parent_dmat) != 0) + return (1); + + return (0); +} + +/* Releases resources. */ +static void +csa_releaseres(struct csa_info *csa, device_t dev) +{ + csa_res *resp; + + 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; + } + if (csa != NULL) { + free(csa, M_DEVBUF); + csa = NULL; + } +} + +static int +pcmcsa_probe(device_t dev) +{ + char *s; + struct sndcard_func *func; + + /* The parent device has already been probed. */ + + func = device_get_ivars(dev); + if (func == NULL || func->func != SCF_PCM) + return (ENXIO); + + s = "CS461x PCM Audio"; + + 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_MAPS; + resp->mem_rid = PCIR_MAPS + 4; + 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", rman_get_start(resp->irq)); + + /* Enable interrupt. */ + if (snd_setup_intr(dev, resp->irq, INTR_MPSAFE, 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); +} + +static int +pcmcsa_detach(device_t dev) +{ + int r; + struct csa_info *csa; + + r = pcm_unregister(dev); + if (r) + return r; + + csa = pcm_getdevinfo(dev); + csa_releaseres(csa, dev); + + 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), + + { 0, 0 }, +}; + +static driver_t pcmcsa_driver = { + "pcm", + pcmcsa_methods, + PCM_SOFTC_SIZE, +}; + +DRIVER_MODULE(snd_csapcm, csa, pcmcsa_driver, pcm_devclass, 0, 0); +MODULE_DEPEND(snd_csapcm, snd_pcm, PCM_MINVER, PCM_PREFVER, PCM_MAXVER); +MODULE_DEPEND(snd_csapcm, snd_csa, 1, 1, 1); +MODULE_VERSION(snd_csapcm, 1); diff --git a/sys/dev/sound/pci/csareg.h b/sys/dev/sound/pci/csareg.h new file mode 100644 index 0000000..8ed292a --- /dev/null +++ b/sys/dev/sound/pci/csareg.h @@ -0,0 +1,1954 @@ +/*- + * 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$ + */ + +#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 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 +#define BA0_DMSR 0x00000100L +#define BA0_HSAR 0x00000110L +#define BA0_HDAR 0x00000114L +#define BA0_HDMR 0x00000118L +#define BA0_HDCR 0x0000011CL +#define BA0_PFMC 0x00000200L +#define BA0_PFCV1 0x00000204L +#define BA0_PFCV2 0x00000208L +#define BA0_PCICFG00 0x00000300L +#define BA0_PCICFG04 0x00000304L +#define BA0_PCICFG08 0x00000308L +#define BA0_PCICFG0C 0x0000030CL +#define BA0_PCICFG10 0x00000310L +#define BA0_PCICFG14 0x00000314L +#define BA0_PCICFG18 0x00000318L +#define BA0_PCICFG1C 0x0000031CL +#define BA0_PCICFG20 0x00000320L +#define BA0_PCICFG24 0x00000324L +#define BA0_PCICFG28 0x00000328L +#define BA0_PCICFG2C 0x0000032CL +#define BA0_PCICFG30 0x00000330L +#define BA0_PCICFG34 0x00000334L +#define BA0_PCICFG38 0x00000338L +#define BA0_PCICFG3C 0x0000033CL +#define BA0_CLKCR1 0x00000400L +#define BA0_CLKCR2 0x00000404L +#define BA0_PLLM 0x00000408L +#define BA0_PLLCC 0x0000040CL +#define BA0_FRR 0x00000410L +#define BA0_CFL1 0x00000414L +#define BA0_CFL2 0x00000418L +#define BA0_SERMC1 0x00000420L +#define BA0_SERMC2 0x00000424L +#define BA0_SERC1 0x00000428L +#define BA0_SERC2 0x0000042CL +#define BA0_SERC3 0x00000430L +#define BA0_SERC4 0x00000434L +#define BA0_SERC5 0x00000438L +#define BA0_SERBSP 0x0000043CL +#define BA0_SERBST 0x00000440L +#define BA0_SERBCM 0x00000444L +#define BA0_SERBAD 0x00000448L +#define BA0_SERBCF 0x0000044CL +#define BA0_SERBWP 0x00000450L +#define BA0_SERBRP 0x00000454L +#ifndef NO_CS4612 +#define BA0_ASER_FADDR 0x00000458L +#endif +#define BA0_ACCTL 0x00000460L +#define BA0_ACSTS 0x00000464L +#define BA0_ACOSV 0x00000468L +#define BA0_ACCAD 0x0000046CL +#define BA0_ACCDA 0x00000470L +#define BA0_ACISV 0x00000474L +#define BA0_ACSAD 0x00000478L +#define BA0_ACSDA 0x0000047CL +#define BA0_JSPT 0x00000480L +#define BA0_JSCTL 0x00000484L +#define BA0_JSC1 0x00000488L +#define BA0_JSC2 0x0000048CL +#define BA0_MIDCR 0x00000490L +#define BA0_MIDSR 0x00000494L +#define BA0_MIDWP 0x00000498L +#define BA0_MIDRP 0x0000049CL +#define BA0_JSIO 0x000004A0L +#ifndef NO_CS4612 +#define BA0_ASER_MASTER 0x000004A4L +#endif +#define BA0_CFGI 0x000004B0L +#define BA0_SSVID 0x000004B4L +#define BA0_GPIOR 0x000004B8L +#ifndef NO_CS4612 +#define BA0_EGPIODR 0x000004BCL +#define BA0_EGPIOPTR 0x000004C0L +#define BA0_EGPIOTR 0x000004C4L +#define BA0_EGPIOWR 0x000004C8L +#define BA0_EGPIOSR 0x000004CCL +#define BA0_SERC6 0x000004D0L +#define BA0_SERC7 0x000004D4L +#define BA0_SERACC 0x000004D8L +#define BA0_ACCTL2 0x000004E0L +#define BA0_ACSTS2 0x000004E4L +#define BA0_ACOSV2 0x000004E8L +#define BA0_ACCAD2 0x000004ECL +#define BA0_ACCDA2 0x000004F0L +#define BA0_ACISV2 0x000004F4L +#define BA0_ACSAD2 0x000004F8L +#define BA0_ACSDA2 0x000004FCL +#define BA0_IOTAC0 0x00000500L +#define BA0_IOTAC1 0x00000504L +#define BA0_IOTAC2 0x00000508L +#define BA0_IOTAC3 0x0000050CL +#define BA0_IOTAC4 0x00000510L +#define BA0_IOTAC5 0x00000514L +#define BA0_IOTAC6 0x00000518L +#define BA0_IOTAC7 0x0000051CL +#define BA0_IOTAC8 0x00000520L +#define BA0_IOTAC9 0x00000524L +#define BA0_IOTAC10 0x00000528L +#define BA0_IOTAC11 0x0000052CL +#define BA0_IOTFR0 0x00000540L +#define BA0_IOTFR1 0x00000544L +#define BA0_IOTFR2 0x00000548L +#define BA0_IOTFR3 0x0000054CL +#define BA0_IOTFR4 0x00000550L +#define BA0_IOTFR5 0x00000554L +#define BA0_IOTFR6 0x00000558L +#define BA0_IOTFR7 0x0000055CL +#define BA0_IOTFIFO 0x00000580L +#define BA0_IOTRRD 0x00000584L +#define BA0_IOTFP 0x00000588L +#define BA0_IOTCR 0x0000058CL +#define BA0_DPCID 0x00000590L +#define BA0_DPCIA 0x00000594L +#define BA0_DPCIC 0x00000598L +#define BA0_PCPCIR 0x00000600L +#define BA0_PCPCIG 0x00000604L +#define BA0_PCPCIEN 0x00000608L +#define BA0_EPCIPMC 0x00000610L +#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. + * + *****************************************************************************/ +#define BA0_AC97_RESET 0x00001000L +#define BA0_AC97_MASTER_VOLUME 0x00001002L +#define BA0_AC97_HEADPHONE_VOLUME 0x00001004L +#define BA0_AC97_MASTER_VOLUME_MONO 0x00001006L +#define BA0_AC97_MASTER_TONE 0x00001008L +#define BA0_AC97_PC_BEEP_VOLUME 0x0000100AL +#define BA0_AC97_PHONE_VOLUME 0x0000100CL +#define BA0_AC97_MIC_VOLUME 0x0000100EL +#define BA0_AC97_LINE_IN_VOLUME 0x00001010L +#define BA0_AC97_CD_VOLUME 0x00001012L +#define BA0_AC97_VIDEO_VOLUME 0x00001014L +#define BA0_AC97_AUX_VOLUME 0x00001016L +#define BA0_AC97_PCM_OUT_VOLUME 0x00001018L +#define BA0_AC97_RECORD_SELECT 0x0000101AL +#define BA0_AC97_RECORD_GAIN 0x0000101CL +#define BA0_AC97_RECORD_GAIN_MIC 0x0000101EL +#define BA0_AC97_GENERAL_PURPOSE 0x00001020L +#define BA0_AC97_3D_CONTROL 0x00001022L +#define BA0_AC97_MODEM_RATE 0x00001024L +#define BA0_AC97_POWERDOWN 0x00001026L +#define BA0_AC97_RESERVED_28 0x00001028L +#define BA0_AC97_RESERVED_2A 0x0000102AL +#define BA0_AC97_RESERVED_2C 0x0000102CL +#define BA0_AC97_RESERVED_2E 0x0000102EL +#define BA0_AC97_RESERVED_30 0x00001030L +#define BA0_AC97_RESERVED_32 0x00001032L +#define BA0_AC97_RESERVED_34 0x00001034L +#define BA0_AC97_RESERVED_36 0x00001036L +#define BA0_AC97_RESERVED_38 0x00001038L +#define BA0_AC97_RESERVED_3A 0x0000103AL +#define BA0_AC97_RESERVED_3C 0x0000103CL +#define BA0_AC97_RESERVED_3E 0x0000103EL +#define BA0_AC97_RESERVED_40 0x00001040L +#define BA0_AC97_RESERVED_42 0x00001042L +#define BA0_AC97_RESERVED_44 0x00001044L +#define BA0_AC97_RESERVED_46 0x00001046L +#define BA0_AC97_RESERVED_48 0x00001048L +#define BA0_AC97_RESERVED_4A 0x0000104AL +#define BA0_AC97_RESERVED_4C 0x0000104CL +#define BA0_AC97_RESERVED_4E 0x0000104EL +#define BA0_AC97_RESERVED_50 0x00001050L +#define BA0_AC97_RESERVED_52 0x00001052L +#define BA0_AC97_RESERVED_54 0x00001054L +#define BA0_AC97_RESERVED_56 0x00001056L +#define BA0_AC97_RESERVED_58 0x00001058L +#define BA0_AC97_VENDOR_RESERVED_5A 0x0000105AL +#define BA0_AC97_VENDOR_RESERVED_5C 0x0000105CL +#define BA0_AC97_VENDOR_RESERVED_5E 0x0000105EL +#define BA0_AC97_VENDOR_RESERVED_60 0x00001060L +#define BA0_AC97_VENDOR_RESERVED_62 0x00001062L +#define BA0_AC97_VENDOR_RESERVED_64 0x00001064L +#define BA0_AC97_VENDOR_RESERVED_66 0x00001066L +#define BA0_AC97_VENDOR_RESERVED_68 0x00001068L +#define BA0_AC97_VENDOR_RESERVED_6A 0x0000106AL +#define BA0_AC97_VENDOR_RESERVED_6C 0x0000106CL +#define BA0_AC97_VENDOR_RESERVED_6E 0x0000106EL +#define BA0_AC97_VENDOR_RESERVED_70 0x00001070L +#define BA0_AC97_VENDOR_RESERVED_72 0x00001072L +#define BA0_AC97_VENDOR_RESERVED_74 0x00001074L +#define BA0_AC97_VENDOR_RESERVED_76 0x00001076L +#define BA0_AC97_VENDOR_RESERVED_78 0x00001078L +#define BA0_AC97_VENDOR_RESERVED_7A 0x0000107AL +#define BA0_AC97_VENDOR_ID1 0x0000107CL +#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. + * + *****************************************************************************/ +#define BA1_SP_DMEM0 0x00000000L +#define BA1_SP_DMEM1 0x00010000L +#define BA1_SP_PMEM 0x00020000L +#define BA1_SPCR 0x00030000L +#define BA1_DREG 0x00030004L +#define BA1_DSRWP 0x00030008L +#define BA1_TWPR 0x0003000CL +#define BA1_SPWR 0x00030010L +#define BA1_SPIR 0x00030014L +#define BA1_FGR1 0x00030020L +#define BA1_SPCS 0x00030028L +#define BA1_SDSR 0x0003002CL +#define BA1_FRMT 0x00030030L +#define BA1_FRCC 0x00030034L +#define BA1_FRSC 0x00030038L +#define BA1_OMNI_MEM 0x000E0000L + +/***************************************************************************** + * + * 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 +#define PI_MAX_LATENCY_MASK 0xFF000000L +#define PI_LINE_SHIFT 0L +#define PI_PIN_SHIFT 8L +#define PI_MIN_GRANT_SHIFT 16L +#define PI_MAX_LATENCY_SHIFT 24L + +/***************************************************************************** + * + * 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 +#define HISR_VC2 0x00000004L +#define HISR_VC3 0x00000008L +#define HISR_VC4 0x00000010L +#define HISR_VC5 0x00000020L +#define HISR_VC6 0x00000040L +#define HISR_VC7 0x00000080L +#define HISR_VC8 0x00000100L +#define HISR_VC9 0x00000200L +#define HISR_VC10 0x00000400L +#define HISR_VC11 0x00000800L +#define HISR_VC12 0x00001000L +#define HISR_VC13 0x00002000L +#define HISR_VC14 0x00004000L +#define HISR_VC15 0x00008000L +#define HISR_INT0 0x00010000L +#define HISR_INT1 0x00020000L +#define HISR_DMAI 0x00040000L +#define HISR_FROVR 0x00080000L +#define HISR_MIDI 0x00100000L +#ifdef NO_CS4612 +#define HISR_RESERVED 0x0FE00000L +#else +#define HISR_SBINT 0x00200000L +#define HISR_RESERVED 0x0FC00000L +#endif +#define HISR_H0P 0x40000000L +#define HISR_INTENA 0x80000000L + +/***************************************************************************** + * + * 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 +#define HSR0_VC18 0x00000004L +#define HSR0_VC19 0x00000008L +#define HSR0_VC20 0x00000010L +#define HSR0_VC21 0x00000020L +#define HSR0_VC22 0x00000040L +#define HSR0_VC23 0x00000080L +#define HSR0_VC24 0x00000100L +#define HSR0_VC25 0x00000200L +#define HSR0_VC26 0x00000400L +#define HSR0_VC27 0x00000800L +#define HSR0_VC28 0x00001000L +#define HSR0_VC29 0x00002000L +#define HSR0_VC30 0x00004000L +#define HSR0_VC31 0x00008000L +#define HSR0_VC32 0x00010000L +#define HSR0_VC33 0x00020000L +#define HSR0_VC34 0x00040000L +#define HSR0_VC35 0x00080000L +#define HSR0_VC36 0x00100000L +#define HSR0_VC37 0x00200000L +#define HSR0_VC38 0x00400000L +#define HSR0_VC39 0x00800000L +#define HSR0_VC40 0x01000000L +#define HSR0_VC41 0x02000000L +#define HSR0_VC42 0x04000000L +#define HSR0_VC43 0x08000000L +#define HSR0_VC44 0x10000000L +#define HSR0_VC45 0x20000000L +#define HSR0_VC46 0x40000000L +#define HSR0_VC47 0x80000000L + +/***************************************************************************** + * + * 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. + * + *****************************************************************************/ +#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. + * + *****************************************************************************/ +#define HSAR_HOST_ADDR_MASK 0xFFFFFFFFL +#define HSAR_DSP_ADDR_MASK 0x0000FFFFL +#define HSAR_MEMID_MASK 0x000F0000L +#define HSAR_MEMID_SP_DMEM0 0x00000000L +#define HSAR_MEMID_SP_DMEM1 0x00010000L +#define HSAR_MEMID_SP_PMEM 0x00020000L +#define HSAR_MEMID_SP_DEBUG 0x00030000L +#define HSAR_MEMID_OMNI_MEM 0x000E0000L +#define HSAR_END 0x40000000L +#define HSAR_ERR 0x80000000L + +/***************************************************************************** + * + * 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 +#define HDAR_MEMID_SP_DMEM0 0x00000000L +#define HDAR_MEMID_SP_DMEM1 0x00010000L +#define HDAR_MEMID_SP_PMEM 0x00020000L +#define HDAR_MEMID_SP_DEBUG 0x00030000L +#define HDAR_MEMID_OMNI_MEM 0x000E0000L +#define HDAR_END 0x40000000L +#define HDAR_ERR 0x80000000L + +/***************************************************************************** + * + * 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 +#define HDMR_AC_B_L 0x00004000L +#define HDMR_AC_S_U 0x00008000L + +/***************************************************************************** + * + * 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 +#define HDCR_WBD 0x00400000L +#define HDCR_WBS 0x00800000L +#define HDCR_DMS_MASK 0x07000000L +#define HDCR_DMS_LINEAR 0x00000000L +#define HDCR_DMS_16_DWORDS 0x01000000L +#define HDCR_DMS_32_DWORDS 0x02000000L +#define HDCR_DMS_64_DWORDS 0x03000000L +#define HDCR_DMS_128_DWORDS 0x04000000L +#define HDCR_DMS_256_DWORDS 0x05000000L +#define HDCR_DMS_512_DWORDS 0x06000000L +#define HDCR_DMS_1024_DWORDS 0x07000000L +#define HDCR_DH 0x08000000L +#define HDCR_SMS_MASK 0x70000000L +#define HDCR_SMS_LINEAR 0x00000000L +#define HDCR_SMS_16_DWORDS 0x10000000L +#define HDCR_SMS_32_DWORDS 0x20000000L +#define HDCR_SMS_64_DWORDS 0x30000000L +#define HDCR_SMS_128_DWORDS 0x40000000L +#define HDCR_SMS_256_DWORDS 0x50000000L +#define HDCR_SMS_512_DWORDS 0x60000000L +#define HDCR_SMS_1024_DWORDS 0x70000000L +#define HDCR_SH 0x80000000L +#define HDCR_COUNT_SHIFT 0L + +/***************************************************************************** + * + * 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 +#define PFMC_C2SS_MASK 0x001F0000L +#define PFMC_C2EV 0x00200000L +#define PFMC_C2RS 0x80000000L +#define PFMC_C1SS_SHIFT 0L +#define PFMC_C2SS_SHIFT 16L +#define PFMC_BUS_GRANT 0L +#define PFMC_GRANT_AFTER_REQ 1L +#define PFMC_TRANSACTION 2L +#define PFMC_DWORD_TRANSFER 3L +#define PFMC_SLAVE_READ 4L +#define PFMC_SLAVE_WRITE 5L +#define PFMC_PREEMPTION 6L +#define PFMC_DISCONNECT_RETRY 7L +#define PFMC_INTERRUPT 8L +#define PFMC_BUS_OWNERSHIP 9L +#define PFMC_TRANSACTION_LAG 10L +#define PFMC_PCI_CLOCK 11L +#define PFMC_SERIAL_CLOCK 12L +#define PFMC_SP_CLOCK 13L + +/***************************************************************************** + * + * 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. + * + *****************************************************************************/ +#define PFCV2_PC2V_MASK 0xFFFFFFFFL +#define PFCV2_PC2V_SHIFT 0L + +/***************************************************************************** + * + * 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 +#define CLKCR1_PLLSS_SERIAL 0x00000000L +#define CLKCR1_PLLSS_CRYSTAL 0x00000004L +#define CLKCR1_PLLSS_PCI 0x00000008L +#define CLKCR1_PLLSS_RESERVED 0x0000000CL +#define CLKCR1_PLLP 0x00000010L +#define CLKCR1_SWCE 0x00000020L +#define CLKCR1_PLLOS 0x00000040L + +/***************************************************************************** + * + * 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 +#define CLKCR2_PDIVS_4 0x00000004L +#define CLKCR2_PDIVS_7 0x00000007L +#define CLKCR2_PDIVS_8 0x00000008L +#define CLKCR2_PDIVS_16 0x00000000L + +/***************************************************************************** + * + * 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. + * + *****************************************************************************/ +#define PLLCC_CDR_MASK 0x00000007L +#ifndef NO_CS4610 +#define PLLCC_CDR_240_350_MHZ 0x00000000L +#define PLLCC_CDR_184_265_MHZ 0x00000001L +#define PLLCC_CDR_144_205_MHZ 0x00000002L +#define PLLCC_CDR_111_160_MHZ 0x00000003L +#define PLLCC_CDR_87_123_MHZ 0x00000004L +#define PLLCC_CDR_67_96_MHZ 0x00000005L +#define PLLCC_CDR_52_74_MHZ 0x00000006L +#define PLLCC_CDR_45_58_MHZ 0x00000007L +#endif +#ifndef NO_CS4612 +#define PLLCC_CDR_271_398_MHZ 0x00000000L +#define PLLCC_CDR_227_330_MHZ 0x00000001L +#define PLLCC_CDR_167_239_MHZ 0x00000002L +#define PLLCC_CDR_150_215_MHZ 0x00000003L +#define PLLCC_CDR_107_154_MHZ 0x00000004L +#define PLLCC_CDR_98_140_MHZ 0x00000005L +#define PLLCC_CDR_73_104_MHZ 0x00000006L +#define PLLCC_CDR_63_90_MHZ 0x00000007L +#endif +#define PLLCC_LPF_MASK 0x000000F8L +#ifndef NO_CS4610 +#define PLLCC_LPF_23850_60000_KHZ 0x00000000L +#define PLLCC_LPF_7960_26290_KHZ 0x00000008L +#define PLLCC_LPF_4160_10980_KHZ 0x00000018L +#define PLLCC_LPF_1740_4580_KHZ 0x00000038L +#define PLLCC_LPF_724_1910_KHZ 0x00000078L +#define PLLCC_LPF_317_798_KHZ 0x000000F8L +#endif +#ifndef NO_CS4612 +#define PLLCC_LPF_25580_64530_KHZ 0x00000000L +#define PLLCC_LPF_14360_37270_KHZ 0x00000008L +#define PLLCC_LPF_6100_16020_KHZ 0x00000018L +#define PLLCC_LPF_2540_6690_KHZ 0x00000038L +#define PLLCC_LPF_1050_2780_KHZ 0x00000078L +#define PLLCC_LPF_450_1160_KHZ 0x000000F8L +#endif + +/***************************************************************************** + * + * 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 +#define FRR_CFOP_MASK 0x000000E0L +#else +#define FRR_CFOP_MASK 0x00000FE0L +#endif +#define FRR_CFOP_NOT_DVD 0x00000020L +#define FRR_CFOP_A3D 0x00000040L +#define FRR_CFOP_128_PIN 0x00000080L +#ifndef NO_CS4612 +#define FRR_CFOP_CS4280 0x00000800L +#endif +#define FRR_FAB_SHIFT 0L +#define FRR_MASK_SHIFT 2L +#define FRR_CFOP_SHIFT 5L + +/***************************************************************************** + * + * 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 +#define CFL1_CLOCK_SOURCE_CRYSTAL 0x00000002L +#define CFL1_CLOCK_SOURCE_DUAL_AC97 0x00000003L +#define CFL1_VALID_DATA_MASK 0x000000FFL + +/***************************************************************************** + * + * 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. + * + *****************************************************************************/ +#define SERMC1_MSPE 0x00000001L +#define SERMC1_PTC_MASK 0x0000000EL +#define SERMC1_PTC_CS423X 0x00000000L +#define SERMC1_PTC_AC97 0x00000002L +#define SERMC1_PTC_DAC 0x00000004L +#define SERMC1_PLB 0x00000010L +#define SERMC1_XLB 0x00000020L + +/***************************************************************************** + * + * 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. + * + *****************************************************************************/ +#define SERC1_SO1EN 0x00000001L +#define SERC1_SO1F_MASK 0x0000000EL +#define SERC1_SO1F_CS423X 0x00000000L +#define SERC1_SO1F_AC97 0x00000002L +#define SERC1_SO1F_DAC 0x00000004L +#define SERC1_SO1F_SPDIF 0x00000006L + +/***************************************************************************** + * + * 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 +#define SERC2_SI1F_AC97 0x00000002L +#define SERC2_SI1F_ADC 0x00000004L +#define SERC2_SI1F_SPDIF 0x00000006L + +/***************************************************************************** + * + * 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. + * + *****************************************************************************/ +#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. + * + *****************************************************************************/ +#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. + * + *****************************************************************************/ +#define SERBSP_FSP_MASK 0x0000000FL +#define SERBSP_FSP_SHIFT 0L + +/***************************************************************************** + * + * 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. + * + *****************************************************************************/ +#define SERBCM_RDC 0x00000001L +#define SERBCM_WRC 0x00000002L + +/***************************************************************************** + * + * The following defines are for the flags in the serial port backdoor address + * register. + * + *****************************************************************************/ +#ifdef NO_CS4612 +#define SERBAD_FAD_MASK 0x000000FFL +#else +#define SERBAD_FAD_MASK 0x000001FFL +#endif +#define SERBAD_FAD_SHIFT 0L + +/***************************************************************************** + * + * 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. + * + *****************************************************************************/ +#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. + * + *****************************************************************************/ +#define SERBRP_FRD_MASK 0x000FFFFFL +#define SERBRP_FRD_SHIFT 0L + +/***************************************************************************** + * + * 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 +#define ASER_FADDR_A2_MASK 0x01FF0000L +#define ASER_FADDR_EN2 0x80000000L +#define ASER_FADDR_A1_SHIFT 0L +#define ASER_FADDR_A2_SHIFT 16L +#endif + +/***************************************************************************** + * + * The following defines are for the flags in the AC97 control register. + * + *****************************************************************************/ +#define ACCTL_RSTN 0x00000001L +#define ACCTL_ESYN 0x00000002L +#define ACCTL_VFRM 0x00000004L +#define ACCTL_DCV 0x00000008L +#define ACCTL_CRW 0x00000010L +#define ACCTL_ASYN 0x00000020L +#ifndef NO_CS4612 +#define ACCTL_TC 0x00000040L +#endif + +/***************************************************************************** + * + * The following defines are for the flags in the AC97 status register. + * + *****************************************************************************/ +#define ACSTS_CRDY 0x00000001L +#define ACSTS_VSTS 0x00000002L +#ifndef NO_CS4612 +#define ACSTS_WKUP 0x00000004L +#endif + +/***************************************************************************** + * + * 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 +#define ACOSV_SLV6 0x00000008L +#define ACOSV_SLV7 0x00000010L +#define ACOSV_SLV8 0x00000020L +#define ACOSV_SLV9 0x00000040L +#define ACOSV_SLV10 0x00000080L +#define ACOSV_SLV11 0x00000100L +#define ACOSV_SLV12 0x00000200L + +/***************************************************************************** + * + * 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. + * + *****************************************************************************/ +#define ACCDA_CD_MASK 0x0000FFFFL +#define ACCDA_CD_SHIFT 0L + +/***************************************************************************** + * + * 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 +#define ACISV_ISV6 0x00000008L +#define ACISV_ISV7 0x00000010L +#define ACISV_ISV8 0x00000020L +#define ACISV_ISV9 0x00000040L +#define ACISV_ISV10 0x00000080L +#define ACISV_ISV11 0x00000100L +#define ACISV_ISV12 0x00000200L + +/***************************************************************************** + * + * 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. + * + *****************************************************************************/ +#define ACSDA_SD_MASK 0x0000FFFFL +#define ACSDA_SD_SHIFT 0L + +/***************************************************************************** + * + * 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 +#define JSPT_CBY 0x00000008L +#define JSPT_BA1 0x00000010L +#define JSPT_BA2 0x00000020L +#define JSPT_BB1 0x00000040L +#define JSPT_BB2 0x00000080L + +/***************************************************************************** + * + * 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 +#define JSCTL_SP_MEDIUM_FAST 0x00000002L +#define JSCTL_SP_FAST 0x00000003L +#define JSCTL_ARE 0x00000004L + +/***************************************************************************** + * + * 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. + * + *****************************************************************************/ +#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. + * + *****************************************************************************/ +#define MIDCR_TXE 0x00000001L +#define MIDCR_RXE 0x00000002L +#define MIDCR_RIE 0x00000004L +#define MIDCR_TIE 0x00000008L +#define MIDCR_MLB 0x00000010L +#define MIDCR_MRST 0x00000020L + +/***************************************************************************** + * + * 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. + * + *****************************************************************************/ +#define MIDWP_MWD_MASK 0x000000FFL +#define MIDWP_MWD_SHIFT 0L + +/***************************************************************************** + * + * 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. + * + *****************************************************************************/ +#define JSIO_DAX 0x00000001L +#define JSIO_DAY 0x00000002L +#define JSIO_DBX 0x00000004L +#define JSIO_DBY 0x00000008L +#define JSIO_AXOE 0x00000010L +#define JSIO_AYOE 0x00000020L +#define JSIO_BXOE 0x00000040L +#define JSIO_BYOE 0x00000080L + +/***************************************************************************** + * + * 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. + * + *****************************************************************************/ +#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. + * + *****************************************************************************/ +#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. + * + *****************************************************************************/ +#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. + * + *****************************************************************************/ +#ifndef NO_CS4612 +#define EGPIODR_GPOE0 0x00000001L +#define EGPIODR_GPOE1 0x00000002L +#define EGPIODR_GPOE2 0x00000004L +#define EGPIODR_GPOE3 0x00000008L +#define EGPIODR_GPOE4 0x00000010L +#define EGPIODR_GPOE5 0x00000020L +#define EGPIODR_GPOE6 0x00000040L +#define EGPIODR_GPOE7 0x00000080L +#define EGPIODR_GPOE8 0x00000100L +#endif + +/***************************************************************************** + * + * 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 +#define EGPIOPTR_GPPT2 0x00000004L +#define EGPIOPTR_GPPT3 0x00000008L +#define EGPIOPTR_GPPT4 0x00000010L +#define EGPIOPTR_GPPT5 0x00000020L +#define EGPIOPTR_GPPT6 0x00000040L +#define EGPIOPTR_GPPT7 0x00000080L +#define EGPIOPTR_GPPT8 0x00000100L +#endif + +/***************************************************************************** + * + * 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 +#define EGPIOTR_GPS2 0x00000004L +#define EGPIOTR_GPS3 0x00000008L +#define EGPIOTR_GPS4 0x00000010L +#define EGPIOTR_GPS5 0x00000020L +#define EGPIOTR_GPS6 0x00000040L +#define EGPIOTR_GPS7 0x00000080L +#define EGPIOTR_GPS8 0x00000100L +#endif + +/***************************************************************************** + * + * 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 +#define EGPIOWR_GPW2 0x00000004L +#define EGPIOWR_GPW3 0x00000008L +#define EGPIOWR_GPW4 0x00000010L +#define EGPIOWR_GPW5 0x00000020L +#define EGPIOWR_GPW6 0x00000040L +#define EGPIOWR_GPW7 0x00000080L +#define EGPIOWR_GPW8 0x00000100L +#endif + +/***************************************************************************** + * + * 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 +#define EGPIOSR_GPS2 0x00000004L +#define EGPIOSR_GPS3 0x00000008L +#define EGPIOSR_GPS4 0x00000010L +#define EGPIOSR_GPS5 0x00000020L +#define EGPIOSR_GPS6 0x00000040L +#define EGPIOSR_GPS7 0x00000080L +#define EGPIOSR_GPS8 0x00000100L +#endif + +/***************************************************************************** + * + * 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. + * + *****************************************************************************/ +#ifndef NO_CS4612 +#define SERC7_ASDI2EN 0x00000001L +#define SERC7_POSILB 0x00000002L +#define SERC7_SIPOLB 0x00000004L +#define SERC7_SOSILB 0x00000008L +#define SERC7_SISOLB 0x00000010L +#endif + +/***************************************************************************** + * + * 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 +#define SERACC_CODEC_TYPE_2_0 0x00000001L +#define SERACC_TWO_CODECS 0x00000002L +#define SERACC_MDM 0x00000004L +#define SERACC_HSP 0x00000008L +#endif + +/***************************************************************************** + * + * The following defines are for the flags in the AC97 control register 2. + * + *****************************************************************************/ +#ifndef NO_CS4612 +#define ACCTL2_RSTN 0x00000001L +#define ACCTL2_ESYN 0x00000002L +#define ACCTL2_VFRM 0x00000004L +#define ACCTL2_DCV 0x00000008L +#define ACCTL2_CRW 0x00000010L +#define ACCTL2_ASYN 0x00000020L +#endif + +/***************************************************************************** + * + * 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. + * + *****************************************************************************/ +#ifndef NO_CS4612 +#define ACOSV2_SLV3 0x00000001L +#define ACOSV2_SLV4 0x00000002L +#define ACOSV2_SLV5 0x00000004L +#define ACOSV2_SLV6 0x00000008L +#define ACOSV2_SLV7 0x00000010L +#define ACOSV2_SLV8 0x00000020L +#define ACOSV2_SLV9 0x00000040L +#define ACOSV2_SLV10 0x00000080L +#define ACOSV2_SLV11 0x00000100L +#define ACOSV2_SLV12 0x00000200L +#endif + +/***************************************************************************** + * + * 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. + * + *****************************************************************************/ +#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. + * + *****************************************************************************/ +#ifndef NO_CS4612 +#define ACISV2_ISV3 0x00000001L +#define ACISV2_ISV4 0x00000002L +#define ACISV2_ISV5 0x00000004L +#define ACISV2_ISV6 0x00000008L +#define ACISV2_ISV7 0x00000010L +#define ACISV2_ISV8 0x00000020L +#define ACISV2_ISV9 0x00000040L +#define ACISV2_ISV10 0x00000080L +#define ACISV2_ISV11 0x00000100L +#define ACISV2_ISV12 0x00000200L +#endif + +/***************************************************************************** + * + * 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. + * + *****************************************************************************/ +#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). + * + *****************************************************************************/ +#ifndef NO_CS4612 +#define IOTAC_SA_MASK 0x0000FFFFL +#define IOTAC_MSK_MASK 0x000F0000L +#define IOTAC_IODC_MASK 0x06000000L +#define IOTAC_IODC_16_BIT 0x00000000L +#define IOTAC_IODC_10_BIT 0x02000000L +#define IOTAC_IODC_12_BIT 0x04000000L +#define IOTAC_WSPI 0x08000000L +#define IOTAC_RSPI 0x10000000L +#define IOTAC_WSE 0x20000000L +#define IOTAC_WE 0x40000000L +#define IOTAC_RE 0x80000000L +#define IOTAC_SA_SHIFT 0L +#define IOTAC_MSK_SHIFT 16L +#endif + +/***************************************************************************** + * + * 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 +#define IOTFR_R_MASK 0x0F000000L +#define IOTFR_ALL 0x40000000L +#define IOTFR_VL 0x80000000L +#define IOTFR_D_SHIFT 0L +#define IOTFR_A_SHIFT 16L +#define IOTFR_R_SHIFT 24L +#endif + +/***************************************************************************** + * + * 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 +#define IOTFIFO_OF 0x40000000L +#define IOTFIFO_SPIOF 0x80000000L +#define IOTFIFO_BA_SHIFT 0L +#define IOTFIFO_S_SHIFT 16L +#endif + +/***************************************************************************** + * + * 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 +#define IOTRRD_D_SHIFT 0L +#endif + +/***************************************************************************** + * + * 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 +#define IOTFP_CA_SHIFT 0L +#define IOTFP_PA_SHIFT 16L +#endif + +/***************************************************************************** + * + * 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 +#define IOTCR_SRV 0x00000004L +#define IOTCR_DTI 0x00000008L +#define IOTCR_DFI 0x00000010L +#define IOTCR_DDP 0x00000020L +#define IOTCR_JTE 0x00000040L +#define IOTCR_PPE 0x00000080L +#endif + +/***************************************************************************** + * + * 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. + * + *****************************************************************************/ +#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. + * + *****************************************************************************/ +#ifndef NO_CS4612 +#define DPCIC_C_MASK 0x0000000FL +#define DPCIC_C_IOREAD 0x00000002L +#define DPCIC_C_IOWRITE 0x00000003L +#define DPCIC_BE_MASK 0x000000F0L +#endif + +/***************************************************************************** + * + * 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 +#define PCPCIR_REQ 0x00008000L +#define PCPCIR_RDC_SHIFT 0L +#define PCPCIR_C_SHIFT 12L +#endif + +/***************************************************************************** + * + * 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 +#define PCPCIG_GDC_SHIFT 0L +#endif + +/***************************************************************************** + * + * 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. + * + *****************************************************************************/ +#ifndef NO_CS4612 +#define EPCIPMC_GWU 0x00000001L +#define EPCIPMC_FSPC 0x00000002L +#endif + +/***************************************************************************** + * + * The following defines are for the flags in the SP control register. + * + *****************************************************************************/ +#define SPCR_RUN 0x00000001L +#define SPCR_STPFR 0x00000002L +#define SPCR_RUNFR 0x00000004L +#define SPCR_TICK 0x00000008L +#define SPCR_DRQEN 0x00000020L +#define SPCR_RSTSP 0x00000040L +#define SPCR_OREN 0x00000080L +#ifndef NO_CS4612 +#define SPCR_PCIINT 0x00000100L +#define SPCR_OINTD 0x00000200L +#define SPCR_CRE 0x00008000L +#endif + +/***************************************************************************** + * + * 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 +#define DREG_TRAP 0x00000800L +#if !defined(NO_CS4612) +#if !defined(NO_CS4615) +#define DREG_TRAPX 0x00001000L +#endif +#endif +#define DREG_REGID_SHIFT 0L +#define DREG_RGBK_SHIFT 8L +#define DREG_RGBK_REGID_MASK 0x0000077FL +#define DREG_REGID_R0 0x00000010L +#define DREG_REGID_R1 0x00000011L +#define DREG_REGID_R2 0x00000012L +#define DREG_REGID_R3 0x00000013L +#define DREG_REGID_R4 0x00000014L +#define DREG_REGID_R5 0x00000015L +#define DREG_REGID_R6 0x00000016L +#define DREG_REGID_R7 0x00000017L +#define DREG_REGID_R8 0x00000018L +#define DREG_REGID_R9 0x00000019L +#define DREG_REGID_RA 0x0000001AL +#define DREG_REGID_RB 0x0000001BL +#define DREG_REGID_RC 0x0000001CL +#define DREG_REGID_RD 0x0000001DL +#define DREG_REGID_RE 0x0000001EL +#define DREG_REGID_RF 0x0000001FL +#define DREG_REGID_RA_BUS_LOW 0x00000020L +#define DREG_REGID_RA_BUS_HIGH 0x00000038L +#define DREG_REGID_YBUS_LOW 0x00000050L +#define DREG_REGID_YBUS_HIGH 0x00000058L +#define DREG_REGID_TRAP_0 0x00000100L +#define DREG_REGID_TRAP_1 0x00000101L +#define DREG_REGID_TRAP_2 0x00000102L +#define DREG_REGID_TRAP_3 0x00000103L +#define DREG_REGID_TRAP_4 0x00000104L +#define DREG_REGID_TRAP_5 0x00000105L +#define DREG_REGID_TRAP_6 0x00000106L +#define DREG_REGID_TRAP_7 0x00000107L +#define DREG_REGID_INDIRECT_ADDRESS 0x0000010EL +#define DREG_REGID_TOP_OF_STACK 0x0000010FL +#if !defined(NO_CS4612) +#if !defined(NO_CS4615) +#define DREG_REGID_TRAP_8 0x00000110L +#define DREG_REGID_TRAP_9 0x00000111L +#define DREG_REGID_TRAP_10 0x00000112L +#define DREG_REGID_TRAP_11 0x00000113L +#define DREG_REGID_TRAP_12 0x00000114L +#define DREG_REGID_TRAP_13 0x00000115L +#define DREG_REGID_TRAP_14 0x00000116L +#define DREG_REGID_TRAP_15 0x00000117L +#define DREG_REGID_TRAP_16 0x00000118L +#define DREG_REGID_TRAP_17 0x00000119L +#define DREG_REGID_TRAP_18 0x0000011AL +#define DREG_REGID_TRAP_19 0x0000011BL +#define DREG_REGID_TRAP_20 0x0000011CL +#define DREG_REGID_TRAP_21 0x0000011DL +#define DREG_REGID_TRAP_22 0x0000011EL +#define DREG_REGID_TRAP_23 0x0000011FL +#endif +#endif +#define DREG_REGID_RSA0_LOW 0x00000200L +#define DREG_REGID_RSA0_HIGH 0x00000201L +#define DREG_REGID_RSA1_LOW 0x00000202L +#define DREG_REGID_RSA1_HIGH 0x00000203L +#define DREG_REGID_RSA2 0x00000204L +#define DREG_REGID_RSA3 0x00000205L +#define DREG_REGID_RSI0_LOW 0x00000206L +#define DREG_REGID_RSI0_HIGH 0x00000207L +#define DREG_REGID_RSI1 0x00000208L +#define DREG_REGID_RSI2 0x00000209L +#define DREG_REGID_SAGUSTATUS 0x0000020AL +#define DREG_REGID_RSCONFIG01_LOW 0x0000020BL +#define DREG_REGID_RSCONFIG01_HIGH 0x0000020CL +#define DREG_REGID_RSCONFIG23_LOW 0x0000020DL +#define DREG_REGID_RSCONFIG23_HIGH 0x0000020EL +#define DREG_REGID_RSDMA01E 0x0000020FL +#define DREG_REGID_RSDMA23E 0x00000210L +#define DREG_REGID_RSD0_LOW 0x00000211L +#define DREG_REGID_RSD0_HIGH 0x00000212L +#define DREG_REGID_RSD1_LOW 0x00000213L +#define DREG_REGID_RSD1_HIGH 0x00000214L +#define DREG_REGID_RSD2_LOW 0x00000215L +#define DREG_REGID_RSD2_HIGH 0x00000216L +#define DREG_REGID_RSD3_LOW 0x00000217L +#define DREG_REGID_RSD3_HIGH 0x00000218L +#define DREG_REGID_SRAR_HIGH 0x0000021AL +#define DREG_REGID_SRAR_LOW 0x0000021BL +#define DREG_REGID_DMA_STATE 0x0000021CL +#define DREG_REGID_CURRENT_DMA_STREAM 0x0000021DL +#define DREG_REGID_NEXT_DMA_STREAM 0x0000021EL +#define DREG_REGID_CPU_STATUS 0x00000300L +#define DREG_REGID_MAC_MODE 0x00000301L +#define DREG_REGID_STACK_AND_REPEAT 0x00000302L +#define DREG_REGID_INDEX0 0x00000304L +#define DREG_REGID_INDEX1 0x00000305L +#define DREG_REGID_DMA_STATE_0_3 0x00000400L +#define DREG_REGID_DMA_STATE_4_7 0x00000404L +#define DREG_REGID_DMA_STATE_8_11 0x00000408L +#define DREG_REGID_DMA_STATE_12_15 0x0000040CL +#define DREG_REGID_DMA_STATE_16_19 0x00000410L +#define DREG_REGID_DMA_STATE_20_23 0x00000414L +#define DREG_REGID_DMA_STATE_24_27 0x00000418L +#define DREG_REGID_DMA_STATE_28_31 0x0000041CL +#define DREG_REGID_DMA_STATE_32_35 0x00000420L +#define DREG_REGID_DMA_STATE_36_39 0x00000424L +#define DREG_REGID_DMA_STATE_40_43 0x00000428L +#define DREG_REGID_DMA_STATE_44_47 0x0000042CL +#define DREG_REGID_DMA_STATE_48_51 0x00000430L +#define DREG_REGID_DMA_STATE_52_55 0x00000434L +#define DREG_REGID_DMA_STATE_56_59 0x00000438L +#define DREG_REGID_DMA_STATE_60_63 0x0000043CL +#define DREG_REGID_DMA_STATE_64_67 0x00000440L +#define DREG_REGID_DMA_STATE_68_71 0x00000444L +#define DREG_REGID_DMA_STATE_72_75 0x00000448L +#define DREG_REGID_DMA_STATE_76_79 0x0000044CL +#define DREG_REGID_DMA_STATE_80_83 0x00000450L +#define DREG_REGID_DMA_STATE_84_87 0x00000454L +#define DREG_REGID_DMA_STATE_88_91 0x00000458L +#define DREG_REGID_DMA_STATE_92_95 0x0000045CL +#define DREG_REGID_TRAP_SELECT 0x00000500L +#define DREG_REGID_TRAP_WRITE_0 0x00000500L +#define DREG_REGID_TRAP_WRITE_1 0x00000501L +#define DREG_REGID_TRAP_WRITE_2 0x00000502L +#define DREG_REGID_TRAP_WRITE_3 0x00000503L +#define DREG_REGID_TRAP_WRITE_4 0x00000504L +#define DREG_REGID_TRAP_WRITE_5 0x00000505L +#define DREG_REGID_TRAP_WRITE_6 0x00000506L +#define DREG_REGID_TRAP_WRITE_7 0x00000507L +#if !defined(NO_CS4612) +#if !defined(NO_CS4615) +#define DREG_REGID_TRAP_WRITE_8 0x00000510L +#define DREG_REGID_TRAP_WRITE_9 0x00000511L +#define DREG_REGID_TRAP_WRITE_10 0x00000512L +#define DREG_REGID_TRAP_WRITE_11 0x00000513L +#define DREG_REGID_TRAP_WRITE_12 0x00000514L +#define DREG_REGID_TRAP_WRITE_13 0x00000515L +#define DREG_REGID_TRAP_WRITE_14 0x00000516L +#define DREG_REGID_TRAP_WRITE_15 0x00000517L +#define DREG_REGID_TRAP_WRITE_16 0x00000518L +#define DREG_REGID_TRAP_WRITE_17 0x00000519L +#define DREG_REGID_TRAP_WRITE_18 0x0000051AL +#define DREG_REGID_TRAP_WRITE_19 0x0000051BL +#define DREG_REGID_TRAP_WRITE_20 0x0000051CL +#define DREG_REGID_TRAP_WRITE_21 0x0000051DL +#define DREG_REGID_TRAP_WRITE_22 0x0000051EL +#define DREG_REGID_TRAP_WRITE_23 0x0000051FL +#endif +#endif +#define DREG_REGID_MAC0_ACC0_LOW 0x00000600L +#define DREG_REGID_MAC0_ACC1_LOW 0x00000601L +#define DREG_REGID_MAC0_ACC2_LOW 0x00000602L +#define DREG_REGID_MAC0_ACC3_LOW 0x00000603L +#define DREG_REGID_MAC1_ACC0_LOW 0x00000604L +#define DREG_REGID_MAC1_ACC1_LOW 0x00000605L +#define DREG_REGID_MAC1_ACC2_LOW 0x00000606L +#define DREG_REGID_MAC1_ACC3_LOW 0x00000607L +#define DREG_REGID_MAC0_ACC0_MID 0x00000608L +#define DREG_REGID_MAC0_ACC1_MID 0x00000609L +#define DREG_REGID_MAC0_ACC2_MID 0x0000060AL +#define DREG_REGID_MAC0_ACC3_MID 0x0000060BL +#define DREG_REGID_MAC1_ACC0_MID 0x0000060CL +#define DREG_REGID_MAC1_ACC1_MID 0x0000060DL +#define DREG_REGID_MAC1_ACC2_MID 0x0000060EL +#define DREG_REGID_MAC1_ACC3_MID 0x0000060FL +#define DREG_REGID_MAC0_ACC0_HIGH 0x00000610L +#define DREG_REGID_MAC0_ACC1_HIGH 0x00000611L +#define DREG_REGID_MAC0_ACC2_HIGH 0x00000612L +#define DREG_REGID_MAC0_ACC3_HIGH 0x00000613L +#define DREG_REGID_MAC1_ACC0_HIGH 0x00000614L +#define DREG_REGID_MAC1_ACC1_HIGH 0x00000615L +#define DREG_REGID_MAC1_ACC2_HIGH 0x00000616L +#define DREG_REGID_MAC1_ACC3_HIGH 0x00000617L +#define DREG_REGID_RSHOUT_LOW 0x00000620L +#define DREG_REGID_RSHOUT_MID 0x00000628L +#define DREG_REGID_RSHOUT_HIGH 0x00000630L + +/***************************************************************************** + * + * 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 +#define DSRWP_DSR_PRIORITY_0 0x00000000L +#define DSRWP_DSR_PRIORITY_1 0x00000002L +#define DSRWP_DSR_PRIORITY_2 0x00000004L +#define DSRWP_DSR_PRIORITY_3 0x00000006L +#define DSRWP_DSR_RQ_PENDING 0x00000008L + +/***************************************************************************** + * + * 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. + * + *****************************************************************************/ +#define SPWR_STKP_MASK 0x0000000FL +#define SPWR_STKP_SHIFT 0L + +/***************************************************************************** + * + * The following defines are for the flags in the SP interrupt register. + * + *****************************************************************************/ +#define SPIR_FRI 0x00000001L +#define SPIR_DOI 0x00000002L +#define SPIR_GPI2 0x00000004L +#define SPIR_GPI3 0x00000008L +#define SPIR_IP0 0x00000010L +#define SPIR_IP1 0x00000020L +#define SPIR_IP2 0x00000040L +#define SPIR_IP3 0x00000080L + +/***************************************************************************** + * + * 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. + * + *****************************************************************************/ +#define SPCS_FRI 0x00000001L +#define SPCS_DOI 0x00000002L +#define SPCS_GPI2 0x00000004L +#define SPCS_GPI3 0x00000008L +#define SPCS_IP0 0x00000010L +#define SPCS_IP1 0x00000020L +#define SPCS_IP2 0x00000040L +#define SPCS_IP3 0x00000080L +#define SPCS_SPRUN 0x00000100L +#define SPCS_SLEEP 0x00000200L +#define SPCS_FG 0x00000400L +#define SPCS_ORUN 0x00000800L +#define SPCS_IRQ 0x00001000L +#define SPCS_FGN_MASK 0x0000E000L +#define SPCS_FGN_SHIFT 13L + +/***************************************************************************** + * + * 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. + * + *****************************************************************************/ +#define FRMT_FTV_MASK 0x0000FFFFL +#define FRMT_FTV_SHIFT 0L + +/***************************************************************************** + * + * 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. + * + *****************************************************************************/ +#define FRSC_FCS_MASK 0x0000FFFFL +#define FRSC_FCS_SHIFT 0L + +/***************************************************************************** + * + * 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 +#define DMA_SG_LOOP_END_FLAG 0x20000000L +#define DMA_SG_SIGNAL_END_FLAG 0x40000000L +#define DMA_SG_SIGNAL_PAGE_FLAG 0x80000000L +#define DMA_SG_NEXT_ENTRY_SHIFT 3L +#define DMA_SG_SAMPLE_END_SHIFT 16L + +/***************************************************************************** + * + * 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 +#define DMA_RQ_DESTINATION_ADDR 0x0000000CL +#define DMA_RQ_NEXT_PAGE_ADDR 0x00000010L +#define DMA_RQ_NEXT_PAGE_SGDESC 0x00000014L +#define DMA_RQ_LOOP_START_ADDR 0x00000018L +#define DMA_RQ_POST_LOOP_ADDR 0x0000001CL +#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. + * + *****************************************************************************/ +#define DMA_RQ_C1_COUNT_MASK 0x000003FFL +#define DMA_RQ_C1_DESTINATION_SCATTER 0x00001000L +#define DMA_RQ_C1_SOURCE_GATHER 0x00002000L +#define DMA_RQ_C1_DONE_FLAG 0x00004000L +#define DMA_RQ_C1_OPTIMIZE_STATE 0x00008000L +#define DMA_RQ_C1_SAMPLE_END_STATE_MASK 0x00030000L +#define DMA_RQ_C1_FULL_PAGE 0x00000000L +#define DMA_RQ_C1_BEFORE_SAMPLE_END 0x00010000L +#define DMA_RQ_C1_PAGE_MAP_ERROR 0x00020000L +#define DMA_RQ_C1_AT_SAMPLE_END 0x00030000L +#define DMA_RQ_C1_LOOP_END_STATE_MASK 0x000C0000L +#define DMA_RQ_C1_NOT_LOOP_END 0x00000000L +#define DMA_RQ_C1_BEFORE_LOOP_END 0x00040000L +#define DMA_RQ_C1_2PAGE_LOOP_BEGIN 0x00080000L +#define DMA_RQ_C1_LOOP_BEGIN 0x000C0000L +#define DMA_RQ_C1_PAGE_MAP_MASK 0x00300000L +#define DMA_RQ_C1_PM_NONE_PENDING 0x00000000L +#define DMA_RQ_C1_PM_NEXT_PENDING 0x00100000L +#define DMA_RQ_C1_PM_RESERVED 0x00200000L +#define DMA_RQ_C1_PM_LOOP_NEXT_PENDING 0x00300000L +#define DMA_RQ_C1_WRITEBACK_DEST_FLAG 0x00400000L +#define DMA_RQ_C1_WRITEBACK_SRC_FLAG 0x00800000L +#define DMA_RQ_C1_DEST_SIZE_MASK 0x07000000L +#define DMA_RQ_C1_DEST_LINEAR 0x00000000L +#define DMA_RQ_C1_DEST_MOD16 0x01000000L +#define DMA_RQ_C1_DEST_MOD32 0x02000000L +#define DMA_RQ_C1_DEST_MOD64 0x03000000L +#define DMA_RQ_C1_DEST_MOD128 0x04000000L +#define DMA_RQ_C1_DEST_MOD256 0x05000000L +#define DMA_RQ_C1_DEST_MOD512 0x06000000L +#define DMA_RQ_C1_DEST_MOD1024 0x07000000L +#define DMA_RQ_C1_DEST_ON_HOST 0x08000000L +#define DMA_RQ_C1_SOURCE_SIZE_MASK 0x70000000L +#define DMA_RQ_C1_SOURCE_LINEAR 0x00000000L +#define DMA_RQ_C1_SOURCE_MOD16 0x10000000L +#define DMA_RQ_C1_SOURCE_MOD32 0x20000000L +#define DMA_RQ_C1_SOURCE_MOD64 0x30000000L +#define DMA_RQ_C1_SOURCE_MOD128 0x40000000L +#define DMA_RQ_C1_SOURCE_MOD256 0x50000000L +#define DMA_RQ_C1_SOURCE_MOD512 0x60000000L +#define DMA_RQ_C1_SOURCE_MOD1024 0x70000000L +#define DMA_RQ_C1_SOURCE_ON_HOST 0x80000000L +#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. + * + *****************************************************************************/ +#define DMA_RQ_C2_VIRTUAL_CHANNEL_MASK 0x0000003FL +#define DMA_RQ_C2_VIRTUAL_SIGNAL_MASK 0x00000300L +#define DMA_RQ_C2_NO_VIRTUAL_SIGNAL 0x00000000L +#define DMA_RQ_C2_SIGNAL_EVERY_DMA 0x00000100L +#define DMA_RQ_C2_SIGNAL_SOURCE_PINGPONG 0x00000200L +#define DMA_RQ_C2_SIGNAL_DEST_PINGPONG 0x00000300L +#define DMA_RQ_C2_AUDIO_CONVERT_MASK 0x0000F000L +#define DMA_RQ_C2_AC_NONE 0x00000000L +#define DMA_RQ_C2_AC_8_TO_16_BIT 0x00001000L +#define DMA_RQ_C2_AC_MONO_TO_STEREO 0x00002000L +#define DMA_RQ_C2_AC_ENDIAN_CONVERT 0x00004000L +#define DMA_RQ_C2_AC_SIGNED_CONVERT 0x00008000L +#define DMA_RQ_C2_LOOP_END_MASK 0x0FFF0000L +#define DMA_RQ_C2_LOOP_MASK 0x30000000L +#define DMA_RQ_C2_NO_LOOP 0x00000000L +#define DMA_RQ_C2_ONE_PAGE_LOOP 0x10000000L +#define DMA_RQ_C2_TWO_PAGE_LOOP 0x20000000L +#define DMA_RQ_C2_MULTI_PAGE_LOOP 0x30000000L +#define DMA_RQ_C2_SIGNAL_LOOP_BACK 0x40000000L +#define DMA_RQ_C2_SIGNAL_POST_BEGIN_PAGE 0x80000000L +#define DMA_RQ_C2_VIRTUAL_CHANNEL_SHIFT 0L +#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. + * + *****************************************************************************/ +#define DMA_RQ_SD_ADDRESS_MASK 0x0000FFFFL +#define DMA_RQ_SD_MEMORY_ID_MASK 0x000F0000L +#define DMA_RQ_SD_SP_PARAM_ADDR 0x00000000L +#define DMA_RQ_SD_SP_SAMPLE_ADDR 0x00010000L +#define DMA_RQ_SD_SP_PROGRAM_ADDR 0x00020000L +#define DMA_RQ_SD_SP_DEBUG_ADDR 0x00030000L +#define DMA_RQ_SD_OMNIMEM_ADDR 0x000E0000L +#define DMA_RQ_SD_END_FLAG 0x40000000L +#define DMA_RQ_SD_ERROR_FLAG 0x80000000L +#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. + * + *****************************************************************************/ +#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. + * + *****************************************************************************/ +#define RSCONFIG_MODULO_SIZE_MASK 0x0000000FL +#define RSCONFIG_MODULO_16 0x00000001L +#define RSCONFIG_MODULO_32 0x00000002L +#define RSCONFIG_MODULO_64 0x00000003L +#define RSCONFIG_MODULO_128 0x00000004L +#define RSCONFIG_MODULO_256 0x00000005L +#define RSCONFIG_MODULO_512 0x00000006L +#define RSCONFIG_MODULO_1024 0x00000007L +#define RSCONFIG_MODULO_4 0x00000008L +#define RSCONFIG_MODULO_8 0x00000009L +#define RSCONFIG_SAMPLE_SIZE_MASK 0x000000C0L +#define RSCONFIG_SAMPLE_8MONO 0x00000000L +#define RSCONFIG_SAMPLE_8STEREO 0x00000040L +#define RSCONFIG_SAMPLE_16MONO 0x00000080L +#define RSCONFIG_SAMPLE_16STEREO 0x000000C0L +#define RSCONFIG_UNDERRUN_ZERO 0x00004000L +#define RSCONFIG_DMA_TO_HOST 0x00008000L +#define RSCONFIG_STREAM_NUM_MASK 0x00FF0000L +#define RSCONFIG_MAX_DMA_SIZE_MASK 0x1F000000L +#define RSCONFIG_DMA_ENABLE 0x20000000L +#define RSCONFIG_PRIORITY_MASK 0xC0000000L +#define RSCONFIG_PRIORITY_HIGH 0x00000000L +#define RSCONFIG_PRIORITY_MEDIUM_HIGH 0x40000000L +#define RSCONFIG_PRIORITY_MEDIUM_LOW 0x80000000L +#define RSCONFIG_PRIORITY_LOW 0xC0000000L +#define RSCONFIG_STREAM_NUM_SHIFT 16L +#define RSCONFIG_MAX_DMA_SIZE_SHIFT 24L + +#define BA1_VARIDEC_BUF_1 0x000 + +#define BA1_PDTC 0x0c0 /* BA1_PLAY_DMA_TRANSACTION_COUNT_REG */ +#define BA1_PFIE 0x0c4 /* BA1_PLAY_FORMAT_&_INTERRUPT_ENABLE_REG */ +#define BA1_PBA 0x0c8 /* BA1_PLAY_BUFFER_ADDRESS */ +#define BA1_PVOL 0x0f8 /* BA1_PLAY_VOLUME_REG */ +#define BA1_PSRC 0x288 /* BA1_PLAY_SAMPLE_RATE_CORRECTION_REG */ +#define BA1_PCTL 0x2a4 /* BA1_PLAY_CONTROL_REG */ +#define BA1_PPI 0x2b4 /* BA1_PLAY_PHASE_INCREMENT_REG */ + +#define BA1_CCTL 0x064 /* BA1_CAPTURE_CONTROL_REG */ +#define BA1_CIE 0x104 /* BA1_CAPTURE_INTERRUPT_ENABLE_REG */ +#define BA1_CBA 0x10c /* BA1_CAPTURE_BUFFER_ADDRESS */ +#define BA1_CSRC 0x2c8 /* BA1_CAPTURE_SAMPLE_RATE_CORRECTION_REG */ +#define BA1_CCI 0x2d8 /* BA1_CAPTURE_COEFFICIENT_INCREMENT_REG */ +#define BA1_CD 0x2e0 /* BA1_CAPTURE_DELAY_REG */ +#define BA1_CPI 0x2f4 /* BA1_CAPTURE_PHASE_INCREMENT_REG */ +#define BA1_CVOL 0x2f8 /* BA1_CAPTURE_VOLUME_REG */ + +#define BA1_CFG1 0x134 /* BA1_CAPTURE_FRAME_GROUP_1_REG */ +#define BA1_CFG2 0x138 /* BA1_CAPTURE_FRAME_GROUP_2_REG */ +#define BA1_CCST 0x13c /* BA1_CAPTURE_CONSTANT_REG */ +#define BA1_CSPB 0x340 /* BA1_CAPTURE_SPB_ADDRESS */ + +/* 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 + */ +#define INKY_BA1_DWORD_SIZE (13 * 1024 + 512) +#define INKY_MEMORY_COUNT 3 + +struct BA1struct +{ + struct + { + u_long ulDestByteOffset, + ulSourceByteSize; + } MemoryStat[INKY_MEMORY_COUNT]; + + u_long BA1Array[INKY_BA1_DWORD_SIZE]; +}; + +#endif /* _CSA_REG_H */ diff --git a/sys/dev/sound/pci/csavar.h b/sys/dev/sound/pci/csavar.h new file mode 100644 index 0000000..f46a625 --- /dev/null +++ b/sys/dev/sound/pci/csavar.h @@ -0,0 +1,69 @@ +/*- + * 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$ + */ + +#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; +}; + +/* 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 */ +}; +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; +}; + +void csa_clearserialfifos(csa_res *resp); + +/* Common functions for csa. */ +struct csa_card *csa_findsubcard(device_t dev); +int csa_readcodec(csa_res *resp, u_long offset, u_int32_t *data); +int csa_writecodec(csa_res *resp, u_long offset, u_int32_t data); + +u_int32_t csa_readio(csa_res *resp, u_long offset); +void csa_writeio(csa_res *resp, u_long offset, u_int32_t data); +u_int32_t csa_readmem(csa_res *resp, u_long offset); +void csa_writemem(csa_res *resp, u_long offset, u_int32_t data); + +#endif /* _CSA_VAR_H */ diff --git a/sys/dev/sound/pci/ds1-fw.h b/sys/dev/sound/pci/ds1-fw.h new file mode 100644 index 0000000..72a052a --- /dev/null +++ b/sys/dev/sound/pci/ds1-fw.h @@ -0,0 +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. + * + * $FreeBSD$ + */ +#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 +}; + +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 +}; + +/* -------------------------------------------- + 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 +}; + +#endif + diff --git a/sys/dev/sound/pci/ds1.c b/sys/dev/sound/pci/ds1.c new file mode 100644 index 0000000..1f1a2fe --- /dev/null +++ b/sys/dev/sound/pci/ds1.c @@ -0,0 +1,1084 @@ +/* + * Copyright (c) 2000 Cameron Grant <cg@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> + +#include <pci/pcireg.h> +#include <pci/pcivar.h> + +#include <dev/sound/pci/ds1.h> +#include <dev/sound/pci/ds1-fw.h> + +SND_DECLARE_FILE("$FreeBSD$"); + +/* -------------------------------------------------------------------- */ + +#define DS1_CHANS 4 +#define DS1_RECPRIMARY 0 +#define DS1_IRQHZ ((48000 << 8) / 256) +#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; +}; + +struct rbank { + 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; +}; + +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; +}; + +/* 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; + + struct sc_pchinfo pch[DS1_CHANS]; + struct sc_rchinfo rch[2]; +}; + +struct { + 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} +}; + +/* -------------------------------------------------------------------- */ + +/* + * prototypes + */ + +/* stuff */ +static int ds_init(struct sc_info *); +static void ds_intr(void *); + +/* talk to the card */ +static u_int32_t ds_rd(struct sc_info *, int, int); +static void ds_wr(struct sc_info *, int, u_int32_t, int); + +/* -------------------------------------------------------------------- */ + +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 +}; +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 +}; +static struct pcmchan_caps ds_playcaps = {4000, 96000, ds_playfmt, 0}; + +/* -------------------------------------------------------------------- */ +/* Hardware */ +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; + } +} + +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; + } +} + +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); +} + +/* -------------------------------------------------------------------- */ +/* ac97 codec */ +static int +ds_cdbusy(struct sc_info *sc, int sec) +{ + 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; +} + +static u_int32_t +ds_initcd(kobj_t obj, void *devinfo) +{ + 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); + } + + 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); + + 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); + + 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 } +}; +AC97_DECLARE(ds_ac97); + +/* -------------------------------------------------------------------- */ + +static void +ds_enadsp(struct sc_info *sc, int on) +{ + 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--; + } + } +} + +static volatile struct pbank * +ds_allocpslot(struct sc_info *sc) +{ + int slot; + + 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}, +/* {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; + + 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%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; + + 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 = %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); +} + +/* -------------------------------------------------------------------- */ +/* play channel interface */ +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; + + 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) == -1) + 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; + + ch->fmt = format; + + return 0; +} + +static int +ds1pchan_setspeed(kobj_t obj, void *data, u_int32_t speed) +{ + struct sc_pchinfo *ch = data; + + ch->spd = speed; + + return speed; +} + +static int +ds1pchan_setblocksize(kobj_t obj, void *data, u_int32_t blocksize) +{ + struct sc_pchinfo *ch = data; + int drate; + + /* irq rate is fixed at 187.5hz */ + drate = ch->spd * sndbuf_getbps(ch->buffer); + blocksize = (drate << 8) / DS1_IRQHZ; + sndbuf_resize(ch->buffer, DS1_BUFFSIZE / blocksize, 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); + } + + 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: %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; +} + +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 } +}; +CHANNEL_DECLARE(ds1pchan); + +/* -------------------------------------------------------------------- */ +/* record channel interface */ +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; + + 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) == -1) + 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; + + ch->fmt = format; + + return 0; +} + +static int +ds1rchan_setspeed(kobj_t obj, void *data, u_int32_t speed) +{ + struct sc_rchinfo *ch = data; + + ch->spd = speed; + + return speed; +} + +static int +ds1rchan_setblocksize(kobj_t obj, void *data, u_int32_t blocksize) +{ + struct sc_rchinfo *ch = data; + int drate; + + /* irq rate is fixed at 187.5hz */ + drate = ch->spd * sndbuf_getbps(ch->buffer); + blocksize = (drate << 8) / DS1_IRQHZ; + sndbuf_resize(ch->buffer, DS1_BUFFSIZE / blocksize, 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); + } + + return 0; +} + +static int +ds1rchan_getptr(kobj_t obj, void *data) +{ + struct sc_rchinfo *ch = data; + struct sc_info *sc = ch->parent; + + return ch->slot[sc->currbank].PgStart; +} + +static struct pcmchan_caps * +ds1rchan_getcaps(kobj_t obj, void *data) +{ + 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 } +}; +CHANNEL_DECLARE(ds1rchan); + +/* -------------------------------------------------------------------- */ +/* The interrupt handler */ +static void +ds_intr(void *p) +{ + 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 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; + chn_intr(sc->pch[i].channel); + } + } + for (i = 0; i < 2; i++) { + if (sc->rch[i].run) { + x = 1; + chn_intr(sc->rch[i].channel); + } + } + i = ds_rd(sc, YDSXGR_MODE, 4); + if (x) + ds_wr(sc, YDSXGR_MODE, i | 0x00000002, 4); + + } + snd_mtxunlock(sc->lock); +} + +/* -------------------------------------------------------------------- */ + +/* + * 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; + + sc->ctrlbase = error? 0 : (u_int32_t)segs->ds_addr; + + 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, &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; +} + +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); + + bus_dmamap_unload(sc->control_dmat, sc->map); + bus_dmamem_free(sc->control_dmat, sc->regbase, sc->map); + + return 0; +} + +static int +ds_finddev(u_int32_t dev, u_int32_t subdev) +{ + 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; +} + +static int +ds_pci_probe(device_t dev) +{ + 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 0; + } 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 softc\n"); + 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_MAPS; + sc->reg = bus_alloc_resource(dev, SYS_RES_MEMORY, &sc->regid, + 0, ~0, 1, 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*/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, &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; + mixer_init(dev, ac97_getmixerclass(), codec); + + 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, 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", + rman_get_start(sc->reg), rman_get_start(sc->irq)); + + 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; + +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; +} + +static int +ds_pci_resume(device_t dev) +{ + struct sc_info *sc; + + sc = pcm_getdevinfo(dev); + + 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; + + 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 } +}; + +static driver_t ds1_driver = { + "pcm", + ds1_methods, + PCM_SOFTC_SIZE, +}; + +DRIVER_MODULE(snd_ds1, pci, ds1_driver, pcm_devclass, 0, 0); +MODULE_DEPEND(snd_ds1, snd_pcm, PCM_MINVER, PCM_PREFVER, PCM_MAXVER); +MODULE_VERSION(snd_ds1, 1); diff --git a/sys/dev/sound/pci/ds1.h b/sys/dev/sound/pci/ds1.h new file mode 100644 index 0000000..ad4e829 --- /dev/null +++ b/sys/dev/sound/pci/ds1.h @@ -0,0 +1,156 @@ +/* + * ======================================================================= + * title : define + * company : YAMAHA + * author : Taichi Sugiyama + * create Data : 28/Sep/99 + * ======================================================================= + * $FreeBSD$ + */ + + +/* ----- YAMAHA DS-XG Devices -------------------------------------------- */ +#define YAMAHA 0x1073 +#define YMF724 0x0004 +#define YMF724F 0x000d +#define YMF734 0x0005 +#define YMF737 0x0008 +#define YMF738 0x0020 +#define YMF740 0x000a +#define YMF740C 0x000c +#define YMF744 0x0010 +#define YMF754 0x0012 +#define YMF738_TEG 0x0006 +#define DEVICE4CH(x) ((x == YMF738) || (x == YMF744) || (x == YMF754)) + + +#define PCIR_DSXGCTRL 0x48 +/* ----- interrupt flag -------------------------------------------------- */ +#define YDSXG_DEFINT 0x01 +#define YDSXG_TIMERINT 0x02 + + +/* ----- AC97 ------------------------------------------------------------ */ +#define YDSXG_AC97TIMEOUT 1000 +#define YDSXG_AC97READCMD 0x8000 +#define YDSXG_AC97WRITECMD 0x0000 +#define YDSXG_AC97READFALSE 0xFFFF + + +/* ----- AC97 register map _---------------------------------------------- */ +#define AC97R_GPIOSTATUS 0x54 + + +/* ----- work buffer ----------------------------------------------------- */ +#define DEF_WORKBUFFLENGTH 0x0400 + + +/* ----- register size --------------------------------------------------- */ +#define YDSXG_MAPLENGTH 0x8000 +#define YDSXG_DSPLENGTH 0x0080 +#define YDSXG_CTRLLENGTH 0x3000 + + +/* ----- register map ---------------------------------------------------- */ +#define YDSXGR_INTFLAG 0x0004 +#define YDSXGR_ACTIVITY 0x0006 +#define YDSXGR_GLOBALCTRL 0x0008 +#define YDSXGR_ZVCTRL 0x000A +#define YDSXGR_TIMERCTRL 0x0010 +#define YDSXGR_TIMERCOUNT 0x0012 +#define YDSXGR_SPDIFOUTCTRL 0x0018 +#define YDSXGR_SPDIFOUTSTATUS 0x001C +#define YDSXGR_EEPROMCTRL 0x0020 +#define YDSXGR_SPDIFINCTRL 0x0034 +#define YDSXGR_SPDIFINSTATUS 0x0038 +#define YDSXGR_DSPPROGRAMDL 0x0048 +#define YDSXGR_DLCNTRL 0x004C +#define YDSXGR_GPIOININTFLAG 0x0050 +#define YDSXGR_GPIOININTENABLE 0x0052 +#define YDSXGR_GPIOINSTATUS 0x0054 +#define YDSXGR_GPIOOUTCTRL 0x0056 +#define YDSXGR_GPIOFUNCENABLE 0x0058 +#define YDSXGR_GPIOTYPECONFIG 0x005A +#define YDSXGR_AC97CMDDATA 0x0060 +#define YDSXGR_AC97CMDADR 0x0062 +#define YDSXGR_PRISTATUSDATA 0x0064 +#define YDSXGR_PRISTATUSADR 0x0066 +#define YDSXGR_SECSTATUSDATA 0x0068 +#define YDSXGR_SECSTATUSADR 0x006A +#define YDSXGR_SECCONFIG 0x0070 +#define YDSXGR_LEGACYOUTVOL 0x0080 +#define YDSXGR_LEGACYOUTVOLL 0x0080 +#define YDSXGR_LEGACYOUTVOLR 0x0082 +#define YDSXGR_NATIVEDACOUTVOL 0x0084 +#define YDSXGR_NATIVEDACOUTVOLL 0x0084 +#define YDSXGR_NATIVEDACOUTVOLR 0x0086 +#define YDSXGR_SPDIFOUTVOL 0x0088 +#define YDSXGR_SPDIFOUTVOLL 0x0088 +#define YDSXGR_SPDIFOUTVOLR 0x008A +#define YDSXGR_AC3OUTVOL 0x008C +#define YDSXGR_AC3OUTVOLL 0x008C +#define YDSXGR_AC3OUTVOLR 0x008E +#define YDSXGR_PRIADCOUTVOL 0x0090 +#define YDSXGR_PRIADCOUTVOLL 0x0090 +#define YDSXGR_PRIADCOUTVOLR 0x0092 +#define YDSXGR_LEGACYLOOPVOL 0x0094 +#define YDSXGR_LEGACYLOOPVOLL 0x0094 +#define YDSXGR_LEGACYLOOPVOLR 0x0096 +#define YDSXGR_NATIVEDACLOOPVOL 0x0098 +#define YDSXGR_NATIVEDACLOOPVOLL 0x0098 +#define YDSXGR_NATIVEDACLOOPVOLR 0x009A +#define YDSXGR_SPDIFLOOPVOL 0x009C +#define YDSXGR_SPDIFLOOPVOLL 0x009E +#define YDSXGR_SPDIFLOOPVOLR 0x009E +#define YDSXGR_AC3LOOPVOL 0x00A0 +#define YDSXGR_AC3LOOPVOLL 0x00A0 +#define YDSXGR_AC3LOOPVOLR 0x00A2 +#define YDSXGR_PRIADCLOOPVOL 0x00A4 +#define YDSXGR_PRIADCLOOPVOLL 0x00A4 +#define YDSXGR_PRIADCLOOPVOLR 0x00A6 +#define YDSXGR_NATIVEADCINVOL 0x00A8 +#define YDSXGR_NATIVEADCINVOLL 0x00A8 +#define YDSXGR_NATIVEADCINVOLR 0x00AA +#define YDSXGR_NATIVEDACINVOL 0x00AC +#define YDSXGR_NATIVEDACINVOLL 0x00AC +#define YDSXGR_NATIVEDACINVOLR 0x00AE +#define YDSXGR_BUF441OUTVOL 0x00B0 +#define YDSXGR_BUF441OUTVOLL 0x00B0 +#define YDSXGR_BUF441OUTVOLR 0x00B2 +#define YDSXGR_BUF441LOOPVOL 0x00B4 +#define YDSXGR_BUF441LOOPVOLL 0x00B4 +#define YDSXGR_BUF441LOOPVOLR 0x00B6 +#define YDSXGR_SPDIFOUTVOL2 0x00B8 +#define YDSXGR_SPDIFOUTVOL2L 0x00B8 +#define YDSXGR_SPDIFOUTVOL2R 0x00BA +#define YDSXGR_SPDIFLOOPVOL2 0x00BC +#define YDSXGR_SPDIFLOOPVOL2L 0x00BC +#define YDSXGR_SPDIFLOOPVOL2R 0x00BE +#define YDSXGR_ADCSLOTSR 0x00C0 +#define YDSXGR_RECSLOTSR 0x00C4 +#define YDSXGR_ADCFORMAT 0x00C8 +#define YDSXGR_RECFORMAT 0x00CC +#define YDSXGR_P44SLOTSR 0x00D0 +#define YDSXGR_STATUS 0x0100 +#define YDSXGR_CTRLSELECT 0x0104 +#define YDSXGR_MODE 0x0108 +#define YDSXGR_SAMPLECOUNT 0x010C +#define YDSXGR_NUMOFSAMPLES 0x0110 +#define YDSXGR_CONFIG 0x0114 +#define YDSXGR_PLAYCTRLSIZE 0x0140 +#define YDSXGR_RECCTRLSIZE 0x0144 +#define YDSXGR_EFFCTRLSIZE 0x0148 +#define YDSXGR_WORKSIZE 0x014C +#define YDSXGR_MAPOFREC 0x0150 +#define YDSXGR_MAPOFEFFECT 0x0154 +#define YDSXGR_PLAYCTRLBASE 0x0158 +#define YDSXGR_RECCTRLBASE 0x015C +#define YDSXGR_EFFCTRLBASE 0x0160 +#define YDSXGR_WORKBASE 0x0164 +#define YDSXGR_DSPINSTRAM 0x1000 +#define YDSXGR_CTRLINSTRAM 0x4000 + + +/* ----- time out -------------------------------------------------------- */ +#define YDSXG_WORKBITTIMEOUT 250000 + diff --git a/sys/dev/sound/pci/emu10k1.c b/sys/dev/sound/pci/emu10k1.c new file mode 100644 index 0000000..c847016 --- /dev/null +++ b/sys/dev/sound/pci/emu10k1.c @@ -0,0 +1,1636 @@ +/* + * Copyright (c) 1999 Cameron Grant <gandalf@vilnya.demon.co.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 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 <pci/pcireg.h> +#include <pci/pcivar.h> +#include <sys/queue.h> + +SND_DECLARE_FILE("$FreeBSD$"); + +/* -------------------------------------------------------------------- */ + +#define EMU10K1_PCI_ID 0x00021102 +#define EMU10K2_PCI_ID 0x00041102 +#define EMU_DEFAULT_BUFSZ 4096 +#define EMU_CHANS 4 +#undef EMUDEBUG + +struct emu_memblk { + 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[MAXPAGES / 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; + 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; +}; + +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; +}; + +/* device private data */ +struct sc_info { + device_t dev; + u_int32_t type, rev; + u_int32_t tos_link:1, APS:1; + + 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; + struct emu_mem mem; + struct emu_voice voice[64]; + struct sc_pchinfo pch[EMU_CHANS]; + struct sc_rchinfo rch[3]; +}; + +/* -------------------------------------------------------------------- */ + +/* + * prototypes + */ + +/* stuff */ +static int emu_init(struct sc_info *); +static void emu_intr(void *); +static void *emu_malloc(struct sc_info *sc, u_int32_t sz, bus_addr_t *addr); +static void *emu_memalloc(struct sc_info *sc, u_int32_t sz, bus_addr_t *addr); +static int emu_memfree(struct sc_info *sc, void *buf); +static int emu_memstart(struct sc_info *sc, void *buf); +#ifdef EMUDEBUG +static void emu_vdump(struct sc_info *sc, struct emu_voice *v); +#endif + +/* talk to the card */ +static u_int32_t emu_rd(struct sc_info *, int, int); +static void emu_wr(struct sc_info *, int, u_int32_t, int); + +/* -------------------------------------------------------------------- */ + +static u_int32_t emu_rfmt_ac97[] = { + AFMT_S16_LE, + AFMT_STEREO | AFMT_S16_LE, + 0 +}; + +static u_int32_t emu_rfmt_mic[] = { + AFMT_U8, + 0 +}; + +static u_int32_t emu_rfmt_efx[] = { + 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}, +}; + +static u_int32_t emu_pfmt[] = { + 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}; + +static int adcspeed[8] = {48000, 44100, 32000, 24000, 22050, 16000, 11025, 8000}; + +/* -------------------------------------------------------------------- */ +/* Hardware */ +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; + } +} + +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; + } +} + +static u_int32_t +emu_rdptr(struct sc_info *sc, int chn, int reg) +{ + u_int32_t ptr, val, mask, size, offset; + + ptr = ((reg << 16) & PTR_ADDRESS_MASK) | (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; + + ptr = ((reg << 16) & PTR_ADDRESS_MASK) | (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) +{ + emu_wrptr(sc, 0, MICROCODEBASE + pc, data); +} + +/* -------------------------------------------------------------------- */ +/* ac97 codec */ +/* no locking needed */ + +static int +emu_rdcd(kobj_t obj, void *devinfo, int regno) +{ + struct sc_info *sc = (struct sc_info *)devinfo; + + 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; + + 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 } +}; +AC97_DECLARE(emu_ac97); + +/* -------------------------------------------------------------------- */ +/* stuff */ +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 < EMU_CHANS; 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; +} + +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; +} + +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); +} + +static int +emu_recval(int speed) { + int val; + + val = 0; + while (val < 7 && speed < 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; + + 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 */ +} + +static u_int32_t +emu_rate_to_linearpitch(u_int32_t rate) +{ + 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; + + 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) +{ + 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 (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->slave = NULL; + } + return 0; +} + +static void +emu_vsetup(struct sc_pchinfo *ch) +{ + 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; + } +} + +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; + + emu_wrptr(sc, v->vnum, FXRT, 0xd01c0000); + + 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); + + 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); +} + +static int +emu_vpos(struct 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; +} + +#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" + }; + 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; + } + 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 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; +} + +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); + + return r; +} + +static int +emupchan_setformat(kobj_t obj, void *data, u_int32_t format) +{ + struct sc_pchinfo *ch = data; + + ch->fmt = format; + return 0; +} + +static int +emupchan_setspeed(kobj_t obj, void *data, u_int32_t speed) +{ + struct sc_pchinfo *ch = data; + + 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; +} + +static int +emupchan_trigger(kobj_t obj, void *data, int go) +{ + struct sc_pchinfo *ch = data; + struct sc_info *sc = ch->parent; + + if (go == PCMTRIG_EMLDMAWR || go == PCMTRIG_EMLDMARD) + 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); +#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); +#endif + } + 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); + + return r; +} + +static struct pcmchan_caps * +emupchan_getcaps(kobj_t obj, void *data) +{ + 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 } +}; +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 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 = 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) == -1) + 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; + + ch->fmt = format; + return 0; +} + +static int +emurchan_setspeed(kobj_t obj, void *data, u_int32_t speed) +{ + struct sc_rchinfo *ch = data; + + if (ch->num == 0) + 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; +} + +/* 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) { + 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; +} + +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); + + return r; +} + +static struct pcmchan_caps * +emurchan_getcaps(kobj_t obj, void *data) +{ + struct sc_rchinfo *ch = data; + + 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 } +}; +CHANNEL_DECLARE(emurchan); + +/* -------------------------------------------------------------------- */ +/* The interrupt handler */ +static void +emu_intr(void *p) +{ + struct sc_info *sc = (struct sc_info *)p; + u_int32_t stat, ack, i, x; + + while (1) { + stat = emu_rd(sc, IPR, 4); + if (stat == 0) + break; + ack = 0; + + /* process irq */ + if (stat & IPR_INTERVALTIMER) { + ack |= IPR_INTERVALTIMER; + x = 0; + for (i = 0; i < EMU_CHANS; i++) { + if (sc->pch[i].run) { + x = 1; + chn_intr(sc->pch[i].channel); + } + } + if (x == 0) + emu_enatimer(sc, 0); + } + + + if (stat & (IPR_ADCBUFFULL | IPR_ADCBUFHALFFULL)) { + ack |= stat & (IPR_ADCBUFFULL | IPR_ADCBUFHALFFULL); + if (sc->rch[0].channel) + chn_intr(sc->rch[0].channel); + } + if (stat & (IPR_EFXBUFFULL | IPR_EFXBUFHALFFULL)) { + ack |= stat & (IPR_EFXBUFFULL | IPR_EFXBUFHALFFULL); + if (sc->rch[1].channel) + chn_intr(sc->rch[1].channel); + } + if (stat & (IPR_MICBUFFULL | IPR_MICBUFHALFFULL)) { + ack |= stat & (IPR_MICBUFFULL | IPR_MICBUFHALFFULL); + if (sc->rch[2].channel) + chn_intr(sc->rch[2].channel); + } + 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; + /* device_printf(sc->dev, "sample rate tracker lock status change\n"); */ + } + + if (stat & ~ack) + device_printf(sc->dev, "dodgy irq: %x (harmless)\n", stat & ~ack); + + emu_wr(sc, IPR, stat, 4); + } +} + +/* -------------------------------------------------------------------- */ + +static void +emu_setmap(void *arg, bus_dma_segment_t *segs, int nseg, int error) +{ + bus_addr_t *phys = arg; + + *phys = error ? 0 : (bus_addr_t)segs->ds_addr; + + 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; + + *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); +} + +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 < 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) + 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; + /* printf("buf %p, pte_start %d, pte_size %d\n", blk->buf, blk->pte_start, blk->pte_size); */ + 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); + /* printf("pte[%d] -> %x phys, %x virt\n", idx, tmp, ((u_int32_t)buf) + ofs); */ + 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; +} + +static int +emu_memstart(struct sc_info *sc, void *buf) +{ + 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; +} + +static void +emu_addefxop(struct sc_info *sc, int op, int z, int w, int x, int y, u_int32_t *pc) +{ + emu_wrefx(sc, (*pc) * 2, (x << 10) | y); + emu_wrefx(sc, (*pc) * 2 + 1, (op << 20) | (z << 10) | w); + (*pc)++; +} + +static void +emu_initefx(struct sc_info *sc) +{ + int i; + u_int32_t pc = 16; + + 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 : APS S/PDIF?? (l/r) + Output + 0x020/0x021 : AC97 Output (l/r) + 0x022/0x023 : TOS link out (l/r) + 0x024/0x025 : ??? (l/r) + 0x026/0x027 : LiveDrive Headphone (l/r) + 0x028/0x029 : Rear Channel (l/r) + 0x02a/0x02b : ADC Recording Buffer (l/r) + 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 + Temporary Values + 0x056 : Accumulator + 0x058 : Noise source? + 0x059 : Noise source? + General Purpose Registers + 0x100 - 0x1ff + Tank Memory Data Registers + 0x200 - 0x2ff + Tank Memory Address Registers + 0x300 - 0x3ff + */ + + /* Operators: + 0 : z := w + (x * y >> 31) + 4 : z := w + x * y + 6 : z := w + x + y + */ + + /* Routing - this will be configurable in later version */ + + /* GPR[0/1] = FX * 4 + SPDIF-in */ + emu_addefxop(sc, 4, 0x100, 0x12, 0, 0x44, &pc); + emu_addefxop(sc, 4, 0x101, 0x13, 1, 0x44, &pc); + /* GPR[0/1] += APS-input */ + emu_addefxop(sc, 6, 0x100, 0x100, 0x40, sc->APS ? 0x16 : 0x40, &pc); + emu_addefxop(sc, 6, 0x101, 0x101, 0x40, sc->APS ? 0x17 : 0x40, &pc); + /* FrontOut (AC97) = GPR[0/1] */ + emu_addefxop(sc, 6, 0x20, 0x40, 0x40, 0x100, &pc); + emu_addefxop(sc, 6, 0x21, 0x40, 0x41, 0x101, &pc); + /* RearOut = (GPR[0/1] * RearVolume) >> 31 */ + /* RearVolume = GRP[0x10/0x11] */ + emu_addefxop(sc, 0, 0x28, 0x40, 0x110, 0x100, &pc); + emu_addefxop(sc, 0, 0x29, 0x40, 0x111, 0x101, &pc); + /* TOS out = GPR[0/1] */ + emu_addefxop(sc, 6, 0x22, 0x40, 0x40, 0x100, &pc); + emu_addefxop(sc, 6, 0x23, 0x40, 0x40, 0x101, &pc); + /* Mute Out2 */ + emu_addefxop(sc, 6, 0x24, 0x40, 0x40, 0x40, &pc); + emu_addefxop(sc, 6, 0x25, 0x40, 0x40, 0x40, &pc); + /* Mute Out3 */ + emu_addefxop(sc, 6, 0x26, 0x40, 0x40, 0x40, &pc); + emu_addefxop(sc, 6, 0x27, 0x40, 0x40, 0x40, &pc); + /* Input0 (AC97) -> Record */ + emu_addefxop(sc, 6, 0x2a, 0x40, 0x40, 0x10, &pc); + emu_addefxop(sc, 6, 0x2b, 0x40, 0x40, 0x11, &pc); + + 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; + + /* 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); + + /* 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); + + 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); + + emu_initefx(sc); + + SLIST_INIT(&sc->mem.blocks); + sc->mem.ptb_pages = emu_malloc(sc, MAXPAGES * 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 < MAXPAGES; 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 + * Enable Audio = 1 + * Mute Disable Audio = 0 + * Lock Tank Memory = 1 + * Lock Sound Memory = 0 + * Auto Mute = 1 + */ + 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 | 0x800, 4); + DELAY(50); + if (tmp != (emu_rd(sc, HCFG, 4) & ~0x800)) { + sc->tos_link = 1; + emu_wr(sc, HCFG, tmp, 4); + } + } + + return 0; +} + +static int +emu_uninit(struct sc_info *sc) +{ + 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); + } + + /* 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); + + 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: + s = "Creative EMU10K2"; + break; +*/ + default: + return ENXIO; + } + + device_set_desc(dev, s); + return 0; +} + +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 softc\n"); + 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); + + 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_MAPS; + sc->reg = bus_alloc_resource(dev, SYS_RES_IOPORT, &i, 0, ~0, 1, 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*/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, &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; + + i = 0; + sc->irq = bus_alloc_resource(dev, SYS_RES_IRQ, &i, 0, ~0, 1, 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", rman_get_start(sc->reg), rman_get_start(sc->irq)); + + if (pcm_register(dev, sc, EMU_CHANS, gotmic ? 3 : 2)) goto bad; + for (i = 0; i < EMU_CHANS; 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); + + return 0; + +bad: + if (codec) ac97_destroy(codec); + if (sc->reg) bus_release_resource(dev, SYS_RES_IOPORT, PCIR_MAPS, 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; + + 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_MAPS, 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; +} + +/* 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), + + { 0, 0 } +}; + +static driver_t emu_driver = { + "pcm", + emu_methods, + PCM_SOFTC_SIZE, +}; + +DRIVER_MODULE(snd_emu10k1, pci, emu_driver, pcm_devclass, 0, 0); +MODULE_DEPEND(snd_emu10k1, snd_pcm, PCM_MINVER, PCM_PREFVER, PCM_MAXVER); +MODULE_VERSION(snd_emu10k1, 1); + +/* dummy driver to silence the joystick device */ +static int +emujoy_pci_probe(device_t dev) +{ + 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; + } + + if (s) device_set_desc(dev, s); + return s ? -1000 : ENXIO; +} + +static int +emujoy_pci_attach(device_t dev) +{ + return 0; +} + +static int +emujoy_pci_detach(device_t dev) +{ + 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), + + { 0, 0 } +}; + +static driver_t emujoy_driver = { + "emujoy", + emujoy_methods, + 8, +}; + +static devclass_t emujoy_devclass; + +DRIVER_MODULE(emujoy, pci, emujoy_driver, emujoy_devclass, 0, 0); + diff --git a/sys/dev/sound/pci/es137x.c b/sys/dev/sound/pci/es137x.c new file mode 100644 index 0000000..f864b4a --- /dev/null +++ b/sys/dev/sound/pci/es137x.c @@ -0,0 +1,968 @@ +/* + * 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@thebarn.com> + * Copyright (c) 1999 Cameron Grant <gandalf@vilnya.demon.co.uk> + * 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@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> +#include <dev/sound/pcm/ac97.h> +#include <dev/sound/pci/es137x.h> + +#include <pci/pcireg.h> +#include <pci/pcivar.h> + +#include <sys/sysctl.h> + +#include "mixer_if.h" + +SND_DECLARE_FILE("$FreeBSD$"); + +static int debug = 0; +SYSCTL_INT(_debug, OID_AUTO, es_debug, CTLFLAG_RW, &debug, 0, ""); + +#define MEM_MAP_REG 0x14 + +/* PCI IDs of supported chips */ +#define ES1370_PCI_ID 0x50001274 +#define ES1371_PCI_ID 0x13711274 +#define ES1371_PCI_ID2 0x13713274 +#define CT5880_PCI_ID 0x58801274 + +#define ES1371REV_ES1371_A 0x02 +#define ES1371REV_ES1371_B 0x09 + +#define ES1371REV_ES1373_8 0x08 +#define ES1371REV_ES1373_A 0x04 +#define ES1371REV_ES1373_B 0x06 + +#define ES1371REV_CT5880_A 0x07 + +#define CT5880REV_CT5880_C 0x02 +#define CT5880REV_CT5880_D 0x03 +#define CT5880REV_CT5880_E 0x04 + +#define ES_DEFAULT_BUFSZ 4096 + +/* device private data */ +struct es_info; + +struct es_chinfo { + struct es_info *parent; + struct pcm_channel *channel; + struct snd_dbuf *buffer; + int dir, num; + u_int32_t fmt, blksz, bufsz; +}; + +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 */ + u_long ctrl; + u_long sctrl; + struct es_chinfo pch, rch; +}; + +/* -------------------------------------------------------------------- */ + +/* prototypes */ +static void es_intr(void *); + +static u_int 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 int es1371_init(struct es_info *, device_t); +static int es1370_init(struct es_info *); +static int es1370_wrcodec(struct es_info *, u_char, u_char); + +static u_int32_t es_playfmt[] = { + AFMT_U8, + AFMT_STEREO | AFMT_U8, + AFMT_S16_LE, + AFMT_STEREO | AFMT_S16_LE, + 0 +}; +static struct pcmchan_caps es_playcaps = {4000, 48000, es_playfmt, 0}; + +static u_int32_t es_recfmt[] = { + AFMT_U8, + AFMT_STEREO | AFMT_U8, + AFMT_S16_LE, + AFMT_STEREO | AFMT_S16_LE, + 0 +}; +static struct pcmchan_caps es_reccaps = {4000, 48000, es_recfmt, 0}; + +static const struct { + 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, 0x0000, 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 } +}; + +/* -------------------------------------------------------------------- */ +/* The es1370 mixer interface */ + +static int +es1370_mixinit(struct snd_mixer *m) +{ + int i; + u_int32_t v; + + v = 0; + for (i = 0; i < SOUND_MIXER_NRDEVICES; i++) + if (mixtable[i].avail) v |= (1 << i); + mix_setdevs(m, v); + v = 0; + for (i = 0; i < SOUND_MIXER_NRDEVICES; i++) + if (mixtable[i].recmask) v |= (1 << i); + mix_setrecdevs(m, v); + return 0; +} + +static int +es1370_mixset(struct snd_mixer *m, unsigned dev, unsigned left, unsigned right) +{ + int l, r, rl, rr; + + 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; + } + if (mixtable[dev].stereo) { + rr = (r < 10)? 0x80 : 15 - (r - 10) / 6; + es1370_wrcodec(mix_getdevinfo(m), mixtable[dev].right, rr); + } + es1370_wrcodec(mix_getdevinfo(m), mixtable[dev].left, rl); + return l | (r << 8); +} + +static int +es1370_mixsetrecsrc(struct snd_mixer *m, u_int32_t src) +{ + int i, j = 0; + + 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; + + es1370_wrcodec(mix_getdevinfo(m), CODEC_LIMIX1, j & 0x55); + es1370_wrcodec(mix_getdevinfo(m), CODEC_RIMIX1, j & 0xaa); + es1370_wrcodec(mix_getdevinfo(m), CODEC_LIMIX2, (j >> 8) & 0x17); + es1370_wrcodec(mix_getdevinfo(m), CODEC_RIMIX2, (j >> 8) & 0x0f); + es1370_wrcodec(mix_getdevinfo(m), CODEC_OMIX1, 0x7f); + es1370_wrcodec(mix_getdevinfo(m), CODEC_OMIX2, 0x3f); + 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 } +}; +MIXER_DECLARE(es1370_mixer); + +/* -------------------------------------------------------------------- */ + +static int +es1370_wrcodec(struct es_info *es, u_char i, u_char data) +{ + int wait = 100; /* 100 msec timeout */ + + do { + if ((bus_space_read_4(es->st, es->sh, ES1370_REG_STATUS) & + STAT_CSTAT) == 0) { + bus_space_write_2(es->st, es->sh, ES1370_REG_CODEC, + ((u_short)i << CODEC_INDEX_SHIFT) | data); + return 0; + } + DELAY(1000); + } while (--wait); + printf("pcm: es1370_wrcodec timed out\n"); + return -1; +} + +/* -------------------------------------------------------------------- */ + +/* channel interface */ +static void * +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 = (dir == PCMDIR_PLAY)? &es->pch : &es->rch; + + ch->parent = es; + ch->channel = c; + ch->buffer = b; + ch->bufsz = es->bufsz; + ch->blksz = ch->bufsz / 2; + ch->num = ch->parent->num++; + if (sndbuf_alloc(ch->buffer, es->parent_dmat, ch->bufsz) == -1) return NULL; + return ch; +} + +static int +eschan_setdir(kobj_t obj, void *data, int dir) +{ + struct es_chinfo *ch = data; + struct es_info *es = ch->parent; + + if (dir == PCMDIR_PLAY) { + bus_space_write_1(es->st, es->sh, ES1370_REG_MEMPAGE, ES1370_REG_DAC2_FRAMEADR >> 8); + bus_space_write_4(es->st, es->sh, ES1370_REG_DAC2_FRAMEADR & 0xff, sndbuf_getbufaddr(ch->buffer)); + bus_space_write_4(es->st, es->sh, ES1370_REG_DAC2_FRAMECNT & 0xff, (ch->bufsz >> 2) - 1); + } else { + bus_space_write_1(es->st, es->sh, ES1370_REG_MEMPAGE, ES1370_REG_ADC_FRAMEADR >> 8); + bus_space_write_4(es->st, es->sh, ES1370_REG_ADC_FRAMEADR & 0xff, sndbuf_getbufaddr(ch->buffer)); + bus_space_write_4(es->st, es->sh, ES1370_REG_ADC_FRAMECNT & 0xff, (ch->bufsz >> 2) - 1); + } + ch->dir = dir; + return 0; +} + +static int +eschan_setformat(kobj_t obj, void *data, u_int32_t format) +{ + struct es_chinfo *ch = data; + struct es_info *es = ch->parent; + + if (ch->dir == PCMDIR_PLAY) { + 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; + } + bus_space_write_4(es->st, es->sh, ES1370_REG_SERIAL_CONTROL, es->sctrl); + 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; + + es->ctrl &= ~CTRL_PCLKDIV; + es->ctrl |= DAC2_SRTODIV(speed) << CTRL_SH_PCLKDIV; + bus_space_write_4(es->st, es->sh, ES1370_REG_CONTROL, es->ctrl); + /* rec/play speeds locked together - should indicate in flags */ + return speed; /* XXX calc real 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; + + if (ch->dir == PCMDIR_PLAY) { + return es1371_dac_rate(es, speed, 3 - ch->num); /* play */ + } else { + return es1371_adc_rate(es, speed, 1); /* record */ + } +} + +static int +eschan_setblocksize(kobj_t obj, void *data, u_int32_t blocksize) +{ + struct es_chinfo *ch = data; + + ch->blksz = blocksize; + ch->bufsz = ch->blksz * 2; + sndbuf_resize(ch->buffer, 2, ch->blksz); + + return ch->blksz; +} + +static int +eschan_trigger(kobj_t obj, void *data, int go) +{ + struct es_chinfo *ch = data; + struct es_info *es = ch->parent; + unsigned cnt; + + if (go == PCMTRIG_EMLDMAWR || go == PCMTRIG_EMLDMARD) + return 0; + + cnt = (ch->blksz / sndbuf_getbps(ch->buffer)) - 1; + + if (ch->dir == PCMDIR_PLAY) { + if (go == PCMTRIG_START) { + int b = (ch->fmt & AFMT_S16_LE)? 2 : 1; + es->ctrl |= CTRL_DAC2_EN; + es->sctrl &= ~(SCTRL_P2ENDINC | SCTRL_P2STINC | SCTRL_P2LOOPSEL | SCTRL_P2PAUSE | SCTRL_P2DACSEN); + es->sctrl |= SCTRL_P2INTEN | (b << SCTRL_SH_P2ENDINC); + bus_space_write_4(es->st, es->sh, ES1370_REG_DAC2_SCOUNT, cnt); + /* start at beginning of buffer */ + bus_space_write_4(es->st, es->sh, ES1370_REG_MEMPAGE, ES1370_REG_DAC2_FRAMECNT >> 8); + bus_space_write_4(es->st, es->sh, ES1370_REG_DAC2_FRAMECNT & 0xff, (ch->bufsz >> 2) - 1); + } else es->ctrl &= ~CTRL_DAC2_EN; + } else { + if (go == PCMTRIG_START) { + es->ctrl |= CTRL_ADC_EN; + es->sctrl &= ~SCTRL_R1LOOPSEL; + es->sctrl |= SCTRL_R1INTEN; + bus_space_write_4(es->st, es->sh, ES1370_REG_ADC_SCOUNT, cnt); + /* start at beginning of buffer */ + bus_space_write_4(es->st, es->sh, ES1370_REG_MEMPAGE, ES1370_REG_ADC_FRAMECNT >> 8); + bus_space_write_4(es->st, es->sh, ES1370_REG_ADC_FRAMECNT & 0xff, (ch->bufsz >> 2) - 1); + } else es->ctrl &= ~CTRL_ADC_EN; + } + bus_space_write_4(es->st, es->sh, ES1370_REG_SERIAL_CONTROL, es->sctrl); + bus_space_write_4(es->st, es->sh, ES1370_REG_CONTROL, es->ctrl); + 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) + reg = ES1370_REG_DAC2_FRAMECNT; + else + reg = ES1370_REG_ADC_FRAMECNT; + + bus_space_write_4(es->st, es->sh, ES1370_REG_MEMPAGE, reg >> 8); + cnt = bus_space_read_4(es->st, es->sh, reg & 0x000000ff) >> 16; + /* cnt is longwords */ + return cnt << 2; +} + +static struct pcmchan_caps * +eschan_getcaps(kobj_t obj, void *data) +{ + struct es_chinfo *ch = data; + return (ch->dir == PCMDIR_PLAY)? &es_playcaps : &es_reccaps; +} + +static kobj_method_t eschan1370_methods[] = { + KOBJMETHOD(channel_init, eschan_init), + KOBJMETHOD(channel_setdir, eschan_setdir), + 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 } +}; +CHANNEL_DECLARE(eschan1370); + +static kobj_method_t eschan1371_methods[] = { + KOBJMETHOD(channel_init, eschan_init), + KOBJMETHOD(channel_setdir, eschan_setdir), + 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 } +}; +CHANNEL_DECLARE(eschan1371); + +/* -------------------------------------------------------------------- */ +/* The interrupt handler */ +static void +es_intr(void *p) +{ + struct es_info *es = p; + unsigned intsrc, sctrl; + + intsrc = bus_space_read_4(es->st, es->sh, ES1370_REG_STATUS); + if ((intsrc & STAT_INTR) == 0) 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; + + bus_space_write_4(es->st, es->sh, ES1370_REG_SERIAL_CONTROL, sctrl); + bus_space_write_4(es->st, es->sh, ES1370_REG_SERIAL_CONTROL, es->sctrl); + + if (intsrc & STAT_ADC) chn_intr(es->rch.channel); + if (intsrc & STAT_DAC1); + if (intsrc & STAT_DAC2) chn_intr(es->pch.channel); +} + +/* ES1370 specific */ +static int +es1370_init(struct es_info *es) +{ + es->ctrl = CTRL_CDC_EN | CTRL_SERR_DIS | + (DAC2_SRTODIV(DSP_DEFAULT_SPEED) << CTRL_SH_PCLKDIV); + bus_space_write_4(es->st, es->sh, ES1370_REG_CONTROL, es->ctrl); + + es->sctrl = 0; + bus_space_write_4(es->st, es->sh, ES1370_REG_SERIAL_CONTROL, es->sctrl); + + 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 */ + + return 0; +} + +/* ES1371 specific */ +int +es1371_init(struct es_info *es, device_t dev) +{ + int idx; + int devid = pci_get_devid(dev); + int revid = pci_get_revid(dev); + + if (debug > 0) printf("es_init\n"); + + es->num = 0; + es->ctrl = 0; + es->sctrl = 0; + /* initialize the chips */ + 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)) { + bus_space_write_4(es->st, es->sh, ES1370_REG_STATUS, 0x20000000); + DELAY(20000); + if (debug > 0) device_printf(dev, "ac97 2.1 enabled\n"); + } else { /* pre ac97 2.1 card */ + bus_space_write_4(es->st, es->sh, ES1370_REG_CONTROL, es->ctrl); + if (debug > 0) device_printf(dev, "ac97 pre-2.1 enabled\n"); + } + bus_space_write_4(es->st, es->sh, ES1370_REG_SERIAL_CONTROL, es->sctrl); + bus_space_write_4(es->st, es->sh, ES1371_REG_LEGACY, 0); + /* AC'97 warm reset to start the bitclk */ + bus_space_write_4(es->st, es->sh, ES1371_REG_LEGACY, es->ctrl | ES1371_SYNC_RES); + DELAY(2000); + bus_space_write_4(es->st, es->sh, ES1370_REG_SERIAL_CONTROL, es->ctrl); + /* Init the sample rate converter */ + bus_space_write_4(es->st, es->sh, ES1371_REG_SMPRATE, ES1371_DIS_SRC); + 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, 1); + es1371_dac_rate (es, 22050, 1); + es1371_dac_rate (es, 22050, 2); + /* 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) + */ + bus_space_write_4(es->st, es->sh, ES1371_REG_SMPRATE, 0); + + return (0); +} + +/* -------------------------------------------------------------------- */ + +static int +es1371_wrcd(kobj_t obj, void *s, int addr, u_int32_t data) +{ + int sl; + unsigned t, x; + struct es_info *es = (struct es_info*)s; + + if (debug > 0) printf("wrcodec addr 0x%x data 0x%x\n", addr, data); + + for (t = 0; t < 0x1000; t++) + if (!(bus_space_read_4(es->st, es->sh,(ES1371_REG_CODEC & CODEC_WIP)))) + break; + sl = spltty(); + /* save the current state for later */ + x = bus_space_read_4(es->st, es->sh, ES1371_REG_SMPRATE); + /* enable SRC state data in SRC mux */ + bus_space_write_4(es->st, es->sh, ES1371_REG_SMPRATE, + (es1371_wait_src_ready(s) & + (ES1371_DIS_SRC | ES1371_DIS_P1 | ES1371_DIS_P2 | ES1371_DIS_R1))); + /* wait for a SAFE time to write addr/data and then do it, dammit */ + for (t = 0; t < 0x1000; t++) + if ((bus_space_read_4(es->st, es->sh, ES1371_REG_SMPRATE) & 0x00070000) == 0x00010000) + break; + + if (debug > 2) + printf("one b_s_w: 0x%lx 0x%x 0x%x\n", + rman_get_start(es->reg), ES1371_REG_CODEC, + ((addr << CODEC_POADD_SHIFT) & CODEC_POADD_MASK) | + ((data << CODEC_PODAT_SHIFT) & CODEC_PODAT_MASK)); + + bus_space_write_4(es->st, es->sh,ES1371_REG_CODEC, + ((addr << CODEC_POADD_SHIFT) & CODEC_POADD_MASK) | + ((data << CODEC_PODAT_SHIFT) & CODEC_PODAT_MASK)); + /* restore SRC reg */ + es1371_wait_src_ready(s); + if (debug > 2) + printf("two b_s_w: 0x%lx 0x%x 0x%x\n", + rman_get_start(es->reg), ES1371_REG_SMPRATE, x); + bus_space_write_4(es->st, es->sh, ES1371_REG_SMPRATE, x); + splx(sl); + + return 0; +} + +static int +es1371_rdcd(kobj_t obj, void *s, int addr) +{ + int sl; + unsigned t, x = 0; + struct es_info *es = (struct es_info *)s; + + if (debug > 0) printf("rdcodec addr 0x%x ... ", addr); + + for (t = 0; t < 0x1000; t++) + if (!(x = bus_space_read_4(es->st, es->sh, ES1371_REG_CODEC) & CODEC_WIP)) + break; + if (debug > 0) printf("loop 1 t 0x%x x 0x%x ", t, x); + + sl = spltty(); + + /* save the current state for later */ + x = bus_space_read_4(es->st, es->sh, ES1371_REG_SMPRATE); + /* enable SRC state data in SRC mux */ + bus_space_write_4(es->st, es->sh, ES1371_REG_SMPRATE, + (es1371_wait_src_ready(s) & + (ES1371_DIS_SRC | ES1371_DIS_P1 | ES1371_DIS_P2 | ES1371_DIS_R1))); + /* wait for a SAFE time to write addr/data and then do it, dammit */ + for (t = 0; t < 0x5000; t++) + if ((x = bus_space_read_4(es->st, es->sh, ES1371_REG_SMPRATE) & 0x00070000) == 0x00010000) + break; + if (debug > 0) printf("loop 2 t 0x%x x 0x%x ", t, x); + bus_space_write_4(es->st, es->sh, ES1371_REG_CODEC, + ((addr << CODEC_POADD_SHIFT) & CODEC_POADD_MASK) | CODEC_PORD); + + /* restore SRC reg */ + es1371_wait_src_ready(s); + bus_space_write_4(es->st, es->sh, ES1371_REG_SMPRATE, x); + + splx(sl); + + /* now wait for the stinkin' data (RDY) */ + for (t = 0; t < 0x1000; t++) + if ((x = bus_space_read_4(es->st, es->sh, ES1371_REG_CODEC)) & CODEC_RDY) + break; + if (debug > 0) printf("loop 3 t 0x%x 0x%x ret 0x%x\n", t, x, ((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 } +}; +AC97_DECLARE(es1371_ac97); + +/* -------------------------------------------------------------------- */ + +static u_int +es1371_src_read(struct es_info *es, u_short reg) +{ + unsigned int 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); + bus_space_write_4(es->st, es->sh, ES1371_REG_SMPRATE,r); + 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){ + u_int 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); + /* printf("es1371_src_write 0x%x 0x%x\n",ES1371_REG_SMPRATE,r | ES1371_SRC_RAM_WE); */ + bus_space_write_4(es->st, es->sh, ES1371_REG_SMPRATE, r | ES1371_SRC_RAM_WE); +} + +static u_int +es1371_adc_rate(struct es_info *es, u_int rate, int set) +{ + u_int n, truncm, freq, result; + + 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; + + if (rate > 48000) rate = 48000; + if (rate < 4000) rate = 4000; + freq = (rate << 15) / 3000; + result = (freq * 3000) >> 15; + if (set) { + dac = (set == 1)? ES_SMPREG_DAC1 : ES_SMPREG_DAC2; + dis = (set == 1)? ES1371_DIS_P2 : ES1371_DIS_P1; + + r = (es1371_wait_src_ready(es) & (ES1371_DIS_SRC | ES1371_DIS_P1 | ES1371_DIS_P2 | ES1371_DIS_R1)); + bus_space_write_4(es->st, es->sh, ES1371_REG_SMPRATE, r); + 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)); + bus_space_write_4(es->st, es->sh, ES1371_REG_SMPRATE, r); + } + return result; +} + +static u_int +es1371_wait_src_ready(struct es_info *es) +{ + u_int t, r; + + for (t = 0; t < 500; t++) { + if (!((r = bus_space_read_4(es->st, es->sh, ES1371_REG_SMPRATE)) & ES1371_SRC_RAM_BUSY)) + return r; + DELAY(1000); + } + printf("es1371: wait src ready timeout 0x%x [0x%x]\n", ES1371_REG_SMPRATE, r); + return 0; +} + +/* -------------------------------------------------------------------- */ + +/* + * 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 0; + + case ES1371_PCI_ID: + switch(pci_get_revid(dev)) { + case ES1371REV_ES1371_A: + device_set_desc(dev, "AudioPCI ES1371-A"); + return 0; + + case ES1371REV_ES1371_B: + device_set_desc(dev, "AudioPCI ES1371-B"); + return 0; + + case ES1371REV_ES1373_A: + device_set_desc(dev, "AudioPCI ES1373-A"); + return 0; + + case ES1371REV_ES1373_B: + device_set_desc(dev, "AudioPCI ES1373-B"); + return 0; + + case ES1371REV_ES1373_8: + device_set_desc(dev, "AudioPCI ES1373-8"); + return 0; + + case ES1371REV_CT5880_A: + device_set_desc(dev, "Creative CT5880-A"); + return 0; + + default: + device_set_desc(dev, "AudioPCI ES1371-?"); + device_printf(dev, "unknown revision %d -- please report to cg@freebsd.org\n", pci_get_revid(dev)); + return 0; + } + + case ES1371_PCI_ID2: + device_set_desc(dev, "Strange AudioPCI ES1371-? (vid=3274)"); + device_printf(dev, "unknown revision %d -- please report to cg@freebsd.org\n", pci_get_revid(dev)); + return 0; + + case CT5880_PCI_ID: + switch(pci_get_revid(dev)) { + case CT5880REV_CT5880_C: + device_set_desc(dev, "Creative CT5880-C"); + return 0; + + case CT5880REV_CT5880_D: + device_set_desc(dev, "Creative CT5880-D"); + return 0; + + case CT5880REV_CT5880_E: + device_set_desc(dev, "Creative CT5880-E"); + return 0; + + default: + device_set_desc(dev, "Creative CT5880-?"); + device_printf(dev, "unknown revision %d -- please report to cg@freebsd.org\n", pci_get_revid(dev)); + return 0; + } + + default: + return ENXIO; + } +} + +static int +es_pci_attach(device_t dev) +{ + u_int32_t data; + struct es_info *es = 0; + int mapped; + char status[SND_STATUSLEN]; + struct ac97_info *codec = 0; + kobj_class_t ct = NULL; + + if ((es = malloc(sizeof *es, M_DEVBUF, M_NOWAIT | M_ZERO)) == NULL) { + device_printf(dev, "cannot allocate softc\n"); + return ENXIO; + } + + es->dev = dev; + mapped = 0; + 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); + if (mapped == 0 && (data & PCIM_CMD_MEMEN)) { + es->regid = MEM_MAP_REG; + es->regtype = SYS_RES_MEMORY; + es->reg = bus_alloc_resource(dev, es->regtype, &es->regid, + 0, ~0, 1, RF_ACTIVE); + if (es->reg) { + es->st = rman_get_bustag(es->reg); + es->sh = rman_get_bushandle(es->reg); + mapped++; + } + } + if (mapped == 0 && (data & PCIM_CMD_PORTEN)) { + es->regid = PCIR_MAPS; + es->regtype = SYS_RES_IOPORT; + es->reg = bus_alloc_resource(dev, es->regtype, &es->regid, + 0, ~0, 1, RF_ACTIVE); + if (es->reg) { + es->st = rman_get_bustag(es->reg); + es->sh = rman_get_bushandle(es->reg); + mapped++; + } + } + if (mapped == 0) { + device_printf(dev, "unable to map register space\n"); + goto bad; + } + + es->bufsz = pcm_getbuffersize(dev, 4096, ES_DEFAULT_BUFSZ, 65536); + + if (pci_get_devid(dev) == ES1371_PCI_ID || + pci_get_devid(dev) == ES1371_PCI_ID2 || + pci_get_devid(dev) == CT5880_PCI_ID) { + if(-1 == es1371_init(es, dev)) { + device_printf(dev, "unable to initialize the card\n"); + goto bad; + } + 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; + } else if (pci_get_devid(dev) == ES1370_PCI_ID) { + if (-1 == es1370_init(es)) { + device_printf(dev, "unable to initialize the card\n"); + goto bad; + } + if (mixer_init(dev, &es1370_mixer_class, es)) goto bad; + ct = &eschan1370_class; + } else goto bad; + + es->irqid = 0; + es->irq = bus_alloc_resource(dev, SYS_RES_IRQ, &es->irqid, + 0, ~0, 1, RF_ACTIVE | RF_SHAREABLE); + if (!es->irq || snd_setup_intr(dev, es->irq, 0, es_intr, es, &es->ih)) { + device_printf(dev, "unable to map interrupt\n"); + 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, &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", + (es->regtype == SYS_RES_IOPORT)? "io" : "memory", + rman_get_start(es->reg), rman_get_start(es->irq)); + + if (pcm_register(dev, es, 1, 1)) goto bad; + pcm_addchan(dev, PCMDIR_REC, ct, es); + pcm_addchan(dev, PCMDIR_PLAY, ct, es); + pcm_setstatus(dev, status); + + return 0; + + bad: + if (codec) ac97_destroy(codec); + if (es->reg) bus_release_resource(dev, es->regtype, es->regid, es->reg); + 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 (es->parent_dmat) bus_dma_tag_destroy(es->parent_dmat); + 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; + + es = pcm_getdevinfo(dev); + bus_release_resource(dev, es->regtype, es->regid, es->reg); + bus_teardown_intr(dev, es->irq, es->ih); + bus_release_resource(dev, SYS_RES_IRQ, es->irqid, es->irq); + bus_dma_tag_destroy(es->parent_dmat); + free(es, M_DEVBUF); + + 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), + + { 0, 0 } +}; + +static driver_t es_driver = { + "pcm", + es_methods, + PCM_SOFTC_SIZE, +}; + +DRIVER_MODULE(snd_es137x, pci, es_driver, pcm_devclass, 0, 0); +MODULE_DEPEND(snd_es137x, snd_pcm, PCM_MINVER, PCM_PREFVER, PCM_MAXVER); +MODULE_VERSION(snd_es137x, 1); diff --git a/sys/dev/sound/pci/es137x.h b/sys/dev/sound/pci/es137x.h new file mode 100644 index 0000000..076fe3c --- /dev/null +++ b/sys/dev/sound/pci/es137x.h @@ -0,0 +1,183 @@ +/* + * This supports the ENSONIQ AudioPCI board based on the ES1370. + * + * Copyright (c) 1998 Joachim Kuebart <joki@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$ + */ + +#ifndef _ES1370_REG_H +#define _ES1370_REG_H + +#define ES1370_REG_CONTROL 0x00 +#define ES1370_REG_STATUS 0x04 +#define ES1370_REG_UART_DATA 0x08 +#define ES1370_REG_UART_STATUS 0x09 +#define ES1370_REG_UART_CONTROL 0x09 +#define ES1370_REG_UART_TEST 0x0a +#define ES1370_REG_MEMPAGE 0x0c +#define ES1370_REG_CODEC 0x10 +#define CODEC_INDEX_SHIFT 8 +#define ES1370_REG_SERIAL_CONTROL 0x20 +#define ES1370_REG_DAC1_SCOUNT 0x24 +#define ES1370_REG_DAC2_SCOUNT 0x28 +#define ES1370_REG_ADC_SCOUNT 0x2c + +#define ES1370_REG_DAC1_FRAMEADR 0xc30 +#define ES1370_REG_DAC1_FRAMECNT 0xc34 +#define ES1370_REG_DAC2_FRAMEADR 0xc38 +#define ES1370_REG_DAC2_FRAMECNT 0xc3c +#define ES1370_REG_ADC_FRAMEADR 0xd30 +#define ES1370_REG_ADC_FRAMECNT 0xd34 + +#define DAC2_SRTODIV(x) (((1411200 + (x) / 2) / (x) - 2) & 0x1fff) +#define DAC2_DIVTOSR(x) (1411200 / ((x) + 2)) + +#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 */ +#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 */ +#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 */ +#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 */ +#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 */ +#define CTRL_DAC2_EN 0x00000020 /* enable DAC2 */ +#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) */ +#define CTRL_CDC_EN 0x00000002 /* enable serial (CODEC) interface */ +#define CTRL_SERR_DIS 0x00000001 /* 1 = disable PCI SERR signal */ + +#define SCTRL_P2ENDINC 0x00380000 /* */ +#define SCTRL_SH_P2ENDINC 19 +#define SCTRL_P2STINC 0x00070000 /* */ +#define SCTRL_SH_P2STINC 16 +#define SCTRL_R1LOOPSEL 0x00008000 /* 0 = loop mode */ +#define SCTRL_P2LOOPSEL 0x00004000 /* 0 = loop mode */ +#define SCTRL_P1LOOPSEL 0x00002000 /* 0 = loop mode */ +#define SCTRL_P2PAUSE 0x00001000 /* 1 = pause mode */ +#define SCTRL_P1PAUSE 0x00000800 /* 1 = pause mode */ +#define SCTRL_R1INTEN 0x00000400 /* enable interrupt */ +#define SCTRL_P2INTEN 0x00000200 /* enable interrupt */ +#define SCTRL_P1INTEN 0x00000100 /* enable interrupt */ +#define SCTRL_P1SCTRLD 0x00000080 /* reload sample count register for + * DAC1 */ +#define SCTRL_P2DACSEN 0x00000040 /* 1 = DAC2 play back last sample + * when disabled */ +#define SCTRL_R1SEB 0x00000020 /* 1 = 16bit */ +#define SCTRL_R1SMB 0x00000010 /* 1 = stereo */ +#define SCTRL_R1FMT 0x00000030 /* format mask */ +#define SCTRL_SH_R1FMT 4 +#define SCTRL_P2SEB 0x00000008 /* 1 = 16bit */ +#define SCTRL_P2SMB 0x00000004 /* 1 = stereo */ +#define SCTRL_P2FMT 0x0000000c /* format mask */ +#define SCTRL_SH_P2FMT 2 +#define SCTRL_P1SEB 0x00000002 /* 1 = 16bit */ +#define SCTRL_P1SMB 0x00000001 /* 1 = stereo */ +#define SCTRL_P1FMT 0x00000003 /* format mask */ +#define SCTRL_SH_P1FMT 0 + +#define STAT_INTR 0x80000000 /* wired or of all interrupt bits */ +#define STAT_CSTAT 0x00000400 /* 1 = codec busy or codec write in + * 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 */ +#define STAT_SH_VC 5 +#define STAT_MCCB 0x00000010 /* CCB int pending */ +#define STAT_UART 0x00000008 /* UART int pending */ +#define STAT_DAC1 0x00000004 /* DAC1 int pending */ +#define STAT_DAC2 0x00000002 /* DAC2 int pending */ +#define STAT_ADC 0x00000001 /* ADC int pending */ + +#define CODEC_OMIX1 0x10 +#define CODEC_OMIX2 0x11 +#define CODEC_LIMIX1 0x12 +#define CODEC_RIMIX1 0x13 +#define CODEC_LIMIX2 0x14 +#define CODEC_RIMIX2 0x15 +#define CODEC_RES_PD 0x16 +#define CODEC_CSEL 0x17 +#define CODEC_ADSEL 0x18 +#define CODEC_MGAIN 0x19 + +/* ES1371 specific */ + +#define CODEC_ID_SESHIFT 10 +#define CODEC_ID_SEMASK 0x1f + +#define CODEC_PIRD 0x00800000 /* 0 = write AC97 register */ +#define CODEC_PIADD_MASK 0x007f0000 +#define CODEC_PIADD_SHIFT 16 +#define CODEC_PIDAT_MASK 0x0000ffff +#define CODEC_PIDAT_SHIFT 0 + +#define CODEC_PORD 0x00800000 /* 0 = write AC97 register */ +#define CODEC_POADD_MASK 0x007f0000 +#define CODEC_POADD_SHIFT 16 +#define CODEC_PODAT_MASK 0x0000ffff +#define CODEC_PODAT_SHIFT 0 + +#define CODEC_RDY 0x80000000 /* AC97 read data valid */ +#define CODEC_WIP 0x40000000 /* AC97 write in progress */ + +#define ES1370_REG_CONTROL 0x00 +#define ES1370_REG_SERIAL_CONTROL 0x20 +#define ES1371_REG_CODEC 0x14 +#define ES1371_REG_LEGACY 0x18 /* W/R: Legacy control/status register */ +#define ES1371_REG_SMPRATE 0x10 /* W/R: Codec rate converter interface register */ + +#define ES1371_SYNC_RES (1<<14) /* Warm AC97 reset */ +#define ES1371_DIS_R1 (1<<19) /* record channel accumulator update disable */ +#define ES1371_DIS_P2 (1<<20) /* playback channel 2 accumulator update disable */ +#define ES1371_DIS_P1 (1<<21) /* playback channel 1 accumulator update disable */ +#define ES1371_DIS_SRC (1<<22) /* sample rate converter disable */ +#define ES1371_SRC_RAM_BUSY (1<<23) /* R/O: sample rate memory is busy */ +#define ES1371_SRC_RAM_WE (1<<24) /* R/W: read/write control for sample rate converter */ +#define ES1371_SRC_RAM_ADDRO(o) (((o)&0x7f)<<25) /* address of the sample rate converter */ +#define ES1371_SRC_RAM_DATAO(o) (((o)&0xffff)<<0) /* current value of the sample rate converter */ +#define ES1371_SRC_RAM_DATAI(i) (((i)>>0)&0xffff) /* current value of the sample rate converter */ + +/* + * Sample rate converter addresses + */ + +#define ES_SMPREG_DAC1 0x70 +#define ES_SMPREG_DAC2 0x74 +#define ES_SMPREG_ADC 0x78 +#define ES_SMPREG_TRUNC_N 0x00 +#define ES_SMPREG_INT_REGS 0x01 +#define ES_SMPREG_VFREQ_FRAC 0x03 +#define ES_SMPREG_VOL_ADC 0x6c +#define ES_SMPREG_VOL_DAC1 0x7c +#define ES_SMPREG_VOL_DAC2 0x7e + +#endif diff --git a/sys/dev/sound/pci/fm801.c b/sys/dev/sound/pci/fm801.c new file mode 100644 index 0000000..c42da08 --- /dev/null +++ b/sys/dev/sound/pci/fm801.c @@ -0,0 +1,801 @@ +/* + * Copyright (c) 2000 Dmitry Dicky diwil@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 <pci/pcireg.h> +#include <pci/pcivar.h> + +SND_DECLARE_FILE("$FreeBSD$"); + +#define PCI_VENDOR_FORTEMEDIA 0x1319 +#define PCI_DEVICE_FORTEMEDIA1 0x08011319 +#define PCI_DEVICE_FORTEMEDIA2 0x08021319 /* ??? have no idea what's this... */ + +#define FM_PCM_VOLUME 0x00 +#define FM_FM_VOLUME 0x02 +#define FM_I2S_VOLUME 0x04 +#define FM_RECORD_SOURCE 0x06 + +#define FM_PLAY_CTL 0x08 +#define FM_PLAY_RATE_MASK 0x0f00 +#define FM_PLAY_BUF1_LAST 0x0001 +#define FM_PLAY_BUF2_LAST 0x0002 +#define FM_PLAY_START 0x0020 +#define FM_PLAY_PAUSE 0x0040 +#define FM_PLAY_STOPNOW 0x0080 +#define FM_PLAY_16BIT 0x4000 +#define FM_PLAY_STEREO 0x8000 + +#define FM_PLAY_DMALEN 0x0a +#define FM_PLAY_DMABUF1 0x0c +#define FM_PLAY_DMABUF2 0x10 + + +#define FM_REC_CTL 0x14 +#define FM_REC_RATE_MASK 0x0f00 +#define FM_REC_BUF1_LAST 0x0001 +#define FM_REC_BUF2_LAST 0x0002 +#define FM_REC_START 0x0020 +#define FM_REC_PAUSE 0x0040 +#define FM_REC_STOPNOW 0x0080 +#define FM_REC_16BIT 0x4000 +#define FM_REC_STEREO 0x8000 + + +#define FM_REC_DMALEN 0x16 +#define FM_REC_DMABUF1 0x18 +#define FM_REC_DMABUF2 0x1c + +#define FM_CODEC_CTL 0x22 +#define FM_VOLUME 0x26 +#define FM_VOLUME_MUTE 0x8000 + +#define FM_CODEC_CMD 0x2a +#define FM_CODEC_CMD_READ 0x0080 +#define FM_CODEC_CMD_VALID 0x0100 +#define FM_CODEC_CMD_BUSY 0x0200 + +#define FM_CODEC_DATA 0x2c + +#define FM_IO_CTL 0x52 +#define FM_CARD_CTL 0x54 + +#define FM_INTMASK 0x56 +#define FM_INTMASK_PLAY 0x0001 +#define FM_INTMASK_REC 0x0002 +#define FM_INTMASK_VOL 0x0040 +#define FM_INTMASK_MPU 0x0080 + +#define FM_INTSTATUS 0x5a +#define FM_INTSTATUS_PLAY 0x0100 +#define FM_INTSTATUS_REC 0x0200 +#define FM_INTSTATUS_VOL 0x4000 +#define FM_INTSTATUS_MPU 0x8000 + +#define FM801_DEFAULT_BUFSZ 4096 /* Other values do not work!!! */ + +/* debug purposes */ +#define DPRINT if(0) printf + +/* +static int fm801ch_setup(struct pcm_channel *c); +*/ + +static u_int32_t fmts[] = { + AFMT_U8, + AFMT_STEREO | AFMT_U8, + AFMT_S16_LE, + AFMT_STEREO | AFMT_S16_LE, + 0 +}; + +static struct pcmchan_caps fm801ch_caps = { + 4000, 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 { + 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; + + struct fm801_chinfo pch, rch; + + 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; + } +} + +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; + } +} + +/* -------------------------------------------------------------------- */ +/* + * 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; + + 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; + } + + 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; + + DPRINT("fm801_wrcd reg 0x%x val 0x%x\n",regno, data); +/* + 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 - 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 } +}; +AC97_DECLARE(fm801_ac97); + +/* -------------------------------------------------------------------- */ + +/* + * 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); + + 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_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 clear\n\n"); + fm801_wr(fm801, FM_INTSTATUS, intsrc & (FM_INTSTATUS_PLAY | FM_INTSTATUS_REC), 2); +} + +/* -------------------------------------------------------------------- */ +/* channel interface */ +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; + + 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, fm801->bufsz) == -1) 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, %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; +} + +struct { + 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 }, +/* 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; + + + 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_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; + + 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; + + if(ch->dir == PCMDIR_PLAY) { + if(fm801->play_flip) return fm801->play_blksize; + fm801->play_blksize = blocksize; + } + + if(ch->dir == PCMDIR_REC) { + if(fm801->rec_flip) return fm801->rec_blksize; + fm801->rec_blksize = blocksize; + } + + DPRINT("fm801ch_setblocksize %d (dir %d)\n",blocksize, ch->dir); + + 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); + } + } + + 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; + } + + return result; +} + +static struct pcmchan_caps * +fm801ch_getcaps(kobj_t obj, void *data) +{ + 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 } +}; +CHANNEL_DECLARE(fm801ch); + +/* -------------------------------------------------------------------- */ + +/* + * Init routine is taken from an original NetBSD driver + */ +static int +fm801_init(struct fm801_info *fm801) +{ + 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); + + 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 softc\n"); + 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_MAPS + i*4; + fm801->regtype = SYS_RES_MEMORY; + fm801->reg = bus_alloc_resource(dev, fm801->regtype, &fm801->regid, + 0, ~0, 1, RF_ACTIVE); + if(!fm801->reg) + { + fm801->regtype = SYS_RES_IOPORT; + fm801->reg = bus_alloc_resource(dev, fm801->regtype, &fm801->regid, + 0, ~0, 1, 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(dev, SYS_RES_IRQ, &fm801->irqid, + 0, ~0, 1, 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*/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, &fm801->parent_dmat) != 0) { + device_printf(dev, "unable to create dma tag\n"); + goto oops; + } + + snprintf(status, 64, "at %s 0x%lx irq %ld", + (fm801->regtype == SYS_RES_IOPORT)? "io" : "memory", + rman_get_start(fm801->reg), rman_get_start(fm801->irq)); + +#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); + + fm801->radio = device_add_child(dev, "radio", -1); + bus_generic_attach(dev); + + 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; +} + +static int +fm801_pci_detach(device_t dev) +{ + int r; + struct fm801_info *fm801; + + DPRINT("Forte Media FM801 detach\n"); + + 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; +} + +static int +fm801_pci_probe( device_t dev ) +{ + u_int32_t data; + int id, regtype, regid, result; + struct resource *reg; + bus_space_tag_t st; + bus_space_handle_t sh; + + result = ENXIO; + + if ((id = pci_get_devid(dev)) == PCI_DEVICE_FORTEMEDIA1 ) { + 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); + + regid = PCIR_MAPS; + regtype = SYS_RES_IOPORT; + reg = bus_alloc_resource(dev, regtype, ®id, 0, ~0, 1, + RF_ACTIVE); + + if (reg == NULL) + return ENXIO; + + st = rman_get_bustag(reg); + sh = rman_get_bushandle(reg); + /* + * XXX: quick check that device actually has sound capabilities. + * The problem is that some cards built around FM801 chip only + * have radio tuner onboard, but no sound capabilities. There + * is no "official" way to quickly check this, because all + * IDs are exactly the same. The only difference is 0x28 + * device control register, described in FM801 specification + * as "SRC/Mixer Test Control/DFC Status", but without + * any more detailed explanation. According to specs, and + * available sample cards (SF256-PCP-R and SF256-PCS-R) its + * power-on value should be `0', while on AC97-less tuner + * card (SF64-PCR) it was 0x80. + */ + if (bus_space_read_1(st, sh, 0x28) == 0) { + device_set_desc(dev, + "Forte Media FM801 Audio Controller"); + result = 0; + } + + bus_release_resource(dev, regtype, regid, reg); + } +/* + if ((id = pci_get_devid(dev)) == PCI_DEVICE_FORTEMEDIA2 ) { + device_set_desc(dev, "Forte Media FM801 Joystick (Not Supported)"); + return ENXIO; + } +*/ + return (result); +} + +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) +{ + struct fm801_info *fm801; + + fm801 = pcm_getdevinfo(bus); + + if (type == SYS_RES_IOPORT && *rid == PCIR_MAPS) + return (fm801->reg); + + return (NULL); +} + +static int +fm801_release_resource(device_t bus, device_t child, int type, int rid, + struct resource *r) +{ + 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} +}; + +static driver_t fm801_driver = { + "pcm", + fm801_methods, + PCM_SOFTC_SIZE, +}; + +DRIVER_MODULE(snd_fm801, pci, fm801_driver, pcm_devclass, 0, 0); +MODULE_DEPEND(snd_fm801, snd_pcm, PCM_MINVER, PCM_PREFVER, PCM_MAXVER); +MODULE_VERSION(snd_fm801, 1); diff --git a/sys/dev/sound/pci/ich.c b/sys/dev/sound/pci/ich.c new file mode 100644 index 0000000..aa5e856 --- /dev/null +++ b/sys/dev/sound/pci/ich.c @@ -0,0 +1,867 @@ +/* + * Copyright (c) 2000 Katsurajima Naoto <raven@katsurajima.seya.yokohama.jp> + * Copyright (c) 2001 Cameron Grant <cg@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> +#include <dev/sound/pci/ich.h> + +#include <pci/pcireg.h> +#include <pci/pcivar.h> + +SND_DECLARE_FILE("$FreeBSD$"); + +/* -------------------------------------------------------------------- */ + +#define ICH_TIMEOUT 1000 /* semaphore timeout polling count */ +#define ICH_DTBL_LENGTH 32 +#define ICH_DEFAULT_BUFSZ 16384 +#define ICH_MAX_BUFSZ 65536 + +#define SIS7012ID 0x70121039 /* SiS 7012 needs special handling */ +#define ICH4ID 0x24c58086 /* ICH4 needs special handling too */ + +/* buffer descriptor */ +struct ich_desc { + volatile u_int32_t buffer; + volatile u_int32_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; + + 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 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; +}; + +/* -------------------------------------------------------------------- */ + +static u_int32_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 u_int32_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; + } +} + +static void +ich_wr(struct sc_info *sc, int regno, u_int32_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; + } +} + +/* 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; + } + 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; + + regno &= 0xff; + ich_waitcd(sc); + + 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) +{ + struct sc_info *sc = (struct sc_info *)devinfo; + + regno &= 0xff; + ich_waitcd(sc); + bus_space_write_2(sc->nambart, sc->nambarh, regno, data); + + return 0; +} + +static kobj_method_t ich_ac97_methods[] = { + KOBJMETHOD(ac97_read, ich_rdcd), + KOBJMETHOD(ac97_write, ich_wrcd), + { 0, 0 } +}; +AC97_DECLARE(ich_ac97); + +/* -------------------------------------------------------------------- */ +/* common routines */ + +static void +ich_filldtbl(struct sc_chinfo *ch) +{ + u_int32_t base; + int i; + + base = sndbuf_getbufaddr(ch->buffer); + ch->blkcnt = sndbuf_getsize(ch->buffer) / ch->blksz; + if (ch->blkcnt != 2 && ch->blkcnt != 4 && ch->blkcnt != 8 && ch->blkcnt != 16 && ch->blkcnt != 32) { + ch->blkcnt = 2; + ch->blksz = sndbuf_getsize(ch->buffer) / ch->blkcnt; + } + + 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; + + 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); + DELAY(100); + 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 %d\n", num); + return ENXIO; +} + +/* -------------------------------------------------------------------- */ +/* channel interface */ + +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; + + 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; + } + + if (sndbuf_alloc(ch->buffer, sc->dmat, sc->bufsz)) + return NULL; + + ich_wr(sc, ch->regbase + ICH_REG_X_BDBAR, (u_int32_t)(ch->desc_addr), 4); + + return ch; +} + +static int +ichchan_setformat(kobj_t obj, void *data, u_int32_t format) +{ + return 0; +} + +static int +ichchan_setspeed(kobj_t obj, void *data, u_int32_t speed) +{ + struct sc_chinfo *ch = data; + struct sc_info *sc = ch->parent; + + if (ch->spdreg) { + int r; + if (sc->ac97rate <= 32000 || sc->ac97rate >= 64000) + sc->ac97rate = 48000; + r = (speed * 48000) / sc->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) * + sc->ac97rate) / 48000; + } else { + ch->spd = 48000; + } + return ch->spd; +} + +static int +ichchan_setblocksize(kobj_t obj, void *data, u_int32_t blocksize) +{ + struct sc_chinfo *ch = data; + struct sc_info *sc = ch->parent; + + ch->blksz = blocksize; + ich_filldtbl(ch); + ich_wr(sc, ch->regbase + ICH_REG_X_LVI, ch->blkcnt - 1, 1); + + 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; + + switch (go) { + case PCMTRIG_START: + ch->run = 1; + 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); + break; + + case PCMTRIG_ABORT: + ich_resetchan(sc, ch->num); + ch->run = 0; + 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; + + ch->civ = ich_rd(sc, ch->regbase + ICH_REG_X_CIV, 1) % ch->blkcnt; + + pos = ch->civ * ch->blksz; + + return pos; +} + +static struct pcmchan_caps * +ichchan_getcaps(kobj_t obj, void *data) +{ + struct sc_chinfo *ch = data; + + 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 } +}; +CHANNEL_DECLARE(ichchan); + +/* -------------------------------------------------------------------- */ +/* The interrupt handler */ + +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; + + 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) + chn_intr(ch->channel); + 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); + } + 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). + */ + +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)"); +#endif /* SND_DYNSYSCTL */ + 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) +{ + 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]; + + if (sc->use_intrhook) + config_intrhook_disestablish(&sc->intrhook); + + /* + * 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")); + + 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); + } + 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 us\n", wait_us); + return; + } + + actual_48k_rate = (bytes * 250000) / wait_us; + + 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"); + } + + return; +} + +/* -------------------------------------------------------------------- */ +/* Probe and attach the card */ + +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; +} + +static int +ich_init(struct sc_info *sc) +{ + u_int32_t stat; + int sz; + + 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 may fail when busmastering is enabled. Continue */ + if (pci_get_devid(sc->dev) != ICH4ID) { + return ENXIO; + } + } + + ich_wr(sc, ICH_REG_GLOB_CNT, ICH_GLOB_CTL_COLD | ICH_GLOB_CTL_PRES, 4); + + if (ich_resetchan(sc, 0) || ich_resetchan(sc, 1)) + return ENXIO; + if (sc->hasmic && ich_resetchan(sc, 2)) + return ENXIO; + + if (bus_dmamem_alloc(sc->dmat, (void **)&sc->dtbl, BUS_DMA_NOWAIT, &sc->dtmap)) + return ENOSPC; + + sz = sizeof(struct ich_desc) * ICH_DTBL_LENGTH * 3; + if (bus_dmamap_load(sc->dmat, sc->dtmap, sc->dtbl, sz, ich_setmap, sc, 0)) { + bus_dmamem_free(sc->dmat, (void **)&sc->dtbl, sc->dtmap); + return ENOSPC; + } + + return 0; +} + +static int +ich_pci_probe(device_t dev) +{ + switch(pci_get_devid(dev)) { + case 0x71958086: + device_set_desc(dev, "Intel 443MX"); + return 0; + + case 0x24158086: + device_set_desc(dev, "Intel 82801AA (ICH)"); + return 0; + + case 0x24258086: + device_set_desc(dev, "Intel 82801AB (ICH)"); + return 0; + + case 0x24458086: + device_set_desc(dev, "Intel 82801BA (ICH2)"); + return 0; + + case 0x24858086: + device_set_desc(dev, "Intel 82801CA (ICH3)"); + return 0; + + case ICH4ID: + device_set_desc(dev, "Intel 82801DB (ICH4)"); + return 0; + + case SIS7012ID: + device_set_desc(dev, "SiS 7012"); + return 0; + + case 0x01b110de: + device_set_desc(dev, "Nvidia nForce AC97 controller"); + return 0; + + case 0x006a10de: + device_set_desc(dev, "Nvidia nForce2 AC97 controller"); + return 0; + + default: + return ENXIO; + } +} + +static int +ich_pci_attach(device_t dev) +{ + u_int16_t extcaps; + struct sc_info *sc; + char status[SND_STATUSLEN]; + + if ((sc = malloc(sizeof(*sc), M_DEVBUF, M_NOWAIT)) == NULL) { + device_printf(dev, "cannot allocate softc\n"); + return ENXIO; + } + + bzero(sc, sizeof(*sc)); + sc->dev = dev; + + /* + * The SiS 7012 register set isn't quite like the standard ich. + * There really should be a general "quirks" mechanism. + */ + if (pci_get_devid(dev) == SIS7012ID) { + sc->swap_reg = 1; + sc->sample_size = 1; + } else { + sc->swap_reg = 0; + sc->sample_size = 2; + } + + /* + * 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 (pci_get_devid(dev) == ICH4ID) { + pci_write_config(dev, PCIR_ICH_LEGACY, ICH_LEGACY_ENABLE, 1); + } + + /* + * Enable bus master. On ich4 this may prevent the detection of + * the primary codec becoming ready in ich_init(). + */ + pci_enable_busmaster(dev); + + sc->nambarid = PCIR_NAMBAR; + sc->nabmbarid = PCIR_NABMBAR; + sc->nambar = bus_alloc_resource(dev, SYS_RES_IOPORT, &sc->nambarid, 0, ~0, 1, RF_ACTIVE); + sc->nabmbar = bus_alloc_resource(dev, SYS_RES_IOPORT, &sc->nabmbarid, 0, ~0, 1, 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, 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, &sc->dmat) != 0) { + device_printf(dev, "unable to create dma tag\n"); + goto bad; + } + + 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, 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; + 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", + rman_get_start(sc->nambar), rman_get_start(sc->nabmbar), rman_get_start(sc->irq), sc->bufsz); + + 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 now\n"); + sc->use_intrhook = 0; + ich_calibrate(sc); + } + + 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, SYS_RES_IOPORT, + sc->nambarid, sc->nambar); + if (sc->nabmbar) + bus_release_resource(dev, SYS_RES_IOPORT, + sc->nabmbarid, sc->nabmbar); + free(sc, M_DEVBUF); + return ENXIO; +} + +static int +ich_pci_detach(device_t dev) +{ + 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, SYS_RES_IOPORT, sc->nambarid, sc->nambar); + bus_release_resource(dev, SYS_RES_IOPORT, sc->nabmbarid, sc->nabmbar); + bus_dma_tag_destroy(sc->dmat); + free(sc, M_DEVBUF); + return 0; +} + +static int +ich_pci_suspend(device_t dev) +{ + struct sc_info *sc; + int i; + + sc = pcm_getdevinfo(dev); + for (i = 0 ; i < 3; i++) { + sc->ch[i].run_save = sc->ch[i].run; + if (sc->ch[i].run) { + ichchan_trigger(0, &sc->ch[i], PCMTRIG_ABORT); + } + } + return 0; +} + +static int +ich_pci_resume(device_t dev) +{ + struct sc_info *sc; + int i; + + sc = pcm_getdevinfo(dev); + + /* Reinit audio device */ + if (ich_init(sc) == -1) { + device_printf(dev, "unable to reinitialize the card\n"); + return ENXIO; + } + /* Reinit mixer */ + 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 } +}; + +static driver_t ich_driver = { + "pcm", + ich_methods, + PCM_SOFTC_SIZE, +}; + +DRIVER_MODULE(snd_ich, pci, ich_driver, pcm_devclass, 0, 0); +MODULE_DEPEND(snd_ich, snd_pcm, PCM_MINVER, PCM_PREFVER, PCM_MAXVER); +MODULE_VERSION(snd_ich, 1); diff --git a/sys/dev/sound/pci/ich.h b/sys/dev/sound/pci/ich.h new file mode 100644 index 0000000..4f3ac9d --- /dev/null +++ b/sys/dev/sound/pci/ich.h @@ -0,0 +1,95 @@ +/* + * Copyright (c) 2000 Katsurajima Naoto <raven@katsurajima.seya.yokohama.jp> + * Copyright (c) 2001 Cameron Grant <cg@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$ + */ + +#define PCIR_NAMBAR 0x10 +#define PCIR_NABMBAR 0x14 + +#define PCIR_ICH_LEGACY 0x41 +#define ICH_LEGACY_ENABLE 0x01 + +/* Native Audio Bus Master Control Registers */ +#define ICH_REG_X_BDBAR 0x00 +#define ICH_REG_X_CIV 0x04 +#define ICH_REG_X_LVI 0x05 +#define ICH_REG_X_SR 0x06 +#define ICH_REG_X_PICB 0x08 +#define ICH_REG_X_PIV 0x0a +#define ICH_REG_X_CR 0x0b + +#define ICH_REG_PI_BASE 0x00 +#define ICH_REG_PO_BASE 0x10 +#define ICH_REG_MC_BASE 0x20 + +#define ICH_REG_GLOB_CNT 0x2c +#define ICH_REG_GLOB_STA 0x30 +#define ICH_REG_ACC_SEMA 0x34 + +/* Status Register Values */ +#define ICH_X_SR_DCH 0x0001 +#define ICH_X_SR_CELV 0x0002 +#define ICH_X_SR_LVBCI 0x0004 +#define ICH_X_SR_BCIS 0x0008 +#define ICH_X_SR_FIFOE 0x0010 + +/* Control Register Values */ +#define ICH_X_CR_RPBM 0x01 +#define ICH_X_CR_RR 0x02 +#define ICH_X_CR_LVBIE 0x04 +#define ICH_X_CR_FEIE 0x08 +#define ICH_X_CR_IOCE 0x10 + +/* Global Control Register Values */ +#define ICH_GLOB_CTL_GIE 0x00000001 +#define ICH_GLOB_CTL_COLD 0x00000002 /* negate */ +#define ICH_GLOB_CTL_WARM 0x00000004 +#define ICH_GLOB_CTL_SHUT 0x00000008 +#define ICH_GLOB_CTL_PRES 0x00000010 +#define ICH_GLOB_CTL_SRES 0x00000020 + +/* Global Status Register Values */ +#define ICH_GLOB_STA_GSCI 0x00000001 +#define ICH_GLOB_STA_MIINT 0x00000002 +#define ICH_GLOB_STA_MOINT 0x00000004 +#define ICH_GLOB_STA_PIINT 0x00000020 +#define ICH_GLOB_STA_POINT 0x00000040 +#define ICH_GLOB_STA_MINT 0x00000080 +#define ICH_GLOB_STA_PCR 0x00000100 +#define ICH_GLOB_STA_SCR 0x00000200 +#define ICH_GLOB_STA_PRES 0x00000400 +#define ICH_GLOB_STA_SRES 0x00000800 +#define ICH_GLOB_STA_SLOT12 0x00007000 +#define ICH_GLOB_STA_RCODEC 0x00008000 +#define ICH_GLOB_STA_AD3 0x00010000 +#define ICH_GLOB_STA_MD3 0x00020000 +#define ICH_GLOB_STA_IMASK (ICH_GLOB_STA_MIINT | ICH_GLOB_STA_MOINT | ICH_GLOB_STA_PIINT | ICH_GLOB_STA_POINT | ICH_GLOB_STA_MINT | ICH_GLOB_STA_PRES | ICH_GLOB_STA_SRES) + +/* play/record buffer */ +#define ICH_BDC_IOC 0x80000000 +#define ICH_BDC_BUP 0x40000000 + diff --git a/sys/dev/sound/pci/maestro.c b/sys/dev/sound/pci/maestro.c new file mode 100644 index 0000000..c479171 --- /dev/null +++ b/sys/dev/sound/pci/maestro.c @@ -0,0 +1,1194 @@ +/*- + * Copyright (c) 2000 Taku YAMAMOTO <taku@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. + * + * $Id: maestro.c,v 1.12 2000/09/06 03:32:34 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@linux.org>, modified heavily by + * Zach Brown <zab@zabbo.net>. + * + * busdma()-ize and buffer size reduction were suggested by + * Cameron Grant <gandalf@vilnya.demon.co.uk>. + * 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@tk.kubota.co.jp>, + * who brought patches based on the Linux driver with some simplification. + */ + +#include <dev/sound/pcm/sound.h> +#include <dev/sound/pcm/ac97.h> +#include <pci/pcireg.h> +#include <pci/pcivar.h> + +#include <dev/sound/pci/maestro_reg.h> + +SND_DECLARE_FILE("$FreeBSD$"); + +#define inline __inline + +/* + * 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 +#define MAESTRO_2E_PCI_ID 0x1978125d + +#define NEC_SUBID1 0x80581033 /* Taken from Linux driver */ +#define NEC_SUBID2 0x803c1033 /* NEC VersaProNX VA26D */ + +#ifndef AGG_MAXPLAYCH +# define AGG_MAXPLAYCH 4 +#endif + +#define AGG_DEFAULT_BUFSZ 0x4000 /* 0x1000, but gets underflows */ + + +/* ----------------------------- + * Data structures. + */ +struct agg_chinfo { + struct agg_info *parent; + struct pcm_channel *channel; + struct snd_dbuf *buffer; + bus_addr_t offset; + u_int32_t blocksize; + u_int32_t speed; + int dir; + u_int num; + u_int16_t aputype; + u_int16_t wcreg_tpl; +}; + +struct agg_info { + device_t dev; + struct resource *reg; + int regid; + + bus_space_tag_t st; + bus_space_handle_t sh; + bus_dma_tag_t parent_dmat; + + struct resource *irq; + int irqid; + void *ih; + + u_int8_t *stat; + bus_addr_t baseaddr; + + struct ac97_info *codec; + struct mtx *lock; + + unsigned int bufsz; + u_int playchns, active; + struct agg_chinfo pch[AGG_MAXPLAYCH]; + struct agg_chinfo rch; +}; + +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*, int, u_int16_t); +static inline void wp_wrapu(struct agg_info*, int, 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_power(struct agg_info*, int); + +static void agg_init(struct agg_info*); + +static void aggch_start_dac(struct agg_chinfo*); +static void aggch_stop_dac(struct agg_chinfo*); + +static inline void suppress_jitter(struct agg_chinfo*); + +static inline u_int calc_timer_freq(struct agg_chinfo*); +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(struct agg_info*, u_int32_t, bus_addr_t*); +static void dma_free(struct agg_info*, void *); + +/* ----------------------------- + * Subsystems. + */ + +/* Codec/Ringbus */ + +/* -------------------------------------------------------------------- */ + +static u_int32_t +agg_ac97_init(kobj_t obj, void *sc) +{ + struct agg_info *ess = sc; + + return (bus_space_read_1(ess->st, ess->sh, PORT_CODEC_STAT) & CODEC_STAT_MASK)? 0 : 1; +} + +static int +agg_rdcodec(kobj_t obj, void *sc, int regno) +{ + struct agg_info *ess = sc; + unsigned t; + + /* We have to wait for a SAFE time to write addr/data */ + for (t = 0; t < 20; t++) { + if ((bus_space_read_1(ess->st, ess->sh, PORT_CODEC_STAT) + & CODEC_STAT_MASK) != CODEC_STAT_PROGLESS) + break; + DELAY(2); /* 20.8us / 13 */ + } + if (t == 20) + device_printf(ess->dev, "agg_rdcodec() PROGLESS timed out.\n"); + + bus_space_write_1(ess->st, ess->sh, PORT_CODEC_CMD, + CODEC_CMD_READ | regno); + DELAY(21); /* AC97 cycle = 20.8usec */ + + /* Wait for data retrieve */ + for (t = 0; t < 20; t++) { + if ((bus_space_read_1(ess->st, ess->sh, PORT_CODEC_STAT) + & CODEC_STAT_MASK) == CODEC_STAT_RW_DONE) + break; + DELAY(2); /* 20.8us / 13 */ + } + if (t == 20) + /* Timed out, but perform dummy read. */ + device_printf(ess->dev, "agg_rdcodec() RW_DONE timed out.\n"); + + return bus_space_read_2(ess->st, ess->sh, PORT_CODEC_REG); +} + +static int +agg_wrcodec(kobj_t obj, void *sc, int regno, u_int32_t data) +{ + unsigned t; + struct agg_info *ess = sc; + + /* We have to wait for a SAFE time to write addr/data */ + for (t = 0; t < 20; t++) { + if ((bus_space_read_1(ess->st, ess->sh, PORT_CODEC_STAT) + & CODEC_STAT_MASK) != CODEC_STAT_PROGLESS) + break; + DELAY(2); /* 20.8us / 13 */ + } + if (t == 20) { + /* Timed out. Abort writing. */ + device_printf(ess->dev, "agg_wrcodec() PROGLESS timed out.\n"); + return -1; + } + + bus_space_write_2(ess->st, ess->sh, PORT_CODEC_REG, data); + bus_space_write_1(ess->st, ess->sh, PORT_CODEC_CMD, + CODEC_CMD_WRITE | regno); + + return 0; +} + +static kobj_method_t agg_ac97_methods[] = { + KOBJMETHOD(ac97_init, agg_ac97_init), + KOBJMETHOD(ac97_read, agg_rdcodec), + KOBJMETHOD(ac97_write, agg_wrcodec), + { 0, 0 } +}; +AC97_DECLARE(agg_ac97); + +/* -------------------------------------------------------------------- */ + +static inline void +ringbus_setdest(struct agg_info *ess, int src, int dest) +{ + u_int32_t data; + + data = bus_space_read_4(ess->st, ess->sh, PORT_RINGBUS_CTRL); + data &= ~(0xfU << src); + data |= (0xfU & dest) << src; + bus_space_write_4(ess->st, ess->sh, PORT_RINGBUS_CTRL, data); +} + +/* Wave Processor */ + +static inline u_int16_t +wp_rdreg(struct agg_info *ess, u_int16_t reg) +{ + bus_space_write_2(ess->st, ess->sh, PORT_DSP_INDEX, reg); + return bus_space_read_2(ess->st, ess->sh, PORT_DSP_DATA); +} + +static inline void +wp_wrreg(struct agg_info *ess, u_int16_t reg, u_int16_t data) +{ + bus_space_write_2(ess->st, ess->sh, PORT_DSP_INDEX, reg); + bus_space_write_2(ess->st, ess->sh, PORT_DSP_DATA, data); +} + +static inline void +apu_setindex(struct agg_info *ess, u_int16_t reg) +{ + int t; + + wp_wrreg(ess, WPREG_CRAM_PTR, reg); + /* Sometimes WP fails to set apu register index. */ + for (t = 0; t < 1000; t++) { + if (bus_space_read_2(ess->st, ess->sh, PORT_DSP_DATA) == reg) + break; + bus_space_write_2(ess->st, ess->sh, PORT_DSP_DATA, reg); + } + if (t == 1000) + device_printf(ess->dev, "apu_setindex() timed out.\n"); +} + +static inline u_int16_t +wp_rdapu(struct agg_info *ess, int ch, u_int16_t reg) +{ + u_int16_t ret; + + apu_setindex(ess, ((unsigned)ch << 4) + reg); + ret = wp_rdreg(ess, WPREG_DATA_PORT); + return ret; +} + +static inline void +wp_wrapu(struct agg_info *ess, int ch, u_int16_t reg, u_int16_t data) +{ + int t; + + apu_setindex(ess, ((unsigned)ch << 4) + reg); + wp_wrreg(ess, WPREG_DATA_PORT, data); + for (t = 0; t < 1000; t++) { + if (bus_space_read_2(ess->st, ess->sh, PORT_DSP_DATA) == data) + break; + bus_space_write_2(ess->st, ess->sh, PORT_DSP_DATA, data); + } + if (t == 1000) + device_printf(ess->dev, "wp_wrapu() timed out.\n"); +} + +static inline void +wp_settimer(struct agg_info *ess, u_int freq) +{ + u_int clock = 48000 << 2; + u_int prescale = 0, divide = (freq != 0) ? (clock / freq) : ~0; + + RANGE(divide, 4, 32 << 8); + + for (; divide > 32 << 1; divide >>= 1) + prescale++; + divide = (divide + 1) >> 1; + + for (; prescale < 7 && divide > 2 && !(divide & 1); divide >>= 1) + prescale++; + + wp_wrreg(ess, WPREG_TIMER_ENABLE, 0); + wp_wrreg(ess, WPREG_TIMER_FREQ, + (prescale << WP_TIMER_FREQ_PRESCALE_SHIFT) | (divide - 1)); + wp_wrreg(ess, WPREG_TIMER_ENABLE, 1); +} + +static inline void +wp_starttimer(struct agg_info *ess) +{ + wp_wrreg(ess, WPREG_TIMER_START, 1); +} + +static inline void +wp_stoptimer(struct agg_info *ess) +{ + wp_wrreg(ess, WPREG_TIMER_START, 0); + bus_space_write_2(ess->st, ess->sh, PORT_INT_STAT, 1); +} + +/* WaveCache */ + +static inline u_int16_t +wc_rdreg(struct agg_info *ess, u_int16_t reg) +{ + bus_space_write_2(ess->st, ess->sh, PORT_WAVCACHE_INDEX, reg); + return bus_space_read_2(ess->st, ess->sh, PORT_WAVCACHE_DATA); +} + +static inline void +wc_wrreg(struct agg_info *ess, u_int16_t reg, u_int16_t data) +{ + bus_space_write_2(ess->st, ess->sh, PORT_WAVCACHE_INDEX, reg); + bus_space_write_2(ess->st, ess->sh, PORT_WAVCACHE_DATA, data); +} + +static inline u_int16_t +wc_rdchctl(struct agg_info *ess, int ch) +{ + return wc_rdreg(ess, ch << 3); +} + +static inline void +wc_wrchctl(struct agg_info *ess, int ch, u_int16_t data) +{ + wc_wrreg(ess, ch << 3, data); +} + +/* Power management */ + +static inline void +agg_power(struct agg_info *ess, int status) +{ + u_int8_t data; + + data = pci_read_config(ess->dev, CONF_PM_PTR, 1); + if (pci_read_config(ess->dev, data, 1) == PPMI_CID) + pci_write_config(ess->dev, data + PM_CTRL, status, 1); +} + + +/* ----------------------------- + * Controller. + */ + +static inline void +agg_initcodec(struct agg_info* ess) +{ + u_int16_t data; + + if (bus_space_read_4(ess->st, ess->sh, PORT_RINGBUS_CTRL) + & RINGBUS_CTRL_ACLINK_ENABLED) { + bus_space_write_4(ess->st, ess->sh, PORT_RINGBUS_CTRL, 0); + DELAY(104); /* 20.8us * (4 + 1) */ + } + /* XXX - 2nd codec should be looked at. */ + bus_space_write_4(ess->st, ess->sh, PORT_RINGBUS_CTRL, + RINGBUS_CTRL_AC97_SWRESET); + DELAY(2); + bus_space_write_4(ess->st, ess->sh, PORT_RINGBUS_CTRL, + RINGBUS_CTRL_ACLINK_ENABLED); + DELAY(21); + + agg_rdcodec(NULL, ess, 0); + if (bus_space_read_1(ess->st, ess->sh, PORT_CODEC_STAT) + & CODEC_STAT_MASK) { + bus_space_write_4(ess->st, ess->sh, PORT_RINGBUS_CTRL, 0); + DELAY(21); + + /* Try cold reset. */ + device_printf(ess->dev, "will perform cold reset.\n"); + data = bus_space_read_2(ess->st, ess->sh, PORT_GPIO_DIR); + if (pci_read_config(ess->dev, 0x58, 2) & 1) + data |= 0x10; + data |= 0x009 & + ~bus_space_read_2(ess->st, ess->sh, PORT_GPIO_DATA); + bus_space_write_2(ess->st, ess->sh, PORT_GPIO_MASK, 0xff6); + bus_space_write_2(ess->st, ess->sh, PORT_GPIO_DIR, + data | 0x009); + bus_space_write_2(ess->st, ess->sh, PORT_GPIO_DATA, 0x000); + DELAY(2); + bus_space_write_2(ess->st, ess->sh, PORT_GPIO_DATA, 0x001); + DELAY(1); + bus_space_write_2(ess->st, ess->sh, PORT_GPIO_DATA, 0x009); + DELAY(500000); + bus_space_write_2(ess->st, ess->sh, PORT_GPIO_DIR, data); + DELAY(84); /* 20.8us * 4 */ + bus_space_write_4(ess->st, ess->sh, PORT_RINGBUS_CTRL, + RINGBUS_CTRL_ACLINK_ENABLED); + DELAY(21); + } +} + +static void +agg_init(struct agg_info* ess) +{ + u_int32_t data; + + /* Setup PCI config registers. */ + + /* 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_CHIBUS | MAESTRO_POSTEDWRITE | MAESTRO_DMA_PCITIMING; + data &= ~MAESTRO_SWAP_LR; + pci_write_config(ess->dev, CONF_MAESTRO, data, 4); + + /* Reset direct sound. */ + bus_space_write_2(ess->st, ess->sh, PORT_HOSTINT_CTRL, + HOSTINT_CTRL_DSOUND_RESET); + DELAY(10000); /* XXX - too long? */ + bus_space_write_2(ess->st, ess->sh, PORT_HOSTINT_CTRL, 0); + DELAY(10000); + + /* Enable direct sound interruption and hardware volume control. */ + bus_space_write_2(ess->st, ess->sh, PORT_HOSTINT_CTRL, + HOSTINT_CTRL_DSOUND_INT_ENABLED | HOSTINT_CTRL_HWVOL_ENABLED); + + /* Setup Wave Processor. */ + + /* Enable WaveCache, set DMA base address. */ + wp_wrreg(ess, WPREG_WAVE_ROMRAM, + WP_WAVE_VIRTUAL_ENABLED | WP_WAVE_DRAM_ENABLED); + bus_space_write_2(ess->st, ess->sh, PORT_WAVCACHE_CTRL, + WAVCACHE_ENABLED | WAVCACHE_WTSIZE_4MB); + + for (data = WAVCACHE_PCMBAR; data < WAVCACHE_PCMBAR + 4; data++) + wc_wrreg(ess, data, ess->baseaddr >> WAVCACHE_BASEADDR_SHIFT); + + /* Setup Codec/Ringbus. */ + agg_initcodec(ess); + bus_space_write_4(ess->st, ess->sh, PORT_RINGBUS_CTRL, + RINGBUS_CTRL_RINGBUS_ENABLED | RINGBUS_CTRL_ACLINK_ENABLED); + + wp_wrreg(ess, WPREG_BASE, 0x8500); /* Parallel I/O */ + 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); + + /* Setup ASSP. Needed for Dell Inspiron 7500? */ + bus_space_write_1(ess->st, ess->sh, PORT_ASSP_CTRL_B, 0x00); + bus_space_write_1(ess->st, ess->sh, PORT_ASSP_CTRL_A, 0x03); + bus_space_write_1(ess->st, ess->sh, PORT_ASSP_CTRL_C, 0x00); + + /* + * 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@braithwaite.net> reported that + * NEC Versa LX doesn't need GPIO operation. */ + bus_space_write_2(ess->st, ess->sh, PORT_GPIO_MASK, 0x9ff); + bus_space_write_2(ess->st, ess->sh, PORT_GPIO_DIR, + bus_space_read_2(ess->st, ess->sh, PORT_GPIO_DIR) | 0x600); + bus_space_write_2(ess->st, ess->sh, PORT_GPIO_DATA, 0x200); + break; + } +} + +/* Channel controller. */ + +static void +aggch_start_dac(struct agg_chinfo *ch) +{ + bus_addr_t wpwa = APU_USE_SYSMEM | (ch->offset >> 9); + u_int size = ch->parent->bufsz >> 1; + u_int speed = ch->speed; + bus_addr_t offset = ch->offset >> 1; + u_int cp = 0; + u_int16_t apuch = ch->num << 1; + u_int dv; + int pan = 0; + + switch (ch->aputype) { + case APUTYPE_16BITSTEREO: + wpwa >>= 1; + size >>= 1; + offset >>= 1; + cp >>= 1; + /* FALLTHROUGH */ + case APUTYPE_8BITSTEREO: + pan = 8; + apuch++; + break; + case APUTYPE_8BITLINEAR: + speed >>= 1; + break; + } + + dv = (((speed % 48000) << 16) + 24000) / 48000 + + ((speed / 48000) << 16); + + do { + wp_wrapu(ch->parent, apuch, APUREG_WAVESPACE, wpwa & 0xff00); + wp_wrapu(ch->parent, apuch, APUREG_CURPTR, offset + cp); + wp_wrapu(ch->parent, apuch, APUREG_ENDPTR, offset + size); + wp_wrapu(ch->parent, apuch, APUREG_LOOPLEN, size); + wp_wrapu(ch->parent, apuch, APUREG_AMPLITUDE, 0xe800); + wp_wrapu(ch->parent, apuch, APUREG_POSITION, 0x8f00 + | (RADIUS_CENTERCIRCLE << APU_RADIUS_SHIFT) + | ((PAN_FRONT + pan) << APU_PAN_SHIFT)); + wp_wrapu(ch->parent, apuch, APUREG_FREQ_LOBYTE, APU_plus6dB + | ((dv & 0xff) << APU_FREQ_LOBYTE_SHIFT)); + wp_wrapu(ch->parent, apuch, APUREG_FREQ_HIWORD, dv >> 8); + + if (ch->aputype == APUTYPE_16BITSTEREO) + wpwa |= APU_STEREO >> 1; + pan = -pan; + } while (pan < 0 && apuch--); + + wc_wrchctl(ch->parent, apuch, ch->wcreg_tpl); + wc_wrchctl(ch->parent, apuch + 1, ch->wcreg_tpl); + + wp_wrapu(ch->parent, apuch, APUREG_APUTYPE, + (ch->aputype << APU_APUTYPE_SHIFT) | APU_DMA_ENABLED | 0xf); + if (ch->wcreg_tpl & WAVCACHE_CHCTL_STEREO) + wp_wrapu(ch->parent, apuch + 1, APUREG_APUTYPE, + (ch->aputype << APU_APUTYPE_SHIFT) | APU_DMA_ENABLED | 0xf); +} + +static void +aggch_stop_dac(struct agg_chinfo *ch) +{ + wp_wrapu(ch->parent, (ch->num << 1), APUREG_APUTYPE, + APUTYPE_INACTIVE << APU_APUTYPE_SHIFT); + wp_wrapu(ch->parent, (ch->num << 1) + 1, APUREG_APUTYPE, + APUTYPE_INACTIVE << APU_APUTYPE_SHIFT); +} + +/* + * Stereo jitter suppressor. + * Sometimes playback pointers differ in stereo-paired channels. + * Calling this routine within intr fixes the problem. + */ +static inline void +suppress_jitter(struct agg_chinfo *ch) +{ + if (ch->wcreg_tpl & WAVCACHE_CHCTL_STEREO) { + int cp, diff, halfsize = ch->parent->bufsz >> 2; + + if (ch->aputype == APUTYPE_16BITSTEREO) + halfsize >>= 1; + cp = wp_rdapu(ch->parent, (ch->num << 1), APUREG_CURPTR); + diff = wp_rdapu(ch->parent, (ch->num << 1) + 1, APUREG_CURPTR); + diff -= cp; + if (diff >> 1 && diff > -halfsize && diff < halfsize) + bus_space_write_2(ch->parent->st, ch->parent->sh, + PORT_DSP_DATA, cp); + } +} + +static inline u_int +calc_timer_freq(struct agg_chinfo *ch) +{ + u_int ss = 2; + + if (ch->aputype == APUTYPE_16BITSTEREO) + ss <<= 1; + if (ch->aputype == APUTYPE_8BITLINEAR) + ss >>= 1; + + return (ch->speed * ss) / ch->blocksize; +} + +static void +set_timer(struct agg_info *ess) +{ + int i; + u_int freq = 0; + + for (i = 0; i < ess->playchns; i++) + if ((ess->active & (1 << i)) && + (freq < calc_timer_freq(ess->pch + i))) + freq = calc_timer_freq(ess->pch + i); + + wp_settimer(ess, freq); +} + + +/* ----------------------------- + * Newpcm glue. + */ + +static void * +aggch_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; + + ch = (dir == PCMDIR_PLAY)? ess->pch + ess->playchns : &ess->rch; + + ch->parent = ess; + ch->channel = c; + ch->buffer = b; + ch->num = ess->playchns; + ch->dir = dir; + + p = dma_malloc(ess, ess->bufsz, &physaddr); + if (p == NULL) + return NULL; + sndbuf_setup(b, p, ess->bufsz); + + ch->offset = physaddr - ess->baseaddr; + if (physaddr < ess->baseaddr || ch->offset > WPWA_MAXADDR) { + device_printf(ess->dev, + "offset %#llx exceeds limit. ", (long long)ch->offset); + dma_free(ess, sndbuf_getbuf(b)); + return NULL; + } + + ch->wcreg_tpl = (physaddr - 16) & WAVCACHE_CHCTL_ADDRTAG_MASK; + + if (dir == PCMDIR_PLAY) { + ess->playchns++; + if (bootverbose) + device_printf(ess->dev, "pch[%d].offset = %#llx\n", ch->num, (long long)ch->offset); + } else if (bootverbose) + device_printf(ess->dev, "rch.offset = %#llx\n", (long long)ch->offset); + + return ch; +} + +static int +aggch_free(kobj_t obj, void *data) +{ + struct agg_chinfo *ch = data; + struct agg_info *ess = ch->parent; + + /* free up buffer - called after channel stopped */ + dma_free(ess, sndbuf_getbuf(ch->buffer)); + + /* return 0 if ok */ + return 0; +} + +static int +aggch_setplayformat(kobj_t obj, void *data, u_int32_t format) +{ + struct agg_chinfo *ch = data; + u_int16_t wcreg_tpl; + u_int16_t aputype = APUTYPE_16BITLINEAR; + + wcreg_tpl = ch->wcreg_tpl & WAVCACHE_CHCTL_ADDRTAG_MASK; + + if (format & AFMT_STEREO) { + wcreg_tpl |= WAVCACHE_CHCTL_STEREO; + aputype += 1; + } + if (format & AFMT_U8 || format & AFMT_S8) { + aputype += 2; + if (format & AFMT_U8) + wcreg_tpl |= WAVCACHE_CHCTL_U8; + } + if (format & AFMT_BIGENDIAN || format & AFMT_U16_LE) { + format &= ~AFMT_BIGENDIAN & ~AFMT_U16_LE; + format |= AFMT_S16_LE; + } + ch->wcreg_tpl = wcreg_tpl; + ch->aputype = aputype; + return 0; +} + +static int +aggch_setspeed(kobj_t obj, void *data, u_int32_t speed) +{ + struct agg_chinfo *ch = data; + + ch->speed = speed; + return ch->speed; +} + +static int +aggch_setblocksize(kobj_t obj, void *data, u_int32_t blocksize) +{ + return ((struct agg_chinfo*)data)->blocksize = blocksize; +} + +static int +aggch_trigger(kobj_t obj, void *data, int go) +{ + struct agg_chinfo *ch = data; + + switch (go) { + case PCMTRIG_EMLDMAWR: + return 0; + case PCMTRIG_START: + ch->parent->active |= (1 << ch->num); + if (ch->dir == PCMDIR_PLAY) + aggch_start_dac(ch); +#if 0 /* XXX - RECORDING */ + else + aggch_start_adc(ch); +#endif + break; + case PCMTRIG_ABORT: + case PCMTRIG_STOP: + ch->parent->active &= ~(1 << ch->num); + if (ch->dir == PCMDIR_PLAY) + aggch_stop_dac(ch); +#if 0 /* XXX - RECORDING */ + else + aggch_stop_adc(ch); +#endif + break; + } + + if (ch->parent->active) { + set_timer(ch->parent); + wp_starttimer(ch->parent); + } else + wp_stoptimer(ch->parent); + + return 0; +} + +static int +aggch_getplayptr(kobj_t obj, void *data) +{ + struct agg_chinfo *ch = data; + u_int cp; + + cp = wp_rdapu(ch->parent, (ch->num << 1), APUREG_CURPTR); + if (ch->aputype == APUTYPE_16BITSTEREO) + cp = (0xffff << 2) & ((cp << 2) - ch->offset); + else + cp = (0xffff << 1) & ((cp << 1) - ch->offset); + + return cp; +} + +static struct pcmchan_caps * +aggch_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 = {2000, 96000, playfmt, 0}; + + static u_int32_t recfmt[] = { + AFMT_S8, + AFMT_STEREO | AFMT_S8, + AFMT_S16_LE, + AFMT_STEREO | AFMT_S16_LE, + 0 + }; + static struct pcmchan_caps reccaps = {4000, 48000, recfmt, 0}; + + return (((struct agg_chinfo*)data)->dir == PCMDIR_PLAY)? + &playcaps : &reccaps; +} + +static kobj_method_t aggch_methods[] = { + KOBJMETHOD(channel_init, aggch_init), + KOBJMETHOD(channel_free, aggch_free), + KOBJMETHOD(channel_setformat, aggch_setplayformat), + KOBJMETHOD(channel_setspeed, aggch_setspeed), + KOBJMETHOD(channel_setblocksize, aggch_setblocksize), + KOBJMETHOD(channel_trigger, aggch_trigger), + KOBJMETHOD(channel_getptr, aggch_getplayptr), + KOBJMETHOD(channel_getcaps, aggch_getcaps), + { 0, 0 } +}; +CHANNEL_DECLARE(aggch); + +/* ----------------------------- + * Bus space. + */ + +static void +agg_intr(void *sc) +{ + struct agg_info* ess = sc; + u_int16_t status; + int i; + + status = bus_space_read_1(ess->st, ess->sh, PORT_HOSTINT_STAT); + if (!status) + return; + + /* Acknowledge all. */ + bus_space_write_2(ess->st, ess->sh, PORT_INT_STAT, 1); + bus_space_write_1(ess->st, ess->sh, PORT_HOSTINT_STAT, 0xff); + + if (status & HOSTINT_STAT_HWVOL) { + u_int event; + + event = bus_space_read_1(ess->st, ess->sh, PORT_HWVOL_MASTER); + switch (event) { + case HWVOL_MUTE: + mixer_hwvol_mute(ess->dev); + break; + 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: + device_printf(ess->dev, "%s: unknown HWVOL event 0x%x\n", + device_get_nameunit(ess->dev), event); + } + bus_space_write_1(ess->st, ess->sh, PORT_HWVOL_MASTER, + HWVOL_NOP); + } + + for (i = 0; i < ess->playchns; i++) + if (ess->active & (1 << i)) { + suppress_jitter(ess->pch + i); + chn_intr(ess->pch[i].channel); + } +#if 0 /* XXX - RECORDING */ + if (ess->active & (1 << i)) + chn_intr(ess->rch.channel); +#endif +} + +static void +setmap(void *arg, bus_dma_segment_t *segs, int nseg, int error) +{ + bus_addr_t *phys = arg; + + *phys = error? 0 : segs->ds_addr; + + 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(struct agg_info *sc, u_int32_t sz, bus_addr_t *phys) +{ + void *buf; + bus_dmamap_t map; + + if (bus_dmamem_alloc(sc->parent_dmat, &buf, BUS_DMA_NOWAIT, &map)) + return NULL; + if (bus_dmamap_load(sc->parent_dmat, map, buf, sz, setmap, phys, 0) + || !*phys) { + bus_dmamem_free(sc->parent_dmat, buf, map); + return NULL; + } + return buf; +} + +static void +dma_free(struct agg_info *sc, void *buf) +{ + bus_dmamem_free(sc->parent_dmat, buf, NULL); +} + +static int +agg_probe(device_t dev) +{ + 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 0; + } + return ENXIO; +} + +static int +agg_attach(device_t dev) +{ + struct agg_info *ess = NULL; + u_int32_t data; + int mapped = 0; + int regid = PCIR_MAPS; + struct resource *reg = NULL; + struct ac97_info *codec = NULL; + int irqid = 0; + struct resource *irq = NULL; + void *ih = NULL; + char status[SND_STATUSLEN]; + + if ((ess = malloc(sizeof *ess, M_DEVBUF, M_NOWAIT | M_ZERO)) == NULL) { + device_printf(dev, "cannot allocate softc\n"); + return ENXIO; + } + ess->dev = dev; + + ess->bufsz = pcm_getbuffersize(dev, 4096, AGG_DEFAULT_BUFSZ, 65536); + + if (bus_dma_tag_create(/*parent*/NULL, + /*alignment*/1 << WAVCACHE_BASEADDR_SHIFT, + /*boundary*/WPWA_MAXADDR + 1, + /*lowaddr*/MAESTRO_MAXADDR, /*highaddr*/BUS_SPACE_MAXADDR, + /*filter*/NULL, /*filterarg*/NULL, + /*maxsize*/ess->bufsz, /*nsegments*/1, /*maxsegz*/0x3ffff, + /*flags*/0, &ess->parent_dmat) != 0) { + device_printf(dev, "unable to create dma tag\n"); + goto bad; + } + + ess->stat = dma_malloc(ess, ess->bufsz, &ess->baseaddr); + if (ess->stat == NULL) { + device_printf(dev, "cannot allocate status buffer\n"); + goto bad; + } + if (bootverbose) + device_printf(dev, "Maestro DMA base: %#llx\n", + (long long)ess->baseaddr); + + agg_power(ess, PPMI_D0); + DELAY(100000); + + 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 (data & PCIM_CMD_PORTEN) { + reg = bus_alloc_resource(dev, SYS_RES_IOPORT, ®id, + 0, BUS_SPACE_UNRESTRICTED, 256, RF_ACTIVE); + if (reg != NULL) { + ess->reg = reg; + ess->regid = regid; + ess->st = rman_get_bustag(reg); + ess->sh = rman_get_bushandle(reg); + mapped++; + } + } + if (mapped == 0) { + device_printf(dev, "unable to map register space\n"); + goto bad; + } + + agg_init(ess); + if (agg_rdcodec(NULL, ess, 0) == 0x80) { + device_printf(dev, "PT101 codec detected!\n"); + goto bad; + } + codec = AC97_CREATE(dev, ess, agg_ac97); + if (codec == NULL) + goto bad; + if (mixer_init(dev, ac97_getmixerclass(), codec) == -1) + goto bad; + ess->codec = codec; + + irq = bus_alloc_resource(dev, SYS_RES_IRQ, &irqid, + 0, BUS_SPACE_UNRESTRICTED, 1, RF_ACTIVE | RF_SHAREABLE); + if (irq == NULL || snd_setup_intr(dev, irq, 0, agg_intr, ess, &ih)) { + device_printf(dev, "unable to map interrupt\n"); + goto bad; + } + ess->irq = irq; + ess->irqid = irqid; + ess->ih = ih; + + snprintf(status, SND_STATUSLEN, "at I/O port 0x%lx irq %ld", + rman_get_start(reg), rman_get_start(irq)); + + if (pcm_register(dev, ess, AGG_MAXPLAYCH, 1)) + goto bad; + + mixer_hwvol_init(dev); + for (data = 0; data < AGG_MAXPLAYCH; data++) + pcm_addchan(dev, PCMDIR_PLAY, &aggch_class, ess); +#if 0 /* XXX - RECORDING */ + pcm_addchan(dev, PCMDIR_REC, &aggrch_class, ess); +#endif + 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) { + agg_power(ess, PPMI_D3); + if (ess->stat != NULL) + dma_free(ess, ess->stat); + if (ess->parent_dmat != NULL) + bus_dma_tag_destroy(ess->parent_dmat); + free(ess, M_DEVBUF); + } + + return ENXIO; +} + +static int +agg_detach(device_t dev) +{ + struct agg_info *ess = pcm_getdevinfo(dev); + int r; + + r = pcm_unregister(dev); + if (r) + return r; + + ess = pcm_getdevinfo(dev); + dma_free(ess, ess->stat); + + /* Power down everything except clock and vref. */ + agg_wrcodec(NULL, ess, AC97_REG_POWER, 0xd700); + DELAY(20); + bus_space_write_4(ess->st, ess->sh, PORT_RINGBUS_CTRL, 0); + agg_power(ess, PPMI_D3); + + 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); + bus_dma_tag_destroy(ess->parent_dmat); + free(ess, M_DEVBUF); + return 0; +} + +static int +agg_suspend(device_t dev) +{ + struct agg_info *ess = pcm_getdevinfo(dev); + int i, x; + + x = spltty(); + wp_stoptimer(ess); + bus_space_write_2(ess->st, ess->sh, PORT_HOSTINT_CTRL, 0); + + for (i = 0; i < ess->playchns; i++) + aggch_stop_dac(ess->pch + i); + +#if 0 /* XXX - RECORDING */ + aggch_stop_adc(&ess->rch); +#endif + splx(x); + /* Power down everything except clock. */ + agg_wrcodec(NULL, ess, AC97_REG_POWER, 0xdf00); + DELAY(20); + bus_space_write_4(ess->st, ess->sh, PORT_RINGBUS_CTRL, 0); + DELAY(1); + agg_power(ess, PPMI_D3); + + return 0; +} + +static int +agg_resume(device_t dev) +{ + int i, x; + struct agg_info *ess = pcm_getdevinfo(dev); + + agg_power(ess, PPMI_D0); + DELAY(100000); + agg_init(ess); + if (mixer_reinit(dev)) { + device_printf(dev, "unable to reinitialize the mixer\n"); + return ENXIO; + } + + x = spltty(); + for (i = 0; i < ess->playchns; i++) + if (ess->active & (1 << i)) + aggch_start_dac(ess->pch + i); +#if 0 /* XXX - RECORDING */ + if (ess->active & (1 << i)) + aggch_start_adc(&ess->rch); +#endif + if (ess->active) { + set_timer(ess); + wp_starttimer(ess); + } + splx(x); + return 0; +} + +static int +agg_shutdown(device_t dev) +{ + struct agg_info *ess = pcm_getdevinfo(dev); + int i; + + wp_stoptimer(ess); + bus_space_write_2(ess->st, ess->sh, PORT_HOSTINT_CTRL, 0); + + for (i = 0; i < ess->playchns; i++) + aggch_stop_dac(ess->pch + i); + +#if 0 /* XXX - RECORDING */ + aggch_stop_adc(&ess->rch); +#endif + 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), + + { 0, 0 } +}; + +static driver_t agg_driver = { + "pcm", + agg_methods, + PCM_SOFTC_SIZE, +}; + +DRIVER_MODULE(snd_maestro, pci, agg_driver, pcm_devclass, 0, 0); +MODULE_DEPEND(snd_maestro, snd_pcm, PCM_MINVER, PCM_PREFVER, PCM_MAXVER); +MODULE_VERSION(snd_maestro, 1); diff --git a/sys/dev/sound/pci/maestro3.c b/sys/dev/sound/pci/maestro3.c new file mode 100644 index 0000000..ae679ca --- /dev/null +++ b/sys/dev/sound/pci/maestro3.c @@ -0,0 +1,1526 @@ +/*- + * Copyright (c) 2001 Scott Long <scottl@freebsd.org> + * Copyright (c) 2001 Darrell Anderson <anderson@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@zabbo.net>, http://www.zabbo.net/maestro3 + * + * Cameron Grant created the pcm framework used here nearly verbatim. + * <cg@freebsd.org>, http://people.freebsd.org/~cg/template.c + * + * Taku YAMAMOTO for his Maestro-1/2 FreeBSD driver and sanity reference. + * <taku@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> + +#include <pci/pcireg.h> +#include <pci/pcivar.h> + +#include <gnu/dev/sound/pci/maestro3_reg.h> +#include <gnu/dev/sound/pci/maestro3_dsp.h> + +SND_DECLARE_FILE("$FreeBSD$"); + +/* -------------------------------------------------------------------- */ + +enum {CHANGE=0, CALL=1, INTR=2, BORING=3, NONE=-1}; +#ifndef M3_DEBUG_LEVEL +#define M3_DEBUG_LEVEL NONE +#endif +#define M3_DEBUG(level, _msg) {if ((level) <= M3_DEBUG_LEVEL) {printf _msg;}} + +/* -------------------------------------------------------------------- */ +enum { + ESS_ALLEGRO_1, + ESS_MAESTRO3 +}; + +static struct m3_card_type { + 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 } +}; + +#define M3_BUFSIZE_DEFAULT 4096 +#define M3_PCHANS 4 /* create /dev/dsp0.[0-N] to use more than one */ +#define M3_RCHANS 1 +#define M3_MAXADDR ((1 << 27) - 1) + +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; +}; + +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; +}; + +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; +}; + +/* -------------------------------------------------------------------- */ + +/* play channel interface */ +static void *m3_pchan_init(kobj_t, void *, struct snd_dbuf *, struct pcm_channel *, int); +static int m3_pchan_free(kobj_t, void *); +static int m3_pchan_setformat(kobj_t, void *, u_int32_t); +static int m3_pchan_setspeed(kobj_t, void *, u_int32_t); +static int m3_pchan_setblocksize(kobj_t, void *, u_int32_t); +static int m3_pchan_trigger(kobj_t, void *, int); +static int m3_pchan_getptr(kobj_t, void *); +static struct pcmchan_caps *m3_pchan_getcaps(kobj_t, void *); + +/* record channel interface */ +static void *m3_rchan_init(kobj_t, void *, struct snd_dbuf *, struct pcm_channel *, int); +static int m3_rchan_free(kobj_t, void *); +static int m3_rchan_setformat(kobj_t, void *, u_int32_t); +static int m3_rchan_setspeed(kobj_t, void *, u_int32_t); +static int m3_rchan_setblocksize(kobj_t, void *, u_int32_t); +static int m3_rchan_trigger(kobj_t, void *, int); +static int m3_rchan_getptr(kobj_t, void *); +static struct pcmchan_caps *m3_rchan_getcaps(kobj_t, void *); + +/* talk to the codec - called from ac97.c */ +static int m3_initcd(kobj_t, void *); +static int m3_rdcd(kobj_t, void *, int); +static int m3_wrcd(kobj_t, void *, int, u_int32_t); + +/* stuff */ +static void m3_intr(void *); +static int m3_power(struct sc_info *, int); +static int m3_init(struct sc_info *); +static int m3_uninit(struct sc_info *); +static u_int8_t m3_assp_halt(struct sc_info *); +static void m3_config(struct sc_info *); +static void m3_amp_enable(struct sc_info *); +static void m3_enable_ints(struct sc_info *); +static void m3_codec_reset(struct sc_info *); + +/* -------------------------------------------------------------------- */ +/* 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 } +}; +AC97_DECLARE(m3_codec); + +/* -------------------------------------------------------------------- */ +/* channel descriptors */ + +static u_int32_t m3_playfmt[] = { + 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 } +}; +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 +}; +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 } +}; +CHANNEL_DECLARE(m3_rch); + +/* -------------------------------------------------------------------- */ +/* some i/o convenience functions */ + +#define m3_rd_1(sc, regno) bus_space_read_1(sc->st, sc->sh, regno) +#define m3_rd_2(sc, regno) bus_space_read_2(sc->st, sc->sh, regno) +#define m3_rd_4(sc, regno) bus_space_read_4(sc->st, sc->sh, regno) +#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) + +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); +} + +static __inline void +m3_wr_assp(struct sc_info *sc, u_int16_t region, u_int16_t index, + 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); +} + +static __inline int +m3_wait(struct sc_info *sc) +{ + int i; + + for (i=0 ; i<20 ; i++) { + if ((m3_rd_1(sc, CODEC_STATUS) & 1) == 0) { + return 0; + } + DELAY(2); + } + return -1; +} + +/* -------------------------------------------------------------------- */ +/* ac97 codec */ + +static int +m3_initcd(kobj_t kobj, void *devinfo) +{ + struct sc_info *sc = (struct sc_info *)devinfo; + u_int32_t data; + + M3_DEBUG(CALL, ("m3_initcd\n")); + + /* init ac-link */ + + 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; + + 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; +} + +/* -------------------------------------------------------------------- */ +/* play channel interface */ + +#define LO(x) (((x) & 0x0000ffff) ) +#define HI(x) (((x) & 0xffff0000) >> 16) + +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 = sc->pch_cnt; /* dac instance number, no active reuse! */ + int data_bytes = (((MINISRC_TMP_BUFFER_SIZE & ~1) + + (MINISRC_IN_BUFFER_SIZE & ~1) + + (MINISRC_OUT_BUFFER_SIZE & ~1) + 4) + 255) &~ 255; + int dac_data = 0x1100 + (data_bytes * idx); + + int dsp_in_size = MINISRC_IN_BUFFER_SIZE - (0x20 * 2); + int dsp_out_size = MINISRC_OUT_BUFFER_SIZE - (0x20 * 2); + int dsp_in_buf = dac_data + (MINISRC_TMP_BUFFER_SIZE/2); + int dsp_out_buf = dsp_in_buf + (dsp_in_size/2) + 1; + + M3_DEBUG(CHANGE, ("m3_pchan_init(dac=%d)\n", idx)); + + if (dir != PCMDIR_PLAY) { + device_printf(sc->dev, "m3_pchan_init not PCMDIR_PLAY\n"); + return NULL; + } + ch = &sc->pch[idx]; + + ch->dac_idx = idx; + ch->dac_data = dac_data; + if (ch->dac_data + data_bytes/2 >= 0x1c00) { + 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; + if (sndbuf_alloc(ch->buffer, sc->parent_dmat, sc->bufsz) == -1) { + device_printf(sc->dev, "m3_pchan_init chn_allocbuf failed\n"); + return NULL; + } + 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); + + m3_pchan_trigger(NULL, ch, PCMTRIG_START); /* gotta start before stop */ + m3_pchan_trigger(NULL, ch, PCMTRIG_STOP); /* silence noise on load */ + + sc->pch_cnt++; + return ch; +} + +static int +m3_pchan_free(kobj_t kobj, void *chdata) +{ + struct sc_pchinfo *ch = chdata; + struct sc_info *sc = ch->parent; + + 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--; + 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_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; + 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_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; + return speed; /* return closest possible speed */ +} + +static int +m3_pchan_setblocksize(kobj_t kobj, void *chdata, u_int32_t blocksize) +{ + struct sc_pchinfo *ch = chdata; + + M3_DEBUG(CHANGE, ("m3_pchan_setblocksize(dac=%d, blocksize=%d)\n", + ch->dac_idx, blocksize)); + + return blocksize; +} + +static int +m3_pchan_trigger(kobj_t kobj, void *chdata, int go) +{ + struct sc_pchinfo *ch = chdata; + struct sc_info *sc = ch->parent; + u_int32_t data; + + 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; + sc->pch_active_cnt++; + + /*[[inc_timer_users]]*/ + 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]]*/ + 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 int +m3_pchan_getptr(kobj_t kobj, void *chdata) +{ + struct sc_pchinfo *ch = chdata; + struct sc_info *sc = ch->parent; + u_int32_t hi, lo, bus_crnt; + u_int32_t 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=%d\n", + ch->dac_idx, bus_crnt - bus_base)); + + return (bus_crnt - bus_base); /* current byte offset of channel */ +} + +static struct pcmchan_caps * +m3_pchan_getcaps(kobj_t kobj, void *chdata) +{ + struct sc_pchinfo *ch = chdata; + + M3_DEBUG(CALL, ("m3_pchan_getcaps(dac=%d)\n", ch->dac_idx)); + + return &m3_playcaps; +} + +/* -------------------------------------------------------------------- */ +/* rec channel interface */ + +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 = sc->rch_cnt; /* adc instance number, no active reuse! */ + int data_bytes = (((MINISRC_TMP_BUFFER_SIZE & ~1) + + (MINISRC_IN_BUFFER_SIZE & ~1) + + (MINISRC_OUT_BUFFER_SIZE & ~1) + 4) + 255) &~ 255; + int adc_data = 0x1100 + (data_bytes * idx) + data_bytes/2; + + int dsp_in_size = MINISRC_IN_BUFFER_SIZE + (0x10 * 2); + int dsp_out_size = MINISRC_OUT_BUFFER_SIZE - (0x10 * 2); + int dsp_in_buf = adc_data + (MINISRC_TMP_BUFFER_SIZE / 2); + int dsp_out_buf = dsp_in_buf + (dsp_in_size / 2) + 1; + + M3_DEBUG(CHANGE, ("m3_rchan_init(adc=%d)\n", idx)); + + if (dir != PCMDIR_REC) { + device_printf(sc->dev, "m3_pchan_init not PCMDIR_REC\n"); + return NULL; + } + ch = &sc->rch[idx]; + + ch->adc_idx = idx; + ch->adc_data = adc_data; + if (ch->adc_data + data_bytes/2 >= 0x1c00) { + 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; + if (sndbuf_alloc(ch->buffer, sc->parent_dmat, sc->bufsz) == -1) { + device_printf(sc->dev, "m3_rchan_init chn_allocbuf failed\n"); + return NULL; + } + 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); + + m3_rchan_trigger(NULL, ch, PCMTRIG_START); /* gotta start before stop */ + m3_rchan_trigger(NULL, ch, PCMTRIG_STOP); /* stop on init */ + + sc->rch_cnt++; + return ch; +} + +static int +m3_rchan_free(kobj_t kobj, void *chdata) +{ + struct sc_rchinfo *ch = chdata; + struct sc_info *sc = ch->parent; + + 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--; + 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_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; + 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_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; + return speed; /* return closest possible speed */ +} + +static int +m3_rchan_setblocksize(kobj_t kobj, void *chdata, u_int32_t blocksize) +{ + struct sc_rchinfo *ch = chdata; + + M3_DEBUG(CHANGE, ("m3_rchan_setblocksize(adc=%d, blocksize=%d)\n", + ch->adc_idx, blocksize)); + + return blocksize; +} + +static int +m3_rchan_trigger(kobj_t kobj, void *chdata, int go) +{ + struct sc_rchinfo *ch = chdata; + struct sc_info *sc = ch->parent; + u_int32_t data; + + 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; + + /*[[inc_timer_users]]*/ + 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]]*/ + 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 int +m3_rchan_getptr(kobj_t kobj, void *chdata) +{ + struct sc_rchinfo *ch = chdata; + struct sc_info *sc = ch->parent; + u_int32_t hi, lo, bus_crnt; + u_int32_t 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=%d\n", + ch->adc_idx, bus_crnt - bus_base)); + + return (bus_crnt - bus_base); /* current byte offset of channel */ +} + +static struct pcmchan_caps * +m3_rchan_getcaps(kobj_t kobj, void *chdata) +{ + struct sc_rchinfo *ch = chdata; + + M3_DEBUG(CALL, ("m3_rchan_getcaps(adc=%d)\n", ch->adc_idx)); + + return &m3_reccaps; +} + +/* -------------------------------------------------------------------- */ +/* The interrupt handler */ + +static void +m3_intr(void *p) +{ + struct sc_info *sc = (struct sc_info *)p; + u_int32_t status, ctl, i; + + M3_DEBUG(INTR, ("m3_intr\n")); + + status = m3_rd_1(sc, HOST_INT_STATUS); + if (!status) + 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]]*/ + } + } + } + + for (i=0 ; i<sc->pch_cnt ; i++) { + if (sc->pch[i].active) { + chn_intr(sc->pch[i].channel); + } + } + for (i=0 ; i<sc->rch_cnt ; i++) { + if (sc->rch[i].active) { + chn_intr(sc->rch[i].channel); + } + } +} + +/* -------------------------------------------------------------------- */ +/* stuff */ + +static int +m3_power(struct sc_info *sc, int state) +{ + u_int32_t data; + + M3_DEBUG(CHANGE, ("m3_power(%d)\n", state)); + + 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; +} + +static int +m3_init(struct sc_info *sc) +{ + u_int32_t data, i, size; + u_int8_t reset_state; + + 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 */ + } + + /* [m3_assp_continue] */ + m3_wr_1(sc, DSP_PORT_CONTROL_REG_B, reset_state | REGB_ENABLE_RESET); + + return 0; +} + +static int +m3_uninit(struct sc_info *sc) +{ + M3_DEBUG(CHANGE, ("m3_uninit\n")); + return 0; +} + +/* -------------------------------------------------------------------- */ +/* Probe and attach the card */ + +static int +m3_pci_probe(device_t dev) +{ + struct m3_card_type *card; + + 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 0; + } + } + return ENXIO; +} + +static int +m3_pci_attach(device_t dev) +{ + struct sc_info *sc; + struct ac97_info *codec = NULL; + u_int32_t data, i; + char status[SND_STATUSLEN]; + struct m3_card_type *card; + int len; + + M3_DEBUG(CALL, ("m3_pci_attach\n")); + + if ((sc = malloc(sizeof(*sc), M_DEVBUF, M_NOWAIT | M_ZERO)) == NULL) { + device_printf(dev, "cannot allocate softc\n"); + return ENXIO; + } + + sc->dev = dev; + sc->type = pci_get_devid(dev); + + 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; + } + } + + 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_MAPS; + sc->regtype = SYS_RES_MEMORY; + sc->reg = bus_alloc_resource(dev, sc->regtype, &sc->regid, + 0, ~0, 1, RF_ACTIVE); + if (!sc->reg) { + sc->regtype = SYS_RES_IOPORT; + sc->reg = bus_alloc_resource(dev, sc->regtype, &sc->regid, + 0, ~0, 1, 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(dev, SYS_RES_IRQ, &sc->irqid, + 0, ~0, 1, 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, m3_intr, sc, &sc->ih)) { + device_printf(dev, "unable to setup interrupt\n"); + goto bad; + } + + sc->bufsz = pcm_getbuffersize(dev, 1024, M3_BUFSIZE_DEFAULT, 65536); + + if (bus_dma_tag_create(/*parent*/NULL, /*alignment*/2, /*boundary*/0, + /*lowaddr*/M3_MAXADDR, + /*highaddr*/BUS_SPACE_MAXADDR, + /*filter*/NULL, /*filterarg*/NULL, + /*maxsize*/sc->bufsz, /*nsegments*/1, + /*maxsegz*/0x3ffff, + /*flags*/0, &sc->parent_dmat) != 0) { + device_printf(dev, "unable to create dma tag\n"); + goto bad; + } + + m3_power(sc, 0); /* power up */ + + /* init chip */ + if (m3_init(sc) == -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, M3_PCHANS, M3_RCHANS)) { + device_printf(dev, "pcm_register error\n"); + goto bad; + } + for (i=0 ; i<M3_PCHANS ; 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<M3_RCHANS ; 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", + (sc->regtype == SYS_RES_IOPORT)? "io" : "memory", + rman_get_start(sc->reg), rman_get_start(sc->irq)); + 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_NOWAIT | M_ZERO); + if (sc->savemem == NULL) { + device_printf(dev, "Failed to create suspend buffer\n"); + goto bad; + } + + return 0; + + bad: + if (codec) { + ac97_destroy(codec); + } + if (sc->reg) { + bus_release_resource(dev, sc->regtype, 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->parent_dmat) { + bus_dma_tag_destroy(sc->parent_dmat); + } + free(sc, M_DEVBUF); + return ENXIO; +} + +static int +m3_pci_detach(device_t dev) +{ + struct sc_info *sc = pcm_getdevinfo(dev); + int r; + + M3_DEBUG(CALL, ("m3_pci_detach\n")); + + if ((r = pcm_unregister(dev)) != 0) { + return r; + } + m3_uninit(sc); /* shutdown chip */ + m3_power(sc, 3); /* power off */ + + bus_release_resource(dev, sc->regtype, 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->parent_dmat); + + free(sc->savemem, M_DEVBUF); + 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; + + M3_DEBUG(CHANGE, ("m3_pci_suspend\n")); + + for (i=0 ; i<sc->pch_cnt ; i++) { + if (sc->pch[i].active) { + m3_pchan_trigger(NULL, &sc->pch[i], PCMTRIG_STOP); + } + } + for (i=0 ; i<sc->rch_cnt ; i++) { + if (sc->rch[i].active) { + m3_rchan_trigger(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); + + 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_resume\n")); + + /* 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); + + if (mixer_reinit(dev) == -1) { + device_printf(dev, "unable to reinitialize the mixer\n"); + return ENXIO; + } + + /* Turn the channels back on */ + for (i=0 ; i<sc->pch_cnt ; i++) { + if (sc->pch[i].active) { + m3_pchan_trigger(NULL, &sc->pch[i], PCMTRIG_START); + } + } + for (i=0 ; i<sc->rch_cnt ; i++) { + if (sc->rch[i].active) { + m3_rchan_trigger(NULL, &sc->rch[i], PCMTRIG_START); + } + } + + return 0; +} + +static int +m3_pci_shutdown(device_t dev) +{ + struct sc_info *sc = pcm_getdevinfo(dev); + + M3_DEBUG(CALL, ("m3_pci_shutdown\n")); + + m3_power(sc, 3); /* power off */ + return 0; +} + +static u_int8_t +m3_assp_halt(struct sc_info *sc) +{ + u_int8_t data, reset_state; + + 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; +} + +static void +m3_config(struct sc_info *sc) +{ + u_int32_t data, hv_cfg; + int hint; + + /* + * 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; + + 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); +} + +static void +m3_enable_ints(struct sc_info *sc) +{ + 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); +} + +static void +m3_amp_enable(struct sc_info *sc) +{ + u_int32_t gpo, polarity_port, polarity; + u_int16_t data; + + 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; + + 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 } +}; + +static driver_t m3_driver = { + "pcm", + m3_methods, + PCM_SOFTC_SIZE, +}; + +DRIVER_MODULE(snd_maestro3, pci, m3_driver, pcm_devclass, 0, 0); +MODULE_DEPEND(snd_maestro3, snd_pcm, PCM_MINVER, PCM_PREFVER, PCM_MAXVER); +MODULE_VERSION(snd_maestro3, 1); diff --git a/sys/dev/sound/pci/maestro_reg.h b/sys/dev/sound/pci/maestro_reg.h new file mode 100644 index 0000000..41ce351 --- /dev/null +++ b/sys/dev/sound/pci/maestro_reg.h @@ -0,0 +1,349 @@ +/*- + * Copyright (c) 1999-2000 Taku YAMAMOTO <taku@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. + * + * $Id: maestro_reg.h,v 1.10 2000/08/29 17:27:29 taku Exp $ + * $FreeBSD$ + */ + +#ifndef MAESTRO_REG_H_INCLUDED +#define MAESTRO_REG_H_INCLUDED + +/* ----------------------------- + * PCI config registers + */ + +/* Legacy emulation */ +#define CONF_LEGACY 0x40 + +#define LEGACY_DISABLED 0x8000 + +/* Chip configurations */ +#define CONF_MAESTRO 0x50 +#define MAESTRO_CHIBUS 0x00100000 +#define MAESTRO_POSTEDWRITE 0x00000080 +#define MAESTRO_DMA_PCITIMING 0x00000040 +#define MAESTRO_SWAP_LR 0x00000010 + +/* ACPI configurations */ +#define CONF_ACPI_STOPCLOCK 0x54 +#define ACPI_PART_2ndC_CLOCK 15 +#define ACPI_PART_CODEC_CLOCK 14 +#define ACPI_PART_978 13 /* Docking station or something */ +#define ACPI_PART_SPDIF 12 +#define ACPI_PART_GLUE 11 /* What? */ +#define ACPI_PART_DAA 10 +#define ACPI_PART_PCI_IF 9 +#define ACPI_PART_HW_VOL 8 +#define ACPI_PART_GPIO 7 +#define ACPI_PART_ASSP 6 +#define ACPI_PART_SB 5 +#define ACPI_PART_FM 4 +#define ACPI_PART_RINGBUS 3 +#define ACPI_PART_MIDI 2 +#define ACPI_PART_GAME_PORT 1 +#define ACPI_PART_WP 0 + +/* Power management */ +#define CONF_PM_PTR 0x34 /* BYTE R */ +#define PM_CID 0 /* BYTE R */ +#define PPMI_CID 1 +#define PM_CTRL 4 /* BYTE RW */ +#define PPMI_D0 0 /* Full power */ +#define PPMI_D1 1 /* Medium power */ +#define PPMI_D2 2 /* Low power */ +#define PPMI_D3 3 /* Turned off */ + + +/* ----------------------------- + * I/O ports + */ + +/* Direct Sound Processor (aka WP) */ +#define PORT_DSP_DATA 0x00 /* WORD RW */ +#define PORT_DSP_INDEX 0x02 /* WORD RW */ +#define PORT_INT_STAT 0x04 /* WORD RW */ +#define PORT_SAMPLE_CNT 0x06 /* WORD RO */ + +/* WaveCache */ +#define PORT_WAVCACHE_INDEX 0x10 /* WORD RW */ +#define PORT_WAVCACHE_DATA 0x12 /* WORD RW */ +#define WAVCACHE_PCMBAR 0x1fc +#define WAVCACHE_WTBAR 0x1f0 +#define WAVCACHE_BASEADDR_SHIFT 12 + +#define WAVCACHE_CHCTL_ADDRTAG_MASK 0xfff8 +#define WAVCACHE_CHCTL_U8 0x0004 +#define WAVCACHE_CHCTL_STEREO 0x0002 +#define WAVCACHE_CHCTL_DECREMENTAL 0x0001 + +#define PORT_WAVCACHE_CTRL 0x14 /* WORD RW */ +#define WAVCACHE_EXTRA_CH_ENABLED 0x0200 +#define WAVCACHE_ENABLED 0x0100 +#define WAVCACHE_CH_60_ENABLED 0x0080 +#define WAVCACHE_WTSIZE_MASK 0x0060 +#define WAVCACHE_WTSIZE_1MB 0x0000 +#define WAVCACHE_WTSIZE_2MB 0x0020 +#define WAVCACHE_WTSIZE_4MB 0x0040 +#define WAVCACHE_WTSIZE_8MB 0x0060 +#define WAVCACHE_SGC_MASK 0x000c +#define WAVCACHE_SGC_DISABLED 0x0000 +#define WAVCACHE_SGC_40_47 0x0004 +#define WAVCACHE_SGC_32_47 0x0008 +#define WAVCACHE_TESTMODE 0x0001 + +/* Host Interruption */ +#define PORT_HOSTINT_CTRL 0x18 /* WORD RW */ +#define HOSTINT_CTRL_SOFT_RESET 0x8000 +#define HOSTINT_CTRL_DSOUND_RESET 0x4000 +#define HOSTINT_CTRL_HW_VOL_TO_PME 0x0400 +#define HOSTINT_CTRL_CLKRUN_ENABLED 0x0100 +#define HOSTINT_CTRL_HWVOL_ENABLED 0x0040 +#define HOSTINT_CTRL_ASSP_INT_ENABLED 0x0010 +#define HOSTINT_CTRL_ISDN_INT_ENABLED 0x0008 +#define HOSTINT_CTRL_DSOUND_INT_ENABLED 0x0004 +#define HOSTINT_CTRL_MPU401_INT_ENABLED 0x0002 +#define HOSTINT_CTRL_SB_INT_ENABLED 0x0001 + +#define PORT_HOSTINT_STAT 0x1a /* BYTE RW */ +#define HOSTINT_STAT_HWVOL 0x40 +#define HOSTINT_STAT_ASSP 0x10 +#define HOSTINT_STAT_ISDN 0x08 +#define HOSTINT_STAT_DSOUND 0x04 +#define HOSTINT_STAT_MPU401 0x02 +#define HOSTINT_STAT_SB 0x01 + +/* Hardware volume */ +#define PORT_HWVOL_VOICE_SHADOW 0x1c /* BYTE RW */ +#define PORT_HWVOL_VOICE 0x1d /* BYTE RW */ +#define PORT_HWVOL_MASTER_SHADOW 0x1e /* BYTE RW */ +#define PORT_HWVOL_MASTER 0x1f /* BYTE RW */ +#define HWVOL_NOP 0x88 +#define HWVOL_MUTE 0x99 +#define HWVOL_UP 0xaa +#define HWVOL_DOWN 0x66 + +/* CODEC */ +#define PORT_CODEC_CMD 0x30 /* BYTE W */ +#define CODEC_CMD_READ 0x80 +#define CODEC_CMD_WRITE 0x00 +#define CODEC_CMD_ADDR_MASK 0x7f + +#define PORT_CODEC_STAT 0x30 /* BYTE R */ +#define CODEC_STAT_MASK 0x01 +#define CODEC_STAT_RW_DONE 0x00 +#define CODEC_STAT_PROGLESS 0x01 + +#define PORT_CODEC_REG 0x32 /* WORD RW */ + +/* Ring bus control */ +#define PORT_RINGBUS_CTRL 0x34 /* DWORD RW */ +#define RINGBUS_CTRL_I2S_ENABLED 0x80000000 +#define RINGBUS_CTRL_RINGBUS_ENABLED 0x20000000 +#define RINGBUS_CTRL_ACLINK_ENABLED 0x10000000 +#define RINGBUS_CTRL_AC97_SWRESET 0x08000000 +#define RINGBUS_CTRL_IODMA_PLAYBACK_ENABLED 0x04000000 +#define RINGBUS_CTRL_IODMA_RECORD_ENABLED 0x02000000 + +#define RINGBUS_SRC_MIC 20 +#define RINGBUS_SRC_I2S 16 +#define RINGBUS_SRC_ADC 12 +#define RINGBUS_SRC_MODEM 8 +#define RINGBUS_SRC_DSOUND 4 +#define RINGBUS_SRC_ASSP 0 + +#define RINGBUS_DEST_MONORAL 000 +#define RINGBUS_DEST_STEREO 010 +#define RINGBUS_DEST_NONE 0 +#define RINGBUS_DEST_DAC 1 +#define RINGBUS_DEST_MODEM_IN 2 +#define RINGBUS_DEST_RESERVED3 3 +#define RINGBUS_DEST_DSOUND_IN 4 +#define RINGBUS_DEST_ASSP_IN 5 + +/* General Purpose I/O */ +#define PORT_GPIO_DATA 0x60 /* WORD RW */ +#define PORT_GPIO_MASK 0x64 /* WORD RW */ +#define PORT_GPIO_DIR 0x68 /* WORD RW */ + +/* Application Specific Signal Processor */ +#define PORT_ASSP_MEM_INDEX 0x80 /* DWORD RW */ +#define PORT_ASSP_MEM_DATA 0x84 /* WORD RW */ +#define PORT_ASSP_CTRL_A 0xa2 /* BYTE RW */ +#define PORT_ASSP_CTRL_B 0xa4 /* BYTE RW */ +#define PORT_ASSP_CTRL_C 0xa6 /* BYTE RW */ +#define PORT_ASSP_HOST_WR_INDEX 0xa8 /* BYTE W */ +#define PORT_ASSP_HOST_WR_DATA 0xaa /* BYTE RW */ +#define PORT_ASSP_INT_STAT 0xac /* BYTE RW */ + + +/* ----------------------------- + * Wave Processor Indexed Data Registers. + */ + +#define WPREG_DATA_PORT 0 +#define WPREG_CRAM_PTR 1 +#define WPREG_CRAM_DATA 2 +#define WPREG_WAVE_DATA 3 +#define WPREG_WAVE_PTR_LOW 4 +#define WPREG_WAVE_PTR_HIGH 5 + +#define WPREG_TIMER_FREQ 6 +#define WP_TIMER_FREQ_PRESCALE_MASK 0x00e0 /* actual - 9 */ +#define WP_TIMER_FREQ_PRESCALE_SHIFT 5 +#define WP_TIMER_FREQ_DIVIDE_MASK 0x001f +#define WP_TIMER_FREQ_DIVIDE_SHIFT 0 + +#define WPREG_WAVE_ROMRAM 7 +#define WP_WAVE_VIRTUAL_ENABLED 0x0400 +#define WP_WAVE_8BITRAM_ENABLED 0x0200 +#define WP_WAVE_DRAM_ENABLED 0x0100 +#define WP_WAVE_RAMSPLIT_MASK 0x00ff +#define WP_WAVE_RAMSPLIT_SHIFT 0 + +#define WPREG_BASE 12 +#define WP_PARAOUT_BASE_MASK 0xf000 +#define WP_PARAOUT_BASE_SHIFT 12 +#define WP_PARAIN_BASE_MASK 0x0f00 +#define WP_PARAIN_BASE_SHIFT 8 +#define WP_SERIAL0_BASE_MASK 0x00f0 +#define WP_SERIAL0_BASE_SHIFT 4 +#define WP_SERIAL1_BASE_MASK 0x000f +#define WP_SERIAL1_BASE_SHIFT 0 + +#define WPREG_TIMER_ENABLE 17 +#define WPREG_TIMER_START 23 + + +/* ----------------------------- + * Audio Processing Unit. + */ +#define APUREG_APUTYPE 0 +#define APU_DMA_ENABLED 0x4000 +#define APU_INT_ON_LOOP 0x2000 +#define APU_ENDCURVE 0x1000 +#define APU_APUTYPE_MASK 0x00f0 +#define APU_FILTERTYPE_MASK 0x000c +#define APU_FILTERQ_MASK 0x0003 + +/* APU types */ +#define APU_APUTYPE_SHIFT 4 + +#define APUTYPE_INACTIVE 0 +#define APUTYPE_16BITLINEAR 1 +#define APUTYPE_16BITSTEREO 2 +#define APUTYPE_8BITLINEAR 3 +#define APUTYPE_8BITSTEREO 4 +#define APUTYPE_8BITDIFF 5 +#define APUTYPE_DIGITALDELAY 6 +#define APUTYPE_DUALTAP_READER 7 +#define APUTYPE_CORRELATOR 8 +#define APUTYPE_INPUTMIXER 9 +#define APUTYPE_WAVETABLE 10 +#define APUTYPE_RATECONV 11 +#define APUTYPE_16BITPINGPONG 12 +/* APU type 13 through 15 are reserved. */ + +/* Filter types */ +#define APU_FILTERTYPE_SHIFT 2 + +#define FILTERTYPE_2POLE_LOPASS 0 +#define FILTERTYPE_2POLE_BANDPASS 1 +#define FILTERTYPE_2POLE_HIPASS 2 +#define FILTERTYPE_1POLE_LOPASS 3 +#define FILTERTYPE_1POLE_HIPASS 4 +#define FILTERTYPE_PASSTHROUGH 5 + +/* Filter Q */ +#define APU_FILTERQ_SHIFT 0 + +#define FILTERQ_LESSQ 0 +#define FILTERQ_MOREQ 3 + +/* APU register 2 */ +#define APUREG_FREQ_LOBYTE 2 +#define APU_FREQ_LOBYTE_MASK 0xff00 +#define APU_plus6dB 0x0010 + +/* APU register 3 */ +#define APUREG_FREQ_HIWORD 3 +#define APU_FREQ_HIWORD_MASK 0x0fff + +/* Frequency */ +#define APU_FREQ_LOBYTE_SHIFT 8 +#define APU_FREQ_HIWORD_SHIFT 0 +#define FREQ_Hz2DIV(freq) (((u_int64_t)(freq) << 16) / 48000) + +/* APU register 4 */ +#define APUREG_WAVESPACE 4 +#define APU_STEREO 0x8000 +#define APU_USE_SYSMEM 0x4000 +#define APU_PCMBAR_MASK 0x6000 +#define APU_64KPAGE_MASK 0xff00 + +/* PCM Base Address Register selection */ +#define APU_PCMBAR_SHIFT 13 + +/* 64KW (==128KB) Page */ +#define APU_64KPAGE_SHIFT 8 + +/* APU register 5 - 7 */ +#define APUREG_CURPTR 5 +#define APUREG_ENDPTR 6 +#define APUREG_LOOPLEN 7 + +/* APU register 9 */ +#define APUREG_AMPLITUDE 9 +#define APU_AMPLITUDE_NOW_MASK 0xff00 +#define APU_AMPLITUDE_DEST_MASK 0x00ff + +/* Amplitude now? */ +#define APU_AMPLITUDE_NOW_SHIFT 8 + +/* APU register 10 */ +#define APUREG_POSITION 10 +#define APU_RADIUS_MASK 0x00c0 +#define APU_PAN_MASK 0x003f + +/* Radius control. */ +#define APU_RADIUS_SHIFT 6 +#define RADIUS_CENTERCIRCLE 0 +#define RADIUS_MIDDLE 1 +#define RADIUS_OUTSIDE 2 + +/* Polar pan. */ +#define APU_PAN_SHIFT 0 +#define PAN_RIGHT 0x00 +#define PAN_FRONT 0x08 +#define PAN_LEFT 0x10 + + +/* ----------------------------- + * Limits. + */ +#define WPWA_MAX ((1 << 22) - 1) +#define WPWA_MAXADDR ((1 << 23) - 1) +#define MAESTRO_MAXADDR ((1 << 28) - 1) + +#endif /* MAESTRO_REG_H_INCLUDED */ diff --git a/sys/dev/sound/pci/neomagic-coeff.h b/sys/dev/sound/pci/neomagic-coeff.h new file mode 100644 index 0000000..c9e777b --- /dev/null +++ b/sys/dev/sound/pci/neomagic-coeff.h @@ -0,0 +1,4638 @@ +/* + * Copyright (c) 1999 Cameron Grant <gandalf@vilnya.demon.co.uk> + * 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$ + */ + +#define NM_TOTAL_COEFF_COUNT 0x3158 + +static 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 +}; + +static u_int16_t +coefficientSizes[] = { + /* Playback */ + 0x00C0, 0x5000, 0x0060, 0x2800, 0x0040, 0x0060, 0x1400, 0x0000, + /* Record */ + 0x0020, 0x1260, 0x0020, 0x1260, 0x0000, 0x0040, 0x1260, 0x0000, +}; + + diff --git a/sys/dev/sound/pci/neomagic.c b/sys/dev/sound/pci/neomagic.c new file mode 100644 index 0000000..86a73c5 --- /dev/null +++ b/sys/dev/sound/pci/neomagic.c @@ -0,0 +1,822 @@ +/* + * Copyright (c) 1999 Cameron Grant <gandalf@vilnya.demon.co.uk> + * 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> +#include <dev/sound/pci/neomagic.h> +#include <dev/sound/pci/neomagic-coeff.h> + +#include <pci/pcireg.h> +#include <pci/pcivar.h> + +SND_DECLARE_FILE("$FreeBSD$"); + +/* -------------------------------------------------------------------- */ + +#define NM_BUFFSIZE 16384 + +#define NM256AV_PCI_ID 0x800510c8 +#define NM256ZX_PCI_ID 0x800610c8 + +struct sc_info; + +/* 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; +}; + +/* device private data */ +struct sc_info { + 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 sc_chinfo pch, rch; +}; + +/* -------------------------------------------------------------------- */ + +/* + * prototypes + */ + +/* stuff */ +static int nm_loadcoeff(struct sc_info *sc, int dir, int num); +static int nm_setch(struct sc_chinfo *ch); +static int nm_init(struct sc_info *); +static void nm_intr(void *); + +/* talk to the card */ +static u_int32_t nm_rd(struct sc_info *, int, int); +static void nm_wr(struct sc_info *, int, u_int32_t, int); +static u_int32_t nm_rdbuf(struct sc_info *, int, int); +static void nm_wrbuf(struct sc_info *, int, u_int32_t, int); + +static u_int32_t badcards[] = { + 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 +}; + +/* -------------------------------------------------------------------- */ + +static u_int32_t nm_fmt[] = { + 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}; + +/* -------------------------------------------------------------------- */ + +/* Hardware */ +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); + + 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); + + 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); + + 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); + + 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; + } +} + +/* -------------------------------------------------------------------- */ +/* ac97 codec */ +static int +nm_waitcd(struct sc_info *sc) +{ + 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); +} + +static u_int32_t +nm_initcd(kobj_t obj, void *devinfo) +{ + struct sc_info *sc = (struct sc_info *)devinfo; + + nm_wr(sc, 0x6c0, 0x01, 1); + nm_wr(sc, 0x6cc, 0x87, 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; + + 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; + + 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 } +}; +AC97_DECLARE(nm_ac97); + +/* -------------------------------------------------------------------- */ + +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); + } +} + +static int +nm_loadcoeff(struct sc_info *sc, int dir, int num) +{ + 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; +} + +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; +} + +/* 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 %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; +} + +static int +nmchan_setformat(kobj_t obj, void *data, u_int32_t format) +{ + struct sc_chinfo *ch = data; + + 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; + + 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; + + ch->blksize = 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; +} + +static int +nmchan_getptr(kobj_t obj, void *data) +{ + 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; +} + +static struct pcmchan_caps * +nmchan_getcaps(kobj_t obj, void *data) +{ + 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 } +}; +CHANNEL_DECLARE(nmchan); + +/* The interrupt handler */ +static void +nm_intr(void *p) +{ + 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 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 + */ + +static int +nm_init(struct sc_info *sc) +{ + 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%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; +} + +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 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_MAPS + 4; + sc->reg = bus_alloc_resource(dev, SYS_RES_MEMORY, + &sc->regid, 0, ~0, 1, + 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@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; +} + +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 softc\n"); + 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_MAPS; + sc->buf = bus_alloc_resource(dev, SYS_RES_MEMORY, &sc->bufid, + 0, ~0, 1, RF_ACTIVE); + sc->regid = PCIR_MAPS + 4; + sc->reg = bus_alloc_resource(dev, SYS_RES_MEMORY, &sc->regid, + 0, ~0, 1, 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(dev, SYS_RES_IRQ, &sc->irqid, + 0, ~0, 1, 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", + rman_get_start(sc->buf), rman_get_start(sc->reg), + rman_get_start(sc->irq)); + + 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; + +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; +} + +static int +nm_pci_detach(device_t dev) +{ + 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); + + return 0; +} + +static int +nm_pci_suspend(device_t dev) +{ + struct sc_info *sc; + + 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; +} + +static int +nm_pci_resume(device_t dev) +{ + struct sc_info *sc; + + 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 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 } +}; + +static driver_t nm_driver = { + "pcm", + nm_methods, + PCM_SOFTC_SIZE, +}; + +DRIVER_MODULE(snd_neomagic, pci, nm_driver, pcm_devclass, 0, 0); +MODULE_DEPEND(snd_neomagic, snd_pcm, PCM_MINVER, PCM_PREFVER, PCM_MAXVER); +MODULE_VERSION(snd_neomagic, 1); diff --git a/sys/dev/sound/pci/neomagic.h b/sys/dev/sound/pci/neomagic.h new file mode 100644 index 0000000..8e4816e --- /dev/null +++ b/sys/dev/sound/pci/neomagic.h @@ -0,0 +1,119 @@ +/* + * Copyright (c) 1999 Cameron Grant <gandalf@vilnya.demon.co.uk> + * 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$ + */ + +#ifndef _NM256_H_ +#define _NM256_H_ + +/* The BIOS signature. */ +#define NM_SIGNATURE 0x4e4d0000 +/* Signature mask. */ +#define NM_SIG_MASK 0xffff0000 + +/* Size of the second memory area. */ +#define NM_PORT2_SIZE 4096 + +/* The base offset of the mixer in the second memory area. */ +#define NM_MIXER_OFFSET 0x600 + +/* The base offset for the AC97 test */ +#define NM_MIXER_PRESENCE 0xa06 +#define NM_PRESENCE_MASK 0x050 +#define NM_PRESENCE_VALUE 0x040 + +/* The maximum size of a coefficient entry. */ +#define NM_MAX_COEFFICIENT 0x5000 + +/* The interrupt register. */ +#define NM_INT_REG 0xa04 +/* And its bits. */ +#define NM_PLAYBACK_INT 0x40 +#define NM_RECORD_INT 0x100 +#define NM_MISC_INT_1 0x4000 +#define NM_MISC_INT_2 0x1 + +/* The AV's "mixer ready" status bit and location. */ +#define NM_MIXER_STATUS_OFFSET 0xa04 +#define NM_MIXER_READY_MASK 0x0800 + +/* + * 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 +#define NM2_MISC_INT_2 0x2 + +/* The ZX's "mixer ready" status bit and location. */ +#define NM2_MIXER_STATUS_OFFSET 0xa06 +#define NM2_MIXER_READY_MASK 0x0800 + +/* The playback registers start from here. */ +#define NM_PLAYBACK_REG_OFFSET 0x0 +/* The record registers start from here. */ +#define NM_RECORD_REG_OFFSET 0x200 + +/* The rate register is located 2 bytes from the start of the register area. */ +#define NM_RATE_REG_OFFSET 2 + +/* Mono/stereo flag, number of bits on playback, and rate mask. */ +#define NM_RATE_STEREO 1 +#define NM_RATE_BITS_16 2 +#define NM_RATE_MASK 0xf0 + +/* Playback enable register. */ +#define NM_PLAYBACK_ENABLE_REG (NM_PLAYBACK_REG_OFFSET + 0x1) +#define NM_PLAYBACK_ENABLE_FLAG 1 +#define NM_PLAYBACK_ONESHOT 2 +#define NM_PLAYBACK_FREERUN 4 + +/* Mutes the audio output. */ +#define NM_AUDIO_MUTE_REG (NM_PLAYBACK_REG_OFFSET + 0x18) +#define NM_AUDIO_MUTE_LEFT 0x8000 +#define NM_AUDIO_MUTE_RIGHT 0x0080 +#define NM_AUDIO_MUTE_BOTH 0x8080 + +/* Recording enable register. */ +#define NM_RECORD_ENABLE_REG (NM_RECORD_REG_OFFSET + 0) +#define NM_RECORD_ENABLE_FLAG 1 +#define NM_RECORD_FREERUN 2 + +#define NM_RBUFFER_START (NM_RECORD_REG_OFFSET + 0x4) +#define NM_RBUFFER_END (NM_RECORD_REG_OFFSET + 0x10) +#define NM_RBUFFER_WMARK (NM_RECORD_REG_OFFSET + 0xc) +#define NM_RBUFFER_CURRP (NM_RECORD_REG_OFFSET + 0x8) + +#define NM_PBUFFER_START (NM_PLAYBACK_REG_OFFSET + 0x4) +#define NM_PBUFFER_END (NM_PLAYBACK_REG_OFFSET + 0x14) +#define NM_PBUFFER_WMARK (NM_PLAYBACK_REG_OFFSET + 0xc) +#define NM_PBUFFER_CURRP (NM_PLAYBACK_REG_OFFSET + 0x8) + + +#endif diff --git a/sys/dev/sound/pci/solo.c b/sys/dev/sound/pci/solo.c new file mode 100644 index 0000000..a077cca --- /dev/null +++ b/sys/dev/sound/pci/solo.c @@ -0,0 +1,1053 @@ +/* + * Copyright (c) 1999 Cameron Grant <gandalf@vilnya.demon.co.uk> + * + * 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 <pci/pcireg.h> +#include <pci/pcivar.h> + +#include <dev/sound/isa/sb.h> +#include <dev/sound/chip.h> + +#include "mixer_if.h" + +SND_DECLARE_FILE("$FreeBSD$"); + +#define SOLO_DEFAULT_BUFSZ 16384 +#define ABS(x) (((x) < 0)? -(x) : (x)) + +/* if defined, playback always uses the 2nd channel and full duplex works */ +#undef ESS18XX_DUPLEX + +/* more accurate clocks and split audio1/audio2 rates */ +#define ESS18XX_NEWSPEED + +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 +}; +static struct pcmchan_caps ess_playcaps = {5000, 49000, ess_playfmt, 0}; + +/* + * 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 +}; +static struct pcmchan_caps ess_reccaps = {5000, 49000, 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 { + 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, duplex:1, newspeed:1, dmasz[2]; + unsigned int bufsz; + + struct ess_chinfo pch, rch; +}; + +static int ess_rd(struct ess_info *sc, int reg); +static void ess_wr(struct ess_info *sc, int reg, u_int8_t val); +static int ess_dspready(struct ess_info *sc); +static int ess_cmd(struct ess_info *sc, u_char val); +static int ess_cmd1(struct ess_info *sc, u_char cmd, int val); +static int ess_get_byte(struct ess_info *sc); +static void ess_setmixer(struct ess_info *sc, u_int port, u_int value); +static int ess_getmixer(struct ess_info *sc, u_int port); +static int ess_reset_dsp(struct ess_info *sc); + +static int ess_write(struct ess_info *sc, u_char reg, int val); +static int ess_read(struct ess_info *sc, u_char reg); + +static void ess_intr(void *arg); +static int ess_setupch(struct ess_info *sc, int ch, int dir, int spd, u_int32_t fmt, int len); +static int ess_start(struct ess_chinfo *ch); +static int ess_stop(struct ess_chinfo *ch); + +static int ess_dmasetup(struct ess_info *sc, int ch, u_int32_t base, u_int16_t cnt, int dir); +static int ess_dmapos(struct ess_info *sc, int ch); +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 + */ + +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); + + 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); + + 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); +} + +static void +ess_wr(struct ess_info *sc, int reg, u_int8_t val) +{ + port_wr(sc->sb, reg, val, 1); +} + +static int +ess_dspready(struct ess_info *sc) +{ + return ((ess_rd(sc, SBDSP_STATUS) & 0x80) == 0); +} + +static int +ess_dspwr(struct ess_info *sc, u_char val) +{ + 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; +} + +static int +ess_cmd(struct ess_info *sc, u_char 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, %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) +{ + u_long flags; + + DEB(printf("ess_setmixer: reg=%x, val=%x\n", port, value);) + flags = spltty(); + 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); + splx(flags); +} + +static int +ess_getmixer(struct ess_info *sc, u_int port) +{ + int val; + u_long flags; + + flags = spltty(); + ess_wr(sc, SB_MIX_ADDR, (u_char) (port & 0xff)); /* Select register */ + DELAY(10); + val = ess_rd(sc, SB_MIX_DATA); + DELAY(10); + splx(flags); + + return val; +} + +static int +ess_get_byte(struct ess_info *sc) +{ + 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; +} + +static int +ess_write(struct ess_info *sc, u_char reg, int 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; +} + +static int +ess_reset_dsp(struct ess_info *sc) +{ + 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))); +*/ + 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; + + src = 0; + if (ess_getmixer(sc, 0x7a) & 0x80) + src |= 2; + if (ess_rd(sc, 0x0c) & 0x01) + src |= 1; + + if (src == 0) + 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); + } + chn_intr(sc->pch.channel); + } + + 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); + } + chn_intr(sc->rch.channel); + } + + if (src & 2) + ess_setmixer(sc, 0x7a, ess_getmixer(sc, 0x7a) & ~0x80); + if (src & 1) + ess_rd(sc, DSP_DATA_AVAIL); +} + +/* utility functions for ESS */ +static u_int8_t +ess_calcspeed8(int *spd) +{ + 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; +} + +static u_int8_t +ess_calcspeed9(int *spd) +{ + 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; + + use0 = (ABS(speed - s0) < ABS(speed - s1))? 1 : 0; + + *spd = use0? s0 : s1; + return use0? t0 : t1; +} + +static u_int8_t +ess_calcfilter(int spd) +{ + int 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_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; +} +static int +ess_start(struct ess_chinfo *ch) +{ + struct ess_info *sc = ch->parent; + + 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 */ +#endif + 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; + + 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; +} + +/* -------------------------------------------------------------------- */ +/* channel interface for ESS18xx */ +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; + + 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, sc->bufsz) == -1) + 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; + + 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; + + 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; + + 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; + + DEB(printf("esschan_trigger: %d\n",go)); + if (go == PCMTRIG_EMLDMAWR || go == PCMTRIG_EMLDMARD) + return 0; + + 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; + } + return 0; +} + +static int +esschan_getptr(kobj_t obj, void *data) +{ + struct ess_chinfo *ch = data; + struct ess_info *sc = ch->parent; + + return ess_dmapos(sc, ch->hwch); +} + +static struct pcmchan_caps * +esschan_getcaps(kobj_t obj, void *data) +{ + struct ess_chinfo *ch = data; + + 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 } +}; +CHANNEL_DECLARE(esschan); + +/************************************************************/ + +static int +essmix_init(struct snd_mixer *m) +{ + struct ess_info *sc = mix_getdevinfo(m); + + 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); + + ess_setmixer(sc, 0, 0); /* reset */ + + 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; + + 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; + + 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; + + case SOUND_MASK_IMIX: + recdev = 0x05; + break; + + case SOUND_MASK_MIC: + default: + recdev = 0x00; + src = SOUND_MASK_MIC; + break; + } + + ess_setmixer(sc, 0x1c, recdev); + + 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 } +}; +MIXER_DECLARE(solomixer); + +/************************************************************/ + +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; +} + +static int +ess_dmapos(struct ess_info *sc, int ch) +{ + int p = 0, i = 0, j = 0; + u_long flags; + + KASSERT(ch == 1 || ch == 2, ("bad ch")); + flags = spltty(); + 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 & %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); + splx(flags); + 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; +} + +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, 0 * 4 + PCIR_MAPS, sc->io); + sc->io = 0; + } + + if (sc->sb) { + bus_release_resource(dev, SYS_RES_IOPORT, 1 * 4 + PCIR_MAPS, sc->sb); + sc->sb = 0; + } + + if (sc->vc) { + bus_release_resource(dev, SYS_RES_IOPORT, 2 * 4 + PCIR_MAPS, sc->vc); + sc->vc = 0; + } + + if (sc->mpu) { + bus_release_resource(dev, SYS_RES_IOPORT, 3 * 4 + PCIR_MAPS, sc->mpu); + sc->mpu = 0; + } + + if (sc->gp) { + bus_release_resource(dev, SYS_RES_IOPORT, 4 * 4 + PCIR_MAPS, sc->gp); + sc->gp = 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; + + rid = 0 * 4 + PCIR_MAPS; + sc->io = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid, 0, ~0, 1, RF_ACTIVE); + + rid = 1 * 4 + PCIR_MAPS; + sc->sb = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid, 0, ~0, 1, RF_ACTIVE); + + rid = 2 * 4 + PCIR_MAPS; + sc->vc = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid, 0, ~0, 1, RF_ACTIVE); + + rid = 3 * 4 + PCIR_MAPS; + sc->mpu = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid, 0, ~0, 1, RF_ACTIVE); + + rid = 4 * 4 + PCIR_MAPS; + sc->gp = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid, 0, ~0, 1, RF_ACTIVE); + + rid = 0; + sc->irq = bus_alloc_resource(dev, SYS_RES_IRQ, &rid, 0, ~0, 1, RF_ACTIVE | RF_SHAREABLE); + + return (sc->irq && sc->io && sc->sb && sc->vc && sc->mpu && sc->gp)? 0 : ENXIO; +} + +static int +ess_probe(device_t dev) +{ + 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? 0 : ENXIO; +} + +#define ESS_PCI_LEGACYCONTROL 0x40 +#define ESS_PCI_CONFIG 0x50 +#define ESS_PCI_DDMACONTROL 0x60 + +static int +ess_suspend(device_t dev) +{ + return 0; +} + +static int +ess_resume(device_t dev) +{ + uint16_t ddma; + uint32_t data; + struct ess_info *sc = pcm_getdevinfo(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); + + 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)) + goto no; + if (mixer_reinit(dev)) + goto no; + if (sc->newspeed) + ess_setmixer(sc, 0x71, 0x2a); + + port_wr(sc->io, 0x7, 0xb0, 1); /* enable irqs */ + + 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); + + if (ess_reset_dsp(sc)) + goto no; + if (mixer_init(dev, &solomixer_class, sc)) + goto no; + + port_wr(sc->io, 0x7, 0xb0, 1); /* enable irqs */ +#ifdef ESS18XX_DUPLEX + sc->duplex = 1; +#else + sc->duplex = 0; +#endif + +#ifdef ESS18XX_NEWSPEED + sc->newspeed = 1; +#else + sc->newspeed = 0; +#endif + if (sc->newspeed) + ess_setmixer(sc, 0x71, 0x2a); + + 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*/65536, /*boundary*/0, + /*lowaddr*/BUS_SPACE_MAXADDR_24BIT, + /*highaddr*/BUS_SPACE_MAXADDR, + /*filter*/NULL, /*filterarg*/NULL, + /*maxsize*/sc->bufsz, /*nsegments*/1, + /*maxsegz*/0x3ffff, + /*flags*/0, &sc->parent_dmat) != 0) { + device_printf(dev, "unable to create dma tag\n"); + goto no; + } + + snprintf(status, SND_STATUSLEN, "at io 0x%lx,0x%lx,0x%lx irq %ld", + rman_get_start(sc->io), rman_get_start(sc->sb), rman_get_start(sc->vc), + rman_get_start(sc->irq)); + + 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; + +no: + ess_release_resources(sc, dev); + return ENXIO; +} + +static int +ess_detach(device_t dev) +{ + 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; +} + +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), + + { 0, 0 } +}; + +static driver_t ess_driver = { + "pcm", + ess_methods, + PCM_SOFTC_SIZE, +}; + +DRIVER_MODULE(snd_solo, pci, ess_driver, pcm_devclass, 0, 0); +MODULE_DEPEND(snd_solo, snd_pcm, PCM_MINVER, PCM_PREFVER, PCM_MAXVER); +MODULE_VERSION(snd_solo, 1); + + + diff --git a/sys/dev/sound/pci/t4dwave.c b/sys/dev/sound/pci/t4dwave.c new file mode 100644 index 0000000..cd7de77 --- /dev/null +++ b/sys/dev/sound/pci/t4dwave.c @@ -0,0 +1,977 @@ +/* + * Copyright (c) 1999 Cameron Grant <gandalf@vilnya.demon.co.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. + */ + +#include <dev/sound/pcm/sound.h> +#include <dev/sound/pcm/ac97.h> +#include <dev/sound/pci/t4dwave.h> + +#include <pci/pcireg.h> +#include <pci/pcivar.h> + +SND_DECLARE_FILE("$FreeBSD$"); + +/* -------------------------------------------------------------------- */ + +#define TDX_PCI_ID 0x20001023 +#define TNX_PCI_ID 0x20011023 +#define ALI_PCI_ID 0x545110b9 +#define SPA_PCI_ID 0x70181039 + +#define TR_DEFAULT_BUFSZ 0x1000 +#define TR_TIMEOUT_CDC 0xffff +#define TR_MAXPLAYCH 4 + +struct tr_info; + +/* 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; +}; + +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; +}; + +/* device private data */ +struct tr_info { + u_int32_t type; + u_int32_t rev; + + 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 mtx *lock; + + u_int32_t playchns; + unsigned int bufsz; + + 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 +}; +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 +}; +static struct pcmchan_caps tr_playcaps = {4000, 48000, tr_playfmt, 0}; + +/* -------------------------------------------------------------------- */ + +/* Hardware */ + +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; + } +} + +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; + } +} + +/* -------------------------------------------------------------------- */ +/* ac97 codec */ + +static int +tr_rdcd(kobj_t obj, void *devinfo, int regno) +{ + 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 %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; + + 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; + + regno &= 0x7f; +#if 0 + 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); + } +#if 0 + 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 %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 } +}; +AC97_DECLARE(tr_ac97); + +/* -------------------------------------------------------------------- */ +/* playback channel interrupts */ + +#if 0 +static u_int32_t +tr_testint(struct tr_chinfo *ch) +{ + 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); +} +#endif + +static void +tr_clrint(struct tr_chinfo *ch) +{ + 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); +} + +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); +} + +/* playback channels */ + +static void +tr_selch(struct tr_chinfo *ch) +{ + 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); +} + +static void +tr_startch(struct tr_chinfo *ch) +{ + 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); +} + +static void +tr_stopch(struct tr_chinfo *ch) +{ + 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); +} + +static void +tr_wrch(struct tr_chinfo *ch) +{ + 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); +} + +static void +tr_rdch(struct tr_chinfo *ch) +{ + 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; + } +} + +static u_int32_t +tr_fmttobits(u_int32_t fmt) +{ + u_int32_t bits; + + bits = 0; + bits |= (fmt & AFMT_SIGNED)? 0x2 : 0; + bits |= (fmt & AFMT_STEREO)? 0x4 : 0; + bits |= (fmt & AFMT_16BIT)? 0x8 : 0; + + return bits; +} + +/* -------------------------------------------------------------------- */ +/* channel interface */ + +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; + + 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) == -1) + return NULL; + + return ch; +} + +static int +trpchan_setformat(kobj_t obj, void *data, u_int32_t format) +{ + struct tr_chinfo *ch = data; + + ch->ctrl = tr_fmttobits(format) | 0x01; + + return 0; +} + +static int +trpchan_setspeed(kobj_t obj, void *data, u_int32_t speed) +{ + struct tr_chinfo *ch = data; + + 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; + + sndbuf_resize(ch->buffer, 2, blocksize); + return blocksize; +} + +static int +trpchan_trigger(kobj_t obj, void *data, int go) +{ + struct tr_chinfo *ch = data; + + if (go == PCMTRIG_EMLDMAWR || go == PCMTRIG_EMLDMARD) + 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; + } + + return 0; +} + +static int +trpchan_getptr(kobj_t obj, void *data) +{ + struct tr_chinfo *ch = data; + + tr_rdch(ch); + return ch->cso * sndbuf_getbps(ch->buffer); +} + +static struct pcmchan_caps * +trpchan_getcaps(kobj_t obj, void *data) +{ + 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 } +}; +CHANNEL_DECLARE(trpchan); + +/* -------------------------------------------------------------------- */ +/* rec channel interface */ + +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; + + 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) == -1) + return NULL; + + 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); + + 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; + + /* 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; +} + +static int +trrchan_setblocksize(kobj_t obj, void *data, u_int32_t blocksize) +{ + struct tr_rchinfo *ch = data; + + sndbuf_resize(ch->buffer, 2, 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; + } + + /* 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; + + /* 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; +} + +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 } +}; +CHANNEL_DECLARE(trrchan); + +/* -------------------------------------------------------------------- */ +/* The interrupt handler */ + +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); + } +} + +/* -------------------------------------------------------------------- */ + +/* + * 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; + } + + 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 0; + case ALI_PCI_ID: + device_set_desc(dev, "Acer Labs M5451"); + return 0; + case TDX_PCI_ID: + device_set_desc(dev, "Trident 4DWave DX"); + return 0; + case TNX_PCI_ID: + device_set_desc(dev, "Trident 4DWave NX"); + return 0; + } + + 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 softc\n"); + 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_MAPS; + tr->regtype = SYS_RES_IOPORT; + tr->reg = bus_alloc_resource(dev, tr->regtype, &tr->regid, 0, ~0, 1, 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(dev, SYS_RES_IRQ, &tr->irqid, + 0, ~0, 1, RF_ACTIVE | RF_SHAREABLE); + if (!tr->irq || snd_setup_intr(dev, tr->irq, INTR_MPSAFE, tr_intr, tr, &tr->ih)) { + device_printf(dev, "unable to map interrupt\n"); + 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*/tr->bufsz, /*nsegments*/1, /*maxsegz*/0x3ffff, + /*flags*/0, &tr->parent_dmat) != 0) { + device_printf(dev, "unable to create dma tag\n"); + goto bad; + } + + snprintf(status, 64, "at io 0x%lx irq %ld", + rman_get_start(tr->reg), rman_get_start(tr->irq)); + + 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); + + 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; +} + +static int +tr_pci_detach(device_t dev) +{ + 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); + + return 0; +} + +static int +tr_pci_suspend(device_t dev) +{ + int i; + struct tr_info *tr; + + 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); + } + + 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 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; +} + +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 } +}; + +static driver_t tr_driver = { + "pcm", + tr_methods, + PCM_SOFTC_SIZE, +}; + +DRIVER_MODULE(snd_t4dwave, pci, tr_driver, pcm_devclass, 0, 0); +MODULE_DEPEND(snd_t4dwave, snd_pcm, PCM_MINVER, PCM_PREFVER, PCM_MAXVER); +MODULE_VERSION(snd_t4dwave, 1); diff --git a/sys/dev/sound/pci/t4dwave.h b/sys/dev/sound/pci/t4dwave.h new file mode 100644 index 0000000..893bc81 --- /dev/null +++ b/sys/dev/sound/pci/t4dwave.h @@ -0,0 +1,104 @@ +/* + * Copyright (c) 1999 Cameron Grant <gandalf@vilnya.demon.co.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$ + */ + +#ifndef _T4DWAVE_REG_H +#define _T4DWAVE_REG_H + +#define TR_REG_CIR 0xa0 +#define TR_CIR_MASK 0x0000003f +#define TR_CIR_ADDRENA 0x00001000 +#define TR_CIR_MIDENA 0x00002000 +#define TR_REG_MISCINT 0xb0 +#define TR_INT_ADDR 0x00000020 +#define TR_INT_SB 0x00000004 + +#define TR_REG_DMAR0 0x00 +#define TR_REG_DMAR4 0x04 +#define TR_REG_DMAR11 0x0b +#define TR_REG_DMAR15 0x0f +#define TR_REG_SBR4 0x14 +#define TR_REG_SBR5 0x15 +#define TR_SB_INTSTATUS 0x82 +#define TR_REG_SBR9 0x1e +#define TR_REG_SBR10 0x1f +#define TR_REG_SBBL 0xc0 +#define TR_REG_SBCTRL 0xc4 +#define TR_REG_SBDELTA 0xac + +#define TR_CDC_DATA 16 +#define TDX_REG_CODECWR 0x40 +#define TDX_REG_CODECRD 0x44 +#define TDX_CDC_RWSTAT 0x00008000 +#define TDX_REG_CODECST 0x48 +#define TDX_CDC_SBCTRL 0x40 +#define TDX_CDC_ACTIVE 0x20 +#define TDX_CDC_READY 0x10 +#define TDX_CDC_ADCON 0x08 +#define TDX_CDC_DACON 0x02 +#define TDX_CDC_RESET 0x01 +#define TDX_CDC_ON (TDX_CDC_ADCON|TDX_CDC_DACON) + +#define SPA_REG_CODECRD 0x44 +#define SPA_REG_CODECWR 0x40 +#define SPA_REG_CODECST 0x48 +#define SPA_RST_OFF 0x0f0000 +#define SPA_REG_GPIO 0x48 +#define SPA_CDC_RWSTAT 0x00008000 + +#define TNX_REG_CODECWR 0x44 +#define TNX_REG_CODEC1RD 0x48 +#define TNX_REG_CODEC2RD 0x4c +#define TNX_CDC_RWSTAT 0x00000c00 +#define TNX_CDC_SEC 0x00000100 +#define TNX_REG_CODECST 0x40 +#define TNX_CDC_READY2 0x40 +#define TNX_CDC_ADC2ON 0x20 +#define TNX_CDC_DAC2ON 0x10 +#define TNX_CDC_READY1 0x08 +#define TNX_CDC_ADC1ON 0x04 +#define TNX_CDC_DAC1ON 0x02 +#define TNX_CDC_RESET 0x01 +#define TNX_CDC_ON (TNX_CDC_ADC1ON|TNX_CDC_DAC1ON) + + +#define TR_REG_STARTA 0x80 +#define TR_REG_STOPA 0x84 +#define TR_REG_CSPF_A 0x90 +#define TR_REG_ADDRINTA 0x98 +#define TR_REG_INTENA 0xa4 + +#define TR_REG_STARTB 0xb4 +#define TR_REG_STOPB 0xb8 +#define TR_REG_CSPF_B 0xbc +#define TR_REG_ADDRINTB 0xd8 +#define TR_REG_INTENB 0xdc + +#define TR_REG_CHNBASE 0xe0 +#define TR_CHN_REGS 5 + +#endif diff --git a/sys/dev/sound/pci/via8233.c b/sys/dev/sound/pci/via8233.c new file mode 100644 index 0000000..f8f136e --- /dev/null +++ b/sys/dev/sound/pci/via8233.c @@ -0,0 +1,921 @@ +/* + * Copyright (c) 2002 Orion Hodson <orion@freebsd.org> + * Portions of this code derived from via82c686.c: + * Copyright (c) 2000 David Jones <dej@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. + */ + +#include <dev/sound/pcm/sound.h> +#include <dev/sound/pcm/ac97.h> + +#include <pci/pcireg.h> +#include <pci/pcivar.h> +#include <sys/sysctl.h> + +#include <dev/sound/pci/via8233.h> + +SND_DECLARE_FILE("$FreeBSD$"); + +#define VIA8233_PCI_ID 0x30591106 + +#define VIA8233_REV_ID_8233PRE 0x10 +#define VIA8233_REV_ID_8233C 0x20 +#define VIA8233_REV_ID_8233 0x30 +#define VIA8233_REV_ID_8233A 0x40 +#define VIA8233_REV_ID_8235 0x50 + +#define SEGS_PER_CHAN 2 /* Segments per channel */ +#define NDXSCHANS 4 /* No of DXS channels */ +#define NMSGDCHANS 1 /* No of multichannel SGD */ +#define NWRCHANS 1 /* No of write channels */ +#define NCHANS (NWRCHANS + NDXSCHANS + NMSGDCHANS) +#define NSEGS NCHANS * SEGS_PER_CHAN /* Segments in SGD table */ + +#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; +#define VIA_DMAOP_EOL 0x80000000 +#define VIA_DMAOP_FLAG 0x40000000 +#define VIA_DMAOP_STOP 0x20000000 +#define VIA_DMAOP_COUNT(x) ((x)&0x00FFFFFF) +}; + +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 { + 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[NDXSCHANS + NMSGDCHANS]; + struct via_chinfo rch[NWRCHANS]; + struct via_dma_op *sgd_table; + u_int16_t codec_caps; + u_int16_t n_dxs_registered; +}; + +static u_int32_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 u_int32_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; + } +} + +static void +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; + } +} + +/* -------------------------------------------------------------------- */ +/* Codec interface */ + +static int +via_waitready_codec(struct via_info *via) +{ + 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 busy\n"); + return 1; +} + +static int +via_waitvalid_codec(struct via_info *via) +{ + 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 invalid\n"); + return 1; +} + +static int +via_write_codec(kobj_t obj, void *addr, int reg, u_int32_t val) +{ + struct via_info *via = addr; + + 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); + + return 0; +} + +static int +via_read_codec(kobj_t obj, void *addr, int reg) +{ + struct via_info *via = addr; + + 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); + + if (via_waitready_codec(via)) + return -1; + + if (via_waitvalid_codec(via)) + return -1; + + 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 } +}; +AC97_DECLARE(via_ac97); + +/* -------------------------------------------------------------------- */ + +static int +via_buildsgdt(struct via_chinfo *ch) +{ + u_int32_t phys_addr, flag; + int i, seg_size; + + seg_size = sndbuf_getsize(ch->buffer) / SEGS_PER_CHAN; + 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; + } + + return 0; +} + +/* -------------------------------------------------------------------- */ +/* Format setting functions */ + +static int +via8233wr_setformat(kobj_t obj, void *data, u_int32_t format) +{ + struct via_chinfo *ch = data; + struct via_info *via = ch->parent; + + u_int32_t f = WR_FORMAT_STOP_INDEX; + + if (format & AFMT_STEREO) + f |= WR_FORMAT_STEREO; + if (format & AFMT_S16_LE) + f |= WR_FORMAT_16BIT; + via_wr(via, VIA_WR0_FORMAT, f, 4); + + return 0; +} + +static int +via8233dxs_setformat(kobj_t obj, void *data, u_int32_t format) +{ + struct via_chinfo *ch = data; + struct via_info *via = ch->parent; + + u_int32_t r = ch->rbase + VIA8233_RP_DXS_RATEFMT; + u_int32_t 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); + + return 0; +} + +static int +via8233msgd_setformat(kobj_t obj, void *data, u_int32_t format) +{ + 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; + + 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); + } + + via_wr(via, VIA_MC_SLOT_SELECT, s, 4); + via_wr(via, VIA_MC_SGD_FORMAT, v, 1); + + return 0; +} + +/* -------------------------------------------------------------------- */ +/* Speed setting functions */ + +static int +via8233wr_setspeed(kobj_t obj, void *data, u_int32_t speed) +{ + struct via_chinfo *ch = data; + struct via_info *via = ch->parent; + + u_int32_t spd = 48000; + if (via->codec_caps & AC97_EXTCAP_VRA) { + spd = ac97_setrate(via->codec, AC97_REGEXT_LADCRATE, speed); + } + return spd; +} + +static int +via8233dxs_setspeed(kobj_t obj, void *data, u_int32_t speed) +{ + struct via_chinfo *ch = data; + struct via_info *via = ch->parent; + + u_int32_t r = ch->rbase + VIA8233_RP_DXS_RATEFMT; + u_int32_t v = via_rd(via, r, 4) & ~VIA8233_DXS_RATEFMT_48K; + + /* 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); + + return speed; +} + +static int +via8233msgd_setspeed(kobj_t obj, void *data, u_int32_t speed) +{ + 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); + + return 48000; +} + +/* -------------------------------------------------------------------- */ +/* Format probing functions */ + +static struct pcmchan_caps * +via8233wr_getcaps(kobj_t obj, void *data) +{ + 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; +} + +static struct pcmchan_caps * +via8233dxs_getcaps(kobj_t obj, void *data) +{ + /* Controlled by onboard registers */ + 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; + + /* 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) +{ + struct via_chinfo *ch = data; + sndbuf_resize(ch->buffer, SEGS_PER_CHAN, blocksize); + ch->blksz = sndbuf_getblksz(ch->buffer); + 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 = via_rd(via, ch->rbase + VIA_RP_CURRENT_COUNT, 4); + u_int32_t index = v >> 24; /* Last completed buffer */ + u_int32_t count = v & 0x00ffffff; /* Bytes remaining */ + int ptr = (index + 1) * ch->blksz - count; + ptr %= SEGS_PER_CHAN * ch->blksz; /* Wrap to available space */ + + 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); +} + +/* -------------------------------------------------------------------- */ +/* Channel initialization functions */ + +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); +} + +static void* +via8233wr_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 = &via->rch[c->num]; + + ch->parent = via; + ch->channel = c; + ch->buffer = b; + ch->dir = dir; + + ch->rbase = VIA_WR_BASE(c->num); + via_wr(via, ch->rbase + VIA_WR_RP_SGD_FORMAT, WR_FIFO_ENABLE, 1); + + if (sndbuf_alloc(ch->buffer, via->parent_dmat, via->bufsz) == -1) + return NULL; + via8233chan_sgdinit(via, ch, c->num); + via8233chan_reset(via, ch); + + return ch; +} + +static void* +via8233dxs_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 = &via->pch[c->num]; + + ch->parent = via; + ch->channel = c; + ch->buffer = b; + ch->dir = dir; + + /* + * 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++; + + if (sndbuf_alloc(ch->buffer, via->parent_dmat, via->bufsz) == -1) + return NULL; + via8233chan_sgdinit(via, ch, NWRCHANS + c->num); + via8233chan_reset(via, ch); + + return ch; +} + +static void* +via8233msgd_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 = &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) == -1) + return NULL; + via8233chan_sgdinit(via, ch, NWRCHANS + c->num); + via8233chan_reset(via, 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); + } + } +} + +static int +via8233chan_trigger(kobj_t obj, void* data, int go) +{ + struct via_chinfo *ch = data; + struct via_info *via = ch->parent; + + 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 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 } +}; +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 } +}; +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 } +}; +CHANNEL_DECLARE(via8233msgd); + +/* -------------------------------------------------------------------- */ + +static void +via_intr(void *p) +{ + struct via_info *via = p; + int i, stat; + + /* Poll playback channels */ + for (i = 0; i < NDXSCHANS + NMSGDCHANS; i++) { + if (via->pch[i].rbase == 0) + continue; + stat = via->pch[i].rbase + VIA_RP_STATUS; + if (via_rd(via, stat, 1) & SGD_STATUS_INTR) { + via_wr(via, stat, SGD_STATUS_INTR, 1); + chn_intr(via->pch[i].channel); + } + } + + /* Poll record channels */ + for (i = 0; i < NWRCHANS; i++) { + if (via->rch[i].rbase == 0) + continue; + stat = via->rch[i].rbase + VIA_RP_STATUS; + if (via_rd(via, stat, 1) & SGD_STATUS_INTR) { + via_wr(via, stat, SGD_STATUS_INTR, 1); + chn_intr(via->rch[i].channel); + } + } +} + +/* + * 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 0; + case VIA8233_REV_ID_8233C: + device_set_desc(dev, "VIA VT8233C"); + return 0; + case VIA8233_REV_ID_8233: + device_set_desc(dev, "VIA VT8233"); + return 0; + case VIA8233_REV_ID_8233A: + device_set_desc(dev, "VIA VT8233A"); + return 0; + case VIA8233_REV_ID_8235: + device_set_desc(dev, "VIA VT8235"); + return 0; + default: + device_set_desc(dev, "VIA VT8233X"); /* Unknown */ + return 0; + } + } + 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; +} + +static int +via_chip_init(device_t dev) +{ + u_int32_t data, cnt; + + /* 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; +} + +#ifdef SND_DYNSYSCTL +static int via8233_spdif_en; + +static int +sysctl_via8233_spdif_enable(SYSCTL_HANDLER_ARGS) +{ + device_t dev; + int err, new_en, r; + + new_en = via8233_spdif_en; + 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; + via8233_spdif_en = new_en; + + dev = oidp->oid_arg1; + r = pci_read_config(dev, VIA_PCI_SPDIF, 1) & ~VIA_SPDIF_EN; + if (new_en) + r |= VIA_SPDIF_EN; + pci_write_config(dev, VIA_PCI_SPDIF, r, 1); + return 0; +} +#endif /* SND_DYNSYSCTL */ + +static void +via_init_sysctls(device_t dev) +{ +#ifdef SND_DYNSYSCTL + int r; + + r = pci_read_config(dev, VIA_PCI_SPDIF, 1); + via8233_spdif_en = (r & VIA_SPDIF_EN) ? 1 : 0; + + 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"); +#endif +} + +static int +via_attach(device_t dev) +{ + struct via_info *via = 0; + char status[SND_STATUSLEN]; + + if ((via = malloc(sizeof *via, M_DEVBUF, M_NOWAIT | M_ZERO)) == NULL) { + device_printf(dev, "cannot allocate softc\n"); + return ENXIO; + } + + pci_set_powerstate(dev, PCI_POWERSTATE_D0); + pci_enable_busmaster(dev); + + via->regid = PCIR_MAPS; + via->reg = bus_alloc_resource(dev, SYS_RES_IOPORT, &via->regid, 0, ~0, + 1, 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(dev, SYS_RES_IRQ, &via->irqid, 0, ~0, 1, + RF_ACTIVE | RF_SHAREABLE); + if (!via->irq || + snd_setup_intr(dev, via->irq, 0, via_intr, via, &via->ih)) { + device_printf(dev, "unable to map interrupt\n"); + 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, &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*/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, &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)) { + 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", + rman_get_start(via->reg), rman_get_start(via->irq)); + + /* Register */ + if (pci_get_revid(dev) == VIA8233_REV_ID_8233A) { + if (pcm_register(dev, via, NMSGDCHANS, 1)) goto bad; + /* + * 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). + pcm_addchan(dev, PCMDIR_PLAY, &via8233dxs_class, via); + */ + pcm_addchan(dev, PCMDIR_PLAY, &via8233msgd_class, via); + pcm_addchan(dev, PCMDIR_REC, &via8233wr_class, via); + } else { + int i; + if (pcm_register(dev, via, NMSGDCHANS + NDXSCHANS, NWRCHANS)) goto bad; + for (i = 0; i < NDXSCHANS; i++) + pcm_addchan(dev, PCMDIR_PLAY, &via8233dxs_class, via); + pcm_addchan(dev, PCMDIR_PLAY, &via8233msgd_class, via); + for (i = 0; i < NWRCHANS; i++) + pcm_addchan(dev, PCMDIR_REC, &via8233wr_class, via); + via_init_sysctls(dev); + } + + 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) 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; + + 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); + 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} +}; + +static driver_t via_driver = { + "pcm", + via_methods, + PCM_SOFTC_SIZE, +}; + +DRIVER_MODULE(snd_via8233, pci, via_driver, pcm_devclass, 0, 0); +MODULE_DEPEND(snd_via8233, snd_pcm, PCM_MINVER, PCM_PREFVER, PCM_MAXVER); +MODULE_VERSION(snd_via8233, 1); diff --git a/sys/dev/sound/pci/via8233.h b/sys/dev/sound/pci/via8233.h new file mode 100644 index 0000000..bc6f57a --- /dev/null +++ b/sys/dev/sound/pci/via8233.h @@ -0,0 +1,166 @@ +/* + * Copyright (c) 2002 Orion Hodson <orion@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$ + */ + +#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) + */ + +#define VIA_PCI_SPDIF 0x49 +#define VIA_SPDIF_EN 0x08 + +#define VIA_DXS0_BASE 0x00 +#define VIA_DXS1_BASE 0x10 +#define VIA_DXS2_BASE 0x20 +#define VIA_DXS3_BASE 0x30 +#define VIA_DXS_BASE(n) (0x10 * (n)) +#define BASE_IS_VIA_DXS_REG(x) ((x) <= VIA_DXS3_BASE) + +#define VIA8233_RP_DXS_LVOL 0x02 +#define VIA8233_RP_DXS_RVOL 0x03 +#define VIA8233_DXS_MUTE 0x3f +#define VIA8233_RP_DXS_RATEFMT 0x08 +#define VIA8233_DXS_STOP_INDEX 0xff000000 +#define VIA8233_DXS_RATEFMT_48K 0x000fffff +#define VIA8233_DXS_RATEFMT_STEREO 0x00100000 +#define VIA8233_DXS_RATEFMT_16BIT 0x00200000 + +#define VIA_PCI_ACLINK_STAT 0x40 +# define VIA_PCI_ACLINK_C11_READY 0x20 +# define VIA_PCI_ACLINK_C10_READY 0x10 +# define VIA_PCI_ACLINK_C01_READY 0x04 +# define VIA_PCI_ACLINK_LOW_POWER 0x02 +# define VIA_PCI_ACLINK_C00_READY 0x01 + +#define VIA_PCI_ACLINK_CTRL 0x41 +# define VIA_PCI_ACLINK_EN 0x80 +# define VIA_PCI_ACLINK_NRST 0x40 +# define VIA_PCI_ACLINK_SYNC 0x20 +# 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_MC_SGD_STATUS 0x40 +#define VIA_WR0_SGD_STATUS 0x60 +#define VIA_WR1_SGD_STATUS 0x70 +# define SGD_STATUS_ACTIVE 0x80 +# define SGD_STATUS_AT_STOP 0x40 +# define SGD_STATUS_TRIGGER_Q 0x08 +# define SGD_STATUS_STOP_I_S 0x04 +# define SGD_STATUS_EOL 0x02 +# define SGD_STATUS_FLAG 0x01 +# define SGD_STATUS_INTR (SGD_STATUS_EOL | SGD_STATUS_FLAG) + +#define VIA_WR_BASE(n) (0x60 + (n) * 0x10) + +#define VIA_MC_SGD_CONTROL 0x41 +#define VIA_WR0_SGD_CONTROL 0x61 +#define VIA_WR1_SGD_CONTROL 0x71 +# define SGD_CONTROL_START 0x80 +# define SGD_CONTROL_STOP 0x40 +# define SGD_CONTROL_AUTOSTART 0x20 +# define SGD_CONTROL_PAUSE 0x08 +# define SGD_CONTROL_I_STOP 0x04 +# define SGD_CONTROL_I_EOL 0x02 +# define SGD_CONTROL_I_FLAG 0x01 + +#define VIA_MC_SGD_FORMAT 0x42 +# define MC_SGD_16BIT 0x80 +# define MC_SGD_8BIT 0x00 +# define MC_SGD_CHANNELS(x) (((x)& 0x07) << 4) + +#define VIA_WR0_SGD_FORMAT 0x62 +#define VIA_WR1_SGD_FORMAT 0x72 +#define VIA_WR_RP_SGD_FORMAT 0x02 +# define WR_FIFO_ENABLE 0x40 + +#define VIA_WR0_SGD_INPUT 0x63 +#define VIA_WR1_SGD_INPUT 0x73 +# define WR_LINE_IN 0x00 +# define WR_MIC_IN 0x04 +# define WR_PRIMARY_CODEC 0x00 +# define WR_SECONDARY_CODEC1 0x01 +# define WR_SECONDARY_CODEC2 0x02 +# define WR_SECONDARY_CODEC3 0x03 + +#define VIA_MC_TABLE_PTR_BASE 0x44 +#define VIA_WR0_TABLE_PTR_BASE 0x64 +#define VIA_WR1_TABLE_PTR_BASE 0x74 + +#define VIA_MC_SLOT_SELECT 0x48 +# define SLOT3(x) (x) +# define SLOT4(x) ((x) << 4) +# define SLOT7(x) ((x) << 8) +# define SLOT8(x) ((x) << 12) +# define SLOT6(x) ((x) << 16) +# define SLOT9(x) ((x) << 20) + +#define VIA_MC_CURRENT_COUNT 0x4c + +#define VIA_WR0_FORMAT 0x68 +#define VIA_WR1_FORMAT 0x78 +# define WR_FORMAT_STOP_INDEX 0xff000000 +# define WR_FORMAT_STEREO 0x00100000 +# define WR_FORMAT_16BIT 0x00200000 + +/* Relative offsets */ +#define VIA_RP_STATUS 0x00 +#define VIA_RP_CONTROL 0x01 +#define VIA_RP_TABLE_PTR 0x04 +#define VIA_RP_CURRENT_COUNT 0x0c + +#define VIA_AC97_CONTROL 0x80 +# define VIA_AC97_CODECID11 0xc0000000 +# define VIA_AC97_CODECID10 0x80000000 +# define VIA_AC97_CODECID01 0x40000000 +# define VIA_AC97_CODEC11_VALID 0x20000000 +# define VIA_AC97_CODEC10_VALID 0x10000000 +# define VIA_AC97_CODEC01_VALID 0x08000000 +# define VIA_AC97_CODEC00_VALID 0x02000000 +# define VIA_AC97_BUSY 0x01000000 +# define VIA_AC97_READ 0x00800000 +# define VIA_AC97_INDEX(x) ((x) << 16) +# define VIA_AC97_DATA(x) ((x) & 0xffff) + +#define VIA_CODEC_BUSY 0x01000000 +#define VIA_CODEC_PRIVALID 0x02000000 +#define VIA_CODEC_INDEX(x) ((x)<<16) + +#endif /* SYS_SOUND_PCI_VIA8233_H_ */ diff --git a/sys/dev/sound/pci/via82c686.c b/sys/dev/sound/pci/via82c686.c new file mode 100644 index 0000000..2e958ac --- /dev/null +++ b/sys/dev/sound/pci/via82c686.c @@ -0,0 +1,630 @@ +/* + * Copyright (c) 2000 David Jones <dej@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> + +#include <pci/pcireg.h> +#include <pci/pcivar.h> +#include <sys/sysctl.h> + +#include <dev/sound/pci/via82c686.h> + +SND_DECLARE_FILE("$FreeBSD$"); + +#define VIA_PCI_ID 0x30581106 +#define NSEGS 4 /* Number of segments in SGD table */ + +#define SEGS_PER_CHAN (NSEGS/2) + +#define TIMEOUT 50 +#define VIA_DEFAULT_BUFSZ 0x1000 + +#undef DEB +#define DEB(x) + +/* we rely on this struct being packed to 64 bits */ +struct via_dma_op { + u_int32_t ptr; + u_int32_t flags; +#define VIA_DMAOP_EOL 0x80000000 +#define VIA_DMAOP_FLAG 0x40000000 +#define VIA_DMAOP_STOP 0x20000000 +#define VIA_DMAOP_COUNT(x) ((x)&0x00FFFFFF) +}; + +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 { + 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; +}; + +static u_int32_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 u_int32_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; + } +} + + +static void +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; + } +} + +/* -------------------------------------------------------------------- */ +/* Codec interface */ + +static int +via_waitready_codec(struct via_info *via) +{ + 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 busy\n"); + return 1; + } + + return 0; +} + + +static int +via_waitvalid_codec(struct via_info *via) +{ + 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 invalid\n"); + return 1; + } + + return 0; +} + + +static int +via_write_codec(kobj_t obj, void *addr, int reg, u_int32_t val) +{ + struct via_info *via = addr; + + if (via_waitready_codec(via)) return -1; + + via_wr(via, VIA_CODEC_CTL, VIA_CODEC_PRIVALID | VIA_CODEC_INDEX(reg) | val, 4); + + return 0; +} + + +static int +via_read_codec(kobj_t obj, void *addr, int reg) +{ + struct via_info *via = addr; + + if (via_waitready_codec(via)) + return -1; + + 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_waitvalid_codec(via)) + return -1; + + 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 } +}; +AC97_DECLARE(via_ac97); + +/* -------------------------------------------------------------------- */ + +static int +via_buildsgdt(struct via_chinfo *ch) +{ + 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; + } + + 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; + + 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; + + if (sndbuf_alloc(ch->buffer, via->parent_dmat, via->bufsz) == -1) + return NULL; + 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=%x\n", ch->dir, format)); + mode = via_rd(via, ch->mode, 1); + mode &= ~(VIA_RPMODE_16BIT | VIA_RPMODE_STEREO); + mode |= mode_set; + via_wr(via, ch->mode, mode, 1); + + 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; +} + +static int +viachan_setblocksize(kobj_t obj, void *data, u_int32_t blocksize) +{ + struct via_chinfo *ch = data; + + ch->blksz = blocksize; + sndbuf_resize(ch->buffer, SEGS_PER_CHAN, 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=%x\n", ado, sgd_addr)); + + 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); + + 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; + 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); + + 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=%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; + + 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 } +}; +CHANNEL_DECLARE(viachan); + +/* -------------------------------------------------------------------- */ + +static void +via_intr(void *p) +{ + struct via_info *via = p; + int st; + + /* DEB(printf("viachan_intr\n")); */ + /* Read channel */ + st = via_rd(via, VIA_PLAY_STAT, 1); + if (st & VIA_RPSTAT_INTR) { + via_wr(via, VIA_PLAY_STAT, VIA_RPSTAT_INTR, 1); + chn_intr(via->pch.channel); + } + + /* Write channel */ + st = via_rd(via, VIA_RECORD_STAT, 1); + if (st & VIA_RPSTAT_INTR) { + via_wr(via, VIA_RECORD_STAT, VIA_RPSTAT_INTR, 1); + chn_intr(via->rch.channel); + } +} + +/* + * 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 0; + } + 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; +} + + +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 softc\n"); + return ENXIO; + } + + /* 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_MAPS; + via->reg = bus_alloc_resource(dev, SYS_RES_IOPORT, &via->regid, 0, ~0, 1, 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(dev, SYS_RES_IRQ, &via->irqid, 0, ~0, 1, RF_ACTIVE | RF_SHAREABLE); + if (!via->irq || snd_setup_intr(dev, via->irq, 0, 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*/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, &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*/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, &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; + + snprintf(status, SND_STATUSLEN, "at io 0x%lx irq %ld", rman_get_start(via->reg), rman_get_start(via->irq)); + + /* 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) 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; + + 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); + 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} +}; + +static driver_t via_driver = { + "pcm", + via_methods, + PCM_SOFTC_SIZE, +}; + +DRIVER_MODULE(snd_via82c686, pci, via_driver, pcm_devclass, 0, 0); +MODULE_DEPEND(snd_via82c686, snd_pcm, PCM_MINVER, PCM_PREFVER, PCM_MAXVER); +MODULE_VERSION(snd_via82c686, 1); diff --git a/sys/dev/sound/pci/via82c686.h b/sys/dev/sound/pci/via82c686.h new file mode 100644 index 0000000..ac6750e --- /dev/null +++ b/sys/dev/sound/pci/via82c686.h @@ -0,0 +1,93 @@ +/*- + * 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$ + */ + +#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) + */ + +#define VIA_AC97STATUS 0x40 +#define VIA_AC97STATUS_RDY 0x01 +#define VIA_AC97STATUS_LOWPWR 0x02 +#define VIA_AC97STATUS_2RDY 0x04 + +#define VIA_ACLINKCTRL 0x41 +#define VIA_ACLINK_EN 0x80 /* ac link enab */ +#define VIA_ACLINK_NRST 0x40 /* ~(ac reset) */ +#define VIA_ACLINK_SYNC 0x20 /* ac sync */ +#define VIA_ACLINK_VSR 0x08 /* var. samp. rate */ +#define VIA_ACLINK_SGD 0x04 /* SGD enab */ +#define VIA_ACLINK_FM 0x02 /* FM enab */ +#define VIA_ACLINK_SB 0x01 /* SB enab */ +#define VIA_ACLINK_DESIRED (VIA_ACLINK_EN|VIA_ACLINK_NRST|VIA_ACLINK_VSR|VIA_ACLINK_SGD) +#define VIA_PCICONF_FUNC_EN 0x42 + +#define VIA_PLAY_STAT 0x00 +#define VIA_RECORD_STAT 0x10 +#define VIA_RPSTAT_INTR 0x03 +#define VIA_PLAY_CONTROL 0x01 +#define VIA_RECORD_CONTROL 0x11 +#define VIA_RPCTRL_START 0x80 +#define VIA_RPCTRL_TERMINATE 0x40 +#define VIA_PLAY_MODE 0x02 +#define VIA_RECORD_MODE 0x12 +#define VIA_RPMODE_INTR_FLAG 0x01 +#define VIA_RPMODE_INTR_EOL 0x02 +#define VIA_RPMODE_STEREO 0x10 +#define VIA_RPMODE_16BIT 0x20 +#define VIA_RPMODE_AUTOSTART 0x80 +#define VIA_PLAY_DMAOPS_BASE 0x04 +#define VIA_RECORD_DMAOPS_BASE 0x14 +#define VIA_PLAY_DMAOPS_COUNT 0x0C +#define VIA_RECORD_DMAOPS_COUNT 0x1C + +#define VIA_CODEC_CTL 0x80 +#define VIA_CODEC_READ 0x00800000 +#define VIA_CODEC_BUSY 0x01000000 +#define VIA_CODEC_PRIVALID 0x02000000 +#define VIA_CODEC_INDEX(x) ((x)<<16) + +#endif /* _VIA_H */ diff --git a/sys/dev/sound/pci/vibes.c b/sys/dev/sound/pci/vibes.c new file mode 100644 index 0000000..7eb4955 --- /dev/null +++ b/sys/dev/sound/pci/vibes.c @@ -0,0 +1,945 @@ +/* + * Copyright (c) 2001 Orion Hodson <O.Hodson@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> + +#include <pci/pcireg.h> +#include <pci/pcivar.h> + +#include "mixer_if.h" + +SND_DECLARE_FILE("$FreeBSD$"); + +/* ------------------------------------------------------------------------- */ +/* Constants */ + +#define SV_PCI_ID 0xca005333 +#define SV_DEFAULT_BUFSZ 16384 +#define SV_MIN_BLKSZ 128 +#define SV_INTR_PER_BUFFER 2 + +#ifndef DEB +#define DEB(x) /* (x) */ +#endif + +/* ------------------------------------------------------------------------- */ +/* Structures */ + +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 { + device_t dev; + + /* 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; + + /* User configurable buffer size */ + unsigned int bufsz; + + 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 +}; + +static struct pcmchan_caps sc_caps = {8000, 48000, sc_fmt, 0}; + +/* ------------------------------------------------------------------------- */ +/* Register Manipulations */ + +#define sv_direct_set(x, y, z) _sv_direct_set(x, y, z, __LINE__) + +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); +} + +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); + + 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; + + 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__) + +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; + + 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 %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) +{ + 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%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; +} + +/* ------------------------------------------------------------------------- */ +/* Play / Record Common Interface */ + +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 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; +} + +static struct pcmchan_caps * +svchan_getcaps(kobj_t obj, void *data) +{ + 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; + + /* 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; +} + +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; +} + +/* ------------------------------------------------------------------------- */ +/* Recording interface */ + +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%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; + } + + 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; +} + +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 } +}; +CHANNEL_DECLARE(svrchan); + +/* ------------------------------------------------------------------------- */ +/* Playback interface */ + +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; + } + + 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); +} + +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 } +}; +CHANNEL_DECLARE(svpchan); + +/* ------------------------------------------------------------------------- */ +/* 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 */ +} 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}, +}; + +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; + + 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; +} + +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); + } +} + +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); + + for(i = v = 0; i < SOUND_MIXER_NRDEVICES; i++) { + if (mt[i].iselect) v |= (1 << i); + } + mix_setrecdevs(m, v); + + 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); +} + +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; + + 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)); + 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 } +}; +MIXER_DECLARE(sv_mixer); + +/* ------------------------------------------------------------------------- */ +/* Power management and reset */ + +static void +sv_power(struct sc_info *sc, int state) +{ + 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 %d\n", state)); +} + +static int +sv_init(struct sc_info *sc) +{ + 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); + + /* Get revision */ + sc->rev = sv_indirect_get(sc, SV_REG_REVISION); + + return 0; +} + +static int +sv_suspend(device_t 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->pch.dma_was_active = sc->pch.dma_active; + svrchan_trigger(NULL, &sc->pch, PCMTRIG_ABORT); + + sv_mix_mute_all(sc); + sv_power(sc, 3); + + 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 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); + } + + return 0; +} + +/* ------------------------------------------------------------------------- */ +/* Resource related */ + +static void +sv_intr(void *data) +{ + 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); + + 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)); + + return; +} + +static int +sv_probe(device_t dev) +{ + switch(pci_get_devid(dev)) { + case SV_PCI_ID: + device_set_desc(dev, "S3 Sonicvibes"); + return 0; + default: + return ENXIO; + } +} + +static int +sv_attach(device_t dev) { + struct snddev_info *d; + struct sc_info *sc; + u_int32_t data; + char status[SND_STATUSLEN]; + u_long midi_start, games_start, count, sdmaa, sdmac, ml, mu; + + d = device_get_softc(dev); + + 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); + +#if __FreeBSD_version > 500000 + 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 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 || + bus_setup_intr(dev, sc->irq, INTR_TYPE_AV, 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*/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, + &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", + rman_get_start(sc->enh_reg), rman_get_start(sc->irq)); + 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; + + 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); + + free(sc, M_DEVBUF); + + 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 } +}; + +static driver_t sonicvibes_driver = { + "pcm", + sc_methods, + PCM_SOFTC_SIZE +}; + +DRIVER_MODULE(snd_vibes, pci, sonicvibes_driver, pcm_devclass, 0, 0); +MODULE_DEPEND(snd_vibes, snd_pcm, PCM_MINVER, PCM_PREFVER, PCM_MAXVER); +MODULE_VERSION(snd_vibes, 1); diff --git a/sys/dev/sound/pci/vibes.h b/sys/dev/sound/pci/vibes.h new file mode 100644 index 0000000..36cbadd --- /dev/null +++ b/sys/dev/sound/pci/vibes.h @@ -0,0 +1,203 @@ +/* + * Copyright (c) 2001 Orion Hodson <O.Hodson@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$ + */ + +/* ------------------------------------------------------------------------- */ +/* PCI Configuration Register Offsets */ + +#define SV_PCI_COMPAT 0x10 +#define SV_PCI_ENHANCED 0x14 +#define SV_PCI_FMSYNTH 0x18 +#define SV_PCI_MIDI 0x1c +#define SV_PCI_GAMES 0x20 +#define SV_PCI_DMAA 0x40 +#define SV_PCI_DMAC 0x48 + +#define SV_PCI_DMAA_SIZE 0x10 +#define SV_PCI_DMAA_ALIGN 0x10 +#define SV_PCI_DMAC_SIZE 0x10 +#define SV_PCI_DMAC_ALIGN 0x10 + +#define SV_PCI_ENHANCED_SIZE 0x08 + +#define SV_PCI_DMA_ENABLE 0x00000001 +#define SV_PCI_DMA_EXTENDED 0x00000008 + +/* ------------------------------------------------------------------------- */ +/* DMA Configuration Registers */ + +#define SV_DMA_ADDR 0x00 +#define SV_DMA_COUNT 0x04 + +#define SV_DMA_MODE 0x0B +#define SV_DMA_MODE_AUTO 0x10 +#define SV_DMA_MODE_RD 0x04 +#define SV_DMA_MODE_WR 0x08 + +/* ------------------------------------------------------------------------- */ +/* Enhanced Mode Configuration Registers */ + +#define SV_CM_CONTROL 0x00 +#define SV_CM_CONTROL_ENHANCED 0x01 +#define SV_CM_CONTROL_TEST 0x02 +#define SV_CM_CONTROL_REVERB 0x04 +#define SV_CM_CONTROL_PWS 0x08 +#define SV_CM_CONTROL_INTA 0x20 +#define SV_CM_CONTROL_RESET 0x80 + +#define SV_CM_IMR 0x01 +#define SV_CM_IMR_AMSK 0x01 +#define SV_CM_IMR_CMSK 0x04 +#define SV_CM_IMR_SMSK 0x08 +#define SV_CM_IMR_UDM 0x40 +#define SV_CM_IMR_MIDM 0x80 + +#define SV_CM_STATUS 0x02 +#define SV_CM_STATUS_AINT 0x01 +#define SV_CM_STATUS_CINT 0x04 +#define SV_CM_STATUS_SINT 0x08 +#define SV_CM_STATUS_UDI 0x40 +#define SV_CM_STATUS_MI 0x80 + +#define SV_CM_INDEX 0x04 +#define SV_CM_INDEX_MASK 0x3f +#define SV_CM_INDEX_MCE 0x40 +#define SV_CM_INDEX_TRD 0x80 + +#define SV_CM_DATA 0x05 + +/* ------------------------------------------------------------------------- */ +/* Indexed Codec/Mixer Registers (left channels were applicable) */ + +#define SV_REG_ADC_INPUT 0x00 +#define SV_INPUT_GAIN_MASK 0x0f +#define SV_INPUT_MICGAIN 0x10 +#define SV_INPUT_CD 0x20 +#define SV_INPUT_DAC 0x40 +#define SV_INPUT_AUX2 0x60 +#define SV_INPUT_LINE 0x80 +#define SV_INPUT_AUX1 0xa0 +#define SV_INPUT_MIC 0xc0 +#define SV_INPUT_MIXOUT 0xe0 + +#define SV_REG_AUX1 0x02 +#define SV_REG_CD 0x04 +#define SV_REG_LINE 0x06 +#define SV_REG_MIC 0x08 +#define SV_REG_SYNTH 0x0a +#define SV_REG_AUX2 0x0c +#define SV_REG_MIX 0x0e +#define SV_REG_PCM 0x10 +#define SV_DEFAULT_MAX 0x1f +#define SV_ADC_MAX 0x0f +#define SV_MIC_MAX 0x0f +#define SV_PCM_MAX 0x3f +#define SV_MUTE 0x80 + +#define SV_REG_FORMAT 0x12 +#define SV_AFMT_MONO 0x00 +#define SV_AFMT_STEREO 0x01 +#define SV_AFMT_S16 0x02 +#define SV_AFMT_U8 0x00 +#define SV_AFMT_DMAA(x) (x) +#define SV_AFMT_DMAA_MSK 0x03 +#define SV_AFMT_DMAC(x) ((x) << 4) +#define SV_AFMT_DMAC_MSK 0x30 + +#define SV_REG_ENABLE 0x13 +#define SV_PLAY_ENABLE 0x01 +#define SV_RECORD_ENABLE 0x02 +#define SV_PLAYBACK_PAUSE 0x04 + +#define SV_REG_REVISION 0x15 + +#define SV_REG_LOOPBACK 0x16 +#define SV_LOOPBACK_ENABLE 0x01 +#define SV_LOOPBACK_MAX 0x3f +#define SV_LOOPBACK_LEVEL(x) ((x) << 2) + +#define SV_REG_DMAA_COUNT_HI 0x18 +#define SV_REG_DMAA_COUNT_LO 0x19 +#define SV_REG_DMAC_COUNT_HI 0x1c +#define SV_REG_DMAC_COUNT_LO 0x1d + +#define SV_REG_PCM_SAMPLING_LO 0x1e +#define SV_REG_PCM_SAMPLING_HI 0x1f + +#define SV_REG_SYN_SAMPLING_LO 0x20 +#define SV_REG_SYN_SAMPLING_HI 0x21 + +#define SV_REG_CLOCK_SOURCE 0x22 +#define SV_CLOCK_ALTERNATE 0x10 +#define SV_REG_ALT_RATE 0x23 + +#define SV_REG_ADC_PLLM 0x24 +#define SV_REG_ADC_PLLN 0x25 +#define SV_ADC_PLLN(x) ((x) & 0x1f) +#define SV_ADC_PLLR(x) ((x) << 5) + +#define SV_REG_SYNTH_PLLM 0x26 +#define SV_REG_SYNTH_PLLN 0x27 +#define SV_SYNTH_PLLN(x) ((x) & 0x1f) +#define SV_SYNTH_PLLR(x) ((x) << 5) + +#define SV_REG_SRS_SPACE 0x2c +#define SV_SRS_SPACE_100 0x00 +#define SV_SRS_SPACE_75 0x01 +#define SV_SRS_SPACE_50 0x02 +#define SV_SRS_SPACE_25 0x03 +#define SV_SRS_SPACE_0 0x04 +#define SV_SRS_DISABLED 0x80 + +#define SV_REG_SRS_CENTER 0x2d +#define SV_SRS_CENTER_100 0x00 +#define SV_SRS_CENTER_75 0x01 +#define SV_SRS_CENTER_50 0x02 +#define SV_SRS_CENTER_25 0x03 +#define SV_SRS_CENTER_0 0x04 + +#define SV_REG_ANALOG_PWR 0x30 +#define SV_ANALOG_OFF_DAC 0x01 +#define SV_ANALOG_OFF_ADC 0x08 +#define SV_ANALOG_OFF_MIX 0x10 +#define SV_ANALOG_OFF_SRS 0x20 +#define SV_ANALOG_OFF_SPLL 0x40 +#define SV_ANALOG_OFF_APLL 0x80 +#define SV_ANALOG_OFF 0xf9 + +#define SV_REG_DIGITAL_PWR 0x31 +#define SV_DIGITAL_OFF_SYN 0x01 +#define SV_DIGITAL_OFF_MU 0x02 +#define SV_DIGITAL_OFF_GP 0x04 +#define SV_DIGITAL_OFF_BI 0x08 +#define SV_DIGITAL_OFF 0x0f + +/* ------------------------------------------------------------------------- */ +/* ADC PLL constants */ + +#define SV_F_SCALE 512 +#define SV_F_REF 24576000 |