aboutsummaryrefslogtreecommitdiffstats
path: root/arch/ia64/kernel/acpi-ext.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/ia64/kernel/acpi-ext.c')
-rw-r--r--arch/ia64/kernel/acpi-ext.c143
1 files changed, 71 insertions, 72 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
19struct 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
24struct acpi_vendor_info { 26struct 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
30acpi_status 32static acpi_status hp_ccsr_locate(acpi_handle obj, u64 *base, u64 *length)
31acpi_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
60acpi_status 39 status = acpi_get_vendor_resource(obj, METHOD_NAME__CRS, &hp_ccsr_uuid,
61acpi_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
79struct acpi_vendor_descriptor hp_ccsr_descriptor = { 58struct 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
86acpi_status hp_acpi_csr_space(acpi_handle obj, u64 * csr_base, u64 * csr_length) 63static 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) 81static 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
94acpi_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}
105EXPORT_SYMBOL(hp_acpi_csr_space); 104EXPORT_SYMBOL(hp_acpi_csr_space);