Merge branch 'linux-2.6' into for-2.6.24
[linux-2.6] / drivers / pnp / pnpbios / rsparser.c
1 /*
2  * rsparser.c - parses and encodes pnpbios resource data streams
3  */
4
5 #include <linux/ctype.h>
6 #include <linux/pnp.h>
7 #include <linux/pnpbios.h>
8 #include <linux/string.h>
9 #include <linux/slab.h>
10
11 #ifdef CONFIG_PCI
12 #include <linux/pci.h>
13 #else
14 inline void pcibios_penalize_isa_irq(int irq, int active)
15 {
16 }
17 #endif                          /* CONFIG_PCI */
18
19 #include "pnpbios.h"
20
21 /* standard resource tags */
22 #define SMALL_TAG_PNPVERNO              0x01
23 #define SMALL_TAG_LOGDEVID              0x02
24 #define SMALL_TAG_COMPATDEVID           0x03
25 #define SMALL_TAG_IRQ                   0x04
26 #define SMALL_TAG_DMA                   0x05
27 #define SMALL_TAG_STARTDEP              0x06
28 #define SMALL_TAG_ENDDEP                0x07
29 #define SMALL_TAG_PORT                  0x08
30 #define SMALL_TAG_FIXEDPORT             0x09
31 #define SMALL_TAG_VENDOR                0x0e
32 #define SMALL_TAG_END                   0x0f
33 #define LARGE_TAG                       0x80
34 #define LARGE_TAG_MEM                   0x81
35 #define LARGE_TAG_ANSISTR               0x82
36 #define LARGE_TAG_UNICODESTR            0x83
37 #define LARGE_TAG_VENDOR                0x84
38 #define LARGE_TAG_MEM32                 0x85
39 #define LARGE_TAG_FIXEDMEM32            0x86
40
41 /*
42  * Resource Data Stream Format:
43  *
44  * Allocated Resources (required)
45  * end tag ->
46  * Resource Configuration Options (optional)
47  * end tag ->
48  * Compitable Device IDs (optional)
49  * final end tag ->
50  */
51
52 /*
53  * Allocated Resources
54  */
55
56 static void pnpbios_parse_allocated_irqresource(struct pnp_resource_table *res,
57                                                 int irq)
58 {
59         int i = 0;
60
61         while (!(res->irq_resource[i].flags & IORESOURCE_UNSET)
62                && i < PNP_MAX_IRQ)
63                 i++;
64         if (i < PNP_MAX_IRQ) {
65                 res->irq_resource[i].flags = IORESOURCE_IRQ;    // Also clears _UNSET flag
66                 if (irq == -1) {
67                         res->irq_resource[i].flags |= IORESOURCE_DISABLED;
68                         return;
69                 }
70                 res->irq_resource[i].start =
71                     res->irq_resource[i].end = (unsigned long)irq;
72                 pcibios_penalize_isa_irq(irq, 1);
73         }
74 }
75
76 static void pnpbios_parse_allocated_dmaresource(struct pnp_resource_table *res,
77                                                 int dma)
78 {
79         int i = 0;
80
81         while (i < PNP_MAX_DMA &&
82                !(res->dma_resource[i].flags & IORESOURCE_UNSET))
83                 i++;
84         if (i < PNP_MAX_DMA) {
85                 res->dma_resource[i].flags = IORESOURCE_DMA;    // Also clears _UNSET flag
86                 if (dma == -1) {
87                         res->dma_resource[i].flags |= IORESOURCE_DISABLED;
88                         return;
89                 }
90                 res->dma_resource[i].start =
91                     res->dma_resource[i].end = (unsigned long)dma;
92         }
93 }
94
95 static void pnpbios_parse_allocated_ioresource(struct pnp_resource_table *res,
96                                                int io, int len)
97 {
98         int i = 0;
99
100         while (!(res->port_resource[i].flags & IORESOURCE_UNSET)
101                && i < PNP_MAX_PORT)
102                 i++;
103         if (i < PNP_MAX_PORT) {
104                 res->port_resource[i].flags = IORESOURCE_IO;    // Also clears _UNSET flag
105                 if (len <= 0 || (io + len - 1) >= 0x10003) {
106                         res->port_resource[i].flags |= IORESOURCE_DISABLED;
107                         return;
108                 }
109                 res->port_resource[i].start = (unsigned long)io;
110                 res->port_resource[i].end = (unsigned long)(io + len - 1);
111         }
112 }
113
114 static void pnpbios_parse_allocated_memresource(struct pnp_resource_table *res,
115                                                 int mem, int len)
116 {
117         int i = 0;
118
119         while (!(res->mem_resource[i].flags & IORESOURCE_UNSET)
120                && i < PNP_MAX_MEM)
121                 i++;
122         if (i < PNP_MAX_MEM) {
123                 res->mem_resource[i].flags = IORESOURCE_MEM;    // Also clears _UNSET flag
124                 if (len <= 0) {
125                         res->mem_resource[i].flags |= IORESOURCE_DISABLED;
126                         return;
127                 }
128                 res->mem_resource[i].start = (unsigned long)mem;
129                 res->mem_resource[i].end = (unsigned long)(mem + len - 1);
130         }
131 }
132
133 static unsigned char *pnpbios_parse_allocated_resource_data(unsigned char *p,
134                                                             unsigned char *end,
135                                                             struct
136                                                             pnp_resource_table
137                                                             *res)
138 {
139         unsigned int len, tag;
140         int io, size, mask, i;
141
142         if (!p)
143                 return NULL;
144
145         /* Blank the resource table values */
146         pnp_init_resource_table(res);
147
148         while ((char *)p < (char *)end) {
149
150                 /* determine the type of tag */
151                 if (p[0] & LARGE_TAG) { /* large tag */
152                         len = (p[2] << 8) | p[1];
153                         tag = p[0];
154                 } else {        /* small tag */
155                         len = p[0] & 0x07;
156                         tag = ((p[0] >> 3) & 0x0f);
157                 }
158
159                 switch (tag) {
160
161                 case LARGE_TAG_MEM:
162                         if (len != 9)
163                                 goto len_err;
164                         io = *(short *)&p[4];
165                         size = *(short *)&p[10];
166                         pnpbios_parse_allocated_memresource(res, io, size);
167                         break;
168
169                 case LARGE_TAG_ANSISTR:
170                         /* ignore this for now */
171                         break;
172
173                 case LARGE_TAG_VENDOR:
174                         /* do nothing */
175                         break;
176
177                 case LARGE_TAG_MEM32:
178                         if (len != 17)
179                                 goto len_err;
180                         io = *(int *)&p[4];
181                         size = *(int *)&p[16];
182                         pnpbios_parse_allocated_memresource(res, io, size);
183                         break;
184
185                 case LARGE_TAG_FIXEDMEM32:
186                         if (len != 9)
187                                 goto len_err;
188                         io = *(int *)&p[4];
189                         size = *(int *)&p[8];
190                         pnpbios_parse_allocated_memresource(res, io, size);
191                         break;
192
193                 case SMALL_TAG_IRQ:
194                         if (len < 2 || len > 3)
195                                 goto len_err;
196                         io = -1;
197                         mask = p[1] + p[2] * 256;
198                         for (i = 0; i < 16; i++, mask = mask >> 1)
199                                 if (mask & 0x01)
200                                         io = i;
201                         pnpbios_parse_allocated_irqresource(res, io);
202                         break;
203
204                 case SMALL_TAG_DMA:
205                         if (len != 2)
206                                 goto len_err;
207                         io = -1;
208                         mask = p[1];
209                         for (i = 0; i < 8; i++, mask = mask >> 1)
210                                 if (mask & 0x01)
211                                         io = i;
212                         pnpbios_parse_allocated_dmaresource(res, io);
213                         break;
214
215                 case SMALL_TAG_PORT:
216                         if (len != 7)
217                                 goto len_err;
218                         io = p[2] + p[3] * 256;
219                         size = p[7];
220                         pnpbios_parse_allocated_ioresource(res, io, size);
221                         break;
222
223                 case SMALL_TAG_VENDOR:
224                         /* do nothing */
225                         break;
226
227                 case SMALL_TAG_FIXEDPORT:
228                         if (len != 3)
229                                 goto len_err;
230                         io = p[1] + p[2] * 256;
231                         size = p[3];
232                         pnpbios_parse_allocated_ioresource(res, io, size);
233                         break;
234
235                 case SMALL_TAG_END:
236                         p = p + 2;
237                         return (unsigned char *)p;
238                         break;
239
240                 default:        /* an unkown tag */
241 len_err:
242                         printk(KERN_ERR
243                                "PnPBIOS: Unknown tag '0x%x', length '%d'.\n",
244                                tag, len);
245                         break;
246                 }
247
248                 /* continue to the next tag */
249                 if (p[0] & LARGE_TAG)
250                         p += len + 3;
251                 else
252                         p += len + 1;
253         }
254
255         printk(KERN_ERR
256                "PnPBIOS: Resource structure does not contain an end tag.\n");
257
258         return NULL;
259 }
260
261 /*
262  * Resource Configuration Options
263  */
264
265 static void pnpbios_parse_mem_option(unsigned char *p, int size,
266                                      struct pnp_option *option)
267 {
268         struct pnp_mem *mem;
269
270         mem = kzalloc(sizeof(struct pnp_mem), GFP_KERNEL);
271         if (!mem)
272                 return;
273         mem->min = ((p[5] << 8) | p[4]) << 8;
274         mem->max = ((p[7] << 8) | p[6]) << 8;
275         mem->align = (p[9] << 8) | p[8];
276         mem->size = ((p[11] << 8) | p[10]) << 8;
277         mem->flags = p[3];
278         pnp_register_mem_resource(option, mem);
279 }
280
281 static void pnpbios_parse_mem32_option(unsigned char *p, int size,
282                                        struct pnp_option *option)
283 {
284         struct pnp_mem *mem;
285
286         mem = kzalloc(sizeof(struct pnp_mem), GFP_KERNEL);
287         if (!mem)
288                 return;
289         mem->min = (p[7] << 24) | (p[6] << 16) | (p[5] << 8) | p[4];
290         mem->max = (p[11] << 24) | (p[10] << 16) | (p[9] << 8) | p[8];
291         mem->align = (p[15] << 24) | (p[14] << 16) | (p[13] << 8) | p[12];
292         mem->size = (p[19] << 24) | (p[18] << 16) | (p[17] << 8) | p[16];
293         mem->flags = p[3];
294         pnp_register_mem_resource(option, mem);
295 }
296
297 static void pnpbios_parse_fixed_mem32_option(unsigned char *p, int size,
298                                              struct pnp_option *option)
299 {
300         struct pnp_mem *mem;
301
302         mem = kzalloc(sizeof(struct pnp_mem), GFP_KERNEL);
303         if (!mem)
304                 return;
305         mem->min = mem->max = (p[7] << 24) | (p[6] << 16) | (p[5] << 8) | p[4];
306         mem->size = (p[11] << 24) | (p[10] << 16) | (p[9] << 8) | p[8];
307         mem->align = 0;
308         mem->flags = p[3];
309         pnp_register_mem_resource(option, mem);
310 }
311
312 static void pnpbios_parse_irq_option(unsigned char *p, int size,
313                                      struct pnp_option *option)
314 {
315         struct pnp_irq *irq;
316         unsigned long bits;
317
318         irq = kzalloc(sizeof(struct pnp_irq), GFP_KERNEL);
319         if (!irq)
320                 return;
321         bits = (p[2] << 8) | p[1];
322         bitmap_copy(irq->map, &bits, 16);
323         if (size > 2)
324                 irq->flags = p[3];
325         else
326                 irq->flags = IORESOURCE_IRQ_HIGHEDGE;
327         pnp_register_irq_resource(option, irq);
328 }
329
330 static void pnpbios_parse_dma_option(unsigned char *p, int size,
331                                      struct pnp_option *option)
332 {
333         struct pnp_dma *dma;
334
335         dma = kzalloc(sizeof(struct pnp_dma), GFP_KERNEL);
336         if (!dma)
337                 return;
338         dma->map = p[1];
339         dma->flags = p[2];
340         pnp_register_dma_resource(option, dma);
341 }
342
343 static void pnpbios_parse_port_option(unsigned char *p, int size,
344                                       struct pnp_option *option)
345 {
346         struct pnp_port *port;
347
348         port = kzalloc(sizeof(struct pnp_port), GFP_KERNEL);
349         if (!port)
350                 return;
351         port->min = (p[3] << 8) | p[2];
352         port->max = (p[5] << 8) | p[4];
353         port->align = p[6];
354         port->size = p[7];
355         port->flags = p[1] ? PNP_PORT_FLAG_16BITADDR : 0;
356         pnp_register_port_resource(option, port);
357 }
358
359 static void pnpbios_parse_fixed_port_option(unsigned char *p, int size,
360                                             struct pnp_option *option)
361 {
362         struct pnp_port *port;
363
364         port = kzalloc(sizeof(struct pnp_port), GFP_KERNEL);
365         if (!port)
366                 return;
367         port->min = port->max = (p[2] << 8) | p[1];
368         port->size = p[3];
369         port->align = 0;
370         port->flags = PNP_PORT_FLAG_FIXED;
371         pnp_register_port_resource(option, port);
372 }
373
374 static unsigned char *pnpbios_parse_resource_option_data(unsigned char *p,
375                                                          unsigned char *end,
376                                                          struct pnp_dev *dev)
377 {
378         unsigned int len, tag;
379         int priority = 0;
380         struct pnp_option *option, *option_independent;
381
382         if (!p)
383                 return NULL;
384
385         option_independent = option = pnp_register_independent_option(dev);
386         if (!option)
387                 return NULL;
388
389         while ((char *)p < (char *)end) {
390
391                 /* determine the type of tag */
392                 if (p[0] & LARGE_TAG) { /* large tag */
393                         len = (p[2] << 8) | p[1];
394                         tag = p[0];
395                 } else {        /* small tag */
396                         len = p[0] & 0x07;
397                         tag = ((p[0] >> 3) & 0x0f);
398                 }
399
400                 switch (tag) {
401
402                 case LARGE_TAG_MEM:
403                         if (len != 9)
404                                 goto len_err;
405                         pnpbios_parse_mem_option(p, len, option);
406                         break;
407
408                 case LARGE_TAG_MEM32:
409                         if (len != 17)
410                                 goto len_err;
411                         pnpbios_parse_mem32_option(p, len, option);
412                         break;
413
414                 case LARGE_TAG_FIXEDMEM32:
415                         if (len != 9)
416                                 goto len_err;
417                         pnpbios_parse_fixed_mem32_option(p, len, option);
418                         break;
419
420                 case SMALL_TAG_IRQ:
421                         if (len < 2 || len > 3)
422                                 goto len_err;
423                         pnpbios_parse_irq_option(p, len, option);
424                         break;
425
426                 case SMALL_TAG_DMA:
427                         if (len != 2)
428                                 goto len_err;
429                         pnpbios_parse_dma_option(p, len, option);
430                         break;
431
432                 case SMALL_TAG_PORT:
433                         if (len != 7)
434                                 goto len_err;
435                         pnpbios_parse_port_option(p, len, option);
436                         break;
437
438                 case SMALL_TAG_VENDOR:
439                         /* do nothing */
440                         break;
441
442                 case SMALL_TAG_FIXEDPORT:
443                         if (len != 3)
444                                 goto len_err;
445                         pnpbios_parse_fixed_port_option(p, len, option);
446                         break;
447
448                 case SMALL_TAG_STARTDEP:
449                         if (len > 1)
450                                 goto len_err;
451                         priority = 0x100 | PNP_RES_PRIORITY_ACCEPTABLE;
452                         if (len > 0)
453                                 priority = 0x100 | p[1];
454                         option = pnp_register_dependent_option(dev, priority);
455                         if (!option)
456                                 return NULL;
457                         break;
458
459                 case SMALL_TAG_ENDDEP:
460                         if (len != 0)
461                                 goto len_err;
462                         if (option_independent == option)
463                                 printk(KERN_WARNING
464                                        "PnPBIOS: Missing SMALL_TAG_STARTDEP tag\n");
465                         option = option_independent;
466                         break;
467
468                 case SMALL_TAG_END:
469                         return p + 2;
470
471                 default:        /* an unkown tag */
472 len_err:
473                         printk(KERN_ERR
474                                "PnPBIOS: Unknown tag '0x%x', length '%d'.\n",
475                                tag, len);
476                         break;
477                 }
478
479                 /* continue to the next tag */
480                 if (p[0] & LARGE_TAG)
481                         p += len + 3;
482                 else
483                         p += len + 1;
484         }
485
486         printk(KERN_ERR
487                "PnPBIOS: Resource structure does not contain an end tag.\n");
488
489         return NULL;
490 }
491
492 /*
493  * Compatible Device IDs
494  */
495
496 #define HEX(id,a) hex[((id)>>a) & 15]
497 #define CHAR(id,a) (0x40 + (((id)>>a) & 31))
498
499 void pnpid32_to_pnpid(u32 id, char *str)
500 {
501         const char *hex = "0123456789abcdef";
502
503         id = be32_to_cpu(id);
504         str[0] = CHAR(id, 26);
505         str[1] = CHAR(id, 21);
506         str[2] = CHAR(id, 16);
507         str[3] = HEX(id, 12);
508         str[4] = HEX(id, 8);
509         str[5] = HEX(id, 4);
510         str[6] = HEX(id, 0);
511         str[7] = '\0';
512 }
513
514 #undef CHAR
515 #undef HEX
516
517 static unsigned char *pnpbios_parse_compatible_ids(unsigned char *p,
518                                                    unsigned char *end,
519                                                    struct pnp_dev *dev)
520 {
521         int len, tag;
522         char id[8];
523         struct pnp_id *dev_id;
524
525         if (!p)
526                 return NULL;
527
528         while ((char *)p < (char *)end) {
529
530                 /* determine the type of tag */
531                 if (p[0] & LARGE_TAG) { /* large tag */
532                         len = (p[2] << 8) | p[1];
533                         tag = p[0];
534                 } else {        /* small tag */
535                         len = p[0] & 0x07;
536                         tag = ((p[0] >> 3) & 0x0f);
537                 }
538
539                 switch (tag) {
540
541                 case LARGE_TAG_ANSISTR:
542                         strncpy(dev->name, p + 3,
543                                 len >= PNP_NAME_LEN ? PNP_NAME_LEN - 2 : len);
544                         dev->name[len >=
545                                   PNP_NAME_LEN ? PNP_NAME_LEN - 1 : len] = '\0';
546                         break;
547
548                 case SMALL_TAG_COMPATDEVID:     /* compatible ID */
549                         if (len != 4)
550                                 goto len_err;
551                         dev_id = kzalloc(sizeof(struct pnp_id), GFP_KERNEL);
552                         if (!dev_id)
553                                 return NULL;
554                         pnpid32_to_pnpid(p[1] | p[2] << 8 | p[3] << 16 | p[4] <<
555                                          24, id);
556                         memcpy(&dev_id->id, id, 7);
557                         pnp_add_id(dev_id, dev);
558                         break;
559
560                 case SMALL_TAG_END:
561                         p = p + 2;
562                         return (unsigned char *)p;
563                         break;
564
565                 default:        /* an unkown tag */
566 len_err:
567                         printk(KERN_ERR
568                                "PnPBIOS: Unknown tag '0x%x', length '%d'.\n",
569                                tag, len);
570                         break;
571                 }
572
573                 /* continue to the next tag */
574                 if (p[0] & LARGE_TAG)
575                         p += len + 3;
576                 else
577                         p += len + 1;
578         }
579
580         printk(KERN_ERR
581                "PnPBIOS: Resource structure does not contain an end tag.\n");
582
583         return NULL;
584 }
585
586 /*
587  * Allocated Resource Encoding
588  */
589
590 static void pnpbios_encode_mem(unsigned char *p, struct resource *res)
591 {
592         unsigned long base = res->start;
593         unsigned long len = res->end - res->start + 1;
594
595         p[4] = (base >> 8) & 0xff;
596         p[5] = ((base >> 8) >> 8) & 0xff;
597         p[6] = (base >> 8) & 0xff;
598         p[7] = ((base >> 8) >> 8) & 0xff;
599         p[10] = (len >> 8) & 0xff;
600         p[11] = ((len >> 8) >> 8) & 0xff;
601 }
602
603 static void pnpbios_encode_mem32(unsigned char *p, struct resource *res)
604 {
605         unsigned long base = res->start;
606         unsigned long len = res->end - res->start + 1;
607
608         p[4] = base & 0xff;
609         p[5] = (base >> 8) & 0xff;
610         p[6] = (base >> 16) & 0xff;
611         p[7] = (base >> 24) & 0xff;
612         p[8] = base & 0xff;
613         p[9] = (base >> 8) & 0xff;
614         p[10] = (base >> 16) & 0xff;
615         p[11] = (base >> 24) & 0xff;
616         p[16] = len & 0xff;
617         p[17] = (len >> 8) & 0xff;
618         p[18] = (len >> 16) & 0xff;
619         p[19] = (len >> 24) & 0xff;
620 }
621
622 static void pnpbios_encode_fixed_mem32(unsigned char *p, struct resource *res)
623 {
624         unsigned long base = res->start;
625         unsigned long len = res->end - res->start + 1;
626
627         p[4] = base & 0xff;
628         p[5] = (base >> 8) & 0xff;
629         p[6] = (base >> 16) & 0xff;
630         p[7] = (base >> 24) & 0xff;
631         p[8] = len & 0xff;
632         p[9] = (len >> 8) & 0xff;
633         p[10] = (len >> 16) & 0xff;
634         p[11] = (len >> 24) & 0xff;
635 }
636
637 static void pnpbios_encode_irq(unsigned char *p, struct resource *res)
638 {
639         unsigned long map = 0;
640
641         map = 1 << res->start;
642         p[1] = map & 0xff;
643         p[2] = (map >> 8) & 0xff;
644 }
645
646 static void pnpbios_encode_dma(unsigned char *p, struct resource *res)
647 {
648         unsigned long map = 0;
649
650         map = 1 << res->start;
651         p[1] = map & 0xff;
652 }
653
654 static void pnpbios_encode_port(unsigned char *p, struct resource *res)
655 {
656         unsigned long base = res->start;
657         unsigned long len = res->end - res->start + 1;
658
659         p[2] = base & 0xff;
660         p[3] = (base >> 8) & 0xff;
661         p[4] = base & 0xff;
662         p[5] = (base >> 8) & 0xff;
663         p[7] = len & 0xff;
664 }
665
666 static void pnpbios_encode_fixed_port(unsigned char *p, struct resource *res)
667 {
668         unsigned long base = res->start;
669         unsigned long len = res->end - res->start + 1;
670
671         p[1] = base & 0xff;
672         p[2] = (base >> 8) & 0xff;
673         p[3] = len & 0xff;
674 }
675
676 static unsigned char *pnpbios_encode_allocated_resource_data(unsigned char *p,
677                                                              unsigned char *end,
678                                                              struct
679                                                              pnp_resource_table
680                                                              *res)
681 {
682         unsigned int len, tag;
683         int port = 0, irq = 0, dma = 0, mem = 0;
684
685         if (!p)
686                 return NULL;
687
688         while ((char *)p < (char *)end) {
689
690                 /* determine the type of tag */
691                 if (p[0] & LARGE_TAG) { /* large tag */
692                         len = (p[2] << 8) | p[1];
693                         tag = p[0];
694                 } else {        /* small tag */
695                         len = p[0] & 0x07;
696                         tag = ((p[0] >> 3) & 0x0f);
697                 }
698
699                 switch (tag) {
700
701                 case LARGE_TAG_MEM:
702                         if (len != 9)
703                                 goto len_err;
704                         pnpbios_encode_mem(p, &res->mem_resource[mem]);
705                         mem++;
706                         break;
707
708                 case LARGE_TAG_MEM32:
709                         if (len != 17)
710                                 goto len_err;
711                         pnpbios_encode_mem32(p, &res->mem_resource[mem]);
712                         mem++;
713                         break;
714
715                 case LARGE_TAG_FIXEDMEM32:
716                         if (len != 9)
717                                 goto len_err;
718                         pnpbios_encode_fixed_mem32(p, &res->mem_resource[mem]);
719                         mem++;
720                         break;
721
722                 case SMALL_TAG_IRQ:
723                         if (len < 2 || len > 3)
724                                 goto len_err;
725                         pnpbios_encode_irq(p, &res->irq_resource[irq]);
726                         irq++;
727                         break;
728
729                 case SMALL_TAG_DMA:
730                         if (len != 2)
731                                 goto len_err;
732                         pnpbios_encode_dma(p, &res->dma_resource[dma]);
733                         dma++;
734                         break;
735
736                 case SMALL_TAG_PORT:
737                         if (len != 7)
738                                 goto len_err;
739                         pnpbios_encode_port(p, &res->port_resource[port]);
740                         port++;
741                         break;
742
743                 case SMALL_TAG_VENDOR:
744                         /* do nothing */
745                         break;
746
747                 case SMALL_TAG_FIXEDPORT:
748                         if (len != 3)
749                                 goto len_err;
750                         pnpbios_encode_fixed_port(p, &res->port_resource[port]);
751                         port++;
752                         break;
753
754                 case SMALL_TAG_END:
755                         p = p + 2;
756                         return (unsigned char *)p;
757                         break;
758
759                 default:        /* an unkown tag */
760 len_err:
761                         printk(KERN_ERR
762                                "PnPBIOS: Unknown tag '0x%x', length '%d'.\n",
763                                tag, len);
764                         break;
765                 }
766
767                 /* continue to the next tag */
768                 if (p[0] & LARGE_TAG)
769                         p += len + 3;
770                 else
771                         p += len + 1;
772         }
773
774         printk(KERN_ERR
775                "PnPBIOS: Resource structure does not contain an end tag.\n");
776
777         return NULL;
778 }
779
780 /*
781  * Core Parsing Functions
782  */
783
784 int pnpbios_parse_data_stream(struct pnp_dev *dev, struct pnp_bios_node *node)
785 {
786         unsigned char *p = (char *)node->data;
787         unsigned char *end = (char *)(node->data + node->size);
788
789         p = pnpbios_parse_allocated_resource_data(p, end, &dev->res);
790         if (!p)
791                 return -EIO;
792         p = pnpbios_parse_resource_option_data(p, end, dev);
793         if (!p)
794                 return -EIO;
795         p = pnpbios_parse_compatible_ids(p, end, dev);
796         if (!p)
797                 return -EIO;
798         return 0;
799 }
800
801 int pnpbios_read_resources_from_node(struct pnp_resource_table *res,
802                                      struct pnp_bios_node *node)
803 {
804         unsigned char *p = (char *)node->data;
805         unsigned char *end = (char *)(node->data + node->size);
806
807         p = pnpbios_parse_allocated_resource_data(p, end, res);
808         if (!p)
809                 return -EIO;
810         return 0;
811 }
812
813 int pnpbios_write_resources_to_node(struct pnp_resource_table *res,
814                                     struct pnp_bios_node *node)
815 {
816         unsigned char *p = (char *)node->data;
817         unsigned char *end = (char *)(node->data + node->size);
818
819         p = pnpbios_encode_allocated_resource_data(p, end, res);
820         if (!p)
821                 return -EIO;
822         return 0;
823 }