📄 esp.c
字号:
switch(format) { case 0: len = cdrom_read_toc(nb_sectors, buf, msf, start_track); if (len < 0) goto error_cmd; s->ti_size = len; break; case 1: /* multi session : only a single session defined */ memset(buf, 0, 12); buf[1] = 0x0a; buf[2] = 0x01; buf[3] = 0x01; s->ti_size = 12; break; case 2: len = cdrom_read_toc_raw(nb_sectors, buf, msf, start_track); if (len < 0) goto error_cmd; s->ti_size = len; break; default: error_cmd: DPRINTF("Read TOC error\n"); // XXX error handling break; } s->ti_dir = 1; break; } default: DPRINTF("Unknown SCSI command (%2.2x)\n", buf[1]); break; } s->rregs[4] = STAT_IN | STAT_TC | STAT_DI; s->rregs[5] = INTR_BS | INTR_FC; s->rregs[6] = SEQ_CD; s->espdmaregs[0] |= DMA_INTR; pic_set_irq(s->irq, 1);}static void dma_write(ESPState *s, const uint8_t *buf, uint32_t len){ uint32_t dmaptr, dmalen; dmalen = s->wregs[0] | (s->wregs[1] << 8); DPRINTF("Transfer status len %d\n", dmalen); if (s->dma) { dmaptr = iommu_translate(s->espdmaregs[1]); DPRINTF("DMA Direction: %c\n", s->espdmaregs[0] & 0x100? 'w': 'r'); cpu_physical_memory_write(dmaptr, buf, len); s->rregs[4] = STAT_IN | STAT_TC | STAT_ST; s->rregs[5] = INTR_BS | INTR_FC; s->rregs[6] = SEQ_CD; } else { memcpy(s->ti_buf, buf, len); s->ti_size = dmalen; s->ti_rptr = 0; s->ti_wptr = 0; s->rregs[7] = dmalen; } s->espdmaregs[0] |= DMA_INTR; pic_set_irq(s->irq, 1);}static const uint8_t okbuf[] = {0, 0};static void handle_ti(ESPState *s){ uint32_t dmaptr, dmalen; unsigned int i; dmalen = s->wregs[0] | (s->wregs[1] << 8); DPRINTF("Transfer Information len %d\n", dmalen); if (s->dma) { dmaptr = iommu_translate(s->espdmaregs[1]); DPRINTF("DMA Direction: %c, addr 0x%8.8x\n", s->espdmaregs[0] & 0x100? 'w': 'r', dmaptr); for (i = 0; i < s->ti_size; i++) { dmaptr = iommu_translate(s->espdmaregs[1] + i); if (s->ti_dir) cpu_physical_memory_write(dmaptr, &s->ti_buf[i], 1); else cpu_physical_memory_read(dmaptr, &s->ti_buf[i], 1); } if (s->dma_cb) { s->dma_cb(s, s->espdmaregs[1], dmalen); s->dma_cb = NULL; } s->rregs[4] = STAT_IN | STAT_TC | STAT_ST; s->rregs[5] = INTR_BS; s->rregs[6] = 0; s->espdmaregs[0] |= DMA_INTR; } else { s->ti_size = dmalen; s->ti_rptr = 0; s->ti_wptr = 0; s->rregs[7] = dmalen; } pic_set_irq(s->irq, 1);}static void esp_reset(void *opaque){ ESPState *s = opaque; memset(s->rregs, 0, ESP_MAXREG); memset(s->wregs, 0, ESP_MAXREG); s->rregs[0x0e] = 0x4; // Indicate fas100a memset(s->espdmaregs, 0, ESPDMA_REGS * 4); s->ti_size = 0; s->ti_rptr = 0; s->ti_wptr = 0; s->ti_dir = 0; s->dma = 0; s->dma_cb = NULL;}static uint32_t esp_mem_readb(void *opaque, target_phys_addr_t addr){ ESPState *s = opaque; uint32_t saddr; saddr = (addr & ESP_MAXREG) >> 2; DPRINTF("read reg[%d]: 0x%2.2x\n", saddr, s->rregs[saddr]); switch (saddr) { case 2: // FIFO if (s->ti_size > 0) { s->ti_size--; s->rregs[saddr] = s->ti_buf[s->ti_rptr++]; pic_set_irq(s->irq, 1); } if (s->ti_size == 0) { s->ti_rptr = 0; s->ti_wptr = 0; } break; case 5: // interrupt // Clear status bits except TC s->rregs[4] &= STAT_TC; pic_set_irq(s->irq, 0); s->espdmaregs[0] &= ~DMA_INTR; break; default: break; } return s->rregs[saddr];}static void esp_mem_writeb(void *opaque, target_phys_addr_t addr, uint32_t val){ ESPState *s = opaque; uint32_t saddr; saddr = (addr & ESP_MAXREG) >> 2; DPRINTF("write reg[%d]: 0x%2.2x -> 0x%2.2x\n", saddr, s->wregs[saddr], val); switch (saddr) { case 0: case 1: s->rregs[saddr] = val; break; case 2: // FIFO s->ti_size++; s->ti_buf[s->ti_wptr++] = val & 0xff; break; case 3: s->rregs[saddr] = val; // Command if (val & 0x80) { s->dma = 1; } else { s->dma = 0; } switch(val & 0x7f) { case 0: DPRINTF("NOP (%2.2x)\n", val); break; case 1: DPRINTF("Flush FIFO (%2.2x)\n", val); //s->ti_size = 0; s->rregs[5] = INTR_FC; s->rregs[6] = 0; break; case 2: DPRINTF("Chip reset (%2.2x)\n", val); esp_reset(s); break; case 3: DPRINTF("Bus reset (%2.2x)\n", val); s->rregs[5] = INTR_RST; if (!(s->wregs[8] & 0x40)) { s->espdmaregs[0] |= DMA_INTR; pic_set_irq(s->irq, 1); } break; case 0x10: handle_ti(s); break; case 0x11: DPRINTF("Initiator Command Complete Sequence (%2.2x)\n", val); dma_write(s, okbuf, 2); break; case 0x12: DPRINTF("Message Accepted (%2.2x)\n", val); dma_write(s, okbuf, 2); s->rregs[5] = INTR_DC; s->rregs[6] = 0; break; case 0x1a: DPRINTF("Set ATN (%2.2x)\n", val); break; case 0x42: handle_satn(s); break; case 0x43: DPRINTF("Set ATN & stop (%2.2x)\n", val); handle_satn(s); break; default: DPRINTF("Unhandled ESP command (%2.2x)\n", val); break; } break; case 4 ... 7: break; case 8: s->rregs[saddr] = val; break; case 9 ... 10: break; case 11: s->rregs[saddr] = val & 0x15; break; case 12 ... 15: s->rregs[saddr] = val; break; default: break; } s->wregs[saddr] = val;}static CPUReadMemoryFunc *esp_mem_read[3] = { esp_mem_readb, esp_mem_readb, esp_mem_readb,};static CPUWriteMemoryFunc *esp_mem_write[3] = { esp_mem_writeb, esp_mem_writeb, esp_mem_writeb,};static uint32_t espdma_mem_readl(void *opaque, target_phys_addr_t addr){ ESPState *s = opaque; uint32_t saddr; saddr = (addr & ESPDMA_MAXADDR) >> 2; DPRINTF("read dmareg[%d]: 0x%8.8x\n", saddr, s->espdmaregs[saddr]); return s->espdmaregs[saddr];}static void espdma_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t val){ ESPState *s = opaque; uint32_t saddr; saddr = (addr & ESPDMA_MAXADDR) >> 2; DPRINTF("write dmareg[%d]: 0x%8.8x -> 0x%8.8x\n", saddr, s->espdmaregs[saddr], val); switch (saddr) { case 0: if (!(val & DMA_INTREN)) pic_set_irq(s->irq, 0); if (val & 0x80) { esp_reset(s); } else if (val & 0x40) { val &= ~0x40; } else if (val == 0) val = 0x40; val &= 0x0fffffff; val |= DMA_VER; break; case 1: s->espdmaregs[0] = DMA_LOADED; break; default: break; } s->espdmaregs[saddr] = val;}static CPUReadMemoryFunc *espdma_mem_read[3] = { espdma_mem_readl, espdma_mem_readl, espdma_mem_readl,};static CPUWriteMemoryFunc *espdma_mem_write[3] = { espdma_mem_writel, espdma_mem_writel, espdma_mem_writel,};static void esp_save(QEMUFile *f, void *opaque){ ESPState *s = opaque; unsigned int i; qemu_put_buffer(f, s->rregs, ESP_MAXREG); qemu_put_buffer(f, s->wregs, ESP_MAXREG); qemu_put_be32s(f, &s->irq); for (i = 0; i < ESPDMA_REGS; i++) qemu_put_be32s(f, &s->espdmaregs[i]); qemu_put_be32s(f, &s->ti_size); qemu_put_be32s(f, &s->ti_rptr); qemu_put_be32s(f, &s->ti_wptr); qemu_put_be32s(f, &s->ti_dir); qemu_put_buffer(f, s->ti_buf, TI_BUFSZ); qemu_put_be32s(f, &s->dma);}static int esp_load(QEMUFile *f, void *opaque, int version_id){ ESPState *s = opaque; unsigned int i; if (version_id != 1) return -EINVAL; qemu_get_buffer(f, s->rregs, ESP_MAXREG); qemu_get_buffer(f, s->wregs, ESP_MAXREG); qemu_get_be32s(f, &s->irq); for (i = 0; i < ESPDMA_REGS; i++) qemu_get_be32s(f, &s->espdmaregs[i]); qemu_get_be32s(f, &s->ti_size); qemu_get_be32s(f, &s->ti_rptr); qemu_get_be32s(f, &s->ti_wptr); qemu_get_be32s(f, &s->ti_dir); qemu_get_buffer(f, s->ti_buf, TI_BUFSZ); qemu_get_be32s(f, &s->dma); return 0;}void esp_init(BlockDriverState **bd, int irq, uint32_t espaddr, uint32_t espdaddr){ ESPState *s; int esp_io_memory, espdma_io_memory; s = qemu_mallocz(sizeof(ESPState)); if (!s) return; s->bd = bd; s->irq = irq; esp_io_memory = cpu_register_io_memory(0, esp_mem_read, esp_mem_write, s); cpu_register_physical_memory(espaddr, ESP_MAXREG*4, esp_io_memory); espdma_io_memory = cpu_register_io_memory(0, espdma_mem_read, espdma_mem_write, s); cpu_register_physical_memory(espdaddr, 16, espdma_io_memory); esp_reset(s); register_savevm("esp", espaddr, 1, esp_save, esp_load, s); qemu_register_reset(esp_reset, s);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -