Add FIS-based switching support. If controller supports FBS, it allows

several devices beyond Port Multiplier to work simultaneously, substantially
increasing performance.
This commit is contained in:
mav 2010-01-28 17:54:47 +00:00
parent f0928fee72
commit 39c73ee5aa
2 changed files with 212 additions and 53 deletions

View File

@ -78,7 +78,7 @@ static void ahci_dmafini(device_t dev);
static void ahci_slotsalloc(device_t dev);
static void ahci_slotsfree(device_t dev);
static void ahci_reset(device_t dev);
static void ahci_start(device_t dev);
static void ahci_start(device_t dev, int fbs);
static void ahci_stop(device_t dev);
static void ahci_clo(device_t dev);
static void ahci_start_fr(device_t dev);
@ -86,6 +86,7 @@ static void ahci_stop_fr(device_t dev);
static int ahci_sata_connect(struct ahci_channel *ch);
static int ahci_sata_phy_reset(device_t dev);
static int ahci_wait_ready(device_t dev, int t);
static void ahci_issue_read_log(device_t dev);
static void ahci_process_read_log(device_t dev, union ccb *ccb);
@ -108,6 +109,7 @@ static struct {
#define AHCI_Q_4CH 32
#define AHCI_Q_EDGEIS 64
#define AHCI_Q_SATA2 128
#define AHCI_Q_NOBSYRES 256
} ahci_ids[] = {
{0x43801002, 0x00, "ATI IXP600", 0},
{0x43901002, 0x00, "ATI IXP700", 0},
@ -162,8 +164,8 @@ static struct {
{0x612111ab, 0x00, "Marvell 88SX6121", AHCI_Q_NOFORCE|AHCI_Q_2CH|AHCI_Q_EDGEIS},
{0x614111ab, 0x00, "Marvell 88SX6141", AHCI_Q_NOFORCE|AHCI_Q_4CH|AHCI_Q_EDGEIS},
{0x614511ab, 0x00, "Marvell 88SX6145", AHCI_Q_NOFORCE|AHCI_Q_4CH|AHCI_Q_EDGEIS},
{0x91231b4b, 0x11, "Marvell 88SE912x", 0},
{0x91231b4b, 0x00, "Marvell 88SE912x", AHCI_Q_EDGEIS|AHCI_Q_SATA2},
{0x91231b4b, 0x11, "Marvell 88SE912x", AHCI_Q_NOBSYRES},
{0x91231b4b, 0x00, "Marvell 88SE912x", AHCI_Q_EDGEIS|AHCI_Q_SATA2|AHCI_Q_NOBSYRES},
{0x044c10de, 0x00, "NVIDIA MCP65", 0},
{0x044d10de, 0x00, "NVIDIA MCP65", 0},
{0x044e10de, 0x00, "NVIDIA MCP65", 0},
@ -379,14 +381,16 @@ ahci_attach(device_t dev)
/* Announce HW capabilities. */
speed = (ctlr->caps & AHCI_CAP_ISS) >> AHCI_CAP_ISS_SHIFT;
device_printf(dev,
"AHCI v%x.%02x with %d %sGbps ports, Port Multiplier %s\n",
"AHCI v%x.%02x with %d %sGbps ports, Port Multiplier %s%s\n",
((version >> 20) & 0xf0) + ((version >> 16) & 0x0f),
((version >> 4) & 0xf0) + (version & 0x0f),
(ctlr->caps & AHCI_CAP_NPMASK) + 1,
((speed == 1) ? "1.5":((speed == 2) ? "3":
((speed == 3) ? "6":"?"))),
(ctlr->caps & AHCI_CAP_SPM) ?
"supported" : "not supported");
"supported" : "not supported",
(ctlr->caps & AHCI_CAP_FBSS) ?
" with FBS" : "");
if (bootverbose) {
device_printf(dev, "Caps:%s%s%s%s%s%s%s%s %sGbps",
(ctlr->caps & AHCI_CAP_64BIT) ? " 64bit":"",
@ -419,7 +423,7 @@ ahci_attach(device_t dev)
(ctlr->caps2 & AHCI_CAP2_BOH) ? " BOH":"");
}
if (bootverbose && (ctlr->caps & AHCI_CAP_EMS)) {
device_printf(dev, "EM Caps: %s%s%s%s%s%s%s%s\n",
device_printf(dev, "EM Caps:%s%s%s%s%s%s%s%s\n",
(ctlr->capsem & AHCI_EM_PM) ? " PM":"",
(ctlr->capsem & AHCI_EM_ALHD) ? " ALHD":"",
(ctlr->capsem & AHCI_EM_XMT) ? " XMT":"",
@ -810,6 +814,7 @@ ahci_ch_attach(device_t dev)
struct ahci_channel *ch = device_get_softc(dev);
struct cam_devq *devq;
int rid, error, i, sata_rev = 0;
u_int32_t version;
ch->dev = dev;
ch->unit = (intptr_t)device_get_ivars(dev);
@ -861,6 +866,18 @@ ahci_ch_attach(device_t dev)
error = ENXIO;
goto err1;
}
ch->chcaps = ATA_INL(ch->r_mem, AHCI_P_CMD);
version = ATA_INL(ctlr->r_mem, AHCI_VS);
if (version < 0x00010020 && (ctlr->caps & AHCI_CAP_FBSS))
ch->chcaps |= AHCI_P_CMD_FBSCP;
if (bootverbose) {
device_printf(dev, "Caps:%s%s%s%s%s\n",
(ch->chcaps & AHCI_P_CMD_HPCP) ? " HPCP":"",
(ch->chcaps & AHCI_P_CMD_MPSP) ? " MPSP":"",
(ch->chcaps & AHCI_P_CMD_CPD) ? " CPD":"",
(ch->chcaps & AHCI_P_CMD_ESP) ? " ESP":"",
(ch->chcaps & AHCI_P_CMD_FBSCP) ? " FBSCP":"");
}
/* Create the device queue for our SIM. */
devq = cam_simq_alloc(ch->numslots);
if (devq == NULL) {
@ -977,7 +994,7 @@ ahci_ch_resume(device_t dev)
((ch->pm_level == 2 || ch->pm_level == 3) ? AHCI_P_CMD_ALPE : 0) |
((ch->pm_level > 2) ? AHCI_P_CMD_ASP : 0 )));
ahci_start_fr(dev);
ahci_start(dev);
ahci_start(dev, 1);
return (0);
}
@ -1007,6 +1024,7 @@ ahci_dmainit(device_t dev)
{
struct ahci_channel *ch = device_get_softc(dev);
struct ahci_dc_cb_args dcba;
size_t rfsize;
if (ch->caps & AHCI_CAP_64BIT)
ch->dma.max_address = BUS_SPACE_MAXADDR;
@ -1028,16 +1046,20 @@ ahci_dmainit(device_t dev)
}
ch->dma.work_bus = dcba.maddr;
/* FIS receive area. */
if (bus_dma_tag_create(bus_get_dma_tag(dev), 4096, 0,
if (ch->chcaps & AHCI_P_CMD_FBSCP)
rfsize = 4096;
else
rfsize = 256;
if (bus_dma_tag_create(bus_get_dma_tag(dev), rfsize, 0,
ch->dma.max_address, BUS_SPACE_MAXADDR,
NULL, NULL, 4096, 1, 4096,
NULL, NULL, rfsize, 1, rfsize,
0, NULL, NULL, &ch->dma.rfis_tag))
goto error;
if (bus_dmamem_alloc(ch->dma.rfis_tag, (void **)&ch->dma.rfis, 0,
&ch->dma.rfis_map))
goto error;
if (bus_dmamap_load(ch->dma.rfis_tag, ch->dma.rfis_map, ch->dma.rfis,
4096, ahci_dmasetupc_cb, &dcba, 0) || dcba.error) {
rfsize, ahci_dmasetupc_cb, &dcba, 0) || dcba.error) {
bus_dmamem_free(ch->dma.rfis_tag, ch->dma.rfis, ch->dma.rfis_map);
goto error;
}
@ -1225,7 +1247,7 @@ ahci_ch_intr(void *data)
struct ahci_channel *ch = device_get_softc(dev);
uint32_t istatus, sstatus, cstatus, serr = 0, sntf = 0, ok, err;
enum ahci_err_type et;
int i, ccs, ncq_err = 0;
int i, ccs, port;
/* Read and clear interrupt statuses. */
istatus = ATA_INL(ch->r_mem, AHCI_P_IS);
@ -1238,7 +1260,17 @@ ahci_ch_intr(void *data)
if (istatus & AHCI_P_IX_SDB) {
if (ch->caps & AHCI_CAP_SSNTF)
sntf = ATA_INL(ch->r_mem, AHCI_P_SNTF);
else {
else if (ch->fbs_enabled) {
u_int8_t *fis = ch->dma.rfis + 0x58;
for (i = 0; i < 16; i++) {
if (fis[1] & 0x80) {
fis[1] &= 0x7f;
sntf |= 1 << i;
}
fis += 256;
}
} else {
u_int8_t *fis = ch->dma.rfis + 0x58;
if (fis[1] & 0x80)
@ -1257,18 +1289,35 @@ ahci_ch_intr(void *data)
/* Process command errors */
if (istatus & (AHCI_P_IX_OF | AHCI_P_IX_IF |
AHCI_P_IX_HBD | AHCI_P_IX_HBF | AHCI_P_IX_TFE)) {
//device_printf(dev, "%s ERROR is %08x cs %08x ss %08x rs %08x tfd %02x serr %08x\n",
// __func__, istatus, cstatus, sstatus, ch->rslots, ATA_INL(ch->r_mem, AHCI_P_TFD),
// serr);
ccs = (ATA_INL(ch->r_mem, AHCI_P_CMD) & AHCI_P_CMD_CCS_MASK)
>> AHCI_P_CMD_CCS_SHIFT;
//device_printf(dev, "%s ERROR is %08x cs %08x ss %08x rs %08x tfd %02x serr %08x fbs %08x ccs %d\n",
// __func__, istatus, cstatus, sstatus, ch->rslots, ATA_INL(ch->r_mem, AHCI_P_TFD),
// serr, ATA_INL(ch->r_mem, AHCI_P_FBS), ccs);
port = -1;
if (ch->fbs_enabled) {
uint32_t fbs = ATA_INL(ch->r_mem, AHCI_P_FBS);
if (fbs & AHCI_P_FBS_SDE) {
port = (fbs & AHCI_P_FBS_DWE)
>> AHCI_P_FBS_DWE_SHIFT;
} else {
for (i = 0; i < 16; i++) {
if (ch->numrslotspd[i] == 0)
continue;
if (port == -1)
port = i;
else if (port != i) {
port = -2;
break;
}
}
}
}
err = ch->rslots & (cstatus | sstatus);
/* Kick controller into sane state */
ahci_stop(dev);
ahci_start(dev);
} else {
ccs = 0;
err = 0;
port = -1;
}
/* Complete all successfull commands. */
ok = ch->rslots & ~(cstatus | sstatus);
@ -1292,9 +1341,14 @@ ahci_ch_intr(void *data)
/* XXX: reqests in loading state. */
if (((err >> i) & 1) == 0)
continue;
if (port >= 0 &&
ch->slot[i].ccb->ccb_h.target_id != port)
continue;
if (istatus & AHCI_P_IX_TFE) {
if (port != -2) {
/* Task File Error */
if (ch->numtslots == 0) {
if (ch->numtslotspd[
ch->slot[i].ccb->ccb_h.target_id] == 0) {
/* Untagged operation. */
if (i == ccs)
et = AHCI_ERR_TFE;
@ -1303,10 +1357,13 @@ ahci_ch_intr(void *data)
} else {
/* Tagged operation. */
et = AHCI_ERR_NCQ;
ncq_err = 1;
}
} else {
et = AHCI_ERR_TFE;
ch->fatalerr = 1;
}
} else if (istatus & AHCI_P_IX_IF) {
if (ch->numtslots == 0 && i != ccs)
if (ch->numtslots == 0 && i != ccs && port != -2)
et = AHCI_ERR_INNOCENT;
else
et = AHCI_ERR_SATA;
@ -1314,8 +1371,12 @@ ahci_ch_intr(void *data)
et = AHCI_ERR_INVALID;
ahci_end_transaction(&ch->slot[i], et);
}
if (ncq_err)
ahci_issue_read_log(dev);
/*
* We can't reinit port if there are some other
* commands active, use resume to complete them.
*/
if (ch->rslots != 0)
ATA_OUTL(ch->r_mem, AHCI_P_FBS, AHCI_P_FBS_EN | AHCI_P_FBS_DEC);
}
/* Process NOTIFY events */
if (sntf)
@ -1327,24 +1388,39 @@ static int
ahci_check_collision(device_t dev, union ccb *ccb)
{
struct ahci_channel *ch = device_get_softc(dev);
int t = ccb->ccb_h.target_id;
if ((ccb->ccb_h.func_code == XPT_ATA_IO) &&
(ccb->ataio.cmd.flags & CAM_ATAIO_FPDMA)) {
/* Tagged command while untagged are active. */
if (ch->numrslots != 0 && ch->numtslots == 0)
return (1);
/* Tagged command while tagged to other target is active. */
if (ch->numtslots != 0 &&
ch->taggedtarget != ccb->ccb_h.target_id)
return (1);
/* Tagged command while we have no supported tag free. */
if (((~ch->oslots) & (0xffffffff >> (32 -
ch->curr[ccb->ccb_h.target_id].tags))) == 0)
ch->curr[t].tags))) == 0)
return (1);
/* If we have FBS */
if (ch->fbs_enabled) {
/* Tagged command while untagged are active. */
if (ch->numrslotspd[t] != 0 && ch->numtslotspd[t] == 0)
return (1);
} else {
/* Tagged command while untagged are active. */
if (ch->numrslots != 0 && ch->numtslots == 0)
return (1);
/* Tagged command while tagged to other target is active. */
if (ch->numtslots != 0 &&
ch->taggedtarget != ccb->ccb_h.target_id)
return (1);
}
} else {
/* Untagged command while tagged are active. */
if (ch->numrslots != 0 && ch->numtslots != 0)
return (1);
/* If we have FBS */
if (ch->fbs_enabled) {
/* Untagged command while tagged are active. */
if (ch->numrslotspd[t] != 0 && ch->numtslotspd[t] != 0)
return (1);
} else {
/* Untagged command while tagged are active. */
if (ch->numrslots != 0 && ch->numtslots != 0)
return (1);
}
}
if ((ccb->ccb_h.func_code == XPT_ATA_IO) &&
(ccb->ataio.cmd.flags & (CAM_ATAIO_CONTROL | CAM_ATAIO_NEEDRESULT))) {
@ -1389,9 +1465,11 @@ ahci_begin_transaction(device_t dev, union ccb *ccb)
/* Update channel stats. */
ch->oslots |= (1 << slot->slot);
ch->numrslots++;
ch->numrslotspd[ccb->ccb_h.target_id]++;
if ((ccb->ccb_h.func_code == XPT_ATA_IO) &&
(ccb->ataio.cmd.flags & CAM_ATAIO_FPDMA)) {
ch->numtslots++;
ch->numtslotspd[ccb->ccb_h.target_id]++;
ch->taggedtarget = ccb->ccb_h.target_id;
}
if ((ccb->ccb_h.func_code == XPT_ATA_IO) &&
@ -1459,7 +1537,9 @@ ahci_execute_transaction(struct ahci_slot *slot)
struct ahci_cmd_list *clp;
union ccb *ccb = slot->ccb;
int port = ccb->ccb_h.target_id & 0x0f;
int fis_size;
int fis_size, i;
uint8_t *fis = ch->dma.rfis + 0x40;
uint8_t val;
/* Get a piece of the workspace for this request */
ctp = (struct ahci_cmd_tab *)
@ -1481,13 +1561,18 @@ ahci_execute_transaction(struct ahci_slot *slot)
(port << 12);
/* Special handling for Soft Reset command. */
if ((ccb->ccb_h.func_code == XPT_ATA_IO) &&
(ccb->ataio.cmd.flags & CAM_ATAIO_CONTROL) &&
(ccb->ataio.cmd.control & ATA_A_RESET)) {
/* Kick controller into sane state */
ahci_stop(dev);
ahci_clo(dev);
ahci_start(dev);
clp->cmd_flags |= AHCI_CMD_RESET | AHCI_CMD_CLR_BUSY;
(ccb->ataio.cmd.flags & CAM_ATAIO_CONTROL)) {
if (ccb->ataio.cmd.control & ATA_A_RESET) {
/* Kick controller into sane state */
ahci_stop(dev);
ahci_clo(dev);
ahci_start(dev, 0);
clp->cmd_flags |= AHCI_CMD_RESET | AHCI_CMD_CLR_BUSY;
} else {
/* Prepare FIS receive area for check. */
for (i = 0; i < 20; i++)
fis[i] = 0xff;
}
}
clp->bytecount = 0;
clp->cmd_table_phys = htole64(ch->dma.work_bus + AHCI_CT_OFFSET +
@ -1501,6 +1586,11 @@ ahci_execute_transaction(struct ahci_slot *slot)
(ccb->ataio.cmd.flags & CAM_ATAIO_FPDMA)) {
ATA_OUTL(ch->r_mem, AHCI_P_SACT, 1 << slot->slot);
}
/* If FBS is enabled, set PMP port. */
if (ch->fbs_enabled) {
ATA_OUTL(ch->r_mem, AHCI_P_FBS, AHCI_P_FBS_EN |
(port << AHCI_P_FBS_DEV_SHIFT));
}
/* Issue command to the controller. */
slot->state = AHCI_SLOT_RUNNING;
ch->rslots |= (1 << slot->slot);
@ -1543,12 +1633,30 @@ ahci_execute_transaction(struct ahci_slot *slot)
ATA_INL(ch->r_mem, AHCI_P_SERR));
et = AHCI_ERR_TIMEOUT;
}
if (et != AHCI_ERR_NONE) {
/* Kick controller into sane state */
ahci_stop(ch->dev);
ahci_start(ch->dev);
/* Marvell controllers do not wait for readyness. */
if ((ch->quirks & AHCI_Q_NOBSYRES) &&
(ccb->ccb_h.func_code == XPT_ATA_IO) &&
(ccb->ataio.cmd.flags & CAM_ATAIO_CONTROL) &&
(ccb->ataio.cmd.control & ATA_A_RESET) == 0) {
while ((val = fis[2]) & (ATA_S_BUSY | ATA_S_DRQ)) {
DELAY(1000);
if (count++ >= timeout) {
device_printf(dev, "device is not "
"ready after soft-reset: "
"tfd = %08x\n", val);
et = AHCI_ERR_TIMEOUT;
break;
}
}
}
ahci_end_transaction(slot, et);
/* Kick controller into sane state and enable FBS. */
if ((ccb->ccb_h.func_code == XPT_ATA_IO) &&
(ccb->ataio.cmd.flags & CAM_ATAIO_CONTROL) &&
(ccb->ataio.cmd.control & ATA_A_RESET) == 0) {
ahci_stop(ch->dev);
ahci_start(ch->dev, 1);
}
return;
}
/* Start command execution timeout */
@ -1577,7 +1685,8 @@ ahci_timeout(struct ahci_slot *slot)
sstatus = ATA_INL(ch->r_mem, AHCI_P_SACT);
ccs = (ATA_INL(ch->r_mem, AHCI_P_CMD) & AHCI_P_CMD_CCS_MASK)
>> AHCI_P_CMD_CCS_SHIFT;
if ((sstatus & (1 << slot->slot)) != 0 || ccs == slot->slot)
if ((sstatus & (1 << slot->slot)) != 0 || ccs == slot->slot ||
ch->fbs_enabled)
slot->state = AHCI_SLOT_EXECUTING;
callout_reset(&slot->timeout,
@ -1635,12 +1744,19 @@ ahci_end_transaction(struct ahci_slot *slot, enum ahci_err_type et)
if ((et == AHCI_ERR_TFE) ||
(ccb->ataio.cmd.flags & CAM_ATAIO_NEEDRESULT)) {
u_int8_t *fis = ch->dma.rfis + 0x40;
uint16_t tfd = ATA_INL(ch->r_mem, AHCI_P_TFD);
bus_dmamap_sync(ch->dma.rfis_tag, ch->dma.rfis_map,
BUS_DMASYNC_POSTREAD);
res->status = tfd;
res->error = tfd >> 8;
if (ch->fbs_enabled) {
fis += ccb->ccb_h.target_id * 256;
res->status = fis[2];
res->error = fis[3];
} else {
uint16_t tfd = ATA_INL(ch->r_mem, AHCI_P_TFD);
res->status = tfd;
res->error = tfd >> 8;
}
res->lba_low = fis[4];
res->lba_mid = fis[5];
res->lba_high = fis[6];
@ -1659,6 +1775,8 @@ ahci_end_transaction(struct ahci_slot *slot, enum ahci_err_type et)
BUS_DMASYNC_POSTREAD : BUS_DMASYNC_POSTWRITE);
bus_dmamap_unload(ch->dma.data_tag, slot->dma.data_map);
}
if (et != AHCI_ERR_NONE)
ch->eslots |= (1 << slot->slot);
/* In case of error, freeze device for proper recovery. */
if ((et != AHCI_ERR_NONE) && (!ch->readlog) &&
!(ccb->ccb_h.status & CAM_DEV_QFRZN)) {
@ -1722,9 +1840,11 @@ ahci_end_transaction(struct ahci_slot *slot, enum ahci_err_type et)
slot->ccb = NULL;
/* Update channel stats. */
ch->numrslots--;
ch->numrslotspd[ccb->ccb_h.target_id]--;
if ((ccb->ccb_h.func_code == XPT_ATA_IO) &&
(ccb->ataio.cmd.flags & CAM_ATAIO_FPDMA)) {
ch->numtslots--;
ch->numtslotspd[ccb->ccb_h.target_id]--;
}
/* If it was first request of reset sequence and there is no error,
* proceed to second request. */
@ -1742,6 +1862,7 @@ ahci_end_transaction(struct ahci_slot *slot, enum ahci_err_type et)
/* If it was NCQ command error, put result on hold. */
} else if (et == AHCI_ERR_NCQ) {
ch->hold[slot->slot] = ccb;
ch->numhslots++;
} else
xpt_done(ccb);
/* Unfreeze frozen command. */
@ -1756,6 +1877,15 @@ ahci_end_transaction(struct ahci_slot *slot, enum ahci_err_type et)
/* if there was fatal error - reset port. */
if (ch->fatalerr) {
ahci_reset(dev);
} else {
/* if we have slots in error, we can reinit port. */
if (ch->eslots != 0) {
ahci_stop(dev);
ahci_start(dev, 1);
}
/* if there commands on hold, we can do READ LOG. */
if (!ch->readlog && ch->numhslots)
ahci_issue_read_log(dev);
}
}
/* Start PM timer. */
@ -1843,6 +1973,7 @@ ahci_process_read_log(device_t dev, union ccb *ccb)
}
xpt_done(ch->hold[i]);
ch->hold[i] = NULL;
ch->numhslots--;
}
} else {
if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)
@ -1855,6 +1986,7 @@ ahci_process_read_log(device_t dev, union ccb *ccb)
continue;
xpt_done(ch->hold[i]);
ch->hold[i] = NULL;
ch->numhslots--;
}
}
free(ccb->ataio.data_ptr, M_AHCI);
@ -1863,7 +1995,7 @@ ahci_process_read_log(device_t dev, union ccb *ccb)
}
static void
ahci_start(device_t dev)
ahci_start(device_t dev, int fbs)
{
struct ahci_channel *ch = device_get_softc(dev);
u_int32_t cmd;
@ -1872,6 +2004,12 @@ ahci_start(device_t dev)
ATA_OUTL(ch->r_mem, AHCI_P_SERR, 0xFFFFFFFF);
/* Clear any interrupts pending on this channel */
ATA_OUTL(ch->r_mem, AHCI_P_IS, 0xFFFFFFFF);
/* Configure FIS-based switching if supported. */
if (ch->chcaps & AHCI_P_CMD_FBSCP) {
ch->fbs_enabled = (fbs && ch->pm_present) ? 1 : 0;
ATA_OUTL(ch->r_mem, AHCI_P_FBS,
ch->fbs_enabled ? AHCI_P_FBS_EN : 0);
}
/* Start operations on this channel */
cmd = ATA_INL(ch->r_mem, AHCI_P_CMD);
ATA_OUTL(ch->r_mem, AHCI_P_CMD, cmd | AHCI_P_CMD_ST |
@ -1897,6 +2035,7 @@ ahci_stop(device_t dev)
break;
}
} while (ATA_INL(ch->r_mem, AHCI_P_CMD) & AHCI_P_CMD_CR);
ch->eslots = 0;
}
static void
@ -2010,7 +2149,9 @@ ahci_reset(device_t dev)
continue;
xpt_done(ch->hold[i]);
ch->hold[i] = NULL;
ch->numhslots--;
}
ch->eslots = 0;
ch->fatalerr = 0;
/* Tell the XPT about the event */
xpt_async(AC_BUS_RESET, ch->path, NULL);
@ -2031,7 +2172,7 @@ ahci_reset(device_t dev)
/* Wait for clearing busy status. */
if (ahci_wait_ready(dev, 15000))
ahci_clo(dev);
ahci_start(dev);
ahci_start(dev, 1);
ch->devices = 1;
/* Enable wanted port interrupts */
ATA_OUTL(ch->r_mem, AHCI_P_IE,

View File

@ -247,8 +247,11 @@
#define AHCI_P_CMD_CPS 0x00010000
#define AHCI_P_CMD_PMA 0x00020000
#define AHCI_P_CMD_HPCP 0x00040000
#define AHCI_P_CMD_ISP 0x00080000
#define AHCI_P_CMD_MPSP 0x00080000
#define AHCI_P_CMD_CPD 0x00100000
#define AHCI_P_CMD_ESP 0x00200000
#define AHCI_P_CMD_FBSCP 0x00400000
#define AHCI_P_CMD_APSTE 0x00800000
#define AHCI_P_CMD_ATAPI 0x01000000
#define AHCI_P_CMD_DLAE 0x02000000
#define AHCI_P_CMD_ALPE 0x04000000
@ -268,6 +271,15 @@
#define AHCI_P_CI 0x38
#define AHCI_P_SNTF 0x3C
#define AHCI_P_FBS 0x40
#define AHCI_P_FBS_EN 0x00000001
#define AHCI_P_FBS_DEC 0x00000002
#define AHCI_P_FBS_SDE 0x00000004
#define AHCI_P_FBS_DEV 0x00000f00
#define AHCI_P_FBS_DEV_SHIFT 8
#define AHCI_P_FBS_ADO 0x0000f000
#define AHCI_P_FBS_ADO_SHIFT 12
#define AHCI_P_FBS_DWE 0x000f0000
#define AHCI_P_FBS_DWE_SHIFT 16
/* Just to be sure, if building as module. */
#if MAXPHYS < 512 * 1024
@ -373,6 +385,7 @@ struct ahci_channel {
struct cam_path *path;
uint32_t caps; /* Controller capabilities */
uint32_t caps2; /* Controller capabilities */
uint32_t chcaps; /* Channel capabilities */
int quirks;
int numslots; /* Number of present slots */
int pm_level; /* power management level */
@ -382,11 +395,16 @@ struct ahci_channel {
struct mtx mtx; /* state lock */
int devices; /* What is present */
int pm_present; /* PM presence reported */
int fbs_enabled; /* FIS-based switching enabled */
uint32_t oslots; /* Occupied slots */
uint32_t rslots; /* Running slots */
uint32_t aslots; /* Slots with atomic commands */
uint32_t eslots; /* Slots in error */
int numrslots; /* Number of running slots */
int numrslotspd[16];/* Number of running slots per dev */
int numtslots; /* Number of tagged slots */
int numtslotspd[16];/* Number of tagged slots per dev */
int numhslots; /* Number of holden slots */
int readlog; /* Our READ LOG active */
int fatalerr; /* Fatal error happend */
int lastslot; /* Last used slot */