PNP: Lindent all source files
[safe/jmp/linux-2.6] / 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
75 pnpacpi_parse_allocated_irqresource(struct pnp_resource_table *res, u32 gsi,
76                                     int triggering, 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
150 pnpacpi_parse_allocated_dmaresource(struct pnp_resource_table *res, u32 dma,
151                                     int type, int bus_master, int transfer)
152 {
153         int i = 0;
154         while (i < PNP_MAX_DMA &&
155                !(res->dma_resource[i].flags & IORESOURCE_UNSET))
156                 i++;
157         if (i < PNP_MAX_DMA) {
158                 res->dma_resource[i].flags = IORESOURCE_DMA;    // Also clears _UNSET flag
159                 res->dma_resource[i].flags |=
160                     dma_flags(type, bus_master, transfer);
161                 if (dma == -1) {
162                         res->dma_resource[i].flags |= IORESOURCE_DISABLED;
163                         return;
164                 }
165                 res->dma_resource[i].start = dma;
166                 res->dma_resource[i].end = dma;
167         }
168 }
169
170 static void
171 pnpacpi_parse_allocated_ioresource(struct pnp_resource_table *res,
172                                    u64 io, u64 len, int io_decode)
173 {
174         int i = 0;
175         while (!(res->port_resource[i].flags & IORESOURCE_UNSET) &&
176                i < PNP_MAX_PORT)
177                 i++;
178         if (i < PNP_MAX_PORT) {
179                 res->port_resource[i].flags = IORESOURCE_IO;    // Also clears _UNSET flag
180                 if (io_decode == ACPI_DECODE_16)
181                         res->port_resource[i].flags |= PNP_PORT_FLAG_16BITADDR;
182                 if (len <= 0 || (io + len - 1) >= 0x10003) {
183                         res->port_resource[i].flags |= IORESOURCE_DISABLED;
184                         return;
185                 }
186                 res->port_resource[i].start = io;
187                 res->port_resource[i].end = io + len - 1;
188         }
189 }
190
191 static void
192 pnpacpi_parse_allocated_memresource(struct pnp_resource_table *res,
193                                     u64 mem, u64 len, int write_protect)
194 {
195         int i = 0;
196         while (!(res->mem_resource[i].flags & IORESOURCE_UNSET) &&
197                (i < PNP_MAX_MEM))
198                 i++;
199         if (i < PNP_MAX_MEM) {
200                 res->mem_resource[i].flags = IORESOURCE_MEM;    // Also clears _UNSET flag
201                 if (len <= 0) {
202                         res->mem_resource[i].flags |= IORESOURCE_DISABLED;
203                         return;
204                 }
205                 if (write_protect == ACPI_READ_WRITE_MEMORY)
206                         res->mem_resource[i].flags |= IORESOURCE_MEM_WRITEABLE;
207
208                 res->mem_resource[i].start = mem;
209                 res->mem_resource[i].end = mem + len - 1;
210         }
211 }
212
213 static void
214 pnpacpi_parse_allocated_address_space(struct pnp_resource_table *res_table,
215                                       struct acpi_resource *res)
216 {
217         struct acpi_resource_address64 addr, *p = &addr;
218         acpi_status status;
219
220         status = acpi_resource_to_address64(res, p);
221         if (!ACPI_SUCCESS(status)) {
222                 pnp_warn("PnPACPI: failed to convert resource type %d",
223                          res->type);
224                 return;
225         }
226
227         if (p->producer_consumer == ACPI_PRODUCER)
228                 return;
229
230         if (p->resource_type == ACPI_MEMORY_RANGE)
231                 pnpacpi_parse_allocated_memresource(res_table,
232                                                     p->minimum,
233                                                     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,
238                                                    p->address_length,
239                                                    p->granularity ==
240                                                    0xfff ? ACPI_DECODE_10 :
241                                                    ACPI_DECODE_16);
242 }
243
244 static acpi_status pnpacpi_allocated_resource(struct acpi_resource *res,
245                                               void *data)
246 {
247         struct pnp_resource_table *res_table =
248             (struct pnp_resource_table *)data;
249         int i;
250
251         switch (res->type) {
252         case ACPI_RESOURCE_TYPE_IRQ:
253                 /*
254                  * Per spec, only one interrupt per descriptor is allowed in
255                  * _CRS, but some firmware violates this, so parse them all.
256                  */
257                 for (i = 0; i < res->data.irq.interrupt_count; i++) {
258                         pnpacpi_parse_allocated_irqresource(res_table,
259                                                             res->data.irq.
260                                                             interrupts[i],
261                                                             res->data.irq.
262                                                             triggering,
263                                                             res->data.irq.
264                                                             polarity,
265                                                             res->data.irq.
266                                                             sharable);
267                 }
268                 break;
269
270         case ACPI_RESOURCE_TYPE_DMA:
271                 if (res->data.dma.channel_count > 0)
272                         pnpacpi_parse_allocated_dmaresource(res_table,
273                                                             res->data.dma.
274                                                             channels[0],
275                                                             res->data.dma.type,
276                                                             res->data.dma.
277                                                             bus_master,
278                                                             res->data.dma.
279                                                             transfer);
280                 break;
281
282         case ACPI_RESOURCE_TYPE_IO:
283                 pnpacpi_parse_allocated_ioresource(res_table,
284                                                    res->data.io.minimum,
285                                                    res->data.io.address_length,
286                                                    res->data.io.io_decode);
287                 break;
288
289         case ACPI_RESOURCE_TYPE_START_DEPENDENT:
290         case ACPI_RESOURCE_TYPE_END_DEPENDENT:
291                 break;
292
293         case ACPI_RESOURCE_TYPE_FIXED_IO:
294                 pnpacpi_parse_allocated_ioresource(res_table,
295                                                    res->data.fixed_io.address,
296                                                    res->data.fixed_io.
297                                                    address_length,
298                                                    ACPI_DECODE_10);
299                 break;
300
301         case ACPI_RESOURCE_TYPE_VENDOR:
302                 break;
303
304         case ACPI_RESOURCE_TYPE_END_TAG:
305                 break;
306
307         case ACPI_RESOURCE_TYPE_MEMORY24:
308                 pnpacpi_parse_allocated_memresource(res_table,
309                                                     res->data.memory24.minimum,
310                                                     res->data.memory24.
311                                                     address_length,
312                                                     res->data.memory24.
313                                                     write_protect);
314                 break;
315         case ACPI_RESOURCE_TYPE_MEMORY32:
316                 pnpacpi_parse_allocated_memresource(res_table,
317                                                     res->data.memory32.minimum,
318                                                     res->data.memory32.
319                                                     address_length,
320                                                     res->data.memory32.
321                                                     write_protect);
322                 break;
323         case ACPI_RESOURCE_TYPE_FIXED_MEMORY32:
324                 pnpacpi_parse_allocated_memresource(res_table,
325                                                     res->data.fixed_memory32.
326                                                     address,
327                                                     res->data.fixed_memory32.
328                                                     address_length,
329                                                     res->data.fixed_memory32.
330                                                     write_protect);
331                 break;
332         case ACPI_RESOURCE_TYPE_ADDRESS16:
333         case ACPI_RESOURCE_TYPE_ADDRESS32:
334         case ACPI_RESOURCE_TYPE_ADDRESS64:
335                 pnpacpi_parse_allocated_address_space(res_table, res);
336                 break;
337
338         case ACPI_RESOURCE_TYPE_EXTENDED_ADDRESS64:
339                 if (res->data.ext_address64.producer_consumer == ACPI_PRODUCER)
340                         return AE_OK;
341                 break;
342
343         case ACPI_RESOURCE_TYPE_EXTENDED_IRQ:
344                 if (res->data.extended_irq.producer_consumer == ACPI_PRODUCER)
345                         return AE_OK;
346
347                 for (i = 0; i < res->data.extended_irq.interrupt_count; i++) {
348                         pnpacpi_parse_allocated_irqresource(res_table,
349                                                             res->data.
350                                                             extended_irq.
351                                                             interrupts[i],
352                                                             res->data.
353                                                             extended_irq.
354                                                             triggering,
355                                                             res->data.
356                                                             extended_irq.
357                                                             polarity,
358                                                             res->data.
359                                                             extended_irq.
360                                                             sharable);
361                 }
362                 break;
363
364         case ACPI_RESOURCE_TYPE_GENERIC_REGISTER:
365                 break;
366
367         default:
368                 pnp_warn("PnPACPI: unknown resource type %d", res->type);
369                 return AE_ERROR;
370         }
371
372         return AE_OK;
373 }
374
375 acpi_status pnpacpi_parse_allocated_resource(acpi_handle handle,
376                                              struct pnp_resource_table * res)
377 {
378         /* Blank the resource table values */
379         pnp_init_resource_table(res);
380
381         return acpi_walk_resources(handle, METHOD_NAME__CRS,
382                                    pnpacpi_allocated_resource, res);
383 }
384
385 static void pnpacpi_parse_dma_option(struct pnp_option *option,
386                                      struct acpi_resource_dma *p)
387 {
388         int i;
389         struct pnp_dma *dma;
390
391         if (p->channel_count == 0)
392                 return;
393         dma = kzalloc(sizeof(struct pnp_dma), GFP_KERNEL);
394         if (!dma)
395                 return;
396
397         for (i = 0; i < p->channel_count; i++)
398                 dma->map |= 1 << p->channels[i];
399
400         dma->flags = dma_flags(p->type, p->bus_master, p->transfer);
401
402         pnp_register_dma_resource(option, dma);
403         return;
404 }
405
406 static void pnpacpi_parse_irq_option(struct pnp_option *option,
407                                      struct acpi_resource_irq *p)
408 {
409         int i;
410         struct pnp_irq *irq;
411
412         if (p->interrupt_count == 0)
413                 return;
414         irq = kzalloc(sizeof(struct pnp_irq), GFP_KERNEL);
415         if (!irq)
416                 return;
417
418         for (i = 0; i < p->interrupt_count; i++)
419                 if (p->interrupts[i])
420                         __set_bit(p->interrupts[i], irq->map);
421         irq->flags = irq_flags(p->triggering, p->polarity);
422
423         pnp_register_irq_resource(option, irq);
424         return;
425 }
426
427 static void pnpacpi_parse_ext_irq_option(struct pnp_option *option,
428                                          struct acpi_resource_extended_irq *p)
429 {
430         int i;
431         struct pnp_irq *irq;
432
433         if (p->interrupt_count == 0)
434                 return;
435         irq = kzalloc(sizeof(struct pnp_irq), GFP_KERNEL);
436         if (!irq)
437                 return;
438
439         for (i = 0; i < p->interrupt_count; i++)
440                 if (p->interrupts[i])
441                         __set_bit(p->interrupts[i], irq->map);
442         irq->flags = irq_flags(p->triggering, p->polarity);
443
444         pnp_register_irq_resource(option, irq);
445         return;
446 }
447
448 static void
449 pnpacpi_parse_port_option(struct pnp_option *option,
450                           struct acpi_resource_io *io)
451 {
452         struct pnp_port *port;
453
454         if (io->address_length == 0)
455                 return;
456         port = kzalloc(sizeof(struct pnp_port), GFP_KERNEL);
457         if (!port)
458                 return;
459         port->min = io->minimum;
460         port->max = io->maximum;
461         port->align = io->alignment;
462         port->size = io->address_length;
463         port->flags = ACPI_DECODE_16 == io->io_decode ?
464             PNP_PORT_FLAG_16BITADDR : 0;
465         pnp_register_port_resource(option, port);
466         return;
467 }
468
469 static void
470 pnpacpi_parse_fixed_port_option(struct pnp_option *option,
471                                 struct acpi_resource_fixed_io *io)
472 {
473         struct pnp_port *port;
474
475         if (io->address_length == 0)
476                 return;
477         port = kzalloc(sizeof(struct pnp_port), GFP_KERNEL);
478         if (!port)
479                 return;
480         port->min = port->max = io->address;
481         port->size = io->address_length;
482         port->align = 0;
483         port->flags = PNP_PORT_FLAG_FIXED;
484         pnp_register_port_resource(option, port);
485         return;
486 }
487
488 static void
489 pnpacpi_parse_mem24_option(struct pnp_option *option,
490                            struct acpi_resource_memory24 *p)
491 {
492         struct pnp_mem *mem;
493
494         if (p->address_length == 0)
495                 return;
496         mem = kzalloc(sizeof(struct pnp_mem), GFP_KERNEL);
497         if (!mem)
498                 return;
499         mem->min = p->minimum;
500         mem->max = p->maximum;
501         mem->align = p->alignment;
502         mem->size = p->address_length;
503
504         mem->flags = (ACPI_READ_WRITE_MEMORY == p->write_protect) ?
505             IORESOURCE_MEM_WRITEABLE : 0;
506
507         pnp_register_mem_resource(option, mem);
508         return;
509 }
510
511 static void
512 pnpacpi_parse_mem32_option(struct pnp_option *option,
513                            struct acpi_resource_memory32 *p)
514 {
515         struct pnp_mem *mem;
516
517         if (p->address_length == 0)
518                 return;
519         mem = kzalloc(sizeof(struct pnp_mem), GFP_KERNEL);
520         if (!mem)
521                 return;
522         mem->min = p->minimum;
523         mem->max = p->maximum;
524         mem->align = p->alignment;
525         mem->size = p->address_length;
526
527         mem->flags = (ACPI_READ_WRITE_MEMORY == p->write_protect) ?
528             IORESOURCE_MEM_WRITEABLE : 0;
529
530         pnp_register_mem_resource(option, mem);
531         return;
532 }
533
534 static void
535 pnpacpi_parse_fixed_mem32_option(struct pnp_option *option,
536                                  struct acpi_resource_fixed_memory32 *p)
537 {
538         struct pnp_mem *mem;
539
540         if (p->address_length == 0)
541                 return;
542         mem = kzalloc(sizeof(struct pnp_mem), GFP_KERNEL);
543         if (!mem)
544                 return;
545         mem->min = mem->max = p->address;
546         mem->size = p->address_length;
547         mem->align = 0;
548
549         mem->flags = (ACPI_READ_WRITE_MEMORY == p->write_protect) ?
550             IORESOURCE_MEM_WRITEABLE : 0;
551
552         pnp_register_mem_resource(option, mem);
553         return;
554 }
555
556 static void
557 pnpacpi_parse_address_option(struct pnp_option *option, struct acpi_resource *r)
558 {
559         struct acpi_resource_address64 addr, *p = &addr;
560         acpi_status status;
561         struct pnp_mem *mem;
562         struct pnp_port *port;
563
564         status = acpi_resource_to_address64(r, p);
565         if (!ACPI_SUCCESS(status)) {
566                 pnp_warn("PnPACPI: failed to convert resource type %d",
567                          r->type);
568                 return;
569         }
570
571         if (p->address_length == 0)
572                 return;
573
574         if (p->resource_type == ACPI_MEMORY_RANGE) {
575                 mem = kzalloc(sizeof(struct pnp_mem), GFP_KERNEL);
576                 if (!mem)
577                         return;
578                 mem->min = mem->max = p->minimum;
579                 mem->size = p->address_length;
580                 mem->align = 0;
581                 mem->flags = (p->info.mem.write_protect ==
582                               ACPI_READ_WRITE_MEMORY) ? IORESOURCE_MEM_WRITEABLE
583                     : 0;
584                 pnp_register_mem_resource(option, mem);
585         } else if (p->resource_type == ACPI_IO_RANGE) {
586                 port = kzalloc(sizeof(struct pnp_port), GFP_KERNEL);
587                 if (!port)
588                         return;
589                 port->min = port->max = p->minimum;
590                 port->size = p->address_length;
591                 port->align = 0;
592                 port->flags = PNP_PORT_FLAG_FIXED;
593                 pnp_register_port_resource(option, port);
594         }
595 }
596
597 struct acpipnp_parse_option_s {
598         struct pnp_option *option;
599         struct pnp_option *option_independent;
600         struct pnp_dev *dev;
601 };
602
603 static acpi_status pnpacpi_option_resource(struct acpi_resource *res,
604                                            void *data)
605 {
606         int priority = 0;
607         struct acpipnp_parse_option_s *parse_data =
608             (struct acpipnp_parse_option_s *)data;
609         struct pnp_dev *dev = parse_data->dev;
610         struct pnp_option *option = parse_data->option;
611
612         switch (res->type) {
613         case ACPI_RESOURCE_TYPE_IRQ:
614                 pnpacpi_parse_irq_option(option, &res->data.irq);
615                 break;
616
617         case ACPI_RESOURCE_TYPE_DMA:
618                 pnpacpi_parse_dma_option(option, &res->data.dma);
619                 break;
620
621         case ACPI_RESOURCE_TYPE_START_DEPENDENT:
622                 switch (res->data.start_dpf.compatibility_priority) {
623                 case ACPI_GOOD_CONFIGURATION:
624                         priority = PNP_RES_PRIORITY_PREFERRED;
625                         break;
626
627                 case ACPI_ACCEPTABLE_CONFIGURATION:
628                         priority = PNP_RES_PRIORITY_ACCEPTABLE;
629                         break;
630
631                 case ACPI_SUB_OPTIMAL_CONFIGURATION:
632                         priority = PNP_RES_PRIORITY_FUNCTIONAL;
633                         break;
634                 default:
635                         priority = PNP_RES_PRIORITY_INVALID;
636                         break;
637                 }
638                 /* TBD: Considering performace/robustness bits */
639                 option = pnp_register_dependent_option(dev, priority);
640                 if (!option)
641                         return AE_ERROR;
642                 parse_data->option = option;
643                 break;
644
645         case ACPI_RESOURCE_TYPE_END_DEPENDENT:
646                 /*only one EndDependentFn is allowed */
647                 if (!parse_data->option_independent) {
648                         pnp_warn("PnPACPI: more than one EndDependentFn");
649                         return AE_ERROR;
650                 }
651                 parse_data->option = parse_data->option_independent;
652                 parse_data->option_independent = NULL;
653                 break;
654
655         case ACPI_RESOURCE_TYPE_IO:
656                 pnpacpi_parse_port_option(option, &res->data.io);
657                 break;
658
659         case ACPI_RESOURCE_TYPE_FIXED_IO:
660                 pnpacpi_parse_fixed_port_option(option, &res->data.fixed_io);
661                 break;
662
663         case ACPI_RESOURCE_TYPE_VENDOR:
664         case ACPI_RESOURCE_TYPE_END_TAG:
665                 break;
666
667         case ACPI_RESOURCE_TYPE_MEMORY24:
668                 pnpacpi_parse_mem24_option(option, &res->data.memory24);
669                 break;
670
671         case ACPI_RESOURCE_TYPE_MEMORY32:
672                 pnpacpi_parse_mem32_option(option, &res->data.memory32);
673                 break;
674
675         case ACPI_RESOURCE_TYPE_FIXED_MEMORY32:
676                 pnpacpi_parse_fixed_mem32_option(option,
677                                                  &res->data.fixed_memory32);
678                 break;
679
680         case ACPI_RESOURCE_TYPE_ADDRESS16:
681         case ACPI_RESOURCE_TYPE_ADDRESS32:
682         case ACPI_RESOURCE_TYPE_ADDRESS64:
683                 pnpacpi_parse_address_option(option, res);
684                 break;
685
686         case ACPI_RESOURCE_TYPE_EXTENDED_ADDRESS64:
687                 break;
688
689         case ACPI_RESOURCE_TYPE_EXTENDED_IRQ:
690                 pnpacpi_parse_ext_irq_option(option, &res->data.extended_irq);
691                 break;
692
693         case ACPI_RESOURCE_TYPE_GENERIC_REGISTER:
694                 break;
695
696         default:
697                 pnp_warn("PnPACPI: unknown resource type %d", res->type);
698                 return AE_ERROR;
699         }
700
701         return AE_OK;
702 }
703
704 acpi_status pnpacpi_parse_resource_option_data(acpi_handle handle,
705                                                struct pnp_dev * dev)
706 {
707         acpi_status status;
708         struct acpipnp_parse_option_s parse_data;
709
710         parse_data.option = pnp_register_independent_option(dev);
711         if (!parse_data.option)
712                 return AE_ERROR;
713         parse_data.option_independent = parse_data.option;
714         parse_data.dev = dev;
715         status = acpi_walk_resources(handle, METHOD_NAME__PRS,
716                                      pnpacpi_option_resource, &parse_data);
717
718         return status;
719 }
720
721 static int pnpacpi_supported_resource(struct acpi_resource *res)
722 {
723         switch (res->type) {
724         case ACPI_RESOURCE_TYPE_IRQ:
725         case ACPI_RESOURCE_TYPE_DMA:
726         case ACPI_RESOURCE_TYPE_IO:
727         case ACPI_RESOURCE_TYPE_FIXED_IO:
728         case ACPI_RESOURCE_TYPE_MEMORY24:
729         case ACPI_RESOURCE_TYPE_MEMORY32:
730         case ACPI_RESOURCE_TYPE_FIXED_MEMORY32:
731         case ACPI_RESOURCE_TYPE_ADDRESS16:
732         case ACPI_RESOURCE_TYPE_ADDRESS32:
733         case ACPI_RESOURCE_TYPE_ADDRESS64:
734         case ACPI_RESOURCE_TYPE_EXTENDED_IRQ:
735                 return 1;
736         }
737         return 0;
738 }
739
740 /*
741  * Set resource
742  */
743 static acpi_status pnpacpi_count_resources(struct acpi_resource *res,
744                                            void *data)
745 {
746         int *res_cnt = (int *)data;
747
748         if (pnpacpi_supported_resource(res))
749                 (*res_cnt)++;
750         return AE_OK;
751 }
752
753 static acpi_status pnpacpi_type_resources(struct acpi_resource *res, void *data)
754 {
755         struct acpi_resource **resource = (struct acpi_resource **)data;
756
757         if (pnpacpi_supported_resource(res)) {
758                 (*resource)->type = res->type;
759                 (*resource)->length = sizeof(struct acpi_resource);
760                 (*resource)++;
761         }
762
763         return AE_OK;
764 }
765
766 int pnpacpi_build_resource_template(acpi_handle handle,
767                                     struct acpi_buffer *buffer)
768 {
769         struct acpi_resource *resource;
770         int res_cnt = 0;
771         acpi_status status;
772
773         status = acpi_walk_resources(handle, METHOD_NAME__CRS,
774                                      pnpacpi_count_resources, &res_cnt);
775         if (ACPI_FAILURE(status)) {
776                 pnp_err("Evaluate _CRS failed");
777                 return -EINVAL;
778         }
779         if (!res_cnt)
780                 return -EINVAL;
781         buffer->length = sizeof(struct acpi_resource) * (res_cnt + 1) + 1;
782         buffer->pointer = kzalloc(buffer->length - 1, GFP_KERNEL);
783         if (!buffer->pointer)
784                 return -ENOMEM;
785         pnp_dbg("Res cnt %d", res_cnt);
786         resource = (struct acpi_resource *)buffer->pointer;
787         status = acpi_walk_resources(handle, METHOD_NAME__CRS,
788                                      pnpacpi_type_resources, &resource);
789         if (ACPI_FAILURE(status)) {
790                 kfree(buffer->pointer);
791                 pnp_err("Evaluate _CRS failed");
792                 return -EINVAL;
793         }
794         /* resource will pointer the end resource now */
795         resource->type = ACPI_RESOURCE_TYPE_END_TAG;
796
797         return 0;
798 }
799
800 static void pnpacpi_encode_irq(struct acpi_resource *resource,
801                                struct resource *p)
802 {
803         int triggering, polarity;
804
805         decode_irq_flags(p->flags & IORESOURCE_BITS, &triggering, &polarity);
806         resource->data.irq.triggering = triggering;
807         resource->data.irq.polarity = polarity;
808         if (triggering == ACPI_EDGE_SENSITIVE)
809                 resource->data.irq.sharable = ACPI_EXCLUSIVE;
810         else
811                 resource->data.irq.sharable = ACPI_SHARED;
812         resource->data.irq.interrupt_count = 1;
813         resource->data.irq.interrupts[0] = p->start;
814 }
815
816 static void pnpacpi_encode_ext_irq(struct acpi_resource *resource,
817                                    struct resource *p)
818 {
819         int triggering, polarity;
820
821         decode_irq_flags(p->flags & IORESOURCE_BITS, &triggering, &polarity);
822         resource->data.extended_irq.producer_consumer = ACPI_CONSUMER;
823         resource->data.extended_irq.triggering = triggering;
824         resource->data.extended_irq.polarity = polarity;
825         if (triggering == ACPI_EDGE_SENSITIVE)
826                 resource->data.irq.sharable = ACPI_EXCLUSIVE;
827         else
828                 resource->data.irq.sharable = ACPI_SHARED;
829         resource->data.extended_irq.interrupt_count = 1;
830         resource->data.extended_irq.interrupts[0] = p->start;
831 }
832
833 static void pnpacpi_encode_dma(struct acpi_resource *resource,
834                                struct resource *p)
835 {
836         /* Note: pnp_assign_dma will copy pnp_dma->flags into p->flags */
837         switch (p->flags & IORESOURCE_DMA_SPEED_MASK) {
838         case IORESOURCE_DMA_TYPEA:
839                 resource->data.dma.type = ACPI_TYPE_A;
840                 break;
841         case IORESOURCE_DMA_TYPEB:
842                 resource->data.dma.type = ACPI_TYPE_B;
843                 break;
844         case IORESOURCE_DMA_TYPEF:
845                 resource->data.dma.type = ACPI_TYPE_F;
846                 break;
847         default:
848                 resource->data.dma.type = ACPI_COMPATIBILITY;
849         }
850
851         switch (p->flags & IORESOURCE_DMA_TYPE_MASK) {
852         case IORESOURCE_DMA_8BIT:
853                 resource->data.dma.transfer = ACPI_TRANSFER_8;
854                 break;
855         case IORESOURCE_DMA_8AND16BIT:
856                 resource->data.dma.transfer = ACPI_TRANSFER_8_16;
857                 break;
858         default:
859                 resource->data.dma.transfer = ACPI_TRANSFER_16;
860         }
861
862         resource->data.dma.bus_master = !!(p->flags & IORESOURCE_DMA_MASTER);
863         resource->data.dma.channel_count = 1;
864         resource->data.dma.channels[0] = p->start;
865 }
866
867 static void pnpacpi_encode_io(struct acpi_resource *resource,
868                               struct resource *p)
869 {
870         /* Note: pnp_assign_port will copy pnp_port->flags into p->flags */
871         resource->data.io.io_decode = (p->flags & PNP_PORT_FLAG_16BITADDR) ?
872             ACPI_DECODE_16 : ACPI_DECODE_10;
873         resource->data.io.minimum = p->start;
874         resource->data.io.maximum = p->end;
875         resource->data.io.alignment = 0;        /* Correct? */
876         resource->data.io.address_length = p->end - p->start + 1;
877 }
878
879 static void pnpacpi_encode_fixed_io(struct acpi_resource *resource,
880                                     struct resource *p)
881 {
882         resource->data.fixed_io.address = p->start;
883         resource->data.fixed_io.address_length = p->end - p->start + 1;
884 }
885
886 static void pnpacpi_encode_mem24(struct acpi_resource *resource,
887                                  struct resource *p)
888 {
889         /* Note: pnp_assign_mem will copy pnp_mem->flags into p->flags */
890         resource->data.memory24.write_protect =
891             (p->flags & IORESOURCE_MEM_WRITEABLE) ?
892             ACPI_READ_WRITE_MEMORY : ACPI_READ_ONLY_MEMORY;
893         resource->data.memory24.minimum = p->start;
894         resource->data.memory24.maximum = p->end;
895         resource->data.memory24.alignment = 0;
896         resource->data.memory24.address_length = p->end - p->start + 1;
897 }
898
899 static void pnpacpi_encode_mem32(struct acpi_resource *resource,
900                                  struct resource *p)
901 {
902         resource->data.memory32.write_protect =
903             (p->flags & IORESOURCE_MEM_WRITEABLE) ?
904             ACPI_READ_WRITE_MEMORY : ACPI_READ_ONLY_MEMORY;
905         resource->data.memory32.minimum = p->start;
906         resource->data.memory32.maximum = p->end;
907         resource->data.memory32.alignment = 0;
908         resource->data.memory32.address_length = p->end - p->start + 1;
909 }
910
911 static void pnpacpi_encode_fixed_mem32(struct acpi_resource *resource,
912                                        struct resource *p)
913 {
914         resource->data.fixed_memory32.write_protect =
915             (p->flags & IORESOURCE_MEM_WRITEABLE) ?
916             ACPI_READ_WRITE_MEMORY : ACPI_READ_ONLY_MEMORY;
917         resource->data.fixed_memory32.address = p->start;
918         resource->data.fixed_memory32.address_length = p->end - p->start + 1;
919 }
920
921 int pnpacpi_encode_resources(struct pnp_resource_table *res_table,
922                              struct acpi_buffer *buffer)
923 {
924         int i = 0;
925         /* pnpacpi_build_resource_template allocates extra mem */
926         int res_cnt = (buffer->length - 1) / sizeof(struct acpi_resource) - 1;
927         struct acpi_resource *resource =
928             (struct acpi_resource *)buffer->pointer;
929         int port = 0, irq = 0, dma = 0, mem = 0;
930
931         pnp_dbg("res cnt %d", res_cnt);
932         while (i < res_cnt) {
933                 switch (resource->type) {
934                 case ACPI_RESOURCE_TYPE_IRQ:
935                         pnp_dbg("Encode irq");
936                         pnpacpi_encode_irq(resource,
937                                            &res_table->irq_resource[irq]);
938                         irq++;
939                         break;
940
941                 case ACPI_RESOURCE_TYPE_DMA:
942                         pnp_dbg("Encode dma");
943                         pnpacpi_encode_dma(resource,
944                                            &res_table->dma_resource[dma]);
945                         dma++;
946                         break;
947                 case ACPI_RESOURCE_TYPE_IO:
948                         pnp_dbg("Encode io");
949                         pnpacpi_encode_io(resource,
950                                           &res_table->port_resource[port]);
951                         port++;
952                         break;
953                 case ACPI_RESOURCE_TYPE_FIXED_IO:
954                         pnp_dbg("Encode fixed io");
955                         pnpacpi_encode_fixed_io(resource,
956                                                 &res_table->
957                                                 port_resource[port]);
958                         port++;
959                         break;
960                 case ACPI_RESOURCE_TYPE_MEMORY24:
961                         pnp_dbg("Encode mem24");
962                         pnpacpi_encode_mem24(resource,
963                                              &res_table->mem_resource[mem]);
964                         mem++;
965                         break;
966                 case ACPI_RESOURCE_TYPE_MEMORY32:
967                         pnp_dbg("Encode mem32");
968                         pnpacpi_encode_mem32(resource,
969                                              &res_table->mem_resource[mem]);
970                         mem++;
971                         break;
972                 case ACPI_RESOURCE_TYPE_FIXED_MEMORY32:
973                         pnp_dbg("Encode fixed mem32");
974                         pnpacpi_encode_fixed_mem32(resource,
975                                                    &res_table->
976                                                    mem_resource[mem]);
977                         mem++;
978                         break;
979                 case ACPI_RESOURCE_TYPE_EXTENDED_IRQ:
980                         pnp_dbg("Encode ext irq");
981                         pnpacpi_encode_ext_irq(resource,
982                                                &res_table->irq_resource[irq]);
983                         irq++;
984                         break;
985                 case ACPI_RESOURCE_TYPE_START_DEPENDENT:
986                 case ACPI_RESOURCE_TYPE_END_DEPENDENT:
987                 case ACPI_RESOURCE_TYPE_VENDOR:
988                 case ACPI_RESOURCE_TYPE_END_TAG:
989                 case ACPI_RESOURCE_TYPE_ADDRESS16:
990                 case ACPI_RESOURCE_TYPE_ADDRESS32:
991                 case ACPI_RESOURCE_TYPE_ADDRESS64:
992                 case ACPI_RESOURCE_TYPE_EXTENDED_ADDRESS64:
993                 case ACPI_RESOURCE_TYPE_GENERIC_REGISTER:
994                 default:        /* other type */
995                         pnp_warn("unknown resource type %d", resource->type);
996                         return -EINVAL;
997                 }
998                 resource++;
999                 i++;
1000         }
1001         return 0;
1002 }