diff options
author | Mark Cave-Ayland <mark.cave-ayland@ilande.co.uk> | 2024-09-13 22:36:19 +0100 |
---|---|---|
committer | Mark Cave-Ayland <mark.cave-ayland@ilande.co.uk> | 2024-09-13 22:53:17 +0100 |
commit | 56fa1b2a72c71bc8aae0ac8599160ccdd1c77668 (patch) | |
tree | e612737518676bccbe2f851edaa7671af2214977 | |
parent | 71bb3bf1312ad968e659a41970fab3c9ba89c4fa (diff) | |
download | openbios-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.c | 16 |
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); |