ce5027feb3da88cd5e32ced586a85c666358ea7c
[linux-2.6.git] / drivers / pnp / pnpacpi / rsparser.c
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>
6  *
7  * 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
9  * Free Software Foundation; either version 2, or (at your option) any
10  * later version.
11  *
12  * This program is distributed in the hope that it will be useful, but
13  * WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
20  */
21 #include <linux/kernel.h>
22 #include <linux/acpi.h>
23 #include <linux/pci.h>
24 #include "pnpacpi.h"
25
26 #ifdef CONFIG_IA64
27 #define valid_IRQ(i) (1)
28 #else
29 #define valid_IRQ(i) (((i) != 0) && ((i) != 2))
30 #endif
31
32 /*
33  * Allocated Resources
34  */
35 static int irq_flags(int triggering, int polarity)
36 {
37         int flag;
38         if (triggering == ACPI_LEVEL_SENSITIVE) {
39                 if (polarity == ACPI_ACTIVE_LOW)
40                         flag = IORESOURCE_IRQ_LOWLEVEL;
41                 else
42                         flag = IORESOURCE_IRQ_HIGHLEVEL;
43         } else {
44                 if (polarity == ACPI_ACTIVE_LOW)
45                         flag = IORESOURCE_IRQ_LOWEDGE;
46                 else
47                         flag = IORESOURCE_IRQ_HIGHEDGE;
48         }
49         return flag;
50 }
51
52 static void decode_irq_flags(int flag, int *triggering, int *polarity)
53 {
54         switch (flag) {
55         case IORESOURCE_IRQ_LOWLEVEL:
56                 *triggering = ACPI_LEVEL_SENSITIVE;
57                 *polarity = ACPI_ACTIVE_LOW;
58                 break;
59         case IORESOURCE_IRQ_HIGHLEVEL:
60                 *triggering = ACPI_LEVEL_SENSITIVE;
61                 *polarity = ACPI_ACTIVE_HIGH;
62                 break;
63         case IORESOURCE_IRQ_LOWEDGE:
64                 *triggering = ACPI_EDGE_SENSITIVE;
65                 *polarity = ACPI_ACTIVE_LOW;
66                 break;
67         case IORESOURCE_IRQ_HIGHEDGE:
68                 *triggering = ACPI_EDGE_SENSITIVE;
69                 *polarity = ACPI_ACTIVE_HIGH;
70                 break;
71         }
72 }
73
74 static void pnpacpi_parse_allocated_irqresource(struct pnp_resource_table *res,
75                                                 u32 gsi, int triggering,
76                                                 int polarity, int shareable)
77 {
78         int i = 0;
79         int irq;
80
81         if (!valid_IRQ(gsi))
82                 return;
83
84         while (!(res->irq_resource[i].flags & IORESOURCE_UNSET) &&
85                i < PNP_MAX_IRQ)
86                 i++;
87         if (i >= PNP_MAX_IRQ)
88                 return;
89
90         res->irq_resource[i].flags = IORESOURCE_IRQ;    // Also clears _UNSET flag
91         res->irq_resource[i].flags |= irq_flags(triggering, polarity);
92         irq = acpi_register_gsi(gsi, triggering, polarity);
93         if (irq < 0) {
94                 res->irq_resource[i].flags |= IORESOURCE_DISABLED;
95                 return;
96         }
97
98         if (shareable)
99                 res->irq_resource[i].flags |= IORESOURCE_IRQ_SHAREABLE;
100
101         res->irq_resource[i].start = irq;
102         res->irq_resource[i].end = irq;
103         pcibios_penalize_isa_irq(irq, 1);
104 }
105
106 static int dma_flags(int type, int bus_master, int transfer)
107 {
108         int flags = 0;
109
110         if (bus_master)
111                 flags |= IORESOURCE_DMA_MASTER;
112         switch (type) {
113         case ACPI_COMPATIBILITY:
114                 flags |= IORESOURCE_DMA_COMPATIBLE;
115                 break;
116         case ACPI_TYPE_A:
117                 flags |= IORESOURCE_DMA_TYPEA;
118                 break;
119         case ACPI_TYPE_B:
120                 flags |= IORESOURCE_DMA_TYPEB;
121                 break;
122         case ACPI_TYPE_F:
123                 flags |= IORESOURCE_DMA_TYPEF;
124                 break;
125         default:
126                 /* Set a default value ? */
127                 flags |= IORESOURCE_DMA_COMPATIBLE;
128                 pnp_err("Invalid DMA type");
129         }
130         switch (transfer) {
131         case ACPI_TRANSFER_8:
132                 flags |= IORESOURCE_DMA_8BIT;
133                 break;
134         case ACPI_TRANSFER_8_16:
135                 flags |= IORESOURCE_DMA_8AND16BIT;
136                 break;
137         case ACPI_TRANSFER_16:
138                 flags |= IORESOURCE_DMA_16BIT;
139                 break;
140         default:
141                 /* Set a default value ? */
142                 flags |= IORESOURCE_DMA_8AND16BIT;
143                 pnp_err("Invalid DMA transfer type");
144         }
145
146         return flags;
147 }
148
149 static void pnpacpi_parse_allocated_dmaresource(struct pnp_resource_table *res,
150                                                 u32 dma, int type,
151                                                 int bus_master, int transfer)
152 {
153         int i = 0;
154
155         while (i < PNP_MAX_DMA &&
156                !(res->dma_resource[i].flags & IORESOURCE_UNSET))
157                 i++;
158         if (i < PNP_MAX_DMA) {
159                 res->dma_resource[i].flags = IORESOURCE_DMA;    // Also clears _UNSET flag
160                 res->dma_resource[i].flags |=
161                     dma_flags(type, bus_master, transfer);
162                 if (dma == -1) {
163                         res->dma_resource[i].flags |= IORESOURCE_DISABLED;
164                         return;
165                 }
166                 res->dma_resource[i].start = dma;
167                 res->dma_resource[i].end = dma;
168         }
169 }
170
171 static void pnpacpi_parse_allocated_ioresource(struct pnp_resource_table *res,
172                                                u64 io, u64 len, int io_decode)
173 {
174         int i = 0;
175
176         while (!(res->port_resource[i].flags & IORESOURCE_UNSET) &&
177                i < PNP_MAX_PORT)
178                 i++;
179         if (i < PNP_MAX_PORT) {
180                 res->port_resource[i].flags = IORESOURCE_IO;    // Also clears _UNSET flag
181                 if (io_decode == ACPI_DECODE_16)
182                         res->port_resource[i].flags |= PNP_PORT_FLAG_16BITADDR;
183                 if (len <= 0 || (io + len - 1) >= 0x10003) {
184                         res->port_resource[i].flags |= IORESOURCE_DISABLED;
185                         return;
186                 }
187                 res->port_resource[i].start = io;
188                 res->port_resource[i].end = io + len - 1;
189         }
190 }
191
192 static void pnpacpi_parse_allocated_memresource(struct pnp_resource_table *res,
193                                                 u64 mem, u64 len,
194                                                 int write_protect)
195 {
196         int i = 0;
197
198         while (!(res->mem_resource[i].flags & IORESOURCE_UNSET) &&
199                (i < PNP_MAX_MEM))
200                 i++;
201         if (i < PNP_MAX_MEM) {
202                 res->mem_resource[i].flags = IORESOURCE_MEM;    // Also clears _UNSET flag
203                 if (len <= 0) {
204                         res->mem_resource[i].flags |= IORESOURCE_DISABLED;
205                         return;
206                 }
207                 if (write_protect == ACPI_READ_WRITE_MEMORY)
208                         res->mem_resource[i].flags |= IORESOURCE_MEM_WRITEABLE;
209
210                 res->mem_resource[i].start = mem;
211                 res->mem_resource[i].end = mem + len - 1;
212         }
213 }
214
215 static void pnpacpi_parse_allocated_address_space(struct pnp_resource_table *res_table,
216                                                   struct acpi_resource *res)
217 {
218         struct acpi_resource_address64 addr, *p = &addr;
219         acpi_status status;
220
221         status = acpi_resource_to_address64(res, p);
222         if (!ACPI_SUCCESS(status)) {
223                 pnp_warn("PnPACPI: failed to convert resource type %d",
224                          res->type);
225                 return;
226         }
227
228         if (p->producer_consumer == ACPI_PRODUCER)
229                 return;
230
231         if (p->resource_type == ACPI_MEMORY_RANGE)
232                 pnpacpi_parse_allocated_memresource(res_table,
233                         p->minimum, p->address_length,
234                         p->info.mem.write_protect);
235         else if (p->resource_type == ACPI_IO_RANGE)
236                 pnpacpi_parse_allocated_ioresource(res_table,
237                         p->minimum, p->address_length,
238                         p->granularity == 0xfff ? ACPI_DECODE_10 :
239                                 ACPI_DECODE_16);
240 }
241
242 static acpi_status pnpacpi_allocated_resource(struct acpi_resource *res,
243                                               void *data)
244 {
245         struct pnp_resource_table *res_table =
246             (struct pnp_resource_table *)data;
247         int i;
248
249         switch (res->type) {
250         case ACPI_RESOURCE_TYPE_IRQ:
251                 /*
252                  * Per spec, only one interrupt per descriptor is allowed in
253                  * _CRS, but some firmware violates this, so parse them all.
254                  */
255                 for (i = 0; i < res->data.irq.interrupt_count; i++) {
256                         pnpacpi_parse_allocated_irqresource(res_table,
257                                 res->data.irq.interrupts[i],
258                                 res->data.irq.triggering,
259                                 res->data.irq.polarity,
260                                 res->data.irq.sharable);
261                 }
262                 break;
263
264         case ACPI_RESOURCE_TYPE_DMA:
265                 if (res->data.dma.channel_count > 0)
266                         pnpacpi_parse_allocated_dmaresource(res_table,
267                                 res->data.dma.channels[0],
268                                 res->data.dma.type,
269                                 res->data.dma.bus_master,
270                                 res->data.dma.transfer);
271                 break;
272
273         case ACPI_RESOURCE_TYPE_IO:
274                 pnpacpi_parse_allocated_ioresource(res_table,
275                         res->data.io.minimum,
276                         res->data.io.address_length,
277                         res->data.io.io_decode);
278                 break;
279
280         case ACPI_RESOURCE_TYPE_START_DEPENDENT:
281         case ACPI_RESOURCE_TYPE_END_DEPENDENT:
282                 break;
283
284         case ACPI_RESOURCE_TYPE_FIXED_IO:
285                 pnpacpi_parse_allocated_ioresource(res_table,
286                         res->data.fixed_io.address,
287                         res->data.fixed_io.address_length,
288                         ACPI_DECODE_10);
289                 break;
290
291         case ACPI_RESOURCE_TYPE_VENDOR:
292                 break;
293
294         case ACPI_RESOURCE_TYPE_END_TAG:
295                 break;
296
297         case ACPI_RESOURCE_TYPE_MEMORY24:
298                 pnpacpi_parse_allocated_memresource(res_table,
299                         res->data.memory24.minimum,
300                         res->data.memory24.address_length,
301                         res->data.memory24.write_protect);
302                 break;
303         case ACPI_RESOURCE_TYPE_MEMORY32:
304                 pnpacpi_parse_allocated_memresource(res_table,
305                         res->data.memory32.minimum,
306                         res->data.memory32.address_length,
307                         res->data.memory32.write_protect);
308                 break;
309         case ACPI_RESOURCE_TYPE_FIXED_MEMORY32:
310                 pnpacpi_parse_allocated_memresource(res_table,
311                         res->data.fixed_memory32.address,
312                         res->data.fixed_memory32.address_length,
313                         res->data.fixed_memory32.write_protect);
314                 break;
315         case ACPI_RESOURCE_TYPE_ADDRESS16:
316         case ACPI_RESOURCE_TYPE_ADDRESS32:
317         case ACPI_RESOURCE_TYPE_ADDRESS64:
318                 pnpacpi_parse_allocated_address_space(res_table, res);
319                 break;
320
321         case ACPI_RESOURCE_TYPE_EXTENDED_ADDRESS64:
322                 if (res->data.ext_address64.producer_consumer == ACPI_PRODUCER)
323                         return AE_OK;
324                 break;
325
326         case ACPI_RESOURCE_TYPE_EXTENDED_IRQ:
327                 if (res->data.extended_irq.producer_consumer == ACPI_PRODUCER)
328                         return AE_OK;
329
330                 for (i = 0; i < res->data.extended_irq.interrupt_count; i++) {
331                         pnpacpi_parse_allocated_irqresource(res_table,
332                                 res->data.extended_irq.interrupts[i],
333                                 res->data.extended_irq.triggering,
334                                 res->data.extended_irq.polarity,
335                                 res->data.extended_irq.sharable);
336                 }
337                 break;
338
339         case ACPI_RESOURCE_TYPE_GENERIC_REGISTER:
340                 break;
341
342         default:
343                 pnp_warn("PnPACPI: unknown resource type %d", res->type);
344                 return AE_ERROR;
345         }
346
347         return AE_OK;
348 }
349
350 acpi_status pnpacpi_parse_allocated_resource(acpi_handle handle,
351                                              struct pnp_resource_table * res)
352 {
353         /* Blank the resource table values */
354         pnp_init_resource_table(res);
355
356         return acpi_walk_resources(handle, METHOD_NAME__CRS,
357                                    pnpacpi_allocated_resource, res);
358 }
359
360 static void pnpacpi_parse_dma_option(struct pnp_option *option,
361                                      struct acpi_resource_dma *p)
362 {
363         int i;
364         struct pnp_dma *dma;
365
366         if (p->channel_count == 0)
367                 return;
368         dma = kzalloc(sizeof(struct pnp_dma), GFP_KERNEL);
369         if (!dma)
370                 return;
371
372         for (i = 0; i < p->channel_count; i++)
373                 dma->map |= 1 << p->channels[i];
374
375         dma->flags = dma_flags(p->type, p->bus_master, p->transfer);
376
377         pnp_register_dma_resource(option, dma);
378 }
379
380 static void pnpacpi_parse_irq_option(struct pnp_option *option,
381                                      struct acpi_resource_irq *p)
382 {
383         int i;
384         struct pnp_irq *irq;
385
386         if (p->interrupt_count == 0)
387                 return;
388         irq = kzalloc(sizeof(struct pnp_irq), GFP_KERNEL);
389         if (!irq)
390                 return;
391
392         for (i = 0; i < p->interrupt_count; i++)
393                 if (p->interrupts[i])
394                         __set_bit(p->interrupts[i], irq->map);
395         irq->flags = irq_flags(p->triggering, p->polarity);
396
397         pnp_register_irq_resource(option, irq);
398 }
399
400 static void pnpacpi_parse_ext_irq_option(struct pnp_option *option,
401                                          struct acpi_resource_extended_irq *p)
402 {
403         int i;
404         struct pnp_irq *irq;
405
406         if (p->interrupt_count == 0)
407                 return;
408         irq = kzalloc(sizeof(struct pnp_irq), GFP_KERNEL);
409         if (!irq)
410                 return;
411
412         for (i = 0; i < p->interrupt_count; i++)
413                 if (p->interrupts[i])
414                         __set_bit(p->interrupts[i], irq->map);
415         irq->flags = irq_flags(p->triggering, p->polarity);
416
417         pnp_register_irq_resource(option, irq);
418 }
419
420 static void pnpacpi_parse_port_option(struct pnp_option *option,
421                                       struct acpi_resource_io *io)
422 {
423         struct pnp_port *port;
424
425         if (io->address_length == 0)
426                 return;
427         port = kzalloc(sizeof(struct pnp_port), GFP_KERNEL);
428         if (!port)
429                 return;
430         port->min = io->minimum;
431         port->max = io->maximum;
432         port->align = io->alignment;
433         port->size = io->address_length;
434         port->flags = ACPI_DECODE_16 == io->io_decode ?
435             PNP_PORT_FLAG_16BITADDR : 0;
436         pnp_register_port_resource(option, port);
437 }
438
439 static void pnpacpi_parse_fixed_port_option(struct pnp_option *option,
440                                             struct acpi_resource_fixed_io *io)
441 {
442         struct pnp_port *port;
443
444         if (io->address_length == 0)
445                 return;
446         port = kzalloc(sizeof(struct pnp_port), GFP_KERNEL);
447         if (!port)
448                 return;
449         port->min = port->max = io->address;
450         port->size = io->address_length;
451         port->align = 0;
452         port->flags = PNP_PORT_FLAG_FIXED;
453         pnp_register_port_resource(option, port);
454 }
455
456 static void pnpacpi_parse_mem24_option(struct pnp_option *option,
457                                        struct acpi_resource_memory24 *p)
458 {
459         struct pnp_mem *mem;
460
461         if (p->address_length == 0)
462                 return;
463         mem = kzalloc(sizeof(struct pnp_mem), GFP_KERNEL);
464         if (!mem)
465                 return;
466         mem->min = p->minimum;
467         mem->max = p->maximum;
468         mem->align = p->alignment;
469         mem->size = p->address_length;
470
471         mem->flags = (ACPI_READ_WRITE_MEMORY == p->write_protect) ?
472             IORESOURCE_MEM_WRITEABLE : 0;
473
474         pnp_register_mem_resource(option, mem);
475 }
476
477 static void pnpacpi_parse_mem32_option(struct pnp_option *option,
478                                        struct acpi_resource_memory32 *p)
479 {
480         struct pnp_mem *mem;
481
482         if (p->address_length == 0)
483                 return;
484         mem = kzalloc(sizeof(struct pnp_mem), GFP_KERNEL);
485         if (!mem)
486                 return;
487         mem->min = p->minimum;
488         mem->max = p->maximum;
489         mem->align = p->alignment;
490         mem->size = p->address_length;
491
492         mem->flags = (ACPI_READ_WRITE_MEMORY == p->write_protect) ?
493             IORESOURCE_MEM_WRITEABLE : 0;
494
495         pnp_register_mem_resource(option, mem);
496 }
497
498 static void pnpacpi_parse_fixed_mem32_option(struct pnp_option *option,
499                                          struct acpi_resource_fixed_memory32 *p)
500 {
501         struct pnp_mem *mem;
502
503         if (p->address_length == 0)
504                 return;
505         mem = kzalloc(sizeof(struct pnp_mem), GFP_KERNEL);
506         if (!mem)
507                 return;
508         mem->min = mem->max = p->address;
509         mem->size = p->address_length;
510         mem->align = 0;
511
512         mem->flags = (ACPI_READ_WRITE_MEMORY == p->write_protect) ?
513             IORESOURCE_MEM_WRITEABLE : 0;
514
515         pnp_register_mem_resource(option, mem);
516 }
517
518 static void pnpacpi_parse_address_option(struct pnp_option *option,
519                                          struct acpi_resource *r)
520 {
521         struct acpi_resource_address64 addr, *p = &addr;
522         acpi_status status;
523         struct pnp_mem *mem;
524         struct pnp_port *port;
525
526         status = acpi_resource_to_address64(r, p);
527         if (!ACPI_SUCCESS(status)) {
528                 pnp_warn("PnPACPI: failed to convert resource type %d",
529                          r->type);
530                 return;
531         }
532
533         if (p->address_length == 0)
534                 return;
535
536         if (p->resource_type == ACPI_MEMORY_RANGE) {
537                 mem = kzalloc(sizeof(struct pnp_mem), GFP_KERNEL);
538                 if (!mem)
539                         return;
540                 mem->min = mem->max = p->minimum;
541                 mem->size = p->address_length;
542                 mem->align = 0;
543                 mem->flags = (p->info.mem.write_protect ==
544                               ACPI_READ_WRITE_MEMORY) ? IORESOURCE_MEM_WRITEABLE
545                     : 0;
546                 pnp_register_mem_resource(option, mem);
547         } else if (p->resource_type == ACPI_IO_RANGE) {
548                 port = kzalloc(sizeof(struct pnp_port), GFP_KERNEL);
549                 if (!port)
550                         return;
551                 port->min = port->max = p->minimum;
552                 port->size = p->address_length;
553                 port->align = 0;
554                 port->flags = PNP_PORT_FLAG_FIXED;
555                 pnp_register_port_resource(option, port);
556         }
557 }
558
559 struct acpipnp_parse_option_s {
560         struct pnp_option *option;
561         struct pnp_option *option_independent;
562         struct pnp_dev *dev;
563 };
564
565 static acpi_status pnpacpi_option_resource(struct acpi_resource *res,
566                                            void *data)
567 {
568         int priority = 0;
569         struct acpipnp_parse_option_s *parse_data =
570             (struct acpipnp_parse_option_s *)data;
571         struct pnp_dev *dev = parse_data->dev;
572         struct pnp_option *option = parse_data->option;
573
574         switch (res->type) {
575         case ACPI_RESOURCE_TYPE_IRQ:
576                 pnpacpi_parse_irq_option(option, &res->data.irq);
577                 break;
578
579         case ACPI_RESOURCE_TYPE_DMA:
580                 pnpacpi_parse_dma_option(option, &res->data.dma);
581                 break;
582
583         case ACPI_RESOURCE_TYPE_START_DEPENDENT:
584                 switch (res->data.start_dpf.compatibility_priority) {
585                 case ACPI_GOOD_CONFIGURATION:
586                         priority = PNP_RES_PRIORITY_PREFERRED;
587                         break;
588
589                 case ACPI_ACCEPTABLE_CONFIGURATION:
590                         priority = PNP_RES_PRIORITY_ACCEPTABLE;
591                         break;
592
593                 case ACPI_SUB_OPTIMAL_CONFIGURATION:
594                         priority = PNP_RES_PRIORITY_FUNCTIONAL;
595                         break;
596                 default:
597                         priority = PNP_RES_PRIORITY_INVALID;
598                         break;
599                 }
600                 /* TBD: Consider performance/robustness bits */
601                 option = pnp_register_dependent_option(dev, priority);
602                 if (!option)
603                         return AE_ERROR;
604                 parse_data->option = option;
605                 break;
606
607         case ACPI_RESOURCE_TYPE_END_DEPENDENT:
608                 /*only one EndDependentFn is allowed */
609                 if (!parse_data->option_independent) {
610                         pnp_warn("PnPACPI: more than one EndDependentFn");
611                         return AE_ERROR;
612                 }
613                 parse_data->option = parse_data->option_independent;
614                 parse_data->option_independent = NULL;
615                 break;
616
617         case ACPI_RESOURCE_TYPE_IO:
618                 pnpacpi_parse_port_option(option, &res->data.io);
619                 break;
620
621         case ACPI_RESOURCE_TYPE_FIXED_IO:
622                 pnpacpi_parse_fixed_port_option(option, &res->data.fixed_io);
623                 break;
624
625         case ACPI_RESOURCE_TYPE_VENDOR:
626         case ACPI_RESOURCE_TYPE_END_TAG:
627                 break;
628
629         case ACPI_RESOURCE_TYPE_MEMORY24:
630                 pnpacpi_parse_mem24_option(option, &res->data.memory24);
631                 break;
632
633         case ACPI_RESOURCE_TYPE_MEMORY32:
634                 pnpacpi_parse_mem32_option(option, &res->data.memory32);
635                 break;
636
637         case ACPI_RESOURCE_TYPE_FIXED_MEMORY32:
638                 pnpacpi_parse_fixed_mem32_option(option,
639                                                  &res->data.fixed_memory32);
640                 break;
641
642         case ACPI_RESOURCE_TYPE_ADDRESS16:
643         case ACPI_RESOURCE_TYPE_ADDRESS32:
644         case ACPI_RESOURCE_TYPE_ADDRESS64:
645                 pnpacpi_parse_address_option(option, res);
646                 break;
647
648         case ACPI_RESOURCE_TYPE_EXTENDED_ADDRESS64:
649                 break;
650
651         case ACPI_RESOURCE_TYPE_EXTENDED_IRQ:
652                 pnpacpi_parse_ext_irq_option(option, &res->data.extended_irq);
653                 break;
654
655         case ACPI_RESOURCE_TYPE_GENERIC_REGISTER:
656                 break;
657
658         default:
659                 pnp_warn("PnPACPI: unknown resource type %d", res->type);
660                 return AE_ERROR;
661         }
662
663         return AE_OK;
664 }
665
666 acpi_status pnpacpi_parse_resource_option_data(acpi_handle handle,
667                                                struct pnp_dev * dev)
668 {
669         acpi_status status;
670         struct acpipnp_parse_option_s parse_data;
671
672         parse_data.option = pnp_register_independent_option(dev);
673         if (!parse_data.option)
674                 return AE_ERROR;
675         parse_data.option_independent = parse_data.option;
676         parse_data.dev = dev;
677         status = acpi_walk_resources(handle, METHOD_NAME__PRS,
678                                      pnpacpi_option_resource, &parse_data);
679
680         return status;
681 }
682
683 static int pnpacpi_supported_resource(struct acpi_resource *res)
684 {
685         switch (res->type) {
686         case ACPI_RESOURCE_TYPE_IRQ:
687         case ACPI_RESOURCE_TYPE_DMA:
688         case ACPI_RESOURCE_TYPE_IO:
689         case ACPI_RESOURCE_TYPE_FIXED_IO:
690         case ACPI_RESOURCE_TYPE_MEMORY24:
691         case ACPI_RESOURCE_TYPE_MEMORY32:
692         case ACPI_RESOURCE_TYPE_FIXED_MEMORY32:
693         case ACPI_RESOURCE_TYPE_ADDRESS16:
694         case ACPI_RESOURCE_TYPE_ADDRESS32:
695         case ACPI_RESOURCE_TYPE_ADDRESS64:
696         case ACPI_RESOURCE_TYPE_EXTENDED_IRQ:
697                 return 1;
698         }
699         return 0;
700 }
701
702 /*
703  * Set resource
704  */
705 static acpi_status pnpacpi_count_resources(struct acpi_resource *res,
706                                            void *data)
707 {
708         int *res_cnt = (int *)data;
709
710         if (pnpacpi_supported_resource(res))
711                 (*res_cnt)++;
712         return AE_OK;
713 }
714
715 static acpi_status pnpacpi_type_resources(struct acpi_resource *res, void *data)
716 {
717         struct acpi_resource **resource = (struct acpi_resource **)data;
718
719         if (pnpacpi_supported_resource(res)) {
720                 (*resource)->type = res->type;
721                 (*resource)->length = sizeof(struct acpi_resource);
722                 (*resource)++;
723         }
724
725         return AE_OK;
726 }
727
728 int pnpacpi_build_resource_template(acpi_handle handle,
729                                     struct acpi_buffer *buffer)
730 {
731         struct acpi_resource *resource;
732         int res_cnt = 0;
733         acpi_status status;
734
735         status = acpi_walk_resources(handle, METHOD_NAME__CRS,
736                                      pnpacpi_count_resources, &res_cnt);
737         if (ACPI_FAILURE(status)) {
738                 pnp_err("Evaluate _CRS failed");
739                 return -EINVAL;
740         }
741         if (!res_cnt)
742                 return -EINVAL;
743         buffer->length = sizeof(struct acpi_resource) * (res_cnt + 1) + 1;
744         buffer->pointer = kzalloc(buffer->length - 1, GFP_KERNEL);
745         if (!buffer->pointer)
746                 return -ENOMEM;
747         pnp_dbg("Res cnt %d", res_cnt);
748         resource = (struct acpi_resource *)buffer->pointer;
749         status = acpi_walk_resources(handle, METHOD_NAME__CRS,
750                                      pnpacpi_type_resources, &resource);
751         if (ACPI_FAILURE(status)) {
752                 kfree(buffer->pointer);
753                 pnp_err("Evaluate _CRS failed");
754                 return -EINVAL;
755         }
756         /* resource will pointer the end resource now */
757         resource->type = ACPI_RESOURCE_TYPE_END_TAG;
758
759         return 0;
760 }
761
762 static void pnpacpi_encode_irq(struct acpi_resource *resource,
763                                struct resource *p)
764 {
765         int triggering, polarity;
766
767         decode_irq_flags(p->flags & IORESOURCE_BITS, &triggering, &polarity);
768         resource->data.irq.triggering = triggering;
769         resource->data.irq.polarity = polarity;
770         if (triggering == ACPI_EDGE_SENSITIVE)
771                 resource->data.irq.sharable = ACPI_EXCLUSIVE;
772         else
773                 resource->data.irq.sharable = ACPI_SHARED;
774         resource->data.irq.interrupt_count = 1;
775         resource->data.irq.interrupts[0] = p->start;
776 }
777
778 static void pnpacpi_encode_ext_irq(struct acpi_resource *resource,
779                                    struct resource *p)
780 {
781         int triggering, polarity;
782
783         decode_irq_flags(p->flags & IORESOURCE_BITS, &triggering, &polarity);
784         resource->data.extended_irq.producer_consumer = ACPI_CONSUMER;
785         resource->data.extended_irq.triggering = triggering;
786         resource->data.extended_irq.polarity = polarity;
787         if (triggering == ACPI_EDGE_SENSITIVE)
788                 resource->data.irq.sharable = ACPI_EXCLUSIVE;
789         else
790                 resource->data.irq.sharable = ACPI_SHARED;
791         resource->data.extended_irq.interrupt_count = 1;
792         resource->data.extended_irq.interrupts[0] = p->start;
793 }
794
795 static void pnpacpi_encode_dma(struct acpi_resource *resource,
796                                struct resource *p)
797 {
798         /* Note: pnp_assign_dma will copy pnp_dma->flags into p->flags */
799         switch (p->flags & IORESOURCE_DMA_SPEED_MASK) {
800         case IORESOURCE_DMA_TYPEA:
801                 resource->data.dma.type = ACPI_TYPE_A;
802                 break;
803         case IORESOURCE_DMA_TYPEB:
804                 resource->data.dma.type = ACPI_TYPE_B;
805                 break;
806         case IORESOURCE_DMA_TYPEF:
807                 resource->data.dma.type = ACPI_TYPE_F;
808                 break;
809         default:
810                 resource->data.dma.type = ACPI_COMPATIBILITY;
811         }
812
813         switch (p->flags & IORESOURCE_DMA_TYPE_MASK) {
814         case IORESOURCE_DMA_8BIT:
815                 resource->data.dma.transfer = ACPI_TRANSFER_8;
816                 break;
817         case IORESOURCE_DMA_8AND16BIT:
818                 resource->data.dma.transfer = ACPI_TRANSFER_8_16;
819                 break;
820         default:
821                 resource->data.dma.transfer = ACPI_TRANSFER_16;
822         }
823
824         resource->data.dma.bus_master = !!(p->flags & IORESOURCE_DMA_MASTER);
825         resource->data.dma.channel_count = 1;
826         resource->data.dma.channels[0] = p->start;
827 }
828
829 static void pnpacpi_encode_io(struct acpi_resource *resource,
830                               struct resource *p)
831 {
832         /* Note: pnp_assign_port will copy pnp_port->flags into p->flags */
833         resource->data.io.io_decode = (p->flags & PNP_PORT_FLAG_16BITADDR) ?
834             ACPI_DECODE_16 : ACPI_DECODE_10;
835         resource->data.io.minimum = p->start;
836         resource->data.io.maximum = p->end;
837         resource->data.io.alignment = 0;        /* Correct? */
838         resource->data.io.address_length = p->end - p->start + 1;
839 }
840
841 static void pnpacpi_encode_fixed_io(struct acpi_resource *resource,
842                                     struct resource *p)
843 {
844         resource->data.fixed_io.address = p->start;
845         resource->data.fixed_io.address_length = p->end - p->start + 1;
846 }
847
848 static void pnpacpi_encode_mem24(struct acpi_resource *resource,
849                                  struct resource *p)
850 {
851         /* Note: pnp_assign_mem will copy pnp_mem->flags into p->flags */
852         resource->data.memory24.write_protect =
853             (p->flags & IORESOURCE_MEM_WRITEABLE) ?
854             ACPI_READ_WRITE_MEMORY : ACPI_READ_ONLY_MEMORY;
855         resource->data.memory24.minimum = p->start;
856         resource->data.memory24.maximum = p->end;
857         resource->data.memory24.alignment = 0;
858         resource->data.memory24.address_length = p->end - p->start + 1;
859 }
860
861 static void pnpacpi_encode_mem32(struct acpi_resource *resource,
862                                  struct resource *p)
863 {
864         resource->data.memory32.write_protect =
865             (p->flags & IORESOURCE_MEM_WRITEABLE) ?
866             ACPI_READ_WRITE_MEMORY : ACPI_READ_ONLY_MEMORY;
867         resource->data.memory32.minimum = p->start;
868         resource->data.memory32.maximum = p->end;
869         resource->data.memory32.alignment = 0;
870         resource->data.memory32.address_length = p->end - p->start + 1;
871 }
872
873 static void pnpacpi_encode_fixed_mem32(struct acpi_resource *resource,
874                                        struct resource *p)
875 {
876         resource->data.fixed_memory32.write_protect =
877             (p->flags & IORESOURCE_MEM_WRITEABLE) ?
878             ACPI_READ_WRITE_MEMORY : ACPI_READ_ONLY_MEMORY;
879         resource->data.fixed_memory32.address = p->start;
880         resource->data.fixed_memory32.address_length = p->end - p->start + 1;
881 }
882
883 int pnpacpi_encode_resources(struct pnp_resource_table *res_table,
884                              struct acpi_buffer *buffer)
885 {
886         int i = 0;
887         /* pnpacpi_build_resource_template allocates extra mem */
888         int res_cnt = (buffer->length - 1) / sizeof(struct acpi_resource) - 1;
889         struct acpi_resource *resource =
890             (struct acpi_resource *)buffer->pointer;
891         int port = 0, irq = 0, dma = 0, mem = 0;
892
893         pnp_dbg("res cnt %d", res_cnt);
894         while (i < res_cnt) {
895                 switch (resource->type) {
896                 case ACPI_RESOURCE_TYPE_IRQ:
897                         pnp_dbg("Encode irq");
898                         pnpacpi_encode_irq(resource,
899                                            &res_table->irq_resource[irq]);
900                         irq++;
901                         break;
902
903                 case ACPI_RESOURCE_TYPE_DMA:
904                         pnp_dbg("Encode dma");
905                         pnpacpi_encode_dma(resource,
906                                            &res_table->dma_resource[dma]);
907                         dma++;
908                         break;
909                 case ACPI_RESOURCE_TYPE_IO:
910                         pnp_dbg("Encode io");
911                         pnpacpi_encode_io(resource,
912                                           &res_table->port_resource[port]);
913                         port++;
914                         break;
915                 case ACPI_RESOURCE_TYPE_FIXED_IO:
916                         pnp_dbg("Encode fixed io");
917                         pnpacpi_encode_fixed_io(resource,
918                                                 &res_table->
919                                                 port_resource[port]);
920                         port++;
921                         break;
922                 case ACPI_RESOURCE_TYPE_MEMORY24:
923                         pnp_dbg("Encode mem24");
924                         pnpacpi_encode_mem24(resource,
925                                              &res_table->mem_resource[mem]);
926                         mem++;
927                         break;
928                 case ACPI_RESOURCE_TYPE_MEMORY32:
929                         pnp_dbg("Encode mem32");
930                         pnpacpi_encode_mem32(resource,
931                                              &res_table->mem_resource[mem]);
932                         mem++;
933                         break;
934                 case ACPI_RESOURCE_TYPE_FIXED_MEMORY32:
935                         pnp_dbg("Encode fixed mem32");
936                         pnpacpi_encode_fixed_mem32(resource,
937                                                    &res_table->
938                                                    mem_resource[mem]);
939                         mem++;
940                         break;
941                 case ACPI_RESOURCE_TYPE_EXTENDED_IRQ:
942                         pnp_dbg("Encode ext irq");
943                         pnpacpi_encode_ext_irq(resource,
944                                                &res_table->irq_resource[irq]);
945                         irq++;
946                         break;
947                 case ACPI_RESOURCE_TYPE_START_DEPENDENT:
948                 case ACPI_RESOURCE_TYPE_END_DEPENDENT:
949                 case ACPI_RESOURCE_TYPE_VENDOR:
950                 case ACPI_RESOURCE_TYPE_END_TAG:
951                 case ACPI_RESOURCE_TYPE_ADDRESS16:
952                 case ACPI_RESOURCE_TYPE_ADDRESS32:
953                 case ACPI_RESOURCE_TYPE_ADDRESS64:
954                 case ACPI_RESOURCE_TYPE_EXTENDED_ADDRESS64:
955                 case ACPI_RESOURCE_TYPE_GENERIC_REGISTER:
956                 default:        /* other type */
957                         pnp_warn("unknown resource type %d", resource->type);
958                         return -EINVAL;
959                 }
960                 resource++;
961                 i++;
962         }
963         return 0;
964 }