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

📄 sb16.c

📁 qemu虚拟机代码
💻 C
📖 第 1 页 / 共 3 页
字号:
            retval = s->out_data[--s->out_data_len];            s->last_read_byte = retval;        }        else {            if (s->cmd != -1) {                dolog ("empty output buffer for command %#x\n",                       s->cmd);            }            retval = s->last_read_byte;            /* goto error; */        }        break;    case 0x0c:                  /* 0 can write */        retval = s->can_write ? 0 : 0x80;        break;    case 0x0d:                  /* timer interrupt clear */        /* dolog ("timer interrupt clear\n"); */        retval = 0;        break;    case 0x0e:                  /* data available status | irq 8 ack */        retval = (!s->out_data_len || s->highspeed) ? 0 : 0x80;        if (s->mixer_regs[0x82] & 1) {            ack = 1;            s->mixer_regs[0x82] &= 1;            pic_set_irq (s->irq, 0);        }        break;    case 0x0f:                  /* irq 16 ack */        retval = 0xff;        if (s->mixer_regs[0x82] & 2) {            ack = 1;            s->mixer_regs[0x82] &= 2;            pic_set_irq (s->irq, 0);        }        break;    default:        goto error;    }    if (!ack) {        ldebug ("read %#x -> %#x\n", nport, retval);    }    return retval; error:    dolog ("warning: dsp_read %#x error\n", nport);    return 0xff;}static void reset_mixer (SB16State *s){    int i;    memset (s->mixer_regs, 0xff, 0x7f);    memset (s->mixer_regs + 0x83, 0xff, sizeof (s->mixer_regs) - 0x83);    s->mixer_regs[0x02] = 4;    /* master volume 3bits */    s->mixer_regs[0x06] = 4;    /* MIDI volume 3bits */    s->mixer_regs[0x08] = 0;    /* CD volume 3bits */    s->mixer_regs[0x0a] = 0;    /* voice volume 2bits */    /* d5=input filt, d3=lowpass filt, d1,d2=input source */    s->mixer_regs[0x0c] = 0;    /* d5=output filt, d1=stereo switch */    s->mixer_regs[0x0e] = 0;    /* voice volume L d5,d7, R d1,d3 */    s->mixer_regs[0x04] = (4 << 5) | (4 << 1);    /* master ... */    s->mixer_regs[0x22] = (4 << 5) | (4 << 1);    /* MIDI ... */    s->mixer_regs[0x26] = (4 << 5) | (4 << 1);    for (i = 0x30; i < 0x48; i++) {        s->mixer_regs[i] = 0x20;    }}static IO_WRITE_PROTO(mixer_write_indexb){    SB16State *s = opaque;    (void) nport;    s->mixer_nreg = val;}static IO_WRITE_PROTO(mixer_write_datab){    SB16State *s = opaque;    (void) nport;    ldebug ("mixer_write [%#x] <- %#x\n", s->mixer_nreg, val);    switch (s->mixer_nreg) {    case 0x00:        reset_mixer (s);        break;    case 0x80:        {            int irq = irq_of_magic (val);            ldebug ("setting irq to %d (val=%#x)\n", irq, val);            if (irq > 0) {                s->irq = irq;            }        }        break;    case 0x81:        {            int dma, hdma;            dma = lsbindex (val & 0xf);            hdma = lsbindex (val & 0xf0);            if (dma != s->dma || hdma != s->hdma) {                dolog (                    "attempt to change DMA "                    "8bit %d(%d), 16bit %d(%d) (val=%#x)\n",                    dma, s->dma, hdma, s->hdma, val);            }#if 0            s->dma = dma;            s->hdma = hdma;#endif        }        break;    case 0x82:        dolog ("attempt to write into IRQ status register (val=%#x)\n",               val);        return;    default:        if (s->mixer_nreg >= 0x80) {            ldebug ("attempt to write mixer[%#x] <- %#x\n", s->mixer_nreg, val);        }        break;    }    s->mixer_regs[s->mixer_nreg] = val;}static IO_WRITE_PROTO(mixer_write_indexw){    mixer_write_indexb (opaque, nport, val & 0xff);    mixer_write_datab (opaque, nport, (val >> 8) & 0xff);}static IO_READ_PROTO(mixer_read){    SB16State *s = opaque;    (void) nport;#ifndef DEBUG_SB16_MOST    if (s->mixer_nreg != 0x82) {        ldebug ("mixer_read[%#x] -> %#x\n",                s->mixer_nreg, s->mixer_regs[s->mixer_nreg]);    }#else    ldebug ("mixer_read[%#x] -> %#x\n",            s->mixer_nreg, s->mixer_regs[s->mixer_nreg]);#endif    return s->mixer_regs[s->mixer_nreg];}static int write_audio (SB16State *s, int nchan, int dma_pos,                        int dma_len, int len){    int temp, net;    uint8_t tmpbuf[4096];    temp = len;    net = 0;    while (temp) {        int left = dma_len - dma_pos;        int copied;        size_t to_copy;        to_copy = audio_MIN (temp, left);        if (to_copy > sizeof (tmpbuf)) {            to_copy = sizeof (tmpbuf);        }        copied = DMA_read_memory (nchan, tmpbuf, dma_pos, to_copy);        copied = AUD_write (s->voice, tmpbuf, copied);        temp -= copied;        dma_pos = (dma_pos + copied) % dma_len;        net += copied;        if (!copied) {            break;        }    }    return net;}static int SB_read_DMA (void *opaque, int nchan, int dma_pos, int dma_len){    SB16State *s = opaque;    int till, copy, written, free;    if (s->left_till_irq < 0) {        s->left_till_irq = s->block_size;    }    if (s->voice) {        free = s->audio_free & ~s->align;        if ((free <= 0) || !dma_len) {            return dma_pos;        }    }    else {        free = dma_len;    }    copy = free;    till = s->left_till_irq;#ifdef DEBUG_SB16_MOST    dolog ("pos:%06d %d till:%d len:%d\n",           dma_pos, free, till, dma_len);#endif    if (till <= copy) {        if (0 == s->dma_auto) {            copy = till;        }    }    written = write_audio (s, nchan, dma_pos, dma_len, copy);    dma_pos = (dma_pos + written) % dma_len;    s->left_till_irq -= written;    if (s->left_till_irq <= 0) {        s->mixer_regs[0x82] |= (nchan & 4) ? 2 : 1;        pic_set_irq (s->irq, 1);        if (0 == s->dma_auto) {            control (s, 0);            speaker (s, 0);        }    }#ifdef DEBUG_SB16_MOST    ldebug ("pos %5d free %5d size %5d till % 5d copy %5d written %5d size %5d\n",            dma_pos, free, dma_len, s->left_till_irq, copy, written,            s->block_size);#endif    while (s->left_till_irq <= 0) {        s->left_till_irq = s->block_size + s->left_till_irq;    }    return dma_pos;}static void SB_audio_callback (void *opaque, int free){    SB16State *s = opaque;    s->audio_free = free;}static void SB_save (QEMUFile *f, void *opaque){    SB16State *s = opaque;    qemu_put_be32s (f, &s->irq);    qemu_put_be32s (f, &s->dma);    qemu_put_be32s (f, &s->hdma);    qemu_put_be32s (f, &s->port);    qemu_put_be32s (f, &s->ver);    qemu_put_be32s (f, &s->in_index);    qemu_put_be32s (f, &s->out_data_len);    qemu_put_be32s (f, &s->fmt_stereo);    qemu_put_be32s (f, &s->fmt_signed);    qemu_put_be32s (f, &s->fmt_bits);    qemu_put_be32s (f, &s->fmt);    qemu_put_be32s (f, &s->dma_auto);    qemu_put_be32s (f, &s->block_size);    qemu_put_be32s (f, &s->fifo);    qemu_put_be32s (f, &s->freq);    qemu_put_be32s (f, &s->time_const);    qemu_put_be32s (f, &s->speaker);    qemu_put_be32s (f, &s->needed_bytes);    qemu_put_be32s (f, &s->cmd);    qemu_put_be32s (f, &s->use_hdma);    qemu_put_be32s (f, &s->highspeed);    qemu_put_be32s (f, &s->can_write);    qemu_put_be32s (f, &s->v2x6);    qemu_put_8s (f, &s->csp_param);    qemu_put_8s (f, &s->csp_value);    qemu_put_8s (f, &s->csp_mode);    qemu_put_8s (f, &s->csp_param);    qemu_put_buffer (f, s->csp_regs, 256);    qemu_put_8s (f, &s->csp_index);    qemu_put_buffer (f, s->csp_reg83, 4);    qemu_put_be32s (f, &s->csp_reg83r);    qemu_put_be32s (f, &s->csp_reg83w);    qemu_put_buffer (f, s->in2_data, sizeof (s->in2_data));    qemu_put_buffer (f, s->out_data, sizeof (s->out_data));    qemu_put_8s (f, &s->test_reg);    qemu_put_8s (f, &s->last_read_byte);    qemu_put_be32s (f, &s->nzero);    qemu_put_be32s (f, &s->left_till_irq);    qemu_put_be32s (f, &s->dma_running);    qemu_put_be32s (f, &s->bytes_per_second);    qemu_put_be32s (f, &s->align);    qemu_put_be32s (f, &s->mixer_nreg);    qemu_put_buffer (f, s->mixer_regs, 256);}static int SB_load (QEMUFile *f, void *opaque, int version_id){    SB16State *s = opaque;    if (version_id != 1) {        return -EINVAL;    }    qemu_get_be32s (f, &s->irq);    qemu_get_be32s (f, &s->dma);    qemu_get_be32s (f, &s->hdma);    qemu_get_be32s (f, &s->port);    qemu_get_be32s (f, &s->ver);    qemu_get_be32s (f, &s->in_index);    qemu_get_be32s (f, &s->out_data_len);    qemu_get_be32s (f, &s->fmt_stereo);    qemu_get_be32s (f, &s->fmt_signed);    qemu_get_be32s (f, &s->fmt_bits);    qemu_get_be32s (f, &s->fmt);    qemu_get_be32s (f, &s->dma_auto);    qemu_get_be32s (f, &s->block_size);    qemu_get_be32s (f, &s->fifo);    qemu_get_be32s (f, &s->freq);    qemu_get_be32s (f, &s->time_const);    qemu_get_be32s (f, &s->speaker);    qemu_get_be32s (f, &s->needed_bytes);    qemu_get_be32s (f, &s->cmd);    qemu_get_be32s (f, &s->use_hdma);    qemu_get_be32s (f, &s->highspeed);    qemu_get_be32s (f, &s->can_write);    qemu_get_be32s (f, &s->v2x6);    qemu_get_8s (f, &s->csp_param);    qemu_get_8s (f, &s->csp_value);    qemu_get_8s (f, &s->csp_mode);    qemu_get_8s (f, &s->csp_param);    qemu_get_buffer (f, s->csp_regs, 256);    qemu_get_8s (f, &s->csp_index);    qemu_get_buffer (f, s->csp_reg83, 4);    qemu_get_be32s (f, &s->csp_reg83r);    qemu_get_be32s (f, &s->csp_reg83w);    qemu_get_buffer (f, s->in2_data, sizeof (s->in2_data));    qemu_get_buffer (f, s->out_data, sizeof (s->out_data));    qemu_get_8s (f, &s->test_reg);    qemu_get_8s (f, &s->last_read_byte);    qemu_get_be32s (f, &s->nzero);    qemu_get_be32s (f, &s->left_till_irq);    qemu_get_be32s (f, &s->dma_running);    qemu_get_be32s (f, &s->bytes_per_second);    qemu_get_be32s (f, &s->align);    qemu_get_be32s (f, &s->mixer_nreg);    qemu_get_buffer (f, s->mixer_regs, 256);    if (s->voice) {        AUD_close_out (&s->card, s->voice);        s->voice = NULL;    }    if (s->dma_running) {        if (s->freq) {            audsettings_t as;            s->audio_free = 0;            as.freq = s->freq;            as.nchannels = 1 << s->fmt_stereo;            as.fmt = s->fmt;            s->voice = AUD_open_out (                &s->card,                s->voice,                "sb16",                s,                SB_audio_callback,                &as,                0               /* little endian */                );        }        control (s, 1);        speaker (s, s->speaker);    }    return 0;}int SB16_init (AudioState *audio){    SB16State *s;    int i;    static const uint8_t dsp_write_ports[] = {0x6, 0xc};    static const uint8_t dsp_read_ports[] = {0x6, 0xa, 0xc, 0xd, 0xe, 0xf};    if (!audio) {        dolog ("No audio state\n");        return -1;    }    s = qemu_mallocz (sizeof (*s));    if (!s) {        dolog ("Could not allocate memory for SB16 (%zu bytes)\n",               sizeof (*s));        return -1;    }    s->cmd = -1;    s->irq = conf.irq;    s->dma = conf.dma;    s->hdma = conf.hdma;    s->port = conf.port;    s->ver = conf.ver_lo | (conf.ver_hi << 8);    s->mixer_regs[0x80] = magic_of_irq (s->irq);    s->mixer_regs[0x81] = (1 << s->dma) | (1 << s->hdma);    s->mixer_regs[0x82] = 2 << 5;    s->csp_regs[5] = 1;    s->csp_regs[9] = 0xf8;    reset_mixer (s);    s->aux_ts = qemu_new_timer (vm_clock, aux_timer, s);    if (!s->aux_ts) {        dolog ("warning: Could not create auxiliary timer\n");    }    for (i = 0; i < LENOFA (dsp_write_ports); i++) {        register_ioport_write (s->port + dsp_write_ports[i], 1, 1, dsp_write, s);    }    for (i = 0; i < LENOFA (dsp_read_ports); i++) {        register_ioport_read (s->port + dsp_read_ports[i], 1, 1, dsp_read, s);    }    register_ioport_write (s->port + 0x4, 1, 1, mixer_write_indexb, s);    register_ioport_write (s->port + 0x4, 1, 2, mixer_write_indexw, s);    register_ioport_read (s->port + 0x5, 1, 1, mixer_read, s);    register_ioport_write (s->port + 0x5, 1, 1, mixer_write_datab, s);    DMA_register_channel (s->hdma, SB_read_DMA, s);    DMA_register_channel (s->dma, SB_read_DMA, s);    s->can_write = 1;    register_savevm ("sb16", 0, 1, SB_save, SB_load, s);    AUD_register_card (audio, "sb16", &s->card);    return 0;}

⌨️ 快捷键说明

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