]> Git Repo - qemu.git/blobdiff - hw/esp.c
usb: uhci: remote wakeup support.
[qemu.git] / hw / esp.c
index c2567a6b8ac3965736815d9d501050206ce30249..fa9d2a270667d67499b88e44e07e063e37609f65 100644 (file)
--- a/hw/esp.c
+++ b/hw/esp.c
@@ -23,8 +23,8 @@
  */
 
 #include "sysbus.h"
-#include "scsi-disk.h"
 #include "scsi.h"
+#include "esp.h"
 
 /* debug ESP card */
 //#define DEBUG_ESP
@@ -77,9 +77,11 @@ struct ESPState {
     uint8_t *async_buf;
     uint32_t async_len;
 
-    espdma_memory_read_write dma_memory_read;
-    espdma_memory_read_write dma_memory_write;
+    ESPDMAMemoryReadWriteFunc dma_memory_read;
+    ESPDMAMemoryReadWriteFunc dma_memory_write;
     void *dma_opaque;
+    int dma_enabled;
+    void (*dma_cb)(ESPState *s);
 };
 
 #define ESP_TCLO   0x0
@@ -154,6 +156,7 @@ static void esp_raise_irq(ESPState *s)
     if (!(s->rregs[ESP_RSTAT] & STAT_INT)) {
         s->rregs[ESP_RSTAT] |= STAT_INT;
         qemu_irq_raise(s->irq);
+        DPRINTF("Raise IRQ\n");
     }
 }
 
@@ -162,6 +165,25 @@ static void esp_lower_irq(ESPState *s)
     if (s->rregs[ESP_RSTAT] & STAT_INT) {
         s->rregs[ESP_RSTAT] &= ~STAT_INT;
         qemu_irq_lower(s->irq);
+        DPRINTF("Lower IRQ\n");
+    }
+}
+
+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;
     }
 }
 
@@ -241,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);
@@ -251,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);
@@ -259,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);
@@ -417,9 +451,9 @@ static void handle_ti(ESPState *s)
     }
 }
 
-static void esp_reset(void *opaque)
+static void esp_hard_reset(DeviceState *d)
 {
-    ESPState *s = opaque;
+    ESPState *s = container_of(d, ESPState, busdev.qdev);
 
     memset(s->rregs, 0, ESP_REGS);
     memset(s->wregs, 0, ESP_REGS);
@@ -429,14 +463,36 @@ static void esp_reset(void *opaque)
     s->ti_wptr = 0;
     s->dma = 0;
     s->do_cmd = 0;
+    s->dma_cb = NULL;
 
     s->rregs[ESP_CFG1] = 7;
 }
 
+static void esp_soft_reset(DeviceState *d)
+{
+    ESPState *s = container_of(d, ESPState, busdev.qdev);
+
+    qemu_irq_lower(s->irq);
+    esp_hard_reset(d);
+}
+
 static void parent_esp_reset(void *opaque, int irq, int level)
 {
-    if (level)
-        esp_reset(opaque);
+    if (level) {
+        esp_soft_reset(opaque);
+    }
+}
+
+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)
@@ -526,7 +582,7 @@ static void esp_mem_writeb(void *opaque, target_phys_addr_t addr, uint32_t val)
             break;
         case CMD_RESET:
             DPRINTF("Chip reset (%2.2x)\n", val);
-            esp_reset(s);
+            esp_soft_reset(&s->busdev.qdev);
             break;
         case CMD_BUSRESET:
             DPRINTF("Bus reset (%2.2x)\n", val);
@@ -633,9 +689,10 @@ static const VMStateDescription vmstate_esp = {
 };
 
 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)
+              ESPDMAMemoryReadWriteFunc dma_memory_read,
+              ESPDMAMemoryReadWriteFunc dma_memory_write,
+              void *dma_opaque, qemu_irq irq, qemu_irq *reset,
+              qemu_irq *dma_enable)
 {
     DeviceState *dev;
     SysBusDevice *s;
@@ -647,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)
@@ -662,24 +722,30 @@ static int esp_init1(SysBusDevice *dev)
     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);
+    esp_io_memory = cpu_register_io_memory(esp_mem_read, esp_mem_write, s,
+                                           DEVICE_NATIVE_ENDIAN);
     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);
+    qdev_init_gpio_in(&dev->qdev, esp_gpio_demux, 2);
 
     scsi_bus_new(&s->bus, &dev->qdev, 0, ESP_MAX_DEVS, esp_command_complete);
-    scsi_bus_legacy_handle_cmdline(&s->bus);
-    return 0;
+    return scsi_bus_legacy_handle_cmdline(&s->bus);
 }
 
+static SysBusDeviceInfo esp_info = {
+    .init = esp_init1,
+    .qdev.name  = "esp",
+    .qdev.size  = sizeof(ESPState),
+    .qdev.vmsd  = &vmstate_esp,
+    .qdev.reset = esp_hard_reset,
+    .qdev.props = (Property[]) {
+        {.name = NULL}
+    }
+};
+
 static void esp_register_devices(void)
 {
-    sysbus_register_dev("esp", sizeof(ESPState), esp_init1);
+    sysbus_register_withprop(&esp_info);
 }
 
 device_init(esp_register_devices)
This page took 0.028978 seconds and 4 git commands to generate.