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

Cache object: 5e594ad7a2a27b6893c2eec8d1ecc58f


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