From: Toni Wilen Date: Wed, 27 Aug 2014 18:02:47 +0000 (+0300) Subject: Added 53C94/FAS216 "software DMA" support. X-Git-Tag: 3000~79 X-Git-Url: https://git.unchartedbackwaters.co.uk/w/?a=commitdiff_plain;h=ad853b6872365989b02fc34ffcae5044f2f898d7;p=francis%2Fwinuae.git Added 53C94/FAS216 "software DMA" support. --- diff --git a/qemuvga/esp.cpp b/qemuvga/esp.cpp index c887b1e2..8454677c 100644 --- a/qemuvga/esp.cpp +++ b/qemuvga/esp.cpp @@ -64,8 +64,8 @@ void esp_dma_enable(void *opaque, int level) if (level) { s->dma_enabled = 1; if (s->dma_cb) { - s->dma_cb(s); - s->dma_cb = NULL; + if (s->dma_cb(s)) + s->dma_cb = NULL; } } else { s->dma_enabled = 0; @@ -134,10 +134,13 @@ static void do_busid_cmd(ESPState *s, uint8_t *buf, uint8_t busid) datalen = scsiesp_req_enqueue(s->current_req); s->ti_size = datalen; if (datalen != 0) { - s->rregs[ESP_RSTAT] = STAT_TC; - s->dma_left = 0; - s->dma_counter = 0; - if (datalen > 0) { + s->rregs[ESP_RSTAT] = 0; + if (s->dma) { + s->rregs[ESP_RSTAT] = STAT_TC; + s->dma_left = 0; + s->dma_counter = 0; + } + if (datalen > 0) { s->rregs[ESP_RSTAT] |= STAT_DI; } else { s->rregs[ESP_RSTAT] |= STAT_DO; @@ -156,40 +159,42 @@ static void do_cmd(ESPState *s, uint8_t *buf) do_busid_cmd(s, &buf[1], busid); } -static void handle_satn(ESPState *s) +static int handle_satn(ESPState *s) { uint8_t buf[32]; int len; if (s->dma && !s->dma_enabled) { s->dma_cb = handle_satn; - return; + return 1; } len = get_cmd(s, buf); if (len) do_cmd(s, buf); + return 1; } -static void handle_s_without_atn(ESPState *s) +static int handle_s_without_atn(ESPState *s) { uint8_t buf[32]; int len; if (s->dma && !s->dma_enabled) { s->dma_cb = handle_s_without_atn; - return; + return 1; } len = get_cmd(s, buf); if (len) { do_busid_cmd(s, buf, 0); } + return 1; } -static void handle_satn_stop(ESPState *s) +static int handle_satn_stop(ESPState *s) { if (s->dma && !s->dma_enabled) { s->dma_cb = handle_satn_stop; - return; + return 1; } s->cmdlen = get_cmd(s, s->cmdbuf); if (s->cmdlen) { @@ -199,6 +204,7 @@ static void handle_satn_stop(ESPState *s) s->rregs[ESP_RSEQ] = SEQ_CD; esp_raise_irq(s); } + return 1; } static void write_response(ESPState *s) @@ -231,9 +237,9 @@ static void esp_dma_done(ESPState *s) esp_raise_irq(s); } -static void esp_do_dma(ESPState *s) +static int esp_do_dma(ESPState *s) { - uint32_t len; + uint32_t len, len2; int to_device; to_device = (s->ti_size < 0); @@ -244,20 +250,23 @@ static void esp_do_dma(ESPState *s) s->cmdlen = 0; s->do_cmd = 0; do_cmd(s, s->cmdbuf); - return; + return 1; } if (s->async_len == 0) { /* Defer until data is available. */ - return; + return 1; } if (len > s->async_len) { len = s->async_len; } + len2 = len; if (to_device) { - s->dma_memory_read(s->dma_opaque, s->async_buf, len); + len = s->dma_memory_read(s->dma_opaque, s->async_buf, len2); } else { - s->dma_memory_write(s->dma_opaque, s->async_buf, len); + len = s->dma_memory_write(s->dma_opaque, s->async_buf, len2); } + if (len < 0) + len = len2; s->dma_left -= len; s->async_buf += len; s->async_len -= len; @@ -271,12 +280,16 @@ static void esp_do_dma(ESPState *s) complete the DMA operation immediately. Otherwise defer until the scsi layer has completed. */ if (to_device || s->dma_left != 0 || s->ti_size == 0) { - return; + return 1; } } + if (len2 > len && s->dma_left > 0) + return 0; + /* Partially filled a scsi buffer. Complete immediately. */ esp_dma_done(s); + return 1; } void esp_command_complete(SCSIRequest *req, uint32_t status, @@ -312,20 +325,20 @@ void esp_transfer_data(SCSIRequest *req, uint32_t len) } } -static void handle_ti(ESPState *s) +static int handle_ti(ESPState *s) { uint32_t dmalen, minlen; if (s->dma && !s->dma_enabled) { s->dma_cb = handle_ti; - return; + return 1; } dmalen = s->rregs[ESP_TCLO]; dmalen |= s->rregs[ESP_TCMID] << 8; dmalen |= s->rregs[ESP_TCHI] << 16; - if (dmalen==0) { - dmalen=0x10000; + if (dmalen == 0) { + dmalen = 0x10000; } s->dma_counter = dmalen; @@ -336,16 +349,27 @@ static void handle_ti(ESPState *s) else minlen = (dmalen < s->ti_size) ? dmalen : s->ti_size; if (s->dma) { - s->dma_left = minlen; + if (s->dma == 1) + s->dma_left = minlen; + s->dma = 2; s->rregs[ESP_RSTAT] &= ~STAT_TC; - esp_do_dma(s); + if (!esp_do_dma(s)) { + s->dma_cb = handle_ti; + return 0; + } + return 1; } else if (s->do_cmd) { s->ti_size = 0; s->cmdlen = 0; s->do_cmd = 0; do_cmd(s, s->cmdbuf); - return; - } + return 1; + } else { + // no dma + s->rregs[ESP_RINTR] = INTR_BS; + esp_raise_irq(s); + } + return 1; } void esp_hard_reset(ESPState *s) @@ -384,18 +408,25 @@ uint64_t esp_reg_read(void *opaque, uint32_t saddr) case ESP_FIFO: if (s->ti_size > 0) { s->ti_size--; - if ((s->rregs[ESP_RSTAT] & STAT_PIO_MASK) == 0) { + if ((s->rregs[ESP_RSTAT] & STAT_PIO_MASK) == 0 || s->pio_on) { /* Data out. */ - write_log("esp: PIO data read not implemented\n"); - s->rregs[ESP_FIFO] = 0; + //write_log("esp: PIO data read not implemented\n"); + s->rregs[ESP_FIFO] = s->async_buf[s->ti_rptr++]; + s->pio_on = 1; + if (s->ti_size == 1) { + scsiesp_req_continue(s->current_req); + } +// esp_command_complete(s); + //activate_debugger(); } else { s->rregs[ESP_FIFO] = s->ti_buf[s->ti_rptr++]; } - esp_raise_irq(s); + esp_raise_irq(s); } if (s->ti_size == 0) { s->ti_rptr = 0; s->ti_wptr = 0; + s->pio_on = 0; } break; case ESP_RINTR: diff --git a/qemuvga/scsi/esp.h b/qemuvga/scsi/esp.h index 221abb5c..f206fc8c 100644 --- a/qemuvga/scsi/esp.h +++ b/qemuvga/scsi/esp.h @@ -3,7 +3,7 @@ /* esp.c */ #define ESP_MAX_DEVS 7 -typedef void (*ESPDMAMemoryReadWriteFunc)(void *opaque, uint8_t *buf, int len); +typedef int (*ESPDMAMemoryReadWriteFunc)(void *opaque, uint8_t *buf, int len); void esp_init(hwaddr espaddr, int it_shift, ESPDMAMemoryReadWriteFunc dma_memory_read, ESPDMAMemoryReadWriteFunc dma_memory_write, @@ -38,6 +38,7 @@ struct ESPState { progress. */ uint32_t dma_counter; int dma_enabled; + int pio_on; uint32_t async_len; uint8_t *async_buf; @@ -45,7 +46,7 @@ struct ESPState { ESPDMAMemoryReadWriteFunc dma_memory_read; ESPDMAMemoryReadWriteFunc dma_memory_write; void *dma_opaque; - void (*dma_cb)(ESPState *s); + int (*dma_cb)(ESPState *s); }; #define ESP_TCLO 0x0