The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ 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  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

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

Cache object: 44e2492ccb039f081f8b636c9b7eceeb


[ 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.