aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/pnp
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/pnp')
-rw-r--r--drivers/pnp/pnpacpi/rsparser.c60
1 files changed, 60 insertions, 0 deletions
diff --git a/drivers/pnp/pnpacpi/rsparser.c b/drivers/pnp/pnpacpi/rsparser.c
index c2f59f4d20bc..d7e9f2152df0 100644
--- a/drivers/pnp/pnpacpi/rsparser.c
+++ b/drivers/pnp/pnpacpi/rsparser.c
@@ -3,6 +3,8 @@
3 * 3 *
4 * Copyright (c) 2004 Matthieu Castet <castet.matthieu@free.fr> 4 * Copyright (c) 2004 Matthieu Castet <castet.matthieu@free.fr>
5 * Copyright (c) 2004 Li Shaohua <shaohua.li@intel.com> 5 * Copyright (c) 2004 Li Shaohua <shaohua.li@intel.com>
6 * Copyright (C) 2008 Hewlett-Packard Development Company, L.P.
7 * Bjorn Helgaas <bjorn.helgaas@hp.com>
6 * 8 *
7 * This program is free software; you can redistribute it and/or modify it 9 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the 10 * under the terms of the GNU General Public License as published by the
@@ -187,6 +189,61 @@ static void pnpacpi_parse_allocated_ioresource(struct pnp_dev *dev, u64 start,
187 pnp_add_io_resource(dev, start, end, flags); 189 pnp_add_io_resource(dev, start, end, flags);
188} 190}
189 191
192/*
193 * Device CSRs that do not appear in PCI config space should be described
194 * via ACPI. This would normally be done with Address Space Descriptors
195 * marked as "consumer-only," but old versions of Windows and Linux ignore
196 * the producer/consumer flag, so HP invented a vendor-defined resource to
197 * describe the location and size of CSR space.
198 */
199static struct acpi_vendor_uuid hp_ccsr_uuid = {
200 .subtype = 2,
201 .data = { 0xf9, 0xad, 0xe9, 0x69, 0x4f, 0x92, 0x5f, 0xab, 0xf6, 0x4a,
202 0x24, 0xd2, 0x01, 0x37, 0x0e, 0xad },
203};
204
205static int vendor_resource_matches(struct pnp_dev *dev,
206 struct acpi_resource_vendor_typed *vendor,
207 struct acpi_vendor_uuid *match,
208 int expected_len)
209{
210 int uuid_len = sizeof(vendor->uuid);
211 u8 uuid_subtype = vendor->uuid_subtype;
212 u8 *uuid = vendor->uuid;
213 int actual_len;
214
215 /* byte_length includes uuid_subtype and uuid */
216 actual_len = vendor->byte_length - uuid_len - 1;
217
218 if (uuid_subtype == match->subtype &&
219 uuid_len == sizeof(match->data) &&
220 memcmp(uuid, match->data, uuid_len) == 0) {
221 if (expected_len && expected_len != actual_len) {
222 dev_err(&dev->dev, "wrong vendor descriptor size; "
223 "expected %d, found %d bytes\n",
224 expected_len, actual_len);
225 return 0;
226 }
227
228 return 1;
229 }
230
231 return 0;
232}
233
234static void pnpacpi_parse_allocated_vendor(struct pnp_dev *dev,
235 struct acpi_resource_vendor_typed *vendor)
236{
237 if (vendor_resource_matches(dev, vendor, &hp_ccsr_uuid, 16)) {
238 u64 start, length;
239
240 memcpy(&start, vendor->byte_data, sizeof(start));
241 memcpy(&length, vendor->byte_data + 8, sizeof(length));
242
243 pnp_add_mem_resource(dev, start, start + length - 1, 0);
244 }
245}
246
190static void pnpacpi_parse_allocated_memresource(struct pnp_dev *dev, 247static void pnpacpi_parse_allocated_memresource(struct pnp_dev *dev,
191 u64 start, u64 len, 248 u64 start, u64 len,
192 int write_protect) 249 int write_protect)
@@ -237,6 +294,7 @@ static acpi_status pnpacpi_allocated_resource(struct acpi_resource *res,
237 struct acpi_resource_dma *dma; 294 struct acpi_resource_dma *dma;
238 struct acpi_resource_io *io; 295 struct acpi_resource_io *io;
239 struct acpi_resource_fixed_io *fixed_io; 296 struct acpi_resource_fixed_io *fixed_io;
297 struct acpi_resource_vendor_typed *vendor_typed;
240 struct acpi_resource_memory24 *memory24; 298 struct acpi_resource_memory24 *memory24;
241 struct acpi_resource_memory32 *memory32; 299 struct acpi_resource_memory32 *memory32;
242 struct acpi_resource_fixed_memory32 *fixed_memory32; 300 struct acpi_resource_fixed_memory32 *fixed_memory32;
@@ -306,6 +364,8 @@ static acpi_status pnpacpi_allocated_resource(struct acpi_resource *res,
306 break; 364 break;
307 365
308 case ACPI_RESOURCE_TYPE_VENDOR: 366 case ACPI_RESOURCE_TYPE_VENDOR:
367 vendor_typed = &res->data.vendor_typed;
368 pnpacpi_parse_allocated_vendor(dev, vendor_typed);
309 break; 369 break;
310 370
311 case ACPI_RESOURCE_TYPE_END_TAG: 371 case ACPI_RESOURCE_TYPE_END_TAG: