void *esp_init(target_phys_addr_t espaddr, int it_shift, espdma_memory_read_write dma_memory_read, espdma_memory_read_write dma_memory_write, void *dma_opaque, qemu_irq irq, qemu_irq *reset) { ESPState *s; int esp_io_memory; s = qemu_mallocz(sizeof(ESPState)); if (!s) return NULL; s->irq = irq; s->it_shift = it_shift; s->dma_memory_read = dma_memory_read; s->dma_memory_write = dma_memory_write; s->dma_opaque = dma_opaque; esp_io_memory = cpu_register_io_memory(0, esp_mem_read, esp_mem_write, s); cpu_register_physical_memory(espaddr, ESP_REGS << it_shift, esp_io_memory); esp_reset(s); register_savevm("esp", espaddr, 3, esp_save, esp_load, s); qemu_register_reset(esp_reset, s); *reset = *qemu_allocate_irqs(parent_esp_reset, s, 1); return s; }
static int esp_init1(SysBusDevice *dev) { ESPState *s = FROM_SYSBUS(ESPState, dev); int esp_io_memory; sysbus_init_irq(dev, &s->irq); assert(s->it_shift != -1); esp_io_memory = cpu_register_io_memory(esp_mem_read, esp_mem_write, s); sysbus_init_mmio(dev, ESP_REGS << s->it_shift, esp_io_memory); esp_reset(s); vmstate_register(-1, &vmstate_esp, s); qemu_register_reset(esp_reset, s); qdev_init_gpio_in(&dev->qdev, parent_esp_reset, 1); scsi_bus_new(&s->bus, &dev->qdev, 0, ESP_MAX_DEVS, esp_command_complete); scsi_bus_legacy_handle_cmdline(&s->bus); return 0; }
static void dma_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t val) { DMAState *s = opaque; uint32_t saddr; saddr = (addr & DMA_MAXADDR) >> 2; DPRINTF("write dmareg[%d]: 0x%8.8x -> 0x%8.8x\n", saddr, s->dmaregs[saddr], val); switch (saddr) { case 0: if (!(val & DMA_INTREN)) pic_set_irq_new(s->intctl, s->espirq, 0); if (val & DMA_RESET) { esp_reset(s->esp_opaque); } else if (val & 0x40) { val &= ~0x40; } else if (val == 0) val = 0x40; val &= 0x0fffffff; val |= DMA_VER; break; case 1: s->dmaregs[0] |= DMA_LOADED; break; case 4: if (!(val & DMA_INTREN)) pic_set_irq_new(s->intctl, s->leirq, 0); if (val & DMA_RESET) pcnet_h_reset(s->lance_opaque); val &= 0x0fffffff; val |= DMA_VER; break; default: break; } s->dmaregs[saddr] = val; }
static void esp_mem_writeb(void *opaque, target_phys_addr_t addr, uint32_t val) { ESPState *s = opaque; uint32_t saddr; saddr = addr >> s->it_shift; DPRINTF("write reg[%d]: 0x%2.2x -> 0x%2.2x\n", saddr, s->wregs[saddr], val); switch (saddr) { case ESP_TCLO: case ESP_TCMID: s->rregs[ESP_RSTAT] &= ~STAT_TC; break; case ESP_FIFO: if (s->do_cmd) { s->cmdbuf[s->cmdlen++] = val & 0xff; } else if (s->ti_size == TI_BUFSZ - 1) { ESP_ERROR("fifo overrun\n"); } else { s->ti_size++; s->ti_buf[s->ti_wptr++] = val & 0xff; } break; case ESP_CMD: s->rregs[saddr] = val; if (val & CMD_DMA) { s->dma = 1; /* Reload DMA counter. */ s->rregs[ESP_TCLO] = s->wregs[ESP_TCLO]; s->rregs[ESP_TCMID] = s->wregs[ESP_TCMID]; } else { s->dma = 0; } switch(val & CMD_CMD) { case CMD_NOP: DPRINTF("NOP (%2.2x)\n", val); break; case CMD_FLUSH: DPRINTF("Flush FIFO (%2.2x)\n", val); //s->ti_size = 0; s->rregs[ESP_RINTR] = INTR_FC; s->rregs[ESP_RSEQ] = 0; s->rregs[ESP_RFLAGS] = 0; break; case CMD_RESET: DPRINTF("Chip reset (%2.2x)\n", val); esp_reset(s); break; case CMD_BUSRESET: DPRINTF("Bus reset (%2.2x)\n", val); s->rregs[ESP_RINTR] = INTR_RST; if (!(s->wregs[ESP_CFG1] & CFG1_RESREPT)) { esp_raise_irq(s); } break; case CMD_TI: handle_ti(s); break; case CMD_ICCS: DPRINTF("Initiator Command Complete Sequence (%2.2x)\n", val); write_response(s); s->rregs[ESP_RINTR] = INTR_FC; s->rregs[ESP_RSTAT] |= STAT_MI; break; case CMD_MSGACC: DPRINTF("Message Accepted (%2.2x)\n", val); write_response(s); s->rregs[ESP_RINTR] = INTR_DC; s->rregs[ESP_RSEQ] = 0; break; case CMD_SATN: DPRINTF("Set ATN (%2.2x)\n", val); break; case CMD_SELATN: DPRINTF("Set ATN (%2.2x)\n", val); handle_satn(s); break; case CMD_SELATNS: DPRINTF("Set ATN & stop (%2.2x)\n", val); handle_satn_stop(s); break; case CMD_ENSEL: DPRINTF("Enable selection (%2.2x)\n", val); s->rregs[ESP_RINTR] = 0; break; default: ESP_ERROR("Unhandled ESP command (%2.2x)\n", val); break; } break; case ESP_WBUSID ... ESP_WSYNO: break; case ESP_CFG1: s->rregs[saddr] = val; break; case ESP_WCCF ... ESP_WTEST: break; case ESP_CFG2 ... ESP_RES4: s->rregs[saddr] = val; break; default: ESP_ERROR("invalid write of 0x%02x at [0x%x]\n", val, saddr); return; } s->wregs[saddr] = val; }
static void parent_esp_reset(void *opaque, int irq, int level) { if (level) esp_reset(opaque); }