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/cardbus/cardbus_cis.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) 2005-2008, M. Warner Losh
    3  * Copyright (c) 2000,2001 Jonathan Chen.
    4  * All rights reserved.
    5  *
    6  * Redistribution and use in source and binary forms, with or without
    7  * modification, are permitted provided that the following conditions
    8  * are met:
    9  * 1. Redistributions of source code must retain the above copyright
   10  *    notice, this list of conditions and the following disclaimer.
   11  * 2. Redistributions in binary form must reproduce the above copyright
   12  *    notice, this list of conditions and the following disclaimer in the
   13  *    documentation and/or other materials provided with the distribution.
   14  *
   15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   16  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   17  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   18  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
   19  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   20  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   21  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   22  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   23  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   24  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   25  * SUCH DAMAGE.
   26  */
   27 
   28 #include <sys/cdefs.h>
   29 __FBSDID("$FreeBSD: releng/11.0/sys/dev/cardbus/cardbus_cis.c 298955 2016-05-03 03:41:25Z pfg $");
   30 
   31 /*
   32  * CIS Handling for the Cardbus Bus
   33  */
   34 
   35 #include <sys/param.h>
   36 #include <sys/systm.h>
   37 #include <sys/kernel.h>
   38 #include <sys/malloc.h>
   39 
   40 #include <sys/bus.h>
   41 #include <machine/bus.h>
   42 #include <machine/resource.h>
   43 #include <sys/rman.h>
   44 #include <sys/endian.h>
   45 
   46 #include <sys/pciio.h>
   47 #include <dev/pci/pcivar.h>
   48 #include <dev/pci/pcireg.h>
   49 
   50 #include <dev/pccard/pccardvar.h>
   51 #include <dev/pccard/pccard_cis.h>
   52 
   53 #include <dev/cardbus/cardbusreg.h>
   54 #include <dev/cardbus/cardbusvar.h>
   55 #include <dev/cardbus/cardbus_cis.h>
   56 
   57 extern int cardbus_cis_debug;
   58 
   59 #define DPRINTF(a) if (cardbus_cis_debug) printf a
   60 #define DEVPRINTF(x) if (cardbus_cis_debug) device_printf x
   61 
   62 #define CIS_CONFIG_SPACE        (struct resource *)~0UL
   63 
   64 static int decode_tuple_generic(device_t cbdev, device_t child, int id,
   65     int len, uint8_t *tupledata, uint32_t start, uint32_t *off,
   66     struct tuple_callbacks *info, void *);
   67 static int decode_tuple_linktarget(device_t cbdev, device_t child, int id,
   68     int len, uint8_t *tupledata, uint32_t start, uint32_t *off,
   69     struct tuple_callbacks *info, void *);
   70 static int decode_tuple_vers_1(device_t cbdev, device_t child, int id,
   71     int len, uint8_t *tupledata, uint32_t start, uint32_t *off,
   72     struct tuple_callbacks *info, void *);
   73 static int decode_tuple_funcid(device_t cbdev, device_t child, int id,
   74     int len, uint8_t *tupledata, uint32_t start, uint32_t *off,
   75     struct tuple_callbacks *info, void *);
   76 static int decode_tuple_manfid(device_t cbdev, device_t child, int id,
   77     int len, uint8_t *tupledata, uint32_t start, uint32_t *off,
   78     struct tuple_callbacks *info, void *);
   79 static int decode_tuple_funce(device_t cbdev, device_t child, int id,
   80     int len, uint8_t *tupledata, uint32_t start, uint32_t *off,
   81     struct tuple_callbacks *info, void *);
   82 static int decode_tuple_bar(device_t cbdev, device_t child, int id,
   83     int len, uint8_t *tupledata, uint32_t start, uint32_t *off,
   84     struct tuple_callbacks *info, void *);
   85 static int decode_tuple_unhandled(device_t cbdev, device_t child, int id,
   86     int len, uint8_t *tupledata, uint32_t start, uint32_t *off,
   87     struct tuple_callbacks *info, void *);
   88 static int decode_tuple_end(device_t cbdev, device_t child, int id,
   89     int len, uint8_t *tupledata, uint32_t start, uint32_t *off,
   90     struct tuple_callbacks *info, void *);
   91 
   92 static int      cardbus_read_tuple_conf(device_t cbdev, device_t child,
   93                     uint32_t start, uint32_t *off, int *tupleid, int *len,
   94                     uint8_t *tupledata);
   95 static int      cardbus_read_tuple_mem(device_t cbdev, struct resource *res,
   96                     uint32_t start, uint32_t *off, int *tupleid, int *len,
   97                     uint8_t *tupledata);
   98 static int      cardbus_read_tuple(device_t cbdev, device_t child,
   99                     struct resource *res, uint32_t start, uint32_t *off,
  100                     int *tupleid, int *len, uint8_t *tupledata);
  101 static void     cardbus_read_tuple_finish(device_t cbdev, device_t child,
  102                     int rid, struct resource *res);
  103 static struct resource  *cardbus_read_tuple_init(device_t cbdev, device_t child,
  104                     uint32_t *start, int *rid);
  105 static int      decode_tuple(device_t cbdev, device_t child, int tupleid,
  106                     int len, uint8_t *tupledata, uint32_t start,
  107                     uint32_t *off, struct tuple_callbacks *callbacks,
  108                     void *);
  109 
  110 #define MAKETUPLE(NAME,FUNC) { CISTPL_ ## NAME, #NAME, decode_tuple_ ## FUNC }
  111 
  112 static char *funcnames[] = {
  113         "Multi-Functioned",
  114         "Memory",
  115         "Serial Port",
  116         "Parallel Port",
  117         "Fixed Disk",
  118         "Video Adaptor",
  119         "Network Adaptor",
  120         "AIMS",
  121         "SCSI",
  122         "Security"
  123 };
  124 
  125 /*
  126  * Handler functions for various CIS tuples
  127  */
  128 
  129 static int
  130 decode_tuple_generic(device_t cbdev, device_t child, int id,
  131     int len, uint8_t *tupledata, uint32_t start, uint32_t *off,
  132     struct tuple_callbacks *info, void *argp)
  133 {
  134         int i;
  135 
  136         if (cardbus_cis_debug) {
  137                 if (info)
  138                         printf("TUPLE: %s [%d]:", info->name, len);
  139                 else
  140                         printf("TUPLE: Unknown(0x%02x) [%d]:", id, len);
  141 
  142                 for (i = 0; i < len; i++) {
  143                         if (i % 0x10 == 0 && len > 0x10)
  144                                 printf("\n       0x%02x:", i);
  145                         printf(" %02x", tupledata[i]);
  146                 }
  147                 printf("\n");
  148         }
  149         return (0);
  150 }
  151 
  152 static int
  153 decode_tuple_linktarget(device_t cbdev, device_t child, int id,
  154     int len, uint8_t *tupledata, uint32_t start, uint32_t *off,
  155     struct tuple_callbacks *info, void *argp)
  156 {
  157         int i;
  158 
  159         if (cardbus_cis_debug) {
  160                 printf("TUPLE: %s [%d]:", info->name, len);
  161 
  162                 for (i = 0; i < len; i++) {
  163                         if (i % 0x10 == 0 && len > 0x10)
  164                                 printf("\n       0x%02x:", i);
  165                         printf(" %02x", tupledata[i]);
  166                 }
  167                 printf("\n");
  168         }
  169         if (len != 3 || tupledata[0] != 'C' || tupledata[1] != 'I' ||
  170             tupledata[2] != 'S') {
  171                 printf("Invalid data for CIS Link Target!\n");
  172                 decode_tuple_generic(cbdev, child, id, len, tupledata,
  173                     start, off, info, argp);
  174                 return (EINVAL);
  175         }
  176         return (0);
  177 }
  178 
  179 static int
  180 decode_tuple_vers_1(device_t cbdev, device_t child, int id,
  181     int len, uint8_t *tupledata, uint32_t start, uint32_t *off,
  182     struct tuple_callbacks *info, void *argp)
  183 {
  184         int i;
  185 
  186         if (cardbus_cis_debug) {
  187                 printf("Product version: %d.%d\n", tupledata[0], tupledata[1]);
  188                 printf("Product name: ");
  189                 for (i = 2; i < len; i++) {
  190                         if (tupledata[i] == '\0')
  191                                 printf(" | ");
  192                         else if (tupledata[i] == 0xff)
  193                                 break;
  194                         else
  195                                 printf("%c", tupledata[i]);
  196                 }
  197                 printf("\n");
  198         }
  199         return (0);
  200 }
  201 
  202 static int
  203 decode_tuple_funcid(device_t cbdev, device_t child, int id,
  204     int len, uint8_t *tupledata, uint32_t start, uint32_t *off,
  205     struct tuple_callbacks *info, void *argp)
  206 {
  207         struct cardbus_devinfo *dinfo = device_get_ivars(child);
  208         int numnames = nitems(funcnames);
  209         int i;
  210 
  211         if (cardbus_cis_debug) {
  212                 printf("Functions: ");
  213                 for (i = 0; i < len; i++) {
  214                         if (tupledata[i] < numnames)
  215                                 printf("%s", funcnames[tupledata[i]]);
  216                         else
  217                                 printf("Unknown(%d)", tupledata[i]);
  218                         if (i < len - 1)
  219                                 printf(", ");
  220                 }
  221                 printf("\n");
  222         }
  223         if (len > 0)
  224                 dinfo->funcid = tupledata[0];           /* use first in list */
  225         return (0);
  226 }
  227 
  228 static int
  229 decode_tuple_manfid(device_t cbdev, device_t child, int id,
  230     int len, uint8_t *tupledata, uint32_t start, uint32_t *off,
  231     struct tuple_callbacks *info, void *argp)
  232 {
  233         struct cardbus_devinfo *dinfo = device_get_ivars(child);
  234         int i;
  235 
  236         if (cardbus_cis_debug) {
  237                 printf("Manufacturer ID: ");
  238                 for (i = 0; i < len; i++)
  239                         printf("%02x", tupledata[i]);
  240                 printf("\n");
  241         }
  242 
  243         if (len == 5) {
  244                 dinfo->mfrid = tupledata[1] | (tupledata[2] << 8);
  245                 dinfo->prodid = tupledata[3] | (tupledata[4] << 8);
  246         }
  247         return (0);
  248 }
  249 
  250 static int
  251 decode_tuple_funce(device_t cbdev, device_t child, int id,
  252     int len, uint8_t *tupledata, uint32_t start, uint32_t *off,
  253     struct tuple_callbacks *info, void *argp)
  254 {
  255         struct cardbus_devinfo *dinfo = device_get_ivars(child);
  256         int type, i;
  257 
  258         if (cardbus_cis_debug) {
  259                 printf("Function Extension: ");
  260                 for (i = 0; i < len; i++)
  261                         printf("%02x", tupledata[i]);
  262                 printf("\n");
  263         }
  264         if (len < 2)                    /* too short */
  265                 return (0);
  266         type = tupledata[0];            /* XXX <32 always? */
  267         switch (dinfo->funcid) {
  268         case PCCARD_FUNCTION_NETWORK:
  269                 switch (type) {
  270                 case PCCARD_TPLFE_TYPE_LAN_NID:
  271                         if (tupledata[1] > sizeof(dinfo->funce.lan.nid)) {
  272                                 /* ignore, warning? */
  273                                 return (0);
  274                         }
  275                         bcopy(tupledata + 2, dinfo->funce.lan.nid,
  276                             tupledata[1]);
  277                         break;
  278                 }
  279                 dinfo->fepresent |= 1<<type;
  280                 break;
  281         }
  282         return (0);
  283 }
  284 
  285 static int
  286 decode_tuple_bar(device_t cbdev, device_t child, int id,
  287     int len, uint8_t *tupledata, uint32_t start, uint32_t *off,
  288     struct tuple_callbacks *info, void *argp)
  289 {
  290         struct cardbus_devinfo *dinfo = device_get_ivars(child);
  291         int type;
  292         uint8_t reg;
  293         uint32_t bar;
  294 
  295         if (len != 6) {
  296                 device_printf(cbdev, "CIS BAR length not 6 (%d)\n", len);
  297                 return (EINVAL);
  298         }
  299 
  300         reg = *tupledata;
  301         len = le32toh(*(uint32_t*)(tupledata + 2));
  302         if (reg & TPL_BAR_REG_AS)
  303                 type = SYS_RES_IOPORT;
  304         else
  305                 type = SYS_RES_MEMORY;
  306 
  307         bar = reg & TPL_BAR_REG_ASI_MASK;
  308         if (bar == 0) {
  309                 device_printf(cbdev, "Invalid BAR type 0 in CIS\n");
  310                 return (EINVAL);        /* XXX Return an error? */
  311         } else if (bar == 7) {
  312                 /* XXX Should we try to map in Option ROMs? */
  313                 return (0);
  314         }
  315 
  316         /* Convert from BAR type to BAR offset */
  317         bar = PCIR_BAR(bar - 1);
  318 
  319         if (type == SYS_RES_MEMORY) {
  320                 if (reg & TPL_BAR_REG_PREFETCHABLE)
  321                         dinfo->mprefetchable |= (1 << PCI_RID2BAR(bar));
  322                 /*
  323                  * The PC Card spec says we're only supposed to honor this
  324                  * hint when the cardbus bridge is a child of pci0 (the main
  325                  * bus).  The PC Card spec seems to indicate that this should
  326                  * only be done on x86 based machines, which suggests that on
  327                  * non-x86 machines the addresses can be anywhere.  Since the
  328                  * hardware can do it on non-x86 machines, it should be able
  329                  * to do it on x86 machines too.  Therefore, we can and should
  330                  * ignore this hint.  Furthermore, the PC Card spec recommends
  331                  * always allocating memory above 1MB, contradicting the other
  332                  * part of the PC Card spec, it seems.  We make note of it,
  333                  * but otherwise don't use this information.
  334                  *
  335                  * Some Realtek cards have this set in their CIS, but fail
  336                  * to actually work when mapped this way, and experience
  337                  * has shown ignoring this big to be a wise choice.
  338                  *
  339                  * XXX We should cite chapter and verse for standard refs.
  340                  */
  341                 if (reg & TPL_BAR_REG_BELOW1MB)
  342                         dinfo->mbelow1mb |= (1 << PCI_RID2BAR(bar));
  343         }
  344 
  345         return (0);
  346 }
  347 
  348 static int
  349 decode_tuple_unhandled(device_t cbdev, device_t child, int id,
  350     int len, uint8_t *tupledata, uint32_t start, uint32_t *off,
  351     struct tuple_callbacks *info, void *argp)
  352 {
  353         /* Make this message suck less XXX */
  354         printf("TUPLE: %s [%d] is unhandled! Bailing...", info->name, len);
  355         return (EINVAL);
  356 }
  357 
  358 static int
  359 decode_tuple_end(device_t cbdev, device_t child, int id,
  360     int len, uint8_t *tupledata, uint32_t start, uint32_t *off,
  361     struct tuple_callbacks *info, void *argp)
  362 {
  363         if (cardbus_cis_debug)
  364                 printf("CIS reading done\n");
  365         return (0);
  366 }
  367 
  368 /*
  369  * Functions to read the a tuple from the card
  370  */
  371 
  372 /*
  373  * Read CIS bytes out of the config space.  We have to read it 4 bytes at a
  374  * time and do the usual mask and shift to return the bytes.  The standard
  375  * defines the byte order to be little endian.  pci_read_config converts it to
  376  * host byte order.  This is why we have no endian conversion functions: the
  377  * shifts wind up being endian neutral.  This is also why we avoid the obvious
  378  * memcpy optimization.
  379  */
  380 static int
  381 cardbus_read_tuple_conf(device_t cbdev, device_t child, uint32_t start,
  382     uint32_t *off, int *tupleid, int *len, uint8_t *tupledata)
  383 {
  384         int i, j;
  385         uint32_t e;
  386         uint32_t loc;
  387 
  388         loc = start + *off;
  389 
  390         e = pci_read_config(child, loc & ~0x3, 4);
  391         e >>= 8 * (loc & 0x3);
  392         *len = 0;
  393         for (i = loc, j = -2; j < *len; j++, i++) {
  394                 if ((i & 0x3) == 0)
  395                         e = pci_read_config(child, i, 4);
  396                 if (j == -2)
  397                         *tupleid = 0xff & e;
  398                 else if (j == -1)
  399                         *len = 0xff & e;
  400                 else
  401                         tupledata[j] = 0xff & e;
  402                 e >>= 8;
  403         }
  404         *off += *len + 2;
  405         return (0);
  406 }
  407 
  408 /*
  409  * Read the CIS data out of memory.  We indirect through the bus space
  410  * routines to ensure proper byte ordering conversions when necessary.
  411  */
  412 static int
  413 cardbus_read_tuple_mem(device_t cbdev, struct resource *res, uint32_t start,
  414     uint32_t *off, int *tupleid, int *len, uint8_t *tupledata)
  415 {
  416         int ret;
  417 
  418         *tupleid = bus_read_1(res, start + *off);
  419         *len = bus_read_1(res, start + *off + 1);
  420         bus_read_region_1(res, *off + start + 2, tupledata, *len);
  421         ret = 0;
  422         *off += *len + 2;
  423         return (ret);
  424 }
  425 
  426 static int
  427 cardbus_read_tuple(device_t cbdev, device_t child, struct resource *res,
  428     uint32_t start, uint32_t *off, int *tupleid, int *len,
  429     uint8_t *tupledata)
  430 {
  431         if (res == CIS_CONFIG_SPACE)
  432                 return (cardbus_read_tuple_conf(cbdev, child, start, off,
  433                     tupleid, len, tupledata));
  434         return (cardbus_read_tuple_mem(cbdev, res, start, off, tupleid, len,
  435             tupledata));
  436 }
  437 
  438 static void
  439 cardbus_read_tuple_finish(device_t cbdev, device_t child, int rid,
  440     struct resource *res)
  441 {
  442         if (res != CIS_CONFIG_SPACE) {
  443                 bus_release_resource(child, SYS_RES_MEMORY, rid, res);
  444                 bus_delete_resource(child, SYS_RES_MEMORY, rid);
  445         }
  446 }
  447 
  448 static struct resource *
  449 cardbus_read_tuple_init(device_t cbdev, device_t child, uint32_t *start,
  450     int *rid)
  451 {
  452         struct resource *res;
  453         uint32_t space;
  454 
  455         space = *start & PCIM_CIS_ASI_MASK;
  456         switch (space) {
  457         case PCIM_CIS_ASI_CONFIG:
  458                 DEVPRINTF((cbdev, "CIS in PCI config space\n"));
  459                 /* CIS in PCI config space need no initialization */
  460                 return (CIS_CONFIG_SPACE);
  461         case PCIM_CIS_ASI_BAR0:
  462         case PCIM_CIS_ASI_BAR1:
  463         case PCIM_CIS_ASI_BAR2:
  464         case PCIM_CIS_ASI_BAR3:
  465         case PCIM_CIS_ASI_BAR4:
  466         case PCIM_CIS_ASI_BAR5:
  467                 *rid = PCIR_BAR(space - PCIM_CIS_ASI_BAR0);
  468                 DEVPRINTF((cbdev, "CIS in BAR %#x\n", *rid));
  469                 break;
  470         case PCIM_CIS_ASI_ROM:
  471                 *rid = PCIR_BIOS;
  472                 DEVPRINTF((cbdev, "CIS in option rom\n"));
  473                 break;
  474         default:
  475                 device_printf(cbdev, "Unable to read CIS: Unknown space: %d\n",
  476                     space);
  477                 return (NULL);
  478         }
  479 
  480         /* allocate the memory space to read CIS */
  481         res = bus_alloc_resource_any(child, SYS_RES_MEMORY, rid,
  482             rman_make_alignment_flags(4096) | RF_ACTIVE);
  483         if (res == NULL) {
  484                 device_printf(cbdev, "Unable to allocate resource "
  485                     "to read CIS.\n");
  486                 return (NULL);
  487         }
  488         DEVPRINTF((cbdev, "CIS Mapped to %#jx\n",
  489             rman_get_start(res)));
  490 
  491         /* Flip to the right ROM image if CIS is in ROM */
  492         if (space == PCIM_CIS_ASI_ROM) {
  493                 uint32_t imagesize;
  494                 uint32_t imagebase = 0;
  495                 uint32_t pcidata;
  496                 uint16_t romsig;
  497                 int romnum = 0;
  498                 int imagenum;
  499 
  500                 imagenum = (*start & PCIM_CIS_ROM_MASK) >> 28;
  501                 for (romnum = 0;; romnum++) {
  502                         romsig = bus_read_2(res,
  503                             imagebase + CARDBUS_EXROM_SIGNATURE);
  504                         if (romsig != 0xaa55) {
  505                                 device_printf(cbdev, "Bad header in rom %d: "
  506                                     "[%x] %04x\n", romnum, imagebase +
  507                                     CARDBUS_EXROM_SIGNATURE, romsig);
  508                                 cardbus_read_tuple_finish(cbdev, child, *rid,
  509                                     res);
  510                                 *rid = 0;
  511                                 return (NULL);
  512                         }
  513 
  514                         /*
  515                          * If this was the Option ROM image that we were
  516                          * looking for, then we are done.
  517                          */
  518                         if (romnum == imagenum)
  519                                 break;
  520 
  521                         /* Find out where the next Option ROM image is */
  522                         pcidata = imagebase + bus_read_2(res,
  523                             imagebase + CARDBUS_EXROM_DATA_PTR);
  524                         imagesize = bus_read_2(res,
  525                             pcidata + CARDBUS_EXROM_DATA_IMAGE_LENGTH);
  526 
  527                         if (imagesize == 0) {
  528                                 /*
  529                                  * XXX some ROMs seem to have this as zero,
  530                                  * can we assume this means 1 block?
  531                                  */
  532                                 device_printf(cbdev, "Warning, size of Option "
  533                                     "ROM image %d is 0 bytes, assuming 512 "
  534                                     "bytes.\n", romnum);
  535                                 imagesize = 1;
  536                         }
  537 
  538                         /* Image size is in 512 byte units */
  539                         imagesize <<= 9;
  540 
  541                         if ((bus_read_1(res, pcidata +
  542                             CARDBUS_EXROM_DATA_INDICATOR) & 0x80) != 0) {
  543                                 device_printf(cbdev, "Cannot find CIS in "
  544                                     "Option ROM\n");
  545                                 cardbus_read_tuple_finish(cbdev, child, *rid,
  546                                     res);
  547                                 *rid = 0;
  548                                 return (NULL);
  549                         }
  550                         imagebase += imagesize;
  551                 }
  552                 *start = imagebase + (*start & PCIM_CIS_ADDR_MASK);
  553         } else {
  554                 *start = *start & PCIM_CIS_ADDR_MASK;
  555         }
  556         DEVPRINTF((cbdev, "CIS offset is %#x\n", *start));
  557 
  558         return (res);
  559 }
  560 
  561 /*
  562  * Dispatch the right handler function per tuple
  563  */
  564 
  565 static int
  566 decode_tuple(device_t cbdev, device_t child, int tupleid, int len,
  567     uint8_t *tupledata, uint32_t start, uint32_t *off,
  568     struct tuple_callbacks *callbacks, void *argp)
  569 {
  570         int i;
  571         for (i = 0; callbacks[i].id != CISTPL_GENERIC; i++) {
  572                 if (tupleid == callbacks[i].id)
  573                         return (callbacks[i].func(cbdev, child, tupleid, len,
  574                             tupledata, start, off, &callbacks[i], argp));
  575         }
  576         return (callbacks[i].func(cbdev, child, tupleid, len,
  577             tupledata, start, off, NULL, argp));
  578 }
  579 
  580 int
  581 cardbus_parse_cis(device_t cbdev, device_t child,
  582     struct tuple_callbacks *callbacks, void *argp)
  583 {
  584         uint8_t tupledata[MAXTUPLESIZE];
  585         int tupleid = CISTPL_NULL;
  586         int len;
  587         int expect_linktarget;
  588         uint32_t start, off;
  589         struct resource *res;
  590         int rid;
  591 
  592         bzero(tupledata, MAXTUPLESIZE);
  593         expect_linktarget = TRUE;
  594         if ((start = pci_read_config(child, PCIR_CIS, 4)) == 0) {
  595                 DEVPRINTF((cbdev, "Warning: CIS pointer is 0: (no CIS)\n"));
  596                 return (0);
  597         }
  598         DEVPRINTF((cbdev, "CIS pointer is %#x\n", start));
  599         off = 0;
  600         res = cardbus_read_tuple_init(cbdev, child, &start, &rid);
  601         if (res == NULL) {
  602                 device_printf(cbdev, "Unable to allocate resources for CIS\n");
  603                 return (ENXIO);
  604         }
  605 
  606         do {
  607                 if (cardbus_read_tuple(cbdev, child, res, start, &off,
  608                     &tupleid, &len, tupledata) != 0) {
  609                         device_printf(cbdev, "Failed to read CIS.\n");
  610                         cardbus_read_tuple_finish(cbdev, child, rid, res);
  611                         return (ENXIO);
  612                 }
  613 
  614                 if (expect_linktarget && tupleid != CISTPL_LINKTARGET) {
  615                         device_printf(cbdev, "Expecting link target, got 0x%x\n",
  616                             tupleid);
  617                         cardbus_read_tuple_finish(cbdev, child, rid, res);
  618                         return (EINVAL);
  619                 }
  620                 expect_linktarget = decode_tuple(cbdev, child, tupleid, len,
  621                     tupledata, start, &off, callbacks, argp);
  622                 if (expect_linktarget != 0) {
  623                         device_printf(cbdev, "Parsing failed with %d\n",
  624                             expect_linktarget);
  625                         cardbus_read_tuple_finish(cbdev, child, rid, res);
  626                         return (expect_linktarget);
  627                 }
  628         } while (tupleid != CISTPL_END);
  629         cardbus_read_tuple_finish(cbdev, child, rid, res);
  630         return (0);
  631 }
  632 
  633 int
  634 cardbus_do_cis(device_t cbdev, device_t child)
  635 {
  636         struct tuple_callbacks init_callbacks[] = {
  637                 MAKETUPLE(LONGLINK_CB,          unhandled),
  638                 MAKETUPLE(INDIRECT,             unhandled),
  639                 MAKETUPLE(LONGLINK_MFC,         unhandled),
  640                 MAKETUPLE(BAR,                  bar),
  641                 MAKETUPLE(LONGLINK_A,           unhandled),
  642                 MAKETUPLE(LONGLINK_C,           unhandled),
  643                 MAKETUPLE(LINKTARGET,           linktarget),
  644                 MAKETUPLE(VERS_1,               vers_1),
  645                 MAKETUPLE(MANFID,               manfid),
  646                 MAKETUPLE(FUNCID,               funcid),
  647                 MAKETUPLE(FUNCE,                funce),
  648                 MAKETUPLE(END,                  end),
  649                 MAKETUPLE(GENERIC,              generic),
  650         };
  651 
  652         return (cardbus_parse_cis(cbdev, child, init_callbacks, NULL));
  653 }

Cache object: 202083ada541325356c1b03291b3344b


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