diff options
| author | Søren Schmidt <sos@FreeBSD.org> | 2007-11-19 18:05:48 +0000 |
|---|---|---|
| committer | Søren Schmidt <sos@FreeBSD.org> | 2007-11-19 18:05:48 +0000 |
| commit | 6b899f5077d33c863c733c94686cf42253b9a7f2 (patch) | |
| tree | 491ed6ea353a84da21e00c0036f398cb187a6bce /sys/dev | |
| parent | 5d3b292219a058282cdec0024c53048f0e70ae9a (diff) | |
Notes
Diffstat (limited to 'sys/dev')
| -rw-r--r-- | sys/dev/ata/ata-chipset.c | 40 | ||||
| -rw-r--r-- | sys/dev/ata/atapi-cd.c | 37 |
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); |
