Fix the signature matching code on AHCI controllers.
Add SATA ATAPI support for AHCI controllers.
This commit is contained in:
parent
8a3367a3b4
commit
4e65ee2c1d
@ -321,8 +321,8 @@ ata_sata_phy_reset(device_t dev)
|
||||
for (loop = 0; loop < 10; loop++) {
|
||||
ATA_IDX_OUTL(ch, ATA_SCONTROL, ATA_SC_DET_RESET);
|
||||
ata_udelay(100);
|
||||
if ((ATA_IDX_INL(ch, ATA_SCONTROL) &
|
||||
ATA_SC_DET_MASK) == ATA_SC_DET_RESET)
|
||||
if ((ATA_IDX_INL(ch, ATA_SCONTROL) & ATA_SC_DET_MASK) ==
|
||||
ATA_SC_DET_RESET)
|
||||
break;
|
||||
}
|
||||
ata_udelay(5000);
|
||||
@ -409,7 +409,7 @@ ata_request2fis_h2d(struct ata_request *request, u_int8_t *fis)
|
||||
fis[0] = 0x27; /* host to device */
|
||||
fis[1] = 0x80; /* command FIS (note PM goes here) */
|
||||
fis[2] = ATA_PACKET_CMD;
|
||||
if (request->flags & ATA_R_DMA)
|
||||
if (request->flags & (ATA_R_READ | ATA_R_WRITE))
|
||||
fis[3] = ATA_F_DMA;
|
||||
else {
|
||||
fis[5] = request->transfersize;
|
||||
@ -620,7 +620,7 @@ ata_ahci_begin_transaction(struct ata_request *request)
|
||||
ATA_IDX_OUTL(ch, ATA_SACTIVE, ATA_IDX_INL(ch, ATA_SACTIVE) & (1 << tag));
|
||||
|
||||
/* set command type bit */
|
||||
if (request->flags & ATA_R_ATAPI)
|
||||
if (ch->devices & ATA_ATAPI_MASTER)
|
||||
ATA_OUTL(ctlr->r_res2, ATA_AHCI_P_CMD + offset,
|
||||
ATA_INL(ctlr->r_res2, ATA_AHCI_P_CMD + offset) |
|
||||
ATA_AHCI_P_CMD_ATAPI);
|
||||
@ -629,8 +629,28 @@ ata_ahci_begin_transaction(struct ata_request *request)
|
||||
ATA_INL(ctlr->r_res2, ATA_AHCI_P_CMD + offset) &
|
||||
~ATA_AHCI_P_CMD_ATAPI);
|
||||
|
||||
/* issue the command */
|
||||
/* issue command to controller */
|
||||
ATA_OUTL(ctlr->r_res2, ATA_AHCI_P_CI + offset, (1 << tag));
|
||||
|
||||
if (!(request->flags & ATA_R_ATAPI)) {
|
||||
/* device reset doesn't interrupt */
|
||||
if (request->u.ata.command == ATA_DEVICE_RESET) {
|
||||
u_int32_t tf_data;
|
||||
int timeout = 1000000;
|
||||
|
||||
do {
|
||||
DELAY(10);
|
||||
tf_data = ATA_INL(ctlr->r_res2, ATA_AHCI_P_TFD + (ch->unit<<7));
|
||||
} while ((tf_data & ATA_S_BUSY) && timeout--);
|
||||
if (bootverbose)
|
||||
device_printf(ch->dev, "device_reset timeout=%dus\n",
|
||||
(1000000-timeout)*10);
|
||||
request->status = tf_data;
|
||||
if (request->status & ATA_S_ERROR)
|
||||
request->error = tf_data >> 8;
|
||||
return ATA_OP_FINISHED;
|
||||
}
|
||||
}
|
||||
|
||||
/* start the timeout */
|
||||
callout_reset(&request->callout, request->timeout * hz,
|
||||
@ -676,7 +696,7 @@ ata_ahci_reset(device_t dev)
|
||||
{
|
||||
struct ata_pci_controller *ctlr = device_get_softc(device_get_parent(dev));
|
||||
struct ata_channel *ch = device_get_softc(dev);
|
||||
u_int32_t cmd;
|
||||
u_int32_t cmd, signature;
|
||||
int offset = ch->unit << 7;
|
||||
int timeout;
|
||||
|
||||
@ -695,10 +715,11 @@ ata_ahci_reset(device_t dev)
|
||||
timeout = 0;
|
||||
do {
|
||||
DELAY(1000);
|
||||
if (timeout++ > 500)
|
||||
if (timeout++ > 500) {
|
||||
device_printf(dev, "stopping AHCI engine failed\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
while (ATA_INL(ctlr->r_res2, ATA_AHCI_P_CMD + offset) & ATA_AHCI_P_CMD_CR);
|
||||
|
||||
/* issue Command List Override if supported */
|
||||
@ -709,43 +730,53 @@ ata_ahci_reset(device_t dev)
|
||||
timeout = 0;
|
||||
do {
|
||||
DELAY(1000);
|
||||
if (timeout++ > 500)
|
||||
if (timeout++ > 500) {
|
||||
device_printf(dev, "executing CLO failed\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
while (ATA_INL(ctlr->r_res2, ATA_AHCI_P_CMD+offset)&ATA_AHCI_P_CMD_CLO);
|
||||
}
|
||||
|
||||
/* spin up device */
|
||||
ATA_OUTL(ctlr->r_res2, ATA_AHCI_P_CMD + offset, ATA_AHCI_P_CMD_SUD);
|
||||
|
||||
/* enable interface */
|
||||
/* reset PHY and decide what is present */
|
||||
if (ata_sata_phy_reset(dev)) {
|
||||
switch (ATA_INL(ctlr->r_res2, ATA_AHCI_P_SIG + offset)) {
|
||||
case 0xeb140101:
|
||||
ch->devices = ATA_ATAPI_MASTER;
|
||||
device_printf(ch->dev, "SATA ATAPI devices not supported yet\n");
|
||||
ch->devices = 0;
|
||||
|
||||
/* clear any interrupts pending on this channel */
|
||||
ATA_OUTL(ctlr->r_res2, ATA_AHCI_P_IS + offset,
|
||||
ATA_INL(ctlr->r_res2, ATA_AHCI_P_IS + offset));
|
||||
|
||||
/* clear SATA error register */
|
||||
ATA_IDX_OUTL(ch, ATA_SERROR, ATA_IDX_INL(ch, ATA_SERROR));
|
||||
|
||||
/* start operations on this channel */
|
||||
ATA_OUTL(ctlr->r_res2, ATA_AHCI_P_CMD + offset,
|
||||
(ATA_AHCI_P_CMD_ACTIVE | ATA_AHCI_P_CMD_FRE |
|
||||
ATA_AHCI_P_CMD_POD | ATA_AHCI_P_CMD_SUD | ATA_AHCI_P_CMD_ST));
|
||||
|
||||
signature = ATA_INL(ctlr->r_res2, ATA_AHCI_P_SIG + offset);
|
||||
if (bootverbose)
|
||||
device_printf(dev, "SIGNATURE: %08x\n", signature);
|
||||
switch (signature) {
|
||||
case 0x00000101:
|
||||
ch->devices = ATA_ATA_MASTER;
|
||||
break;
|
||||
case 0x96690101:
|
||||
ch->devices = ATA_PORTMULTIPLIER;
|
||||
device_printf(ch->dev, "Portmultipliers not supported yet\n");
|
||||
ch->devices = 0;
|
||||
break;
|
||||
case 0x00000101:
|
||||
ch->devices = ATA_ATA_MASTER;
|
||||
case 0xeb140101:
|
||||
ch->devices = ATA_ATAPI_MASTER;
|
||||
break;
|
||||
default: /* SOS XXX */
|
||||
if (bootverbose)
|
||||
device_printf(ch->dev, "No signature, asuming disk device\n");
|
||||
ch->devices = ATA_ATA_MASTER;
|
||||
}
|
||||
}
|
||||
|
||||
/* clear any interrupts pending on this channel */
|
||||
ATA_OUTL(ctlr->r_res2, ATA_AHCI_P_IS + offset,
|
||||
ATA_INL(ctlr->r_res2, ATA_AHCI_P_IS + offset));
|
||||
|
||||
/* start operations on this channel */
|
||||
ATA_OUTL(ctlr->r_res2, ATA_AHCI_P_CMD + offset,
|
||||
(ATA_AHCI_P_CMD_ACTIVE | ATA_AHCI_P_CMD_FRE |
|
||||
ATA_AHCI_P_CMD_POD | ATA_AHCI_P_CMD_SUD | ATA_AHCI_P_CMD_ST));
|
||||
if (bootverbose)
|
||||
device_printf(dev, "ahci_reset devices=0x%b\n", ch->devices,
|
||||
"\20\4ATAPI_SLAVE\3ATAPI_MASTER\2ATA_SLAVE\1ATA_MASTER");
|
||||
}
|
||||
|
||||
static void
|
||||
@ -786,7 +817,7 @@ ata_ahci_setup_fis(struct ata_ahci_cmd_tab *ctp, struct ata_request *request)
|
||||
bzero(ctp->cfis, 64);
|
||||
if (request->flags & ATA_R_ATAPI) {
|
||||
bzero(ctp->acmd, 32);
|
||||
bcopy(request->u.atapi.ccb, ctp->acmd, 12);
|
||||
bcopy(request->u.atapi.ccb, ctp->acmd, 16);
|
||||
}
|
||||
return ata_request2fis_h2d(request, &ctp->cfis[0]);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user