Merge from vendor branch GCC:
[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.2 2004/03/15 17:15:18 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         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_INTWAIT | 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_INTWAIT | 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 = malloc(sizeof(*cfe), M_DEVBUF, M_INTWAIT);
891
892                                 *cfe = *state->default_cfe;
893
894                                 STAILQ_INSERT_TAIL(&state->pf->cfe_head,
895                                     cfe, cfe_list);
896
897                                 cfe->number = num;
898
899                                 /*
900                                  * if the default bit is set in the cis, then
901                                  * point the new default at whatever is being
902                                  * filled in
903                                  */
904                                 if (def)
905                                         state->default_cfe = cfe;
906                         } else {
907                                 /*
908                                  * the cis index matches the default index,
909                                  * fill in the default cfentry.  It is
910                                  * assumed that the cfdefault index is in the
911                                  * queue.  For it to be otherwise, the cis
912                                  * index would have to be -1 (initial
913                                  * condition) which is not possible, or there
914                                  * would have to be a preceding cis entry
915                                  * which had the same cis index and had the
916                                  * default bit unset. Neither condition
917                                  * should happen.  If it does, this cfentry
918                                  * is lost (written into temp space), which
919                                  * is an acceptable failure mode.
920                                  */
921
922                                 cfe = state->default_cfe;
923
924                                 /*
925                                  * if the cis entry does not have the default
926                                  * bit set, copy the default out of the way
927                                  * first.
928                                  */
929                                 if (!def) {
930                                         state->temp_cfe = *state->default_cfe;
931                                         state->default_cfe = &state->temp_cfe;
932                                 }
933                         }
934
935                         if (intface) {
936                                 reg = pccard_tuple_read_1(tuple, idx);
937                                 idx++;
938                                 cfe->flags &= ~(PCCARD_CFE_MWAIT_REQUIRED
939                                     | PCCARD_CFE_RDYBSY_ACTIVE
940                                     | PCCARD_CFE_WP_ACTIVE
941                                     | PCCARD_CFE_BVD_ACTIVE);
942                                 if (reg & PCCARD_TPCE_IF_MWAIT)
943                                         cfe->flags |= PCCARD_CFE_MWAIT_REQUIRED;
944                                 if (reg & PCCARD_TPCE_IF_RDYBSY)
945                                         cfe->flags |= PCCARD_CFE_RDYBSY_ACTIVE;
946                                 if (reg & PCCARD_TPCE_IF_WP)
947                                         cfe->flags |= PCCARD_CFE_WP_ACTIVE;
948                                 if (reg & PCCARD_TPCE_IF_BVD)
949                                         cfe->flags |= PCCARD_CFE_BVD_ACTIVE;
950                                 cfe->iftype = reg & PCCARD_TPCE_IF_IFTYPE;
951                         }
952                         reg = pccard_tuple_read_1(tuple, idx);
953                         idx++;
954
955                         power = reg & PCCARD_TPCE_FS_POWER_MASK;
956                         timing = reg & PCCARD_TPCE_FS_TIMING;
957                         iospace = reg & PCCARD_TPCE_FS_IOSPACE;
958                         irq = reg & PCCARD_TPCE_FS_IRQ;
959                         memspace = reg & PCCARD_TPCE_FS_MEMSPACE_MASK;
960                         misc = reg & PCCARD_TPCE_FS_MISC;
961
962                         if (power) {
963                                 /* skip over power, don't save */
964                                 /* for each parameter selection byte */
965                                 for (i = 0; i < power; i++) {
966                                         reg = pccard_tuple_read_1(tuple, idx);
967                                         idx++;
968                                         /* for each bit */
969                                         for (j = 0; j < 7; j++) {
970                                                 /* if the bit is set */
971                                                 if ((reg >> j) & 0x01) {
972                                                         /* skip over bytes */
973                                                         do {
974                                                                 reg2 = pccard_tuple_read_1(tuple, idx);
975                                                                 idx++;
976                                                                 /*
977                                                                  * until
978                                                                  * non-extensi
979                                                                  * on byte
980                                                                  */
981                                                         } while (reg2 & 0x80);
982                                                 }
983                                         }
984                                 }
985                         }
986                         if (timing) {
987                                 /* skip over timing, don't save */
988                                 reg = pccard_tuple_read_1(tuple, idx);
989                                 idx++;
990
991                                 if ((reg & PCCARD_TPCE_TD_RESERVED_MASK) !=
992                                     PCCARD_TPCE_TD_RESERVED_MASK)
993                                         idx++;
994                                 if ((reg & PCCARD_TPCE_TD_RDYBSY_MASK) !=
995                                     PCCARD_TPCE_TD_RDYBSY_MASK)
996                                         idx++;
997                                 if ((reg & PCCARD_TPCE_TD_WAIT_MASK) !=
998                                     PCCARD_TPCE_TD_WAIT_MASK)
999                                         idx++;
1000                         }
1001                         if (iospace) {
1002                                 if (tuple->length <= idx) {
1003                                         DPRINTF(("ran out of space before TCPE_IO\n"));
1004                                         goto abort_cfe;
1005                                 }
1006
1007                                 reg = pccard_tuple_read_1(tuple, idx);
1008                                 idx++;
1009                                 cfe->flags &=
1010                                     ~(PCCARD_CFE_IO8 | PCCARD_CFE_IO16);
1011                                 if (reg & PCCARD_TPCE_IO_BUSWIDTH_8BIT)
1012                                         cfe->flags |= PCCARD_CFE_IO8;
1013                                 if (reg & PCCARD_TPCE_IO_BUSWIDTH_16BIT)
1014                                         cfe->flags |= PCCARD_CFE_IO16;
1015                                 cfe->iomask =
1016                                     reg & PCCARD_TPCE_IO_IOADDRLINES_MASK;
1017
1018                                 if (reg & PCCARD_TPCE_IO_HASRANGE) {
1019                                         reg = pccard_tuple_read_1(tuple, idx);
1020                                         idx++;
1021
1022                                         cfe->num_iospace = 1 + (reg &
1023                                             PCCARD_TPCE_IO_RANGE_COUNT);
1024
1025                                         if (cfe->num_iospace >
1026                                             (sizeof(cfe->iospace) /
1027                                              sizeof(cfe->iospace[0]))) {
1028                                                 DPRINTF(("too many io "
1029                                                     "spaces %d",
1030                                                     cfe->num_iospace));
1031                                                 state->card->error++;
1032                                                 break;
1033                                         }
1034                                         for (i = 0; i < cfe->num_iospace; i++) {
1035                                                 switch (reg & PCCARD_TPCE_IO_RANGE_ADDRSIZE_MASK) {
1036                                                 case PCCARD_TPCE_IO_RANGE_ADDRSIZE_ONE:
1037                                                         cfe->iospace[i].start =
1038                                                                 pccard_tuple_read_1(tuple, idx);
1039                                                         idx++;
1040                                                         break;
1041                                                 case PCCARD_TPCE_IO_RANGE_ADDRSIZE_TWO:
1042                                                         cfe->iospace[i].start =
1043                                                                 pccard_tuple_read_2(tuple, idx);
1044                                                         idx += 2;
1045                                                         break;
1046                                                 case PCCARD_TPCE_IO_RANGE_ADDRSIZE_FOUR:
1047                                                         cfe->iospace[i].start =
1048                                                                 pccard_tuple_read_4(tuple, idx);
1049                                                         idx += 4;
1050                                                         break;
1051                                                 }
1052                                                 switch (reg &
1053                                                         PCCARD_TPCE_IO_RANGE_LENGTHSIZE_MASK) {
1054                                                 case PCCARD_TPCE_IO_RANGE_LENGTHSIZE_ONE:
1055                                                         cfe->iospace[i].length =
1056                                                                 pccard_tuple_read_1(tuple, idx);
1057                                                         idx++;
1058                                                         break;
1059                                                 case PCCARD_TPCE_IO_RANGE_LENGTHSIZE_TWO:
1060                                                         cfe->iospace[i].length =
1061                                                                 pccard_tuple_read_2(tuple, idx);
1062                                                         idx += 2;
1063                                                         break;
1064                                                 case PCCARD_TPCE_IO_RANGE_LENGTHSIZE_FOUR:
1065                                                         cfe->iospace[i].length =
1066                                                                 pccard_tuple_read_4(tuple, idx);
1067                                                         idx += 4;
1068                                                         break;
1069                                                 }
1070                                                 cfe->iospace[i].length++;
1071                                         }
1072                                 } else {
1073                                         cfe->num_iospace = 1;
1074                                         cfe->iospace[0].start = 0;
1075                                         cfe->iospace[0].length =
1076                                             (1 << cfe->iomask);
1077                                 }
1078                         }
1079                         if (irq) {
1080                                 if (tuple->length <= idx) {
1081                                         DPRINTF(("ran out of space before TCPE_IR\n"));
1082                                         goto abort_cfe;
1083                                 }
1084
1085                                 reg = pccard_tuple_read_1(tuple, idx);
1086                                 idx++;
1087                                 cfe->flags &= ~(PCCARD_CFE_IRQSHARE
1088                                     | PCCARD_CFE_IRQPULSE
1089                                     | PCCARD_CFE_IRQLEVEL);
1090                                 if (reg & PCCARD_TPCE_IR_SHARE)
1091                                         cfe->flags |= PCCARD_CFE_IRQSHARE;
1092                                 if (reg & PCCARD_TPCE_IR_PULSE)
1093                                         cfe->flags |= PCCARD_CFE_IRQPULSE;
1094                                 if (reg & PCCARD_TPCE_IR_LEVEL)
1095                                         cfe->flags |= PCCARD_CFE_IRQLEVEL;
1096
1097                                 if (reg & PCCARD_TPCE_IR_HASMASK) {
1098                                         /*
1099                                          * it's legal to ignore the
1100                                          * special-interrupt bits, so I will
1101                                          */
1102
1103                                         cfe->irqmask =
1104                                             pccard_tuple_read_2(tuple, idx);
1105                                         idx += 2;
1106                                 } else {
1107                                         cfe->irqmask =
1108                                             (1 << (reg & PCCARD_TPCE_IR_IRQ));
1109                                 }
1110                         }
1111                         if (memspace) {
1112                                 if (tuple->length <= idx) {
1113                                         DPRINTF(("ran out of space before TCPE_MS\n"));
1114                                         goto abort_cfe;
1115                                 }
1116
1117                                 if (memspace == PCCARD_TPCE_FS_MEMSPACE_NONE) {
1118                                         cfe->num_memspace = 0;
1119                                 } else if (memspace == PCCARD_TPCE_FS_MEMSPACE_LENGTH) {
1120                                         cfe->num_memspace = 1;
1121                                         cfe->memspace[0].length = 256 *
1122                                             pccard_tuple_read_2(tuple, idx);
1123                                         idx += 2;
1124                                         cfe->memspace[0].cardaddr = 0;
1125                                         cfe->memspace[0].hostaddr = 0;
1126                                 } else if (memspace ==
1127                                     PCCARD_TPCE_FS_MEMSPACE_LENGTHADDR) {
1128                                         cfe->num_memspace = 1;
1129                                         cfe->memspace[0].length = 256 *
1130                                             pccard_tuple_read_2(tuple, idx);
1131                                         idx += 2;
1132                                         cfe->memspace[0].cardaddr = 256 *
1133                                             pccard_tuple_read_2(tuple, idx);
1134                                         idx += 2;
1135                                         cfe->memspace[0].hostaddr = cfe->memspace[0].cardaddr;
1136                                 } else {
1137                                         int lengthsize;
1138                                         int cardaddrsize;
1139                                         int hostaddrsize;
1140
1141                                         reg = pccard_tuple_read_1(tuple, idx);
1142                                         idx++;
1143
1144                                         cfe->num_memspace = (reg &
1145                                             PCCARD_TPCE_MS_COUNT) + 1;
1146
1147                                         if (cfe->num_memspace >
1148                                             (sizeof(cfe->memspace) /
1149                                              sizeof(cfe->memspace[0]))) {
1150                                                 DPRINTF(("too many mem "
1151                                                     "spaces %d",
1152                                                     cfe->num_memspace));
1153                                                 state->card->error++;
1154                                                 break;
1155                                         }
1156                                         lengthsize =
1157                                                 ((reg & PCCARD_TPCE_MS_LENGTH_SIZE_MASK) >>
1158                                                  PCCARD_TPCE_MS_LENGTH_SIZE_SHIFT);
1159                                         cardaddrsize =
1160                                                 ((reg & PCCARD_TPCE_MS_CARDADDR_SIZE_MASK) >>
1161                                                  PCCARD_TPCE_MS_CARDADDR_SIZE_SHIFT);
1162                                         hostaddrsize =
1163                                                 (reg & PCCARD_TPCE_MS_HOSTADDR) ? cardaddrsize : 0;
1164
1165                                         if (lengthsize == 0) {
1166                                                 DPRINTF(("cfe memspace "
1167                                                     "lengthsize == 0"));
1168                                                 state->card->error++;
1169                                         }
1170                                         for (i = 0; i < cfe->num_memspace; i++) {
1171                                                 if (lengthsize) {
1172                                                         cfe->memspace[i].length =
1173                                                                 256 * pccard_tuple_read_n(tuple, lengthsize,
1174                                                                        idx);
1175                                                         idx += lengthsize;
1176                                                 } else {
1177                                                         cfe->memspace[i].length = 0;
1178                                                 }
1179                                                 if (cfe->memspace[i].length == 0) {
1180                                                         DPRINTF(("cfe->memspace[%d].length == 0",
1181                                                                  i));
1182                                                         state->card->error++;
1183                                                 }
1184                                                 if (cardaddrsize) {
1185                                                         cfe->memspace[i].cardaddr =
1186                                                                 256 * pccard_tuple_read_n(tuple, cardaddrsize,
1187                                                                        idx);
1188                                                         idx += cardaddrsize;
1189                                                 } else {
1190                                                         cfe->memspace[i].cardaddr = 0;
1191                                                 }
1192                                                 if (hostaddrsize) {
1193                                                         cfe->memspace[i].hostaddr =
1194                                                                 256 * pccard_tuple_read_n(tuple, hostaddrsize,
1195                                                                        idx);
1196                                                         idx += hostaddrsize;
1197                                                 } else {
1198                                                         cfe->memspace[i].hostaddr = 0;
1199                                                 }
1200                                         }
1201                                 }
1202                         }
1203                         if (misc) {
1204                                 if (tuple->length <= idx) {
1205                                         DPRINTF(("ran out of space before TCPE_MI\n"));
1206                                         goto abort_cfe;
1207                                 }
1208
1209                                 reg = pccard_tuple_read_1(tuple, idx);
1210                                 idx++;
1211                                 cfe->flags &= ~(PCCARD_CFE_POWERDOWN
1212                                     | PCCARD_CFE_READONLY
1213                                     | PCCARD_CFE_AUDIO);
1214                                 if (reg & PCCARD_TPCE_MI_PWRDOWN)
1215                                         cfe->flags |= PCCARD_CFE_POWERDOWN;
1216                                 if (reg & PCCARD_TPCE_MI_READONLY)
1217                                         cfe->flags |= PCCARD_CFE_READONLY;
1218                                 if (reg & PCCARD_TPCE_MI_AUDIO)
1219                                         cfe->flags |= PCCARD_CFE_AUDIO;
1220                                 cfe->maxtwins = reg & PCCARD_TPCE_MI_MAXTWINS;
1221
1222                                 while (reg & PCCARD_TPCE_MI_EXT) {
1223                                         reg = pccard_tuple_read_1(tuple, idx);
1224                                         idx++;
1225                                 }
1226                         }
1227                         /* skip all the subtuples */
1228                 }
1229
1230         abort_cfe:
1231                 DPRINTF(("CISTPL_CFTABLE_ENTRY\n"));
1232                 break;
1233         default:
1234                 DPRINTF(("unhandled CISTPL %x\n", tuple->code));
1235                 break;
1236         }
1237
1238         return (0);
1239 }
1240
1241 static int
1242 decode_funce(struct pccard_tuple *tuple, struct pccard_function *pf)
1243 {
1244         int type = pccard_tuple_read_1(tuple, 0);
1245
1246         switch (pf->function) {
1247         case PCCARD_FUNCTION_DISK:
1248                 if (type == PCCARD_TPLFE_TYPE_DISK_DEVICE_INTERFACE) {
1249                         pf->pf_funce_disk_interface
1250                                 = pccard_tuple_read_1(tuple, 1);
1251                 }
1252                 break;
1253         case PCCARD_FUNCTION_NETWORK:
1254                 if (type == PCCARD_TPLFE_TYPE_LAN_NID) {
1255                         int i;
1256                         int len = pccard_tuple_read_1(tuple, 1);
1257                         if (tuple->length < 2 + len || len > 8) {
1258                                 /* tuple length not enough or nid too long */
1259                                 break;
1260                         }
1261                         for (i = 0; i < len; i++) {
1262                                 pf->pf_funce_lan_nid[i]
1263                                         = pccard_tuple_read_1(tuple, i + 2);
1264                         }
1265                         pf->pf_funce_lan_nidlen = len;
1266                 }
1267                 break;
1268         default:
1269                 break;
1270         }
1271         return 0;
1272 }