This commit was manufactured by cvs2svn to create branch 'vserver'.
[linux-2.6.git] / drivers / pnp / pnpacpi / rsparser.c
1 /*
2  * pnpacpi -- PnP ACPI driver
3  *
4  * Copyright (c) 2004 Matthieu Castet <castet.matthieu@free.fr>
5  * Copyright (c) 2004 Li Shaohua <shaohua.li@intel.com>
6  * 
7  * This program is free software; you can redistribute it and/or modify it
8  * under the terms of the GNU General Public License as published by the
9  * Free Software Foundation; either version 2, or (at your option) any
10  * later version.
11  *
12  * This program is distributed in the hope that it will be useful, but
13  * WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
20  */
21 #include <linux/kernel.h>
22 #include <linux/acpi.h>
23 #include <linux/pci.h>
24 #include "pnpacpi.h"
25
26 #ifdef CONFIG_IA64
27 #define valid_IRQ(i) (1)
28 #else
29 #define valid_IRQ(i) (((i) != 0) && ((i) != 2))
30 #endif
31
32 /*
33  * Allocated Resources
34  */
35 static int irq_flags(int edge_level, int active_high_low)
36 {
37         int flag;
38         if (edge_level == ACPI_LEVEL_SENSITIVE) {
39                 if(active_high_low == ACPI_ACTIVE_LOW)
40                         flag = IORESOURCE_IRQ_LOWLEVEL;
41                 else
42                         flag = IORESOURCE_IRQ_HIGHLEVEL;
43         }
44         else {
45                 if(active_high_low == 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 *edge_level, int *active_high_low)
54 {
55         switch (flag) {
56         case IORESOURCE_IRQ_LOWLEVEL:
57                 *edge_level = ACPI_LEVEL_SENSITIVE;
58                 *active_high_low = ACPI_ACTIVE_LOW;
59                 break;
60         case IORESOURCE_IRQ_HIGHLEVEL:  
61                 *edge_level = ACPI_LEVEL_SENSITIVE;
62                 *active_high_low = ACPI_ACTIVE_HIGH;
63                 break;
64         case IORESOURCE_IRQ_LOWEDGE:
65                 *edge_level = ACPI_EDGE_SENSITIVE;
66                 *active_high_low = ACPI_ACTIVE_LOW;
67                 break;
68         case IORESOURCE_IRQ_HIGHEDGE:
69                 *edge_level = ACPI_EDGE_SENSITIVE;
70                 *active_high_low = ACPI_ACTIVE_HIGH;
71                 break;
72         }
73 }
74
75 static void
76 pnpacpi_parse_allocated_irqresource(struct pnp_resource_table * res, int irq)
77 {
78         int i = 0;
79         while (!(res->irq_resource[i].flags & IORESOURCE_UNSET) &&
80                         i < PNP_MAX_IRQ)
81                 i++;
82         if (i < PNP_MAX_IRQ) {
83                 res->irq_resource[i].flags = IORESOURCE_IRQ;  //Also clears _UNSET flag
84                 if (irq == -1) {
85                         res->irq_resource[i].flags |= IORESOURCE_DISABLED;
86                         return;
87                 }
88                 res->irq_resource[i].start =(unsigned long) irq;
89                 res->irq_resource[i].end = (unsigned long) irq;
90         }
91 }
92
93 static void
94 pnpacpi_parse_allocated_dmaresource(struct pnp_resource_table * res, int dma)
95 {
96         int i = 0;
97         while (!(res->dma_resource[i].flags & IORESOURCE_UNSET) &&
98                         i < PNP_MAX_DMA)
99                 i++;
100         if (i < PNP_MAX_DMA) {
101                 res->dma_resource[i].flags = IORESOURCE_DMA;  // Also clears _UNSET flag
102                 if (dma == -1) {
103                         res->dma_resource[i].flags |= IORESOURCE_DISABLED;
104                         return;
105                 }
106                 res->dma_resource[i].start =(unsigned long) dma;
107                 res->dma_resource[i].end = (unsigned long) dma;
108         }
109 }
110
111 static void
112 pnpacpi_parse_allocated_ioresource(struct pnp_resource_table * res,
113         int io, int len)
114 {
115         int i = 0;
116         while (!(res->port_resource[i].flags & IORESOURCE_UNSET) &&
117                         i < PNP_MAX_PORT)
118                 i++;
119         if (i < PNP_MAX_PORT) {
120                 res->port_resource[i].flags = IORESOURCE_IO;  // Also clears _UNSET flag
121                 if (len <= 0 || (io + len -1) >= 0x10003) {
122                         res->port_resource[i].flags |= IORESOURCE_DISABLED;
123                         return;
124                 }
125                 res->port_resource[i].start = (unsigned long) io;
126                 res->port_resource[i].end = (unsigned long)(io + len - 1);
127         }
128 }
129
130 static void
131 pnpacpi_parse_allocated_memresource(struct pnp_resource_table * res,
132         int mem, int len)
133 {
134         int i = 0;
135         while (!(res->mem_resource[i].flags & IORESOURCE_UNSET) &&
136                         (i < PNP_MAX_MEM))
137                 i++;
138         if (i < PNP_MAX_MEM) {
139                 res->mem_resource[i].flags = IORESOURCE_MEM;  // Also clears _UNSET flag
140                 if (len <= 0) {
141                         res->mem_resource[i].flags |= IORESOURCE_DISABLED;
142                         return;
143                 }
144                 res->mem_resource[i].start = (unsigned long) mem;
145                 res->mem_resource[i].end = (unsigned long)(mem + len - 1);
146         }
147 }
148
149
150 static acpi_status pnpacpi_allocated_resource(struct acpi_resource *res,
151         void *data)
152 {
153         struct pnp_resource_table * res_table = (struct pnp_resource_table *)data;
154
155         switch (res->id) {
156         case ACPI_RSTYPE_IRQ:
157                 if ((res->data.irq.number_of_interrupts > 0) &&
158                         valid_IRQ(res->data.irq.interrupts[0])) {
159                         pnpacpi_parse_allocated_irqresource(res_table, 
160                                 acpi_register_gsi(res->data.irq.interrupts[0],
161                                         res->data.irq.edge_level,
162                                         res->data.irq.active_high_low));
163                         pcibios_penalize_isa_irq(res->data.irq.interrupts[0]);
164                 }
165                 break;
166
167         case ACPI_RSTYPE_EXT_IRQ:
168                 if ((res->data.extended_irq.number_of_interrupts > 0) &&
169                         valid_IRQ(res->data.extended_irq.interrupts[0])) {
170                         pnpacpi_parse_allocated_irqresource(res_table, 
171                                 acpi_register_gsi(res->data.extended_irq.interrupts[0],
172                                         res->data.extended_irq.edge_level,
173                                         res->data.extended_irq.active_high_low));
174                         pcibios_penalize_isa_irq(res->data.extended_irq.interrupts[0]);
175                 }
176                 break;
177         case ACPI_RSTYPE_DMA:
178                 if (res->data.dma.number_of_channels > 0)
179                         pnpacpi_parse_allocated_dmaresource(res_table, 
180                                         res->data.dma.channels[0]);
181                 break;
182         case ACPI_RSTYPE_IO:
183                 pnpacpi_parse_allocated_ioresource(res_table, 
184                                 res->data.io.min_base_address, 
185                                 res->data.io.range_length);
186                 break;
187         case ACPI_RSTYPE_FIXED_IO:
188                 pnpacpi_parse_allocated_ioresource(res_table, 
189                                 res->data.fixed_io.base_address, 
190                                 res->data.fixed_io.range_length);
191                 break;
192         case ACPI_RSTYPE_MEM24:
193                 pnpacpi_parse_allocated_memresource(res_table, 
194                                 res->data.memory24.min_base_address, 
195                                 res->data.memory24.range_length);
196                 break;
197         case ACPI_RSTYPE_MEM32:
198                 pnpacpi_parse_allocated_memresource(res_table, 
199                                 res->data.memory32.min_base_address, 
200                                 res->data.memory32.range_length);
201                 break;
202         case ACPI_RSTYPE_FIXED_MEM32:
203                 pnpacpi_parse_allocated_memresource(res_table, 
204                                 res->data.fixed_memory32.range_base_address, 
205                                 res->data.fixed_memory32.range_length);
206                 break;
207         case ACPI_RSTYPE_ADDRESS16:
208                 pnpacpi_parse_allocated_memresource(res_table, 
209                                 res->data.address16.min_address_range, 
210                                 res->data.address16.address_length);
211                 break;
212         case ACPI_RSTYPE_ADDRESS32:
213                 pnpacpi_parse_allocated_memresource(res_table, 
214                                 res->data.address32.min_address_range, 
215                                 res->data.address32.address_length);
216                 break;
217         case ACPI_RSTYPE_ADDRESS64:
218                 pnpacpi_parse_allocated_memresource(res_table, 
219                 res->data.address64.min_address_range, 
220                 res->data.address64.address_length);
221                 break;
222         default:
223                 pnp_warn("PnPACPI: Alloc type : %d not handle", 
224                                 res->id);
225                 return AE_ERROR;
226         }
227                         
228         return AE_OK;
229 }
230
231 acpi_status pnpacpi_parse_allocated_resource(acpi_handle handle, struct pnp_resource_table * res)
232 {
233         /* Blank the resource table values */
234         pnp_init_resource_table(res);
235
236         return acpi_walk_resources(handle, METHOD_NAME__CRS, pnpacpi_allocated_resource, res);
237 }
238
239 static void pnpacpi_parse_dma_option(struct pnp_option *option, struct acpi_resource_dma *p)
240 {
241         int i;
242         struct pnp_dma * dma;
243
244         if (p->number_of_channels == 0)
245                 return;
246         dma = pnpacpi_kmalloc(sizeof(struct pnp_dma), GFP_KERNEL);
247         if (!dma)
248                 return;
249
250         for(i = 0; i < p->number_of_channels; i++)
251                 dma->map |= 1 << p->channels[i];
252         dma->flags = 0;
253         if (p->bus_master)
254                 dma->flags |= IORESOURCE_DMA_MASTER;
255         switch (p->type) {
256         case ACPI_COMPATIBILITY:
257                 dma->flags |= IORESOURCE_DMA_COMPATIBLE;
258                 break;
259         case ACPI_TYPE_A:
260                 dma->flags |= IORESOURCE_DMA_TYPEA;
261                 break;
262         case ACPI_TYPE_B:
263                 dma->flags |= IORESOURCE_DMA_TYPEB;
264                 break;
265         case ACPI_TYPE_F:
266                 dma->flags |= IORESOURCE_DMA_TYPEF;
267                 break;
268         default:
269                 /* Set a default value ? */
270                 dma->flags |= IORESOURCE_DMA_COMPATIBLE;
271                 pnp_err("Invalid DMA type");
272         }
273         switch (p->transfer) {
274         case ACPI_TRANSFER_8:
275                 dma->flags |= IORESOURCE_DMA_8BIT;
276                 break;
277         case ACPI_TRANSFER_8_16:
278                 dma->flags |= IORESOURCE_DMA_8AND16BIT;
279                 break;
280         case ACPI_TRANSFER_16:
281                 dma->flags |= IORESOURCE_DMA_16BIT;
282                 break;
283         default:
284                 /* Set a default value ? */
285                 dma->flags |= IORESOURCE_DMA_8AND16BIT;
286                 pnp_err("Invalid DMA transfer type");
287         }
288
289         pnp_register_dma_resource(option,dma);
290         return;
291 }
292
293         
294 static void pnpacpi_parse_irq_option(struct pnp_option *option,
295         struct acpi_resource_irq *p)
296 {
297         int i;
298         struct pnp_irq * irq;
299         
300         if (p->number_of_interrupts == 0)
301                 return;
302         irq = pnpacpi_kmalloc(sizeof(struct pnp_irq), GFP_KERNEL);
303         if (!irq)
304                 return;
305
306         for(i = 0; i < p->number_of_interrupts; i++)
307                 if (p->interrupts[i])
308                         __set_bit(p->interrupts[i], irq->map);
309         irq->flags = irq_flags(p->edge_level, p->active_high_low);
310
311         pnp_register_irq_resource(option, irq);
312         return;
313 }
314
315 static void pnpacpi_parse_ext_irq_option(struct pnp_option *option,
316         struct acpi_resource_ext_irq *p)
317 {
318         int i;
319         struct pnp_irq * irq;
320
321         if (p->number_of_interrupts == 0)
322                 return;
323         irq = pnpacpi_kmalloc(sizeof(struct pnp_irq), GFP_KERNEL);
324         if (!irq)
325                 return;
326
327         for(i = 0; i < p->number_of_interrupts; i++)
328                 if (p->interrupts[i])
329                         __set_bit(p->interrupts[i], irq->map);
330         irq->flags = irq_flags(p->edge_level, p->active_high_low);
331
332         pnp_register_irq_resource(option, irq);
333         return;
334 }
335
336 static void
337 pnpacpi_parse_port_option(struct pnp_option *option,
338         struct acpi_resource_io *io)
339 {
340         struct pnp_port * port;
341
342         if (io->range_length == 0)
343                 return;
344         port = pnpacpi_kmalloc(sizeof(struct pnp_port), GFP_KERNEL);
345         if (!port)
346                 return;
347         port->min = io->min_base_address;
348         port->max = io->max_base_address;
349         port->align = io->alignment;
350         port->size = io->range_length;
351         port->flags = ACPI_DECODE_16 == io->io_decode ? 
352                 PNP_PORT_FLAG_16BITADDR : 0;
353         pnp_register_port_resource(option,port);
354         return;
355 }
356
357 static void
358 pnpacpi_parse_fixed_port_option(struct pnp_option *option,
359         struct acpi_resource_fixed_io *io)
360 {
361         struct pnp_port * port;
362
363         if (io->range_length == 0)
364                 return;
365         port = pnpacpi_kmalloc(sizeof(struct pnp_port), GFP_KERNEL);
366         if (!port)
367                 return;
368         port->min = port->max = io->base_address;
369         port->size = io->range_length;
370         port->align = 0;
371         port->flags = PNP_PORT_FLAG_FIXED;
372         pnp_register_port_resource(option,port);
373         return;
374 }
375
376 static void
377 pnpacpi_parse_mem24_option(struct pnp_option *option,
378         struct acpi_resource_mem24 *p)
379 {
380         struct pnp_mem * mem;
381
382         if (p->range_length == 0)
383                 return;
384         mem = pnpacpi_kmalloc(sizeof(struct pnp_mem), GFP_KERNEL);
385         if (!mem)
386                 return;
387         mem->min = p->min_base_address;
388         mem->max = p->max_base_address;
389         mem->align = p->alignment;
390         mem->size = p->range_length;
391
392         mem->flags = (ACPI_READ_WRITE_MEMORY == p->read_write_attribute) ?
393                         IORESOURCE_MEM_WRITEABLE : 0;
394
395         pnp_register_mem_resource(option,mem);
396         return;
397 }
398
399 static void
400 pnpacpi_parse_mem32_option(struct pnp_option *option,
401         struct acpi_resource_mem32 *p)
402 {
403         struct pnp_mem * mem;
404
405         if (p->range_length == 0)
406                 return;
407         mem = pnpacpi_kmalloc(sizeof(struct pnp_mem), GFP_KERNEL);
408         if (!mem)
409                 return;
410         mem->min = p->min_base_address;
411         mem->max = p->max_base_address;
412         mem->align = p->alignment;
413         mem->size = p->range_length;
414
415         mem->flags = (ACPI_READ_WRITE_MEMORY == p->read_write_attribute) ?
416                         IORESOURCE_MEM_WRITEABLE : 0;
417
418         pnp_register_mem_resource(option,mem);
419         return;
420 }
421
422 static void
423 pnpacpi_parse_fixed_mem32_option(struct pnp_option *option,
424         struct acpi_resource_fixed_mem32 *p)
425 {
426         struct pnp_mem * mem;
427
428         if (p->range_length == 0)
429                 return;
430         mem = pnpacpi_kmalloc(sizeof(struct pnp_mem), GFP_KERNEL);
431         if (!mem)
432                 return;
433         mem->min = mem->max = p->range_base_address;
434         mem->size = p->range_length;
435         mem->align = 0;
436
437         mem->flags = (ACPI_READ_WRITE_MEMORY == p->read_write_attribute) ?
438                         IORESOURCE_MEM_WRITEABLE : 0;
439
440         pnp_register_mem_resource(option,mem);
441         return;
442 }
443
444 struct acpipnp_parse_option_s {
445         struct pnp_option *option;
446         struct pnp_dev *dev;
447 };
448
449 static acpi_status pnpacpi_option_resource(struct acpi_resource *res, 
450         void *data)
451 {
452         int priority = 0;
453         struct acpipnp_parse_option_s *parse_data = (struct acpipnp_parse_option_s *)data;
454         struct pnp_dev *dev = parse_data->dev;
455         struct pnp_option *option = parse_data->option;
456
457         switch (res->id) {
458                 case ACPI_RSTYPE_IRQ:
459                         pnpacpi_parse_irq_option(option, &res->data.irq);
460                         break;
461                 case ACPI_RSTYPE_EXT_IRQ:
462                         pnpacpi_parse_ext_irq_option(option,
463                                 &res->data.extended_irq);
464                         break;
465                 case ACPI_RSTYPE_DMA:
466                         pnpacpi_parse_dma_option(option, &res->data.dma);       
467                         break;
468                 case ACPI_RSTYPE_IO:
469                         pnpacpi_parse_port_option(option, &res->data.io);
470                         break;
471                 case ACPI_RSTYPE_FIXED_IO:
472                         pnpacpi_parse_fixed_port_option(option,
473                                 &res->data.fixed_io);
474                         break;
475                 case ACPI_RSTYPE_MEM24:
476                         pnpacpi_parse_mem24_option(option, &res->data.memory24);
477                         break;
478                 case ACPI_RSTYPE_MEM32:
479                         pnpacpi_parse_mem32_option(option, &res->data.memory32);
480                         break;
481                 case ACPI_RSTYPE_FIXED_MEM32:
482                         pnpacpi_parse_fixed_mem32_option(option,
483                                 &res->data.fixed_memory32);
484                         break;
485                 case ACPI_RSTYPE_START_DPF:
486                         switch (res->data.start_dpf.compatibility_priority) {
487                                 case ACPI_GOOD_CONFIGURATION:
488                                         priority = PNP_RES_PRIORITY_PREFERRED;
489                                         break;
490                                         
491                                 case ACPI_ACCEPTABLE_CONFIGURATION:
492                                         priority = PNP_RES_PRIORITY_ACCEPTABLE;
493                                         break;
494
495                                 case ACPI_SUB_OPTIMAL_CONFIGURATION:
496                                         priority = PNP_RES_PRIORITY_FUNCTIONAL;
497                                         break;
498                                 default:
499                                         priority = PNP_RES_PRIORITY_INVALID;
500                                         break;
501                         }
502                         /* TBD: Considering performace/robustness bits */
503                         option = pnp_register_dependent_option(dev, priority);
504                         if (!option)
505                                 return AE_ERROR;
506                         parse_data->option = option;    
507                         break;
508                 case ACPI_RSTYPE_END_DPF:
509                         return AE_CTRL_TERMINATE;
510                 default:
511                         pnp_warn("PnPACPI:Option type: %d not handle", res->id);
512                         return AE_ERROR;
513         }
514                         
515         return AE_OK;
516 }
517
518 acpi_status pnpacpi_parse_resource_option_data(acpi_handle handle, 
519         struct pnp_dev *dev)
520 {
521         acpi_status status;
522         struct acpipnp_parse_option_s parse_data;
523
524         parse_data.option = pnp_register_independent_option(dev);
525         if (!parse_data.option)
526                 return AE_ERROR;
527         parse_data.dev = dev;
528         status = acpi_walk_resources(handle, METHOD_NAME__PRS, 
529                 pnpacpi_option_resource, &parse_data);
530
531         return status;
532 }
533
534 /*
535  * Set resource
536  */
537 static acpi_status pnpacpi_count_resources(struct acpi_resource *res,
538         void *data)
539 {
540         int *res_cnt = (int *)data;
541         switch (res->id) {
542         case ACPI_RSTYPE_IRQ:
543         case ACPI_RSTYPE_EXT_IRQ:
544         case ACPI_RSTYPE_DMA:
545         case ACPI_RSTYPE_IO:
546         case ACPI_RSTYPE_FIXED_IO:
547         case ACPI_RSTYPE_MEM24:
548         case ACPI_RSTYPE_MEM32:
549         case ACPI_RSTYPE_FIXED_MEM32:
550 #if 0
551         case ACPI_RSTYPE_ADDRESS16:
552         case ACPI_RSTYPE_ADDRESS32:
553         case ACPI_RSTYPE_ADDRESS64:
554 #endif
555                 (*res_cnt) ++;
556         default:
557                 return AE_OK;
558         }
559         return AE_OK;
560 }
561
562 static acpi_status pnpacpi_type_resources(struct acpi_resource *res,
563         void *data)
564 {
565         struct acpi_resource **resource = (struct acpi_resource **)data;        
566         switch (res->id) {
567         case ACPI_RSTYPE_IRQ:
568         case ACPI_RSTYPE_EXT_IRQ:
569         case ACPI_RSTYPE_DMA:
570         case ACPI_RSTYPE_IO:
571         case ACPI_RSTYPE_FIXED_IO:
572         case ACPI_RSTYPE_MEM24:
573         case ACPI_RSTYPE_MEM32:
574         case ACPI_RSTYPE_FIXED_MEM32:
575 #if 0
576         case ACPI_RSTYPE_ADDRESS16:
577         case ACPI_RSTYPE_ADDRESS32:
578         case ACPI_RSTYPE_ADDRESS64:
579 #endif
580                 (*resource)->id = res->id;
581                 (*resource)++;
582         default:
583                 return AE_OK;
584         }
585
586         return AE_OK;
587 }
588
589 int pnpacpi_build_resource_template(acpi_handle handle, 
590         struct acpi_buffer *buffer)
591 {
592         struct acpi_resource *resource;
593         int res_cnt = 0;
594         acpi_status status;
595
596         status = acpi_walk_resources(handle, METHOD_NAME__CRS, 
597                 pnpacpi_count_resources, &res_cnt);
598         if (ACPI_FAILURE(status)) {
599                 pnp_err("Evaluate _CRS failed");
600                 return -EINVAL;
601         }
602         if (!res_cnt)
603                 return -EINVAL;
604         buffer->length = sizeof(struct acpi_resource) * (res_cnt + 1) + 1;
605         buffer->pointer = pnpacpi_kmalloc(buffer->length - 1, GFP_KERNEL);
606         if (!buffer->pointer)
607                 return -ENOMEM;
608         pnp_dbg("Res cnt %d", res_cnt);
609         resource = (struct acpi_resource *)buffer->pointer;
610         status = acpi_walk_resources(handle, METHOD_NAME__CRS, 
611                 pnpacpi_type_resources, &resource);
612         if (ACPI_FAILURE(status)) {
613                 kfree(buffer->pointer);
614                 pnp_err("Evaluate _CRS failed");
615                 return -EINVAL;
616         }
617         /* resource will pointer the end resource now */
618         resource->id = ACPI_RSTYPE_END_TAG;
619
620         return 0;
621 }
622
623 static void pnpacpi_encode_irq(struct acpi_resource *resource, 
624         struct resource *p)
625 {
626         int edge_level, active_high_low;
627         
628         decode_irq_flags(p->flags & IORESOURCE_BITS, &edge_level, 
629                 &active_high_low);
630         resource->id = ACPI_RSTYPE_IRQ;
631         resource->length = sizeof(struct acpi_resource);
632         resource->data.irq.edge_level = edge_level;
633         resource->data.irq.active_high_low = active_high_low;
634         if (edge_level == ACPI_EDGE_SENSITIVE)
635                 resource->data.irq.shared_exclusive = ACPI_EXCLUSIVE;
636         else
637                 resource->data.irq.shared_exclusive = ACPI_SHARED;
638         resource->data.irq.number_of_interrupts = 1;
639         resource->data.irq.interrupts[0] = p->start;
640 }
641
642 static void pnpacpi_encode_ext_irq(struct acpi_resource *resource,
643         struct resource *p)
644 {
645         int edge_level, active_high_low;
646         
647         decode_irq_flags(p->flags & IORESOURCE_BITS, &edge_level, 
648                 &active_high_low);
649         resource->id = ACPI_RSTYPE_EXT_IRQ;
650         resource->length = sizeof(struct acpi_resource);
651         resource->data.extended_irq.producer_consumer = ACPI_CONSUMER;
652         resource->data.extended_irq.edge_level = edge_level;
653         resource->data.extended_irq.active_high_low = active_high_low;
654         if (edge_level == ACPI_EDGE_SENSITIVE)
655                 resource->data.irq.shared_exclusive = ACPI_EXCLUSIVE;
656         else
657                 resource->data.irq.shared_exclusive = ACPI_SHARED;
658         resource->data.extended_irq.number_of_interrupts = 1;
659         resource->data.extended_irq.interrupts[0] = p->start;
660 }
661
662 static void pnpacpi_encode_dma(struct acpi_resource *resource,
663         struct resource *p)
664 {
665         resource->id = ACPI_RSTYPE_DMA;
666         resource->length = sizeof(struct acpi_resource);
667         /* Note: pnp_assign_dma will copy pnp_dma->flags into p->flags */
668         if (p->flags & IORESOURCE_DMA_COMPATIBLE)
669                 resource->data.dma.type = ACPI_COMPATIBILITY;
670         else if (p->flags & IORESOURCE_DMA_TYPEA)
671                 resource->data.dma.type = ACPI_TYPE_A;
672         else if (p->flags & IORESOURCE_DMA_TYPEB)
673                 resource->data.dma.type = ACPI_TYPE_B;
674         else if (p->flags & IORESOURCE_DMA_TYPEF)
675                 resource->data.dma.type = ACPI_TYPE_F;
676         if (p->flags & IORESOURCE_DMA_8BIT)
677                 resource->data.dma.transfer = ACPI_TRANSFER_8;
678         else if (p->flags & IORESOURCE_DMA_8AND16BIT)
679                 resource->data.dma.transfer = ACPI_TRANSFER_8_16;
680         else if (p->flags & IORESOURCE_DMA_16BIT)
681                 resource->data.dma.transfer = ACPI_TRANSFER_16;
682         resource->data.dma.bus_master = p->flags & IORESOURCE_DMA_MASTER;
683         resource->data.dma.number_of_channels = 1;
684         resource->data.dma.channels[0] = p->start;
685 }
686
687 static void pnpacpi_encode_io(struct acpi_resource *resource,
688         struct resource *p)
689 {
690         resource->id = ACPI_RSTYPE_IO;
691         resource->length = sizeof(struct acpi_resource);
692         /* Note: pnp_assign_port will copy pnp_port->flags into p->flags */
693         resource->data.io.io_decode = (p->flags & PNP_PORT_FLAG_16BITADDR)?
694                 ACPI_DECODE_16 : ACPI_DECODE_10; 
695         resource->data.io.min_base_address = p->start;
696         resource->data.io.max_base_address = p->end;
697         resource->data.io.alignment = 0; /* Correct? */
698         resource->data.io.range_length = p->end - p->start + 1;
699 }
700
701 static void pnpacpi_encode_fixed_io(struct acpi_resource *resource,
702         struct resource *p)
703 {
704         resource->id = ACPI_RSTYPE_FIXED_IO;
705         resource->length = sizeof(struct acpi_resource);
706         resource->data.fixed_io.base_address = p->start;
707         resource->data.fixed_io.range_length = p->end - p->start + 1;
708 }
709
710 static void pnpacpi_encode_mem24(struct acpi_resource *resource,
711         struct resource *p)
712 {
713         resource->id = ACPI_RSTYPE_MEM24;
714         resource->length = sizeof(struct acpi_resource);
715         /* Note: pnp_assign_mem will copy pnp_mem->flags into p->flags */
716         resource->data.memory24.read_write_attribute =
717                 (p->flags & IORESOURCE_MEM_WRITEABLE) ?
718                 ACPI_READ_WRITE_MEMORY : ACPI_READ_ONLY_MEMORY;
719         resource->data.memory24.min_base_address = p->start;
720         resource->data.memory24.max_base_address = p->end;
721         resource->data.memory24.alignment = 0;
722         resource->data.memory24.range_length = p->end - p->start + 1;
723 }
724
725 static void pnpacpi_encode_mem32(struct acpi_resource *resource,
726         struct resource *p)
727 {
728         resource->id = ACPI_RSTYPE_MEM32;
729         resource->length = sizeof(struct acpi_resource);
730         resource->data.memory32.read_write_attribute =
731                 (p->flags & IORESOURCE_MEM_WRITEABLE) ?
732                 ACPI_READ_WRITE_MEMORY : ACPI_READ_ONLY_MEMORY;
733         resource->data.memory32.min_base_address = p->start;
734         resource->data.memory32.max_base_address = p->end;
735         resource->data.memory32.alignment = 0;
736         resource->data.memory32.range_length = p->end - p->start + 1;
737 }
738
739 static void pnpacpi_encode_fixed_mem32(struct acpi_resource *resource,
740         struct resource *p)
741 {
742         resource->id = ACPI_RSTYPE_FIXED_MEM32;
743         resource->length = sizeof(struct acpi_resource);
744         resource->data.fixed_memory32.read_write_attribute =
745                 (p->flags & IORESOURCE_MEM_WRITEABLE) ?
746                 ACPI_READ_WRITE_MEMORY : ACPI_READ_ONLY_MEMORY;
747         resource->data.fixed_memory32.range_base_address = p->start;
748         resource->data.fixed_memory32.range_length = p->end - p->start + 1;
749 }
750
751 int pnpacpi_encode_resources(struct pnp_resource_table *res_table, 
752         struct acpi_buffer *buffer)
753 {
754         int i = 0;
755         /* pnpacpi_build_resource_template allocates extra mem */
756         int res_cnt = (buffer->length - 1)/sizeof(struct acpi_resource) - 1;
757         struct acpi_resource *resource = (struct acpi_resource*)buffer->pointer;
758         int port = 0, irq = 0, dma = 0, mem = 0;
759
760         pnp_dbg("res cnt %d", res_cnt);
761         while (i < res_cnt) {
762                 switch(resource->id) {
763                 case ACPI_RSTYPE_IRQ:
764                         pnp_dbg("Encode irq");
765                         pnpacpi_encode_irq(resource, 
766                                 &res_table->irq_resource[irq]);
767                         irq++;
768                         break;
769
770                 case ACPI_RSTYPE_EXT_IRQ:
771                         pnp_dbg("Encode ext irq");
772                         pnpacpi_encode_ext_irq(resource, 
773                                 &res_table->irq_resource[irq]);
774                         irq++;
775                         break;
776                 case ACPI_RSTYPE_DMA:
777                         pnp_dbg("Encode dma");
778                         pnpacpi_encode_dma(resource, 
779                                 &res_table->dma_resource[dma]);
780                         dma ++;
781                         break;
782                 case ACPI_RSTYPE_IO:
783                         pnp_dbg("Encode io");
784                         pnpacpi_encode_io(resource, 
785                                 &res_table->port_resource[port]);
786                         port ++;
787                         break;
788                 case ACPI_RSTYPE_FIXED_IO:
789                         pnp_dbg("Encode fixed io");
790                         pnpacpi_encode_fixed_io(resource,
791                                 &res_table->port_resource[port]);
792                         port ++;
793                         break;
794                 case ACPI_RSTYPE_MEM24:
795                         pnp_dbg("Encode mem24");
796                         pnpacpi_encode_mem24(resource,
797                                 &res_table->mem_resource[mem]);
798                         mem ++;
799                         break;
800                 case ACPI_RSTYPE_MEM32:
801                         pnp_dbg("Encode mem32");
802                         pnpacpi_encode_mem32(resource,
803                                 &res_table->mem_resource[mem]);
804                         mem ++;
805                         break;
806                 case ACPI_RSTYPE_FIXED_MEM32:
807                         pnp_dbg("Encode fixed mem32");
808                         pnpacpi_encode_fixed_mem32(resource,
809                                 &res_table->mem_resource[mem]);
810                         mem ++;
811                         break;
812                 default: /* other type */
813                         pnp_warn("Invalid type");
814                         return -EINVAL;
815                 }
816                 resource ++;
817                 i ++;
818         }
819         return 0;
820 }