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