aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMark Cave-Ayland <mark.cave-ayland@ilande.co.uk>2024-09-13 22:36:19 +0100
committerMark Cave-Ayland <mark.cave-ayland@ilande.co.uk>2024-09-13 22:53:17 +0100
commit56fa1b2a72c71bc8aae0ac8599160ccdd1c77668 (patch)
treee612737518676bccbe2f851edaa7671af2214977
parent71bb3bf1312ad968e659a41970fab3c9ba89c4fa (diff)
downloadopenbios-56fa1b2a72c71bc8aae0ac8599160ccdd1c77668.zip
openbios-56fa1b2a72c71bc8aae0ac8599160ccdd1c77668.tar.gz
openbios-56fa1b2a72c71bc8aae0ac8599160ccdd1c77668.tar.bz2
esp: use ESP rather than DMA interrupt to detect end of transfer
Rather than rely on the DMA interrupt to determine that an ESP interrupt has occurred, poll the ESP interrupt register directly. This enables us to poll until one of the specified interrupts occurs. Since an ESP interrupt can still be in a pending state before issuing an ESP command, read the ESP interrupt register beforehand to clear any pending interrupts. Signed-off-by: Mark Cave-Ayland <mark.cave-ayland@ilande.co.uk>
-rw-r--r--drivers/esp.c16
1 files changed, 8 insertions, 8 deletions
diff --git a/drivers/esp.c b/drivers/esp.c
index 95e969f..5c7ddb5 100644
--- a/drivers/esp.c
+++ b/drivers/esp.c
@@ -99,14 +99,14 @@ do_command(esp_private_t *esp, sd_private_t *sd, int cmdlen, int replylen)
esp->espdma.regs->cond_reg = DMA_ENABLE;
// Clear FIFO
esp->ll->regs[ESP_CMD] = ESP_CMD_FLUSH;
+ // Clear pending interrupts
+ (void)esp->ll->regs[ESP_INTRPT];
// Set ATN, issue command
esp->ll->regs[ESP_CMD] = ESP_CMD_SELA | ESP_CMD_DMA;
- // Wait for DMA to complete. Can this fail?
- while ((esp->espdma.regs->cond_reg & DMA_HNDL_INTR) == 0) /* no-op */;
+ // Wait for ESP to complete
+ while (!(esp->ll->regs[ESP_INTRPT] & (ESP_INTR_BSERV | ESP_INTR_FDONE | ESP_INTR_DC)));
// Check status
status = esp->ll->regs[ESP_STATUS];
- // Clear interrupts to avoid guests seeing spurious interrupts
- (void)esp->ll->regs[ESP_INTRPT];
DPRINTF("do_command: id %d, cmd[0] 0x%x, status 0x%x\n", sd->id, esp->buffer[1], status);
@@ -130,14 +130,14 @@ do_command(esp_private_t *esp, sd_private_t *sd, int cmdlen, int replylen)
esp->ll->regs[ESP_TCMED] = (replylen >> 8) & 0xff;
// Set DMA direction
esp->espdma.regs->cond_reg = DMA_ST_WRITE | DMA_ENABLE;
+ // Clear pending interrupts
+ (void)esp->ll->regs[ESP_INTRPT];
// Transfer
esp->ll->regs[ESP_CMD] = ESP_CMD_TI | ESP_CMD_DMA;
- // Wait for DMA to complete
- while ((esp->espdma.regs->cond_reg & DMA_HNDL_INTR) == 0) /* no-op */;
+ // Wait for ESP to complete
+ while (!(esp->ll->regs[ESP_INTRPT] & (ESP_INTR_BSERV | ESP_INTR_FDONE | ESP_INTR_DC)));
// Check status
status = esp->ll->regs[ESP_STATUS];
- // Clear interrupts to avoid guests seeing spurious interrupts
- (void)esp->ll->regs[ESP_INTRPT];
DPRINTF("do_command_reply: status 0x%x\n", status);