summaryrefslogtreecommitdiffstats
path: root/sys/dev/siis/siis.c
diff options
context:
space:
mode:
authormav <mav@FreeBSD.org>2009-10-23 21:33:26 +0000
committermav <mav@FreeBSD.org>2009-10-23 21:33:26 +0000
commited25b398103473db0271f27026338e782a033374 (patch)
tree410371259558c98ba077e3fb0a582336d1af8a07 /sys/dev/siis/siis.c
parent0b8763c6075a12452406c521d0750710d76199a1 (diff)
downloadFreeBSD-src-ed25b398103473db0271f27026338e782a033374.zip
FreeBSD-src-ed25b398103473db0271f27026338e782a033374.tar.gz
Reimplement device reset sequence in more controller-specific way.
Diffstat (limited to 'sys/dev/siis/siis.c')
-rw-r--r--sys/dev/siis/siis.c72
1 files changed, 34 insertions, 38 deletions
diff --git a/sys/dev/siis/siis.c b/sys/dev/siis/siis.c
index 2077137..0529f2a 100644
--- a/sys/dev/siis/siis.c
+++ b/sys/dev/siis/siis.c
@@ -80,7 +80,6 @@ static void siis_portinit(device_t dev);
static int siis_wait_ready(device_t dev, int t);
static int siis_sata_connect(struct siis_channel *ch);
-static int siis_sata_phy_reset(device_t dev);
static void siis_issue_read_log(device_t dev);
static void siis_process_read_log(device_t dev, union ccb *ccb);
@@ -1250,16 +1249,27 @@ siis_portinit(device_t dev)
siis_wait_ready(dev, 1000);
}
-#if 0
-static void
+static int
siis_devreset(device_t dev)
{
struct siis_channel *ch = device_get_softc(dev);
+ int timeout = 0;
+ uint32_t val;
ATA_OUTL(ch->r_mem, SIIS_P_CTLSET, SIIS_P_CTL_DEV_RESET);
- siis_wait_ready(dev, 1000);
+ while (((val = ATA_INL(ch->r_mem, SIIS_P_STS)) &
+ SIIS_P_CTL_DEV_RESET) != 0) {
+ DELAY(1000);
+ if (timeout++ > 100) {
+ device_printf(dev, "device reset stuck (timeout %dms) "
+ "status = %08x\n", timeout, val);
+ return (EBUSY);
+ }
+ }
+ if (bootverbose)
+ device_printf(dev, "device reset time=%dms\n", timeout);
+ return (0);
}
-#endif
static int
siis_wait_ready(device_t dev, int t)
@@ -1287,6 +1297,7 @@ siis_reset(device_t dev)
{
struct siis_channel *ch = device_get_softc(dev);
int i;
+ uint32_t val;
if (bootverbose)
device_printf(dev, "SIIS reset...\n");
@@ -1303,10 +1314,7 @@ siis_reset(device_t dev)
}
xpt_done(fccb);
}
- /* Disable port interrupts */
- ATA_OUTL(ch->r_mem, SIIS_P_IECLR, 0x0000FFFF);
- /* Kill the engine and requeue all running commands. */
- siis_portinit(dev);
+ /* Requeue all running commands. */
for (i = 0; i < SIIS_MAX_SLOTS; i++) {
/* Do we have a running request on slot? */
if (ch->slot[i].state < SIIS_SLOT_RUNNING)
@@ -1314,8 +1322,23 @@ siis_reset(device_t dev)
/* XXX; Commands in loading state. */
siis_end_transaction(&ch->slot[i], SIIS_ERR_INNOCENT);
}
+ /* Disable port interrupts */
+ ATA_OUTL(ch->r_mem, SIIS_P_IECLR, 0x0000FFFF);
+ /* Set speed limit. */
+ if (ch->sata_rev == 1)
+ val = ATA_SC_SPD_SPEED_GEN1;
+ else if (ch->sata_rev == 2)
+ val = ATA_SC_SPD_SPEED_GEN2;
+ else if (ch->sata_rev == 3)
+ val = ATA_SC_SPD_SPEED_GEN3;
+ else
+ val = 0;
+ ATA_OUTL(ch->r_mem, SIIS_P_SCTL,
+ ATA_SC_DET_IDLE | val | ((ch->pm_level > 0) ? 0 :
+ (ATA_SC_IPM_DIS_PARTIAL | ATA_SC_IPM_DIS_SLUMBER)));
+ siis_devreset(dev);
/* Reset and reconnect PHY, */
- if (!siis_sata_phy_reset(dev)) {
+ if (!siis_sata_connect(ch)) {
ch->devices = 0;
/* Enable port interrupts */
ATA_OUTL(ch->r_mem, SIIS_P_IESET, SIIS_P_IX_ENABLED);
@@ -1327,9 +1350,8 @@ siis_reset(device_t dev)
return;
}
/* Wait for clearing busy status. */
- if (siis_wait_ready(dev, 10000)) {
+ if (siis_wait_ready(dev, 10000))
device_printf(dev, "device ready timeout\n");
- }
ch->devices = 1;
/* Enable port interrupts */
ATA_OUTL(ch->r_mem, SIIS_P_IS, 0xFFFFFFFF);
@@ -1420,32 +1442,6 @@ siis_sata_connect(struct siis_channel *ch)
return (1);
}
-static int
-siis_sata_phy_reset(device_t dev)
-{
- struct siis_channel *ch = device_get_softc(dev);
- uint32_t val;
-
- if (bootverbose)
- device_printf(dev, "hardware reset ...\n");
- ATA_OUTL(ch->r_mem, SIIS_P_SCTL, ATA_SC_IPM_DIS_PARTIAL |
- ATA_SC_IPM_DIS_SLUMBER | ATA_SC_DET_RESET);
- DELAY(50000);
- if (ch->sata_rev == 1)
- val = ATA_SC_SPD_SPEED_GEN1;
- else if (ch->sata_rev == 2)
- val = ATA_SC_SPD_SPEED_GEN2;
- else if (ch->sata_rev == 3)
- val = ATA_SC_SPD_SPEED_GEN3;
- else
- val = 0;
- ATA_OUTL(ch->r_mem, SIIS_P_SCTL,
- ATA_SC_DET_IDLE | val | ((ch->pm_level > 0) ? 0 :
- (ATA_SC_IPM_DIS_PARTIAL | ATA_SC_IPM_DIS_SLUMBER)));
- DELAY(50000);
- return (siis_sata_connect(ch));
-}
-
static void
siisaction(struct cam_sim *sim, union ccb *ccb)
{
OpenPOWER on IntegriCloud