#include <linux/acpi.h>
#include <linux/libata.h>
#include <linux/pci.h>
+#include <scsi/scsi_device.h>
#include "libata.h"
#include <acpi/acpi_bus.h>
}
}
+static void ata_acpi_handle_hotplug (struct ata_port *ap, struct kobject *kobj,
+ u32 event)
+{
+ char event_string[12];
+ char *envp[] = { event_string, NULL };
+ struct ata_eh_info *ehi = &ap->link.eh_info;
+
+ if (event == 0 || event == 1) {
+ unsigned long flags;
+ spin_lock_irqsave(ap->lock, flags);
+ ata_ehi_clear_desc(ehi);
+ ata_ehi_push_desc(ehi, "ACPI event");
+ ata_ehi_hotplugged(ehi);
+ ata_port_freeze(ap);
+ spin_unlock_irqrestore(ap->lock, flags);
+ }
+
+ if (kobj) {
+ sprintf(event_string, "BAY_EVENT=%d", event);
+ kobject_uevent_env(kobj, KOBJ_CHANGE, envp);
+ }
+}
+
+static void ata_acpi_dev_notify(acpi_handle handle, u32 event, void *data)
+{
+ struct ata_device *dev = data;
+ struct kobject *kobj = NULL;
+
+ if (dev->sdev)
+ kobj = &dev->sdev->sdev_gendev.kobj;
+
+ ata_acpi_handle_hotplug (dev->link->ap, kobj, event);
+}
+
+static void ata_acpi_ap_notify(acpi_handle handle, u32 event, void *data)
+{
+ struct ata_port *ap = data;
+
+ ata_acpi_handle_hotplug (ap, &ap->dev->kobj, event);
+}
+
/**
* ata_acpi_associate - associate ATA host with ACPI objects
* @host: target ATA host
*/
void ata_acpi_associate(struct ata_host *host)
{
- int i;
+ int i, j;
if (!is_pci_dev(host->dev) || libata_noacpi)
return;
ata_acpi_associate_sata_port(ap);
else
ata_acpi_associate_ide_port(ap);
+
+ if (ap->acpi_handle)
+ acpi_install_notify_handler (ap->acpi_handle,
+ ACPI_SYSTEM_NOTIFY,
+ ata_acpi_ap_notify,
+ ap);
+
+ for (j = 0; j < ata_link_max_devices(&ap->link); j++) {
+ struct ata_device *dev = &ap->link.device[j];
+
+ if (dev->acpi_handle)
+ acpi_install_notify_handler (dev->acpi_handle,
+ ACPI_SYSTEM_NOTIFY,
+ ata_acpi_dev_notify,
+ dev);
+ }
}
}
* RETURNS:
* 0 on success, -ENOENT if _GTM doesn't exist, -errno on failure.
*/
-static int ata_acpi_gtm(const struct ata_port *ap, struct ata_acpi_gtm *gtm)
+int ata_acpi_gtm(const struct ata_port *ap, struct ata_acpi_gtm *gtm)
{
struct acpi_buffer output = { .length = ACPI_ALLOCATE_BUFFER };
union acpi_object *out_obj;
return rc;
}
+EXPORT_SYMBOL_GPL(ata_acpi_gtm);
+
/**
* ata_acpi_stm - execute _STM
* @ap: target ATA port
* RETURNS:
* 0 on success, -ENOENT if _STM doesn't exist, -errno on failure.
*/
-static int ata_acpi_stm(const struct ata_port *ap, struct ata_acpi_gtm *stm)
+int ata_acpi_stm(const struct ata_port *ap, struct ata_acpi_gtm *stm)
{
acpi_status status;
struct acpi_object_list input;
return 0;
}
+EXPORT_SYMBOL_GPL(ata_acpi_stm);
+
/**
* ata_dev_get_GTF - get the drive bootup default taskfile settings
* @dev: target ATA device
tf.lbal, tf.lbam, tf.lbah, tf.device);
rtf = tf;
- err_mask = ata_exec_internal(dev, &rtf, NULL, DMA_NONE, NULL, 0);
+ err_mask = ata_exec_internal(dev, &rtf, NULL, DMA_NONE, NULL, 0, 0);
if (err_mask) {
ata_dev_printk(dev, KERN_ERR,
"ACPI cmd %02x/%02x:%02x:%02x:%02x:%02x:%02x failed "