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/dev/ipmi/ipmi_kcs.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  * Copyright (c) 2006 IronPort Systems Inc. <ambrisko@ironport.com>
    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: releng/8.4/sys/dev/ipmi/ipmi_kcs.c 182321 2008-08-28 02:11:04Z jhb $");
   29 
   30 #include <sys/param.h>
   31 #include <sys/systm.h>
   32 #include <sys/bus.h>
   33 #include <sys/condvar.h>
   34 #include <sys/eventhandler.h>
   35 #include <sys/kernel.h>
   36 #include <sys/kthread.h>
   37 #include <sys/rman.h>
   38 #include <sys/selinfo.h>
   39 #include <machine/bus.h>
   40 
   41 #ifdef LOCAL_MODULE
   42 #include <ipmi.h>
   43 #include <ipmivars.h>
   44 #else
   45 #include <sys/ipmi.h>
   46 #include <dev/ipmi/ipmivars.h>
   47 #endif
   48 
   49 static void     kcs_clear_obf(struct ipmi_softc *, int);
   50 static void     kcs_error(struct ipmi_softc *);
   51 static int      kcs_wait_for_ibf(struct ipmi_softc *, int);
   52 static int      kcs_wait_for_obf(struct ipmi_softc *, int);
   53 
   54 static int
   55 kcs_wait_for_ibf(struct ipmi_softc *sc, int state)
   56 {
   57         int status, start = ticks;
   58 
   59         status = INB(sc, KCS_CTL_STS);
   60         if (state == 0) {
   61                 /* WAIT FOR IBF = 0 */
   62                 while (ticks - start < MAX_TIMEOUT && status & KCS_STATUS_IBF) {
   63                         DELAY(100);
   64                         status = INB(sc, KCS_CTL_STS);
   65                 }
   66         } else {
   67                 /* WAIT FOR IBF = 1 */
   68                 while (ticks - start < MAX_TIMEOUT &&
   69                     !(status & KCS_STATUS_IBF)) {
   70                         DELAY(100);
   71                         status = INB(sc, KCS_CTL_STS);
   72                 }
   73         }
   74         return (status);
   75 }
   76 
   77 static int
   78 kcs_wait_for_obf(struct ipmi_softc *sc, int state)
   79 {
   80         int status, start = ticks;
   81 
   82         status = INB(sc, KCS_CTL_STS);
   83         if (state == 0) {
   84                 /* WAIT FOR OBF = 0 */
   85                 while (ticks - start < MAX_TIMEOUT && status & KCS_STATUS_OBF) {
   86                         DELAY(100);
   87                         status = INB(sc, KCS_CTL_STS);
   88                 }
   89         } else {
   90                 /* WAIT FOR OBF = 1 */
   91                 while (ticks - start < MAX_TIMEOUT &&
   92                     !(status & KCS_STATUS_OBF)) {
   93                         DELAY(100);
   94                         status = INB(sc, KCS_CTL_STS);
   95                 }
   96         }
   97         return (status);
   98 }
   99 
  100 static void
  101 kcs_clear_obf(struct ipmi_softc *sc, int status)
  102 {
  103         int data;
  104 
  105         /* Clear OBF */
  106         if (status & KCS_STATUS_OBF) {
  107                 data = INB(sc, KCS_DATA);
  108         }
  109 }
  110 
  111 static void
  112 kcs_error(struct ipmi_softc *sc)
  113 {
  114         int retry, status;
  115         u_char data;
  116 
  117         for (retry = 0; retry < 2; retry++) {
  118 
  119                 /* Wait for IBF = 0 */
  120                 status = kcs_wait_for_ibf(sc, 0);
  121 
  122                 /* ABORT */
  123                 OUTB(sc, KCS_CTL_STS, KCS_CONTROL_GET_STATUS_ABORT);
  124 
  125                 /* Wait for IBF = 0 */
  126                 status = kcs_wait_for_ibf(sc, 0);
  127 
  128                 /* Clear OBF */
  129                 kcs_clear_obf(sc, status);
  130 
  131                 if (status & KCS_STATUS_OBF) {
  132                         data = INB(sc, KCS_DATA);
  133                         if (data != 0)
  134                                 device_printf(sc->ipmi_dev,
  135                                     "KCS Error Data %02x\n", data);
  136                 }
  137 
  138                 /* 0x00 to DATA_IN */
  139                 OUTB(sc, KCS_DATA, 0x00);
  140 
  141                 /* Wait for IBF = 0 */
  142                 status = kcs_wait_for_ibf(sc, 0);
  143 
  144                 if (KCS_STATUS_STATE(status) == KCS_STATUS_STATE_READ) {
  145 
  146                         /* Wait for OBF = 1 */
  147                         status = kcs_wait_for_obf(sc, 1);
  148 
  149                         /* Read error status */
  150                         data = INB(sc, KCS_DATA);
  151                         if (data != 0)
  152                                 device_printf(sc->ipmi_dev, "KCS error: %02x\n",
  153                                     data);
  154 
  155                         /* Write READ into Data_in */
  156                         OUTB(sc, KCS_DATA, KCS_DATA_IN_READ);
  157 
  158                         /* Wait for IBF = 0 */
  159                         status = kcs_wait_for_ibf(sc, 0);
  160                 }
  161 
  162                 /* IDLE STATE */
  163                 if (KCS_STATUS_STATE(status) == KCS_STATUS_STATE_IDLE) {
  164                         /* Wait for OBF = 1 */
  165                         status = kcs_wait_for_obf(sc, 1);
  166 
  167                         /* Clear OBF */
  168                         kcs_clear_obf(sc, status);
  169                         return;
  170                 }
  171         }
  172         device_printf(sc->ipmi_dev, "KCS: Error retry exhausted\n");
  173 }
  174 
  175 /*
  176  * Start to write a request.  Waits for IBF to clear and then sends the
  177  * WR_START command.
  178  */
  179 static int
  180 kcs_start_write(struct ipmi_softc *sc)
  181 {
  182         int retry, status;
  183 
  184         for (retry = 0; retry < 10; retry++) {
  185                 /* Wait for IBF = 0 */
  186                 status = kcs_wait_for_ibf(sc, 0);
  187 
  188                 /* Clear OBF */
  189                 kcs_clear_obf(sc, status);
  190 
  191                 /* Write start to command */
  192                 OUTB(sc, KCS_CTL_STS, KCS_CONTROL_WRITE_START);
  193 
  194                 /* Wait for IBF = 0 */
  195                 status = kcs_wait_for_ibf(sc, 0);
  196                 if (KCS_STATUS_STATE(status) == KCS_STATUS_STATE_WRITE)
  197                         break;
  198                 DELAY(1000000);
  199         }
  200 
  201         if (KCS_STATUS_STATE(status) != KCS_STATUS_STATE_WRITE)
  202                 /* error state */
  203                 return (0);
  204 
  205         /* Clear OBF */
  206         kcs_clear_obf(sc, status);
  207 
  208         return (1);
  209 }
  210 
  211 /*
  212  * Write a byte of the request message, excluding the last byte of the
  213  * message which requires special handling.
  214  */
  215 static int
  216 kcs_write_byte(struct ipmi_softc *sc, u_char data)
  217 {
  218         int status;
  219 
  220         /* Data to Data */
  221         OUTB(sc, KCS_DATA, data);
  222 
  223         /* Wait for IBF = 0 */
  224         status = kcs_wait_for_ibf(sc, 0);
  225 
  226         if (KCS_STATUS_STATE(status) != KCS_STATUS_STATE_WRITE)
  227                 return (0);
  228 
  229         /* Clear OBF */
  230         kcs_clear_obf(sc, status);
  231         return (1);
  232 }
  233 
  234 /*
  235  * Write the last byte of a request message.
  236  */
  237 static int
  238 kcs_write_last_byte(struct ipmi_softc *sc, u_char data)
  239 {
  240         int status;
  241 
  242         /* Write end to command */
  243         OUTB(sc, KCS_CTL_STS, KCS_CONTROL_WRITE_END);
  244 
  245         /* Wait for IBF = 0 */
  246         status = kcs_wait_for_ibf(sc, 0);
  247 
  248         if (KCS_STATUS_STATE(status) != KCS_STATUS_STATE_WRITE)
  249                 /* error state */
  250                 return (0);
  251 
  252         /* Clear OBF */
  253         kcs_clear_obf(sc, status);
  254 
  255         /* Send data byte to DATA. */
  256         OUTB(sc, KCS_DATA, data);
  257         return (1);
  258 }
  259 
  260 /*
  261  * Read one byte of the reply message.
  262  */
  263 static int
  264 kcs_read_byte(struct ipmi_softc *sc, u_char *data)
  265 {
  266         int status;
  267         u_char dummy;
  268 
  269         /* Wait for IBF = 0 */
  270         status = kcs_wait_for_ibf(sc, 0);
  271 
  272         /* Read State */
  273         if (KCS_STATUS_STATE(status) == KCS_STATUS_STATE_READ) {
  274 
  275                 /* Wait for OBF = 1 */
  276                 status = kcs_wait_for_obf(sc, 1);
  277 
  278                 /* Read Data_out */
  279                 *data = INB(sc, KCS_DATA);
  280 
  281                 /* Write READ into Data_in */
  282                 OUTB(sc, KCS_DATA, KCS_DATA_IN_READ);
  283                 return (1);
  284         }
  285 
  286         /* Idle State */
  287         if (KCS_STATUS_STATE(status) == KCS_STATUS_STATE_IDLE) {
  288 
  289                 /* Wait for OBF = 1*/
  290                 status = kcs_wait_for_obf(sc, 1);
  291 
  292                 /* Read Dummy */
  293                 dummy = INB(sc, KCS_DATA);
  294                 return (2);
  295         }
  296 
  297         /* Error State */
  298         return (0);
  299 }
  300 
  301 /*
  302  * Send a request message and collect the reply.  Returns true if we
  303  * succeed.
  304  */
  305 static int
  306 kcs_polled_request(struct ipmi_softc *sc, struct ipmi_request *req)
  307 {
  308         u_char *cp, data;
  309         int i, state;
  310 
  311         /* Send the request. */
  312         if (!kcs_start_write(sc)) {
  313                 device_printf(sc->ipmi_dev, "KCS: Failed to start write\n");
  314                 goto fail;
  315         }
  316 #ifdef KCS_DEBUG
  317         device_printf(sc->ipmi_dev, "KCS: WRITE_START... ok\n");
  318 #endif
  319 
  320         if (!kcs_write_byte(sc, req->ir_addr)) {
  321                 device_printf(sc->ipmi_dev, "KCS: Failed to write address\n");
  322                 goto fail;
  323         }
  324 #ifdef KCS_DEBUG
  325         device_printf(sc->ipmi_dev, "KCS: Wrote address: %02x\n", req->ir_addr);
  326 #endif
  327 
  328         if (req->ir_requestlen == 0) {
  329                 if (!kcs_write_last_byte(sc, req->ir_command)) {
  330                         device_printf(sc->ipmi_dev,
  331                             "KCS: Failed to write command\n");
  332                         goto fail;
  333                 }
  334 #ifdef KCS_DEBUG
  335                 device_printf(sc->ipmi_dev, "KCS: Wrote command: %02x\n",
  336                     req->ir_command);
  337 #endif
  338         } else {
  339                 if (!kcs_write_byte(sc, req->ir_command)) {
  340                         device_printf(sc->ipmi_dev,
  341                             "KCS: Failed to write command\n");
  342                         goto fail;
  343                 }
  344 #ifdef KCS_DEBUG
  345                 device_printf(sc->ipmi_dev, "KCS: Wrote command: %02x\n",
  346                     req->ir_command);
  347 #endif
  348 
  349                 cp = req->ir_request;
  350                 for (i = 0; i < req->ir_requestlen - 1; i++) {
  351                         if (!kcs_write_byte(sc, *cp++)) {
  352                                 device_printf(sc->ipmi_dev,
  353                                     "KCS: Failed to write data byte %d\n",
  354                                     i + 1);
  355                                 goto fail;
  356                         }
  357 #ifdef KCS_DEBUG
  358                         device_printf(sc->ipmi_dev, "KCS: Wrote data: %02x\n",
  359                             cp[-1]);
  360 #endif
  361                 }
  362 
  363                 if (!kcs_write_last_byte(sc, *cp)) {
  364                         device_printf(sc->ipmi_dev,
  365                             "KCS: Failed to write last dta byte\n");
  366                         goto fail;
  367                 }
  368 #ifdef KCS_DEBUG
  369                 device_printf(sc->ipmi_dev, "KCS: Wrote last data: %02x\n",
  370                     *cp);
  371 #endif
  372         }
  373 
  374         /* Read the reply.  First, read the NetFn/LUN. */
  375         if (kcs_read_byte(sc, &data) != 1) {
  376                 device_printf(sc->ipmi_dev, "KCS: Failed to read address\n");
  377                 goto fail;
  378         }
  379 #ifdef KCS_DEBUG
  380         device_printf(sc->ipmi_dev, "KCS: Read address: %02x\n", data);
  381 #endif
  382         if (data != IPMI_REPLY_ADDR(req->ir_addr)) {
  383                 device_printf(sc->ipmi_dev, "KCS: Reply address mismatch\n");
  384                 goto fail;
  385         }
  386 
  387         /* Next we read the command. */
  388         if (kcs_read_byte(sc, &data) != 1) {
  389                 device_printf(sc->ipmi_dev, "KCS: Failed to read command\n");
  390                 goto fail;
  391         }
  392 #ifdef KCS_DEBUG
  393         device_printf(sc->ipmi_dev, "KCS: Read command: %02x\n", data);
  394 #endif
  395         if (data != req->ir_command) {
  396                 device_printf(sc->ipmi_dev, "KCS: Command mismatch\n");
  397                 goto fail;
  398         }
  399 
  400         /* Next we read the completion code. */
  401         if (kcs_read_byte(sc, &req->ir_compcode) != 1) {
  402                 device_printf(sc->ipmi_dev,
  403                     "KCS: Failed to read completion code\n");
  404                 goto fail;
  405         }
  406 #ifdef KCS_DEBUG
  407         device_printf(sc->ipmi_dev, "KCS: Read completion code: %02x\n",
  408             req->ir_compcode);
  409 #endif
  410 
  411         /* Finally, read the reply from the BMC. */
  412         i = 0;
  413         for (;;) {
  414                 state = kcs_read_byte(sc, &data);
  415                 if (state == 0) {
  416                         device_printf(sc->ipmi_dev,
  417                             "KCS: Read failed on byte %d\n", i + 1);
  418                         goto fail;
  419                 }
  420                 if (state == 2)
  421                         break;
  422                 if (i < req->ir_replybuflen) {
  423                         req->ir_reply[i] = data;
  424 #ifdef KCS_DEBUG
  425                         device_printf(sc->ipmi_dev, "KCS: Read data %02x\n",
  426                             data);
  427                 } else {
  428                         device_printf(sc->ipmi_dev,
  429                             "KCS: Read short %02x byte %d\n", data, i + 1);
  430 #endif
  431                 }
  432                 i++;
  433         }
  434         req->ir_replylen = i;
  435 #ifdef KCS_DEBUG
  436         device_printf(sc->ipmi_dev, "KCS: READ finished (%d bytes)\n", i);
  437         if (req->ir_replybuflen < i)
  438 #else
  439         if (req->ir_replybuflen < i && req->ir_replybuflen != 0)
  440 #endif
  441                 device_printf(sc->ipmi_dev,
  442                     "KCS: Read short: %zd buffer, %d actual\n",
  443                     req->ir_replybuflen, i);
  444         return (1);
  445 fail:
  446         kcs_error(sc);
  447         return (0);
  448 }
  449 
  450 static void
  451 kcs_loop(void *arg)
  452 {
  453         struct ipmi_softc *sc = arg;
  454         struct ipmi_request *req;
  455         int i, ok;
  456 
  457         IPMI_LOCK(sc);
  458         while ((req = ipmi_dequeue_request(sc)) != NULL) {
  459                 ok = 0;
  460                 for (i = 0; i < 3 && !ok; i++)
  461                         ok = kcs_polled_request(sc, req);
  462                 if (ok)
  463                         req->ir_error = 0;
  464                 else
  465                         req->ir_error = EIO;
  466                 ipmi_complete_request(sc, req);
  467         }
  468         IPMI_UNLOCK(sc);
  469         kproc_exit(0);
  470 }
  471 
  472 static int
  473 kcs_startup(struct ipmi_softc *sc)
  474 {
  475 
  476         return (kproc_create(kcs_loop, sc, &sc->ipmi_kthread, 0, 0, "%s: kcs",
  477             device_get_nameunit(sc->ipmi_dev)));
  478 }
  479 
  480 int
  481 ipmi_kcs_attach(struct ipmi_softc *sc)
  482 {
  483         int status;
  484 
  485         /* Setup function pointers. */
  486         sc->ipmi_startup = kcs_startup;
  487         sc->ipmi_enqueue_request = ipmi_polled_enqueue_request;
  488 
  489         /* See if we can talk to the controller. */
  490         status = INB(sc, KCS_CTL_STS);
  491         if (status == 0xff) {
  492                 device_printf(sc->ipmi_dev, "couldn't find it\n");
  493                 return (ENXIO);
  494         }
  495 
  496 #ifdef KCS_DEBUG
  497         device_printf(sc->ipmi_dev, "KCS: initial state: %02x\n", status);
  498 #endif
  499         if (status & KCS_STATUS_OBF ||
  500             KCS_STATUS_STATE(status) != KCS_STATUS_STATE_IDLE)
  501                 kcs_error(sc);
  502 
  503         return (0);
  504 }
  505 
  506 /*
  507  * Determine the alignment automatically for a PCI attachment.  In this case,
  508  * any unused bytes will return 0x00 when read.  We make use of the C/D bit
  509  * in the CTL_STS register to try to start a GET_STATUS transaction.  When
  510  * we write the command, that bit should be set, so we should get a non-zero
  511  * value back when we read CTL_STS if the offset we are testing is the CTL_STS
  512  * register.
  513  */
  514 int
  515 ipmi_kcs_probe_align(struct ipmi_softc *sc)
  516 {
  517         int data, status;
  518 
  519         sc->ipmi_io_spacing = 1;
  520 retry:
  521 #ifdef KCS_DEBUG
  522         device_printf(sc->ipmi_dev, "Trying KCS align %d... ", sc->ipmi_io_spacing);
  523 #endif
  524 
  525         /* Wait for IBF = 0 */
  526         status = INB(sc, KCS_CTL_STS);
  527         while (status & KCS_STATUS_IBF) {
  528                 DELAY(100);
  529                 status = INB(sc, KCS_CTL_STS);
  530         }
  531 
  532         OUTB(sc, KCS_CTL_STS, KCS_CONTROL_GET_STATUS_ABORT);
  533 
  534         /* Wait for IBF = 0 */
  535         status = INB(sc, KCS_CTL_STS);
  536         while (status & KCS_STATUS_IBF) {
  537                 DELAY(100);
  538                 status = INB(sc, KCS_CTL_STS);
  539         }
  540 
  541         /* If we got 0x00 back, then this must not be the CTL_STS register. */
  542         if (status == 0) {
  543 #ifdef KCS_DEBUG
  544                 printf("failed\n");
  545 #endif
  546                 sc->ipmi_io_spacing <<= 1;
  547                 if (sc->ipmi_io_spacing > 4)
  548                         return (0);
  549                 goto retry;
  550         }
  551 #ifdef KCS_DEBUG
  552         printf("ok\n");
  553 #endif
  554 
  555         /* Finish out the transaction. */
  556 
  557         /* Clear OBF */
  558         if (status & KCS_STATUS_OBF)
  559                 data = INB(sc, KCS_DATA);
  560 
  561         /* 0x00 to DATA_IN */
  562         OUTB(sc, KCS_DATA, 0);
  563 
  564         /* Wait for IBF = 0 */
  565         status = INB(sc, KCS_CTL_STS);
  566         while (status & KCS_STATUS_IBF) {
  567                 DELAY(100);
  568                 status = INB(sc, KCS_CTL_STS);
  569         }
  570 
  571         if (KCS_STATUS_STATE(status) == KCS_STATUS_STATE_READ) {
  572                 /* Wait for IBF = 1 */
  573                 while (!(status & KCS_STATUS_OBF)) {
  574                         DELAY(100);
  575                         status = INB(sc, KCS_CTL_STS);
  576                 }
  577 
  578                 /* Read error status. */
  579                 data = INB(sc, KCS_DATA);
  580 
  581                 /* Write dummy READ to DATA_IN. */
  582                 OUTB(sc, KCS_DATA, KCS_DATA_IN_READ);
  583 
  584                 /* Wait for IBF = 0 */
  585                 status = INB(sc, KCS_CTL_STS);
  586                 while (status & KCS_STATUS_IBF) {
  587                         DELAY(100);
  588                         status = INB(sc, KCS_CTL_STS);
  589                 }
  590         }
  591 
  592         if (KCS_STATUS_STATE(status) == KCS_STATUS_STATE_IDLE) {
  593                 /* Wait for IBF = 1 */
  594                 while (!(status & KCS_STATUS_OBF)) {
  595                         DELAY(100);
  596                         status = INB(sc, KCS_CTL_STS);
  597                 }
  598 
  599                 /* Clear OBF */
  600                 if (status & KCS_STATUS_OBF)
  601                         data = INB(sc, KCS_DATA);
  602         } else
  603                 device_printf(sc->ipmi_dev, "KCS probe: end state %x\n",
  604                     KCS_STATUS_STATE(status));
  605 
  606         return (1);
  607 }

Cache object: a588cc95992a00e10d4d1c4623683904


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