static int wdc_atapi_get_params(struct scsipi_channel *chan, int drive, struct ataparams *id) { struct wdc_softc *wdc = device_private(chan->chan_adapter->adapt_dev); struct atac_softc *atac = &wdc->sc_atac; struct wdc_regs *wdr = &wdc->regs[chan->chan_channel]; struct ata_channel *chp = atac->atac_channels[chan->chan_channel]; struct ata_command ata_c; memset(&ata_c, 0, sizeof(struct ata_command)); ata_c.r_command = ATAPI_SOFT_RESET; ata_c.r_st_bmask = 0; ata_c.r_st_pmask = 0; ata_c.flags = AT_WAIT | AT_POLL; ata_c.timeout = WDC_RESET_WAIT; if (wdc_exec_command(&chp->ch_drive[drive], &ata_c) != ATACMD_COMPLETE) { printf("wdc_atapi_get_params: ATAPI_SOFT_RESET failed for" " drive %s:%d:%d: driver failed\n", device_xname(atac->atac_dev), chp->ch_channel, drive); panic("wdc_atapi_get_params"); } if (ata_c.flags & (AT_ERROR | AT_TIMEOU | AT_DF)) { ATADEBUG_PRINT(("wdc_atapi_get_params: ATAPI_SOFT_RESET " "failed for drive %s:%d:%d: error 0x%x\n", device_xname(atac->atac_dev), chp->ch_channel, drive, ata_c.r_error), DEBUG_PROBE); return -1; } chp->ch_drive[drive].state = 0; (void)bus_space_read_1(wdr->cmd_iot, wdr->cmd_iohs[wd_status], 0); /* Some ATAPI devices need a bit more time after software reset. */ delay(5000); if (ata_get_params(&chp->ch_drive[drive], AT_WAIT, id) != 0) { ATADEBUG_PRINT(("wdc_atapi_get_params: ATAPI_IDENTIFY_DEVICE " "failed for drive %s:%d:%d: error 0x%x\n", device_xname(atac->atac_dev), chp->ch_channel, drive, ata_c.r_error), DEBUG_PROBE); return -1; } return 0; }
int wd_get_params(struct wd_softc *wd, u_int8_t flags, struct ataparams *params) { switch (ata_get_params(wd->drvp, flags, params)) { case CMD_AGAIN: return 1; case CMD_ERR: /* If we already have drive parameters, reuse them. */ if (wd->sc_params.atap_cylinders != 0) { if (params != &wd->sc_params) bcopy(&wd->sc_params, params, sizeof(struct ataparams)); return 0; } /* * We `know' there's a drive here; just assume it's old. * This geometry is only used to read the MBR and print a * (false) attach message. */ bzero(params, sizeof(struct ataparams)); strncpy(params->atap_model, "ST506", sizeof params->atap_model); params->atap_config = ATA_CFG_FIXED; params->atap_cylinders = 1024; params->atap_heads = 8; params->atap_sectors = 17; params->atap_multi = 1; params->atap_capabilities1 = params->atap_capabilities2 = 0; wd->drvp->ata_vers = -1; /* Mark it as pre-ATA */ return 0; case CMD_OK: return 0; default: panic("wd_get_params: bad return code from ata_get_params"); /* NOTREACHED */ } }
/* * Probe drive's capabilities, for use by the controller later * Assumes drvp points to an existing drive. */ void ata_probe_caps(struct ata_drive_datas *drvp) { struct ataparams params, params2; struct ata_channel *chp = drvp->chnl_softc; struct atac_softc *atac = chp->ch_atac; device_t drv_dev = drvp->drv_softc; int i, printed, s; const char *sep = ""; int cf_flags; if (ata_get_params(drvp, AT_WAIT, ¶ms) != CMD_OK) { /* IDENTIFY failed. Can't tell more about the device */ return; } if ((atac->atac_cap & (ATAC_CAP_DATA16 | ATAC_CAP_DATA32)) == (ATAC_CAP_DATA16 | ATAC_CAP_DATA32)) { /* * Controller claims 16 and 32 bit transfers. * Re-do an IDENTIFY with 32-bit transfers, * and compare results. */ s = splbio(); drvp->drive_flags |= ATA_DRIVE_CAP32; splx(s); ata_get_params(drvp, AT_WAIT, ¶ms2); if (memcmp(¶ms, ¶ms2, sizeof(struct ataparams)) != 0) { /* Not good. fall back to 16bits */ s = splbio(); drvp->drive_flags &= ~ATA_DRIVE_CAP32; splx(s); } else { aprint_verbose_dev(drv_dev, "32-bit data port\n"); } } #if 0 /* Some ultra-DMA drives claims to only support ATA-3. sigh */ if (params.atap_ata_major > 0x01 && params.atap_ata_major != 0xffff) { for (i = 14; i > 0; i--) { if (params.atap_ata_major & (1 << i)) { aprint_verbose_dev(drv_dev, "ATA version %d\n", i); drvp->ata_vers = i; break; } } } #endif /* An ATAPI device is at last PIO mode 3 */ if (drvp->drive_type == ATA_DRIVET_ATAPI) drvp->PIO_mode = 3; /* * It's not in the specs, but it seems that some drive * returns 0xffff in atap_extensions when this field is invalid */ if (params.atap_extensions != 0xffff && (params.atap_extensions & WDC_EXT_MODES)) { printed = 0; /* * XXX some drives report something wrong here (they claim to * support PIO mode 8 !). As mode is coded on 3 bits in * SET FEATURE, limit it to 7 (so limit i to 4). * If higher mode than 7 is found, abort. */ for (i = 7; i >= 0; i--) { if ((params.atap_piomode_supp & (1 << i)) == 0) continue; if (i > 4) return; /* * See if mode is accepted. * If the controller can't set its PIO mode, * assume the defaults are good, so don't try * to set it */ if (atac->atac_set_modes) /* * It's OK to pool here, it's fast enough * to not bother waiting for interrupt */ if (ata_set_mode(drvp, 0x08 | (i + 3), AT_WAIT) != CMD_OK) continue; if (!printed) { aprint_verbose_dev(drv_dev, "drive supports PIO mode %d", i + 3); sep = ","; printed = 1; } /* * If controller's driver can't set its PIO mode, * get the highter one for the drive. */ if (atac->atac_set_modes == NULL || atac->atac_pio_cap >= i + 3) { drvp->PIO_mode = i + 3; drvp->PIO_cap = i + 3; break; } } if (!printed) { /* * We didn't find a valid PIO mode. * Assume the values returned for DMA are buggy too */ return; } s = splbio(); drvp->drive_flags |= ATA_DRIVE_MODE; splx(s); printed = 0; for (i = 7; i >= 0; i--) { if ((params.atap_dmamode_supp & (1 << i)) == 0) continue; #if NATA_DMA if ((atac->atac_cap & ATAC_CAP_DMA) && atac->atac_set_modes != NULL) if (ata_set_mode(drvp, 0x20 | i, AT_WAIT) != CMD_OK) continue; #endif if (!printed) { aprint_verbose("%s DMA mode %d", sep, i); sep = ","; printed = 1; } #if NATA_DMA if (atac->atac_cap & ATAC_CAP_DMA) { if (atac->atac_set_modes != NULL && atac->atac_dma_cap < i) continue; drvp->DMA_mode = i; drvp->DMA_cap = i; s = splbio(); drvp->drive_flags |= ATA_DRIVE_DMA; splx(s); } #endif break; } if (params.atap_extensions & WDC_EXT_UDMA_MODES) { printed = 0; for (i = 7; i >= 0; i--) { if ((params.atap_udmamode_supp & (1 << i)) == 0) continue; #if NATA_UDMA if (atac->atac_set_modes != NULL && (atac->atac_cap & ATAC_CAP_UDMA)) if (ata_set_mode(drvp, 0x40 | i, AT_WAIT) != CMD_OK) continue; #endif if (!printed) { aprint_verbose("%s Ultra-DMA mode %d", sep, i); if (i == 2) aprint_verbose(" (Ultra/33)"); else if (i == 4) aprint_verbose(" (Ultra/66)"); else if (i == 5) aprint_verbose(" (Ultra/100)"); else if (i == 6) aprint_verbose(" (Ultra/133)"); sep = ","; printed = 1; } #if NATA_UDMA if (atac->atac_cap & ATAC_CAP_UDMA) { if (atac->atac_set_modes != NULL && atac->atac_udma_cap < i) continue; drvp->UDMA_mode = i; drvp->UDMA_cap = i; s = splbio(); drvp->drive_flags |= ATA_DRIVE_UDMA; splx(s); } #endif break; } } aprint_verbose("\n"); } s = splbio(); drvp->drive_flags &= ~ATA_DRIVE_NOSTREAM; if (drvp->drive_type == ATA_DRIVET_ATAPI) { if (atac->atac_cap & ATAC_CAP_ATAPI_NOSTREAM) drvp->drive_flags |= ATA_DRIVE_NOSTREAM; } else { if (atac->atac_cap & ATAC_CAP_ATA_NOSTREAM) drvp->drive_flags |= ATA_DRIVE_NOSTREAM; } splx(s); /* Try to guess ATA version here, if it didn't get reported */ if (drvp->ata_vers == 0) { #if NATA_UDMA if (drvp->drive_flags & ATA_DRIVE_UDMA) drvp->ata_vers = 4; /* should be at last ATA-4 */ else #endif if (drvp->PIO_cap > 2) drvp->ata_vers = 2; /* should be at last ATA-2 */ } cf_flags = device_cfdata(drv_dev)->cf_flags; if (cf_flags & ATA_CONFIG_PIO_SET) { s = splbio(); drvp->PIO_mode = (cf_flags & ATA_CONFIG_PIO_MODES) >> ATA_CONFIG_PIO_OFF; drvp->drive_flags |= ATA_DRIVE_MODE; splx(s); }