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