📄 libata-core.c
字号:
dev->flags |= ATA_DFLAG_NCQ; } if (hdepth >= ddepth) snprintf(desc, desc_sz, "NCQ (depth %d)", ddepth); else snprintf(desc, desc_sz, "NCQ (depth %d/%d)", hdepth, ddepth);}/** * ata_dev_configure - Configure the specified ATA/ATAPI device * @dev: Target device to configure * * Configure @dev according to @dev->id. Generic and low-level * driver specific fixups are also applied. * * LOCKING: * Kernel thread context (may sleep) * * RETURNS: * 0 on success, -errno otherwise */int ata_dev_configure(struct ata_device *dev){ struct ata_port *ap = dev->link->ap; struct ata_eh_context *ehc = &dev->link->eh_context; int print_info = ehc->i.flags & ATA_EHI_PRINTINFO; const u16 *id = dev->id; unsigned int xfer_mask; char revbuf[7]; /* XYZ-99\0 */ char fwrevbuf[ATA_ID_FW_REV_LEN+1]; char modelbuf[ATA_ID_PROD_LEN+1]; int rc; if (!ata_dev_enabled(dev) && ata_msg_info(ap)) { ata_dev_printk(dev, KERN_INFO, "%s: ENTER/EXIT -- nodev\n", __FUNCTION__); return 0; } if (ata_msg_probe(ap)) ata_dev_printk(dev, KERN_DEBUG, "%s: ENTER\n", __FUNCTION__); /* set horkage */ dev->horkage |= ata_dev_blacklisted(dev); /* let ACPI work its magic */ rc = ata_acpi_on_devcfg(dev); if (rc) return rc; /* massage HPA, do it early as it might change IDENTIFY data */ rc = ata_hpa_resize(dev); if (rc) return rc; /* print device capabilities */ if (ata_msg_probe(ap)) ata_dev_printk(dev, KERN_DEBUG, "%s: cfg 49:%04x 82:%04x 83:%04x 84:%04x " "85:%04x 86:%04x 87:%04x 88:%04x\n", __FUNCTION__, id[49], id[82], id[83], id[84], id[85], id[86], id[87], id[88]); /* initialize to-be-configured parameters */ dev->flags &= ~ATA_DFLAG_CFG_MASK; dev->max_sectors = 0; dev->cdb_len = 0; dev->n_sectors = 0; dev->cylinders = 0; dev->heads = 0; dev->sectors = 0; /* * common ATA, ATAPI feature tests */ /* find max transfer mode; for printk only */ xfer_mask = ata_id_xfermask(id); if (ata_msg_probe(ap)) ata_dump_id(id); /* SCSI only uses 4-char revisions, dump full 8 chars from ATA */ ata_id_c_string(dev->id, fwrevbuf, ATA_ID_FW_REV, sizeof(fwrevbuf)); ata_id_c_string(dev->id, modelbuf, ATA_ID_PROD, sizeof(modelbuf)); /* ATA-specific feature tests */ if (dev->class == ATA_DEV_ATA) { if (ata_id_is_cfa(id)) { if (id[162] & 1) /* CPRM may make this media unusable */ ata_dev_printk(dev, KERN_WARNING, "supports DRM functions and may " "not be fully accessable.\n"); snprintf(revbuf, 7, "CFA"); } else snprintf(revbuf, 7, "ATA-%d", ata_id_major_version(id)); dev->n_sectors = ata_id_n_sectors(id); if (dev->id[59] & 0x100) dev->multi_count = dev->id[59] & 0xff; if (ata_id_has_lba(id)) { const char *lba_desc; char ncq_desc[20]; lba_desc = "LBA"; dev->flags |= ATA_DFLAG_LBA; if (ata_id_has_lba48(id)) { dev->flags |= ATA_DFLAG_LBA48; lba_desc = "LBA48"; if (dev->n_sectors >= (1UL << 28) && ata_id_has_flush_ext(id)) dev->flags |= ATA_DFLAG_FLUSH_EXT; } /* config NCQ */ ata_dev_config_ncq(dev, ncq_desc, sizeof(ncq_desc)); /* print device info to dmesg */ if (ata_msg_drv(ap) && print_info) { ata_dev_printk(dev, KERN_INFO, "%s: %s, %s, max %s\n", revbuf, modelbuf, fwrevbuf, ata_mode_string(xfer_mask)); ata_dev_printk(dev, KERN_INFO, "%Lu sectors, multi %u: %s %s\n", (unsigned long long)dev->n_sectors, dev->multi_count, lba_desc, ncq_desc); } } else { /* CHS */ /* Default translation */ dev->cylinders = id[1]; dev->heads = id[3]; dev->sectors = id[6]; if (ata_id_current_chs_valid(id)) { /* Current CHS translation is valid. */ dev->cylinders = id[54]; dev->heads = id[55]; dev->sectors = id[56]; } /* print device info to dmesg */ if (ata_msg_drv(ap) && print_info) { ata_dev_printk(dev, KERN_INFO, "%s: %s, %s, max %s\n", revbuf, modelbuf, fwrevbuf, ata_mode_string(xfer_mask)); ata_dev_printk(dev, KERN_INFO, "%Lu sectors, multi %u, CHS %u/%u/%u\n", (unsigned long long)dev->n_sectors, dev->multi_count, dev->cylinders, dev->heads, dev->sectors); } } dev->cdb_len = 16; } /* ATAPI-specific feature tests */ else if (dev->class == ATA_DEV_ATAPI) { const char *cdb_intr_string = ""; const char *atapi_an_string = ""; u32 sntf; rc = atapi_cdb_len(id); if ((rc < 12) || (rc > ATAPI_CDB_LEN)) { if (ata_msg_warn(ap)) ata_dev_printk(dev, KERN_WARNING, "unsupported CDB len\n"); rc = -EINVAL; goto err_out_nosup; } dev->cdb_len = (unsigned int) rc; /* Enable ATAPI AN if both the host and device have * the support. If PMP is attached, SNTF is required * to enable ATAPI AN to discern between PHY status * changed notifications and ATAPI ANs. */ if ((ap->flags & ATA_FLAG_AN) && ata_id_has_atapi_AN(id) && (!ap->nr_pmp_links || sata_scr_read(&ap->link, SCR_NOTIFICATION, &sntf) == 0)) { unsigned int err_mask; /* issue SET feature command to turn this on */ err_mask = ata_dev_set_feature(dev, SETFEATURES_SATA_ENABLE, SATA_AN); if (err_mask) ata_dev_printk(dev, KERN_ERR, "failed to enable ATAPI AN " "(err_mask=0x%x)\n", err_mask); else { dev->flags |= ATA_DFLAG_AN; atapi_an_string = ", ATAPI AN"; } } if (ata_id_cdb_intr(dev->id)) { dev->flags |= ATA_DFLAG_CDB_INTR; cdb_intr_string = ", CDB intr"; } /* print device info to dmesg */ if (ata_msg_drv(ap) && print_info) ata_dev_printk(dev, KERN_INFO, "ATAPI: %s, %s, max %s%s%s\n", modelbuf, fwrevbuf, ata_mode_string(xfer_mask), cdb_intr_string, atapi_an_string); } /* determine max_sectors */ dev->max_sectors = ATA_MAX_SECTORS; if (dev->flags & ATA_DFLAG_LBA48) dev->max_sectors = ATA_MAX_SECTORS_LBA48; if (!(dev->horkage & ATA_HORKAGE_IPM)) { if (ata_id_has_hipm(dev->id)) dev->flags |= ATA_DFLAG_HIPM; if (ata_id_has_dipm(dev->id)) dev->flags |= ATA_DFLAG_DIPM; } if (dev->horkage & ATA_HORKAGE_DIAGNOSTIC) { /* Let the user know. We don't want to disallow opens for rescue purposes, or in case the vendor is just a blithering idiot */ if (print_info) { ata_dev_printk(dev, KERN_WARNING,"Drive reports diagnostics failure. This may indicate a drive\n"); ata_dev_printk(dev, KERN_WARNING,"fault or invalid emulation. Contact drive vendor for information.\n"); } } /* limit bridge transfers to udma5, 200 sectors */ if (ata_dev_knobble(dev)) { if (ata_msg_drv(ap) && print_info) ata_dev_printk(dev, KERN_INFO, "applying bridge limits\n"); dev->udma_mask &= ATA_UDMA5; dev->max_sectors = ATA_MAX_SECTORS; } if ((dev->class == ATA_DEV_ATAPI) && (atapi_command_packet_set(id) == TYPE_TAPE)) { dev->max_sectors = ATA_MAX_SECTORS_TAPE; dev->horkage |= ATA_HORKAGE_STUCK_ERR; } if (dev->horkage & ATA_HORKAGE_MAX_SEC_128) dev->max_sectors = min_t(unsigned int, ATA_MAX_SECTORS_128, dev->max_sectors); if (ata_dev_blacklisted(dev) & ATA_HORKAGE_IPM) { dev->horkage |= ATA_HORKAGE_IPM; /* reset link pm_policy for this port to no pm */ ap->pm_policy = MAX_PERFORMANCE; } if (ap->ops->dev_config) ap->ops->dev_config(dev); if (ata_msg_probe(ap)) ata_dev_printk(dev, KERN_DEBUG, "%s: EXIT, drv_stat = 0x%x\n", __FUNCTION__, ata_chk_status(ap)); return 0;err_out_nosup: if (ata_msg_probe(ap)) ata_dev_printk(dev, KERN_DEBUG, "%s: EXIT, err\n", __FUNCTION__); return rc;}/** * ata_cable_40wire - return 40 wire cable type * @ap: port * * Helper method for drivers which want to hardwire 40 wire cable * detection. */int ata_cable_40wire(struct ata_port *ap){ return ATA_CBL_PATA40;}/** * ata_cable_80wire - return 80 wire cable type * @ap: port * * Helper method for drivers which want to hardwire 80 wire cable * detection. */int ata_cable_80wire(struct ata_port *ap){ return ATA_CBL_PATA80;}/** * ata_cable_unknown - return unknown PATA cable. * @ap: port * * Helper method for drivers which have no PATA cable detection. */int ata_cable_unknown(struct ata_port *ap){ return ATA_CBL_PATA_UNK;}/** * ata_cable_sata - return SATA cable type * @ap: port * * Helper method for drivers which have SATA cables */int ata_cable_sata(struct ata_port *ap){ return ATA_CBL_SATA;}/** * ata_bus_probe - Reset and probe ATA bus * @ap: Bus to probe * * Master ATA bus probing function. Initiates a hardware-dependent * bus reset, then attempts to identify any devices found on * the bus. * * LOCKING: * PCI/etc. bus probe sem. * * RETURNS: * Zero on success, negative errno otherwise. */int ata_bus_probe(struct ata_port *ap){ unsigned int classes[ATA_MAX_DEVICES]; int tries[ATA_MAX_DEVICES]; int rc; struct ata_device *dev; ata_port_probe(ap); ata_link_for_each_dev(dev, &ap->link) tries[dev->devno] = ATA_PROBE_MAX_TRIES; retry: ata_link_for_each_dev(dev, &ap->link) { /* If we issue an SRST then an ATA drive (not ATAPI) * may change configuration and be in PIO0 timing. If * we do a hard reset (or are coming from power on) * this is true for ATA or ATAPI. Until we've set a * suitable controller mode we should not touch the * bus as we may be talking too fast. */ dev->pio_mode = XFER_PIO_0; /* If the controller has a pio mode setup function * then use it to set the chipset to rights. Don't * touch the DMA setup as that will be dealt with when * configuring devices. */ if (ap->ops->set_piomode) ap->ops->set_piomode(ap, dev); } /* reset and determine device classes */ ap->ops->phy_reset(ap); ata_link_for_each_dev(dev, &ap->link) { if (!(ap->flags & ATA_FLAG_DISABLED) && dev->class != ATA_DEV_UNKNOWN) classes[dev->devno] = dev->class; else classes[dev->devno] = ATA_DEV_NONE; dev->class = ATA_DEV_UNKNOWN; } ata_port_probe(ap); /* read IDENTIFY page and configure devices. We have to do the identify specific sequence bass-ackwards so that PDIAG- is released by the slave device */ ata_link_for_each_dev(dev, &ap->link) { if (tries[dev->devno]) dev->class = classes[dev->devno]; if (!ata_dev_enabled(dev)) continue; rc = ata_dev_read_id(dev, &dev->class, ATA_READID_POSTRESET, dev->id); if (rc) goto fail; } /* Now ask for the cable type as PDIAG- should have been released */ if (ap->ops->cable_detect) ap->cbl = ap->ops->cable_detect(ap); /* We may have SATA bridge glue hiding here irrespective of the reported cable types and sensed types */ ata_link_for_each_dev(dev, &ap->link) { if (!ata_dev_enabled(dev)) continue; /* SATA drives indicate we have a bridge. We don't know which end of the link the bridge is which is a problem */ if (ata_id_is_sata(dev->id)) ap->cbl = ATA_CBL_SATA; } /* After the identify sequence we can now set up the devices. We do this in the normal order so that the user doesn't get confused */ ata_link_for_each_dev(dev, &ap->link) { if (!ata_dev_enabled(dev)) continue; ap->link.eh_context.i.flags |= ATA_EHI_PRINTINFO; rc = ata_dev_configure(dev); ap->link.eh_context.i.flags &= ~ATA_EHI_PRINTINFO; if (rc) goto fail; } /* configure transfer mode */ rc = ata_set_mode(&ap->link, &dev); if (rc) goto fail; ata_link_for_each_dev(dev, &ap->link) if (ata_dev_enabled(dev)) return 0; /* no device present, disable port */ ata_port_disable(ap); return -ENODEV; fail: tries[dev->devno]--; switch (rc) { case -EINVAL: /* eeek, something went very wrong, give up */ tries[dev->devno] = 0; break; case -ENODEV: /* give it just one more chance */ tries[dev->devno] = min(tries[dev->devno], 1); case -EIO: if (tries[dev->devno] == 1) { /* This is the last chance, better to slow * down than lose it. */ sata_down_spd_limit(&ap->link); ata_down_xfermask_limit(dev, ATA_DNXFER_PIO); } } if (!tries[dev->devno]) ata_dev_disable(dev); goto retry;}/** * ata_port_probe - Mark port as enabled * @ap: Port for which we indicate enablement * * Modify @ap data structure such that the system * thinks that the entire port is enabled. * * LOCKING: host lock, or some other form of * serialization. */void ata_port_probe(struct ata_port *ap){ ap->flags &= ~ATA_FLAG_DISABLED;}/** * sata_print_link_status - Print SATA link status * @link: SATA link to printk link status about * * This function prints link speed and status of a SATA link. * * LOCKING: * None. */void sata_print_link_status(struct ata_link *link){ u32 sstatus, scontrol, tmp; if (sata_sc
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -