*/
#include "sysbus.h"
-#include "scsi-disk.h"
#include "scsi.h"
+#include "esp.h"
/* debug ESP card */
//#define DEBUG_ESP
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
if (!(s->rregs[ESP_RSTAT] & STAT_INT)) {
s->rregs[ESP_RSTAT] |= STAT_INT;
qemu_irq_raise(s->irq);
+ DPRINTF("Raise IRQ\n");
}
}
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;
}
}
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);
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);
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);
}
}
-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);
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)
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);
};
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;
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)
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)