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