diff --git a/hw/esp.c b/hw/esp.c index 349052a024..910fd31665 100644 --- a/hw/esp.c +++ b/hw/esp.c @@ -80,6 +80,8 @@ struct ESPState { ESPDMAMemoryReadWriteFunc dma_memory_read; ESPDMAMemoryReadWriteFunc dma_memory_write; void *dma_opaque; + int dma_enabled; + void (*dma_cb)(ESPState *s); }; #define ESP_TCLO 0x0 @@ -167,6 +169,24 @@ static void esp_lower_irq(ESPState *s) } } +static void esp_dma_enable(void *opaque, int irq, int level) +{ + DeviceState *d = opaque; + ESPState *s = container_of(d, ESPState, busdev.qdev); + + if (level) { + s->dma_enabled = 1; + DPRINTF("Raise enable\n"); + if (s->dma_cb) { + s->dma_cb(s); + s->dma_cb = NULL; + } + } else { + DPRINTF("Lower enable\n"); + s->dma_enabled = 0; + } +} + static uint32_t get_cmd(ESPState *s, uint8_t *buf) { uint32_t dmalen; @@ -243,6 +263,10 @@ static void handle_satn(ESPState *s) uint8_t buf[32]; int len; + if (!s->dma_enabled) { + s->dma_cb = handle_satn; + return; + } len = get_cmd(s, buf); if (len) do_cmd(s, buf); @@ -253,6 +277,10 @@ static void handle_s_without_atn(ESPState *s) uint8_t buf[32]; int len; + if (!s->dma_enabled) { + s->dma_cb = handle_s_without_atn; + return; + } len = get_cmd(s, buf); if (len) { do_busid_cmd(s, buf, 0); @@ -261,6 +289,10 @@ static void handle_s_without_atn(ESPState *s) static void handle_satn_stop(ESPState *s) { + if (!s->dma_enabled) { + s->dma_cb = handle_satn_stop; + return; + } s->cmdlen = get_cmd(s, s->cmdbuf); if (s->cmdlen) { DPRINTF("Set ATN & Stop: cmdlen %d\n", s->cmdlen); @@ -431,6 +463,7 @@ static void esp_hard_reset(DeviceState *d) s->ti_wptr = 0; s->dma = 0; s->do_cmd = 0; + s->dma_cb = NULL; s->rregs[ESP_CFG1] = 7; } @@ -450,6 +483,18 @@ static void parent_esp_reset(void *opaque, int irq, int level) } } +static void esp_gpio_demux(void *opaque, int irq, int level) +{ + switch (irq) { + case 0: + parent_esp_reset(opaque, irq, level); + break; + case 1: + esp_dma_enable(opaque, irq, level); + break; + } +} + static uint32_t esp_mem_readb(void *opaque, target_phys_addr_t addr) { ESPState *s = opaque; @@ -646,7 +691,8 @@ static const VMStateDescription vmstate_esp = { void esp_init(target_phys_addr_t espaddr, int it_shift, ESPDMAMemoryReadWriteFunc dma_memory_read, ESPDMAMemoryReadWriteFunc dma_memory_write, - void *dma_opaque, qemu_irq irq, qemu_irq *reset) + void *dma_opaque, qemu_irq irq, qemu_irq *reset, + qemu_irq *dma_enable) { DeviceState *dev; SysBusDevice *s; @@ -658,11 +704,14 @@ void esp_init(target_phys_addr_t espaddr, int it_shift, esp->dma_memory_write = dma_memory_write; esp->dma_opaque = dma_opaque; esp->it_shift = it_shift; + /* XXX for now until rc4030 has been changed to use DMA enable signal */ + esp->dma_enabled = 1; qdev_init_nofail(dev); s = sysbus_from_qdev(dev); sysbus_connect_irq(s, 0, irq); sysbus_mmio_map(s, 0, espaddr); *reset = qdev_get_gpio_in(dev, 0); + *dma_enable = qdev_get_gpio_in(dev, 1); } static int esp_init1(SysBusDevice *dev) @@ -676,7 +725,7 @@ static int esp_init1(SysBusDevice *dev) 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); - qdev_init_gpio_in(&dev->qdev, parent_esp_reset, 1); + qdev_init_gpio_in(&dev->qdev, esp_gpio_demux, 2); scsi_bus_new(&s->bus, &dev->qdev, 0, ESP_MAX_DEVS, esp_command_complete); return scsi_bus_legacy_handle_cmdline(&s->bus); diff --git a/hw/esp.h b/hw/esp.h index 605f953754..62bfd4d129 100644 --- a/hw/esp.h +++ b/hw/esp.h @@ -7,6 +7,7 @@ typedef void (*ESPDMAMemoryReadWriteFunc)(void *opaque, uint8_t *buf, int len); void esp_init(target_phys_addr_t espaddr, int it_shift, ESPDMAMemoryReadWriteFunc dma_memory_read, ESPDMAMemoryReadWriteFunc dma_memory_write, - void *dma_opaque, qemu_irq irq, qemu_irq *reset); + void *dma_opaque, qemu_irq irq, qemu_irq *reset, + qemu_irq *dma_enable); #endif diff --git a/hw/mips_jazz.c b/hw/mips_jazz.c index 5d5305a82d..66397c0c9a 100644 --- a/hw/mips_jazz.c +++ b/hw/mips_jazz.c @@ -137,7 +137,7 @@ void mips_jazz_init (ram_addr_t ram_size, NICInfo *nd; PITState *pit; DriveInfo *fds[MAX_FD]; - qemu_irq esp_reset; + qemu_irq esp_reset, dma_enable; qemu_irq *cpu_exit_irq; ram_addr_t ram_offset; ram_addr_t bios_offset; @@ -245,7 +245,7 @@ void mips_jazz_init (ram_addr_t ram_size, /* SCSI adapter */ esp_init(0x80002000, 0, rc4030_dma_read, rc4030_dma_write, dmas[0], - rc4030[5], &esp_reset); + rc4030[5], &esp_reset, &dma_enable); /* Floppy */ if (drive_get_max_bus(IF_FLOPPY) >= MAX_FD) { diff --git a/hw/sparc32_dma.c b/hw/sparc32_dma.c index b52170787b..984ffc3e53 100644 --- a/hw/sparc32_dma.c +++ b/hw/sparc32_dma.c @@ -58,6 +58,7 @@ #define DMA_INTR 1 #define DMA_INTREN 0x10 #define DMA_WRITE_MEM 0x100 +#define DMA_EN 0x200 #define DMA_LOADED 0x04000000 #define DMA_DRAIN_FIFO 0x40 #define DMA_RESET 0x80 @@ -72,7 +73,12 @@ struct DMAState { uint32_t dmaregs[DMA_REGS]; qemu_irq irq; void *iommu; - qemu_irq dev_reset; + qemu_irq gpio[2]; +}; + +enum { + GPIO_RESET = 0, + GPIO_DMA, }; /* Note: on sparc, the lance 16 bit bus is swapped */ @@ -201,12 +207,21 @@ static void dma_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t val) } } if (val & DMA_RESET) { - qemu_irq_raise(s->dev_reset); - qemu_irq_lower(s->dev_reset); + qemu_irq_raise(s->gpio[GPIO_RESET]); + qemu_irq_lower(s->gpio[GPIO_RESET]); } else if (val & DMA_DRAIN_FIFO) { val &= ~DMA_DRAIN_FIFO; } else if (val == 0) val = DMA_DRAIN_FIFO; + + if (val & DMA_EN && !(s->dmaregs[0] & DMA_EN)) { + DPRINTF("Raise DMA enable\n"); + qemu_irq_raise(s->gpio[GPIO_DMA]); + } else if (!(val & DMA_EN) && !!(s->dmaregs[0] & DMA_EN)) { + DPRINTF("Lower DMA enable\n"); + qemu_irq_lower(s->gpio[GPIO_DMA]); + } + val &= ~DMA_CSR_RO_MASK; val |= DMA_VER; s->dmaregs[0] = (s->dmaregs[0] & DMA_CSR_RO_MASK) | val; @@ -262,7 +277,7 @@ static int sparc32_dma_init1(SysBusDevice *dev) sysbus_init_mmio(dev, DMA_SIZE, dma_io_memory); qdev_init_gpio_in(&dev->qdev, dma_set_irq, 1); - qdev_init_gpio_out(&dev->qdev, &s->dev_reset, 1); + qdev_init_gpio_out(&dev->qdev, s->gpio, 2); return 0; } diff --git a/hw/sun4m.c b/hw/sun4m.c index 7d7a7df1cf..0392109230 100644 --- a/hw/sun4m.c +++ b/hw/sun4m.c @@ -810,7 +810,7 @@ static void sun4m_hw_init(const struct sun4m_hwdef *hwdef, ram_addr_t RAM_size, void *iommu, *espdma, *ledma, *nvram; qemu_irq *cpu_irqs[MAX_CPUS], slavio_irq[32], slavio_cpu_irq[MAX_CPUS], espdma_irq, ledma_irq; - qemu_irq esp_reset; + qemu_irq esp_reset, dma_enable; qemu_irq fdc_tc; qemu_irq *cpu_halt; unsigned long kernel_size; @@ -930,11 +930,12 @@ static void sun4m_hw_init(const struct sun4m_hwdef *hwdef, ram_addr_t RAM_size, exit(1); } - esp_reset = qdev_get_gpio_in(espdma, 0); esp_init(hwdef->esp_base, 2, espdma_memory_read, espdma_memory_write, - espdma, espdma_irq, &esp_reset); + espdma, espdma_irq, &esp_reset, &dma_enable); + qdev_connect_gpio_out(espdma, 0, esp_reset); + qdev_connect_gpio_out(espdma, 1, dma_enable); if (hwdef->cs_base) { sysbus_create_simple("SUNW,CS4231", hwdef->cs_base, @@ -1494,7 +1495,7 @@ static void sun4d_hw_init(const struct sun4d_hwdef *hwdef, ram_addr_t RAM_size, void *iounits[MAX_IOUNITS], *espdma, *ledma, *nvram; qemu_irq *cpu_irqs[MAX_CPUS], sbi_irq[32], sbi_cpu_irq[MAX_CPUS], espdma_irq, ledma_irq; - qemu_irq esp_reset; + qemu_irq esp_reset, dma_enable; unsigned long kernel_size; void *fw_cfg; DeviceState *dev; @@ -1561,10 +1562,12 @@ static void sun4d_hw_init(const struct sun4d_hwdef *hwdef, ram_addr_t RAM_size, exit(1); } - esp_reset = qdev_get_gpio_in(espdma, 0); esp_init(hwdef->esp_base, 2, espdma_memory_read, espdma_memory_write, - espdma, espdma_irq, &esp_reset); + espdma, espdma_irq, &esp_reset, &dma_enable); + + qdev_connect_gpio_out(espdma, 0, esp_reset); + qdev_connect_gpio_out(espdma, 1, dma_enable); kernel_size = sun4m_load_kernel(kernel_filename, initrd_filename, RAM_size); @@ -1683,7 +1686,7 @@ static void sun4c_hw_init(const struct sun4c_hwdef *hwdef, ram_addr_t RAM_size, { void *iommu, *espdma, *ledma, *nvram; qemu_irq *cpu_irqs, slavio_irq[8], espdma_irq, ledma_irq; - qemu_irq esp_reset; + qemu_irq esp_reset, dma_enable; qemu_irq fdc_tc; unsigned long kernel_size; DriveInfo *fd[MAX_FD]; @@ -1751,10 +1754,12 @@ static void sun4c_hw_init(const struct sun4c_hwdef *hwdef, ram_addr_t RAM_size, exit(1); } - esp_reset = qdev_get_gpio_in(espdma, 0); esp_init(hwdef->esp_base, 2, espdma_memory_read, espdma_memory_write, - espdma, espdma_irq, &esp_reset); + espdma, espdma_irq, &esp_reset, &dma_enable); + + qdev_connect_gpio_out(espdma, 0, esp_reset); + qdev_connect_gpio_out(espdma, 1, dma_enable); kernel_size = sun4m_load_kernel(kernel_filename, initrd_filename, RAM_size);