From: Laurent Vivier
Signed-off-by: Laurent Vivier
---
hw/mips/mips_jazz.c | 2 +-
hw/scsi/esp.c | 330 +-
include/hw/scsi/esp.h | 15 ++-
3 files changed, 313 insertions(+), 34 deletions(-)
diff --git a/hw/mips/mips_jazz.c b/hw/mips/mips_jazz.c
index 90cb306f53..87118f2d03 100644
--- a/hw/mips/mips_jazz.c
+++ b/hw/mips/mips_jazz.c
@@ -282,7 +282,7 @@ static void mips_jazz_init(MachineState *machine,
/* SCSI adapter */
esp = esp_init(0x80002000, 0, rc4030_dma_read, rc4030_dma_write, dmas[0],
- qdev_get_gpio_in(rc4030, 5), _reset, _enable);
+ qdev_get_gpio_in(rc4030, 5), NULL, _reset, _enable);
scsi_bus_legacy_handle_cmdline(>bus);
/* Floppy */
diff --git a/hw/scsi/esp.c b/hw/scsi/esp.c
index 9ed9727744..4d7fa71309 100644
--- a/hw/scsi/esp.c
+++ b/hw/scsi/esp.c
@@ -37,6 +37,8 @@
* http://www.ibiblio.org/pub/historic-linux/early-ports/Sparc/NCR/NCR53C9X.txt
*/
+/* on Macintosh Quadra it is a NCR53C96 */
+
static void esp_raise_irq(ESPState *s)
{
if (!(s->rregs[ESP_RSTAT] & STAT_INT)) {
@@ -55,6 +57,16 @@ static void esp_lower_irq(ESPState *s)
}
}
+static void esp_raise_drq(ESPState *s)
+{
+qemu_irq_raise(s->irq_data);
+}
+
+static void esp_lower_drq(ESPState *s)
+{
+qemu_irq_lower(s->irq_data);
+}
+
void esp_dma_enable(ESPState *s, int irq, int level)
{
if (level) {
@@ -81,29 +93,11 @@ void esp_request_cancelled(SCSIRequest *req)
}
}
-static uint32_t get_cmd(ESPState *s, uint8_t *buf, uint8_t buflen)
+static int get_cmd_cb(ESPState *s)
{
-uint32_t dmalen;
int target;
target = s->wregs[ESP_WBUSID] & BUSID_DID;
-if (s->dma) {
-dmalen = s->rregs[ESP_TCLO];
-dmalen |= s->rregs[ESP_TCMID] << 8;
-dmalen |= s->rregs[ESP_TCHI] << 16;
-if (dmalen > buflen) {
-return 0;
-}
-s->dma_memory_read(s->dma_opaque, buf, dmalen);
-} else {
-dmalen = s->ti_size;
-if (dmalen > TI_BUFSZ) {
-return 0;
-}
-memcpy(buf, s->ti_buf, dmalen);
-buf[0] = buf[2] >> 5;
-}
-trace_esp_get_cmd(dmalen, target);
s->ti_size = 0;
s->ti_rptr = 0;
@@ -122,8 +116,48 @@ static uint32_t get_cmd(ESPState *s, uint8_t *buf, uint8_t
buflen)
s->rregs[ESP_RINTR] = INTR_DC;
s->rregs[ESP_RSEQ] = SEQ_0;
esp_raise_irq(s);
+return -1;
+}
+return 0;
+}
+
+static uint32_t get_cmd(ESPState *s, uint8_t *buf, uint8_t buflen)
+{
+int target;
+uint32_t dmalen;
+
+target = s->wregs[ESP_WBUSID] & BUSID_DID;
+if (s->dma) {
+dmalen = s->rregs[ESP_TCLO];
+dmalen |= s->rregs[ESP_TCMID] << 8;
+dmalen |= s->rregs[ESP_TCHI] << 16;
+if (dmalen > buflen) {
+return 0;
+}
+if (s->dma_memory_read) {
+s->dma_memory_read(s->dma_opaque, buf, dmalen);
+} else {
+memcpy(s->pdma_buf, buf, dmalen);
+s->pdma_len = dmalen;
+s->pdma_start = s->pdma_buf;
+s->pdma_cur = s->pdma_buf;
+esp_raise_drq(s);
+return 0;
+}
+} else {
+dmalen = s->ti_size;
+if (dmalen > TI_BUFSZ) {
+return 0;
+}
+memcpy(buf, s->ti_buf, dmalen);
+buf[0] = buf[2] >> 5;
+}
+trace_esp_get_cmd(dmalen, target);
+
+if (get_cmd_cb(s) < 0) {
return 0;
}
+
return dmalen;
}
@@ -162,6 +196,15 @@ static void do_cmd(ESPState *s, uint8_t *buf)
do_busid_cmd(s, [1], busid);
}
+static void satn_pdma_cb(ESPState *s)
+{
+if (get_cmd_cb(s) < 0) {
+return;
+}
+if (s->pdma_cur != s->pdma_start)
+do_cmd(s, s->pdma_start);
+}
+
static void handle_satn(ESPState *s)
{
uint8_t buf[32];
@@ -171,11 +214,21 @@ static void handle_satn(ESPState *s)
s->dma_cb = handle_satn;
return;
}
+s->pdma_cb = satn_pdma_cb;
len = get_cmd(s, buf, sizeof(buf));
if (len)
do_cmd(s, buf);
}
+static void s_without_satn_pdma_cb(ESPState *s)
+{
+if (get_cmd_cb(s) < 0) {
+return;
+}
+if (s->pdma_cur != s->pdma_start)
+do_busid_cmd(s, s->pdma_start, 0);
+}
+
static void handle_s_without_atn(ESPState *s)
{
uint8_t buf[32];
@@ -185,18 +238,36 @@ static void handle_s_without_atn(ESPState *s)
s->dma_cb = handle_s_without_atn;
return;
}
+s->pdma_cb = s_without_satn_pdma_cb;
len = get_cmd(s, buf, sizeof(buf));
if (len) {
do_busid_cmd(s, buf, 0);
}
}
+static void satn_stop_pdma_cb(ESPState *s)
+{
+if (get_cmd_cb(s) < 0) {
+return;
+}
+s->cmdlen = s->pdma_cur - s->pdma_start;
+if (s->cmdlen) {
+trace_esp_handle_satn_stop(s->cmdlen);
+s->do_cmd = 1;
+s->rregs[ESP_RSTAT] = STAT_TC | STAT_CD;
+s->rregs[ESP_RINTR] = INTR_BS |