// SPDX-License-Identifier: GPL-2.0-only /* * libata-acpi.c * Provides ACPI support for PATA/SATA. * * Copyright (C) 2006 Intel Corp. * Copyright (C) 2006 Randy Dunlap */ #include <linux/module.h> #include <linux/ata.h> #include <linux/delay.h> #include <linux/device.h> #include <linux/errno.h> #include <linux/kernel.h> #include <linux/acpi.h> #include <linux/libata.h> #include <linux/pci.h> #include <linux/slab.h> #include <linux/pm_runtime.h> #include <scsi/scsi_device.h> #include "libata.h" unsigned int ata_acpi_gtf_filter = …; module_param_named(acpi_gtf_filter, ata_acpi_gtf_filter, int, 0644); MODULE_PARM_DESC(…) …; #define NO_PORT_MULT … #define SATA_ADR(root, pmp) … #define REGS_PER_GTF … struct ata_acpi_gtf { … } __packed; static void ata_acpi_clear_gtf(struct ata_device *dev) { … } struct ata_acpi_hotplug_context { … }; #define ata_hotplug_data(context) … /** * ata_dev_acpi_handle - provide the acpi_handle for an ata_device * @dev: the acpi_handle returned will correspond to this device * * Returns the acpi_handle for the ACPI namespace object corresponding to * the ata_device passed into the function, or NULL if no such object exists * or ACPI is disabled for this device due to consecutive errors. */ acpi_handle ata_dev_acpi_handle(struct ata_device *dev) { … } /* @ap and @dev are the same as ata_acpi_handle_hotplug() */ static void ata_acpi_detach_device(struct ata_port *ap, struct ata_device *dev) { … } /** * ata_acpi_handle_hotplug - ACPI event handler backend * @ap: ATA port ACPI event occurred * @dev: ATA device ACPI event occurred (can be NULL) * @event: ACPI event which occurred * * All ACPI bay / device realted events end up in this function. If * the event is port-wide @dev is NULL. If the event is specific to a * device, @dev points to it. * * Hotplug (as opposed to unplug) notification is always handled as * port-wide while unplug only kills the target device on device-wide * event. * * LOCKING: * ACPI notify handler context. May sleep. */ static void ata_acpi_handle_hotplug(struct ata_port *ap, struct ata_device *dev, u32 event) { … } static int ata_acpi_dev_notify_dock(struct acpi_device *adev, u32 event) { … } static int ata_acpi_ap_notify_dock(struct acpi_device *adev, u32 event) { … } static void ata_acpi_uevent(struct ata_port *ap, struct ata_device *dev, u32 event) { … } static void ata_acpi_ap_uevent(struct acpi_device *adev, u32 event) { … } static void ata_acpi_dev_uevent(struct acpi_device *adev, u32 event) { … } /* bind acpi handle to pata port */ void ata_acpi_bind_port(struct ata_port *ap) { … } void ata_acpi_bind_dev(struct ata_device *dev) { … } /** * ata_acpi_dissociate - dissociate ATA host from ACPI objects * @host: target ATA host * * This function is called during driver detach after the whole host * is shut down. * * LOCKING: * EH context. */ void ata_acpi_dissociate(struct ata_host *host) { … } /** * ata_acpi_gtm - execute _GTM * @ap: target ATA port * @gtm: out parameter for _GTM result * * Evaluate _GTM and store the result in @gtm. * * LOCKING: * EH context. * * RETURNS: * 0 on success, -ENOENT if _GTM doesn't exist, -errno on failure. */ int ata_acpi_gtm(struct ata_port *ap, struct ata_acpi_gtm *gtm) { … } EXPORT_SYMBOL_GPL(…); /** * ata_acpi_stm - execute _STM * @ap: target ATA port * @stm: timing parameter to _STM * * Evaluate _STM with timing parameter @stm. * * LOCKING: * EH context. * * RETURNS: * 0 on success, -ENOENT if _STM doesn't exist, -errno on failure. */ int ata_acpi_stm(struct ata_port *ap, const struct ata_acpi_gtm *stm) { … } EXPORT_SYMBOL_GPL(…); /** * ata_dev_get_GTF - get the drive bootup default taskfile settings * @dev: target ATA device * @gtf: output parameter for buffer containing _GTF taskfile arrays * * This applies to both PATA and SATA drives. * * The _GTF method has no input parameters. * It returns a variable number of register set values (registers * hex 1F1..1F7, taskfiles). * The <variable number> is not known in advance, so have ACPI-CA * allocate the buffer as needed and return it, then free it later. * * LOCKING: * EH context. * * RETURNS: * Number of taskfiles on success, 0 if _GTF doesn't exist. -EINVAL * if _GTF is invalid. */ static int ata_dev_get_GTF(struct ata_device *dev, struct ata_acpi_gtf **gtf) { … } /** * ata_acpi_gtm_xfermask - determine xfermode from GTM parameter * @dev: target device * @gtm: GTM parameter to use * * Determine xfermask for @dev from @gtm. * * LOCKING: * None. * * RETURNS: * Determined xfermask. */ unsigned int ata_acpi_gtm_xfermask(struct ata_device *dev, const struct ata_acpi_gtm *gtm) { … } EXPORT_SYMBOL_GPL(…); /** * ata_acpi_cbl_80wire - Check for 80 wire cable * @ap: Port to check * @gtm: GTM data to use * * Return 1 if the @gtm indicates the BIOS selected an 80wire mode. */ int ata_acpi_cbl_80wire(struct ata_port *ap, const struct ata_acpi_gtm *gtm) { … } EXPORT_SYMBOL_GPL(…); static void ata_acpi_gtf_to_tf(struct ata_device *dev, const struct ata_acpi_gtf *gtf, struct ata_taskfile *tf) { … } static int ata_acpi_filter_tf(struct ata_device *dev, const struct ata_taskfile *tf, const struct ata_taskfile *ptf) { … } /** * ata_acpi_run_tf - send taskfile registers to host controller * @dev: target ATA device * @gtf: raw ATA taskfile register set (0x1f1 - 0x1f7) * @prev_gtf: previous command * * Outputs ATA taskfile to standard ATA host controller. * 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) { … } /** * ata_acpi_exec_tfs - get then write drive taskfile settings * @dev: target ATA device * @nr_executed: out parameter for the number of executed commands * * Evaluate _GTF and execute 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) { … } /** * 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, -ENOENT if _SDD doesn't exist, -errno on failure. */ static int ata_acpi_push_id(struct ata_device *dev) { … } /** * 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) { … } static int ata_acpi_choose_suspend_state(struct ata_device *dev, bool runtime) { … } static void sata_acpi_set_state(struct ata_port *ap, pm_message_t state) { … } /* ACPI spec requires _PS0 when IDE power on and _PS3 when power off */ static void pata_acpi_set_state(struct ata_port *ap, pm_message_t state) { … } /** * ata_acpi_set_state - set the port power state * @ap: target ATA port * @state: state, on/off * * This function sets a proper ACPI D state for the device on * system and runtime PM operations. */ void ata_acpi_set_state(struct ata_port *ap, pm_message_t state) { … } /** * 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) { … } /** * 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) { … }