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