⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 es1370.c

📁 qemu虚拟机代码
💻 C
📖 第 1 页 / 共 2 页
字号:
        mask = 0xffff << shift;        val = (s->ctl & ~mask) | ((val & 0xffff) << shift);        es1370_update_voices (s, val, s->sctl);        print_ctl (val);        break;    case ES1370_REG_ADC_SCOUNT:        d++;    case ES1370_REG_DAC2_SCOUNT:        d++;    case ES1370_REG_DAC1_SCOUNT:        d->scount = (d->scount & ~0xffff) | (val & 0xffff);        break;    default:        lwarn ("writew %#x <- %#x\n", addr, val);        break;    }}IO_WRITE_PROTO (es1370_writel){    ES1370State *s = opaque;    struct chan *d = &s->chan[0];    addr = es1370_fixup (s, addr);    switch (addr) {    case ES1370_REG_CONTROL:        es1370_update_voices (s, val, s->sctl);        print_ctl (val);        break;    case ES1370_REG_MEMPAGE:        s->mempage = val & 0xf;        break;    case ES1370_REG_SERIAL_CONTROL:        es1370_maybe_lower_irq (s, val);        es1370_update_voices (s, s->ctl, val);        print_sctl (val);        break;    case ES1370_REG_ADC_SCOUNT:        d++;    case ES1370_REG_DAC2_SCOUNT:        d++;    case ES1370_REG_DAC1_SCOUNT:        d->scount = (val & 0xffff) | (d->scount & ~0xffff);        ldebug ("chan %d CURR_SAMP_CT %d, SAMP_CT %d\n",                d - &s->chan[0], val >> 16, (val & 0xffff));        break;    case ES1370_REG_ADC_FRAMEADR:        d++;    case ES1370_REG_DAC2_FRAMEADR:        d++;    case ES1370_REG_DAC1_FRAMEADR:        d->frame_addr = val;        ldebug ("chan %d frame address %#x\n", d - &s->chan[0], val);        break;    case ES1370_REG_PHANTOM_FRAMECNT:        lwarn ("writing to phantom frame count %#x\n", val);        break;    case ES1370_REG_PHANTOM_FRAMEADR:        lwarn ("writing to phantom frame address %#x\n", val);        break;    case ES1370_REG_ADC_FRAMECNT:        d++;    case ES1370_REG_DAC2_FRAMECNT:        d++;    case ES1370_REG_DAC1_FRAMECNT:        d->frame_cnt = val;        d->leftover = 0;        ldebug ("chan %d frame count %d, buffer size %d\n",                d - &s->chan[0], val >> 16, val & 0xffff);        break;    default:        lwarn ("writel %#x <- %#x\n", addr, val);        break;    }}IO_READ_PROTO (es1370_readb){    ES1370State *s = opaque;    uint32_t val;    addr = es1370_fixup (s, addr);    switch (addr) {    case 0x1b:                  /* Legacy */        lwarn ("Attempt to read from legacy register\n");        val = 5;        break;    case ES1370_REG_MEMPAGE:        val = s->mempage;        break;    case ES1370_REG_CONTROL + 0:    case ES1370_REG_CONTROL + 1:    case ES1370_REG_CONTROL + 2:    case ES1370_REG_CONTROL + 3:        val = s->ctl >> ((addr - ES1370_REG_CONTROL) << 3);        break;    case ES1370_REG_STATUS + 0:    case ES1370_REG_STATUS + 1:    case ES1370_REG_STATUS + 2:    case ES1370_REG_STATUS + 3:        val = s->status >> ((addr - ES1370_REG_STATUS) << 3);        break;    default:        val = ~0;        lwarn ("readb %#x -> %#x\n", addr, val);        break;    }    return val;}IO_READ_PROTO (es1370_readw){    ES1370State *s = opaque;    struct chan *d = &s->chan[0];    uint32_t val;    addr = es1370_fixup (s, addr);    switch (addr) {    case ES1370_REG_ADC_SCOUNT + 2:        d++;    case ES1370_REG_DAC2_SCOUNT + 2:        d++;    case ES1370_REG_DAC1_SCOUNT + 2:        val = d->scount >> 16;        break;    case ES1370_REG_ADC_FRAMECNT:        d++;    case ES1370_REG_DAC2_FRAMECNT:        d++;    case ES1370_REG_DAC1_FRAMECNT:        val = d->frame_cnt & 0xffff;        break;    case ES1370_REG_ADC_FRAMECNT + 2:        d++;    case ES1370_REG_DAC2_FRAMECNT + 2:        d++;    case ES1370_REG_DAC1_FRAMECNT + 2:        val = d->frame_cnt >> 16;        break;    default:        val = ~0;        lwarn ("readw %#x -> %#x\n", addr, val);        break;    }    return val;}IO_READ_PROTO (es1370_readl){    ES1370State *s = opaque;    uint32_t val;    struct chan *d = &s->chan[0];    addr = es1370_fixup (s, addr);    switch (addr) {    case ES1370_REG_CONTROL:        val = s->ctl;        break;    case ES1370_REG_STATUS:        val = s->status;        break;    case ES1370_REG_MEMPAGE:        val = s->mempage;        break;    case ES1370_REG_CODEC:        val = s->codec;        break;    case ES1370_REG_SERIAL_CONTROL:        val = s->sctl;        break;    case ES1370_REG_ADC_SCOUNT:        d++;    case ES1370_REG_DAC2_SCOUNT:        d++;    case ES1370_REG_DAC1_SCOUNT:        val = d->scount;#ifdef DEBUG_ES1370        {            uint32_t curr_count = d->scount >> 16;            uint32_t count = d->scount & 0xffff;            curr_count <<= d->shift;            count <<= d->shift;            dolog ("read scount curr %d, total %d\n", curr_count, count);        }#endif        break;    case ES1370_REG_ADC_FRAMECNT:        d++;    case ES1370_REG_DAC2_FRAMECNT:        d++;    case ES1370_REG_DAC1_FRAMECNT:        val = d->frame_cnt;#ifdef DEBUG_ES1370        {            uint32_t size = ((d->frame_cnt & 0xffff) + 1) << 2;            uint32_t curr = ((d->frame_cnt >> 16) + 1) << 2;            if (curr > size)                dolog ("read framecnt curr %d, size %d %d\n", curr, size,                       curr > size);        }#endif        break;    case ES1370_REG_ADC_FRAMEADR:        d++;    case ES1370_REG_DAC2_FRAMEADR:        d++;    case ES1370_REG_DAC1_FRAMEADR:        val = d->frame_addr;        break;    case ES1370_REG_PHANTOM_FRAMECNT:        val = ~0U;        lwarn ("reading from phantom frame count\n");        break;    case ES1370_REG_PHANTOM_FRAMEADR:        val = ~0U;        lwarn ("reading from phantom frame address\n");        break;    default:        val = ~0U;        lwarn ("readl %#x -> %#x\n", addr, val);        break;    }    return val;}static void es1370_transfer_audio (ES1370State *s, struct chan *d, int loop_sel,                                   int max, int *irq){    uint8_t tmpbuf[4096];    uint32_t addr = d->frame_addr;    int sc = d->scount & 0xffff;    int csc = d->scount >> 16;    int csc_bytes = (csc + 1) << d->shift;    int cnt = d->frame_cnt >> 16;    int size = d->frame_cnt & 0xffff;    int left = ((size - cnt + 1) << 2) + d->leftover;    int transfered = 0;    int temp = audio_MIN (max, audio_MIN (left, csc_bytes));    int index = d - &s->chan[0];    addr += (cnt << 2) + d->leftover;    if (index == ADC_CHANNEL) {        while (temp) {            int acquired, to_copy;            to_copy = audio_MIN ((size_t) temp, sizeof (tmpbuf));            acquired = AUD_read (s->adc_voice, tmpbuf, to_copy);            if (!acquired)                break;            cpu_physical_memory_write (addr, tmpbuf, acquired);            temp -= acquired;            addr += acquired;            transfered += acquired;        }    }    else {        SWVoiceOut *voice = s->dac_voice[index];        while (temp) {            int copied, to_copy;            to_copy = audio_MIN ((size_t) temp, sizeof (tmpbuf));            cpu_physical_memory_read (addr, tmpbuf, to_copy);            copied = AUD_write (voice, tmpbuf, to_copy);            if (!copied)                break;            temp -= copied;            addr += copied;            transfered += copied;        }    }    if (csc_bytes == transfered) {        *irq = 1;        d->scount = sc | (sc << 16);        ldebug ("sc = %d, rate = %f\n",                (sc + 1) << d->shift,                (sc + 1) / (double) 44100);    }    else {        *irq = 0;        d->scount = sc | (((csc_bytes - transfered - 1) >> d->shift) << 16);    }    cnt += (transfered + d->leftover) >> 2;    if (s->sctl & loop_sel) {        /* Bah, how stupid is that having a 0 represent true value?           i just spent few hours on this shit */        AUD_log ("es1370: warning", "non looping mode\n");    }    else {        d->frame_cnt = size;        if ((uint32_t) cnt <= d->frame_cnt)            d->frame_cnt |= cnt << 16;    }    d->leftover = (transfered + d->leftover) & 3;}static void es1370_run_channel (ES1370State *s, size_t chan, int free_or_avail){    uint32_t new_status = s->status;    int max_bytes, irq;    struct chan *d = &s->chan[chan];    const struct chan_bits *b = &es1370_chan_bits[chan];    if (!(s->ctl & b->ctl_en) || (s->sctl & b->sctl_pause)) {        return;    }    max_bytes = free_or_avail;    max_bytes &= ~((1 << d->shift) - 1);    if (!max_bytes) {        return;    }    es1370_transfer_audio (s, d, b->sctl_loopsel, max_bytes, &irq);    if (irq) {        if (s->sctl & b->sctl_inten) {            new_status |= b->stat_int;        }    }    if (new_status != s->status) {        es1370_update_status (s, new_status);    }}static void es1370_dac1_callback (void *opaque, int free){    ES1370State *s = opaque;    es1370_run_channel (s, DAC1_CHANNEL, free);}static void es1370_dac2_callback (void *opaque, int free){    ES1370State *s = opaque;    es1370_run_channel (s, DAC2_CHANNEL, free);}static void es1370_adc_callback (void *opaque, int avail){    ES1370State *s = opaque;    es1370_run_channel (s, ADC_CHANNEL, avail);}static void es1370_map (PCIDevice *pci_dev, int region_num,                        uint32_t addr, uint32_t size, int type){    PCIES1370State *d = (PCIES1370State *) pci_dev;    ES1370State *s = &d->es1370;    (void) region_num;    (void) size;    (void) type;    register_ioport_write (addr, 0x40 * 4, 1, es1370_writeb, s);    register_ioport_write (addr, 0x40 * 2, 2, es1370_writew, s);    register_ioport_write (addr, 0x40, 4, es1370_writel, s);    register_ioport_read (addr, 0x40 * 4, 1, es1370_readb, s);    register_ioport_read (addr, 0x40 * 2, 2, es1370_readw, s);    register_ioport_read (addr, 0x40, 4, es1370_readl, s);}static void es1370_save (QEMUFile *f, void *opaque){    ES1370State *s = opaque;    size_t i;    for (i = 0; i < NB_CHANNELS; ++i) {        struct chan *d = &s->chan[i];        qemu_put_be32s (f, &d->shift);        qemu_put_be32s (f, &d->leftover);        qemu_put_be32s (f, &d->scount);        qemu_put_be32s (f, &d->frame_addr);        qemu_put_be32s (f, &d->frame_cnt);    }    qemu_put_be32s (f, &s->ctl);    qemu_put_be32s (f, &s->status);    qemu_put_be32s (f, &s->mempage);    qemu_put_be32s (f, &s->codec);    qemu_put_be32s (f, &s->sctl);}static int es1370_load (QEMUFile *f, void *opaque, int version_id){    uint32_t ctl, sctl;    ES1370State *s = opaque;    size_t i;    if (version_id != 1)        return -EINVAL;    for (i = 0; i < NB_CHANNELS; ++i) {        struct chan *d = &s->chan[i];        qemu_get_be32s (f, &d->shift);        qemu_get_be32s (f, &d->leftover);        qemu_get_be32s (f, &d->scount);        qemu_get_be32s (f, &d->frame_addr);        qemu_get_be32s (f, &d->frame_cnt);        if (i == ADC_CHANNEL) {            if (s->adc_voice) {                AUD_close_in (&s->card, s->adc_voice);                s->adc_voice = NULL;            }        }        else {            if (s->dac_voice[i]) {                AUD_close_out (&s->card, s->dac_voice[i]);                s->dac_voice[i] = NULL;            }        }    }    qemu_get_be32s (f, &ctl);    qemu_get_be32s (f, &s->status);    qemu_get_be32s (f, &s->mempage);    qemu_get_be32s (f, &s->codec);    qemu_get_be32s (f, &sctl);    s->ctl = 0;    s->sctl = 0;    es1370_update_voices (s, ctl, sctl);    return 0;}static void es1370_on_reset (void *opaque){    ES1370State *s = opaque;    es1370_reset (s);}int es1370_init (PCIBus *bus, AudioState *audio){    PCIES1370State *d;    ES1370State *s;    uint8_t *c;    if (!bus) {        dolog ("No PCI bus\n");        return -1;    }    if (!audio) {        dolog ("No audio state\n");        return -1;    }    d = (PCIES1370State *) pci_register_device (bus, "ES1370",                                                sizeof (PCIES1370State),                                                -1, NULL, NULL);    if (!d) {        AUD_log (NULL, "Failed to register PCI device for ES1370\n");        return -1;    }    c = d->dev.config;    c[0x00] = 0x74;    c[0x01] = 0x12;    c[0x02] = 0x00;    c[0x03] = 0x50;    c[0x07] = 2 << 1;    c[0x0a] = 0x01;    c[0x0b] = 0x04;#if 1    c[0x2c] = 0x42;    c[0x2d] = 0x49;    c[0x2e] = 0x4c;    c[0x2f] = 0x4c;#else    c[0x2c] = 0x74;    c[0x2d] = 0x12;    c[0x2e] = 0x71;    c[0x2f] = 0x13;    c[0x34] = 0xdc;    c[0x3c] = 10;    c[0xdc] = 0x00;#endif    c[0x3d] = 1;    c[0x3e] = 0x0c;    c[0x3f] = 0x80;    s = &d->es1370;    s->pci_dev = &d->dev;    pci_register_io_region (&d->dev, 0, 256, PCI_ADDRESS_SPACE_IO, es1370_map);    register_savevm ("es1370", 0, 1, es1370_save, es1370_load, s);    qemu_register_reset (es1370_on_reset, s);    AUD_register_card (audio, "es1370", &s->card);    es1370_reset (s);    return 0;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -