Merge tag 'scsi-misc' of git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi
[deliverable/linux.git] / drivers / pnp / pnpacpi / rsparser.c
CommitLineData
1da177e4
LT
1/*
2 * pnpacpi -- PnP ACPI driver
3 *
4 * Copyright (c) 2004 Matthieu Castet <castet.matthieu@free.fr>
5 * Copyright (c) 2004 Li Shaohua <shaohua.li@intel.com>
40ab4f4c
BH
6 * Copyright (C) 2008 Hewlett-Packard Development Company, L.P.
7 * Bjorn Helgaas <bjorn.helgaas@hp.com>
50eca3eb 8 *
1da177e4
LT
9 * This program is free software; you can redistribute it and/or modify it
10 * under the terms of the GNU General Public License as published by the
11 * Free Software Foundation; either version 2, or (at your option) any
12 * later version.
13 *
14 * This program is distributed in the hope that it will be useful, but
15 * WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 */
23#include <linux/kernel.h>
24#include <linux/acpi.h>
25#include <linux/pci.h>
02d83b5d 26#include <linux/pnp.h>
5a0e3ad6 27#include <linux/slab.h>
02d83b5d 28#include "../base.h"
1da177e4
LT
29#include "pnpacpi.h"
30
bbee06d0
FF
31static void decode_irq_flags(struct pnp_dev *dev, int flags, u8 *triggering,
32 u8 *polarity, u8 *shareable)
1da177e4 33{
e9fe9e18
BH
34 switch (flags & (IORESOURCE_IRQ_LOWLEVEL | IORESOURCE_IRQ_HIGHLEVEL |
35 IORESOURCE_IRQ_LOWEDGE | IORESOURCE_IRQ_HIGHEDGE)) {
1da177e4 36 case IORESOURCE_IRQ_LOWLEVEL:
50eca3eb
BM
37 *triggering = ACPI_LEVEL_SENSITIVE;
38 *polarity = ACPI_ACTIVE_LOW;
1da177e4 39 break;
1c6e7d0a 40 case IORESOURCE_IRQ_HIGHLEVEL:
50eca3eb
BM
41 *triggering = ACPI_LEVEL_SENSITIVE;
42 *polarity = ACPI_ACTIVE_HIGH;
1da177e4
LT
43 break;
44 case IORESOURCE_IRQ_LOWEDGE:
50eca3eb
BM
45 *triggering = ACPI_EDGE_SENSITIVE;
46 *polarity = ACPI_ACTIVE_LOW;
1da177e4
LT
47 break;
48 case IORESOURCE_IRQ_HIGHEDGE:
50eca3eb
BM
49 *triggering = ACPI_EDGE_SENSITIVE;
50 *polarity = ACPI_ACTIVE_HIGH;
1da177e4 51 break;
e9fe9e18
BH
52 default:
53 dev_err(&dev->dev, "can't encode invalid IRQ mode %#x\n",
54 flags);
55 *triggering = ACPI_EDGE_SENSITIVE;
56 *polarity = ACPI_ACTIVE_HIGH;
57 break;
1da177e4 58 }
a993273b
BH
59
60 if (flags & IORESOURCE_IRQ_SHAREABLE)
61 *shareable = ACPI_SHARED;
62 else
63 *shareable = ACPI_EXCLUSIVE;
1da177e4
LT
64}
65
958a1fdd
BH
66static int dma_flags(struct pnp_dev *dev, int type, int bus_master,
67 int transfer)
362ea087
MK
68{
69 int flags = 0;
70
71 if (bus_master)
72 flags |= IORESOURCE_DMA_MASTER;
73 switch (type) {
74 case ACPI_COMPATIBILITY:
75 flags |= IORESOURCE_DMA_COMPATIBLE;
76 break;
77 case ACPI_TYPE_A:
78 flags |= IORESOURCE_DMA_TYPEA;
79 break;
80 case ACPI_TYPE_B:
81 flags |= IORESOURCE_DMA_TYPEB;
82 break;
83 case ACPI_TYPE_F:
84 flags |= IORESOURCE_DMA_TYPEF;
85 break;
86 default:
87 /* Set a default value ? */
88 flags |= IORESOURCE_DMA_COMPATIBLE;
958a1fdd 89 dev_err(&dev->dev, "invalid DMA type %d\n", type);
362ea087
MK
90 }
91 switch (transfer) {
92 case ACPI_TRANSFER_8:
93 flags |= IORESOURCE_DMA_8BIT;
94 break;
95 case ACPI_TRANSFER_8_16:
96 flags |= IORESOURCE_DMA_8AND16BIT;
97 break;
98 case ACPI_TRANSFER_16:
99 flags |= IORESOURCE_DMA_16BIT;
100 break;
101 default:
102 /* Set a default value ? */
103 flags |= IORESOURCE_DMA_8AND16BIT;
958a1fdd 104 dev_err(&dev->dev, "invalid DMA transfer type %d\n", transfer);
362ea087
MK
105 }
106
107 return flags;
108}
109
046d9ce6
RW
110/*
111 * Allocated Resources
112 */
07d4e9af 113
046d9ce6
RW
114static void pnpacpi_add_irqresource(struct pnp_dev *dev, struct resource *r)
115{
116 if (!(r->flags & IORESOURCE_DISABLED))
117 pcibios_penalize_isa_irq(r->start, 1);
cc8c2e30 118
046d9ce6 119 pnp_add_resource(dev, r);
1da177e4
LT
120}
121
40ab4f4c
BH
122/*
123 * Device CSRs that do not appear in PCI config space should be described
124 * via ACPI. This would normally be done with Address Space Descriptors
125 * marked as "consumer-only," but old versions of Windows and Linux ignore
126 * the producer/consumer flag, so HP invented a vendor-defined resource to
127 * describe the location and size of CSR space.
128 */
129static struct acpi_vendor_uuid hp_ccsr_uuid = {
130 .subtype = 2,
131 .data = { 0xf9, 0xad, 0xe9, 0x69, 0x4f, 0x92, 0x5f, 0xab, 0xf6, 0x4a,
132 0x24, 0xd2, 0x01, 0x37, 0x0e, 0xad },
133};
134
135static int vendor_resource_matches(struct pnp_dev *dev,
136 struct acpi_resource_vendor_typed *vendor,
137 struct acpi_vendor_uuid *match,
138 int expected_len)
139{
140 int uuid_len = sizeof(vendor->uuid);
141 u8 uuid_subtype = vendor->uuid_subtype;
142 u8 *uuid = vendor->uuid;
143 int actual_len;
144
145 /* byte_length includes uuid_subtype and uuid */
146 actual_len = vendor->byte_length - uuid_len - 1;
147
148 if (uuid_subtype == match->subtype &&
149 uuid_len == sizeof(match->data) &&
150 memcmp(uuid, match->data, uuid_len) == 0) {
151 if (expected_len && expected_len != actual_len) {
152 dev_err(&dev->dev, "wrong vendor descriptor size; "
153 "expected %d, found %d bytes\n",
154 expected_len, actual_len);
155 return 0;
156 }
157
158 return 1;
159 }
160
161 return 0;
162}
163
164static void pnpacpi_parse_allocated_vendor(struct pnp_dev *dev,
165 struct acpi_resource_vendor_typed *vendor)
166{
167 if (vendor_resource_matches(dev, vendor, &hp_ccsr_uuid, 16)) {
168 u64 start, length;
169
170 memcpy(&start, vendor->byte_data, sizeof(start));
171 memcpy(&length, vendor->byte_data + 8, sizeof(length));
172
173 pnp_add_mem_resource(dev, start, start + length - 1, 0);
174 }
175}
176
1da177e4 177static acpi_status pnpacpi_allocated_resource(struct acpi_resource *res,
9dd78466 178 void *data)
1da177e4 179{
4ab55d8d 180 struct pnp_dev *dev = data;
9570a20e 181 struct acpi_resource_dma *dma;
40ab4f4c 182 struct acpi_resource_vendor_typed *vendor_typed;
a49170b5
JL
183 struct resource_win win = {{0}, 0};
184 struct resource *r = &win.res;
dc16f5f2 185 int i, flags;
1da177e4 186
a49170b5
JL
187 if (acpi_dev_resource_address_space(res, &win)
188 || acpi_dev_resource_ext_address_space(res, &win)) {
189 pnp_add_resource(dev, &win.res);
046d9ce6
RW
190 return AE_OK;
191 }
192
a49170b5
JL
193 r->flags = 0;
194 if (acpi_dev_resource_interrupt(res, 0, r)) {
195 pnpacpi_add_irqresource(dev, r);
196 for (i = 1; acpi_dev_resource_interrupt(res, i, r); i++)
197 pnpacpi_add_irqresource(dev, r);
5acf9141 198
046d9ce6 199 if (i > 1) {
5acf9141
BH
200 /*
201 * The IRQ encoder puts a single interrupt in each
202 * descriptor, so if a _CRS descriptor has more than
203 * one interrupt, we won't be able to re-encode it.
204 */
046d9ce6 205 if (pnp_can_write(dev)) {
5acf9141
BH
206 dev_warn(&dev->dev, "multiple interrupts in "
207 "_CRS descriptor; configuration can't "
208 "be changed\n");
209 dev->capabilities &= ~PNP_WRITE;
210 }
1da177e4 211 }
046d9ce6 212 return AE_OK;
a49170b5 213 } else if (r->flags & IORESOURCE_DISABLED) {
046d9ce6
RW
214 pnp_add_irq_resource(dev, 0, IORESOURCE_DISABLED);
215 return AE_OK;
216 }
1da177e4 217
046d9ce6 218 switch (res->type) {
89935315
ZR
219 case ACPI_RESOURCE_TYPE_MEMORY24:
220 case ACPI_RESOURCE_TYPE_MEMORY32:
221 case ACPI_RESOURCE_TYPE_FIXED_MEMORY32:
a49170b5
JL
222 if (acpi_dev_resource_memory(res, r))
223 pnp_add_resource(dev, r);
89935315
ZR
224 break;
225 case ACPI_RESOURCE_TYPE_IO:
226 case ACPI_RESOURCE_TYPE_FIXED_IO:
a49170b5
JL
227 if (acpi_dev_resource_io(res, r))
228 pnp_add_resource(dev, r);
89935315 229 break;
50eca3eb 230 case ACPI_RESOURCE_TYPE_DMA:
9570a20e 231 dma = &res->data.dma;
5acf9141 232 if (dma->channel_count > 0 && dma->channels[0] != (u8) -1)
958a1fdd 233 flags = dma_flags(dev, dma->type, dma->bus_master,
dc16f5f2 234 dma->transfer);
5acf9141
BH
235 else
236 flags = IORESOURCE_DISABLED;
237 pnp_add_dma_resource(dev, dma->channels[0], flags);
1da177e4 238 break;
0af5853b 239
0af5853b
LB
240 case ACPI_RESOURCE_TYPE_START_DEPENDENT:
241 case ACPI_RESOURCE_TYPE_END_DEPENDENT:
242 break;
243
0af5853b 244 case ACPI_RESOURCE_TYPE_VENDOR:
40ab4f4c
BH
245 vendor_typed = &res->data.vendor_typed;
246 pnpacpi_parse_allocated_vendor(dev, vendor_typed);
0af5853b
LB
247 break;
248
249 case ACPI_RESOURCE_TYPE_END_TAG:
250 break;
251
0af5853b 252 case ACPI_RESOURCE_TYPE_GENERIC_REGISTER:
1da177e4 253 break;
86e75410
HA
254
255 case ACPI_RESOURCE_TYPE_SERIAL_BUS:
256 /* serial bus connections (I2C/SPI/UART) are not pnp */
257 break;
0af5853b 258
1da177e4 259 default:
af11cb2d
BH
260 dev_warn(&dev->dev, "unknown resource type %d in _CRS\n",
261 res->type);
1da177e4
LT
262 return AE_ERROR;
263 }
1c6e7d0a 264
1da177e4
LT
265 return AE_OK;
266}
267
d152cf5d 268int pnpacpi_parse_allocated_resource(struct pnp_dev *dev)
1da177e4 269{
c4da6940
BH
270 struct acpi_device *acpi_dev = dev->data;
271 acpi_handle handle = acpi_dev->handle;
d152cf5d 272 acpi_status status;
4ab55d8d 273
2f53432c 274 pnp_dbg(&dev->dev, "parse allocated resources\n");
72dcc883 275
f4490002 276 pnp_init_resources(dev);
1da177e4 277
d152cf5d
BH
278 status = acpi_walk_resources(handle, METHOD_NAME__CRS,
279 pnpacpi_allocated_resource, dev);
280
281 if (ACPI_FAILURE(status)) {
282 if (status != AE_NOT_FOUND)
283 dev_err(&dev->dev, "can't evaluate _CRS: %d", status);
284 return -EPERM;
285 }
286 return 0;
1da177e4
LT
287}
288
c1caf06c 289static __init void pnpacpi_parse_dma_option(struct pnp_dev *dev,
1f32ca31 290 unsigned int option_flags,
2bb9a6b3 291 struct acpi_resource_dma *p)
1da177e4
LT
292{
293 int i;
18fd470a 294 unsigned char map = 0, flags;
1da177e4 295
9dd78466 296 for (i = 0; i < p->channel_count; i++)
c227536b 297 map |= 1 << p->channels[i];
1da177e4 298
18fd470a 299 flags = dma_flags(dev, p->type, p->bus_master, p->transfer);
1f32ca31 300 pnp_register_dma_resource(dev, option_flags, map, flags);
1da177e4
LT
301}
302
c1caf06c 303static __init void pnpacpi_parse_irq_option(struct pnp_dev *dev,
1f32ca31 304 unsigned int option_flags,
2bb9a6b3 305 struct acpi_resource_irq *p)
1da177e4
LT
306{
307 int i;
c227536b 308 pnp_irq_mask_t map;
18fd470a 309 unsigned char flags;
1da177e4 310
c227536b 311 bitmap_zero(map.bits, PNP_IRQ_NR);
9dd78466 312 for (i = 0; i < p->interrupt_count; i++)
1da177e4 313 if (p->interrupts[i])
c227536b 314 __set_bit(p->interrupts[i], map.bits);
1da177e4 315
046d9ce6 316 flags = acpi_dev_irq_flags(p->triggering, p->polarity, p->sharable);
1f32ca31 317 pnp_register_irq_resource(dev, option_flags, &map, flags);
1da177e4
LT
318}
319
c1caf06c 320static __init void pnpacpi_parse_ext_irq_option(struct pnp_dev *dev,
1f32ca31 321 unsigned int option_flags,
2bb9a6b3 322 struct acpi_resource_extended_irq *p)
1da177e4
LT
323{
324 int i;
c227536b 325 pnp_irq_mask_t map;
18fd470a 326 unsigned char flags;
1da177e4 327
c227536b 328 bitmap_zero(map.bits, PNP_IRQ_NR);
fe2cf598
BH
329 for (i = 0; i < p->interrupt_count; i++) {
330 if (p->interrupts[i]) {
331 if (p->interrupts[i] < PNP_IRQ_NR)
332 __set_bit(p->interrupts[i], map.bits);
333 else
334 dev_err(&dev->dev, "ignoring IRQ %d option "
335 "(too large for %d entry bitmap)\n",
336 p->interrupts[i], PNP_IRQ_NR);
337 }
338 }
1da177e4 339
046d9ce6 340 flags = acpi_dev_irq_flags(p->triggering, p->polarity, p->sharable);
1f32ca31 341 pnp_register_irq_resource(dev, option_flags, &map, flags);
1da177e4
LT
342}
343
c1caf06c 344static __init void pnpacpi_parse_port_option(struct pnp_dev *dev,
1f32ca31 345 unsigned int option_flags,
2bb9a6b3 346 struct acpi_resource_io *io)
1da177e4 347{
c227536b 348 unsigned char flags = 0;
1da177e4 349
c227536b 350 if (io->io_decode == ACPI_DECODE_16)
18fd470a 351 flags = IORESOURCE_IO_16BIT_ADDR;
1f32ca31 352 pnp_register_port_resource(dev, option_flags, io->minimum, io->maximum,
c227536b 353 io->alignment, io->address_length, flags);
1da177e4
LT
354}
355
c1caf06c 356static __init void pnpacpi_parse_fixed_port_option(struct pnp_dev *dev,
1f32ca31 357 unsigned int option_flags,
2bb9a6b3 358 struct acpi_resource_fixed_io *io)
1da177e4 359{
1f32ca31 360 pnp_register_port_resource(dev, option_flags, io->address, io->address,
18fd470a 361 0, io->address_length, IORESOURCE_IO_FIXED);
1da177e4
LT
362}
363
c1caf06c 364static __init void pnpacpi_parse_mem24_option(struct pnp_dev *dev,
1f32ca31 365 unsigned int option_flags,
2bb9a6b3 366 struct acpi_resource_memory24 *p)
1da177e4 367{
c227536b 368 unsigned char flags = 0;
1da177e4 369
c227536b 370 if (p->write_protect == ACPI_READ_WRITE_MEMORY)
18fd470a 371 flags = IORESOURCE_MEM_WRITEABLE;
1f32ca31 372 pnp_register_mem_resource(dev, option_flags, p->minimum, p->maximum,
c227536b 373 p->alignment, p->address_length, flags);
1da177e4
LT
374}
375
c1caf06c 376static __init void pnpacpi_parse_mem32_option(struct pnp_dev *dev,
1f32ca31 377 unsigned int option_flags,
2bb9a6b3 378 struct acpi_resource_memory32 *p)
1da177e4 379{
c227536b 380 unsigned char flags = 0;
1da177e4 381
c227536b 382 if (p->write_protect == ACPI_READ_WRITE_MEMORY)
18fd470a 383 flags = IORESOURCE_MEM_WRITEABLE;
1f32ca31 384 pnp_register_mem_resource(dev, option_flags, p->minimum, p->maximum,
c227536b 385 p->alignment, p->address_length, flags);
1da177e4
LT
386}
387
c1caf06c 388static __init void pnpacpi_parse_fixed_mem32_option(struct pnp_dev *dev,
1f32ca31 389 unsigned int option_flags,
2bb9a6b3 390 struct acpi_resource_fixed_memory32 *p)
1da177e4 391{
c227536b 392 unsigned char flags = 0;
1da177e4 393
c227536b 394 if (p->write_protect == ACPI_READ_WRITE_MEMORY)
18fd470a 395 flags = IORESOURCE_MEM_WRITEABLE;
1f32ca31 396 pnp_register_mem_resource(dev, option_flags, p->address, p->address,
c227536b 397 0, p->address_length, flags);
1da177e4
LT
398}
399
c1caf06c 400static __init void pnpacpi_parse_address_option(struct pnp_dev *dev,
1f32ca31 401 unsigned int option_flags,
2bb9a6b3 402 struct acpi_resource *r)
6f957eaf
BH
403{
404 struct acpi_resource_address64 addr, *p = &addr;
405 acpi_status status;
c227536b 406 unsigned char flags = 0;
6f957eaf
BH
407
408 status = acpi_resource_to_address64(r, p);
958a1fdd
BH
409 if (ACPI_FAILURE(status)) {
410 dev_warn(&dev->dev, "can't convert resource type %d\n",
9dd78466 411 r->type);
6f957eaf
BH
412 return;
413 }
414
6f957eaf 415 if (p->resource_type == ACPI_MEMORY_RANGE) {
c227536b 416 if (p->info.mem.write_protect == ACPI_READ_WRITE_MEMORY)
18fd470a 417 flags = IORESOURCE_MEM_WRITEABLE;
a45de93e
LZ
418 pnp_register_mem_resource(dev, option_flags, p->address.minimum,
419 p->address.minimum, 0, p->address.address_length,
1f32ca31 420 flags);
c227536b 421 } else if (p->resource_type == ACPI_IO_RANGE)
a45de93e
LZ
422 pnp_register_port_resource(dev, option_flags, p->address.minimum,
423 p->address.minimum, 0, p->address.address_length,
18fd470a 424 IORESOURCE_IO_FIXED);
6f957eaf
BH
425}
426
8cb24c8f
BH
427static __init void pnpacpi_parse_ext_address_option(struct pnp_dev *dev,
428 unsigned int option_flags,
429 struct acpi_resource *r)
430{
431 struct acpi_resource_extended_address64 *p = &r->data.ext_address64;
432 unsigned char flags = 0;
433
8cb24c8f
BH
434 if (p->resource_type == ACPI_MEMORY_RANGE) {
435 if (p->info.mem.write_protect == ACPI_READ_WRITE_MEMORY)
18fd470a 436 flags = IORESOURCE_MEM_WRITEABLE;
a45de93e
LZ
437 pnp_register_mem_resource(dev, option_flags, p->address.minimum,
438 p->address.minimum, 0, p->address.address_length,
8cb24c8f
BH
439 flags);
440 } else if (p->resource_type == ACPI_IO_RANGE)
a45de93e
LZ
441 pnp_register_port_resource(dev, option_flags, p->address.minimum,
442 p->address.minimum, 0, p->address.address_length,
18fd470a 443 IORESOURCE_IO_FIXED);
8cb24c8f
BH
444}
445
1da177e4 446struct acpipnp_parse_option_s {
1da177e4 447 struct pnp_dev *dev;
1f32ca31 448 unsigned int option_flags;
1da177e4
LT
449};
450
2bb9a6b3
TR
451static __init acpi_status pnpacpi_option_resource(struct acpi_resource *res,
452 void *data)
1da177e4 453{
e2a1a6f1 454 int priority;
4721a4cc 455 struct acpipnp_parse_option_s *parse_data = data;
1da177e4 456 struct pnp_dev *dev = parse_data->dev;
1f32ca31 457 unsigned int option_flags = parse_data->option_flags;
1da177e4 458
eca008c8 459 switch (res->type) {
9dd78466 460 case ACPI_RESOURCE_TYPE_IRQ:
1f32ca31 461 pnpacpi_parse_irq_option(dev, option_flags, &res->data.irq);
9dd78466 462 break;
0af5853b 463
9dd78466 464 case ACPI_RESOURCE_TYPE_DMA:
1f32ca31 465 pnpacpi_parse_dma_option(dev, option_flags, &res->data.dma);
9dd78466 466 break;
0af5853b 467
9dd78466
BH
468 case ACPI_RESOURCE_TYPE_START_DEPENDENT:
469 switch (res->data.start_dpf.compatibility_priority) {
470 case ACPI_GOOD_CONFIGURATION:
471 priority = PNP_RES_PRIORITY_PREFERRED;
1da177e4 472 break;
0af5853b 473
9dd78466
BH
474 case ACPI_ACCEPTABLE_CONFIGURATION:
475 priority = PNP_RES_PRIORITY_ACCEPTABLE;
b008b8d7 476 break;
0af5853b 477
9dd78466
BH
478 case ACPI_SUB_OPTIMAL_CONFIGURATION:
479 priority = PNP_RES_PRIORITY_FUNCTIONAL;
0af5853b 480 break;
9dd78466
BH
481 default:
482 priority = PNP_RES_PRIORITY_INVALID;
0af5853b 483 break;
9dd78466 484 }
1f32ca31 485 parse_data->option_flags = pnp_new_dependent_set(dev, priority);
9dd78466 486 break;
0af5853b 487
9dd78466 488 case ACPI_RESOURCE_TYPE_END_DEPENDENT:
1f32ca31 489 parse_data->option_flags = 0;
9dd78466 490 break;
0af5853b 491
9dd78466 492 case ACPI_RESOURCE_TYPE_IO:
1f32ca31 493 pnpacpi_parse_port_option(dev, option_flags, &res->data.io);
9dd78466 494 break;
0af5853b 495
9dd78466 496 case ACPI_RESOURCE_TYPE_FIXED_IO:
1f32ca31 497 pnpacpi_parse_fixed_port_option(dev, option_flags,
c1caf06c 498 &res->data.fixed_io);
9dd78466 499 break;
0af5853b 500
9dd78466
BH
501 case ACPI_RESOURCE_TYPE_VENDOR:
502 case ACPI_RESOURCE_TYPE_END_TAG:
503 break;
0af5853b 504
9dd78466 505 case ACPI_RESOURCE_TYPE_MEMORY24:
1f32ca31
BH
506 pnpacpi_parse_mem24_option(dev, option_flags,
507 &res->data.memory24);
9dd78466 508 break;
0af5853b 509
9dd78466 510 case ACPI_RESOURCE_TYPE_MEMORY32:
1f32ca31
BH
511 pnpacpi_parse_mem32_option(dev, option_flags,
512 &res->data.memory32);
9dd78466 513 break;
0af5853b 514
9dd78466 515 case ACPI_RESOURCE_TYPE_FIXED_MEMORY32:
1f32ca31 516 pnpacpi_parse_fixed_mem32_option(dev, option_flags,
9dd78466
BH
517 &res->data.fixed_memory32);
518 break;
0af5853b 519
9dd78466
BH
520 case ACPI_RESOURCE_TYPE_ADDRESS16:
521 case ACPI_RESOURCE_TYPE_ADDRESS32:
522 case ACPI_RESOURCE_TYPE_ADDRESS64:
1f32ca31 523 pnpacpi_parse_address_option(dev, option_flags, res);
9dd78466 524 break;
0af5853b 525
9dd78466 526 case ACPI_RESOURCE_TYPE_EXTENDED_ADDRESS64:
8cb24c8f 527 pnpacpi_parse_ext_address_option(dev, option_flags, res);
9dd78466
BH
528 break;
529
530 case ACPI_RESOURCE_TYPE_EXTENDED_IRQ:
1f32ca31 531 pnpacpi_parse_ext_irq_option(dev, option_flags,
c1caf06c 532 &res->data.extended_irq);
9dd78466
BH
533 break;
534
535 case ACPI_RESOURCE_TYPE_GENERIC_REGISTER:
536 break;
537
538 default:
af11cb2d
BH
539 dev_warn(&dev->dev, "unknown resource type %d in _PRS\n",
540 res->type);
9dd78466 541 return AE_ERROR;
1da177e4 542 }
1c6e7d0a 543
1da177e4
LT
544 return AE_OK;
545}
546
d152cf5d 547int __init pnpacpi_parse_resource_option_data(struct pnp_dev *dev)
1da177e4 548{
c4da6940
BH
549 struct acpi_device *acpi_dev = dev->data;
550 acpi_handle handle = acpi_dev->handle;
1da177e4
LT
551 acpi_status status;
552 struct acpipnp_parse_option_s parse_data;
553
2f53432c 554 pnp_dbg(&dev->dev, "parse resource options\n");
72dcc883 555
1da177e4 556 parse_data.dev = dev;
1f32ca31
BH
557 parse_data.option_flags = 0;
558
50eca3eb 559 status = acpi_walk_resources(handle, METHOD_NAME__PRS,
9dd78466 560 pnpacpi_option_resource, &parse_data);
1da177e4 561
d152cf5d
BH
562 if (ACPI_FAILURE(status)) {
563 if (status != AE_NOT_FOUND)
564 dev_err(&dev->dev, "can't evaluate _PRS: %d", status);
565 return -EPERM;
566 }
567 return 0;
1da177e4
LT
568}
569
b5f2490b 570static int pnpacpi_supported_resource(struct acpi_resource *res)
1da177e4 571{
eca008c8 572 switch (res->type) {
50eca3eb 573 case ACPI_RESOURCE_TYPE_IRQ:
50eca3eb
BM
574 case ACPI_RESOURCE_TYPE_DMA:
575 case ACPI_RESOURCE_TYPE_IO:
576 case ACPI_RESOURCE_TYPE_FIXED_IO:
577 case ACPI_RESOURCE_TYPE_MEMORY24:
578 case ACPI_RESOURCE_TYPE_MEMORY32:
579 case ACPI_RESOURCE_TYPE_FIXED_MEMORY32:
50eca3eb
BM
580 case ACPI_RESOURCE_TYPE_ADDRESS16:
581 case ACPI_RESOURCE_TYPE_ADDRESS32:
582 case ACPI_RESOURCE_TYPE_ADDRESS64:
8cb24c8f 583 case ACPI_RESOURCE_TYPE_EXTENDED_ADDRESS64:
0af5853b 584 case ACPI_RESOURCE_TYPE_EXTENDED_IRQ:
b5f2490b 585 return 1;
1da177e4 586 }
b5f2490b
BH
587 return 0;
588}
589
590/*
591 * Set resource
592 */
593static acpi_status pnpacpi_count_resources(struct acpi_resource *res,
9dd78466 594 void *data)
b5f2490b 595{
4721a4cc 596 int *res_cnt = data;
b5f2490b
BH
597
598 if (pnpacpi_supported_resource(res))
599 (*res_cnt)++;
1da177e4
LT
600 return AE_OK;
601}
602
1c6e7d0a 603static acpi_status pnpacpi_type_resources(struct acpi_resource *res, void *data)
1da177e4 604{
4721a4cc 605 struct acpi_resource **resource = data;
b5f2490b
BH
606
607 if (pnpacpi_supported_resource(res)) {
eca008c8 608 (*resource)->type = res->type;
b5f2490b 609 (*resource)->length = sizeof(struct acpi_resource);
36d872a3
BH
610 if (res->type == ACPI_RESOURCE_TYPE_IRQ)
611 (*resource)->data.irq.descriptor_length =
612 res->data.irq.descriptor_length;
1da177e4 613 (*resource)++;
1da177e4
LT
614 }
615
616 return AE_OK;
617}
618
cdef6254 619int pnpacpi_build_resource_template(struct pnp_dev *dev,
9dd78466 620 struct acpi_buffer *buffer)
1da177e4 621{
c4da6940
BH
622 struct acpi_device *acpi_dev = dev->data;
623 acpi_handle handle = acpi_dev->handle;
1da177e4
LT
624 struct acpi_resource *resource;
625 int res_cnt = 0;
626 acpi_status status;
627
50eca3eb 628 status = acpi_walk_resources(handle, METHOD_NAME__CRS,
9dd78466 629 pnpacpi_count_resources, &res_cnt);
1da177e4 630 if (ACPI_FAILURE(status)) {
d152cf5d 631 dev_err(&dev->dev, "can't evaluate _CRS: %d\n", status);
1da177e4
LT
632 return -EINVAL;
633 }
634 if (!res_cnt)
635 return -EINVAL;
636 buffer->length = sizeof(struct acpi_resource) * (res_cnt + 1) + 1;
cd861280 637 buffer->pointer = kzalloc(buffer->length - 1, GFP_KERNEL);
1da177e4
LT
638 if (!buffer->pointer)
639 return -ENOMEM;
72dcc883 640
1da177e4 641 resource = (struct acpi_resource *)buffer->pointer;
50eca3eb 642 status = acpi_walk_resources(handle, METHOD_NAME__CRS,
9dd78466 643 pnpacpi_type_resources, &resource);
1da177e4
LT
644 if (ACPI_FAILURE(status)) {
645 kfree(buffer->pointer);
d152cf5d 646 dev_err(&dev->dev, "can't evaluate _CRS: %d\n", status);
1da177e4
LT
647 return -EINVAL;
648 }
649 /* resource will pointer the end resource now */
50eca3eb 650 resource->type = ACPI_RESOURCE_TYPE_END_TAG;
f084dbb9 651 resource->length = sizeof(struct acpi_resource);
1da177e4
LT
652
653 return 0;
654}
655
72dcc883
BH
656static void pnpacpi_encode_irq(struct pnp_dev *dev,
657 struct acpi_resource *resource,
9dd78466 658 struct resource *p)
1da177e4 659{
9570a20e 660 struct acpi_resource_irq *irq = &resource->data.irq;
bbee06d0 661 u8 triggering, polarity, shareable;
1c6e7d0a 662
aee3ad81
BH
663 if (!pnp_resource_enabled(p)) {
664 irq->interrupt_count = 0;
2f53432c 665 pnp_dbg(&dev->dev, " encode irq (%s)\n",
aee3ad81
BH
666 p ? "disabled" : "missing");
667 return;
668 }
669
a993273b 670 decode_irq_flags(dev, p->flags, &triggering, &polarity, &shareable);
9570a20e
BH
671 irq->triggering = triggering;
672 irq->polarity = polarity;
a993273b 673 irq->sharable = shareable;
9570a20e
BH
674 irq->interrupt_count = 1;
675 irq->interrupts[0] = p->start;
72dcc883 676
2f53432c 677 pnp_dbg(&dev->dev, " encode irq %d %s %s %s (%d-byte descriptor)\n",
36d872a3 678 (int) p->start,
72dcc883
BH
679 triggering == ACPI_LEVEL_SENSITIVE ? "level" : "edge",
680 polarity == ACPI_ACTIVE_LOW ? "low" : "high",
36d872a3
BH
681 irq->sharable == ACPI_SHARED ? "shared" : "exclusive",
682 irq->descriptor_length);
1da177e4
LT
683}
684
72dcc883
BH
685static void pnpacpi_encode_ext_irq(struct pnp_dev *dev,
686 struct acpi_resource *resource,
9dd78466 687 struct resource *p)
1da177e4 688{
9570a20e 689 struct acpi_resource_extended_irq *extended_irq = &resource->data.extended_irq;
bbee06d0 690 u8 triggering, polarity, shareable;
1c6e7d0a 691
aee3ad81
BH
692 if (!pnp_resource_enabled(p)) {
693 extended_irq->interrupt_count = 0;
2f53432c 694 pnp_dbg(&dev->dev, " encode extended irq (%s)\n",
aee3ad81
BH
695 p ? "disabled" : "missing");
696 return;
697 }
698
a993273b 699 decode_irq_flags(dev, p->flags, &triggering, &polarity, &shareable);
9570a20e
BH
700 extended_irq->producer_consumer = ACPI_CONSUMER;
701 extended_irq->triggering = triggering;
702 extended_irq->polarity = polarity;
a993273b 703 extended_irq->sharable = shareable;
9570a20e
BH
704 extended_irq->interrupt_count = 1;
705 extended_irq->interrupts[0] = p->start;
72dcc883 706
2f53432c 707 pnp_dbg(&dev->dev, " encode irq %d %s %s %s\n", (int) p->start,
72dcc883
BH
708 triggering == ACPI_LEVEL_SENSITIVE ? "level" : "edge",
709 polarity == ACPI_ACTIVE_LOW ? "low" : "high",
710 extended_irq->sharable == ACPI_SHARED ? "shared" : "exclusive");
1da177e4
LT
711}
712
72dcc883
BH
713static void pnpacpi_encode_dma(struct pnp_dev *dev,
714 struct acpi_resource *resource,
9dd78466 715 struct resource *p)
1da177e4 716{
9570a20e
BH
717 struct acpi_resource_dma *dma = &resource->data.dma;
718
aee3ad81
BH
719 if (!pnp_resource_enabled(p)) {
720 dma->channel_count = 0;
2f53432c 721 pnp_dbg(&dev->dev, " encode dma (%s)\n",
aee3ad81
BH
722 p ? "disabled" : "missing");
723 return;
724 }
725
1da177e4 726 /* Note: pnp_assign_dma will copy pnp_dma->flags into p->flags */
ccc4c7bb 727 switch (p->flags & IORESOURCE_DMA_SPEED_MASK) {
9dd78466 728 case IORESOURCE_DMA_TYPEA:
9570a20e 729 dma->type = ACPI_TYPE_A;
9dd78466
BH
730 break;
731 case IORESOURCE_DMA_TYPEB:
9570a20e 732 dma->type = ACPI_TYPE_B;
9dd78466
BH
733 break;
734 case IORESOURCE_DMA_TYPEF:
9570a20e 735 dma->type = ACPI_TYPE_F;
9dd78466
BH
736 break;
737 default:
9570a20e 738 dma->type = ACPI_COMPATIBILITY;
ccc4c7bb
VP
739 }
740
741 switch (p->flags & IORESOURCE_DMA_TYPE_MASK) {
9dd78466 742 case IORESOURCE_DMA_8BIT:
9570a20e 743 dma->transfer = ACPI_TRANSFER_8;
9dd78466
BH
744 break;
745 case IORESOURCE_DMA_8AND16BIT:
9570a20e 746 dma->transfer = ACPI_TRANSFER_8_16;
9dd78466
BH
747 break;
748 default:
9570a20e 749 dma->transfer = ACPI_TRANSFER_16;
ccc4c7bb
VP
750 }
751
9570a20e
BH
752 dma->bus_master = !!(p->flags & IORESOURCE_DMA_MASTER);
753 dma->channel_count = 1;
754 dma->channels[0] = p->start;
72dcc883 755
2f53432c 756 pnp_dbg(&dev->dev, " encode dma %d "
72dcc883
BH
757 "type %#x transfer %#x master %d\n",
758 (int) p->start, dma->type, dma->transfer, dma->bus_master);
1da177e4
LT
759}
760
72dcc883
BH
761static void pnpacpi_encode_io(struct pnp_dev *dev,
762 struct acpi_resource *resource,
9dd78466 763 struct resource *p)
1da177e4 764{
9570a20e
BH
765 struct acpi_resource_io *io = &resource->data.io;
766
aee3ad81
BH
767 if (pnp_resource_enabled(p)) {
768 /* Note: pnp_assign_port copies pnp_port->flags into p->flags */
08c9f262 769 io->io_decode = (p->flags & IORESOURCE_IO_16BIT_ADDR) ?
aee3ad81
BH
770 ACPI_DECODE_16 : ACPI_DECODE_10;
771 io->minimum = p->start;
772 io->maximum = p->end;
773 io->alignment = 0; /* Correct? */
28f65c11 774 io->address_length = resource_size(p);
aee3ad81
BH
775 } else {
776 io->minimum = 0;
777 io->address_length = 0;
778 }
72dcc883 779
2f53432c 780 pnp_dbg(&dev->dev, " encode io %#x-%#x decode %#x\n", io->minimum,
aee3ad81 781 io->minimum + io->address_length - 1, io->io_decode);
1da177e4
LT
782}
783
72dcc883
BH
784static void pnpacpi_encode_fixed_io(struct pnp_dev *dev,
785 struct acpi_resource *resource,
9dd78466 786 struct resource *p)
1da177e4 787{
9570a20e
BH
788 struct acpi_resource_fixed_io *fixed_io = &resource->data.fixed_io;
789
aee3ad81
BH
790 if (pnp_resource_enabled(p)) {
791 fixed_io->address = p->start;
28f65c11 792 fixed_io->address_length = resource_size(p);
aee3ad81
BH
793 } else {
794 fixed_io->address = 0;
795 fixed_io->address_length = 0;
796 }
72dcc883 797
2f53432c 798 pnp_dbg(&dev->dev, " encode fixed_io %#x-%#x\n", fixed_io->address,
aee3ad81 799 fixed_io->address + fixed_io->address_length - 1);
1da177e4
LT
800}
801
72dcc883
BH
802static void pnpacpi_encode_mem24(struct pnp_dev *dev,
803 struct acpi_resource *resource,
9dd78466 804 struct resource *p)
1da177e4 805{
9570a20e
BH
806 struct acpi_resource_memory24 *memory24 = &resource->data.memory24;
807
aee3ad81
BH
808 if (pnp_resource_enabled(p)) {
809 /* Note: pnp_assign_mem copies pnp_mem->flags into p->flags */
810 memory24->write_protect = p->flags & IORESOURCE_MEM_WRITEABLE ?
811 ACPI_READ_WRITE_MEMORY : ACPI_READ_ONLY_MEMORY;
812 memory24->minimum = p->start;
813 memory24->maximum = p->end;
814 memory24->alignment = 0;
28f65c11 815 memory24->address_length = resource_size(p);
aee3ad81
BH
816 } else {
817 memory24->minimum = 0;
818 memory24->address_length = 0;
819 }
820
2f53432c 821 pnp_dbg(&dev->dev, " encode mem24 %#x-%#x write_protect %#x\n",
aee3ad81
BH
822 memory24->minimum,
823 memory24->minimum + memory24->address_length - 1,
72dcc883 824 memory24->write_protect);
1da177e4
LT
825}
826
72dcc883
BH
827static void pnpacpi_encode_mem32(struct pnp_dev *dev,
828 struct acpi_resource *resource,
9dd78466 829 struct resource *p)
1da177e4 830{
9570a20e
BH
831 struct acpi_resource_memory32 *memory32 = &resource->data.memory32;
832
aee3ad81
BH
833 if (pnp_resource_enabled(p)) {
834 memory32->write_protect = p->flags & IORESOURCE_MEM_WRITEABLE ?
835 ACPI_READ_WRITE_MEMORY : ACPI_READ_ONLY_MEMORY;
836 memory32->minimum = p->start;
837 memory32->maximum = p->end;
838 memory32->alignment = 0;
28f65c11 839 memory32->address_length = resource_size(p);
aee3ad81
BH
840 } else {
841 memory32->minimum = 0;
842 memory32->alignment = 0;
843 }
72dcc883 844
2f53432c 845 pnp_dbg(&dev->dev, " encode mem32 %#x-%#x write_protect %#x\n",
aee3ad81
BH
846 memory32->minimum,
847 memory32->minimum + memory32->address_length - 1,
72dcc883 848 memory32->write_protect);
1da177e4
LT
849}
850
72dcc883
BH
851static void pnpacpi_encode_fixed_mem32(struct pnp_dev *dev,
852 struct acpi_resource *resource,
9dd78466 853 struct resource *p)
1da177e4 854{
9570a20e
BH
855 struct acpi_resource_fixed_memory32 *fixed_memory32 = &resource->data.fixed_memory32;
856
aee3ad81
BH
857 if (pnp_resource_enabled(p)) {
858 fixed_memory32->write_protect =
859 p->flags & IORESOURCE_MEM_WRITEABLE ?
860 ACPI_READ_WRITE_MEMORY : ACPI_READ_ONLY_MEMORY;
861 fixed_memory32->address = p->start;
28f65c11 862 fixed_memory32->address_length = resource_size(p);
aee3ad81
BH
863 } else {
864 fixed_memory32->address = 0;
865 fixed_memory32->address_length = 0;
866 }
72dcc883 867
2f53432c 868 pnp_dbg(&dev->dev, " encode fixed_mem32 %#x-%#x write_protect %#x\n",
aee3ad81
BH
869 fixed_memory32->address,
870 fixed_memory32->address + fixed_memory32->address_length - 1,
72dcc883 871 fixed_memory32->write_protect);
1da177e4
LT
872}
873
4ab55d8d 874int pnpacpi_encode_resources(struct pnp_dev *dev, struct acpi_buffer *buffer)
1da177e4
LT
875{
876 int i = 0;
877 /* pnpacpi_build_resource_template allocates extra mem */
9dd78466 878 int res_cnt = (buffer->length - 1) / sizeof(struct acpi_resource) - 1;
4721a4cc 879 struct acpi_resource *resource = buffer->pointer;
fac69a2b 880 unsigned int port = 0, irq = 0, dma = 0, mem = 0;
1da177e4 881
2f53432c 882 pnp_dbg(&dev->dev, "encode %d resources\n", res_cnt);
1da177e4 883 while (i < res_cnt) {
9dd78466 884 switch (resource->type) {
50eca3eb 885 case ACPI_RESOURCE_TYPE_IRQ:
72dcc883 886 pnpacpi_encode_irq(dev, resource,
7e2cf31f 887 pnp_get_resource(dev, IORESOURCE_IRQ, irq));
1da177e4
LT
888 irq++;
889 break;
890
50eca3eb 891 case ACPI_RESOURCE_TYPE_DMA:
72dcc883 892 pnpacpi_encode_dma(dev, resource,
7e2cf31f 893 pnp_get_resource(dev, IORESOURCE_DMA, dma));
1c6e7d0a 894 dma++;
1da177e4 895 break;
50eca3eb 896 case ACPI_RESOURCE_TYPE_IO:
72dcc883 897 pnpacpi_encode_io(dev, resource,
7e2cf31f 898 pnp_get_resource(dev, IORESOURCE_IO, port));
1c6e7d0a 899 port++;
1da177e4 900 break;
50eca3eb 901 case ACPI_RESOURCE_TYPE_FIXED_IO:
72dcc883 902 pnpacpi_encode_fixed_io(dev, resource,
7e2cf31f 903 pnp_get_resource(dev, IORESOURCE_IO, port));
1c6e7d0a 904 port++;
1da177e4 905 break;
50eca3eb 906 case ACPI_RESOURCE_TYPE_MEMORY24:
72dcc883 907 pnpacpi_encode_mem24(dev, resource,
7e2cf31f 908 pnp_get_resource(dev, IORESOURCE_MEM, mem));
1c6e7d0a 909 mem++;
1da177e4 910 break;
50eca3eb 911 case ACPI_RESOURCE_TYPE_MEMORY32:
72dcc883 912 pnpacpi_encode_mem32(dev, resource,
7e2cf31f 913 pnp_get_resource(dev, IORESOURCE_MEM, mem));
1c6e7d0a 914 mem++;
1da177e4 915 break;
50eca3eb 916 case ACPI_RESOURCE_TYPE_FIXED_MEMORY32:
72dcc883 917 pnpacpi_encode_fixed_mem32(dev, resource,
7e2cf31f 918 pnp_get_resource(dev, IORESOURCE_MEM, mem));
1c6e7d0a 919 mem++;
1da177e4 920 break;
0af5853b 921 case ACPI_RESOURCE_TYPE_EXTENDED_IRQ:
72dcc883 922 pnpacpi_encode_ext_irq(dev, resource,
7e2cf31f 923 pnp_get_resource(dev, IORESOURCE_IRQ, irq));
0af5853b
LB
924 irq++;
925 break;
926 case ACPI_RESOURCE_TYPE_START_DEPENDENT:
927 case ACPI_RESOURCE_TYPE_END_DEPENDENT:
928 case ACPI_RESOURCE_TYPE_VENDOR:
929 case ACPI_RESOURCE_TYPE_END_TAG:
930 case ACPI_RESOURCE_TYPE_ADDRESS16:
931 case ACPI_RESOURCE_TYPE_ADDRESS32:
932 case ACPI_RESOURCE_TYPE_ADDRESS64:
933 case ACPI_RESOURCE_TYPE_EXTENDED_ADDRESS64:
934 case ACPI_RESOURCE_TYPE_GENERIC_REGISTER:
9dd78466 935 default: /* other type */
af11cb2d
BH
936 dev_warn(&dev->dev, "can't encode unknown resource "
937 "type %d\n", resource->type);
1da177e4
LT
938 return -EINVAL;
939 }
1c6e7d0a
BH
940 resource++;
941 i++;
1da177e4
LT
942 }
943 return 0;
944}
This page took 0.920614 seconds and 5 git commands to generate.