version 1.1.1.7, 2018/04/24 16:53:45
|
version 1.1.1.8, 2018/04/24 17:24:54
|
Line 22
|
Line 22
|
* THE SOFTWARE. |
* THE SOFTWARE. |
*/ |
*/ |
|
|
#include "hw.h" |
#include "sysbus.h" |
#include "scsi-disk.h" |
#include "scsi-disk.h" |
#include "scsi.h" |
#include "scsi.h" |
|
|
Line 38
|
Line 38
|
*/ |
*/ |
|
|
#ifdef DEBUG_ESP |
#ifdef DEBUG_ESP |
#define DPRINTF(fmt, args...) \ |
#define DPRINTF(fmt, ...) \ |
do { printf("ESP: " fmt , ##args); } while (0) |
do { printf("ESP: " fmt , ## __VA_ARGS__); } while (0) |
#else |
#else |
#define DPRINTF(fmt, args...) do {} while (0) |
#define DPRINTF(fmt, ...) do {} while (0) |
#endif |
#endif |
|
|
#define ESP_ERROR(fmt, args...) \ |
#define ESP_ERROR(fmt, ...) \ |
do { printf("ESP ERROR: %s: " fmt, __func__ , ##args); } while (0) |
do { printf("ESP ERROR: %s: " fmt, __func__ , ## __VA_ARGS__); } while (0) |
|
|
#define ESP_REGS 16 |
#define ESP_REGS 16 |
#define TI_BUFSZ 16 |
#define TI_BUFSZ 16 |
Line 53 do { printf("ESP ERROR: %s: " fmt, __fun
|
Line 53 do { printf("ESP ERROR: %s: " fmt, __fun
|
typedef struct ESPState ESPState; |
typedef struct ESPState ESPState; |
|
|
struct ESPState { |
struct ESPState { |
|
SysBusDevice busdev; |
uint32_t it_shift; |
uint32_t it_shift; |
qemu_irq irq; |
qemu_irq irq; |
uint8_t rregs[ESP_REGS]; |
uint8_t rregs[ESP_REGS]; |
Line 400 static void esp_reset(void *opaque)
|
Line 401 static void esp_reset(void *opaque)
|
{ |
{ |
ESPState *s = opaque; |
ESPState *s = opaque; |
|
|
esp_lower_irq(s); |
|
|
|
memset(s->rregs, 0, ESP_REGS); |
memset(s->rregs, 0, ESP_REGS); |
memset(s->wregs, 0, ESP_REGS); |
memset(s->wregs, 0, ESP_REGS); |
s->rregs[ESP_TCHI] = TCHI_FAS100A; // Indicate fas100a |
s->rregs[ESP_TCHI] = TCHI_FAS100A; // Indicate fas100a |
Line 423 static void parent_esp_reset(void *opaqu
|
Line 422 static void parent_esp_reset(void *opaqu
|
static uint32_t esp_mem_readb(void *opaque, target_phys_addr_t addr) |
static uint32_t esp_mem_readb(void *opaque, target_phys_addr_t addr) |
{ |
{ |
ESPState *s = opaque; |
ESPState *s = opaque; |
uint32_t saddr; |
uint32_t saddr, old_val; |
|
|
saddr = addr >> s->it_shift; |
saddr = addr >> s->it_shift; |
DPRINTF("read reg[%d]: 0x%2.2x\n", saddr, s->rregs[saddr]); |
DPRINTF("read reg[%d]: 0x%2.2x\n", saddr, s->rregs[saddr]); |
Line 446 static uint32_t esp_mem_readb(void *opaq
|
Line 445 static uint32_t esp_mem_readb(void *opaq
|
} |
} |
break; |
break; |
case ESP_RINTR: |
case ESP_RINTR: |
// Clear interrupt/error status bits |
/* Clear sequence step, interrupt register and all status bits |
s->rregs[ESP_RSTAT] &= ~(STAT_GE | STAT_PE); |
except TC */ |
|
old_val = s->rregs[ESP_RINTR]; |
|
s->rregs[ESP_RINTR] = 0; |
|
s->rregs[ESP_RSTAT] &= ~STAT_TC; |
|
s->rregs[ESP_RSEQ] = SEQ_CD; |
esp_lower_irq(s); |
esp_lower_irq(s); |
break; |
|
|
return old_val; |
default: |
default: |
break; |
break; |
} |
} |
Line 617 static int esp_load(QEMUFile *f, void *o
|
Line 621 static int esp_load(QEMUFile *f, void *o
|
return 0; |
return 0; |
} |
} |
|
|
void esp_scsi_attach(void *opaque, BlockDriverState *bd, int id) |
static void esp_scsi_attach(DeviceState *host, BlockDriverState *bd, int id) |
{ |
{ |
ESPState *s = (ESPState *)opaque; |
ESPState *s = FROM_SYSBUS(ESPState, sysbus_from_qdev(host)); |
|
|
if (id < 0) { |
if (id < 0) { |
for (id = 0; id < ESP_MAX_DEVS; id++) { |
for (id = 0; id < ESP_MAX_DEVS; id++) { |
Line 644 void esp_scsi_attach(void *opaque, Block
|
Line 648 void esp_scsi_attach(void *opaque, Block
|
s->scsi_dev[id] = scsi_disk_init(bd, 0, esp_command_complete, s); |
s->scsi_dev[id] = scsi_disk_init(bd, 0, esp_command_complete, s); |
} |
} |
|
|
void *esp_init(target_phys_addr_t espaddr, int it_shift, |
void esp_init(target_phys_addr_t espaddr, int it_shift, |
espdma_memory_read_write dma_memory_read, |
espdma_memory_read_write dma_memory_read, |
espdma_memory_read_write dma_memory_write, |
espdma_memory_read_write dma_memory_write, |
void *dma_opaque, qemu_irq irq, qemu_irq *reset) |
void *dma_opaque, qemu_irq irq, qemu_irq *reset) |
|
{ |
|
DeviceState *dev; |
|
SysBusDevice *s; |
|
ESPState *esp; |
|
|
|
dev = qdev_create(NULL, "esp"); |
|
esp = DO_UPCAST(ESPState, busdev.qdev, dev); |
|
esp->dma_memory_read = dma_memory_read; |
|
esp->dma_memory_write = dma_memory_write; |
|
esp->dma_opaque = dma_opaque; |
|
esp->it_shift = it_shift; |
|
qdev_init(dev); |
|
s = sysbus_from_qdev(dev); |
|
sysbus_connect_irq(s, 0, irq); |
|
sysbus_mmio_map(s, 0, espaddr); |
|
} |
|
|
|
static void esp_init1(SysBusDevice *dev) |
{ |
{ |
ESPState *s; |
ESPState *s = FROM_SYSBUS(ESPState, dev); |
int esp_io_memory; |
int esp_io_memory; |
|
|
s = qemu_mallocz(sizeof(ESPState)); |
sysbus_init_irq(dev, &s->irq); |
|
assert(s->it_shift != -1); |
|
|
s->irq = irq; |
esp_io_memory = cpu_register_io_memory(esp_mem_read, esp_mem_write, s); |
s->it_shift = it_shift; |
sysbus_init_mmio(dev, ESP_REGS << s->it_shift, esp_io_memory); |
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); |
esp_reset(s); |
|
|
register_savevm("esp", espaddr, 3, esp_save, esp_load, s); |
register_savevm("esp", -1, 3, esp_save, esp_load, s); |
qemu_register_reset(esp_reset, s); |
qemu_register_reset(esp_reset, s); |
|
|
*reset = *qemu_allocate_irqs(parent_esp_reset, s, 1); |
qdev_init_gpio_in(&dev->qdev, parent_esp_reset, 1); |
|
|
return s; |
scsi_bus_new(&dev->qdev, esp_scsi_attach); |
} |
} |
|
|
|
static void esp_register_devices(void) |
|
{ |
|
sysbus_register_dev("esp", sizeof(ESPState), esp_init1); |
|
} |
|
|
|
device_init(esp_register_devices) |