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