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

Cache object: 334717c0ee0566d88d8ba20052fc700d


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