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/pccard/pccard_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 /*      $NetBSD: pcmcia_cis.c,v 1.10 1998/12/29 09:03:15 marc Exp $     */
    2 /* $FreeBSD$ */
    3 
    4 /*
    5  * Copyright (c) 1997 Marc Horowitz.  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  * 3. All advertising materials mentioning features or use of this software
   16  *    must display the following acknowledgement:
   17  *      This product includes software developed by Marc Horowitz.
   18  * 4. The name of the author may not be used to endorse or promote products
   19  *    derived from this software without specific prior written permission.
   20  *
   21  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
   22  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   23  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
   24  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
   25  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
   26  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
   27  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
   28  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
   29  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
   30  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   31  */
   32 
   33 #include <sys/param.h>
   34 #include <sys/systm.h>
   35 #include <sys/malloc.h>
   36 #include <sys/module.h>
   37 #include <sys/kernel.h>
   38 #include <sys/queue.h>
   39 #include <sys/types.h>
   40 
   41 #include <sys/bus.h>
   42 #include <machine/bus.h>
   43 #include <sys/rman.h>
   44 #include <machine/resource.h>
   45 
   46 #include <dev/pccard/pccardreg.h>
   47 #include <dev/pccard/pccardvar.h>
   48 
   49 #include "card_if.h"
   50 
   51 #define PCCARDCISDEBUG
   52 #ifdef PCCARDCISDEBUG
   53 int     pccardcis_debug = 1;
   54 #define DPRINTF(arg) if (pccardcis_debug) printf arg
   55 #define DEVPRINTF(arg) if (pccardcis_debug) device_printf arg
   56 #else
   57 #define DPRINTF(arg)
   58 #define DEVPRINTF(arg)
   59 #endif
   60 
   61 #define PCCARD_CIS_SIZE         1024
   62 
   63 struct cis_state {
   64         int     count;
   65         int     gotmfc;
   66         struct pccard_config_entry temp_cfe;
   67         struct pccard_config_entry *default_cfe;
   68         struct pccard_card *card;
   69         struct pccard_function *pf;
   70 };
   71 
   72 int     pccard_parse_cis_tuple(struct pccard_tuple *, void *);
   73 
   74 void
   75 pccard_read_cis(struct pccard_softc *sc)
   76 {
   77         struct cis_state state;
   78 
   79         state.count = 0;
   80         state.gotmfc = 0;
   81 
   82         state.card = &sc->card;
   83 
   84         state.card->error = 0;
   85         state.card->cis1_major = -1;
   86         state.card->cis1_minor = -1;
   87         state.card->cis1_info[0] = NULL;
   88         state.card->cis1_info[1] = NULL;
   89         state.card->cis1_info[2] = NULL;
   90         state.card->cis1_info[3] = NULL;
   91         state.card->manufacturer = PCCARD_VENDOR_INVALID;
   92         state.card->product = PCCARD_PRODUCT_INVALID;
   93         STAILQ_INIT(&state.card->pf_head);
   94 
   95         state.pf = NULL;
   96 
   97 printf("Calling scan_cis\n");
   98 
   99         if (pccard_scan_cis(sc->dev, pccard_parse_cis_tuple,
  100             &state) == -1)
  101                 state.card->error++;
  102 }
  103 
  104 int
  105 pccard_scan_cis(device_t dev, int (*fct)(struct pccard_tuple *, void *),
  106         void *arg)
  107 {
  108         struct resource *res;
  109         int rid;
  110         struct pccard_tuple tuple;
  111         int longlink_present;
  112         int longlink_common;
  113         u_long longlink_addr;
  114         int mfc_count;
  115         int mfc_index;
  116         struct {
  117                 int     common;
  118                 u_long  addr;
  119         } mfc[256 / 5];
  120         int ret;
  121 
  122         ret = 0;
  123 
  124         /* allocate some memory */
  125 
  126         rid = 0;
  127         res = bus_alloc_resource(dev, SYS_RES_MEMORY, &rid, 0, ~0, 
  128             PCCARD_CIS_SIZE, RF_ACTIVE);
  129         if (res == NULL) {
  130                 device_printf(dev, "can't alloc memory to read attributes\n");
  131                 return -1;
  132         }
  133         CARD_SET_RES_FLAGS(device_get_parent(dev), dev, SYS_RES_MEMORY,
  134             rid, PCCARD_A_MEM_ATTR);
  135         tuple.memt = rman_get_bustag(res);
  136         tuple.memh = rman_get_bushandle(res);
  137         tuple.ptr = 0;
  138 
  139         DPRINTF(("cis mem map %x\n", (unsigned int) tuple.memh));
  140 
  141         tuple.mult = 2;
  142 
  143         longlink_present = 1;
  144         longlink_common = 1;
  145         longlink_addr = 0;
  146 
  147         mfc_count = 0;
  148         mfc_index = 0;
  149 
  150         DEVPRINTF((dev, "CIS tuple chain:\n"));
  151 
  152         while (1) {
  153                 while (1) {
  154                         /* get the tuple code */
  155 
  156                         tuple.code = pccard_cis_read_1(&tuple, tuple.ptr);
  157 
  158                         /* two special-case tuples */
  159 
  160                         if (tuple.code == PCCARD_CISTPL_NULL) {
  161                                 DPRINTF(("CISTPL_NONE\n 00\n"));
  162                                 tuple.ptr++;
  163                                 continue;
  164                         } else if (tuple.code == PCCARD_CISTPL_END) {
  165                                 DPRINTF(("CISTPL_END\n ff\n"));
  166                                 /* Call the function for the END tuple, since
  167                                    the CIS semantics depend on it */
  168                                 if ((*fct) (&tuple, arg)) {
  169                                         ret = 1;
  170                                         goto done;
  171                                 }
  172                                 ret = 1; goto done; /* XXX IMP XXX */
  173                                 tuple.ptr++;
  174                                 break;
  175                         }
  176                         /* now all the normal tuples */
  177 
  178                         tuple.length = pccard_cis_read_1(&tuple, tuple.ptr + 1);
  179                         switch (tuple.code) {
  180                         case PCCARD_CISTPL_LONGLINK_A:
  181                         case PCCARD_CISTPL_LONGLINK_C:
  182                                 if (tuple.length < 4) {
  183                                         DPRINTF(("CISTPL_LONGLINK_%s too "
  184                                             "short %d\n",
  185                                             longlink_common ? "C" : "A",
  186                                             tuple.length));
  187                                         break;
  188                                 }
  189                                 longlink_present = 1;
  190                                 longlink_common = (tuple.code ==
  191                                     PCCARD_CISTPL_LONGLINK_C) ? 1 : 0;
  192                                 longlink_addr = pccard_tuple_read_4(&tuple, 0);
  193                                 DPRINTF(("CISTPL_LONGLINK_%s %lx\n",
  194                                     longlink_common ? "C" : "A",
  195                                     longlink_addr));
  196                                 break;
  197                         case PCCARD_CISTPL_NO_LINK:
  198                                 longlink_present = 0;
  199                                 DPRINTF(("CISTPL_NO_LINK\n"));
  200                                 break;
  201                         case PCCARD_CISTPL_CHECKSUM:
  202                                 if (tuple.length < 5) {
  203                                         DPRINTF(("CISTPL_CHECKSUM too "
  204                                             "short %d\n", tuple.length));
  205                                         break;
  206                                 } {
  207                                         int16_t offset;
  208                                         u_long addr, length;
  209                                         u_int cksum, sum;
  210                                         int i;
  211 
  212                                         *((u_int16_t *) & offset) =
  213                                             pccard_tuple_read_2(&tuple, 0);
  214                                         length = pccard_tuple_read_2(&tuple, 2);
  215                                         cksum = pccard_tuple_read_1(&tuple, 4);
  216 
  217                                         addr = tuple.ptr + offset;
  218 
  219                                         DPRINTF(("CISTPL_CHECKSUM addr=%lx "
  220                                             "len=%lx cksum=%x",
  221                                             addr, length, cksum));
  222 
  223                                         /*
  224                                          * XXX do more work to deal with
  225                                          * distant regions
  226                                          */
  227                                         if ((addr >= PCCARD_CIS_SIZE) ||
  228                                             ((addr + length) < 0) ||
  229                                             ((addr + length) >=
  230                                               PCCARD_CIS_SIZE)) {
  231                                                 DPRINTF((" skipped, "
  232                                                     "too distant\n"));
  233                                                 break;
  234                                         }
  235                                         sum = 0;
  236                                         for (i = 0; i < length; i++)
  237                                                 sum +=
  238                                                     bus_space_read_1(tuple.memt,
  239                                                     tuple.memh,
  240                                                     addr + tuple.mult * i);
  241                                         if (cksum != (sum & 0xff)) {
  242                                                 DPRINTF((" failed sum=%x\n",
  243                                                     sum));
  244                                                 device_printf(dev, 
  245                                                     "CIS checksum failed\n");
  246 #if 0
  247                                                 /*
  248                                                  * XXX Some working cards have
  249                                                  * XXX bad checksums!!
  250                                                  */
  251                                                 ret = -1;
  252 #endif
  253                                         } else {
  254                                                 DPRINTF((" ok\n"));
  255                                         }
  256                                 }
  257                                 break;
  258                         case PCCARD_CISTPL_LONGLINK_MFC:
  259                                 if (tuple.length < 1) {
  260                                         DPRINTF(("CISTPL_LONGLINK_MFC too "
  261                                             "short %d\n", tuple.length));
  262                                         break;
  263                                 }
  264                                 /*
  265                                  * this is kind of ad hoc, as I don't have
  266                                  * any real documentation
  267                                  */
  268                                 {
  269                                         int i;
  270 
  271                                         mfc_count =
  272                                             pccard_tuple_read_1(&tuple, 0);
  273                                         DPRINTF(("CISTPL_LONGLINK_MFC %d",
  274                                             mfc_count));
  275                                         for (i = 0; i < mfc_count; i++) {
  276                                                 mfc[i].common =
  277                                                     (pccard_tuple_read_1(&tuple,
  278                                                     1 + 5 * i) ==
  279                                                     PCCARD_MFC_MEM_COMMON) ?
  280                                                     1 : 0;
  281                                                 mfc[i].addr =
  282                                                     pccard_tuple_read_4(&tuple,
  283                                                     1 + 5 * i + 1);
  284                                                 DPRINTF((" %s:%lx",
  285                                                     mfc[i].common ? "common" :
  286                                                     "attr", mfc[i].addr));
  287                                         }
  288                                         DPRINTF(("\n"));
  289                                 }
  290                                 /*
  291                                  * for LONGLINK_MFC, fall through to the
  292                                  * function.  This tuple has structural and
  293                                  * semantic content.
  294                                  */
  295                         default:
  296                                 {
  297                                         if ((*fct) (&tuple, arg)) {
  298                                                 ret = 1;
  299                                                 goto done;
  300                                         }
  301                                 }
  302                                 break;
  303                         }       /* switch */
  304 #ifdef PCCARDCISDEBUG
  305                         /* print the tuple */
  306                         {
  307                                 int i;
  308 
  309                                 DPRINTF((" %02x %02x", tuple.code,
  310                                     tuple.length));
  311 
  312                                 for (i = 0; i < tuple.length; i++) {
  313                                         DPRINTF((" %02x",
  314                                             pccard_tuple_read_1(&tuple, i)));
  315                                         if ((i % 16) == 13)
  316                                                 DPRINTF(("\n"));
  317                                 }
  318                                 if ((i % 16) != 14)
  319                                         DPRINTF(("\n"));
  320                         }
  321 #endif
  322                         /* skip to the next tuple */
  323                         tuple.ptr += 2 + tuple.length;
  324                 }
  325 
  326 #ifdef XXX      /* I'm not up to this tonight, need to implement new API */
  327                 /* to deal with moving windows and such.  At least that's */
  328                 /* what it appears at this instant */
  329 
  330                 /*
  331                  * the chain is done.  Clean up and move onto the next one,
  332                  * if any.  The loop is here in the case that there is an MFC
  333                  * card with no longlink (which defaults to existing, == 0).
  334                  * In general, this means that if one pointer fails, it will
  335                  * try the next one, instead of just bailing.
  336                  */
  337 
  338                 while (1) {
  339                         pccard_chip_mem_unmap(pct, pch, window);
  340 
  341                         if (longlink_present) {
  342                                 /*
  343                                  * if the longlink is to attribute memory,
  344                                  * then it is unindexed.  That is, if the
  345                                  * link value is 0x100, then the actual
  346                                  * memory address is 0x200.  This means that
  347                                  * we need to multiply by 2 before calling
  348                                  * mem_map, and then divide the resulting ptr
  349                                  * by 2 after.
  350                                  */
  351 
  352                                 if (!longlink_common)
  353                                         longlink_addr *= 2;
  354 
  355                                 pccard_chip_mem_map(pct, pch, longlink_common ?
  356                                     PCCARD_MEM_COMMON : PCCARD_MEM_ATTR,
  357                                     longlink_addr, PCCARD_CIS_SIZE,
  358                                     &pcmh, &tuple.ptr, &window);
  359 
  360                                 if (!longlink_common)
  361                                         tuple.ptr /= 2;
  362                                 DPRINTF(("cis mem map %x\n",
  363                                     (unsigned int) tuple.memh));
  364                                 tuple.mult = longlink_common ? 1 : 2;
  365                                 longlink_present = 0;
  366                                 longlink_common = 1;
  367                                 longlink_addr = 0;
  368                         } else if (mfc_count && (mfc_index < mfc_count)) {
  369                                 if (!mfc[mfc_index].common)
  370                                         mfc[mfc_index].addr *= 2;
  371 
  372                                 pccard_chip_mem_map(pct, pch,
  373                                     mfc[mfc_index].common ?
  374                                     PCCARD_MEM_COMMON : PCCARD_MEM_ATTR,
  375                                     mfc[mfc_index].addr, PCCARD_CIS_SIZE,
  376                                     &pcmh, &tuple.ptr, &window);
  377 
  378                                 if (!mfc[mfc_index].common)
  379                                         tuple.ptr /= 2;
  380                                 DPRINTF(("cis mem map %x\n",
  381                                     (unsigned int) tuple.memh));
  382                                 /* set parse state, and point at the next one */
  383 
  384                                 tuple.mult = mfc[mfc_index].common ? 1 : 2;
  385 
  386                                 mfc_index++;
  387                         } else {
  388                                 goto done;
  389                         }
  390 
  391                         /* make sure that the link is valid */
  392                         tuple.code = pccard_cis_read_1(&tuple, tuple.ptr);
  393                         if (tuple.code != PCCARD_CISTPL_LINKTARGET) {
  394                                 DPRINTF(("CISTPL_LINKTARGET expected, "
  395                                     "code %02x observed\n", tuple.code));
  396                                 continue;
  397                         }
  398                         tuple.length = pccard_cis_read_1(&tuple, tuple.ptr + 1);
  399                         if (tuple.length < 3) {
  400                                 DPRINTF(("CISTPL_LINKTARGET too short %d\n",
  401                                     tuple.length));
  402                                 continue;
  403                         }
  404                         if ((pccard_tuple_read_1(&tuple, 0) != 'C') ||
  405                             (pccard_tuple_read_1(&tuple, 1) != 'I') ||
  406                             (pccard_tuple_read_1(&tuple, 2) != 'S')) {
  407                                 DPRINTF(("CISTPL_LINKTARGET magic "
  408                                     "%02x%02x%02x incorrect\n",
  409                                     pccard_tuple_read_1(&tuple, 0),
  410                                     pccard_tuple_read_1(&tuple, 1),
  411                                     pccard_tuple_read_1(&tuple, 2)));
  412                                 continue;
  413                         }
  414                         tuple.ptr += 2 + tuple.length;
  415 
  416                         break;
  417                 }
  418 #endif /* XXX */
  419         }
  420 
  421 done:
  422         bus_release_resource(dev, SYS_RES_MEMORY, rid, res);
  423 
  424         return (ret);
  425 }
  426 
  427 /* XXX this is incredibly verbose.  Not sure what trt is */
  428 
  429 void
  430 pccard_print_cis(device_t dev)
  431 {
  432         struct pccard_softc *sc = (struct pccard_softc *) device_get_softc(dev);
  433         struct pccard_card *card = &sc->card;
  434         struct pccard_function *pf;
  435         struct pccard_config_entry *cfe;
  436         int i;
  437 
  438         device_printf(dev, "CIS version ");
  439         if (card->cis1_major == 4) {
  440                 if (card->cis1_minor == 0)
  441                         printf("PCCARD 1.0\n");
  442                 else if (card->cis1_minor == 1)
  443                         printf("PCCARD 2.0 or 2.1\n");
  444         } else if (card->cis1_major >= 5)
  445                 printf("PC Card Standard %d.%d\n", card->cis1_major, card->cis1_minor);
  446         else
  447                 printf("unknown (major=%d, minor=%d)\n",
  448                     card->cis1_major, card->cis1_minor);
  449 
  450         device_printf(dev, "CIS info: ");
  451         for (i = 0; i < 4; i++) {
  452                 if (card->cis1_info[i] == NULL)
  453                         break;
  454                 if (i)
  455                         printf(", ");
  456                 printf("%s", card->cis1_info[i]);
  457         }
  458         printf("\n");
  459 
  460         device_printf(dev, "Manufacturer code 0x%x, product 0x%x\n",
  461             card->manufacturer, card->product);
  462 
  463         STAILQ_FOREACH(pf, &card->pf_head, pf_list) {
  464                 device_printf(dev, "function %d: ", pf->number);
  465 
  466                 switch (pf->function) {
  467                 case PCCARD_FUNCTION_UNSPEC:
  468                         printf("unspecified");
  469                         break;
  470                 case PCCARD_FUNCTION_MULTIFUNCTION:
  471                         printf("multi-function");
  472                         break;
  473                 case PCCARD_FUNCTION_MEMORY:
  474                         printf("memory");
  475                         break;
  476                 case PCCARD_FUNCTION_SERIAL:
  477                         printf("serial port");
  478                         break;
  479                 case PCCARD_FUNCTION_PARALLEL:
  480                         printf("parallel port");
  481                         break;
  482                 case PCCARD_FUNCTION_DISK:
  483                         printf("fixed disk");
  484                         break;
  485                 case PCCARD_FUNCTION_VIDEO:
  486                         printf("video adapter");
  487                         break;
  488                 case PCCARD_FUNCTION_NETWORK:
  489                         printf("network adapter");
  490                         break;
  491                 case PCCARD_FUNCTION_AIMS:
  492                         printf("auto incrementing mass storage");
  493                         break;
  494                 case PCCARD_FUNCTION_SCSI:
  495                         printf("SCSI bridge");
  496                         break;
  497                 case PCCARD_FUNCTION_SECURITY:
  498                         printf("Security services");
  499                         break;
  500                 case PCCARD_FUNCTION_INSTRUMENT:
  501                         printf("Instrument");
  502                         break;
  503                 default:
  504                         printf("unknown (%d)", pf->function);
  505                         break;
  506                 }
  507 
  508                 printf(", ccr addr %lx mask %lx\n", pf->ccr_base, pf->ccr_mask);
  509 
  510                 STAILQ_FOREACH(cfe, &pf->cfe_head, cfe_list) {
  511                         device_printf(dev, "function %d, config table entry "
  512                             "%d: ", pf->number, cfe->number);
  513 
  514                         switch (cfe->iftype) {
  515                         case PCCARD_IFTYPE_MEMORY:
  516                                 printf("memory card");
  517                                 break;
  518                         case PCCARD_IFTYPE_IO:
  519                                 printf("I/O card");
  520                                 break;
  521                         default:
  522                                 printf("card type unknown");
  523                                 break;
  524                         }
  525 
  526                         printf("; irq mask %x", cfe->irqmask);
  527 
  528                         if (cfe->num_iospace) {
  529                                 printf("; iomask %lx, iospace", cfe->iomask);
  530 
  531                                 for (i = 0; i < cfe->num_iospace; i++) {
  532                                         printf(" %lx", cfe->iospace[i].start);
  533                                         if (cfe->iospace[i].length)
  534                                                 printf("-%lx",
  535                                                     cfe->iospace[i].start +
  536                                                     cfe->iospace[i].length - 1);
  537                                 }
  538                         }
  539                         if (cfe->num_memspace) {
  540                                 printf("; memspace");
  541 
  542                                 for (i = 0; i < cfe->num_memspace; i++) {
  543                                         printf(" %lx",
  544                                             cfe->memspace[i].cardaddr);
  545                                         if (cfe->memspace[i].length)
  546                                                 printf("-%lx",
  547                                                     cfe->memspace[i].cardaddr +
  548                                                     cfe->memspace[i].length - 1);
  549                                         if (cfe->memspace[i].hostaddr)
  550                                                 printf("@%lx",
  551                                                     cfe->memspace[i].hostaddr);
  552                                 }
  553                         }
  554                         if (cfe->maxtwins)
  555                                 printf("; maxtwins %d", cfe->maxtwins);
  556 
  557                         printf(";");
  558 
  559                         if (cfe->flags & PCCARD_CFE_MWAIT_REQUIRED)
  560                                 printf(" mwait_required");
  561                         if (cfe->flags & PCCARD_CFE_RDYBSY_ACTIVE)
  562                                 printf(" rdybsy_active");
  563                         if (cfe->flags & PCCARD_CFE_WP_ACTIVE)
  564                                 printf(" wp_active");
  565                         if (cfe->flags & PCCARD_CFE_BVD_ACTIVE)
  566                                 printf(" bvd_active");
  567                         if (cfe->flags & PCCARD_CFE_IO8)
  568                                 printf(" io8");
  569                         if (cfe->flags & PCCARD_CFE_IO16)
  570                                 printf(" io16");
  571                         if (cfe->flags & PCCARD_CFE_IRQSHARE)
  572                                 printf(" irqshare");
  573                         if (cfe->flags & PCCARD_CFE_IRQPULSE)
  574                                 printf(" irqpulse");
  575                         if (cfe->flags & PCCARD_CFE_IRQLEVEL)
  576                                 printf(" irqlevel");
  577                         if (cfe->flags & PCCARD_CFE_POWERDOWN)
  578                                 printf(" powerdown");
  579                         if (cfe->flags & PCCARD_CFE_READONLY)
  580                                 printf(" readonly");
  581                         if (cfe->flags & PCCARD_CFE_AUDIO)
  582                                 printf(" audio");
  583 
  584                         printf("\n");
  585                 }
  586         }
  587 
  588         if (card->error)
  589                 device_printf(dev, "%d errors found while parsing CIS\n",
  590                     card->error);
  591 }
  592 
  593 int
  594 pccard_parse_cis_tuple(struct pccard_tuple *tuple, void *arg)
  595 {
  596         /* most of these are educated guesses */
  597         static struct pccard_config_entry init_cfe = {
  598                 -1, PCCARD_CFE_RDYBSY_ACTIVE | PCCARD_CFE_WP_ACTIVE |
  599                 PCCARD_CFE_BVD_ACTIVE, PCCARD_IFTYPE_MEMORY,
  600         };
  601 
  602         struct cis_state *state = arg;
  603 
  604         switch (tuple->code) {
  605         case PCCARD_CISTPL_END:
  606                 /* if we've seen a LONGLINK_MFC, and this is the first
  607                  * END after it, reset the function list.  
  608                  *
  609                  * XXX This might also be the right place to start a
  610                  * new function, but that assumes that a function
  611                  * definition never crosses any longlink, and I'm not
  612                  * sure about that.  This is probably safe for MFC
  613                  * cards, but what we have now isn't broken, so I'd
  614                  * rather not change it.
  615                  */
  616                 if (state->gotmfc == 1) {
  617                         struct pccard_function *pf, *pfnext;
  618 
  619                         for (pf = STAILQ_FIRST(&state->card->pf_head); 
  620                              pf != NULL; pf = pfnext) {
  621                                 pfnext = STAILQ_NEXT(pf, pf_list);
  622                                 free(pf, M_DEVBUF);
  623                         }
  624 
  625                         STAILQ_INIT(&state->card->pf_head);
  626 
  627                         state->count = 0;
  628                         state->gotmfc = 2;
  629                         state->pf = NULL;
  630                 }
  631                 break;
  632         case PCCARD_CISTPL_LONGLINK_MFC:
  633                 /*
  634                  * this tuple's structure was dealt with in scan_cis.  here,
  635                  * record the fact that the MFC tuple was seen, so that
  636                  * functions declared before the MFC link can be cleaned
  637                  * up.
  638                  */
  639                 state->gotmfc = 1;
  640                 break;
  641 #ifdef PCCARDCISDEBUG
  642         case PCCARD_CISTPL_DEVICE:
  643         case PCCARD_CISTPL_DEVICE_A:
  644                 {
  645                         u_int reg, dtype, dspeed;
  646 
  647                         reg = pccard_tuple_read_1(tuple, 0);
  648                         dtype = reg & PCCARD_DTYPE_MASK;
  649                         dspeed = reg & PCCARD_DSPEED_MASK;
  650 
  651                         DPRINTF(("CISTPL_DEVICE%s type=",
  652                         (tuple->code == PCCARD_CISTPL_DEVICE) ? "" : "_A"));
  653                         switch (dtype) {
  654                         case PCCARD_DTYPE_NULL:
  655                                 DPRINTF(("null"));
  656                                 break;
  657                         case PCCARD_DTYPE_ROM:
  658                                 DPRINTF(("rom"));
  659                                 break;
  660                         case PCCARD_DTYPE_OTPROM:
  661                                 DPRINTF(("otprom"));
  662                                 break;
  663                         case PCCARD_DTYPE_EPROM:
  664                                 DPRINTF(("eprom"));
  665                                 break;
  666                         case PCCARD_DTYPE_EEPROM:
  667                                 DPRINTF(("eeprom"));
  668                                 break;
  669                         case PCCARD_DTYPE_FLASH:
  670                                 DPRINTF(("flash"));
  671                                 break;
  672                         case PCCARD_DTYPE_SRAM:
  673                                 DPRINTF(("sram"));
  674                                 break;
  675                         case PCCARD_DTYPE_DRAM:
  676                                 DPRINTF(("dram"));
  677                                 break;
  678                         case PCCARD_DTYPE_FUNCSPEC:
  679                                 DPRINTF(("funcspec"));
  680                                 break;
  681                         case PCCARD_DTYPE_EXTEND:
  682                                 DPRINTF(("extend"));
  683                                 break;
  684                         default:
  685                                 DPRINTF(("reserved"));
  686                                 break;
  687                         }
  688                         DPRINTF((" speed="));
  689                         switch (dspeed) {
  690                         case PCCARD_DSPEED_NULL:
  691                                 DPRINTF(("null"));
  692                                 break;
  693                         case PCCARD_DSPEED_250NS:
  694                                 DPRINTF(("250ns"));
  695                                 break;
  696                         case PCCARD_DSPEED_200NS:
  697                                 DPRINTF(("200ns"));
  698                                 break;
  699                         case PCCARD_DSPEED_150NS:
  700                                 DPRINTF(("150ns"));
  701                                 break;
  702                         case PCCARD_DSPEED_100NS:
  703                                 DPRINTF(("100ns"));
  704                                 break;
  705                         case PCCARD_DSPEED_EXT:
  706                                 DPRINTF(("ext"));
  707                                 break;
  708                         default:
  709                                 DPRINTF(("reserved"));
  710                                 break;
  711                         }
  712                 }
  713                 DPRINTF(("\n"));
  714                 break;
  715 #endif
  716         case PCCARD_CISTPL_VERS_1:
  717                 if (tuple->length < 6) {
  718                         DPRINTF(("CISTPL_VERS_1 too short %d\n",
  719                             tuple->length));
  720                         break;
  721                 } {
  722                         int start, i, ch, count;
  723 
  724                         state->card->cis1_major = pccard_tuple_read_1(tuple, 0);
  725                         state->card->cis1_minor = pccard_tuple_read_1(tuple, 1);
  726 
  727                         for (count = 0, start = 0, i = 0;
  728                             (count < 4) && ((i + 4) < 256); i++) {
  729                                 ch = pccard_tuple_read_1(tuple, 2 + i);
  730                                 if (ch == 0xff)
  731                                         break;
  732                                 state->card->cis1_info_buf[i] = ch;
  733                                 if (ch == 0) {
  734                                         state->card->cis1_info[count] =
  735                                             state->card->cis1_info_buf + start;
  736                                         start = i + 1;
  737                                         count++;
  738                                 }
  739                         }
  740                         DPRINTF(("CISTPL_VERS_1\n"));
  741                 }
  742                 break;
  743         case PCCARD_CISTPL_MANFID:
  744                 if (tuple->length < 4) {
  745                         DPRINTF(("CISTPL_MANFID too short %d\n",
  746                             tuple->length));
  747                         break;
  748                 }
  749                 state->card->manufacturer = pccard_tuple_read_2(tuple, 0);
  750                 state->card->product = pccard_tuple_read_2(tuple, 2);
  751                 DPRINTF(("CISTPL_MANFID\n"));
  752                 break;
  753         case PCCARD_CISTPL_FUNCID:
  754                 if (tuple->length < 1) {
  755                         DPRINTF(("CISTPL_FUNCID too short %d\n",
  756                             tuple->length));
  757                         break;
  758                 }
  759                 if ((state->pf == NULL) || (state->gotmfc == 2)) {
  760                         state->pf = malloc(sizeof(*state->pf), M_DEVBUF,
  761                             M_NOWAIT);
  762                         bzero(state->pf, sizeof(*state->pf));
  763                         state->pf->number = state->count++;
  764                         state->pf->last_config_index = -1;
  765                         STAILQ_INIT(&state->pf->cfe_head);
  766 
  767                         STAILQ_INSERT_TAIL(&state->card->pf_head, state->pf,
  768                             pf_list);
  769                 }
  770                 state->pf->function = pccard_tuple_read_1(tuple, 0);
  771 
  772                 DPRINTF(("CISTPL_FUNCID\n"));
  773                 break;
  774         case PCCARD_CISTPL_CONFIG:
  775                 if (tuple->length < 3) {
  776                         DPRINTF(("CISTPL_CONFIG too short %d\n",
  777                             tuple->length));
  778                         break;
  779                 } {
  780                         u_int reg, rasz, rmsz, rfsz;
  781                         int i;
  782 
  783                         reg = pccard_tuple_read_1(tuple, 0);
  784                         rasz = 1 + ((reg & PCCARD_TPCC_RASZ_MASK) >>
  785                             PCCARD_TPCC_RASZ_SHIFT);
  786                         rmsz = 1 + ((reg & PCCARD_TPCC_RMSZ_MASK) >>
  787                             PCCARD_TPCC_RMSZ_SHIFT);
  788                         rfsz = ((reg & PCCARD_TPCC_RFSZ_MASK) >>
  789                             PCCARD_TPCC_RFSZ_SHIFT);
  790 
  791                         if (tuple->length < (rasz + rmsz + rfsz)) {
  792                                 DPRINTF(("CISTPL_CONFIG (%d,%d,%d) too "
  793                                     "short %d\n", rasz, rmsz, rfsz,
  794                                     tuple->length));
  795                                 break;
  796                         }
  797                         if (state->pf == NULL) {
  798                                 state->pf = malloc(sizeof(*state->pf),
  799                                     M_DEVBUF, M_NOWAIT);
  800                                 bzero(state->pf, sizeof(*state->pf));
  801                                 state->pf->number = state->count++;
  802                                 state->pf->last_config_index = -1;
  803                                 STAILQ_INIT(&state->pf->cfe_head);
  804 
  805                                 STAILQ_INSERT_TAIL(&state->card->pf_head,
  806                                     state->pf, pf_list);
  807 
  808                                 state->pf->function = PCCARD_FUNCTION_UNSPEC;
  809                         }
  810                         state->pf->last_config_index =
  811                             pccard_tuple_read_1(tuple, 1);
  812 
  813                         state->pf->ccr_base = 0;
  814                         for (i = 0; i < rasz; i++)
  815                                 state->pf->ccr_base |=
  816                                     ((pccard_tuple_read_1(tuple, 2 + i)) <<
  817                                     (i * 8));
  818 
  819                         state->pf->ccr_mask = 0;
  820                         for (i = 0; i < rmsz; i++)
  821                                 state->pf->ccr_mask |=
  822                                     ((pccard_tuple_read_1(tuple,
  823                                     2 + rasz + i)) << (i * 8));
  824 
  825                         /* skip the reserved area and subtuples */
  826 
  827                         /* reset the default cfe for each cfe list */
  828                         state->temp_cfe = init_cfe;
  829                         state->default_cfe = &state->temp_cfe;
  830                 }
  831                 DPRINTF(("CISTPL_CONFIG\n"));
  832                 break;
  833         case PCCARD_CISTPL_CFTABLE_ENTRY:
  834                 {
  835                         int idx, i, j;
  836                         u_int reg, reg2;
  837                         u_int intface, def, num;
  838                         u_int power, timing, iospace, irq, memspace, misc;
  839                         struct pccard_config_entry *cfe;
  840 
  841                         idx = 0;
  842 
  843                         reg = pccard_tuple_read_1(tuple, idx);
  844                         idx++;
  845                         intface = reg & PCCARD_TPCE_INDX_INTFACE;
  846                         def = reg & PCCARD_TPCE_INDX_DEFAULT;
  847                         num = reg & PCCARD_TPCE_INDX_NUM_MASK;
  848 
  849                         /*
  850                          * this is a little messy.  Some cards have only a
  851                          * cfentry with the default bit set.  So, as we go
  852                          * through the list, we add new indexes to the queue,
  853                          * and keep a pointer to the last one with the
  854                          * default bit set.  if we see a record with the same
  855                          * index, as the default, we stash the default and
  856                          * replace the queue entry. otherwise, we just add
  857                          * new entries to the queue, pointing the default ptr
  858                          * at them if the default bit is set.  if we get to
  859                          * the end with the default pointer pointing at a
  860                          * record which hasn't had a matching index, that's
  861                          * ok; it just becomes a cfentry like any other.
  862                          */
  863 
  864                         /*
  865                          * if the index in the cis differs from the default
  866                          * cis, create new entry in the queue and start it
  867                          * with the current default
  868                          */
  869                         if (num != state->default_cfe->number) {
  870                                 cfe = (struct pccard_config_entry *)
  871                                     malloc(sizeof(*cfe), M_DEVBUF, M_NOWAIT);
  872 
  873                                 *cfe = *state->default_cfe;
  874 
  875                                 STAILQ_INSERT_TAIL(&state->pf->cfe_head,
  876                                     cfe, cfe_list);
  877 
  878                                 cfe->number = num;
  879 
  880                                 /*
  881                                  * if the default bit is set in the cis, then
  882                                  * point the new default at whatever is being
  883                                  * filled in
  884                                  */
  885                                 if (def)
  886                                         state->default_cfe = cfe;
  887                         } else {
  888                                 /*
  889                                  * the cis index matches the default index,
  890                                  * fill in the default cfentry.  It is
  891                                  * assumed that the cfdefault index is in the
  892                                  * queue.  For it to be otherwise, the cis
  893                                  * index would have to be -1 (initial
  894                                  * condition) which is not possible, or there
  895                                  * would have to be a preceding cis entry
  896                                  * which had the same cis index and had the
  897                                  * default bit unset. Neither condition
  898                                  * should happen.  If it does, this cfentry
  899                                  * is lost (written into temp space), which
  900                                  * is an acceptable failure mode.
  901                                  */
  902 
  903                                 cfe = state->default_cfe;
  904 
  905                                 /*
  906                                  * if the cis entry does not have the default
  907                                  * bit set, copy the default out of the way
  908                                  * first.
  909                                  */
  910                                 if (!def) {
  911                                         state->temp_cfe = *state->default_cfe;
  912                                         state->default_cfe = &state->temp_cfe;
  913                                 }
  914                         }
  915 
  916                         if (intface) {
  917                                 reg = pccard_tuple_read_1(tuple, idx);
  918                                 idx++;
  919                                 if (reg & PCCARD_TPCE_IF_MWAIT)
  920                                         cfe->flags |= PCCARD_CFE_MWAIT_REQUIRED;
  921                                 if (reg & PCCARD_TPCE_IF_RDYBSY)
  922                                         cfe->flags |= PCCARD_CFE_RDYBSY_ACTIVE;
  923                                 if (reg & PCCARD_TPCE_IF_WP)
  924                                         cfe->flags |= PCCARD_CFE_WP_ACTIVE;
  925                                 if (reg & PCCARD_TPCE_IF_BVD)
  926                                         cfe->flags |= PCCARD_CFE_BVD_ACTIVE;
  927                                 cfe->iftype = reg & PCCARD_TPCE_IF_IFTYPE;
  928                         }
  929                         reg = pccard_tuple_read_1(tuple, idx);
  930                         idx++;
  931 
  932                         power = reg & PCCARD_TPCE_FS_POWER_MASK;
  933                         timing = reg & PCCARD_TPCE_FS_TIMING;
  934                         iospace = reg & PCCARD_TPCE_FS_IOSPACE;
  935                         irq = reg & PCCARD_TPCE_FS_IRQ;
  936                         memspace = reg & PCCARD_TPCE_FS_MEMSPACE_MASK;
  937                         misc = reg & PCCARD_TPCE_FS_MISC;
  938 
  939                         if (power) {
  940                                 /* skip over power, don't save */
  941                                 /* for each parameter selection byte */
  942                                 for (i = 0; i < power; i++) {
  943                                         reg = pccard_tuple_read_1(tuple, idx);
  944                                         idx++;
  945                                         /* for each bit */
  946                                         for (j = 0; j < 7; j++) {
  947                                                 /* if the bit is set */
  948                                                 if ((reg >> j) & 0x01) {
  949                                                         /* skip over bytes */
  950                                                         do {
  951                                                                 reg2 = pccard_tuple_read_1(tuple, idx);
  952                                                                 idx++;
  953                                                                 /*
  954                                                                  * until
  955                                                                  * non-extensi
  956                                                                  * on byte
  957                                                                  */
  958                                                         } while (reg2 & 0x80);
  959                                                 }
  960                                         }
  961                                 }
  962                         }
  963                         if (timing) {
  964                                 /* skip over timing, don't save */
  965                                 reg = pccard_tuple_read_1(tuple, idx);
  966                                 idx++;
  967 
  968                                 if ((reg & PCCARD_TPCE_TD_RESERVED_MASK) !=
  969                                     PCCARD_TPCE_TD_RESERVED_MASK)
  970                                         idx++;
  971                                 if ((reg & PCCARD_TPCE_TD_RDYBSY_MASK) !=
  972                                     PCCARD_TPCE_TD_RDYBSY_MASK)
  973                                         idx++;
  974                                 if ((reg & PCCARD_TPCE_TD_WAIT_MASK) !=
  975                                     PCCARD_TPCE_TD_WAIT_MASK)
  976                                         idx++;
  977                         }
  978                         if (iospace) {
  979                                 if (tuple->length <= idx) {
  980                                         DPRINTF(("ran out of space before TCPE_IO\n"));
  981                                         goto abort_cfe;
  982                                 }
  983 
  984                                 reg = pccard_tuple_read_1(tuple, idx);
  985                                 idx++;
  986 
  987                                 if (reg & PCCARD_TPCE_IO_BUSWIDTH_8BIT)
  988                                         cfe->flags |= PCCARD_CFE_IO8;
  989                                 if (reg & PCCARD_TPCE_IO_BUSWIDTH_16BIT)
  990                                         cfe->flags |= PCCARD_CFE_IO16;
  991                                 cfe->iomask =
  992                                     reg & PCCARD_TPCE_IO_IOADDRLINES_MASK;
  993 
  994                                 if (reg & PCCARD_TPCE_IO_HASRANGE) {
  995                                         reg = pccard_tuple_read_1(tuple, idx);
  996                                         idx++;
  997 
  998                                         cfe->num_iospace = 1 + (reg &
  999                                             PCCARD_TPCE_IO_RANGE_COUNT);
 1000 
 1001                                         if (cfe->num_iospace >
 1002                                             (sizeof(cfe->iospace) /
 1003                                              sizeof(cfe->iospace[0]))) {
 1004                                                 DPRINTF(("too many io "
 1005                                                     "spaces %d",
 1006                                                     cfe->num_iospace));
 1007                                                 state->card->error++;
 1008                                                 break;
 1009                                         }
 1010                                         for (i = 0; i < cfe->num_iospace; i++) {
 1011                                                 switch (reg & PCCARD_TPCE_IO_RANGE_ADDRSIZE_MASK) {
 1012                                                 case PCCARD_TPCE_IO_RANGE_ADDRSIZE_ONE:
 1013                                                         cfe->iospace[i].start =
 1014                                                                 pccard_tuple_read_1(tuple, idx);
 1015                                                         idx++;
 1016                                                         break;
 1017                                                 case PCCARD_TPCE_IO_RANGE_ADDRSIZE_TWO:
 1018                                                         cfe->iospace[i].start =
 1019                                                                 pccard_tuple_read_2(tuple, idx);
 1020                                                         idx += 2;
 1021                                                         break;
 1022                                                 case PCCARD_TPCE_IO_RANGE_ADDRSIZE_FOUR:
 1023                                                         cfe->iospace[i].start =
 1024                                                                 pccard_tuple_read_4(tuple, idx);
 1025                                                         idx += 4;
 1026                                                         break;
 1027                                                 }
 1028                                                 switch (reg &
 1029                                                         PCCARD_TPCE_IO_RANGE_LENGTHSIZE_MASK) {
 1030                                                 case PCCARD_TPCE_IO_RANGE_LENGTHSIZE_ONE:
 1031                                                         cfe->iospace[i].length =
 1032                                                                 pccard_tuple_read_1(tuple, idx);
 1033                                                         idx++;
 1034                                                         break;
 1035                                                 case PCCARD_TPCE_IO_RANGE_LENGTHSIZE_TWO:
 1036                                                         cfe->iospace[i].length =
 1037                                                                 pccard_tuple_read_2(tuple, idx);
 1038                                                         idx += 2;
 1039                                                         break;
 1040                                                 case PCCARD_TPCE_IO_RANGE_LENGTHSIZE_FOUR:
 1041                                                         cfe->iospace[i].length =
 1042                                                                 pccard_tuple_read_4(tuple, idx);
 1043                                                         idx += 4;
 1044                                                         break;
 1045                                                 }
 1046                                                 cfe->iospace[i].length++;
 1047                                         }
 1048                                 } else {
 1049                                         cfe->num_iospace = 1;
 1050                                         cfe->iospace[0].start = 0;
 1051                                         cfe->iospace[0].length =
 1052                                             (1 << cfe->iomask);
 1053                                 }
 1054                         }
 1055                         if (irq) {
 1056                                 if (tuple->length <= idx) {
 1057                                         DPRINTF(("ran out of space before TCPE_IR\n"));
 1058                                         goto abort_cfe;
 1059                                 }
 1060 
 1061                                 reg = pccard_tuple_read_1(tuple, idx);
 1062                                 idx++;
 1063 
 1064                                 if (reg & PCCARD_TPCE_IR_SHARE)
 1065                                         cfe->flags |= PCCARD_CFE_IRQSHARE;
 1066                                 if (reg & PCCARD_TPCE_IR_PULSE)
 1067                                         cfe->flags |= PCCARD_CFE_IRQPULSE;
 1068                                 if (reg & PCCARD_TPCE_IR_LEVEL)
 1069                                         cfe->flags |= PCCARD_CFE_IRQLEVEL;
 1070 
 1071                                 if (reg & PCCARD_TPCE_IR_HASMASK) {
 1072                                         /*
 1073                                          * it's legal to ignore the
 1074                                          * special-interrupt bits, so I will
 1075                                          */
 1076 
 1077                                         cfe->irqmask =
 1078                                             pccard_tuple_read_2(tuple, idx);
 1079                                         idx += 2;
 1080                                 } else {
 1081                                         cfe->irqmask =
 1082                                             (1 << (reg & PCCARD_TPCE_IR_IRQ));
 1083                                 }
 1084                         }
 1085                         if (memspace) {
 1086                                 if (tuple->length <= idx) {
 1087                                         DPRINTF(("ran out of space before TCPE_MS\n"));
 1088                                         goto abort_cfe;
 1089                                 }
 1090 
 1091                                 if (memspace == PCCARD_TPCE_FS_MEMSPACE_NONE) {
 1092                                         cfe->num_memspace = 0;
 1093                                 } else if (memspace == PCCARD_TPCE_FS_MEMSPACE_LENGTH) {
 1094                                         cfe->num_memspace = 1;
 1095                                         cfe->memspace[0].length = 256 *
 1096                                             pccard_tuple_read_2(tuple, idx);
 1097                                         idx += 2;
 1098                                         cfe->memspace[0].cardaddr = 0;
 1099                                         cfe->memspace[0].hostaddr = 0;
 1100                                 } else if (memspace ==
 1101                                     PCCARD_TPCE_FS_MEMSPACE_LENGTHADDR) {
 1102                                         cfe->num_memspace = 1;
 1103                                         cfe->memspace[0].length = 256 *
 1104                                             pccard_tuple_read_2(tuple, idx);
 1105                                         idx += 2;
 1106                                         cfe->memspace[0].cardaddr = 256 *
 1107                                             pccard_tuple_read_2(tuple, idx);
 1108                                         idx += 2;
 1109                                         cfe->memspace[0].hostaddr = cfe->memspace[0].cardaddr;
 1110                                 } else {
 1111                                         int lengthsize;
 1112                                         int cardaddrsize;
 1113                                         int hostaddrsize;
 1114 
 1115                                         reg = pccard_tuple_read_1(tuple, idx);
 1116                                         idx++;
 1117 
 1118                                         cfe->num_memspace = (reg &
 1119                                             PCCARD_TPCE_MS_COUNT) + 1;
 1120 
 1121                                         if (cfe->num_memspace >
 1122                                             (sizeof(cfe->memspace) /
 1123                                              sizeof(cfe->memspace[0]))) {
 1124                                                 DPRINTF(("too many mem "
 1125                                                     "spaces %d",
 1126                                                     cfe->num_memspace));
 1127                                                 state->card->error++;
 1128                                                 break;
 1129                                         }
 1130                                         lengthsize =
 1131                                                 ((reg & PCCARD_TPCE_MS_LENGTH_SIZE_MASK) >>
 1132                                                  PCCARD_TPCE_MS_LENGTH_SIZE_SHIFT);
 1133                                         cardaddrsize =
 1134                                                 ((reg & PCCARD_TPCE_MS_CARDADDR_SIZE_MASK) >>
 1135                                                  PCCARD_TPCE_MS_CARDADDR_SIZE_SHIFT);
 1136                                         hostaddrsize =
 1137                                                 (reg & PCCARD_TPCE_MS_HOSTADDR) ? cardaddrsize : 0;
 1138 
 1139                                         if (lengthsize == 0) {
 1140                                                 DPRINTF(("cfe memspace "
 1141                                                     "lengthsize == 0"));
 1142                                                 state->card->error++;
 1143                                         }
 1144                                         for (i = 0; i < cfe->num_memspace; i++) {
 1145                                                 if (lengthsize) {
 1146                                                         cfe->memspace[i].length =
 1147                                                                 256 * pccard_tuple_read_n(tuple, lengthsize,
 1148                                                                        idx);
 1149                                                         idx += lengthsize;
 1150                                                 } else {
 1151                                                         cfe->memspace[i].length = 0;
 1152                                                 }
 1153                                                 if (cfe->memspace[i].length == 0) {
 1154                                                         DPRINTF(("cfe->memspace[%d].length == 0",
 1155                                                                  i));
 1156                                                         state->card->error++;
 1157                                                 }
 1158                                                 if (cardaddrsize) {
 1159                                                         cfe->memspace[i].cardaddr =
 1160                                                                 256 * pccard_tuple_read_n(tuple, cardaddrsize,
 1161                                                                        idx);
 1162                                                         idx += cardaddrsize;
 1163                                                 } else {
 1164                                                         cfe->memspace[i].cardaddr = 0;
 1165                                                 }
 1166                                                 if (hostaddrsize) {
 1167                                                         cfe->memspace[i].hostaddr =
 1168                                                                 256 * pccard_tuple_read_n(tuple, hostaddrsize,
 1169                                                                        idx);
 1170                                                         idx += hostaddrsize;
 1171                                                 } else {
 1172                                                         cfe->memspace[i].hostaddr = 0;
 1173                                                 }
 1174                                         }
 1175                                 }
 1176                         }
 1177                         if (misc) {
 1178                                 if (tuple->length <= idx) {
 1179                                         DPRINTF(("ran out of space before TCPE_MI\n"));
 1180                                         goto abort_cfe;
 1181                                 }
 1182 
 1183                                 reg = pccard_tuple_read_1(tuple, idx);
 1184                                 idx++;
 1185 
 1186                                 if (reg & PCCARD_TPCE_MI_PWRDOWN)
 1187                                         cfe->flags = PCCARD_CFE_POWERDOWN;
 1188                                 if (reg & PCCARD_TPCE_MI_READONLY)
 1189                                         cfe->flags = PCCARD_CFE_READONLY;
 1190                                 if (reg & PCCARD_TPCE_MI_AUDIO)
 1191                                         cfe->flags = PCCARD_CFE_AUDIO;
 1192                                 cfe->maxtwins = reg & PCCARD_TPCE_MI_MAXTWINS;
 1193 
 1194                                 while (reg & PCCARD_TPCE_MI_EXT) {
 1195                                         reg = pccard_tuple_read_1(tuple, idx);
 1196                                         idx++;
 1197                                 }
 1198                         }
 1199                         /* skip all the subtuples */
 1200                 }
 1201 
 1202         abort_cfe:
 1203                 DPRINTF(("CISTPL_CFTABLE_ENTRY\n"));
 1204                 break;
 1205         default:
 1206                 DPRINTF(("unhandled CISTPL %x\n", tuple->code));
 1207                 break;
 1208         }
 1209 
 1210         return (0);
 1211 }

Cache object: ee75dddf22369a44488c62d946d2c15f


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