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

Cache object: fcf5fb9cce71de57674df154cdaccb86


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