diff options
| -rw-r--r-- | arch/ia64/kernel/acpi-ext.c | 143 | ||||
| -rw-r--r-- | include/asm-ia64/acpi-ext.h | 11 |
2 files changed, 78 insertions, 76 deletions
diff --git a/arch/ia64/kernel/acpi-ext.c b/arch/ia64/kernel/acpi-ext.c index 4a5574ff007b..fff82929d225 100644 --- a/arch/ia64/kernel/acpi-ext.c +++ b/arch/ia64/kernel/acpi-ext.c | |||
| @@ -1,105 +1,104 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * arch/ia64/kernel/acpi-ext.c | 2 | * (c) Copyright 2003, 2006 Hewlett-Packard Development Company, L.P. |
| 3 | * Alex Williamson <alex.williamson@hp.com> | ||
| 4 | * Bjorn Helgaas <bjorn.helgaas@hp.com> | ||
| 3 | * | 5 | * |
| 4 | * Copyright (C) 2003 Hewlett-Packard | 6 | * This program is free software; you can redistribute it and/or modify |
| 5 | * Copyright (C) Alex Williamson | 7 | * it under the terms of the GNU General Public License version 2 as |
| 6 | * Copyright (C) Bjorn Helgaas | 8 | * published by the Free Software Foundation. |
| 7 | * | ||
| 8 | * Vendor specific extensions to ACPI. | ||
| 9 | */ | 9 | */ |
| 10 | 10 | ||
| 11 | #include <linux/config.h> | 11 | #include <linux/config.h> |
| 12 | #include <linux/module.h> | 12 | #include <linux/module.h> |
| 13 | #include <linux/types.h> | 13 | #include <linux/types.h> |
| 14 | #include <linux/acpi.h> | 14 | #include <linux/acpi.h> |
| 15 | #include <linux/efi.h> | ||
| 16 | 15 | ||
| 17 | #include <asm/acpi-ext.h> | 16 | #include <asm/acpi-ext.h> |
| 18 | 17 | ||
| 19 | struct acpi_vendor_descriptor { | 18 | /* |
| 20 | u8 guid_id; | 19 | * Device CSRs that do not appear in PCI config space should be described |
| 21 | efi_guid_t guid; | 20 | * via ACPI. This would normally be done with Address Space Descriptors |
| 22 | }; | 21 | * marked as "consumer-only," but old versions of Windows and Linux ignore |
| 22 | * the producer/consumer flag, so HP invented a vendor-defined resource to | ||
| 23 | * describe the location and size of CSR space. | ||
| 24 | */ | ||
| 23 | 25 | ||
| 24 | struct acpi_vendor_info { | 26 | struct acpi_vendor_uuid hp_ccsr_uuid = { |
| 25 | struct acpi_vendor_descriptor *descriptor; | 27 | .subtype = 2, |
| 26 | u8 *data; | 28 | .data = { 0xf9, 0xad, 0xe9, 0x69, 0x4f, 0x92, 0x5f, 0xab, 0xf6, 0x4a, |
| 27 | u32 length; | 29 | 0x24, 0xd2, 0x01, 0x37, 0x0e, 0xad }, |
| 28 | }; | 30 | }; |
| 29 | 31 | ||
| 30 | acpi_status | 32 | static acpi_status hp_ccsr_locate(acpi_handle obj, u64 *base, u64 *length) |
| 31 | acpi_vendor_resource_match(struct acpi_resource *resource, void *context) | ||
| 32 | { | 33 | { |
| 33 | struct acpi_vendor_info *info = (struct acpi_vendor_info *)context; | 34 | acpi_status status; |
| 34 | struct acpi_resource_vendor *vendor; | 35 | struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; |
| 35 | struct acpi_vendor_descriptor *descriptor; | 36 | struct acpi_resource *resource; |
| 36 | u32 byte_length; | 37 | struct acpi_resource_vendor_typed *vendor; |
| 37 | |||
| 38 | if (resource->type != ACPI_RESOURCE_TYPE_VENDOR) | ||
| 39 | return AE_OK; | ||
| 40 | |||
| 41 | vendor = (struct acpi_resource_vendor *)&resource->data; | ||
| 42 | descriptor = (struct acpi_vendor_descriptor *)vendor->byte_data; | ||
| 43 | if (vendor->byte_length <= sizeof(*info->descriptor) || | ||
| 44 | descriptor->guid_id != info->descriptor->guid_id || | ||
| 45 | efi_guidcmp(descriptor->guid, info->descriptor->guid)) | ||
| 46 | return AE_OK; | ||
| 47 | |||
| 48 | byte_length = vendor->byte_length - sizeof(struct acpi_vendor_descriptor); | ||
| 49 | info->data = acpi_os_allocate(byte_length); | ||
| 50 | if (!info->data) | ||
| 51 | return AE_NO_MEMORY; | ||
| 52 | |||
| 53 | memcpy(info->data, | ||
| 54 | vendor->byte_data + sizeof(struct acpi_vendor_descriptor), | ||
| 55 | byte_length); | ||
| 56 | info->length = byte_length; | ||
| 57 | return AE_CTRL_TERMINATE; | ||
| 58 | } | ||
| 59 | 38 | ||
| 60 | acpi_status | 39 | status = acpi_get_vendor_resource(obj, METHOD_NAME__CRS, &hp_ccsr_uuid, |
| 61 | acpi_find_vendor_resource(acpi_handle obj, struct acpi_vendor_descriptor * id, | 40 | &buffer); |
| 62 | u8 ** data, u32 * byte_length) | ||
| 63 | { | ||
| 64 | struct acpi_vendor_info info; | ||
| 65 | 41 | ||
| 66 | info.descriptor = id; | 42 | resource = buffer.pointer; |
| 67 | info.data = NULL; | 43 | vendor = &resource->data.vendor_typed; |
| 68 | 44 | ||
| 69 | acpi_walk_resources(obj, METHOD_NAME__CRS, acpi_vendor_resource_match, | 45 | if (ACPI_FAILURE(status) || vendor->byte_length < 16) { |
| 70 | &info); | 46 | status = AE_NOT_FOUND; |
| 71 | if (!info.data) | 47 | goto exit; |
| 72 | return AE_NOT_FOUND; | 48 | } |
| 73 | 49 | ||
| 74 | *data = info.data; | 50 | memcpy(base, vendor->byte_data, sizeof(*base)); |
| 75 | *byte_length = info.length; | 51 | memcpy(length, vendor->byte_data + 8, sizeof(*length)); |
| 76 | return AE_OK; | 52 | |
| 53 | exit: | ||
| 54 | acpi_os_free(buffer.pointer); | ||
| 55 | return status; | ||
| 77 | } | 56 | } |
| 78 | 57 | ||
| 79 | struct acpi_vendor_descriptor hp_ccsr_descriptor = { | 58 | struct csr_space { |
| 80 | .guid_id = 2, | 59 | u64 base; |
| 81 | .guid = | 60 | u64 length; |
| 82 | EFI_GUID(0x69e9adf9, 0x924f, 0xab5f, 0xf6, 0x4a, 0x24, 0xd2, 0x01, | ||
| 83 | 0x37, 0x0e, 0xad) | ||
| 84 | }; | 61 | }; |
| 85 | 62 | ||
| 86 | acpi_status hp_acpi_csr_space(acpi_handle obj, u64 * csr_base, u64 * csr_length) | 63 | static acpi_status find_csr_space(struct acpi_resource *resource, void *data) |
| 87 | { | 64 | { |
| 65 | struct csr_space *space = data; | ||
| 66 | struct acpi_resource_address64 addr; | ||
| 88 | acpi_status status; | 67 | acpi_status status; |
| 89 | u8 *data; | ||
| 90 | u32 length; | ||
| 91 | 68 | ||
| 92 | status = | 69 | status = acpi_resource_to_address64(resource, &addr); |
| 93 | acpi_find_vendor_resource(obj, &hp_ccsr_descriptor, &data, &length); | 70 | if (ACPI_SUCCESS(status) && |
| 71 | addr.resource_type == ACPI_MEMORY_RANGE && | ||
| 72 | addr.address_length && | ||
| 73 | addr.producer_consumer == ACPI_CONSUMER) { | ||
| 74 | space->base = addr.minimum; | ||
| 75 | space->length = addr.address_length; | ||
| 76 | return AE_CTRL_TERMINATE; | ||
| 77 | } | ||
| 78 | return AE_OK; /* keep looking */ | ||
| 79 | } | ||
| 94 | 80 | ||
| 95 | if (ACPI_FAILURE(status) || length != 16) | 81 | static acpi_status hp_crs_locate(acpi_handle obj, u64 *base, u64 *length) |
| 96 | return AE_NOT_FOUND; | 82 | { |
| 83 | struct csr_space space = { 0, 0 }; | ||
| 97 | 84 | ||
| 98 | memcpy(csr_base, data, sizeof(*csr_base)); | 85 | acpi_walk_resources(obj, METHOD_NAME__CRS, find_csr_space, &space); |
| 99 | memcpy(csr_length, data + 8, sizeof(*csr_length)); | 86 | if (!space.length) |
| 100 | acpi_os_free(data); | 87 | return AE_NOT_FOUND; |
| 101 | 88 | ||
| 89 | *base = space.base; | ||
| 90 | *length = space.length; | ||
| 102 | return AE_OK; | 91 | return AE_OK; |
| 103 | } | 92 | } |
| 104 | 93 | ||
| 94 | acpi_status hp_acpi_csr_space(acpi_handle obj, u64 *csr_base, u64 *csr_length) | ||
| 95 | { | ||
| 96 | acpi_status status; | ||
| 97 | |||
| 98 | status = hp_ccsr_locate(obj, csr_base, csr_length); | ||
| 99 | if (ACPI_SUCCESS(status)) | ||
| 100 | return status; | ||
| 101 | |||
| 102 | return hp_crs_locate(obj, csr_base, csr_length); | ||
| 103 | } | ||
| 105 | EXPORT_SYMBOL(hp_acpi_csr_space); | 104 | EXPORT_SYMBOL(hp_acpi_csr_space); |
diff --git a/include/asm-ia64/acpi-ext.h b/include/asm-ia64/acpi-ext.h index 56d2ddc97b30..734d137dda6e 100644 --- a/include/asm-ia64/acpi-ext.h +++ b/include/asm-ia64/acpi-ext.h | |||
| @@ -1,12 +1,15 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * ia64/platform/hp/common/hp_acpi.h | 2 | * (c) Copyright 2003, 2006 Hewlett-Packard Development Company, L.P. |
| 3 | * Alex Williamson <alex.williamson@hp.com> | ||
| 4 | * Bjorn Helgaas <bjorn.helgaas@hp.com> | ||
| 3 | * | 5 | * |
| 4 | * Copyright (C) 2003 Hewlett-Packard | 6 | * This program is free software; you can redistribute it and/or modify |
| 5 | * Copyright (C) Alex Williamson | 7 | * it under the terms of the GNU General Public License version 2 as |
| 6 | * Copyright (C) Bjorn Helgaas | 8 | * published by the Free Software Foundation. |
| 7 | * | 9 | * |
| 8 | * Vendor specific extensions to ACPI. | 10 | * Vendor specific extensions to ACPI. |
| 9 | */ | 11 | */ |
| 12 | |||
| 10 | #ifndef _ASM_IA64_ACPI_EXT_H | 13 | #ifndef _ASM_IA64_ACPI_EXT_H |
| 11 | #define _ASM_IA64_ACPI_EXT_H | 14 | #define _ASM_IA64_ACPI_EXT_H |
| 12 | 15 | ||
