aboutsummaryrefslogtreecommitdiff
path: root/sys/dev
diff options
context:
space:
mode:
authorSøren Schmidt <sos@FreeBSD.org>2007-11-19 18:05:48 +0000
committerSøren Schmidt <sos@FreeBSD.org>2007-11-19 18:05:48 +0000
commit6b899f5077d33c863c733c94686cf42253b9a7f2 (patch)
tree491ed6ea353a84da21e00c0036f398cb187a6bce /sys/dev
parent5d3b292219a058282cdec0024c53048f0e70ae9a (diff)
Notes
Diffstat (limited to 'sys/dev')
-rw-r--r--sys/dev/ata/ata-chipset.c40
-rw-r--r--sys/dev/ata/atapi-cd.c37
2 files changed, 58 insertions, 19 deletions
diff --git a/sys/dev/ata/ata-chipset.c b/sys/dev/ata/ata-chipset.c
index 9d136173f57f0..4f8943b8c5316 100644
--- a/sys/dev/ata/ata-chipset.c
+++ b/sys/dev/ata/ata-chipset.c
@@ -460,7 +460,11 @@ ata_ahci_ident(device_t dev)
if (pci_read_config(dev, PCIR_PROGIF, 1) != PCIP_STORAGE_SATA_AHCI_1_0)
return ENXIO;
- sprintf(buffer, "%s AHCI controller", ata_pcivendor2str(dev));
+ if (bootverbose)
+ sprintf(buffer, "%s (ID=%08x) AHCI controller",
+ ata_pcivendor2str(dev), pci_get_devid(dev));
+ else
+ sprintf(buffer, "%s AHCI controller", ata_pcivendor2str(dev));
device_set_desc_copy(dev, buffer);
ctlr->chipinit = ata_ahci_chipinit;
return 0;
@@ -591,16 +595,44 @@ ata_ahci_status(device_t dev)
if (action & (1 << ch->unit)) {
u_int32_t istatus = ATA_INL(ctlr->r_res2, ATA_AHCI_P_IS + offset);
+ u_int32_t cstatus = ATA_INL(ctlr->r_res2, ATA_AHCI_P_CI + offset);
/* clear interrupt(s) */
ATA_OUTL(ctlr->r_res2, ATA_AHCI_IS, action & (1 << ch->unit));
ATA_OUTL(ctlr->r_res2, ATA_AHCI_P_IS + offset, istatus);
/* do we have any PHY events ? */
+ /* XXX SOS check istatus phy bits */
ata_sata_phy_check_events(dev);
- /* do we have any device action ? */
- return (!(ATA_INL(ctlr->r_res2, ATA_AHCI_P_CI + offset) & (1 << tag)));
+ /* do we have a potentially hanging engine to take care of? */
+ if ((istatus & 0x78400050) && (cstatus & (1 << tag))) {
+
+ u_int32_t cmd = ATA_INL(ctlr->r_res2, ATA_AHCI_P_CMD + offset);
+ int timeout = 0;
+
+ /* kill off all activity on this channel */
+ ATA_OUTL(ctlr->r_res2, ATA_AHCI_P_CMD + offset,
+ cmd & ~(ATA_AHCI_P_CMD_FRE | ATA_AHCI_P_CMD_ST));
+
+ /* XXX SOS this is not entirely wrong */
+ do {
+ DELAY(1000);
+ 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);
+
+ /* start operations on this channel */
+ ATA_OUTL(ctlr->r_res2, ATA_AHCI_P_CMD + offset,
+ cmd | (ATA_AHCI_P_CMD_FRE | ATA_AHCI_P_CMD_ST));
+
+ return 1;
+ }
+ else
+ return (!(cstatus & (1 << tag)));
}
return 0;
}
@@ -655,7 +687,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 (ch->devices & ATA_ATAPI_MASTER)
+ if (request->flags & ATA_R_ATAPI)
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);
diff --git a/sys/dev/ata/atapi-cd.c b/sys/dev/ata/atapi-cd.c
index 4c6b55dc45caf..22caf9b8926fb 100644
--- a/sys/dev/ata/atapi-cd.c
+++ b/sys/dev/ata/atapi-cd.c
@@ -689,25 +689,32 @@ acd_geom_access(struct g_provider *pp, int dr, int dw, int de)
{
device_t dev = pp->geom->softc;
struct acd_softc *cdp = device_get_ivars(dev);
+ struct ata_request *request;
+ int8_t ccb[16] = { ATAPI_TEST_UNIT_READY, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
int timeout = 60, track;
- /* check for media present, waiting for loading medium just in case */
+ if (!(request = ata_alloc_request()))
+ return ENOMEM;
+
+ /* wait if drive is not finished loading the medium */
while (timeout--) {
- if (!acd_mode_sense(dev, ATAPI_CDROM_CAP_PAGE,
- (caddr_t)&cdp->cap, sizeof(cdp->cap)) &&
- cdp->cap.page_code == ATAPI_CDROM_CAP_PAGE) {
- if ((cdp->cap.medium_type == MST_FMT_NONE) ||
- (cdp->cap.medium_type == MST_NO_DISC) ||
- (cdp->cap.medium_type == MST_DOOR_OPEN) ||
- (cdp->cap.medium_type == MST_FMT_ERROR))
- return EIO;
- else
- break;
- }
- pause("acdld", hz / 2);
+ bzero(request, sizeof(struct ata_request));
+ request->dev = dev;
+ bcopy(ccb, request->u.atapi.ccb, 16);
+ request->flags = ATA_R_ATAPI;
+ request->timeout = 5;
+ ata_queue_request(request);
+ if (!request->error &&
+ (request->u.atapi.sense.key == 2 ||
+ request->u.atapi.sense.key == 7) &&
+ request->u.atapi.sense.asc == 4 &&
+ request->u.atapi.sense.ascq == 1)
+ pause("acdld", hz / 2);
+ else
+ break;
}
- if (timeout <= 0)
- return EIO;
+ ata_free_request(request);
if (pp->acr == 0) {
acd_prevent_allow(dev, 1);