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

📄 ac97.c

📁 xen虚拟机源代码安装包
💻 C
📖 第 1 页 / 共 3 页
字号:
    switch (index) {    case PI_SR:    case PO_SR:    case MC_SR:        r = &s->bm_regs[GET_BM (index)];        r->sr |= val & ~(SR_RO_MASK | SR_WCLEAR_MASK);        update_sr (s, r, r->sr & ~(val & SR_WCLEAR_MASK));        dolog ("SR[%d] <- %#x (sr %#x)\n", GET_BM (index), val, r->sr);        break;    default:        dolog ("U nabm writew %#x <- %#x\n", addr, val);        break;    }}static void nabm_writel (void *opaque, uint32_t addr, uint32_t val){    PCIAC97LinkState *d = opaque;    AC97LinkState *s = &d->ac97;    AC97BusMasterRegs *r = NULL;    uint32_t index = addr - s->base[1];    switch (index) {    case PI_BDBAR:    case PO_BDBAR:    case MC_BDBAR:        r = &s->bm_regs[GET_BM (index)];        r->bdbar = val & ~3;        dolog ("BDBAR[%d] <- %#x (bdbar %#x)\n",               GET_BM (index), val, r->bdbar);        break;    case GLOB_CNT:        if (val & GC_WR)            warm_reset (s);        if (val & GC_CR)            cold_reset (s);        if (!(val & (GC_WR | GC_CR)))            s->glob_cnt = val & GC_VALID_MASK;        dolog ("glob_cnt <- %#x (glob_cnt %#x)\n", val, s->glob_cnt);        break;    case GLOB_STA:        s->glob_sta &= ~(val & GS_WCLEAR_MASK);        s->glob_sta |= (val & ~(GS_WCLEAR_MASK | GS_RO_MASK)) & GS_VALID_MASK;        dolog ("glob_sta <- %#x (glob_sta %#x)\n", val, s->glob_sta);        break;    default:        dolog ("U nabm writel %#x <- %#x\n", addr, val);        break;    }}static int write_audio (AC97LinkState *s, AC97BusMasterRegs *r,                        int max, int *stop){    uint8_t tmpbuf[4096];    uint32_t addr = r->bd.addr;    uint32_t temp = r->picb << 1;    uint32_t written = 0;    int to_copy = 0;    temp = audio_MIN (temp, max);    if (!temp) {        *stop = 1;        return 0;    }    while (temp) {        int copied;        to_copy = audio_MIN (temp, sizeof (tmpbuf));        cpu_physical_memory_read (addr, tmpbuf, to_copy);        copied = AUD_write (s->voice_po, tmpbuf, to_copy);        dolog ("write_audio max=%x to_copy=%x copied=%x\n",               max, to_copy, copied);        if (!copied) {            *stop = 1;            break;        }        temp -= copied;        addr += copied;        written += copied;    }    if (!temp) {        if (to_copy < 4) {            dolog ("whoops\n");            s->last_samp = 0;        }        else {            s->last_samp = *(uint32_t *) &tmpbuf[to_copy - 4];        }    }    r->bd.addr = addr;    return written;}static void write_bup (AC97LinkState *s, int elapsed){    int written = 0;    dolog ("write_bup\n");    if (!(s->bup_flag & BUP_SET)) {        if (s->bup_flag & BUP_LAST) {            int i;            uint8_t *p = s->silence;            for (i = 0; i < sizeof (s->silence) / 4; i++, p += 4) {                *(uint32_t *) p = s->last_samp;            }        }        else {            memset (s->silence, 0, sizeof (s->silence));        }        s->bup_flag |= BUP_SET;    }    while (elapsed) {        int temp = audio_MIN (elapsed, sizeof (s->silence));        while (temp) {            int copied = AUD_write (s->voice_po, s->silence, temp);            if (!copied)                return;            temp -= copied;            elapsed -= copied;            written += copied;        }    }}static int read_audio (AC97LinkState *s, AC97BusMasterRegs *r,                       int max, int *stop){    uint8_t tmpbuf[4096];    uint32_t addr = r->bd.addr;    uint32_t temp = r->picb << 1;    uint32_t nread = 0;    int to_copy = 0;    SWVoiceIn *voice = (r - s->bm_regs) == MC_INDEX ? s->voice_mc : s->voice_pi;    temp = audio_MIN (temp, max);    if (!temp) {        *stop = 1;        return 0;    }    while (temp) {        int acquired;        to_copy = audio_MIN (temp, sizeof (tmpbuf));        acquired = AUD_read (voice, tmpbuf, to_copy);        if (!acquired) {            *stop = 1;            break;        }        cpu_physical_memory_write (addr, tmpbuf, acquired);        temp -= acquired;        addr += acquired;        nread += acquired;    }    r->bd.addr = addr;    return nread;}static void transfer_audio (AC97LinkState *s, int index, int elapsed){    AC97BusMasterRegs *r = &s->bm_regs[index];    int written = 0, stop = 0;    if (r->sr & SR_DCH) {        if (r->cr & CR_RPBM) {            switch (index) {            case PO_INDEX:                write_bup (s, elapsed);                break;            }        }        return;    }    while ((elapsed >> 1) && !stop) {        int temp;        if (!r->bd_valid) {            dolog ("invalid bd\n");            fetch_bd (s, r);        }        if (!r->picb) {            dolog ("fresh bd %d is empty %#x %#x\n",                   r->civ, r->bd.addr, r->bd.ctl_len);            if (r->civ == r->lvi) {                r->sr |= SR_DCH; /* CELV? */                s->bup_flag = 0;                break;            }            r->sr &= ~SR_CELV;            r->civ = r->piv;            r->piv = (r->piv + 1) % 32;            fetch_bd (s, r);            return;        }        switch (index) {        case PO_INDEX:            temp = write_audio (s, r, elapsed, &stop);            written += temp;            elapsed -= temp;            r->picb -= (temp >> 1);            break;        case PI_INDEX:        case MC_INDEX:            temp = read_audio (s, r, elapsed, &stop);            elapsed -= temp;            r->picb -= (temp >> 1);            break;        }        if (!r->picb) {            uint32_t new_sr = r->sr & ~SR_CELV;            if (r->bd.ctl_len & BD_IOC) {                new_sr |= SR_BCIS;            }            if (r->civ == r->lvi) {                dolog ("Underrun civ (%d) == lvi (%d)\n", r->civ, r->lvi);                new_sr |= SR_LVBCI | SR_DCH | SR_CELV;                stop = 1;                s->bup_flag = (r->bd.ctl_len & BD_BUP) ? BUP_LAST : 0;            }            else {                r->civ = r->piv;                r->piv = (r->piv + 1) % 32;                fetch_bd (s, r);            }            update_sr (s, r, new_sr);        }    }}static void pi_callback (void *opaque, int avail){    transfer_audio (opaque, PI_INDEX, avail);}static void mc_callback (void *opaque, int avail){    transfer_audio (opaque, MC_INDEX, avail);}static void po_callback (void *opaque, int free){    transfer_audio (opaque, PO_INDEX, free);}static void ac97_save (QEMUFile *f, void *opaque){    size_t i;    uint8_t active[LAST_INDEX];    AC97LinkState *s = opaque;    qemu_put_be32s (f, &s->glob_cnt);    qemu_put_be32s (f, &s->glob_sta);    qemu_put_be32s (f, &s->cas);    for (i = 0; i < sizeof (s->bm_regs) / sizeof (s->bm_regs[0]); ++i) {        AC97BusMasterRegs *r = &s->bm_regs[i];        qemu_put_be32s (f, &r->bdbar);        qemu_put_8s (f, &r->civ);        qemu_put_8s (f, &r->lvi);        qemu_put_be16s (f, &r->sr);        qemu_put_be16s (f, &r->picb);        qemu_put_8s (f, &r->piv);        qemu_put_8s (f, &r->cr);        qemu_put_be32s (f, &r->bd_valid);        qemu_put_be32s (f, &r->bd.addr);        qemu_put_be32s (f, &r->bd.ctl_len);    }    qemu_put_buffer (f, s->mixer_data, sizeof (s->mixer_data));    active[PI_INDEX] = AUD_is_active_in (s->voice_pi) ? 1 : 0;    active[PO_INDEX] = AUD_is_active_out (s->voice_po) ? 1 : 0;    active[MC_INDEX] = AUD_is_active_in (s->voice_mc) ? 1 : 0;    qemu_put_buffer (f, active, sizeof (active));}static int ac97_load (QEMUFile *f, void *opaque, int version_id){    size_t i;    uint8_t active[LAST_INDEX];    AC97LinkState *s = opaque;    if (version_id != 1)        return -EINVAL;    qemu_get_be32s (f, &s->glob_cnt);    qemu_get_be32s (f, &s->glob_sta);    qemu_get_be32s (f, &s->cas);    for (i = 0; i < sizeof (s->bm_regs) / sizeof (s->bm_regs[0]); ++i) {        AC97BusMasterRegs *r = &s->bm_regs[i];        qemu_get_be32s (f, &r->bdbar);        qemu_get_8s (f, &r->civ);        qemu_get_8s (f, &r->lvi);        qemu_get_be16s (f, &r->sr);        qemu_get_be16s (f, &r->picb);        qemu_get_8s (f, &r->piv);        qemu_get_8s (f, &r->cr);        qemu_get_be32s (f, &r->bd_valid);        qemu_get_be32s (f, &r->bd.addr);        qemu_get_be32s (f, &r->bd.ctl_len);    }    qemu_get_buffer (f, s->mixer_data, sizeof (s->mixer_data));    qemu_get_buffer (f, active, sizeof (active));#ifdef USE_MIXER    record_select (s, mixer_load (s, AC97_Record_Select));#define V_(a, b) set_volume (s, a, b, mixer_load (s, a))    V_ (AC97_Master_Volume_Mute, AUD_MIXER_VOLUME);    V_ (AC97_PCM_Out_Volume_Mute, AUD_MIXER_PCM);    V_ (AC97_Line_In_Volume_Mute, AUD_MIXER_LINE_IN);#undef V_#endif    reset_voices (s, active);    s->bup_flag = 0;    s->last_samp = 0;    return 0;}static void ac97_map (PCIDevice *pci_dev, int region_num,                      uint32_t addr, uint32_t size, int type){    PCIAC97LinkState *d = (PCIAC97LinkState *) pci_dev;    AC97LinkState *s = &d->ac97;    if (!region_num) {        s->base[0] = addr;        register_ioport_read (addr, 256 * 1, 1, nam_readb, d);        register_ioport_read (addr, 256 * 2, 2, nam_readw, d);        register_ioport_read (addr, 256 * 4, 4, nam_readl, d);        register_ioport_write (addr, 256 * 1, 1, nam_writeb, d);        register_ioport_write (addr, 256 * 2, 2, nam_writew, d);        register_ioport_write (addr, 256 * 4, 4, nam_writel, d);    }    else {        s->base[1] = addr;        register_ioport_read (addr, 64 * 1, 1, nabm_readb, d);        register_ioport_read (addr, 64 * 2, 2, nabm_readw, d);        register_ioport_read (addr, 64 * 4, 4, nabm_readl, d);        register_ioport_write (addr, 64 * 1, 1, nabm_writeb, d);        register_ioport_write (addr, 64 * 2, 2, nabm_writew, d);        register_ioport_write (addr, 64 * 4, 4, nabm_writel, d);    }}static void ac97_on_reset (void *opaque){    AC97LinkState *s = opaque;    reset_bm_regs (s, &s->bm_regs[0]);    reset_bm_regs (s, &s->bm_regs[1]);    reset_bm_regs (s, &s->bm_regs[2]);    /*     * Reset the mixer too. The Windows XP driver seems to rely on     * this. At least it wants to read the vendor id before it resets     * the codec manually.     */    mixer_reset (s);}int ac97_init (PCIBus *bus, AudioState *audio){    PCIAC97LinkState *d;    AC97LinkState *s;    uint8_t *c;    if (!bus) {        AUD_log ("ac97", "No PCI bus\n");        return -1;    }    if (!audio) {        AUD_log ("ac97", "No audio state\n");        return -1;    }    d = (PCIAC97LinkState *) pci_register_device (bus, "AC97",                                                  sizeof (PCIAC97LinkState),                                                  -1, NULL, NULL);    if (!d) {        AUD_log ("ac97", "Failed to register PCI device\n");        return -1;    }    s = &d->ac97;    s->pci_dev = &d->dev;    c = d->dev.config;    c[0x00] = 0x86;      /* vid vendor id intel ro */    c[0x01] = 0x80;      /* intel */    c[0x02] = 0x15;      /* did device id 82801 ro */    c[0x03] = 0x24;      /* 82801aa */    c[0x04] = 0x00;      /* pcicmd pci command rw, ro */    c[0x05] = 0x00;    c[0x06] = 0x80;      /* pcists pci status rwc, ro */    c[0x07] = 0x02;    c[0x08] = 0x01;      /* rid revision ro */    c[0x09] = 0x00;      /* pi programming interface ro */    c[0x0a] = 0x01;      /* scc sub class code ro */    c[0x0b] = 0x04;      /* bcc base class code ro */    c[0x0e] = 0x00;      /* headtyp header type ro */    c[0x10] = 0x01;      /* nabmar native audio mixer base                            address rw */    c[0x11] = 0x00;    c[0x12] = 0x00;    c[0x13] = 0x00;    c[0x14] = 0x01;      /* nabmbar native audio bus mastering                            base address rw */    c[0x15] = 0x00;    c[0x16] = 0x00;    c[0x17] = 0x00;    c[0x2c] = 0x86;      /* svid subsystem vendor id rwo */    c[0x2d] = 0x80;    c[0x2e] = 0x00;      /* sid subsystem id rwo */    c[0x2f] = 0x00;    c[0x3c] = 0x00;      /* intr_ln interrupt line rw */    c[0x3d] = 0x01;      /* intr_pn interrupt pin ro */    pci_register_io_region (&d->dev, 0, 256 * 4, PCI_ADDRESS_SPACE_IO, ac97_map);    pci_register_io_region (&d->dev, 1, 64 * 4, PCI_ADDRESS_SPACE_IO, ac97_map);    register_savevm ("ac97", 0, 1, ac97_save, ac97_load, s);    qemu_register_reset (ac97_on_reset, s);    AUD_register_card (audio, "ac97", &s->card);    ac97_on_reset (s);    return 0;}

⌨️ 快捷键说明

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