static void esp_command_complete(SCSIBus *bus, int reason, uint32_t tag, uint32_t arg) { ESPState *s = DO_UPCAST(ESPState, busdev.qdev, bus->qbus.parent); if (reason == SCSI_REASON_DONE) { DPRINTF("SCSI Command complete\n"); if (s->ti_size != 0) DPRINTF("SCSI command completed unexpectedly\n"); s->ti_size = 0; s->dma_left = 0; s->async_len = 0; if (arg) DPRINTF("Command failed\n"); s->sense = arg; s->rregs[ESP_RSTAT] = STAT_ST; esp_dma_done(s); s->current_dev = NULL; } else { DPRINTF("transfer %d/%d\n", s->dma_left, s->ti_size); s->async_len = arg; s->async_buf = s->current_dev->info->get_buf(s->current_dev, 0); if (s->dma_left) { esp_do_dma(s); } else if (s->dma_counter != 0 && s->ti_size <= 0) { /* If this was the last part of a DMA transfer then the completion interrupt is deferred to here. */ esp_dma_done(s); } } }
static void esp_do_dma(ESPState *s) { uint32_t len; int to_device; to_device = (s->ti_size < 0); len = s->dma_left; if (s->do_cmd) { DPRINTF("command len %d + %d\n", s->cmdlen, len); s->dma_memory_read(s->dma_opaque, &s->cmdbuf[s->cmdlen], len); s->ti_size = 0; s->cmdlen = 0; s->do_cmd = 0; do_cmd(s, s->cmdbuf); return; } if (s->async_len == 0) { /* Defer until data is available. */ return; } if (len > s->async_len) { len = s->async_len; } if (to_device) { s->dma_memory_read(s->dma_opaque, s->async_buf, len); } else { s->dma_memory_write(s->dma_opaque, s->async_buf, len); } s->dma_left -= len; s->async_buf += len; s->async_len -= len; if (to_device) s->ti_size += len; else s->ti_size -= len; if (s->async_len == 0) { if (to_device) { // ti_size is negative s->current_dev->info->write_data(s->current_dev, 0); } else { s->current_dev->info->read_data(s->current_dev, 0); /* If there is still data to be read from the device then complete the DMA operation immediately. Otherwise defer until the scsi layer has completed. */ if (s->dma_left == 0 && s->ti_size > 0) { esp_dma_done(s); } } } else { /* Partially filled a scsi buffer. Complete immediately. */ esp_dma_done(s); } }
static int esp_do_dma(ESPState *s) { int len, len2; int to_device; to_device = (s->ti_size < 0); len = s->dma_left; if (s->do_cmd) { s->dma_memory_read(s->dma_opaque, &s->cmdbuf[s->cmdlen], len); s->ti_size = 0; s->cmdlen = 0; s->do_cmd = 0; do_cmd(s, s->cmdbuf); return 1; } if (s->async_len == 0) { /* Defer until data is available. */ return 1; } if (len > s->async_len) { len = s->async_len; } len2 = len; if (to_device) { len = s->dma_memory_read(s->dma_opaque, s->async_buf, len2); } else { 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; if (to_device) s->ti_size += len; else s->ti_size -= len; if (s->async_len == 0) { scsiesp_req_continue(s->current_req); /* If there is still data to be read from the device then 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 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_transfer_data(SCSIRequest *req, uint32_t len) { ESPState *s = (ESPState*)req->hba_private; s->async_len = len; s->async_buf = scsiesp_req_get_buf(req); if (s->dma_left) { esp_do_dma(s); } else if (s->dma_counter != 0 && s->ti_size == 0) { /* If this was the last part of a DMA transfer then the completion interrupt is deferred to here. */ esp_dma_done(s); } }
static void esp_transfer_data(SCSIRequest *req, uint32_t len) { ESPState *s = DO_UPCAST(ESPState, busdev.qdev, req->bus->qbus.parent); trace_esp_transfer_data(s->dma_left, s->ti_size); s->async_len = len; s->async_buf = scsi_req_get_buf(req); if (s->dma_left) { esp_do_dma(s); } else if (s->dma_counter != 0 && s->ti_size <= 0) { /* If this was the last part of a DMA transfer then the completion interrupt is deferred to here. */ esp_dma_done(s); } }
void esp_command_complete(SCSIRequest *req, uint32_t status, size_t resid) { ESPState *s = (ESPState*)req->hba_private; s->ti_size = 0; s->dma_left = 0; s->async_len = 0; s->status = status; s->rregs[ESP_RSTAT] = STAT_ST; esp_dma_done(s); if (s->current_req) { scsiesp_req_unref(s->current_req); s->current_req = NULL; s->current_dev = NULL; } }
static void esp_do_dma(ESPState *s) { uint32_t len; int to_device; len = s->dma_left; if (s->do_cmd) { trace_esp_do_dma(s->cmdlen, len); assert (s->cmdlen <= sizeof(s->cmdbuf) && len <= sizeof(s->cmdbuf) - s->cmdlen); s->dma_memory_read(s->dma_opaque, &s->cmdbuf[s->cmdlen], len); return; } if (s->async_len == 0) { /* Defer until data is available. */ return; } if (len > s->async_len) { len = s->async_len; } to_device = (s->ti_size < 0); if (to_device) { s->dma_memory_read(s->dma_opaque, s->async_buf, len); } else { s->dma_memory_write(s->dma_opaque, s->async_buf, len); } s->dma_left -= len; s->async_buf += len; s->async_len -= len; if (to_device) s->ti_size += len; else s->ti_size -= len; if (s->async_len == 0) { scsi_req_continue(s->current_req); /* If there is still data to be read from the device then 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; } } /* Partially filled a scsi buffer. Complete immediately. */ esp_dma_done(s); }
static void esp_command_complete(SCSIRequest *req, uint32_t status) { ESPState *s = DO_UPCAST(ESPState, busdev.qdev, req->bus->qbus.parent); trace_esp_command_complete(); if (s->ti_size != 0) { trace_esp_command_complete_unexpected(); } s->ti_size = 0; s->dma_left = 0; s->async_len = 0; if (status) { trace_esp_command_complete_fail(); } s->status = status; s->rregs[ESP_RSTAT] = STAT_ST; esp_dma_done(s); if (s->current_req) { scsi_req_unref(s->current_req); s->current_req = NULL; s->current_dev = NULL; } }
void esp_command_complete(SCSIRequest *req, uint32_t status, size_t resid) { ESPState *s = req->hba_private; trace_esp_command_complete(); if (s->ti_size != 0) { trace_esp_command_complete_unexpected(); } s->ti_size = 0; s->dma_left = 0; s->async_len = 0; if (status) { trace_esp_command_complete_fail(); } s->status = status; s->rregs[ESP_RSTAT] = STAT_ST; esp_dma_done(s); if (s->current_req) { scsi_req_unref(s->current_req); s->current_req = NULL; s->current_dev = NULL; } }