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