[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/isa/pnpparse.c

Version: -  FREEBSD  -  FREEBSD10  -  FREEBSD9  -  FREEBSD92  -  FREEBSD91  -  FREEBSD90  -  FREEBSD8  -  FREEBSD82  -  FREEBSD81  -  FREEBSD80  -  FREEBSD7  -  FREEBSD74  -  FREEBSD73  -  FREEBSD72  -  FREEBSD71  -  FREEBSD70  -  FREEBSD6  -  FREEBSD64  -  FREEBSD63  -  FREEBSD62  -  FREEBSD61  -  FREEBSD60  -  FREEBSD5  -  FREEBSD55  -  FREEBSD54  -  FREEBSD53  -  FREEBSD52  -  FREEBSD51  -  FREEBSD50  -  FREEBSD4  -  FREEBSD3  -  FREEBSD22  -  cheribsd  -  linux-2.6  -  linux-2.4.22  -  MK83  -  MK84  -  PLAN9  -  DFBSD  -  NETBSD  -  NETBSD5  -  NETBSD4  -  NETBSD3  -  NETBSD20  -  OPENBSD  -  xnu-517  -  xnu-792  -  xnu-792.6.70  -  xnu-1228  -  xnu-1456.1.26  -  xnu-1699.24.8  -  xnu-2050.18.24  -  OPENSOLARIS  -  minix-3-1-1  -  FREEBSD-LIBC  -  FREEBSD8-LIBC  -  FREEBSD7-LIBC  -  FREEBSD6-LIBC  -  GLIBC27 
SearchContext: -  none  -  3  -  10 

    1 /*-
    2  * Copyright (c) 1999 Doug Rabson
    3  * All rights reserved.
    4  *
    5  * Redistribution and use in source and binary forms, with or without
    6  * modification, are permitted provided that the following conditions
    7  * are met:
    8  * 1. Redistributions of source code must retain the above copyright
    9  *    notice, this list of conditions and the following disclaimer.
   10  * 2. Redistributions in binary form must reproduce the above copyright
   11  *    notice, this list of conditions and the following disclaimer in the
   12  *    documentation and/or other materials provided with the distribution.
   13  *
   14  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   15  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   17  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
   18  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   19  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   20  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   21  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   22  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   23  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   24  * SUCH DAMAGE.
   25  */
   26 
   27 #include <sys/cdefs.h>
   28 __FBSDID("$FreeBSD: src/sys/isa/pnpparse.c,v 1.14 2003/06/11 00:32:45 obrien Exp $");
   29 
   30 #include <sys/param.h>
   31 #include <sys/systm.h>
   32 #include <sys/malloc.h>
   33 #include <sys/module.h>
   34 #include <sys/bus.h>
   35 
   36 #include <machine/stdarg.h>
   37 
   38 #include <isa/isavar.h>
   39 #include <isa/pnpreg.h>
   40 #include <isa/pnpvar.h>
   41 
   42 #define MAXDEP  8
   43 
   44 #define I16(p)  ((p)[0] + ((p)[1] << 8))
   45 #define I32(p)  (I16(p) + (I16((p)+2) << 16))
   46 
   47 void
   48 pnp_printf(u_int32_t id, char *fmt, ...)
   49 {
   50         va_list ap;
   51 
   52         va_start(ap, fmt);
   53         printf("%s: ", pnp_eisaformat(id));
   54         vprintf(fmt, ap);
   55         va_end(ap);
   56 }
   57 
   58 /* parse a single descriptor */
   59 
   60 static int
   61 pnp_parse_desc(device_t dev, u_char tag, u_char *res, int len,
   62                struct isa_config *config, int ldn)
   63 {
   64         char buf[100];
   65         u_int32_t id;
   66         u_int32_t compat_id;
   67         int temp;
   68 
   69         id = isa_get_logicalid(dev);
   70 
   71         if (PNP_RES_TYPE(tag) == 0) {
   72 
   73                 /* Small resource */
   74                 switch (PNP_SRES_NUM(tag)) {
   75 
   76                 case PNP_TAG_VERSION:
   77                 case PNP_TAG_VENDOR:
   78                         /* these descriptors are quietly ignored */
   79                         break;
   80 
   81                 case PNP_TAG_LOGICAL_DEVICE:
   82                 case PNP_TAG_START_DEPENDANT:
   83                 case PNP_TAG_END_DEPENDANT:
   84                         if (bootverbose)
   85                                 pnp_printf(id, "unexpected small tag %d\n",
   86                                            PNP_SRES_NUM(tag));
   87                         /* shouldn't happen; quit now */
   88                         return (1);
   89 
   90                 case PNP_TAG_COMPAT_DEVICE:
   91                         /*
   92                          * Got a compatible device id resource.
   93                          * Should keep a list of compat ids in the device.
   94                          */
   95                         bcopy(res, &compat_id, 4);
   96                         if (isa_get_compatid(dev) == 0)
   97                                 isa_set_compatid(dev, compat_id);
   98                         break;
   99             
  100                 case PNP_TAG_IRQ_FORMAT:
  101                         if (config->ic_nirq == ISA_NIRQ) {
  102                                 pnp_printf(id, "too many irqs\n");
  103                                 return (1);
  104                         }
  105                         if (I16(res) == 0) {
  106                                 /* a null descriptor */
  107                                 config->ic_irqmask[config->ic_nirq] = 0;
  108                                 config->ic_nirq++;
  109                                 break;
  110                         }
  111                         if (bootverbose)
  112                                 pnp_printf(id, "adding irq mask %#02x\n",
  113                                            I16(res));
  114                         config->ic_irqmask[config->ic_nirq] = I16(res);
  115                         config->ic_nirq++;
  116                         break;
  117 
  118                 case PNP_TAG_DMA_FORMAT:
  119                         if (config->ic_ndrq == ISA_NDRQ) {
  120                                 pnp_printf(id, "too many drqs\n");
  121                                 return (1);
  122                         }
  123                         if (res[0] == 0) {
  124                                 /* a null descriptor */
  125                                 config->ic_drqmask[config->ic_ndrq] = 0;
  126                                 config->ic_ndrq++;
  127                                 break;
  128                         }
  129                         if (bootverbose)
  130                                 pnp_printf(id, "adding dma mask %#02x\n",
  131                                            res[0]);
  132                         config->ic_drqmask[config->ic_ndrq] = res[0];
  133                         config->ic_ndrq++;
  134                         break;
  135 
  136                 case PNP_TAG_IO_RANGE:
  137                         if (config->ic_nport == ISA_NPORT) {
  138                                 pnp_printf(id, "too many ports\n");
  139                                 return (1);
  140                         }
  141                         if (res[6] == 0) {
  142                                 /* a null descriptor */
  143                                 config->ic_port[config->ic_nport].ir_start = 0;
  144                                 config->ic_port[config->ic_nport].ir_end = 0;
  145                                 config->ic_port[config->ic_nport].ir_size = 0;
  146                                 config->ic_port[config->ic_nport].ir_align = 0;
  147                                 config->ic_nport++;
  148                                 break;
  149                         }
  150                         if (bootverbose) {
  151                                 pnp_printf(id, "adding io range "
  152                                            "%#x-%#x, size=%#x, "
  153                                            "align=%#x\n",
  154                                            I16(res + 1),
  155                                            I16(res + 3) + res[6]-1,
  156                                            res[6], res[5]);
  157                         }
  158                         config->ic_port[config->ic_nport].ir_start =
  159                             I16(res + 1);
  160                         config->ic_port[config->ic_nport].ir_end =
  161                             I16(res + 3) + res[6] - 1;
  162                         config->ic_port[config->ic_nport].ir_size = res[6];
  163                         if (res[5] == 0) {
  164                             /* Make sure align is at least one */
  165                             res[5] = 1;
  166                         }
  167                         config->ic_port[config->ic_nport].ir_align = res[5];
  168                         config->ic_nport++;
  169                         pnp_check_quirks(isa_get_vendorid(dev),
  170                                          isa_get_logicalid(dev), ldn, config);
  171                         break;
  172 
  173                 case PNP_TAG_IO_FIXED:
  174                         if (config->ic_nport == ISA_NPORT) {
  175                                 pnp_printf(id, "too many ports\n");
  176                                 return (1);
  177                         }
  178                         if (res[2] == 0) {
  179                                 /* a null descriptor */
  180                                 config->ic_port[config->ic_nport].ir_start = 0;
  181                                 config->ic_port[config->ic_nport].ir_end = 0;
  182                                 config->ic_port[config->ic_nport].ir_size = 0;
  183                                 config->ic_port[config->ic_nport].ir_align = 0;
  184                                 config->ic_nport++;
  185                                 break;
  186                         }
  187                         if (bootverbose) {
  188                                 pnp_printf(id, "adding fixed io range "
  189                                            "%#x-%#x, size=%#x, "
  190                                            "align=%#x\n",
  191                                            I16(res),
  192                                            I16(res) + res[2] - 1,
  193                                            res[2], 1);
  194                         }
  195                         config->ic_port[config->ic_nport].ir_start = I16(res);
  196                         config->ic_port[config->ic_nport].ir_end =
  197                             I16(res) + res[2] - 1;
  198                         config->ic_port[config->ic_nport].ir_size = res[2];
  199                         config->ic_port[config->ic_nport].ir_align = 1;
  200                         config->ic_nport++;
  201                         break;
  202 
  203                 case PNP_TAG_END:
  204                         if (bootverbose)
  205                                 pnp_printf(id, "end config\n");
  206                         return (1);
  207 
  208                 default:
  209                         /* Skip this resource */
  210                         pnp_printf(id, "unexpected small tag %d\n",
  211                                       PNP_SRES_NUM(tag));
  212                         break;
  213                 }
  214         } else {
  215                 /* Large resource */
  216                 switch (PNP_LRES_NUM(tag)) {
  217 
  218                 case PNP_TAG_ID_UNICODE:
  219                 case PNP_TAG_LARGE_VENDOR:
  220                         /* these descriptors are quietly ignored */
  221                         break;
  222 
  223                 case PNP_TAG_ID_ANSI:
  224                         if (len > sizeof(buf) - 1)
  225                                 len = sizeof(buf) - 1;
  226                         bcopy(res, buf, len);
  227 
  228                         /*
  229                          * Trim trailing spaces and garbage.
  230                          */
  231                         while (len > 0 && buf[len - 1] <= ' ')
  232                                 len--;
  233                         buf[len] = '\0';
  234                         device_set_desc_copy(dev, buf);
  235                         break;
  236                         
  237                 case PNP_TAG_MEMORY_RANGE:
  238                         if (config->ic_nmem == ISA_NMEM) {
  239                                 pnp_printf(id, "too many memory ranges\n");
  240                                 return (1);
  241                         }
  242                         if (I16(res + 7) == 0) {
  243                                 /* a null descriptor */
  244                                 config->ic_mem[config->ic_nmem].ir_start = 0;
  245                                 config->ic_mem[config->ic_nmem].ir_end = 0;
  246                                 config->ic_mem[config->ic_nmem].ir_size = 0;
  247                                 config->ic_mem[config->ic_nmem].ir_align = 0;
  248                                 config->ic_nmem++;
  249                                 break;
  250                         }
  251                         if (bootverbose) {
  252                                 temp = I16(res + 7) << 8;
  253                                 pnp_printf(id, "adding memory range "
  254                                            "%#x-%#x, size=%#x, "
  255                                            "align=%#x\n",
  256                                            I16(res + 1) << 8,
  257                                            (I16(res + 3) << 8) + temp - 1,
  258                                            temp, I16(res + 5));
  259                         }
  260                         config->ic_mem[config->ic_nmem].ir_start =
  261                             I16(res + 1) << 8;
  262                         config->ic_mem[config->ic_nmem].ir_end =
  263                             (I16(res + 3) << 8) + (I16(res + 7) << 8) - 1;
  264                         config->ic_mem[config->ic_nmem].ir_size =
  265                             I16(res + 7) << 8;
  266                         config->ic_mem[config->ic_nmem].ir_align = I16(res + 5);
  267                         if (!config->ic_mem[config->ic_nmem].ir_align)
  268                                 config->ic_mem[config->ic_nmem].ir_align =
  269                                     0x10000;
  270                         config->ic_nmem++;
  271                         break;
  272 
  273                 case PNP_TAG_MEMORY32_RANGE:
  274                         if (config->ic_nmem == ISA_NMEM) {
  275                                 pnp_printf(id, "too many memory ranges\n");
  276                                 return (1);
  277                         }
  278                         if (I32(res + 13) == 0) {
  279                                 /* a null descriptor */
  280                                 config->ic_mem[config->ic_nmem].ir_start = 0;
  281                                 config->ic_mem[config->ic_nmem].ir_end = 0;
  282                                 config->ic_mem[config->ic_nmem].ir_size = 0;
  283                                 config->ic_mem[config->ic_nmem].ir_align = 0;
  284                                 config->ic_nmem++;
  285                                 break;
  286                         }
  287                         if (bootverbose) {
  288                                 pnp_printf(id, "adding memory32 range "
  289                                            "%#x-%#x, size=%#x, "
  290                                            "align=%#x\n",
  291                                            I32(res + 1),
  292                                            I32(res + 5) + I32(res + 13) - 1,
  293                                            I32(res + 13), I32(res + 9));
  294                         }
  295                         config->ic_mem[config->ic_nmem].ir_start = I32(res + 1);
  296                         config->ic_mem[config->ic_nmem].ir_end =
  297                             I32(res + 5) + I32(res + 13) - 1;
  298                         config->ic_mem[config->ic_nmem].ir_size = I32(res + 13);
  299                         config->ic_mem[config->ic_nmem].ir_align = I32(res + 9);
  300                         config->ic_nmem++;
  301                         break;
  302 
  303                 case PNP_TAG_MEMORY32_FIXED:
  304                         if (config->ic_nmem == ISA_NMEM) {
  305                                 pnp_printf(id, "too many memory ranges\n");
  306                                 return (1);
  307                         }
  308                         if (I32(res + 5) == 0) {
  309                                 /* a null descriptor */
  310                                 config->ic_mem[config->ic_nmem].ir_start = 0;
  311                                 config->ic_mem[config->ic_nmem].ir_end = 0;
  312                                 config->ic_mem[config->ic_nmem].ir_size = 0;
  313                                 config->ic_mem[config->ic_nmem].ir_align = 0;
  314                                 break;
  315                         }
  316                         if (bootverbose) {
  317                                 pnp_printf(id, "adding fixed memory32 range "
  318                                            "%#x-%#x, size=%#x\n",
  319                                            I32(res + 1),
  320                                            I32(res + 1) + I32(res + 5) - 1,
  321                                            I32(res + 5));
  322                         }
  323                         config->ic_mem[config->ic_nmem].ir_start = I32(res + 1);
  324                         config->ic_mem[config->ic_nmem].ir_end =
  325                             I32(res + 1) + I32(res + 5) - 1;
  326                         config->ic_mem[config->ic_nmem].ir_size = I32(res + 5);
  327                         config->ic_mem[config->ic_nmem].ir_align = 1;
  328                         config->ic_nmem++;
  329                         break;
  330 
  331                 default:
  332                         /* Skip this resource */
  333                         pnp_printf(id, "unexpected large tag %d\n",
  334                                    PNP_SRES_NUM(tag));
  335                         break;
  336                 }
  337         }
  338 
  339         return (0);
  340 }
  341 
  342 /*
  343  * Parse a single "dependent" resource combination.
  344  */
  345 
  346 u_char
  347 *pnp_parse_dependant(device_t dev, u_char *resources, int len,
  348                      struct isa_config *config, int ldn)
  349 {
  350 
  351         return pnp_scan_resources(dev, resources, len, config, ldn,
  352                                   pnp_parse_desc);
  353 }
  354 
  355 static void
  356 pnp_merge_resources(device_t dev, struct isa_config *from,
  357                     struct isa_config *to)
  358 {
  359         device_t parent;
  360         int i;
  361 
  362         parent = device_get_parent(dev);
  363         for (i = 0; i < from->ic_nmem; i++) {
  364                 if (to->ic_nmem == ISA_NMEM) {
  365                         device_printf(parent, "too many memory ranges\n");
  366                         return;
  367                 }
  368                 to->ic_mem[to->ic_nmem] = from->ic_mem[i];
  369                 to->ic_nmem++;
  370         }
  371         for (i = 0; i < from->ic_nport; i++) {
  372                 if (to->ic_nport == ISA_NPORT) {
  373                         device_printf(parent, "too many port ranges\n");
  374                         return;
  375                 }
  376                 to->ic_port[to->ic_nport] = from->ic_port[i];
  377                 to->ic_nport++;
  378         }
  379         for (i = 0; i < from->ic_nirq; i++) {
  380                 if (to->ic_nirq == ISA_NIRQ) {
  381                         device_printf(parent, "too many irq ranges\n");
  382                         return;
  383                 }
  384                 to->ic_irqmask[to->ic_nirq] = from->ic_irqmask[i];
  385                 to->ic_nirq++;
  386         }
  387         for (i = 0; i < from->ic_ndrq; i++) {
  388                 if (to->ic_ndrq == ISA_NDRQ) {
  389                         device_printf(parent, "too many drq ranges\n");
  390                         return;
  391                 }
  392                 to->ic_drqmask[to->ic_ndrq] = from->ic_drqmask[i];
  393                 to->ic_ndrq++;
  394         }
  395 }
  396 
  397 /*
  398  * Parse resource data for Logical Devices, make a list of available
  399  * resource configurations, and add them to the device.
  400  *
  401  * This function exits as soon as it gets an error reading *ANY*
  402  * Resource Data or it reaches the end of Resource Data.
  403  */
  404 
  405 void
  406 pnp_parse_resources(device_t dev, u_char *resources, int len, int ldn)
  407 {
  408         struct isa_config *configs;
  409         struct isa_config *config;
  410         device_t parent;
  411         int priorities[1 + MAXDEP];
  412         u_char *start;
  413         u_char *p;
  414         u_char tag;
  415         u_int32_t id;
  416         int ncfgs;
  417         int l;
  418         int i;
  419 
  420         parent = device_get_parent(dev);
  421         id = isa_get_logicalid(dev);
  422 
  423         configs = (struct isa_config *)malloc(sizeof(*configs)*(1 + MAXDEP),
  424                                               M_DEVBUF, M_NOWAIT | M_ZERO);
  425         if (configs == NULL) {
  426                 device_printf(parent, "No memory to parse PNP data\n");
  427                 return;
  428         }
  429         config = &configs[0];
  430         priorities[0] = 0;
  431         ncfgs = 1;
  432 
  433         p = resources;
  434         start = NULL;
  435         while (len > 0) {
  436                 tag = *p++;
  437                 len--;
  438                 if (PNP_RES_TYPE(tag) == 0) {
  439                         /* Small resource */
  440                         l = PNP_SRES_LEN(tag);
  441                         if (len < l) {
  442                                 len = 0;
  443                                 continue;
  444                         }
  445                         len -= l;
  446 
  447                         switch (PNP_SRES_NUM(tag)) {
  448 
  449                         case PNP_TAG_START_DEPENDANT:
  450                                 if (start != NULL) {
  451                                         /*
  452                                          * Copy the common resources first,
  453                                          * then parse the "dependent" resources.
  454                                          */
  455                                         pnp_merge_resources(dev, &configs[0],
  456                                                             config);
  457                                         pnp_parse_dependant(dev, start,
  458                                                             p - start - 1,
  459                                                             config, ldn);
  460                                 }
  461                                 start = p + l;
  462                                 if (ncfgs > MAXDEP) {
  463                                         device_printf(parent, "too many dependant configs (%d)\n", MAXDEP);
  464                                         len = 0;
  465                                         break;
  466                                 }
  467                                 config = &configs[ncfgs];
  468                                 /*
  469                                  * If the priority is not specified,
  470                                  * then use the default of 'acceptable'
  471                                  */
  472                                 if (l > 0)
  473                                         priorities[ncfgs] = p[0];
  474                                 else
  475                                         priorities[ncfgs] = 1;
  476                                 if (bootverbose)
  477                                         pnp_printf(id, "start dependent (%d)\n",
  478                                                    priorities[ncfgs]);
  479                                 ncfgs++;
  480                                 break;
  481 
  482                         case PNP_TAG_END_DEPENDANT:
  483                                 if (start == NULL) {
  484                                         device_printf(parent,
  485                                                       "malformed resources\n");
  486                                         len = 0;
  487                                         break;
  488                                 }
  489                                 /*
  490                                  * Copy the common resources first,
  491                                  * then parse the "dependent" resources.
  492                                  */
  493                                 pnp_merge_resources(dev, &configs[0], config);
  494                                 pnp_parse_dependant(dev, start, p - start - 1,
  495                                                     config, ldn);
  496                                 start = NULL;
  497                                 if (bootverbose)
  498                                         pnp_printf(id, "end dependent\n");
  499                                 /*
  500                                  * Back to the common part; clear it
  501                                  * as its contents has already been copied
  502                                  * to each dependant.
  503                                  */
  504                                 config = &configs[0];
  505                                 bzero(config, sizeof(*config));
  506                                 break;
  507 
  508                         case PNP_TAG_END:
  509                                 if (start != NULL) {
  510                                         device_printf(parent,
  511                                                       "malformed resources\n");
  512                                 }
  513                                 len = 0;
  514                                 break;
  515 
  516                         default:
  517                                 if (start != NULL)
  518                                         /* defer parsing a dependent section */
  519                                         break;
  520                                 if (pnp_parse_desc(dev, tag, p, l, config, ldn))
  521                                         len = 0;
  522                                 break;
  523                         }
  524                         p += l;
  525                 } else {
  526                         /* Large resource */
  527                         if (len < 2) {
  528                                 len = 0;
  529                                 break;
  530                         }
  531                         l = I16(p);
  532                         p += 2;
  533                         len -= 2;
  534                         if (len < l) {
  535                                 len = 0;
  536                                 break;
  537                         }
  538                         len -= l;
  539                         if (start == NULL &&
  540                             pnp_parse_desc(dev, tag, p, l, config, ldn)) {
  541                                 len = 0;
  542                                 break;
  543                         }
  544                         p += l;
  545                 }
  546         }
  547 
  548         if (ncfgs == 1) {
  549                 /* Single config without dependants */
  550                 ISA_ADD_CONFIG(parent, dev, priorities[0], &configs[0]);
  551                 free(configs, M_DEVBUF);
  552                 return;
  553         }
  554 
  555         for (i = 1; i < ncfgs; i++) {
  556                 /*
  557                  * Merge the remaining part of the common resources,
  558                  * if any. Strictly speaking, there shouldn't be common/main
  559                  * resources after the END_DEPENDENT tag.
  560                  */
  561                 pnp_merge_resources(dev, &configs[0], &configs[i]);
  562                 ISA_ADD_CONFIG(parent, dev, priorities[i], &configs[i]);
  563         }
  564 
  565         free(configs, M_DEVBUF);
  566 }
  567 
  568 u_char
  569 *pnp_scan_resources(device_t dev, u_char *resources, int len,
  570                     struct isa_config *config, int ldn, pnp_scan_cb *cb)
  571 {
  572         u_char *p;
  573         u_char tag;
  574         int l;
  575 
  576         p = resources;
  577         while (len > 0) {
  578                 tag = *p++;
  579                 len--;
  580                 if (PNP_RES_TYPE(tag) == 0) {
  581                         /* small resource */
  582                         l = PNP_SRES_LEN(tag);
  583                         if (len < l)
  584                                 break;
  585                         if ((*cb)(dev, tag, p, l, config, ldn))
  586                                 return (p + l);
  587                         if (PNP_SRES_NUM(tag) == PNP_TAG_END)
  588                                 return (p + l);
  589                 } else {
  590                         /* large resource */
  591                         if (len < 2)
  592                                 break;
  593                         l = I16(p);
  594                         p += 2;
  595                         len -= 2;
  596                         if (len < l)
  597                                 break;
  598                         if ((*cb)(dev, tag, p, l, config, ldn))
  599                                 return (p + l);
  600                 }
  601                 p += l;
  602                 len -= l;
  603         }
  604         return NULL;
  605 }

Cache object: fb33222ad86b4d875b37fa45eb7b519a


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.