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