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