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