LCOV - code coverage report
Current view: top level - dev/pcmcia - pcmcia_cis.c (source / functions) Hit Total Coverage
Test: 6.4 Lines: 0 536 0.0 %
Date: 2018-10-19 03:25:38 Functions: 0 5 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*      $OpenBSD: pcmcia_cis.c,v 1.21 2017/09/08 05:36:52 deraadt Exp $ */
       2             : /*      $NetBSD: pcmcia_cis.c,v 1.9 1998/08/22 23:41:48 msaitoh Exp $   */
       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/device.h>
      36             : #include <sys/malloc.h>
      37             : 
      38             : #include <dev/pcmcia/pcmciareg.h>
      39             : #include <dev/pcmcia/pcmciachip.h>
      40             : #include <dev/pcmcia/pcmciavar.h>
      41             : 
      42             : #ifdef PCMCIACISDEBUG
      43             : #define DPRINTF(arg) printf arg
      44             : #else
      45             : #define DPRINTF(arg)
      46             : #endif
      47             : 
      48             : #define PCMCIA_CIS_SIZE         1024
      49             : 
      50             : struct cis_state {
      51             :         int     count;
      52             :         int     gotmfc;
      53             :         struct pcmcia_config_entry temp_cfe;
      54             :         struct pcmcia_config_entry *default_cfe;
      55             :         struct pcmcia_card *card;
      56             :         struct pcmcia_function *pf;
      57             : };
      58             : 
      59             : int     pcmcia_parse_cis_tuple(struct pcmcia_tuple *, void *);
      60             : 
      61             : uint8_t
      62           0 : pcmcia_cis_read_1(struct pcmcia_tuple *tuple, bus_size_t idx)
      63             : {
      64           0 :         if (tuple->flags & PTF_INDIRECT) {
      65           0 :                 bus_space_write_1(tuple->memt, tuple->memh,
      66             :                     tuple->indirect_ptr + PCMCIA_INDR_CONTROL, PCMCIA_ICR_ATTR);
      67           0 :                 idx <<= tuple->addrshift;
      68           0 :                 bus_space_write_1(tuple->memt, tuple->memh,
      69             :                     tuple->indirect_ptr + PCMCIA_INDR_ADDRESS + 0, idx >> 0);
      70           0 :                 bus_space_write_1(tuple->memt, tuple->memh,
      71             :                     tuple->indirect_ptr + PCMCIA_INDR_ADDRESS + 1, idx >> 8);
      72           0 :                 bus_space_write_1(tuple->memt, tuple->memh,
      73             :                     tuple->indirect_ptr + PCMCIA_INDR_ADDRESS + 2, idx >> 16);
      74           0 :                 bus_space_write_1(tuple->memt, tuple->memh,
      75             :                     tuple->indirect_ptr + PCMCIA_INDR_ADDRESS + 3, idx >> 24);
      76           0 :                 return bus_space_read_1(tuple->memt, tuple->memh,
      77             :                     tuple->indirect_ptr + PCMCIA_INDR_DATA);
      78             :         } else
      79           0 :                 return bus_space_read_1(tuple->memt, tuple->memh,
      80             :                     idx << tuple->addrshift);
      81           0 : }
      82             : 
      83             : void
      84           0 : pcmcia_read_cis(sc)
      85             :         struct pcmcia_softc *sc;
      86             : {
      87           0 :         struct cis_state state;
      88             : 
      89           0 :         memset(&state, 0, sizeof state);
      90             : 
      91           0 :         state.card = &sc->card;
      92             : 
      93           0 :         state.card->error = 0;
      94           0 :         state.card->cis1_major = -1;
      95           0 :         state.card->cis1_minor = -1;
      96           0 :         state.card->cis1_info[0] = NULL;
      97           0 :         state.card->cis1_info[1] = NULL;
      98           0 :         state.card->cis1_info[2] = NULL;
      99           0 :         state.card->cis1_info[3] = NULL;
     100           0 :         state.card->manufacturer = PCMCIA_VENDOR_INVALID;
     101           0 :         state.card->product = PCMCIA_PRODUCT_INVALID;
     102           0 :         SIMPLEQ_INIT(&state.card->pf_head);
     103             : 
     104           0 :         state.pf = NULL;
     105             : 
     106           0 :         if (pcmcia_scan_cis((struct device *)sc, pcmcia_parse_cis_tuple,
     107           0 :             &state) == -1)
     108           0 :                 state.card->error++;
     109           0 : }
     110             : 
     111             : int
     112           0 : pcmcia_scan_cis(dev, fct, arg)
     113             :         struct device *dev;
     114             :         int (*fct)(struct pcmcia_tuple *, void *);
     115             :         void *arg;
     116             : {
     117           0 :         struct pcmcia_softc *sc = (struct pcmcia_softc *) dev;
     118             :         pcmcia_chipset_tag_t pct;
     119             :         pcmcia_chipset_handle_t pch;
     120           0 :         int window;
     121           0 :         struct pcmcia_mem_handle pcmh;
     122           0 :         struct pcmcia_tuple tuple;
     123             :         int indirect_present;
     124             :         int longlink_present;
     125             :         int longlink_common;
     126             :         u_long longlink_addr;
     127             :         int mfc_count;
     128             :         int mfc_index;
     129           0 :         struct {
     130             :                 int     common;
     131             :                 u_long  addr;
     132             :         } mfc[256 / 5];
     133             :         int ret;
     134             : 
     135             :         ret = 0;
     136             : 
     137           0 :         pct = sc->pct;
     138           0 :         pch = sc->pch;
     139             : 
     140             :         /* allocate some memory */
     141             : 
     142           0 :         if (pcmcia_chip_mem_alloc(pct, pch, PCMCIA_CIS_SIZE, &pcmh)) {
     143             : #ifdef DIAGNOSTIC
     144           0 :                 printf("%s: can't alloc memory to read attributes\n",
     145           0 :                     sc->dev.dv_xname);
     146             : #endif
     147           0 :                 return -1;
     148             :         }
     149             : 
     150             :         /* initialize state for the primary tuple chain */
     151           0 :         if (pcmcia_chip_mem_map(pct, pch, PCMCIA_MEM_ATTR, 0,
     152             :             PCMCIA_CIS_SIZE, &pcmh, &tuple.ptr, &window)) {
     153           0 :                 pcmcia_chip_mem_free(pct, pch, &pcmh);
     154             : #ifdef DIAGNOSTIC
     155           0 :                 printf("%s: can't map memory to read attributes\n",
     156           0 :                     sc->dev.dv_xname);
     157             : #endif
     158           0 :                 return -1;
     159             :         }
     160           0 :         tuple.memt = pcmh.memt;
     161           0 :         tuple.memh = pcmh.memh;
     162             : 
     163             :         DPRINTF(("cis mem map %x\n", (unsigned int) tuple.memh));
     164             : 
     165           0 :         tuple.addrshift = 1;
     166           0 :         tuple.flags = 0;
     167             : 
     168             :         indirect_present = 0;
     169             :         longlink_present = 1;
     170             :         longlink_common = 1;
     171             :         longlink_addr = 0;
     172             : 
     173             :         mfc_count = 0;
     174             :         mfc_index = 0;
     175             : 
     176             :         DPRINTF(("%s: CIS tuple chain:\n", sc->dev.dv_xname));
     177             : 
     178           0 :         while (1) {
     179           0 :                 while (1) {
     180             :                         /*
     181             :                          * Perform boundary check for insane cards.
     182             :                          * If CIS is too long, simulate CIS end.
     183             :                          * (This check may not be sufficient for
     184             :                          * malicious cards.)
     185             :                          */
     186           0 :                         if ((tuple.ptr << tuple.addrshift) >=
     187             :                             PCMCIA_CIS_SIZE - 1 - 32 /* ad hoc value */) {
     188             :                                 DPRINTF(("CISTPL_END (too long CIS)\n"));
     189           0 :                                 tuple.code = PCMCIA_CISTPL_END;
     190           0 :                                 goto cis_end;
     191             :                         }
     192             : 
     193             :                         /* get the tuple code */
     194             : 
     195           0 :                         tuple.code = pcmcia_cis_read_1(&tuple, tuple.ptr);
     196             : 
     197             :                         /* two special-case tuples */
     198             : 
     199           0 :                         if (tuple.code == PCMCIA_CISTPL_NULL) {
     200             :                                 DPRINTF(("CISTPL_NONE\n 00\n"));
     201           0 :                                 tuple.ptr++;
     202           0 :                                 continue;
     203           0 :                         } else if (tuple.code == PCMCIA_CISTPL_END) {
     204             :                                 DPRINTF(("CISTPL_END\n ff\n"));
     205             :                         cis_end:
     206             :                                 /* Call the function for the END tuple, since
     207             :                                    the CIS semantics depend on it */
     208           0 :                                 if ((*fct) (&tuple, arg)) {
     209           0 :                                         pcmcia_chip_mem_unmap(pct, pch,
     210             :                                                               window);
     211             :                                         ret = 1;
     212           0 :                                         goto done;
     213             :                                 }
     214           0 :                                 tuple.ptr++;
     215             :                                 break;
     216             :                         }
     217             :                         /* now all the normal tuples */
     218             : 
     219           0 :                         tuple.length = pcmcia_cis_read_1(&tuple, tuple.ptr + 1);
     220           0 :                         switch (tuple.code) {
     221             :                         case PCMCIA_CISTPL_INDIRECT:
     222             :                                 indirect_present = 1;
     223             :                                 DPRINTF(("CISTPL_INDIRECT\n"));
     224           0 :                                 break;
     225             :                         case PCMCIA_CISTPL_LONGLINK_A:
     226             :                         case PCMCIA_CISTPL_LONGLINK_C:
     227           0 :                                 if (tuple.length < 4) {
     228             :                                         DPRINTF(("CISTPL_LONGLINK_%s too "
     229             :                                             "short %d\n",
     230             :                                             longlink_common ? "C" : "A",
     231             :                                             tuple.length));
     232             :                                         break;
     233             :                                 }
     234             :                                 longlink_present = 1;
     235           0 :                                 longlink_common = (tuple.code ==
     236             :                                     PCMCIA_CISTPL_LONGLINK_C) ? 1 : 0;
     237           0 :                                 longlink_addr = pcmcia_tuple_read_4(&tuple, 0);
     238             :                                 DPRINTF(("CISTPL_LONGLINK_%s %lx\n",
     239             :                                     longlink_common ? "C" : "A",
     240             :                                     longlink_addr));
     241           0 :                                 break;
     242             :                         case PCMCIA_CISTPL_NO_LINK:
     243             :                                 longlink_present = 0;
     244             :                                 DPRINTF(("CISTPL_NO_LINK\n"));
     245           0 :                                 break;
     246             :                         case PCMCIA_CISTPL_CHECKSUM:
     247           0 :                                 if (tuple.length < 5) {
     248             :                                         DPRINTF(("CISTPL_CHECKSUM too "
     249             :                                             "short %d\n", tuple.length));
     250             :                                         break;
     251             :                                 } {
     252             :                                         int16_t offset;
     253             :                                         u_long addr, length;
     254             :                                         u_int cksum, sum;
     255             :                                         int i;
     256             : 
     257             :                                         *((u_int16_t *) & offset) =
     258           0 :                                             pcmcia_tuple_read_2(&tuple, 0);
     259           0 :                                         length = pcmcia_tuple_read_2(&tuple, 2);
     260           0 :                                         cksum = pcmcia_tuple_read_1(&tuple, 4);
     261             : 
     262           0 :                                         addr = tuple.ptr + offset;
     263             : 
     264             :                                         DPRINTF(("CISTPL_CHECKSUM addr=%lx "
     265             :                                             "len=%lx cksum=%x",
     266             :                                             addr, length, cksum));
     267             : 
     268             :                                         /*
     269             :                                          * XXX do more work to deal with
     270             :                                          * distant regions
     271             :                                          */
     272           0 :                                         if ((addr >= PCMCIA_CIS_SIZE) ||
     273           0 :                                             ((addr + length) >=
     274             :                                               PCMCIA_CIS_SIZE)) {
     275             :                                                 DPRINTF((" skipped, "
     276             :                                                     "too distant\n"));
     277           0 :                                                 break;
     278             :                                         }
     279             :                                         sum = 0;
     280           0 :                                         for (i = 0; i < length; i++)
     281           0 :                                                 sum += pcmcia_cis_read_1(&tuple,
     282           0 :                                                     addr + i);
     283           0 :                                         if (cksum != (sum & 0xff)) {
     284             :                                                 DPRINTF((" failed sum=%x\n",
     285             :                                                     sum));
     286           0 :                                                 printf("%s: CIS checksum "
     287             :                                                     "failed\n",
     288           0 :                                                     sc->dev.dv_xname);
     289             : #if 0
     290             :                                                 /*
     291             :                                                  * XXX Some working cards have
     292             :                                                  * XXX bad checksums!!
     293             :                                                  */
     294             :                                                 ret = -1;
     295             : #endif
     296           0 :                                         } else {
     297             :                                                 DPRINTF((" ok\n"));
     298             :                                         }
     299           0 :                                 }
     300             :                                 break;
     301             :                         case PCMCIA_CISTPL_LONGLINK_MFC:
     302           0 :                                 if (tuple.length < 6) {
     303             :                                         DPRINTF(("CISTPL_LONGLINK_MFC too "
     304             :                                             "short %d\n", tuple.length));
     305             :                                         break;
     306             :                                 }
     307           0 :                                 if (((tuple.length - 1) % 5) != 0) {
     308             :                                         DPRINTF(("CISTPL_LONGLINK_MFC bogus "
     309             :                                             "length %d\n", tuple.length));
     310             :                                         break;
     311             :                                 }
     312             :                                 {
     313             :                                         int i, tmp_count;
     314             : 
     315             :                                         /*
     316             :                                          * put count into tmp var so that
     317             :                                          * if we have to bail (because it's
     318             :                                          * a bogus count) it won't be
     319             :                                          * remembered for later use.
     320             :                                          */
     321             :                                         tmp_count =
     322           0 :                                             pcmcia_tuple_read_1(&tuple, 0);
     323             :                                         DPRINTF(("CISTPL_LONGLINK_MFC %d",
     324             :                                             tmp_count));
     325             : 
     326             :                                         /*
     327             :                                          * make _sure_ it's the right size;
     328             :                                          * if too short, it may be a weird
     329             :                                          * (unknown/undefined) format
     330             :                                          */
     331           0 :                                         if (tuple.length != (tmp_count*5 + 1)) {
     332             :                                                 DPRINTF((" bogus length %d\n",
     333             :                                                     tuple.length));
     334           0 :                                                 break;
     335             :                                         }
     336             : 
     337             : #ifdef PCMCIACISDEBUG   /* maybe enable all the time? */
     338             :                                         /*
     339             :                                          * sanity check for a programming
     340             :                                          * error which is difficult to find
     341             :                                          * when debugging.
     342             :                                          */
     343             :                                         if (tmp_count >
     344             :                                             howmany(sizeof mfc, sizeof mfc[0]))
     345             :                                                 panic("CISTPL_LONGLINK_MFC mfc "
     346             :                                                     "count would blow stack");
     347             : #endif
     348             : 
     349             :                                         mfc_count = tmp_count;
     350           0 :                                         for (i = 0; i < mfc_count; i++) {
     351           0 :                                                 mfc[i].common =
     352           0 :                                                     (pcmcia_tuple_read_1(&tuple,
     353           0 :                                                     1 + 5 * i) ==
     354             :                                                     PCMCIA_MFC_MEM_COMMON) ?
     355             :                                                     1 : 0;
     356           0 :                                                 mfc[i].addr =
     357           0 :                                                     pcmcia_tuple_read_4(&tuple,
     358             :                                                     1 + 5 * i + 1);
     359             :                                                 DPRINTF((" %s:%lx",
     360             :                                                     mfc[i].common ? "common" :
     361             :                                                     "attr", mfc[i].addr));
     362             :                                         }
     363             :                                         DPRINTF(("\n"));
     364           0 :                                 }
     365             :                                 /*
     366             :                                  * for LONGLINK_MFC, fall through to the
     367             :                                  * function.  This tuple has structural and
     368             :                                  * semantic content.
     369             :                                  */
     370             :                         default:
     371             :                                 {
     372           0 :                                         if ((*fct) (&tuple, arg)) {
     373           0 :                                                 pcmcia_chip_mem_unmap(pct,
     374             :                                                     pch, window);
     375             :                                                 ret = 1;
     376           0 :                                                 goto done;
     377             :                                         }
     378             :                                 }
     379             :                                 break;
     380             :                         }       /* switch */
     381             : #ifdef PCMCIACISDEBUG
     382             :                         /* print the tuple */
     383             :                         {
     384             :                                 int i;
     385             : 
     386             :                                 DPRINTF((" %02x %02x", tuple.code,
     387             :                                     tuple.length));
     388             : 
     389             :                                 for (i = 0; i < tuple.length; i++) {
     390             :                                         DPRINTF((" %02x",
     391             :                                             pcmcia_tuple_read_1(&tuple, i)));
     392             :                                         if ((i % 16) == 13)
     393             :                                                 DPRINTF(("\n"));
     394             :                                 }
     395             :                                 if ((i % 16) != 14)
     396             :                                         DPRINTF(("\n"));
     397             :                         }
     398             : #endif
     399             :                         /* skip to the next tuple */
     400           0 :                         tuple.ptr += 2 + tuple.length;
     401             :                 }
     402             : 
     403             :                 /*
     404             :                  * the chain is done.  Clean up and move onto the next one,
     405             :                  * if any.  The loop is here in the case that there is an MFC
     406             :                  * card with no longlink (which defaults to existing, == 0).
     407             :                  * In general, this means that if one pointer fails, it will
     408             :                  * try the next one, instead of just bailing.
     409             :                  */
     410             : 
     411           0 :                 while (1) {
     412           0 :                         pcmcia_chip_mem_unmap(pct, pch, window);
     413             : 
     414           0 :                         if (indirect_present) {
     415             :                                 /*
     416             :                                  * Indirect CIS data needs to be obtained
     417             :                                  * from specific registers accessible at
     418             :                                  * a fixed location in the common window,
     419             :                                  * but otherwise is similar to longlink
     420             :                                  * in attribute memory.
     421             :                                  */
     422             : 
     423           0 :                                 pcmcia_chip_mem_map(pct, pch, PCMCIA_MEM_COMMON,
     424             :                                     0, PCMCIA_INDR_SIZE,
     425             :                                     &pcmh, &tuple.indirect_ptr, &window);
     426             : 
     427             :                                 DPRINTF(("cis mem map %x ind %x\n",
     428             :                                     (unsigned int) tuple.memh,
     429             :                                     (unsigned int) tuple.indirect_ptr));
     430             : 
     431           0 :                                 tuple.addrshift = 1;
     432           0 :                                 tuple.flags |= PTF_INDIRECT;
     433           0 :                                 tuple.ptr = 0;
     434             :                                 longlink_present = 0;
     435             :                                 indirect_present = 0;
     436           0 :                         } else if (longlink_present) {
     437             :                                 /*
     438             :                                  * if the longlink is to attribute memory,
     439             :                                  * then it is unindexed.  That is, if the
     440             :                                  * link value is 0x100, then the actual
     441             :                                  * memory address is 0x200.  This means that
     442             :                                  * we need to multiply by 2 before calling
     443             :                                  * mem_map, and then divide the resulting ptr
     444             :                                  * by 2 after.
     445             :                                  */
     446             : 
     447           0 :                                 if (!longlink_common)
     448           0 :                                         longlink_addr *= 2;
     449             : 
     450           0 :                                 pcmcia_chip_mem_map(pct, pch, longlink_common ?
     451             :                                     PCMCIA_MEM_COMMON : PCMCIA_MEM_ATTR,
     452             :                                     longlink_addr, PCMCIA_CIS_SIZE,
     453             :                                     &pcmh, &tuple.ptr, &window);
     454             : 
     455           0 :                                 if (!longlink_common)
     456           0 :                                         tuple.ptr /= 2;
     457             : 
     458             :                                 DPRINTF(("cis mem map %x\n",
     459             :                                     (unsigned int) tuple.memh));
     460             : 
     461           0 :                                 tuple.addrshift = longlink_common ? 0 : 1;
     462             :                                 longlink_present = 0;
     463             :                                 longlink_common = 1;
     464             :                                 longlink_addr = 0;
     465           0 :                         } else if (mfc_count && (mfc_index < mfc_count)) {
     466           0 :                                 if (!mfc[mfc_index].common)
     467           0 :                                         mfc[mfc_index].addr *= 2;
     468             : 
     469           0 :                                 pcmcia_chip_mem_map(pct, pch,
     470             :                                     mfc[mfc_index].common ?
     471             :                                     PCMCIA_MEM_COMMON : PCMCIA_MEM_ATTR,
     472             :                                     mfc[mfc_index].addr, PCMCIA_CIS_SIZE,
     473             :                                     &pcmh, &tuple.ptr, &window);
     474             : 
     475           0 :                                 if (!mfc[mfc_index].common)
     476           0 :                                         tuple.ptr /= 2;
     477             : 
     478             :                                 DPRINTF(("cis mem map %x\n",
     479             :                                     (unsigned int) tuple.memh));
     480             : 
     481             :                                 /* set parse state, and point at the next one */
     482             : 
     483           0 :                                 tuple.addrshift = mfc[mfc_index].common ? 0 : 1;
     484             : 
     485           0 :                                 mfc_index++;
     486             :                         } else {
     487             :                                 goto done;
     488             :                         }
     489             : 
     490             :                         /* make sure that the link is valid */
     491           0 :                         tuple.code = pcmcia_cis_read_1(&tuple, tuple.ptr);
     492           0 :                         if (tuple.code != PCMCIA_CISTPL_LINKTARGET) {
     493             :                                 DPRINTF(("CISTPL_LINKTARGET expected, "
     494             :                                     "code %02x observed\n", tuple.code));
     495           0 :                                 continue;
     496             :                         }
     497           0 :                         tuple.length = pcmcia_cis_read_1(&tuple, tuple.ptr + 1);
     498           0 :                         if (tuple.length < 3) {
     499             :                                 DPRINTF(("CISTPL_LINKTARGET too short %d\n",
     500             :                                     tuple.length));
     501           0 :                                 continue;
     502             :                         }
     503           0 :                         if ((pcmcia_tuple_read_1(&tuple, 0) != 'C') ||
     504           0 :                             (pcmcia_tuple_read_1(&tuple, 1) != 'I') ||
     505           0 :                             (pcmcia_tuple_read_1(&tuple, 2) != 'S')) {
     506             :                                 DPRINTF(("CISTPL_LINKTARGET magic "
     507             :                                     "%02x%02x%02x incorrect\n",
     508             :                                     pcmcia_tuple_read_1(&tuple, 0),
     509             :                                     pcmcia_tuple_read_1(&tuple, 1),
     510             :                                     pcmcia_tuple_read_1(&tuple, 2)));
     511           0 :                                 continue;
     512             :                         }
     513           0 :                         tuple.ptr += 2 + tuple.length;
     514             : 
     515             :                         break;
     516             :                 }
     517             :         }
     518             : 
     519             :         pcmcia_chip_mem_unmap(pct, pch, window);
     520             : 
     521             : done:
     522             :         /* Last, free the allocated memory block */
     523           0 :         pcmcia_chip_mem_free(pct, pch, &pcmh);
     524             : 
     525           0 :         return (ret);
     526           0 : }
     527             : 
     528             : /* XXX this is incredibly verbose.  Not sure what trt is */
     529             : 
     530             : void
     531           0 : pcmcia_print_cis(sc)
     532             :         struct pcmcia_softc *sc;
     533             : {
     534           0 :         struct pcmcia_card *card = &sc->card;
     535             :         struct pcmcia_function *pf;
     536             :         struct pcmcia_config_entry *cfe;
     537             :         int i;
     538             : 
     539           0 :         printf("%s: CIS version ", sc->dev.dv_xname);
     540           0 :         if (card->cis1_major == 4) {
     541           0 :                 if (card->cis1_minor == 0)
     542           0 :                         printf("PCMCIA 1.0\n");
     543           0 :                 else if (card->cis1_minor == 1)
     544           0 :                         printf("PCMCIA 2.0 or 2.1\n");
     545           0 :         } else if (card->cis1_major >= 5)
     546           0 :                 printf("PC Card Standard %d.%d\n", card->cis1_major,
     547             :                     card->cis1_minor);
     548             :         else
     549           0 :                 printf("unknown (major=%d, minor=%d)\n",
     550             :                     card->cis1_major, card->cis1_minor);
     551             : 
     552           0 :         printf("%s: CIS info: ", sc->dev.dv_xname);
     553           0 :         for (i = 0; i < 4; i++) {
     554           0 :                 if (card->cis1_info[i] == NULL)
     555             :                         break;
     556           0 :                 if (i)
     557           0 :                         printf(", ");
     558           0 :                 printf("%s", card->cis1_info[i]);
     559             :         }
     560           0 :         printf("\n");
     561             : 
     562           0 :         printf("%s: Manufacturer code 0x%x, product 0x%x\n",
     563           0 :                sc->dev.dv_xname, card->manufacturer, card->product);
     564             : 
     565           0 :         SIMPLEQ_FOREACH(pf, &card->pf_head, pf_list) {
     566           0 :                 printf("%s: function %d: ", sc->dev.dv_xname, pf->number);
     567             : 
     568           0 :                 switch (pf->function) {
     569             :                 case PCMCIA_FUNCTION_UNSPEC:
     570           0 :                         printf("unspecified");
     571           0 :                         break;
     572             :                 case PCMCIA_FUNCTION_MULTIFUNCTION:
     573           0 :                         printf("multi-function");
     574           0 :                         break;
     575             :                 case PCMCIA_FUNCTION_MEMORY:
     576           0 :                         printf("memory");
     577           0 :                         break;
     578             :                 case PCMCIA_FUNCTION_SERIAL:
     579           0 :                         printf("serial port");
     580           0 :                         break;
     581             :                 case PCMCIA_FUNCTION_PARALLEL:
     582           0 :                         printf("parallel port");
     583           0 :                         break;
     584             :                 case PCMCIA_FUNCTION_DISK:
     585           0 :                         printf("fixed disk");
     586           0 :                         break;
     587             :                 case PCMCIA_FUNCTION_VIDEO:
     588           0 :                         printf("video adapter");
     589           0 :                         break;
     590             :                 case PCMCIA_FUNCTION_NETWORK:
     591           0 :                         printf("network adapter");
     592           0 :                         break;
     593             :                 case PCMCIA_FUNCTION_AIMS:
     594           0 :                         printf("auto incrementing mass storage");
     595           0 :                         break;
     596             :                 case PCMCIA_FUNCTION_SCSI:
     597           0 :                         printf("SCSI bridge");
     598           0 :                         break;
     599             :                 case PCMCIA_FUNCTION_SECURITY:
     600           0 :                         printf("Security services");
     601           0 :                         break;
     602             :                 case PCMCIA_FUNCTION_INSTRUMENT:
     603           0 :                         printf("Instrument");
     604           0 :                         break;
     605             :                 case PCMCIA_FUNCTION_IOBUS:
     606           0 :                         printf("Serial I/O Bus Adapter");
     607           0 :                         break;
     608             :                 default:
     609           0 :                         printf("unknown (%d)", pf->function);
     610           0 :                         break;
     611             :                 }
     612             : 
     613           0 :                 printf(", ccr addr %lx mask %lx\n", pf->ccr_base, pf->ccr_mask);
     614             : 
     615           0 :                 SIMPLEQ_FOREACH(cfe, &pf->cfe_head, cfe_list) {
     616           0 :                         printf("%s: function %d, config table entry %d: ",
     617           0 :                             sc->dev.dv_xname, pf->number, cfe->number);
     618             : 
     619           0 :                         switch (cfe->iftype) {
     620             :                         case PCMCIA_IFTYPE_MEMORY:
     621           0 :                                 printf("memory card");
     622           0 :                                 break;
     623             :                         case PCMCIA_IFTYPE_IO:
     624           0 :                                 printf("I/O card");
     625           0 :                                 break;
     626             :                         default:
     627           0 :                                 printf("card type unknown");
     628           0 :                                 break;
     629             :                         }
     630             : 
     631           0 :                         printf("; irq mask %x", cfe->irqmask);
     632             : 
     633           0 :                         if (cfe->num_iospace) {
     634           0 :                                 printf("; iomask %lx, iospace", cfe->iomask);
     635             : 
     636           0 :                                 for (i = 0; i < cfe->num_iospace; i++)
     637           0 :                                         printf(" %lx%s%lx",
     638           0 :                                             cfe->iospace[i].start,
     639           0 :                                             cfe->iospace[i].length ? "-" : "",
     640           0 :                                             cfe->iospace[i].start +
     641           0 :                                               cfe->iospace[i].length - 1);
     642             :                         }
     643           0 :                         if (cfe->num_memspace) {
     644           0 :                                 printf("; memspace");
     645             : 
     646           0 :                                 for (i = 0; i < cfe->num_memspace; i++)
     647           0 :                                         printf(" %lx%s%lx%s%lx",
     648           0 :                                             cfe->memspace[i].cardaddr,
     649           0 :                                             cfe->memspace[i].length ? "-" : "",
     650           0 :                                             cfe->memspace[i].cardaddr +
     651           0 :                                               cfe->memspace[i].length - 1,
     652           0 :                                             cfe->memspace[i].hostaddr ?
     653             :                                               "@" : "",
     654             :                                             cfe->memspace[i].hostaddr);
     655             :                         }
     656           0 :                         if (cfe->maxtwins)
     657           0 :                                 printf("; maxtwins %d", cfe->maxtwins);
     658             : 
     659           0 :                         printf(";");
     660             : 
     661           0 :                         if (cfe->flags & PCMCIA_CFE_MWAIT_REQUIRED)
     662           0 :                                 printf(" mwait_required");
     663           0 :                         if (cfe->flags & PCMCIA_CFE_RDYBSY_ACTIVE)
     664           0 :                                 printf(" rdybsy_active");
     665           0 :                         if (cfe->flags & PCMCIA_CFE_WP_ACTIVE)
     666           0 :                                 printf(" wp_active");
     667           0 :                         if (cfe->flags & PCMCIA_CFE_BVD_ACTIVE)
     668           0 :                                 printf(" bvd_active");
     669           0 :                         if (cfe->flags & PCMCIA_CFE_IO8)
     670           0 :                                 printf(" io8");
     671           0 :                         if (cfe->flags & PCMCIA_CFE_IO16)
     672           0 :                                 printf(" io16");
     673           0 :                         if (cfe->flags & PCMCIA_CFE_IRQSHARE)
     674           0 :                                 printf(" irqshare");
     675           0 :                         if (cfe->flags & PCMCIA_CFE_IRQPULSE)
     676           0 :                                 printf(" irqpulse");
     677           0 :                         if (cfe->flags & PCMCIA_CFE_IRQLEVEL)
     678           0 :                                 printf(" irqlevel");
     679           0 :                         if (cfe->flags & PCMCIA_CFE_POWERDOWN)
     680           0 :                                 printf(" powerdown");
     681           0 :                         if (cfe->flags & PCMCIA_CFE_READONLY)
     682           0 :                                 printf(" readonly");
     683           0 :                         if (cfe->flags & PCMCIA_CFE_AUDIO)
     684           0 :                                 printf(" audio");
     685             : 
     686           0 :                         printf("\n");
     687             :                 }
     688             :         }
     689             : 
     690           0 :         if (card->error)
     691           0 :                 printf("%s: %d errors found while parsing CIS\n",
     692           0 :                     sc->dev.dv_xname, card->error);
     693           0 : }
     694             : 
     695             : int
     696           0 : pcmcia_parse_cis_tuple(tuple, arg)
     697             :         struct pcmcia_tuple *tuple;
     698             :         void *arg;
     699             : {
     700             :         /* most of these are educated guesses */
     701             :         static struct pcmcia_config_entry init_cfe = {
     702             :                 -1, PCMCIA_CFE_RDYBSY_ACTIVE | PCMCIA_CFE_WP_ACTIVE |
     703             :                 PCMCIA_CFE_BVD_ACTIVE, PCMCIA_IFTYPE_MEMORY,
     704             :         };
     705             : 
     706           0 :         struct cis_state *state = arg;
     707             : 
     708           0 :         switch (tuple->code) {
     709             :         case PCMCIA_CISTPL_END:
     710             :                 /*
     711             :                  * If we've seen a LONGLINK_MFC, and this is the first
     712             :                  * END after it, reset the function list.  
     713             :                  *
     714             :                  * XXX This might also be the right place to start a
     715             :                  * new function, but that assumes that a function
     716             :                  * definition never crosses any longlink, and I'm not
     717             :                  * sure about that.  This is probably safe for MFC
     718             :                  * cards, but what we have now isn't broken, so I'd
     719             :                  * rather not change it.
     720             :                  */
     721           0 :                 if (state->gotmfc == 1) {
     722             :                         struct pcmcia_function *pf, *pfnext;
     723             : 
     724           0 :                         for (pf = SIMPLEQ_FIRST(&state->card->pf_head);
     725           0 :                             pf != NULL; pf = pfnext) {
     726           0 :                                 pfnext = SIMPLEQ_NEXT(pf, pf_list);
     727           0 :                                 free(pf, M_DEVBUF, 0);
     728             :                         }
     729             : 
     730           0 :                         SIMPLEQ_INIT(&state->card->pf_head);
     731             : 
     732           0 :                         state->count = 0;
     733           0 :                         state->gotmfc = 2;
     734           0 :                         state->pf = NULL;
     735           0 :                 }
     736             :                 break;
     737             : 
     738             :         case PCMCIA_CISTPL_LONGLINK_MFC:
     739             :                 /*
     740             :                  * This tuple's structure was dealt with in scan_cis.  here,
     741             :                  * record the fact that the MFC tuple was seen, so that
     742             :                  * functions declared before the MFC link can be cleaned
     743             :                  * up.
     744             :                  */
     745           0 :                 state->gotmfc = 1;
     746           0 :                 break;
     747             : 
     748             : #ifdef PCMCIACISDEBUG
     749             :         case PCMCIA_CISTPL_DEVICE:
     750             :         case PCMCIA_CISTPL_DEVICE_A:
     751             :                 {
     752             :                         u_int reg, dtype, dspeed;
     753             : 
     754             :                         reg = pcmcia_tuple_read_1(tuple, 0);
     755             :                         dtype = reg & PCMCIA_DTYPE_MASK;
     756             :                         dspeed = reg & PCMCIA_DSPEED_MASK;
     757             : 
     758             :                         DPRINTF(("CISTPL_DEVICE%s type=",
     759             :                         (tuple->code == PCMCIA_CISTPL_DEVICE) ? "" : "_A"));
     760             :                         switch (dtype) {
     761             :                         case PCMCIA_DTYPE_NULL:
     762             :                                 DPRINTF(("null"));
     763             :                                 break;
     764             :                         case PCMCIA_DTYPE_ROM:
     765             :                                 DPRINTF(("rom"));
     766             :                                 break;
     767             :                         case PCMCIA_DTYPE_OTPROM:
     768             :                                 DPRINTF(("otprom"));
     769             :                                 break;
     770             :                         case PCMCIA_DTYPE_EPROM:
     771             :                                 DPRINTF(("eprom"));
     772             :                                 break;
     773             :                         case PCMCIA_DTYPE_EEPROM:
     774             :                                 DPRINTF(("eeprom"));
     775             :                                 break;
     776             :                         case PCMCIA_DTYPE_FLASH:
     777             :                                 DPRINTF(("flash"));
     778             :                                 break;
     779             :                         case PCMCIA_DTYPE_SRAM:
     780             :                                 DPRINTF(("sram"));
     781             :                                 break;
     782             :                         case PCMCIA_DTYPE_DRAM:
     783             :                                 DPRINTF(("dram"));
     784             :                                 break;
     785             :                         case PCMCIA_DTYPE_FUNCSPEC:
     786             :                                 DPRINTF(("funcspec"));
     787             :                                 break;
     788             :                         case PCMCIA_DTYPE_EXTEND:
     789             :                                 DPRINTF(("extend"));
     790             :                                 break;
     791             :                         default:
     792             :                                 DPRINTF(("reserved"));
     793             :                                 break;
     794             :                         }
     795             :                         DPRINTF((" speed="));
     796             :                         switch (dspeed) {
     797             :                         case PCMCIA_DSPEED_NULL:
     798             :                                 DPRINTF(("null"));
     799             :                                 break;
     800             :                         case PCMCIA_DSPEED_250NS:
     801             :                                 DPRINTF(("250ns"));
     802             :                                 break;
     803             :                         case PCMCIA_DSPEED_200NS:
     804             :                                 DPRINTF(("200ns"));
     805             :                                 break;
     806             :                         case PCMCIA_DSPEED_150NS:
     807             :                                 DPRINTF(("150ns"));
     808             :                                 break;
     809             :                         case PCMCIA_DSPEED_100NS:
     810             :                                 DPRINTF(("100ns"));
     811             :                                 break;
     812             :                         case PCMCIA_DSPEED_EXT:
     813             :                                 DPRINTF(("ext"));
     814             :                                 break;
     815             :                         default:
     816             :                                 DPRINTF(("reserved"));
     817             :                                 break;
     818             :                         }
     819             :                 }
     820             :                 DPRINTF(("\n"));
     821             :                 break;
     822             : #endif
     823             : 
     824             :         case PCMCIA_CISTPL_VERS_1:
     825           0 :                 if (tuple->length < 6) {
     826             :                         DPRINTF(("CISTPL_VERS_1 too short %d\n",
     827             :                             tuple->length));
     828             :                         break;
     829             :                 } {
     830             :                         int start, i, ch, count;
     831             : 
     832           0 :                         state->card->cis1_major = pcmcia_tuple_read_1(tuple, 0);
     833           0 :                         state->card->cis1_minor = pcmcia_tuple_read_1(tuple, 1);
     834             : 
     835           0 :                         for (count = 0, start = 0, i = 0;
     836           0 :                             (count < 4) && ((i + 4) < 256); i++) {
     837           0 :                                 ch = pcmcia_tuple_read_1(tuple, 2 + i);
     838           0 :                                 if (ch == 0xff)
     839             :                                         break;
     840           0 :                                 state->card->cis1_info_buf[i] = ch;
     841           0 :                                 if (ch == 0) {
     842           0 :                                         state->card->cis1_info[count] =
     843           0 :                                             state->card->cis1_info_buf + start;
     844           0 :                                         start = i + 1;
     845           0 :                                         count++;
     846           0 :                                 }
     847             :                         }
     848             :                         DPRINTF(("CISTPL_VERS_1\n"));
     849             :                 }
     850           0 :                 break;
     851             : 
     852             :         case PCMCIA_CISTPL_MANFID:
     853           0 :                 if (tuple->length < 4) {
     854             :                         DPRINTF(("CISTPL_MANFID too short %d\n",
     855             :                             tuple->length));
     856             :                         break;
     857             :                 }
     858           0 :                 state->card->manufacturer = pcmcia_tuple_read_2(tuple, 0);
     859           0 :                 state->card->product = pcmcia_tuple_read_2(tuple, 2);
     860             :                 DPRINTF(("CISTPL_MANFID\n"));
     861           0 :                 break;
     862             : 
     863             :         case PCMCIA_CISTPL_FUNCID:
     864           0 :                 if (tuple->length < 2) {
     865             :                         DPRINTF(("CISTPL_FUNCID too short %d\n",
     866             :                             tuple->length));
     867             :                         break;
     868             :                 }
     869             : 
     870             :                 /*
     871             :                  * As far as I understand this, manufacturers do multifunction
     872             :                  * cards in various ways.  Sadly enough I do not have the
     873             :                  * PC-Card standard (donate!) so I can only guess what can
     874             :                  * be done.
     875             :                  * The original code implies FUNCID nodes are above CONFIG
     876             :                  * nodes in the CIS tree, however Xircom does it the other
     877             :                  * way round, which of course makes things a bit hard.
     878             :                  * --niklas@openbsd.org
     879             :                  */
     880           0 :                 if (state->pf) {
     881           0 :                         if (state->pf->function == PCMCIA_FUNCTION_UNSPEC) {
     882             :                                 /*
     883             :                                  * This looks like a opportunistic function
     884             :                                  * created by a CONFIG tuple.  Just keep it.
     885             :                                  */
     886             :                         } else {
     887             :                                 /*
     888             :                                  * A function is being defined, end it.
     889             :                                  */
     890           0 :                                 state->pf = NULL;
     891             :                         }
     892             :                 }
     893           0 :                 if (state->pf == NULL) {
     894           0 :                         state->pf = malloc(sizeof(*state->pf), M_DEVBUF,
     895             :                             M_NOWAIT | M_ZERO);
     896           0 :                         if (state->pf == NULL)
     897           0 :                                 panic("pcmcia_parse_cis_tuple");
     898           0 :                         state->pf->number = state->count++;
     899           0 :                         state->pf->last_config_index = -1;
     900           0 :                         SIMPLEQ_INIT(&state->pf->cfe_head);
     901             : 
     902           0 :                         SIMPLEQ_INSERT_TAIL(&state->card->pf_head, state->pf,
     903             :                             pf_list);
     904           0 :                 }
     905           0 :                 state->pf->function = pcmcia_tuple_read_1(tuple, 0);
     906             : 
     907             :                 DPRINTF(("CISTPL_FUNCID\n"));
     908           0 :                 break;
     909             : 
     910             :         case PCMCIA_CISTPL_CONFIG:
     911           0 :                 if (tuple->length < 3) {
     912             :                         DPRINTF(("CISTPL_CONFIG too short %d\n",
     913             :                             tuple->length));
     914             :                         break;
     915             :                 } {
     916             :                         u_int reg, rasz, rmsz, rfsz;
     917             :                         int i;
     918             : 
     919           0 :                         reg = pcmcia_tuple_read_1(tuple, 0);
     920           0 :                         rasz = 1 + ((reg & PCMCIA_TPCC_RASZ_MASK) >>
     921             :                             PCMCIA_TPCC_RASZ_SHIFT);
     922           0 :                         rmsz = 1 + ((reg & PCMCIA_TPCC_RMSZ_MASK) >>
     923             :                             PCMCIA_TPCC_RMSZ_SHIFT);
     924           0 :                         rfsz = ((reg & PCMCIA_TPCC_RFSZ_MASK) >>
     925             :                             PCMCIA_TPCC_RFSZ_SHIFT);
     926             : 
     927           0 :                         if (tuple->length < 2 + rasz + rmsz + rfsz) {
     928             :                                 DPRINTF(("CISTPL_CONFIG (%d,%d,%d) too "
     929             :                                     "short %d\n", rasz, rmsz, rfsz,
     930             :                                     tuple->length));
     931           0 :                                 break;
     932             :                         }
     933           0 :                         if (state->pf == NULL) {
     934           0 :                                 state->pf = malloc(sizeof(*state->pf),
     935             :                                     M_DEVBUF, M_NOWAIT | M_ZERO);
     936           0 :                                 if (state->pf == NULL)
     937           0 :                                         panic("pcmcia_parse_cis_tuple");
     938           0 :                                 state->pf->number = state->count++;
     939           0 :                                 state->pf->last_config_index = -1;
     940           0 :                                 SIMPLEQ_INIT(&state->pf->cfe_head);
     941             : 
     942           0 :                                 SIMPLEQ_INSERT_TAIL(&state->card->pf_head,
     943             :                                     state->pf, pf_list);
     944             : 
     945           0 :                                 state->pf->function = PCMCIA_FUNCTION_UNSPEC;
     946           0 :                         }
     947           0 :                         state->pf->last_config_index =
     948           0 :                             pcmcia_tuple_read_1(tuple, 1);
     949             : 
     950           0 :                         state->pf->ccr_base = 0;
     951           0 :                         for (i = 0; i < rasz; i++)
     952           0 :                                 state->pf->ccr_base |=
     953           0 :                                     ((pcmcia_tuple_read_1(tuple, 2 + i)) <<
     954           0 :                                     (i * 8));
     955             : 
     956           0 :                         state->pf->ccr_mask = 0;
     957           0 :                         for (i = 0; i < rmsz; i++)
     958           0 :                                 state->pf->ccr_mask |=
     959           0 :                                     ((pcmcia_tuple_read_1(tuple,
     960           0 :                                     2 + rasz + i)) << (i * 8));
     961             : 
     962             :                         /* skip the reserved area and subtuples */
     963             : 
     964             :                         /* reset the default cfe for each cfe list */
     965           0 :                         state->temp_cfe = init_cfe;
     966           0 :                         state->default_cfe = &state->temp_cfe;
     967           0 :                 }
     968             :                 DPRINTF(("CISTPL_CONFIG\n"));
     969             :                 break;
     970             : 
     971             :         case PCMCIA_CISTPL_CFTABLE_ENTRY:
     972           0 :                 if (tuple->length < 2) {
     973             :                         DPRINTF(("CISTPL_CFTABLE_ENTRY too short %d\n",
     974             :                             tuple->length));
     975             :                         break;
     976             :                 } {
     977             :                         int idx, i, j;
     978             :                         u_int reg, reg2;
     979             :                         u_int intface, def, num;
     980             :                         u_int power, timing, iospace, irq, memspace, misc;
     981             :                         struct pcmcia_config_entry *cfe;
     982             : 
     983             :                         idx = 0;
     984             : 
     985           0 :                         reg = pcmcia_tuple_read_1(tuple, idx);
     986             :                         idx++;
     987           0 :                         intface = reg & PCMCIA_TPCE_INDX_INTFACE;
     988           0 :                         def = reg & PCMCIA_TPCE_INDX_DEFAULT;
     989           0 :                         num = reg & PCMCIA_TPCE_INDX_NUM_MASK;
     990             : 
     991             :                         /*
     992             :                          * this is a little messy.  Some cards have only a
     993             :                          * cfentry with the default bit set.  So, as we go
     994             :                          * through the list, we add new indexes to the queue,
     995             :                          * and keep a pointer to the last one with the
     996             :                          * default bit set.  if we see a record with the same
     997             :                          * index, as the default, we stash the default and
     998             :                          * replace the queue entry. otherwise, we just add
     999             :                          * new entries to the queue, pointing the default ptr
    1000             :                          * at them if the default bit is set.  if we get to
    1001             :                          * the end with the default pointer pointing at a
    1002             :                          * record which hasn't had a matching index, that's
    1003             :                          * ok; it just becomes a cfentry like any other.
    1004             :                          */
    1005             : 
    1006             :                         /*
    1007             :                          * if the index in the cis differs from the default
    1008             :                          * cis, create new entry in the queue and start it
    1009             :                          * with the current default
    1010             :                          */
    1011           0 :                         if (state->default_cfe == NULL) {
    1012             :                                 DPRINTF(("CISTPL_CFTABLE_ENTRY with no "
    1013             :                                     "default\n"));
    1014           0 :                                 break;
    1015             :                         }
    1016           0 :                         if (num != state->default_cfe->number) {
    1017           0 :                                 cfe = (struct pcmcia_config_entry *)
    1018           0 :                                     malloc(sizeof(*cfe), M_DEVBUF, M_NOWAIT);
    1019           0 :                                 if (cfe == NULL)
    1020           0 :                                         panic("pcmcia_parse_cis_tuple");
    1021             : 
    1022           0 :                                 *cfe = *state->default_cfe;
    1023             : 
    1024           0 :                                 SIMPLEQ_INSERT_TAIL(&state->pf->cfe_head,
    1025             :                                     cfe, cfe_list);
    1026             : 
    1027           0 :                                 cfe->number = num;
    1028             : 
    1029             :                                 /*
    1030             :                                  * if the default bit is set in the cis, then
    1031             :                                  * point the new default at whatever is being
    1032             :                                  * filled in
    1033             :                                  */
    1034           0 :                                 if (def)
    1035           0 :                                         state->default_cfe = cfe;
    1036             :                         } else {
    1037             :                                 /*
    1038             :                                  * the cis index matches the default index,
    1039             :                                  * fill in the default cfentry.  It is
    1040             :                                  * assumed that the cfdefault index is in the
    1041             :                                  * queue.  For it to be otherwise, the cis
    1042             :                                  * index would have to be -1 (initial
    1043             :                                  * condition) which is not possible, or there
    1044             :                                  * would have to be a preceding cis entry
    1045             :                                  * which had the same cis index and had the
    1046             :                                  * default bit unset. Neither condition
    1047             :                                  * should happen.  If it does, this cfentry
    1048             :                                  * is lost (written into temp space), which
    1049             :                                  * is an acceptable failure mode.
    1050             :                                  */
    1051             : 
    1052             :                                 cfe = state->default_cfe;
    1053             : 
    1054             :                                 /*
    1055             :                                  * if the cis entry does not have the default
    1056             :                                  * bit set, copy the default out of the way
    1057             :                                  * first.
    1058             :                                  */
    1059           0 :                                 if (!def) {
    1060           0 :                                         state->temp_cfe = *state->default_cfe;
    1061           0 :                                         state->default_cfe = &state->temp_cfe;
    1062           0 :                                 }
    1063             :                         }
    1064             : 
    1065           0 :                         if (intface) {
    1066           0 :                                 reg = pcmcia_tuple_read_1(tuple, idx);
    1067             :                                 idx++;
    1068           0 :                                 cfe->flags &= ~(PCMCIA_CFE_MWAIT_REQUIRED
    1069             :                                     | PCMCIA_CFE_RDYBSY_ACTIVE
    1070             :                                     | PCMCIA_CFE_WP_ACTIVE
    1071             :                                     | PCMCIA_CFE_BVD_ACTIVE);
    1072           0 :                                 if (reg & PCMCIA_TPCE_IF_MWAIT)
    1073           0 :                                         cfe->flags |= PCMCIA_CFE_MWAIT_REQUIRED;
    1074           0 :                                 if (reg & PCMCIA_TPCE_IF_RDYBSY)
    1075           0 :                                         cfe->flags |= PCMCIA_CFE_RDYBSY_ACTIVE;
    1076           0 :                                 if (reg & PCMCIA_TPCE_IF_WP)
    1077           0 :                                         cfe->flags |= PCMCIA_CFE_WP_ACTIVE;
    1078           0 :                                 if (reg & PCMCIA_TPCE_IF_BVD)
    1079           0 :                                         cfe->flags |= PCMCIA_CFE_BVD_ACTIVE;
    1080           0 :                                 cfe->iftype = reg & PCMCIA_TPCE_IF_IFTYPE;
    1081           0 :                         }
    1082           0 :                         reg = pcmcia_tuple_read_1(tuple, idx);
    1083           0 :                         idx++;
    1084             : 
    1085           0 :                         power = reg & PCMCIA_TPCE_FS_POWER_MASK;
    1086           0 :                         timing = reg & PCMCIA_TPCE_FS_TIMING;
    1087           0 :                         iospace = reg & PCMCIA_TPCE_FS_IOSPACE;
    1088           0 :                         irq = reg & PCMCIA_TPCE_FS_IRQ;
    1089           0 :                         memspace = reg & PCMCIA_TPCE_FS_MEMSPACE_MASK;
    1090           0 :                         misc = reg & PCMCIA_TPCE_FS_MISC;
    1091             : 
    1092           0 :                         if (power) {
    1093             :                                 /* skip over power, don't save */
    1094             :                                 /* for each parameter selection byte */
    1095           0 :                                 for (i = 0; i < power; i++) {
    1096           0 :                                         reg = pcmcia_tuple_read_1(tuple, idx);
    1097           0 :                                         idx++;
    1098             :                                         /* for each bit */
    1099           0 :                                         for (j = 0; j < 7; j++) {
    1100             :                                                 /* if the bit is set */
    1101           0 :                                                 if ((reg >> j) & 0x01) {
    1102             :                                                         /* skip over bytes */
    1103           0 :                                                         do {
    1104           0 :                                                                 reg2 = pcmcia_tuple_read_1(tuple, idx);
    1105           0 :                                                                 idx++;
    1106             :                                                                 /*
    1107             :                                                                  * until
    1108             :                                                                  * non-
    1109             :                                                                  * extension
    1110             :                                                                  * byte
    1111             :                                                                  */
    1112           0 :                                                         } while (reg2 & 0x80);
    1113             :                                                 }
    1114             :                                         }
    1115             :                                 }
    1116             :                         }
    1117           0 :                         if (timing) {
    1118             :                                 /* skip over timing, don't save */
    1119           0 :                                 reg = pcmcia_tuple_read_1(tuple, idx);
    1120           0 :                                 idx++;
    1121             : 
    1122           0 :                                 if ((reg & PCMCIA_TPCE_TD_RESERVED_MASK) !=
    1123             :                                     PCMCIA_TPCE_TD_RESERVED_MASK)
    1124           0 :                                         idx++;
    1125           0 :                                 if ((reg & PCMCIA_TPCE_TD_RDYBSY_MASK) !=
    1126             :                                     PCMCIA_TPCE_TD_RDYBSY_MASK)
    1127           0 :                                         idx++;
    1128           0 :                                 if ((reg & PCMCIA_TPCE_TD_WAIT_MASK) !=
    1129             :                                     PCMCIA_TPCE_TD_WAIT_MASK)
    1130           0 :                                         idx++;
    1131             :                         }
    1132           0 :                         if (iospace) {
    1133           0 :                                 if (tuple->length <= idx) {
    1134             :                                         DPRINTF(("ran out of space before TPCE_IO\n"));
    1135             : 
    1136           0 :                                         goto abort_cfe;
    1137             :                                 }
    1138             : 
    1139           0 :                                 reg = pcmcia_tuple_read_1(tuple, idx);
    1140           0 :                                 idx++;
    1141             : 
    1142           0 :                                 cfe->flags &=
    1143             :                                     ~(PCMCIA_CFE_IO8 | PCMCIA_CFE_IO16);
    1144           0 :                                 if (reg & PCMCIA_TPCE_IO_BUSWIDTH_8BIT)
    1145           0 :                                         cfe->flags |= PCMCIA_CFE_IO8;
    1146           0 :                                 if (reg & PCMCIA_TPCE_IO_BUSWIDTH_16BIT)
    1147           0 :                                         cfe->flags |= PCMCIA_CFE_IO16;
    1148           0 :                                 cfe->iomask =
    1149           0 :                                     reg & PCMCIA_TPCE_IO_IOADDRLINES_MASK;
    1150             : 
    1151           0 :                                 if (reg & PCMCIA_TPCE_IO_HASRANGE) {
    1152           0 :                                         reg = pcmcia_tuple_read_1(tuple, idx);
    1153           0 :                                         idx++;
    1154             : 
    1155           0 :                                         cfe->num_iospace = 1 + (reg &
    1156             :                                             PCMCIA_TPCE_IO_RANGE_COUNT);
    1157             : 
    1158           0 :                                         if (cfe->num_iospace >
    1159             :                                             (sizeof(cfe->iospace) /
    1160             :                                              sizeof(cfe->iospace[0]))) {
    1161             :                                                 DPRINTF(("too many io "
    1162             :                                                     "spaces %d",
    1163             :                                                     cfe->num_iospace));
    1164           0 :                                                 state->card->error++;
    1165           0 :                                                 break;
    1166             :                                         }
    1167           0 :                                         for (i = 0; i < cfe->num_iospace; i++) {
    1168           0 :                                                 switch (reg & PCMCIA_TPCE_IO_RANGE_ADDRSIZE_MASK) {
    1169             :                                                 case PCMCIA_TPCE_IO_RANGE_ADDRSIZE_ONE:
    1170           0 :                                                         cfe->iospace[i].start =
    1171           0 :                                                                 pcmcia_tuple_read_1(tuple, idx);
    1172           0 :                                                         idx++;
    1173           0 :                                                         break;
    1174             :                                                 case PCMCIA_TPCE_IO_RANGE_ADDRSIZE_TWO:
    1175           0 :                                                         cfe->iospace[i].start =
    1176           0 :                                                                 pcmcia_tuple_read_2(tuple, idx);
    1177             :                                                         idx += 2;
    1178           0 :                                                         break;
    1179             :                                                 case PCMCIA_TPCE_IO_RANGE_ADDRSIZE_FOUR:
    1180           0 :                                                         cfe->iospace[i].start =
    1181           0 :                                                                 pcmcia_tuple_read_4(tuple, idx);
    1182           0 :                                                         idx += 4;
    1183           0 :                                                         break;
    1184             :                                                 }
    1185           0 :                                                 switch (reg &
    1186             :                                                         PCMCIA_TPCE_IO_RANGE_LENGTHSIZE_MASK) {
    1187             :                                                 case PCMCIA_TPCE_IO_RANGE_LENGTHSIZE_ONE:
    1188           0 :                                                         cfe->iospace[i].length =
    1189           0 :                                                                 pcmcia_tuple_read_1(tuple, idx);
    1190           0 :                                                         idx++;
    1191           0 :                                                         break;
    1192             :                                                 case PCMCIA_TPCE_IO_RANGE_LENGTHSIZE_TWO:
    1193           0 :                                                         cfe->iospace[i].length =
    1194           0 :                                                                 pcmcia_tuple_read_2(tuple, idx);
    1195             :                                                         idx += 2;
    1196           0 :                                                         break;
    1197             :                                                 case PCMCIA_TPCE_IO_RANGE_LENGTHSIZE_FOUR:
    1198           0 :                                                         cfe->iospace[i].length =
    1199           0 :                                                                 pcmcia_tuple_read_4(tuple, idx);
    1200           0 :                                                         idx += 4;
    1201           0 :                                                         break;
    1202             :                                                 }
    1203           0 :                                                 cfe->iospace[i].length++;
    1204             :                                         }
    1205             :                                 } else {
    1206           0 :                                         cfe->num_iospace = 1;
    1207           0 :                                         cfe->iospace[0].start = 0;
    1208           0 :                                         cfe->iospace[0].length =
    1209           0 :                                             (1 << cfe->iomask);
    1210             :                                 }
    1211             :                         }
    1212             : 
    1213           0 :                         if (irq) {
    1214           0 :                                 if (tuple->length <= idx) {
    1215             :                                         DPRINTF(("ran out of space before TPCE_IR\n"));
    1216             : 
    1217           0 :                                         goto abort_cfe;
    1218             :                                 }
    1219             : 
    1220           0 :                                 reg = pcmcia_tuple_read_1(tuple, idx);
    1221           0 :                                 idx++;
    1222             : 
    1223           0 :                                 cfe->flags &= ~(PCMCIA_CFE_IRQSHARE
    1224             :                                     | PCMCIA_CFE_IRQPULSE
    1225             :                                     | PCMCIA_CFE_IRQLEVEL);
    1226           0 :                                 if (reg & PCMCIA_TPCE_IR_SHARE)
    1227           0 :                                         cfe->flags |= PCMCIA_CFE_IRQSHARE;
    1228           0 :                                 if (reg & PCMCIA_TPCE_IR_PULSE)
    1229           0 :                                         cfe->flags |= PCMCIA_CFE_IRQPULSE;
    1230           0 :                                 if (reg & PCMCIA_TPCE_IR_LEVEL)
    1231           0 :                                         cfe->flags |= PCMCIA_CFE_IRQLEVEL;
    1232             : 
    1233           0 :                                 if (reg & PCMCIA_TPCE_IR_HASMASK) {
    1234             :                                         /*
    1235             :                                          * it's legal to ignore the
    1236             :                                          * special-interrupt bits, so I will
    1237             :                                          */
    1238             : 
    1239           0 :                                         cfe->irqmask =
    1240           0 :                                             pcmcia_tuple_read_2(tuple, idx);
    1241             :                                         idx += 2;
    1242           0 :                                 } else {
    1243           0 :                                         cfe->irqmask =
    1244           0 :                                             (1 << (reg & PCMCIA_TPCE_IR_IRQ));
    1245             :                                 }
    1246             :                         }
    1247           0 :                         if (memspace) {
    1248           0 :                                 if (tuple->length <= idx) {
    1249             :                                         DPRINTF(("ran out of space before TPCE_MS\n"));
    1250           0 :                                         goto abort_cfe;
    1251             :                                 }
    1252             : 
    1253           0 :                                 if (memspace == PCMCIA_TPCE_FS_MEMSPACE_NONE) {
    1254           0 :                                         cfe->num_memspace = 0;
    1255           0 :                                 } else if (memspace == PCMCIA_TPCE_FS_MEMSPACE_LENGTH) {
    1256           0 :                                         cfe->num_memspace = 1;
    1257           0 :                                         cfe->memspace[0].length = 256 *
    1258           0 :                                             pcmcia_tuple_read_2(tuple, idx);
    1259             :                                         idx += 2;
    1260           0 :                                         cfe->memspace[0].cardaddr = 0;
    1261           0 :                                         cfe->memspace[0].hostaddr = 0;
    1262           0 :                                 } else if (memspace ==
    1263             :                                     PCMCIA_TPCE_FS_MEMSPACE_LENGTHADDR) {
    1264           0 :                                         cfe->num_memspace = 1;
    1265           0 :                                         cfe->memspace[0].length = 256 *
    1266           0 :                                             pcmcia_tuple_read_2(tuple, idx);
    1267             :                                         idx += 2;
    1268           0 :                                         cfe->memspace[0].cardaddr = 256 *
    1269           0 :                                             pcmcia_tuple_read_2(tuple, idx);
    1270             :                                         idx += 2;
    1271           0 :                                         cfe->memspace[0].hostaddr = cfe->memspace[0].cardaddr;
    1272           0 :                                 } else {
    1273             :                                         int lengthsize;
    1274             :                                         int cardaddrsize;
    1275             :                                         int hostaddrsize;
    1276             : 
    1277           0 :                                         reg = pcmcia_tuple_read_1(tuple, idx);
    1278           0 :                                         idx++;
    1279             : 
    1280           0 :                                         cfe->num_memspace = (reg &
    1281           0 :                                             PCMCIA_TPCE_MS_COUNT) + 1;
    1282             : 
    1283           0 :                                         if (cfe->num_memspace >
    1284             :                                             (sizeof(cfe->memspace) /
    1285             :                                              sizeof(cfe->memspace[0]))) {
    1286             :                                                 DPRINTF(("too many mem "
    1287             :                                                     "spaces %d",
    1288             :                                                     cfe->num_memspace));
    1289           0 :                                                 state->card->error++;
    1290           0 :                                                 break;
    1291             :                                         }
    1292             :                                         lengthsize =
    1293           0 :                                                 ((reg & PCMCIA_TPCE_MS_LENGTH_SIZE_MASK) >>
    1294             :                                                  PCMCIA_TPCE_MS_LENGTH_SIZE_SHIFT);
    1295             :                                         cardaddrsize =
    1296           0 :                                                 ((reg & PCMCIA_TPCE_MS_CARDADDR_SIZE_MASK) >>
    1297             :                                                  PCMCIA_TPCE_MS_CARDADDR_SIZE_SHIFT);
    1298             :                                         hostaddrsize =
    1299           0 :                                                 (reg & PCMCIA_TPCE_MS_HOSTADDR) ? cardaddrsize : 0;
    1300             : 
    1301           0 :                                         if (lengthsize == 0) {
    1302             :                                                 DPRINTF(("cfe memspace "
    1303             :                                                     "lengthsize == 0"));
    1304           0 :                                                 state->card->error++;
    1305           0 :                                         }
    1306           0 :                                         for (i = 0; i < cfe->num_memspace; i++) {
    1307           0 :                                                 if (lengthsize) {
    1308           0 :                                                         cfe->memspace[i].length =
    1309           0 :                                                                 256 * pcmcia_tuple_read_n(tuple, lengthsize,
    1310             :                                                                        idx);
    1311           0 :                                                         idx += lengthsize;
    1312           0 :                                                 } else {
    1313           0 :                                                         cfe->memspace[i].length = 0;
    1314             :                                                 }
    1315           0 :                                                 if (cfe->memspace[i].length == 0) {
    1316             :                                                         DPRINTF(("cfe->memspace[%d].length == 0",
    1317             :                                                                  i));
    1318           0 :                                                         state->card->error++;
    1319           0 :                                                 }
    1320           0 :                                                 if (cardaddrsize) {
    1321           0 :                                                         cfe->memspace[i].cardaddr =
    1322           0 :                                                                 256 * pcmcia_tuple_read_n(tuple, cardaddrsize,
    1323             :                                                                        idx);
    1324           0 :                                                         idx += cardaddrsize;
    1325           0 :                                                 } else {
    1326           0 :                                                         cfe->memspace[i].cardaddr = 0;
    1327             :                                                 }
    1328           0 :                                                 if (hostaddrsize) {
    1329           0 :                                                         cfe->memspace[i].hostaddr =
    1330           0 :                                                                 256 * pcmcia_tuple_read_n(tuple, hostaddrsize,
    1331             :                                                                        idx);
    1332           0 :                                                         idx += hostaddrsize;
    1333           0 :                                                 } else {
    1334           0 :                                                         cfe->memspace[i].hostaddr = 0;
    1335             :                                                 }
    1336             :                                         }
    1337           0 :                                 }
    1338             :                         }
    1339           0 :                         if (misc) {
    1340           0 :                                 if (tuple->length <= idx) {
    1341             :                                         DPRINTF(("ran out of space before TPCE_MI\n"));
    1342             : 
    1343           0 :                                         goto abort_cfe;
    1344             :                                 }
    1345             : 
    1346           0 :                                 reg = pcmcia_tuple_read_1(tuple, idx);
    1347           0 :                                 idx++;
    1348             : 
    1349           0 :                                 cfe->flags &= ~(PCMCIA_CFE_POWERDOWN
    1350             :                                     | PCMCIA_CFE_READONLY
    1351             :                                     | PCMCIA_CFE_AUDIO);
    1352           0 :                                 if (reg & PCMCIA_TPCE_MI_PWRDOWN)
    1353           0 :                                         cfe->flags |= PCMCIA_CFE_POWERDOWN;
    1354           0 :                                 if (reg & PCMCIA_TPCE_MI_READONLY)
    1355           0 :                                         cfe->flags |= PCMCIA_CFE_READONLY;
    1356           0 :                                 if (reg & PCMCIA_TPCE_MI_AUDIO)
    1357           0 :                                         cfe->flags |= PCMCIA_CFE_AUDIO;
    1358           0 :                                 cfe->maxtwins = reg & PCMCIA_TPCE_MI_MAXTWINS;
    1359             : 
    1360           0 :                                 while (reg & PCMCIA_TPCE_MI_EXT) {
    1361           0 :                                         reg = pcmcia_tuple_read_1(tuple, idx);
    1362           0 :                                         idx++;
    1363             :                                 }
    1364             :                         }
    1365             :                         /* skip all the subtuples */
    1366           0 :                 }
    1367             : 
    1368             :         abort_cfe:
    1369             :                 DPRINTF(("CISTPL_CFTABLE_ENTRY\n"));
    1370             :                 break;
    1371             : 
    1372             :         default:
    1373             :                 DPRINTF(("unhandled CISTPL %x\n", tuple->code));
    1374             :                 break;
    1375             :         }
    1376             : 
    1377           0 :         return (0);
    1378           0 : }

Generated by: LCOV version 1.13