Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /*
0003  * rsparser.c - parses and encodes pnpbios resource data streams
0004  */
0005 
0006 #include <linux/ctype.h>
0007 #include <linux/pnp.h>
0008 #include <linux/string.h>
0009 
0010 #ifdef CONFIG_PCI
0011 #include <linux/pci.h>
0012 #else
0013 inline void pcibios_penalize_isa_irq(int irq, int active)
0014 {
0015 }
0016 #endif              /* CONFIG_PCI */
0017 
0018 #include "../base.h"
0019 #include "pnpbios.h"
0020 
0021 /* standard resource tags */
0022 #define SMALL_TAG_PNPVERNO      0x01
0023 #define SMALL_TAG_LOGDEVID      0x02
0024 #define SMALL_TAG_COMPATDEVID       0x03
0025 #define SMALL_TAG_IRQ           0x04
0026 #define SMALL_TAG_DMA           0x05
0027 #define SMALL_TAG_STARTDEP      0x06
0028 #define SMALL_TAG_ENDDEP        0x07
0029 #define SMALL_TAG_PORT          0x08
0030 #define SMALL_TAG_FIXEDPORT     0x09
0031 #define SMALL_TAG_VENDOR        0x0e
0032 #define SMALL_TAG_END           0x0f
0033 #define LARGE_TAG           0x80
0034 #define LARGE_TAG_MEM           0x81
0035 #define LARGE_TAG_ANSISTR       0x82
0036 #define LARGE_TAG_UNICODESTR        0x83
0037 #define LARGE_TAG_VENDOR        0x84
0038 #define LARGE_TAG_MEM32         0x85
0039 #define LARGE_TAG_FIXEDMEM32        0x86
0040 
0041 /*
0042  * Resource Data Stream Format:
0043  *
0044  * Allocated Resources (required)
0045  * end tag ->
0046  * Resource Configuration Options (optional)
0047  * end tag ->
0048  * Compitable Device IDs (optional)
0049  * final end tag ->
0050  */
0051 
0052 /*
0053  * Allocated Resources
0054  */
0055 
0056 static void pnpbios_parse_allocated_ioresource(struct pnp_dev *dev,
0057                            int start, int len)
0058 {
0059     int flags = 0;
0060     int end = start + len - 1;
0061 
0062     if (len <= 0 || end >= 0x10003)
0063         flags |= IORESOURCE_DISABLED;
0064 
0065     pnp_add_io_resource(dev, start, end, flags);
0066 }
0067 
0068 static void pnpbios_parse_allocated_memresource(struct pnp_dev *dev,
0069                         int start, int len)
0070 {
0071     int flags = 0;
0072     int end = start + len - 1;
0073 
0074     if (len <= 0)
0075         flags |= IORESOURCE_DISABLED;
0076 
0077     pnp_add_mem_resource(dev, start, end, flags);
0078 }
0079 
0080 static unsigned char *pnpbios_parse_allocated_resource_data(struct pnp_dev *dev,
0081                                 unsigned char *p,
0082                                 unsigned char *end)
0083 {
0084     unsigned int len, tag;
0085     int io, size, mask, i, flags;
0086 
0087     if (!p)
0088         return NULL;
0089 
0090     pnp_dbg(&dev->dev, "parse allocated resources\n");
0091 
0092     pnp_init_resources(dev);
0093 
0094     while ((char *)p < (char *)end) {
0095 
0096         /* determine the type of tag */
0097         if (p[0] & LARGE_TAG) { /* large tag */
0098             len = (p[2] << 8) | p[1];
0099             tag = p[0];
0100         } else {    /* small tag */
0101             len = p[0] & 0x07;
0102             tag = ((p[0] >> 3) & 0x0f);
0103         }
0104 
0105         switch (tag) {
0106 
0107         case LARGE_TAG_MEM:
0108             if (len != 9)
0109                 goto len_err;
0110             io = *(short *)&p[4];
0111             size = *(short *)&p[10];
0112             pnpbios_parse_allocated_memresource(dev, io, size);
0113             break;
0114 
0115         case LARGE_TAG_ANSISTR:
0116             /* ignore this for now */
0117             break;
0118 
0119         case LARGE_TAG_VENDOR:
0120             /* do nothing */
0121             break;
0122 
0123         case LARGE_TAG_MEM32:
0124             if (len != 17)
0125                 goto len_err;
0126             io = *(int *)&p[4];
0127             size = *(int *)&p[16];
0128             pnpbios_parse_allocated_memresource(dev, io, size);
0129             break;
0130 
0131         case LARGE_TAG_FIXEDMEM32:
0132             if (len != 9)
0133                 goto len_err;
0134             io = *(int *)&p[4];
0135             size = *(int *)&p[8];
0136             pnpbios_parse_allocated_memresource(dev, io, size);
0137             break;
0138 
0139         case SMALL_TAG_IRQ:
0140             if (len < 2 || len > 3)
0141                 goto len_err;
0142             flags = 0;
0143             io = -1;
0144             mask = p[1] + p[2] * 256;
0145             for (i = 0; i < 16; i++, mask = mask >> 1)
0146                 if (mask & 0x01)
0147                     io = i;
0148             if (io != -1)
0149                 pcibios_penalize_isa_irq(io, 1);
0150             else
0151                 flags = IORESOURCE_DISABLED;
0152             pnp_add_irq_resource(dev, io, flags);
0153             break;
0154 
0155         case SMALL_TAG_DMA:
0156             if (len != 2)
0157                 goto len_err;
0158             flags = 0;
0159             io = -1;
0160             mask = p[1];
0161             for (i = 0; i < 8; i++, mask = mask >> 1)
0162                 if (mask & 0x01)
0163                     io = i;
0164             if (io == -1)
0165                 flags = IORESOURCE_DISABLED;
0166             pnp_add_dma_resource(dev, io, flags);
0167             break;
0168 
0169         case SMALL_TAG_PORT:
0170             if (len != 7)
0171                 goto len_err;
0172             io = p[2] + p[3] * 256;
0173             size = p[7];
0174             pnpbios_parse_allocated_ioresource(dev, io, size);
0175             break;
0176 
0177         case SMALL_TAG_VENDOR:
0178             /* do nothing */
0179             break;
0180 
0181         case SMALL_TAG_FIXEDPORT:
0182             if (len != 3)
0183                 goto len_err;
0184             io = p[1] + p[2] * 256;
0185             size = p[3];
0186             pnpbios_parse_allocated_ioresource(dev, io, size);
0187             break;
0188 
0189         case SMALL_TAG_END:
0190             p = p + 2;
0191             return (unsigned char *)p;
0192             break;
0193 
0194         default:    /* an unknown tag */
0195 len_err:
0196             dev_err(&dev->dev, "unknown tag %#x length %d\n",
0197                 tag, len);
0198             break;
0199         }
0200 
0201         /* continue to the next tag */
0202         if (p[0] & LARGE_TAG)
0203             p += len + 3;
0204         else
0205             p += len + 1;
0206     }
0207 
0208     dev_err(&dev->dev, "no end tag in resource structure\n");
0209 
0210     return NULL;
0211 }
0212 
0213 /*
0214  * Resource Configuration Options
0215  */
0216 
0217 static __init void pnpbios_parse_mem_option(struct pnp_dev *dev,
0218                         unsigned char *p, int size,
0219                         unsigned int option_flags)
0220 {
0221     resource_size_t min, max, align, len;
0222     unsigned char flags;
0223 
0224     min = ((p[5] << 8) | p[4]) << 8;
0225     max = ((p[7] << 8) | p[6]) << 8;
0226     align = (p[9] << 8) | p[8];
0227     len = ((p[11] << 8) | p[10]) << 8;
0228     flags = p[3];
0229     pnp_register_mem_resource(dev, option_flags, min, max, align, len,
0230                   flags);
0231 }
0232 
0233 static __init void pnpbios_parse_mem32_option(struct pnp_dev *dev,
0234                           unsigned char *p, int size,
0235                           unsigned int option_flags)
0236 {
0237     resource_size_t min, max, align, len;
0238     unsigned char flags;
0239 
0240     min = (p[7] << 24) | (p[6] << 16) | (p[5] << 8) | p[4];
0241     max = (p[11] << 24) | (p[10] << 16) | (p[9] << 8) | p[8];
0242     align = (p[15] << 24) | (p[14] << 16) | (p[13] << 8) | p[12];
0243     len = (p[19] << 24) | (p[18] << 16) | (p[17] << 8) | p[16];
0244     flags = p[3];
0245     pnp_register_mem_resource(dev, option_flags, min, max, align, len,
0246                   flags);
0247 }
0248 
0249 static __init void pnpbios_parse_fixed_mem32_option(struct pnp_dev *dev,
0250                             unsigned char *p, int size,
0251                             unsigned int option_flags)
0252 {
0253     resource_size_t base, len;
0254     unsigned char flags;
0255 
0256     base = (p[7] << 24) | (p[6] << 16) | (p[5] << 8) | p[4];
0257     len = (p[11] << 24) | (p[10] << 16) | (p[9] << 8) | p[8];
0258     flags = p[3];
0259     pnp_register_mem_resource(dev, option_flags, base, base, 0, len, flags);
0260 }
0261 
0262 static __init void pnpbios_parse_irq_option(struct pnp_dev *dev,
0263                         unsigned char *p, int size,
0264                         unsigned int option_flags)
0265 {
0266     unsigned long bits;
0267     pnp_irq_mask_t map;
0268     unsigned char flags = IORESOURCE_IRQ_HIGHEDGE;
0269 
0270     bits = (p[2] << 8) | p[1];
0271 
0272     bitmap_zero(map.bits, PNP_IRQ_NR);
0273     bitmap_copy(map.bits, &bits, 16);
0274 
0275     if (size > 2)
0276         flags = p[3];
0277 
0278     pnp_register_irq_resource(dev, option_flags, &map, flags);
0279 }
0280 
0281 static __init void pnpbios_parse_dma_option(struct pnp_dev *dev,
0282                         unsigned char *p, int size,
0283                         unsigned int option_flags)
0284 {
0285     pnp_register_dma_resource(dev, option_flags, p[1], p[2]);
0286 }
0287 
0288 static __init void pnpbios_parse_port_option(struct pnp_dev *dev,
0289                          unsigned char *p, int size,
0290                          unsigned int option_flags)
0291 {
0292     resource_size_t min, max, align, len;
0293     unsigned char flags;
0294 
0295     min = (p[3] << 8) | p[2];
0296     max = (p[5] << 8) | p[4];
0297     align = p[6];
0298     len = p[7];
0299     flags = p[1] ? IORESOURCE_IO_16BIT_ADDR : 0;
0300     pnp_register_port_resource(dev, option_flags, min, max, align, len,
0301                    flags);
0302 }
0303 
0304 static __init void pnpbios_parse_fixed_port_option(struct pnp_dev *dev,
0305                            unsigned char *p, int size,
0306                            unsigned int option_flags)
0307 {
0308     resource_size_t base, len;
0309 
0310     base = (p[2] << 8) | p[1];
0311     len = p[3];
0312     pnp_register_port_resource(dev, option_flags, base, base, 0, len,
0313                    IORESOURCE_IO_FIXED);
0314 }
0315 
0316 static __init unsigned char *
0317 pnpbios_parse_resource_option_data(unsigned char *p, unsigned char *end,
0318                    struct pnp_dev *dev)
0319 {
0320     unsigned int len, tag;
0321     int priority;
0322     unsigned int option_flags;
0323 
0324     if (!p)
0325         return NULL;
0326 
0327     pnp_dbg(&dev->dev, "parse resource options\n");
0328     option_flags = 0;
0329     while ((char *)p < (char *)end) {
0330 
0331         /* determine the type of tag */
0332         if (p[0] & LARGE_TAG) { /* large tag */
0333             len = (p[2] << 8) | p[1];
0334             tag = p[0];
0335         } else {    /* small tag */
0336             len = p[0] & 0x07;
0337             tag = ((p[0] >> 3) & 0x0f);
0338         }
0339 
0340         switch (tag) {
0341 
0342         case LARGE_TAG_MEM:
0343             if (len != 9)
0344                 goto len_err;
0345             pnpbios_parse_mem_option(dev, p, len, option_flags);
0346             break;
0347 
0348         case LARGE_TAG_MEM32:
0349             if (len != 17)
0350                 goto len_err;
0351             pnpbios_parse_mem32_option(dev, p, len, option_flags);
0352             break;
0353 
0354         case LARGE_TAG_FIXEDMEM32:
0355             if (len != 9)
0356                 goto len_err;
0357             pnpbios_parse_fixed_mem32_option(dev, p, len,
0358                              option_flags);
0359             break;
0360 
0361         case SMALL_TAG_IRQ:
0362             if (len < 2 || len > 3)
0363                 goto len_err;
0364             pnpbios_parse_irq_option(dev, p, len, option_flags);
0365             break;
0366 
0367         case SMALL_TAG_DMA:
0368             if (len != 2)
0369                 goto len_err;
0370             pnpbios_parse_dma_option(dev, p, len, option_flags);
0371             break;
0372 
0373         case SMALL_TAG_PORT:
0374             if (len != 7)
0375                 goto len_err;
0376             pnpbios_parse_port_option(dev, p, len, option_flags);
0377             break;
0378 
0379         case SMALL_TAG_VENDOR:
0380             /* do nothing */
0381             break;
0382 
0383         case SMALL_TAG_FIXEDPORT:
0384             if (len != 3)
0385                 goto len_err;
0386             pnpbios_parse_fixed_port_option(dev, p, len,
0387                             option_flags);
0388             break;
0389 
0390         case SMALL_TAG_STARTDEP:
0391             if (len > 1)
0392                 goto len_err;
0393             priority = PNP_RES_PRIORITY_ACCEPTABLE;
0394             if (len > 0)
0395                 priority = p[1];
0396             option_flags = pnp_new_dependent_set(dev, priority);
0397             break;
0398 
0399         case SMALL_TAG_ENDDEP:
0400             if (len != 0)
0401                 goto len_err;
0402             option_flags = 0;
0403             break;
0404 
0405         case SMALL_TAG_END:
0406             return p + 2;
0407 
0408         default:    /* an unknown tag */
0409 len_err:
0410             dev_err(&dev->dev, "unknown tag %#x length %d\n",
0411                 tag, len);
0412             break;
0413         }
0414 
0415         /* continue to the next tag */
0416         if (p[0] & LARGE_TAG)
0417             p += len + 3;
0418         else
0419             p += len + 1;
0420     }
0421 
0422     dev_err(&dev->dev, "no end tag in resource structure\n");
0423 
0424     return NULL;
0425 }
0426 
0427 /*
0428  * Compatible Device IDs
0429  */
0430 
0431 static unsigned char *pnpbios_parse_compatible_ids(unsigned char *p,
0432                            unsigned char *end,
0433                            struct pnp_dev *dev)
0434 {
0435     int len, tag;
0436     u32 eisa_id;
0437     char id[8];
0438     struct pnp_id *dev_id;
0439 
0440     if (!p)
0441         return NULL;
0442 
0443     while ((char *)p < (char *)end) {
0444 
0445         /* determine the type of tag */
0446         if (p[0] & LARGE_TAG) { /* large tag */
0447             len = (p[2] << 8) | p[1];
0448             tag = p[0];
0449         } else {    /* small tag */
0450             len = p[0] & 0x07;
0451             tag = ((p[0] >> 3) & 0x0f);
0452         }
0453 
0454         switch (tag) {
0455 
0456         case LARGE_TAG_ANSISTR:
0457             strncpy(dev->name, p + 3,
0458                 len >= PNP_NAME_LEN ? PNP_NAME_LEN - 2 : len);
0459             dev->name[len >=
0460                   PNP_NAME_LEN ? PNP_NAME_LEN - 1 : len] = '\0';
0461             break;
0462 
0463         case SMALL_TAG_COMPATDEVID: /* compatible ID */
0464             if (len != 4)
0465                 goto len_err;
0466             eisa_id = p[1] | p[2] << 8 | p[3] << 16 | p[4] << 24;
0467             pnp_eisa_id_to_string(eisa_id & PNP_EISA_ID_MASK, id);
0468             dev_id = pnp_add_id(dev, id);
0469             if (!dev_id)
0470                 return NULL;
0471             break;
0472 
0473         case SMALL_TAG_END:
0474             p = p + 2;
0475             return (unsigned char *)p;
0476             break;
0477 
0478         default:    /* an unknown tag */
0479 len_err:
0480             dev_err(&dev->dev, "unknown tag %#x length %d\n",
0481                 tag, len);
0482             break;
0483         }
0484 
0485         /* continue to the next tag */
0486         if (p[0] & LARGE_TAG)
0487             p += len + 3;
0488         else
0489             p += len + 1;
0490     }
0491 
0492     dev_err(&dev->dev, "no end tag in resource structure\n");
0493 
0494     return NULL;
0495 }
0496 
0497 /*
0498  * Allocated Resource Encoding
0499  */
0500 
0501 static void pnpbios_encode_mem(struct pnp_dev *dev, unsigned char *p,
0502                    struct resource *res)
0503 {
0504     unsigned long base;
0505     unsigned long len;
0506 
0507     if (pnp_resource_enabled(res)) {
0508         base = res->start;
0509         len = resource_size(res);
0510     } else {
0511         base = 0;
0512         len = 0;
0513     }
0514 
0515     p[4] = (base >> 8) & 0xff;
0516     p[5] = ((base >> 8) >> 8) & 0xff;
0517     p[6] = (base >> 8) & 0xff;
0518     p[7] = ((base >> 8) >> 8) & 0xff;
0519     p[10] = (len >> 8) & 0xff;
0520     p[11] = ((len >> 8) >> 8) & 0xff;
0521 
0522     pnp_dbg(&dev->dev, "  encode mem %#lx-%#lx\n", base, base + len - 1);
0523 }
0524 
0525 static void pnpbios_encode_mem32(struct pnp_dev *dev, unsigned char *p,
0526                  struct resource *res)
0527 {
0528     unsigned long base;
0529     unsigned long len;
0530 
0531     if (pnp_resource_enabled(res)) {
0532         base = res->start;
0533         len = resource_size(res);
0534     } else {
0535         base = 0;
0536         len = 0;
0537     }
0538 
0539     p[4] = base & 0xff;
0540     p[5] = (base >> 8) & 0xff;
0541     p[6] = (base >> 16) & 0xff;
0542     p[7] = (base >> 24) & 0xff;
0543     p[8] = base & 0xff;
0544     p[9] = (base >> 8) & 0xff;
0545     p[10] = (base >> 16) & 0xff;
0546     p[11] = (base >> 24) & 0xff;
0547     p[16] = len & 0xff;
0548     p[17] = (len >> 8) & 0xff;
0549     p[18] = (len >> 16) & 0xff;
0550     p[19] = (len >> 24) & 0xff;
0551 
0552     pnp_dbg(&dev->dev, "  encode mem32 %#lx-%#lx\n", base, base + len - 1);
0553 }
0554 
0555 static void pnpbios_encode_fixed_mem32(struct pnp_dev *dev, unsigned char *p,
0556                        struct resource *res)
0557 {
0558     unsigned long base;
0559     unsigned long len;
0560 
0561     if (pnp_resource_enabled(res)) {
0562         base = res->start;
0563         len = resource_size(res);
0564     } else {
0565         base = 0;
0566         len = 0;
0567     }
0568 
0569     p[4] = base & 0xff;
0570     p[5] = (base >> 8) & 0xff;
0571     p[6] = (base >> 16) & 0xff;
0572     p[7] = (base >> 24) & 0xff;
0573     p[8] = len & 0xff;
0574     p[9] = (len >> 8) & 0xff;
0575     p[10] = (len >> 16) & 0xff;
0576     p[11] = (len >> 24) & 0xff;
0577 
0578     pnp_dbg(&dev->dev, "  encode fixed_mem32 %#lx-%#lx\n", base,
0579         base + len - 1);
0580 }
0581 
0582 static void pnpbios_encode_irq(struct pnp_dev *dev, unsigned char *p,
0583                    struct resource *res)
0584 {
0585     unsigned long map;
0586 
0587     if (pnp_resource_enabled(res))
0588         map = 1 << res->start;
0589     else
0590         map = 0;
0591 
0592     p[1] = map & 0xff;
0593     p[2] = (map >> 8) & 0xff;
0594 
0595     pnp_dbg(&dev->dev, "  encode irq mask %#lx\n", map);
0596 }
0597 
0598 static void pnpbios_encode_dma(struct pnp_dev *dev, unsigned char *p,
0599                    struct resource *res)
0600 {
0601     unsigned long map;
0602 
0603     if (pnp_resource_enabled(res))
0604         map = 1 << res->start;
0605     else
0606         map = 0;
0607 
0608     p[1] = map & 0xff;
0609 
0610     pnp_dbg(&dev->dev, "  encode dma mask %#lx\n", map);
0611 }
0612 
0613 static void pnpbios_encode_port(struct pnp_dev *dev, unsigned char *p,
0614                 struct resource *res)
0615 {
0616     unsigned long base;
0617     unsigned long len;
0618 
0619     if (pnp_resource_enabled(res)) {
0620         base = res->start;
0621         len = resource_size(res);
0622     } else {
0623         base = 0;
0624         len = 0;
0625     }
0626 
0627     p[2] = base & 0xff;
0628     p[3] = (base >> 8) & 0xff;
0629     p[4] = base & 0xff;
0630     p[5] = (base >> 8) & 0xff;
0631     p[7] = len & 0xff;
0632 
0633     pnp_dbg(&dev->dev, "  encode io %#lx-%#lx\n", base, base + len - 1);
0634 }
0635 
0636 static void pnpbios_encode_fixed_port(struct pnp_dev *dev, unsigned char *p,
0637                       struct resource *res)
0638 {
0639     unsigned long base = res->start;
0640     unsigned long len = resource_size(res);
0641 
0642     if (pnp_resource_enabled(res)) {
0643         base = res->start;
0644         len = resource_size(res);
0645     } else {
0646         base = 0;
0647         len = 0;
0648     }
0649 
0650     p[1] = base & 0xff;
0651     p[2] = (base >> 8) & 0xff;
0652     p[3] = len & 0xff;
0653 
0654     pnp_dbg(&dev->dev, "  encode fixed_io %#lx-%#lx\n", base,
0655         base + len - 1);
0656 }
0657 
0658 static unsigned char *pnpbios_encode_allocated_resource_data(struct pnp_dev
0659                                 *dev,
0660                                  unsigned char *p,
0661                                  unsigned char *end)
0662 {
0663     unsigned int len, tag;
0664     int port = 0, irq = 0, dma = 0, mem = 0;
0665 
0666     if (!p)
0667         return NULL;
0668 
0669     while ((char *)p < (char *)end) {
0670 
0671         /* determine the type of tag */
0672         if (p[0] & LARGE_TAG) { /* large tag */
0673             len = (p[2] << 8) | p[1];
0674             tag = p[0];
0675         } else {    /* small tag */
0676             len = p[0] & 0x07;
0677             tag = ((p[0] >> 3) & 0x0f);
0678         }
0679 
0680         switch (tag) {
0681 
0682         case LARGE_TAG_MEM:
0683             if (len != 9)
0684                 goto len_err;
0685             pnpbios_encode_mem(dev, p,
0686                 pnp_get_resource(dev, IORESOURCE_MEM, mem));
0687             mem++;
0688             break;
0689 
0690         case LARGE_TAG_MEM32:
0691             if (len != 17)
0692                 goto len_err;
0693             pnpbios_encode_mem32(dev, p,
0694                 pnp_get_resource(dev, IORESOURCE_MEM, mem));
0695             mem++;
0696             break;
0697 
0698         case LARGE_TAG_FIXEDMEM32:
0699             if (len != 9)
0700                 goto len_err;
0701             pnpbios_encode_fixed_mem32(dev, p,
0702                 pnp_get_resource(dev, IORESOURCE_MEM, mem));
0703             mem++;
0704             break;
0705 
0706         case SMALL_TAG_IRQ:
0707             if (len < 2 || len > 3)
0708                 goto len_err;
0709             pnpbios_encode_irq(dev, p,
0710                 pnp_get_resource(dev, IORESOURCE_IRQ, irq));
0711             irq++;
0712             break;
0713 
0714         case SMALL_TAG_DMA:
0715             if (len != 2)
0716                 goto len_err;
0717             pnpbios_encode_dma(dev, p,
0718                 pnp_get_resource(dev, IORESOURCE_DMA, dma));
0719             dma++;
0720             break;
0721 
0722         case SMALL_TAG_PORT:
0723             if (len != 7)
0724                 goto len_err;
0725             pnpbios_encode_port(dev, p,
0726                 pnp_get_resource(dev, IORESOURCE_IO, port));
0727             port++;
0728             break;
0729 
0730         case SMALL_TAG_VENDOR:
0731             /* do nothing */
0732             break;
0733 
0734         case SMALL_TAG_FIXEDPORT:
0735             if (len != 3)
0736                 goto len_err;
0737             pnpbios_encode_fixed_port(dev, p,
0738                 pnp_get_resource(dev, IORESOURCE_IO, port));
0739             port++;
0740             break;
0741 
0742         case SMALL_TAG_END:
0743             p = p + 2;
0744             return (unsigned char *)p;
0745             break;
0746 
0747         default:    /* an unknown tag */
0748 len_err:
0749             dev_err(&dev->dev, "unknown tag %#x length %d\n",
0750                 tag, len);
0751             break;
0752         }
0753 
0754         /* continue to the next tag */
0755         if (p[0] & LARGE_TAG)
0756             p += len + 3;
0757         else
0758             p += len + 1;
0759     }
0760 
0761     dev_err(&dev->dev, "no end tag in resource structure\n");
0762 
0763     return NULL;
0764 }
0765 
0766 /*
0767  * Core Parsing Functions
0768  */
0769 
0770 int __init pnpbios_parse_data_stream(struct pnp_dev *dev,
0771                     struct pnp_bios_node *node)
0772 {
0773     unsigned char *p = (char *)node->data;
0774     unsigned char *end = (char *)(node->data + node->size);
0775 
0776     p = pnpbios_parse_allocated_resource_data(dev, p, end);
0777     if (!p)
0778         return -EIO;
0779     p = pnpbios_parse_resource_option_data(p, end, dev);
0780     if (!p)
0781         return -EIO;
0782     p = pnpbios_parse_compatible_ids(p, end, dev);
0783     if (!p)
0784         return -EIO;
0785     return 0;
0786 }
0787 
0788 int pnpbios_read_resources_from_node(struct pnp_dev *dev,
0789                      struct pnp_bios_node *node)
0790 {
0791     unsigned char *p = (char *)node->data;
0792     unsigned char *end = (char *)(node->data + node->size);
0793 
0794     p = pnpbios_parse_allocated_resource_data(dev, p, end);
0795     if (!p)
0796         return -EIO;
0797     return 0;
0798 }
0799 
0800 int pnpbios_write_resources_to_node(struct pnp_dev *dev,
0801                     struct pnp_bios_node *node)
0802 {
0803     unsigned char *p = (char *)node->data;
0804     unsigned char *end = (char *)(node->data + node->size);
0805 
0806     p = pnpbios_encode_allocated_resource_data(dev, p, end);
0807     if (!p)
0808         return -EIO;
0809     return 0;
0810 }