]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/dev/cardbus/cardbus_cis.c
This commit was generated by cvs2svn to compensate for changes in r145516,
[FreeBSD/FreeBSD.git] / sys / dev / cardbus / cardbus_cis.c
1 /*-
2  * Copyright (c) 2000,2001 Jonathan Chen.
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24  * SUCH DAMAGE.
25  */
26
27 #include <sys/cdefs.h>
28 __FBSDID("$FreeBSD$");
29
30 /*
31  * CIS Handling for the Cardbus Bus
32  */
33
34 #include <sys/param.h>
35 #include <sys/systm.h>
36 #include <sys/kernel.h>
37 #include <sys/malloc.h>
38
39 #include <sys/bus.h>
40 #include <machine/bus.h>
41 #include <machine/resource.h>
42 #include <sys/rman.h>
43 #include <sys/endian.h>
44
45 #include <sys/pciio.h>
46 #include <dev/pci/pcivar.h>
47 #include <dev/pci/pcireg.h>
48
49 #include <dev/pccard/pccardvar.h>
50 #include <dev/pccard/pccard_cis.h>
51
52 #include <dev/cardbus/cardbusreg.h>
53 #include <dev/cardbus/cardbusvar.h>
54 #include <dev/cardbus/cardbus_cis.h>
55
56 extern int cardbus_cis_debug;
57
58 #define DPRINTF(a) if (cardbus_cis_debug) printf a
59 #define DEVPRINTF(x) if (cardbus_cis_debug) device_printf x
60
61 struct tuple_callbacks;
62
63 typedef int (tuple_cb) (device_t cbdev, device_t child, int id, int len,
64                  uint8_t *tupledata, uint32_t start, uint32_t *off,
65                  struct tuple_callbacks *info);
66
67 struct tuple_callbacks {
68         int     id;
69         char    *name;
70         tuple_cb *func;
71 };
72
73 static int decode_tuple_generic(device_t cbdev, device_t child, int id,
74     int len, uint8_t *tupledata, uint32_t start, uint32_t *off,
75     struct tuple_callbacks *info);
76 static int decode_tuple_linktarget(device_t cbdev, device_t child, int id,
77     int len, uint8_t *tupledata, uint32_t start, uint32_t *off,
78     struct tuple_callbacks *info);
79 static int decode_tuple_vers_1(device_t cbdev, device_t child, int id,
80     int len, uint8_t *tupledata, uint32_t start, uint32_t *off,
81     struct tuple_callbacks *info);
82 static int decode_tuple_funcid(device_t cbdev, device_t child, int id,
83     int len, uint8_t *tupledata, uint32_t start, uint32_t *off,
84     struct tuple_callbacks *info);
85 static int decode_tuple_manfid(device_t cbdev, device_t child, int id,
86     int len, uint8_t *tupledata, uint32_t start, uint32_t *off,
87     struct tuple_callbacks *info);
88 static int decode_tuple_funce(device_t cbdev, device_t child, int id,
89     int len, uint8_t *tupledata, uint32_t start, uint32_t *off,
90     struct tuple_callbacks *info);
91 static int decode_tuple_bar(device_t cbdev, device_t child, int id,
92     int len, uint8_t *tupledata, uint32_t start, uint32_t *off,
93     struct tuple_callbacks *info);
94 static int decode_tuple_unhandled(device_t cbdev, device_t child, int id,
95     int len, uint8_t *tupledata, uint32_t start, uint32_t *off,
96     struct tuple_callbacks *info);
97 static int decode_tuple_end(device_t cbdev, device_t child, int id,
98     int len, uint8_t *tupledata, uint32_t start, uint32_t *off,
99     struct tuple_callbacks *info);
100
101 static int      cardbus_read_tuple_conf(device_t cbdev, device_t child,
102                     uint32_t start, uint32_t *off, int *tupleid, int *len,
103                     uint8_t *tupledata);
104 static int      cardbus_read_tuple_mem(device_t cbdev, struct resource *res,
105                     uint32_t start, uint32_t *off, int *tupleid, int *len,
106                     uint8_t *tupledata);
107 static int      cardbus_read_tuple(device_t cbdev, device_t child,
108                     struct resource *res, uint32_t start, uint32_t *off,
109                     int *tupleid, int *len, uint8_t *tupledata);
110 static void     cardbus_read_tuple_finish(device_t cbdev, device_t child,
111                     int rid, struct resource *res);
112 static struct resource  *cardbus_read_tuple_init(device_t cbdev, device_t child,
113                     uint32_t *start, int *rid);
114 static int      decode_tuple(device_t cbdev, device_t child, int tupleid,
115                     int len, uint8_t *tupledata, uint32_t start,
116                     uint32_t *off, struct tuple_callbacks *callbacks);
117 static int      cardbus_parse_cis(device_t cbdev, device_t child,
118                     struct tuple_callbacks *callbacks);
119
120 #define MAKETUPLE(NAME,FUNC) { CISTPL_ ## NAME, #NAME, decode_tuple_ ## FUNC }
121
122 static char *funcnames[] = {
123         "Multi-Functioned",
124         "Memory",
125         "Serial Port",
126         "Parallel Port",
127         "Fixed Disk",
128         "Video Adaptor",
129         "Network Adaptor",
130         "AIMS",
131         "SCSI",
132         "Security"
133 };
134
135 /*
136  * Handler functions for various CIS tuples
137  */
138
139 static int
140 decode_tuple_generic(device_t cbdev, device_t child, int id,
141     int len, uint8_t *tupledata, uint32_t start, uint32_t *off,
142     struct tuple_callbacks *info)
143 {
144         int i;
145
146         if (cardbus_cis_debug) {
147                 if (info)
148                         printf("TUPLE: %s [%d]:", info->name, len);
149                 else
150                         printf("TUPLE: Unknown(0x%02x) [%d]:", id, len);
151
152                 for (i = 0; i < len; i++) {
153                         if (i % 0x10 == 0 && len > 0x10)
154                                 printf("\n       0x%02x:", i);
155                         printf(" %02x", tupledata[i]);
156                 }
157                 printf("\n");
158         }
159         return (0);
160 }
161
162 static int
163 decode_tuple_linktarget(device_t cbdev, device_t child, int id,
164     int len, uint8_t *tupledata, uint32_t start, uint32_t *off,
165     struct tuple_callbacks *info)
166 {
167         int i;
168
169         if (cardbus_cis_debug) {
170                 printf("TUPLE: %s [%d]:", info->name, len);
171
172                 for (i = 0; i < len; i++) {
173                         if (i % 0x10 == 0 && len > 0x10)
174                                 printf("\n       0x%02x:", i);
175                         printf(" %02x", tupledata[i]);
176                 }
177                 printf("\n");
178         }
179         if (len != 3 || tupledata[0] != 'C' || tupledata[1] != 'I' ||
180             tupledata[2] != 'S') {
181                 printf("Invalid data for CIS Link Target!\n");
182                 decode_tuple_generic(cbdev, child, id, len, tupledata,
183                     start, off, info);
184                 return (EINVAL);
185         }
186         return (0);
187 }
188
189 static int
190 decode_tuple_vers_1(device_t cbdev, device_t child, int id,
191     int len, uint8_t *tupledata, uint32_t start, uint32_t *off,
192     struct tuple_callbacks *info)
193 {
194         int i;
195
196         if (cardbus_cis_debug) {
197                 printf("Product version: %d.%d\n", tupledata[0], tupledata[1]);
198                 printf("Product name: ");
199                 for (i = 2; i < len; i++) {
200                         if (tupledata[i] == '\0')
201                                 printf(" | ");
202                         else if (tupledata[i] == 0xff)
203                                 break;
204                         else
205                                 printf("%c", tupledata[i]);
206                 }
207                 printf("\n");
208         }
209         return (0);
210 }
211
212 static int
213 decode_tuple_funcid(device_t cbdev, device_t child, int id,
214     int len, uint8_t *tupledata, uint32_t start, uint32_t *off,
215     struct tuple_callbacks *info)
216 {
217         struct cardbus_devinfo *dinfo = device_get_ivars(child);
218         int numnames = sizeof(funcnames) / sizeof(funcnames[0]);
219         int i;
220
221         if (cardbus_cis_debug) {
222                 printf("Functions: ");
223                 for (i = 0; i < len; i++) {
224                         if (tupledata[i] < numnames)
225                                 printf("%s", funcnames[tupledata[i]]);
226                         else
227                                 printf("Unknown(%d)", tupledata[i]);
228                         if (i < len-1)
229                                 printf(", ");
230                 }
231                 printf("\n");
232         }
233         if (len > 0)
234                 dinfo->funcid = tupledata[0];           /* use first in list */
235         return (0);
236 }
237
238 static int
239 decode_tuple_manfid(device_t cbdev, device_t child, int id,
240     int len, uint8_t *tupledata, uint32_t start, uint32_t *off,
241     struct tuple_callbacks *info)
242 {
243         struct cardbus_devinfo *dinfo = device_get_ivars(child);
244         int i;
245
246         if (cardbus_cis_debug) {
247                 printf("Manufacturer ID: ");
248                 for (i = 0; i < len; i++)
249                         printf("%02x", tupledata[i]);
250                 printf("\n");
251         }
252
253         if (len == 5) {
254                 dinfo->mfrid = tupledata[1] | (tupledata[2] << 8);
255                 dinfo->prodid = tupledata[3] | (tupledata[4] << 8);
256         }
257         return (0);
258 }
259
260 static int
261 decode_tuple_funce(device_t cbdev, device_t child, int id,
262     int len, uint8_t *tupledata, uint32_t start, uint32_t *off,
263     struct tuple_callbacks *info)
264 {
265         struct cardbus_devinfo *dinfo = device_get_ivars(child);
266         int type, i;
267
268         if (cardbus_cis_debug) {
269                 printf("Function Extension: ");
270                 for (i = 0; i < len; i++)
271                         printf("%02x", tupledata[i]);
272                 printf("\n");
273         }
274         if (len < 2)                    /* too short */
275                 return (0);
276         type = tupledata[0];            /* XXX <32 always? */
277         switch (dinfo->funcid) {
278         case PCCARD_FUNCTION_NETWORK:
279                 switch (type) {
280                 case PCCARD_TPLFE_TYPE_LAN_NID:
281                         if (tupledata[1] > sizeof(dinfo->funce.lan.nid)) {
282                                 /* ignore, warning? */
283                                 return (0);
284                         }
285                         bcopy(tupledata + 2, dinfo->funce.lan.nid,
286                             tupledata[1]);
287                         break;
288                 }
289                 dinfo->fepresent |= 1<<type;
290                 break;
291         }
292         return (0);
293 }
294
295 static int
296 decode_tuple_bar(device_t cbdev, device_t child, int id,
297     int len, uint8_t *tupledata, uint32_t start, uint32_t *off,
298     struct tuple_callbacks *info)
299 {
300         struct cardbus_devinfo *dinfo = device_get_ivars(child);
301         int type;
302         uint8_t reg;
303         uint32_t bar, pci_bar;
304
305         if (len != 6) {
306                 device_printf(cbdev, "CIS BAR length not 6 (%d)\n", len);
307                 return (EINVAL);
308         }
309
310         reg = *tupledata;
311         len = le32toh(*(uint32_t*)(tupledata + 2));
312         if (reg & TPL_BAR_REG_AS) {
313                 type = SYS_RES_IOPORT;
314         } else {
315                 type = SYS_RES_MEMORY;
316         }
317
318         bar = reg & TPL_BAR_REG_ASI_MASK;
319         if (bar == 0) {
320                 device_printf(cbdev, "Invalid BAR type 0 in CIS\n");
321                 return (EINVAL);        /* XXX Return an error? */
322         } else if (bar == 7) {
323                 /* XXX Should we try to map in Option ROMs? */
324                 return (0);
325         }
326
327         /* Convert from BAR type to BAR offset */
328         bar = CARDBUS_BASE0_REG + (bar - 1) * 4;
329
330         if (type == SYS_RES_MEMORY) {
331                 if (reg & TPL_BAR_REG_PREFETCHABLE)
332                         dinfo->mprefetchable |= BARBIT(bar);
333 #if 0
334                 /*
335                  * XXX: It appears from a careful reading of the spec
336                  * that we're not supposed to honor this when the bridge
337                  * is not on the main system bus.  PCI spec doesn't appear
338                  * to allow for memory ranges not listed in the bridge's
339                  * decode range to be decoded.  The PC Card spec seems to
340                  * indicate that this should only be done on x86 based
341                  * machines, which seems to imply that on non-x86 machines
342                  * the adddresses can be anywhere.  This further implies that
343                  * since the hardware can do it on non-x86 machines, it should
344                  * be able to do it on x86 machines.  Therefore, we can and
345                  * should ignore this hint.  Furthermore, the PC Card spec
346                  * recommends always allocating memory above 1MB, contradicting
347                  * the other part of the PC Card spec.
348                  *
349                  * NetBSD ignores this bit, but it also ignores the
350                  * prefetchable bit too, so that's not an indication of
351                  * correctness.
352                  */
353                 if (reg & TPL_BAR_REG_BELOW1MB)
354                         dinfo->mbelow1mb |= BARBIT(bar);
355 #endif
356         }
357
358         /*
359          * Sanity check the BAR length reported in the CIS with the length
360          * encoded in the PCI BAR.  The latter seems to be more reliable.
361          * XXX - This probably belongs elsewhere.
362          */
363         pci_write_config(child, bar, 0xffffffff, 4);
364         pci_bar = pci_read_config(child, bar, 4);
365         if ((pci_bar != 0x0) && (pci_bar != 0xffffffff)) {
366                 if (type == SYS_RES_MEMORY) {
367                         pci_bar &= ~0xf;
368                 } else {
369                         pci_bar &= ~0x3;
370                 }
371                 len = 1 << (ffs(pci_bar) - 1);
372         }
373
374         DEVPRINTF((cbdev, "Opening BAR: type=%s, bar=%02x, len=%04x%s%s\n",
375             (type == SYS_RES_MEMORY) ? "MEM" : "IO", bar, len,
376             (type == SYS_RES_MEMORY && dinfo->mprefetchable & BARBIT(bar)) ?
377             " (Prefetchable)" : "", type == SYS_RES_MEMORY ?
378             ((dinfo->mbelow1mb & BARBIT(bar)) ? " (Below 1Mb)" : "") : ""));
379
380         resource_list_add(&dinfo->pci.resources, type, bar, 0UL, ~0UL, len);
381
382         /*
383          * Mark the appropriate bit in the PCI command register so that
384          * device drivers will know which type of BARs can be used.
385          */
386         pci_enable_io(child, type);
387         return (0);
388 }
389
390 static int
391 decode_tuple_unhandled(device_t cbdev, device_t child, int id,
392     int len, uint8_t *tupledata, uint32_t start, uint32_t *off,
393     struct tuple_callbacks *info)
394 {
395         /* Make this message suck less XXX */
396         printf("TUPLE: %s [%d] is unhandled! Bailing...", info->name, len);
397         return (-1);
398 }
399
400 static int
401 decode_tuple_end(device_t cbdev, device_t child, int id,
402     int len, uint8_t *tupledata, uint32_t start, uint32_t *off,
403     struct tuple_callbacks *info)
404 {
405         if (cardbus_cis_debug)
406                 printf("CIS reading done\n");
407         return (0);
408 }
409
410 /*
411  * Functions to read the a tuple from the card
412  */
413
414 static int
415 cardbus_read_tuple_conf(device_t cbdev, device_t child, uint32_t start,
416     uint32_t *off, int *tupleid, int *len, uint8_t *tupledata)
417 {
418         int i, j;
419         uint32_t e;
420         uint32_t loc;
421
422         loc = start + *off;
423
424         e = pci_read_config(child, loc - loc % 4, 4);
425         for (j = loc % 4; j > 0; j--)
426                 e >>= 8;
427         *len = 0;
428         for (i = loc, j = -2; j < *len; j++, i++) {
429                 if (i % 4 == 0)
430                         e = pci_read_config(child, i, 4);
431                 if (j == -2)
432                         *tupleid = 0xff & e;
433                 else if (j == -1)
434                         *len = 0xff & e;
435                 else
436                         tupledata[j] = 0xff & e;
437                 e >>= 8;
438         }
439         *off += *len + 2;
440         return (0);
441 }
442
443 static int
444 cardbus_read_tuple_mem(device_t cbdev, struct resource *res, uint32_t start,
445     uint32_t *off, int *tupleid, int *len, uint8_t *tupledata)
446 {
447         bus_space_tag_t bt;
448         bus_space_handle_t bh;
449         int ret;
450
451         bt = rman_get_bustag(res);
452         bh = rman_get_bushandle(res);
453
454         *tupleid = bus_space_read_1(bt, bh, start + *off);
455         *len = bus_space_read_1(bt, bh, start + *off + 1);
456         bus_space_read_region_1(bt, bh, *off + start + 2, tupledata, *len);
457         ret = 0;
458         *off += *len + 2;
459         return (ret);
460 }
461
462 static int
463 cardbus_read_tuple(device_t cbdev, device_t child, struct resource *res,
464     uint32_t start, uint32_t *off, int *tupleid, int *len,
465     uint8_t *tupledata)
466 {
467         if (res == (struct resource*)~0UL) {
468                 return (cardbus_read_tuple_conf(cbdev, child, start, off,
469                     tupleid, len, tupledata));
470         } else {
471                 return (cardbus_read_tuple_mem(cbdev, res, start, off,
472                     tupleid, len, tupledata));
473         }
474 }
475
476 static void
477 cardbus_read_tuple_finish(device_t cbdev, device_t child, int rid,
478     struct resource *res)
479 {
480         if (res != (struct resource*)~0UL) {
481                 bus_release_resource(cbdev, SYS_RES_MEMORY, rid, res);
482                 pci_write_config(child, rid, 0, 4);
483                 PCI_DISABLE_IO(cbdev, child, SYS_RES_MEMORY);
484         }
485 }
486
487 static struct resource *
488 cardbus_read_tuple_init(device_t cbdev, device_t child, uint32_t *start,
489     int *rid)
490 {
491         uint32_t testval;
492         uint32_t size;
493         struct resource *res;
494
495         switch (CARDBUS_CIS_SPACE(*start)) {
496         case CARDBUS_CIS_ASI_TUPLE:
497                 /* CIS in PCI config space need no initialization */
498                 return ((struct resource*)~0UL);
499         case CARDBUS_CIS_ASI_BAR0:
500         case CARDBUS_CIS_ASI_BAR1:
501         case CARDBUS_CIS_ASI_BAR2:
502         case CARDBUS_CIS_ASI_BAR3:
503         case CARDBUS_CIS_ASI_BAR4:
504         case CARDBUS_CIS_ASI_BAR5:
505                 *rid = CARDBUS_BASE0_REG + (CARDBUS_CIS_SPACE(*start) - 1) * 4;
506                 break;
507         case CARDBUS_CIS_ASI_ROM:
508                 *rid = CARDBUS_ROM_REG;
509 #if 0
510                 /*
511                  * This mask doesn't contain the bit that actually enables
512                  * the Option ROM.
513                  */
514                 pci_write_config(child, *rid, CARDBUS_ROM_ADDRMASK, 4);
515 #endif
516                 break;
517         default:
518                 device_printf(cbdev, "Unable to read CIS: Unknown space: %d\n",
519                     CARDBUS_CIS_SPACE(*start));
520                 return (NULL);
521         }
522
523         /* figure out how much space we need */
524         pci_write_config(child, *rid, 0xffffffff, 4);
525         testval = pci_read_config(child, *rid, 4);
526
527         /*
528          * This bit has a different meaning depending if we are dealing
529          * with a normal BAR or an Option ROM BAR.
530          */
531         if (((testval & 0x1) == 0x1) && (*rid != CARDBUS_ROM_REG)) {
532                 device_printf(cbdev, "CIS Space is IO, expecting memory.\n");
533                 return (NULL);
534         }
535
536         size = CARDBUS_MAPREG_MEM_SIZE(testval);
537         /* XXX Is this some kind of hack? */
538         if (size < 4096)
539                 size = 4096;
540         /* allocate the memory space to read CIS */
541         res = bus_alloc_resource(cbdev, SYS_RES_MEMORY, rid, 0, ~0, size,
542             rman_make_alignment_flags(size) | RF_ACTIVE);
543         if (res == NULL) {
544                 device_printf(cbdev, "Unable to allocate resource "
545                     "to read CIS.\n");
546                 return (NULL);
547         }
548         pci_write_config(child, *rid,
549             rman_get_start(res) | ((*rid == CARDBUS_ROM_REG)?
550                 CARDBUS_ROM_ENABLE : 0),
551             4);
552         PCI_ENABLE_IO(cbdev, child, SYS_RES_MEMORY);
553
554         /* Flip to the right ROM image if CIS is in ROM */
555         if (CARDBUS_CIS_SPACE(*start) == CARDBUS_CIS_ASI_ROM) {
556                 bus_space_tag_t bt;
557                 bus_space_handle_t bh;
558                 uint32_t imagesize;
559                 uint32_t imagebase = 0;
560                 uint32_t pcidata;
561                 uint16_t romsig;
562                 int romnum = 0;
563                 int imagenum;
564
565                 bt = rman_get_bustag(res);
566                 bh = rman_get_bushandle(res);
567
568                 imagenum = CARDBUS_CIS_ASI_ROM_IMAGE(*start);
569                 for (romnum = 0;; romnum++) {
570                         romsig = bus_space_read_2(bt, bh,
571                             imagebase + CARDBUS_EXROM_SIGNATURE);
572                         if (romsig != 0xaa55) {
573                                 device_printf(cbdev, "Bad header in rom %d: "
574                                     "[%x] %04x\n", romnum, imagebase +
575                                     CARDBUS_EXROM_SIGNATURE, romsig);
576                                 bus_release_resource(cbdev, SYS_RES_MEMORY,
577                                     *rid, res);
578                                 *rid = 0;
579                                 return (NULL);
580                         }
581
582                         /*
583                          * If this was the Option ROM image that we were
584                          * looking for, then we are done.
585                          */
586                         if (romnum == imagenum)
587                                 break;
588
589                         /* Find out where the next Option ROM image is */
590                         pcidata = imagebase + bus_space_read_2(bt, bh,
591                             imagebase + CARDBUS_EXROM_DATA_PTR);
592                         imagesize = bus_space_read_2(bt, bh,
593                             pcidata + CARDBUS_EXROM_DATA_IMAGE_LENGTH);
594
595                         if (imagesize == 0) {
596                                 /*
597                                  * XXX some ROMs seem to have this as zero,
598                                  * can we assume this means 1 block?
599                                  */
600                                 device_printf(cbdev, "Warning, size of Option "
601                                     "ROM image %d is 0 bytes, assuming 512 "
602                                     "bytes.\n", romnum);
603                                 imagesize = 1;
604                         }
605
606                         /* Image size is in 512 byte units */
607                         imagesize <<= 9;
608
609                         if ((bus_space_read_1(bt, bh, pcidata +
610                             CARDBUS_EXROM_DATA_INDICATOR) & 0x80) != 0) {
611                                 device_printf(cbdev, "Cannot find CIS in "
612                                     "Option ROM\n");
613                                 bus_release_resource(cbdev, SYS_RES_MEMORY,
614                                     *rid, res);
615                                 *rid = 0;
616                                 return (NULL);
617                         }
618                         imagebase += imagesize;
619                 }
620                 *start = imagebase + CARDBUS_CIS_ADDR(*start);
621         } else {
622                 *start = CARDBUS_CIS_ADDR(*start);
623         }
624
625         return (res);
626 }
627
628 /*
629  * Dispatch the right handler function per tuple
630  */
631
632 static int
633 decode_tuple(device_t cbdev, device_t child, int tupleid, int len,
634     uint8_t *tupledata, uint32_t start, uint32_t *off,
635     struct tuple_callbacks *callbacks)
636 {
637         int i;
638         for (i = 0; callbacks[i].id != CISTPL_GENERIC; i++) {
639                 if (tupleid == callbacks[i].id)
640                         return (callbacks[i].func(cbdev, child, tupleid, len,
641                             tupledata, start, off, &callbacks[i]));
642         }
643         return (callbacks[i].func(cbdev, child, tupleid, len,
644             tupledata, start, off, NULL));
645 }
646
647 static int
648 cardbus_parse_cis(device_t cbdev, device_t child,
649     struct tuple_callbacks *callbacks)
650 {
651         uint8_t tupledata[MAXTUPLESIZE];
652         int tupleid;
653         int len;
654         int expect_linktarget;
655         uint32_t start, off;
656         struct resource *res;
657         int rid;
658
659         bzero(tupledata, MAXTUPLESIZE);
660         expect_linktarget = TRUE;
661         if ((start = pci_read_config(child, CARDBUS_CIS_REG, 4)) == 0) {
662                 device_printf(cbdev, "CIS pointer is 0!\n");
663                 return (ENXIO);
664         }
665         off = 0;
666         res = cardbus_read_tuple_init(cbdev, child, &start, &rid);
667         if (res == NULL) {
668                 device_printf(cbdev, "Unable to allocate resources for CIS\n");
669                 return (ENXIO);
670         }
671
672         do {
673                 if (0 != cardbus_read_tuple(cbdev, child, res, start, &off,
674                     &tupleid, &len, tupledata)) {
675                         device_printf(cbdev, "Failed to read CIS.\n");
676                         cardbus_read_tuple_finish(cbdev, child, rid, res);
677                         return (ENXIO);
678                 }
679
680                 if (expect_linktarget && tupleid != CISTPL_LINKTARGET) {
681                         device_printf(cbdev, "Expecting link target, got 0x%x\n",
682                             tupleid);
683                         cardbus_read_tuple_finish(cbdev, child, rid, res);
684                         return (EINVAL);
685                 }
686                 expect_linktarget = decode_tuple(cbdev, child, tupleid, len,
687                     tupledata, start, &off, callbacks);
688                 if (expect_linktarget != 0) {
689                         device_printf(cbdev, "Parsing failed with %d\n",
690                             expect_linktarget);
691                         cardbus_read_tuple_finish(cbdev, child, rid, res);
692                         return (expect_linktarget);
693                 }
694         } while (tupleid != CISTPL_END);
695         cardbus_read_tuple_finish(cbdev, child, rid, res);
696         return (0);
697 }
698
699 int
700 cardbus_do_cis(device_t cbdev, device_t child)
701 {
702         int ret;
703         struct tuple_callbacks init_callbacks[] = {
704                 MAKETUPLE(LONGLINK_CB,          unhandled),
705                 MAKETUPLE(INDIRECT,             unhandled),
706                 MAKETUPLE(LONGLINK_MFC,         unhandled),
707                 MAKETUPLE(BAR,                  bar),
708                 MAKETUPLE(LONGLINK_A,           unhandled),
709                 MAKETUPLE(LONGLINK_C,           unhandled),
710                 MAKETUPLE(LINKTARGET,           linktarget),
711                 MAKETUPLE(VERS_1,               vers_1),
712                 MAKETUPLE(MANFID,               manfid),
713                 MAKETUPLE(FUNCID,               funcid),
714                 MAKETUPLE(FUNCE,                funce),
715                 MAKETUPLE(END,                  end),
716                 MAKETUPLE(GENERIC,              generic),
717         };
718
719         ret = cardbus_parse_cis(cbdev, child, init_callbacks);
720         if (ret < 0)
721                 return (ret);
722         return 0;
723 }