⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 libata-acpi.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
	return rc; out_free:	ata_acpi_clear_gtf(dev);	return rc;}/** * ata_acpi_cbl_80wire		-	Check for 80 wire cable * @ap: Port to check * * Return 1 if the ACPI mode data for this port indicates the BIOS selected * an 80wire mode. */int ata_acpi_cbl_80wire(struct ata_port *ap){	const struct ata_acpi_gtm *gtm = ata_acpi_init_gtm(ap);	int valid = 0;	if (!gtm)		return 0;	/* Split timing, DMA enabled */	if ((gtm->flags & 0x11) == 0x11 && gtm->drive[0].dma < 55)		valid |= 1;	if ((gtm->flags & 0x14) == 0x14 && gtm->drive[1].dma < 55)		valid |= 2;	/* Shared timing, DMA enabled */	if ((gtm->flags & 0x11) == 0x01 && gtm->drive[0].dma < 55)		valid |= 1;	if ((gtm->flags & 0x14) == 0x04 && gtm->drive[0].dma < 55)		valid |= 2;	/* Drive check */	if ((valid & 1) && ata_dev_enabled(&ap->link.device[0]))		return 1;	if ((valid & 2) && ata_dev_enabled(&ap->link.device[1]))		return 1;	return 0;}EXPORT_SYMBOL_GPL(ata_acpi_cbl_80wire);static void ata_acpi_gtf_to_tf(struct ata_device *dev,			       const struct ata_acpi_gtf *gtf,			       struct ata_taskfile *tf){	ata_tf_init(dev, tf);	tf->flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE;	tf->protocol = ATA_PROT_NODATA;	tf->feature = gtf->tf[0];	/* 0x1f1 */	tf->nsect   = gtf->tf[1];	/* 0x1f2 */	tf->lbal    = gtf->tf[2];	/* 0x1f3 */	tf->lbam    = gtf->tf[3];	/* 0x1f4 */	tf->lbah    = gtf->tf[4];	/* 0x1f5 */	tf->device  = gtf->tf[5];	/* 0x1f6 */	tf->command = gtf->tf[6];	/* 0x1f7 */}static int ata_acpi_filter_tf(const struct ata_taskfile *tf,			      const struct ata_taskfile *ptf){	if (ata_acpi_gtf_filter & ATA_ACPI_FILTER_SETXFER) {		/* libata doesn't use ACPI to configure transfer mode.		 * It will only confuse device configuration.  Skip.		 */		if (tf->command == ATA_CMD_SET_FEATURES &&		    tf->feature == SETFEATURES_XFER)			return 1;	}	if (ata_acpi_gtf_filter & ATA_ACPI_FILTER_LOCK) {		/* BIOS writers, sorry but we don't wanna lock		 * features unless the user explicitly said so.		 */		/* DEVICE CONFIGURATION FREEZE LOCK */		if (tf->command == ATA_CMD_CONF_OVERLAY &&		    tf->feature == ATA_DCO_FREEZE_LOCK)			return 1;		/* SECURITY FREEZE LOCK */		if (tf->command == ATA_CMD_SEC_FREEZE_LOCK)			return 1;		/* SET MAX LOCK and SET MAX FREEZE LOCK */		if ((!ptf || ptf->command != ATA_CMD_READ_NATIVE_MAX) &&		    tf->command == ATA_CMD_SET_MAX &&		    (tf->feature == ATA_SET_MAX_LOCK ||		     tf->feature == ATA_SET_MAX_FREEZE_LOCK))			return 1;	}	return 0;}/** * ata_acpi_run_tf - send taskfile registers to host controller * @dev: target ATA device * @gtf: raw ATA taskfile register set (0x1f1 - 0x1f7) * * Outputs ATA taskfile to standard ATA host controller using MMIO * or PIO as indicated by the ATA_FLAG_MMIO flag. * Writes the control, feature, nsect, lbal, lbam, and lbah registers. * Optionally (ATA_TFLAG_LBA48) writes hob_feature, hob_nsect, * hob_lbal, hob_lbam, and hob_lbah. * * This function waits for idle (!BUSY and !DRQ) after writing * registers.  If the control register has a new value, this * function also waits for idle after writing control and before * writing the remaining registers. * * LOCKING: * EH context. * * RETURNS: * 1 if command is executed successfully.  0 if ignored, rejected or * filtered out, -errno on other errors. */static int ata_acpi_run_tf(struct ata_device *dev,			   const struct ata_acpi_gtf *gtf,			   const struct ata_acpi_gtf *prev_gtf){	struct ata_taskfile *pptf = NULL;	struct ata_taskfile tf, ptf, rtf;	unsigned int err_mask;	const char *level;	char msg[60];	int rc;	if ((gtf->tf[0] == 0) && (gtf->tf[1] == 0) && (gtf->tf[2] == 0)	    && (gtf->tf[3] == 0) && (gtf->tf[4] == 0) && (gtf->tf[5] == 0)	    && (gtf->tf[6] == 0))		return 0;	ata_acpi_gtf_to_tf(dev, gtf, &tf);	if (prev_gtf) {		ata_acpi_gtf_to_tf(dev, prev_gtf, &ptf);		pptf = &ptf;	}	if (!ata_acpi_filter_tf(&tf, pptf)) {		rtf = tf;		err_mask = ata_exec_internal(dev, &rtf, NULL,					     DMA_NONE, NULL, 0, 0);		switch (err_mask) {		case 0:			level = KERN_DEBUG;			snprintf(msg, sizeof(msg), "succeeded");			rc = 1;			break;		case AC_ERR_DEV:			level = KERN_INFO;			snprintf(msg, sizeof(msg),				 "rejected by device (Stat=0x%02x Err=0x%02x)",				 rtf.command, rtf.feature);			rc = 0;			break;		default:			level = KERN_ERR;			snprintf(msg, sizeof(msg),				 "failed (Emask=0x%x Stat=0x%02x Err=0x%02x)",				 err_mask, rtf.command, rtf.feature);			rc = -EIO;			break;		}	} else {		level = KERN_INFO;		snprintf(msg, sizeof(msg), "filtered out");		rc = 0;	}	ata_dev_printk(dev, level,		       "ACPI cmd %02x/%02x:%02x:%02x:%02x:%02x:%02x %s\n",		       tf.command, tf.feature, tf.nsect, tf.lbal,		       tf.lbam, tf.lbah, tf.device, msg);	return rc;}/** * ata_acpi_exec_tfs - get then write drive taskfile settings * @dev: target ATA device * @nr_executed: out paramter for the number of executed commands * * Evaluate _GTF and excute returned taskfiles. * * LOCKING: * EH context. * * RETURNS: * Number of executed taskfiles on success, 0 if _GTF doesn't exist. * -errno on other errors. */static int ata_acpi_exec_tfs(struct ata_device *dev, int *nr_executed){	struct ata_acpi_gtf *gtf = NULL, *pgtf = NULL;	int gtf_count, i, rc;	/* get taskfiles */	rc = ata_dev_get_GTF(dev, &gtf);	if (rc < 0)		return rc;	gtf_count = rc;	/* execute them */	for (i = 0; i < gtf_count; i++, gtf++) {		rc = ata_acpi_run_tf(dev, gtf, pgtf);		if (rc < 0)			break;		if (rc) {			(*nr_executed)++;			pgtf = gtf;		}	}	ata_acpi_clear_gtf(dev);	if (rc < 0)		return rc;	return 0;}/** * ata_acpi_push_id - send Identify data to drive * @dev: target ATA device * * _SDD ACPI object: for SATA mode only * Must be after Identify (Packet) Device -- uses its data * ATM this function never returns a failure.  It is an optional * method and if it fails for whatever reason, we should still * just keep going. * * LOCKING: * EH context. * * RETURNS: * 0 on success, -errno on failure. */static int ata_acpi_push_id(struct ata_device *dev){	struct ata_port *ap = dev->link->ap;	int err;	acpi_status status;	struct acpi_object_list input;	union acpi_object in_params[1];	if (ata_msg_probe(ap))		ata_dev_printk(dev, KERN_DEBUG, "%s: ix = %d, port#: %d\n",			       __FUNCTION__, dev->devno, ap->port_no);	/* Give the drive Identify data to the drive via the _SDD method */	/* _SDD: set up input parameters */	input.count = 1;	input.pointer = in_params;	in_params[0].type = ACPI_TYPE_BUFFER;	in_params[0].buffer.length = sizeof(dev->id[0]) * ATA_ID_WORDS;	in_params[0].buffer.pointer = (u8 *)dev->id;	/* Output buffer: _SDD has no output */	/* It's OK for _SDD to be missing too. */	swap_buf_le16(dev->id, ATA_ID_WORDS);	status = acpi_evaluate_object(dev->acpi_handle, "_SDD", &input, NULL);	swap_buf_le16(dev->id, ATA_ID_WORDS);	err = ACPI_FAILURE(status) ? -EIO : 0;	if (err < 0)		ata_dev_printk(dev, KERN_WARNING,			       "ACPI _SDD failed (AE 0x%x)\n", status);	return err;}/** * ata_acpi_on_suspend - ATA ACPI hook called on suspend * @ap: target ATA port * * This function is called when @ap is about to be suspended.  All * devices are already put to sleep but the port_suspend() callback * hasn't been executed yet.  Error return from this function aborts * suspend. * * LOCKING: * EH context. * * RETURNS: * 0 on success, -errno on failure. */int ata_acpi_on_suspend(struct ata_port *ap){	/* nada */	return 0;}/** * ata_acpi_on_resume - ATA ACPI hook called on resume * @ap: target ATA port * * This function is called when @ap is resumed - right after port * itself is resumed but before any EH action is taken. * * LOCKING: * EH context. */void ata_acpi_on_resume(struct ata_port *ap){	const struct ata_acpi_gtm *gtm = ata_acpi_init_gtm(ap);	struct ata_device *dev;	if (ap->acpi_handle && gtm) {		/* _GTM valid */		/* restore timing parameters */		ata_acpi_stm(ap, gtm);		/* _GTF should immediately follow _STM so that it can		 * use values set by _STM.  Cache _GTF result and		 * schedule _GTF.		 */		ata_link_for_each_dev(dev, &ap->link) {			ata_acpi_clear_gtf(dev);			if (ata_dev_get_GTF(dev, NULL) >= 0)				dev->flags |= ATA_DFLAG_ACPI_PENDING;		}	} else {		/* SATA _GTF needs to be evaulated after _SDD and		 * there's no reason to evaluate IDE _GTF early		 * without _STM.  Clear cache and schedule _GTF.		 */		ata_link_for_each_dev(dev, &ap->link) {			ata_acpi_clear_gtf(dev);			dev->flags |= ATA_DFLAG_ACPI_PENDING;		}	}}/** * ata_acpi_on_devcfg - ATA ACPI hook called on device donfiguration * @dev: target ATA device * * This function is called when @dev is about to be configured. * IDENTIFY data might have been modified after this hook is run. * * LOCKING: * EH context. * * RETURNS: * Positive number if IDENTIFY data needs to be refreshed, 0 if not, * -errno on failure. */int ata_acpi_on_devcfg(struct ata_device *dev){	struct ata_port *ap = dev->link->ap;	struct ata_eh_context *ehc = &ap->link.eh_context;	int acpi_sata = ap->flags & ATA_FLAG_ACPI_SATA;	int nr_executed = 0;	int rc;	if (!dev->acpi_handle)		return 0;	/* do we need to do _GTF? */	if (!(dev->flags & ATA_DFLAG_ACPI_PENDING) &&	    !(acpi_sata && (ehc->i.flags & ATA_EHI_DID_HARDRESET)))		return 0;	/* do _SDD if SATA */	if (acpi_sata) {		rc = ata_acpi_push_id(dev);		if (rc)			goto acpi_err;	}	/* do _GTF */	rc = ata_acpi_exec_tfs(dev, &nr_executed);	if (rc)		goto acpi_err;	dev->flags &= ~ATA_DFLAG_ACPI_PENDING;	/* refresh IDENTIFY page if any _GTF command has been executed */	if (nr_executed) {		rc = ata_dev_reread_id(dev, 0);		if (rc < 0) {			ata_dev_printk(dev, KERN_ERR, "failed to IDENTIFY "				       "after ACPI commands\n");			return rc;		}	}	return 0; acpi_err:	/* ignore evaluation failure if we can continue safely */	if (rc == -EINVAL && !nr_executed && !(ap->pflags & ATA_PFLAG_FROZEN))		return 0;	/* fail and let EH retry once more for unknown IO errors */	if (!(dev->flags & ATA_DFLAG_ACPI_FAILED)) {		dev->flags |= ATA_DFLAG_ACPI_FAILED;		return rc;	}	ata_dev_printk(dev, KERN_WARNING,		       "ACPI: failed the second time, disabled\n");	dev->acpi_handle = NULL;	/* We can safely continue if no _GTF command has been executed	 * and port is not frozen.	 */	if (!nr_executed && !(ap->pflags & ATA_PFLAG_FROZEN))		return 0;	return rc;}/** * ata_acpi_on_disable - ATA ACPI hook called when a device is disabled * @dev: target ATA device * * This function is called when @dev is about to be disabled. * * LOCKING: * EH context. */void ata_acpi_on_disable(struct ata_device *dev){	ata_acpi_clear_gtf(dev);}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -