esp.c: separate logic based upon ESP command in esp_command_complete()

The handling of the INTR_FC and INTR_BS bits is different depending upon the
last command executed by the ESP. Note that currently INTR_FC is managed
elsewhere, but that will change soon.

Signed-off-by: Mark Cave-Ayland <mark.cave-ayland@ilande.co.uk>
Tested-by: Helge Deller <deller@gmx.de>
Tested-by: Thomas Huth <thuth@redhat.com>
Message-Id: <20240112125420.514425-59-mark.cave-ayland@ilande.co.uk>
Signed-off-by: Mark Cave-Ayland <mark.cave-ayland@ilande.co.uk>
This commit is contained in:
Mark Cave-Ayland 2024-01-12 12:53:50 +00:00
parent 8dded6de15
commit 8bb2249585
1 changed files with 16 additions and 14 deletions

View File

@ -823,25 +823,27 @@ void esp_command_complete(SCSIRequest *req, size_t resid)
* Switch to status phase. For non-DMA transfers from the target the last
* byte is still in the FIFO
*/
esp_set_phase(s, STAT_ST);
if (s->ti_size == 0) {
s->ti_size = 0;
switch (s->rregs[ESP_CMD]) {
case CMD_SEL | CMD_DMA:
case CMD_SEL:
case CMD_SELATN | CMD_DMA:
case CMD_SELATN:
/*
* Transfer complete: force TC to zero just in case a TI command was
* requested for more data than the command returns (Solaris 8 does
* this)
*/
esp_set_tc(s, 0);
esp_dma_ti_check(s);
} else {
/*
* Transfer truncated: raise INTR_BS to indicate early change of
* phase
* No data phase for sequencer command so raise deferred bus service
* interrupt
*/
s->rregs[ESP_RINTR] |= INTR_BS;
esp_raise_irq(s);
s->ti_size = 0;
break;
}
/* Raise bus service interrupt to indicate change to STATUS phase */
esp_set_phase(s, STAT_ST);
s->rregs[ESP_RINTR] |= INTR_BS;
esp_raise_irq(s);
esp_lower_drq(s);
if (s->current_req) {
scsi_req_unref(s->current_req);
s->current_req = NULL;