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