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