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