>From 4be00033adb966eb40c1ca2700cc770db0ff682a Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Thu, 26 May 2011 13:39:26 +0200 Subject: [PATCH] ahci: use interrupt status register Poll interrupt status register to figure when the device has updated the status and possibly finished the request, continue polling until BSY is clear as we might see multiple status updates per request. Signed-off-by: Gerd Hoffmann --- src/ahci.c | 23 ++++++++++++++++------- 1 files changed, 16 insertions(+), 7 deletions(-) diff --git a/src/ahci.c b/src/ahci.c index b820e28..ac3b92a 100644 --- a/src/ahci.c +++ b/src/ahci.c @@ -105,7 +105,7 @@ static void ahci_port_writel(struct ahci_ctrl_s *ctrl, u32 pnr, u32 reg, u32 val static int ahci_command(struct ahci_port_s *port, int iswrite, int isatapi, void *buffer, u32 bsize) { - u32 val, status, success, flags; + u32 val, status, success, flags, intbits; struct ahci_ctrl_s *ctrl = GET_GLOBAL(port->ctrl); struct ahci_cmd_s *cmd = GET_GLOBAL(port->cmd); struct ahci_fis_s *fis = GET_GLOBAL(port->fis); @@ -136,14 +136,23 @@ static int ahci_command(struct ahci_port_s *port, int iswrite, int isatapi, dprintf(2, "AHCI/%d: send cmd ...\n", pnr); SET_FLATPTR(fis->rfis[2], 0); + intbits = ahci_port_readl(ctrl, pnr, PORT_IRQ_STAT); + ahci_port_writel(ctrl, pnr, PORT_IRQ_STAT, intbits); ahci_port_writel(ctrl, pnr, PORT_SCR_ACT, 1); ahci_port_writel(ctrl, pnr, PORT_CMD_ISSUE, 1); - while (ahci_port_readl(ctrl, pnr, PORT_CMD_ISSUE)) { - yield(); - } - while ((status = GET_FLATPTR(fis->rfis[2])) == 0) { - yield(); - } + + do { + for (;;) { + intbits = ahci_port_readl(ctrl, pnr, PORT_IRQ_STAT); + ahci_port_writel(ctrl, pnr, PORT_IRQ_STAT, intbits); + if (intbits & 0x01) + break; + yield(); + } + status = GET_FLATPTR(fis->rfis[2]); + dprintf(2, "AHCI/%d: ... intbits 0x%x, status 0x%x ...\n", + pnr, intbits, status); + } while (status & ATA_CB_STAT_BSY); success = (0x00 == (status & (ATA_CB_STAT_BSY | ATA_CB_STAT_DF | ATA_CB_STAT_DRQ | ATA_CB_STAT_ERR)) && -- 1.7.1