Initial backport of NEWCARD from FreeBSD 5.
[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  *    without modification, immediately at the beginning of the file.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in
13  *    the documentation and/or other materials provided with the
14  *    distribution.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
20  * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26  * SUCH DAMAGE.
27  *
28  * $FreeBSD: src/sys/dev/cardbus/cardbus_cis.c,v 1.27 2002/11/27 06:56:29 imp Exp $
29  * $DragonFly: src/sys/dev/pccard/cardbus/cardbus_cis.c,v 1.1 2004/02/10 07:55:47 joerg Exp $
30  */
31
32 /*
33  * CIS Handling for the Cardbus Bus
34  */
35
36 #include <sys/param.h>
37 #include <sys/systm.h>
38 #include <sys/kernel.h>
39 #include <sys/malloc.h>
40
41 #include <sys/bus.h>
42 #include <machine/bus.h>
43 #include <machine/resource.h>
44 #include <sys/rman.h>
45
46 #include <sys/pciio.h>
47 #include <bus/pci/pcivar.h>
48 #include <bus/pci/pcireg.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 #include <bus/pccard/pccardvar.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 #define DECODE_PARAMS                                                   \
62                 (device_t cbdev, device_t child, int id, int len,       \
63                  u_int8_t *tupledata, u_int32_t start, u_int32_t *off,  \
64                  struct tuple_callbacks *info)
65
66 struct tuple_callbacks {
67         int     id;
68         char    *name;
69         int     (*func) DECODE_PARAMS;
70 };
71
72 #define DECODE_PROTOTYPE(NAME) static int decode_tuple_ ## NAME DECODE_PARAMS
73 DECODE_PROTOTYPE(generic);
74 DECODE_PROTOTYPE(nothing);
75 DECODE_PROTOTYPE(copy);
76 DECODE_PROTOTYPE(linktarget);
77 DECODE_PROTOTYPE(vers_1);
78 DECODE_PROTOTYPE(funcid);
79 DECODE_PROTOTYPE(manfid);
80 DECODE_PROTOTYPE(funce);
81 DECODE_PROTOTYPE(bar);
82 DECODE_PROTOTYPE(unhandled);
83 DECODE_PROTOTYPE(end);
84 static int      cardbus_read_tuple_conf(device_t cbdev, device_t child,
85                     u_int32_t start, u_int32_t *off, int *tupleid, int *len,
86                     u_int8_t *tupledata);
87 static int      cardbus_read_tuple_mem(device_t cbdev, struct resource *res,
88                     u_int32_t start, u_int32_t *off, int *tupleid, int *len,
89                     u_int8_t *tupledata);
90 static int      cardbus_read_tuple(device_t cbdev, device_t child,
91                     struct resource *res, u_int32_t start, u_int32_t *off,
92                     int *tupleid, int *len, u_int8_t *tupledata);
93 static void     cardbus_read_tuple_finish(device_t cbdev, device_t child,
94                     int rid, struct resource *res);
95 static struct resource  *cardbus_read_tuple_init(device_t cbdev, device_t child,
96                     u_int32_t *start, int *rid);
97 static int      decode_tuple(device_t cbdev, device_t child, int tupleid,
98                     int len, u_int8_t *tupledata, u_int32_t start,
99                     u_int32_t *off, struct tuple_callbacks *callbacks);
100 static int      cardbus_parse_cis(device_t cbdev, device_t child,
101                     struct tuple_callbacks *callbacks);
102 static int      barsort(const void *a, const void *b);
103 static int      cardbus_alloc_resources(device_t cbdev, device_t child);
104 static void     cardbus_add_map(device_t cbdev, device_t child, int reg);
105 static void     cardbus_pickup_maps(device_t cbdev, device_t child);
106
107
108 #define MAKETUPLE(NAME,FUNC) { CISTPL_ ## NAME, #NAME, decode_tuple_ ## FUNC }
109
110 static char *funcnames[] = {
111         "Multi-Functioned",
112         "Memory",
113         "Serial Port",
114         "Parallel Port",
115         "Fixed Disk",
116         "Video Adaptor",
117         "Network Adaptor",
118         "AIMS",
119         "SCSI",
120         "Security"
121 };
122
123 struct cardbus_quirk {
124         u_int32_t devid;        /* Vendor/device of the card */
125         int     type;
126 #define CARDBUS_QUIRK_MAP_REG   1 /* PCI map register in weird place */
127         int     arg1;
128         int     arg2;
129 };
130
131 struct cardbus_quirk cardbus_quirks[] = {
132         { 0 }
133 };
134
135 static struct cis_tupleinfo *cisread_buf;
136 static int ncisread_buf;
137
138 /*
139  * Handler functions for various CIS tuples
140  */
141
142 DECODE_PROTOTYPE(generic)
143 {
144 #ifdef CARDBUS_DEBUG
145         int i;
146
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 #endif
159         return (0);
160 }
161
162 DECODE_PROTOTYPE(nothing)
163 {
164         return (0);
165 }
166
167 DECODE_PROTOTYPE(copy)
168 {
169         struct cis_tupleinfo *tmpbuf;
170
171         tmpbuf = malloc(sizeof(struct cis_tupleinfo) * (ncisread_buf+1),
172             M_DEVBUF, M_WAITOK);
173         if (ncisread_buf > 0) {
174                 memcpy(tmpbuf, cisread_buf,
175                     sizeof(struct cis_tupleinfo) * ncisread_buf);
176                 free(cisread_buf, M_DEVBUF);
177         }
178         cisread_buf = tmpbuf;
179
180         cisread_buf[ncisread_buf].id = id;
181         cisread_buf[ncisread_buf].len = len;
182         cisread_buf[ncisread_buf].data = malloc(len, M_DEVBUF, M_WAITOK);
183         memcpy(cisread_buf[ncisread_buf].data, tupledata, len);
184         ncisread_buf++;
185         return (0);
186 }
187
188 DECODE_PROTOTYPE(linktarget)
189 {
190 #ifdef CARDBUS_DEBUG
191         int i;
192
193         printf("TUPLE: %s [%d]:", info->name, len);
194
195         for (i = 0; i < len; i++) {
196                 if (i % 0x10 == 0 && len > 0x10)
197                         printf("\n       0x%02x:", i);
198                 printf(" %02x", tupledata[i]);
199         }
200         printf("\n");
201 #endif
202         if (len != 3 || tupledata[0] != 'C' || tupledata[1] != 'I' ||
203             tupledata[2] != 'S') {
204                 printf("Invalid data for CIS Link Target!\n");
205                 decode_tuple_generic(cbdev, child, id, len, tupledata,
206                     start, off, info);
207                 return (EINVAL);
208         }
209         return (0);
210 }
211
212 DECODE_PROTOTYPE(vers_1)
213 {
214         int i;
215
216         printf("Product version: %d.%d\n", tupledata[0], tupledata[1]);
217         printf("Product name: ");
218         for (i = 2; i < len; i++) {
219                 if (tupledata[i] == '\0')
220                         printf(" | ");
221                 else if (tupledata[i] == 0xff)
222                         break;
223                 else
224                         printf("%c", tupledata[i]);
225         }
226         printf("\n");
227         return (0);
228 }
229
230 DECODE_PROTOTYPE(funcid)
231 {
232         struct cardbus_devinfo *dinfo = device_get_ivars(child);
233         int numnames = sizeof(funcnames) / sizeof(funcnames[0]);
234         int i;
235
236         printf("Functions: ");
237         for (i = 0; i < len; i++) {
238                 if (tupledata[i] < numnames)
239                         printf("%s", funcnames[tupledata[i]]);
240                 else
241                         printf("Unknown(%d)", tupledata[i]);
242                 if (i < len-1)
243                         printf(", ");
244         }
245
246         if (len > 0)
247                 dinfo->funcid = tupledata[0];           /* use first in list */
248         printf("\n");
249         return (0);
250 }
251
252 DECODE_PROTOTYPE(manfid)
253 {
254         struct cardbus_devinfo *dinfo = device_get_ivars(child);
255         int i;
256
257         printf("Manufacturer ID: ");
258         for (i = 0; i < len; i++)
259                 printf("%02x", tupledata[i]);
260         printf("\n");
261
262         if (len == 5) {
263                 dinfo->mfrid = tupledata[1] | (tupledata[2]<<8);
264                 dinfo->prodid = tupledata[3] | (tupledata[4]<<8);
265         }
266         return (0);
267 }
268
269 DECODE_PROTOTYPE(funce)
270 {
271         struct cardbus_devinfo *dinfo = device_get_ivars(child);
272         int type, i;
273
274         printf("Function Extension: ");
275         for (i = 0; i < len; i++)
276                 printf("%02x", tupledata[i]);
277         printf("\n");
278         if (len < 2)                    /* too short */
279                 return (0);
280         type = tupledata[0];            /* XXX <32 always? */
281         switch (dinfo->funcid) {
282         case TPL_FUNC_SERIAL:
283                 if (type == TPL_FUNCE_SER_UART) {       /* NB: len known > 1 */
284                         dinfo->funce.sio.type = tupledata[1] & 0x1f;
285                 }
286                 dinfo->fepresent |= 1<<type;
287                 break;
288         case TPL_FUNC_LAN:
289                 switch (type) {
290                 case TPL_FUNCE_LAN_TECH:
291                         dinfo->funce.lan.tech = tupledata[1];   /* XXX mask? */
292                         break;
293 #if 0
294                 case TPL_FUNCE_LAN_SPEED:
295                         for (i = 0; i < 3; i++) {
296                                 if (dinfo->funce.lan.speed[i] == 0) {
297                                         if (len > 4) {
298                                                 dinfo->funce.lan.speed[i] =
299                                                         ...;
300                                         }
301                                         break;
302                                 }
303                         }
304                         break;
305 #endif
306                 case TPL_FUNCE_LAN_MEDIA:
307                         for (i = 0; i < 4 && dinfo->funce.lan.media[i]; i++) {
308                                 if (dinfo->funce.lan.media[i] == 0) {
309                                         /* NB: len known > 1 */
310                                         dinfo->funce.lan.media[i] =
311                                                 tupledata[1];   /*XXX? mask */
312                                         break;
313                                 }
314                         }
315                         break;
316                 case TPL_FUNCE_LAN_NID:
317                         if (len > 6)
318                                 bcopy(&tupledata[1], dinfo->funce.lan.nid, 6);
319                         break;
320                 case TPL_FUNCE_LAN_CONN:
321                         dinfo->funce.lan.contype = tupledata[1];/*XXX mask? */
322                         break;
323                 }
324                 dinfo->fepresent |= 1<<type;
325                 break;
326         }
327         return (0);
328 }
329
330 DECODE_PROTOTYPE(bar)
331 {
332         struct cardbus_devinfo *dinfo = device_get_ivars(child);
333         int type;
334         int reg;
335         u_int32_t bar;
336
337         if (len != 6) {
338                 printf("*** ERROR *** BAR length not 6 (%d)\n", len);
339                 return (EINVAL);
340         }
341         reg = *(u_int16_t*)tupledata;
342         len = *(u_int32_t*)(tupledata + 2);
343         if (reg & TPL_BAR_REG_AS) {
344                 type = SYS_RES_IOPORT;
345         } else {
346                 type = SYS_RES_MEMORY;
347         }
348         bar = (reg & TPL_BAR_REG_ASI_MASK) - 1;
349         if (bar < 0 || bar > 5 ||
350             (type == SYS_RES_IOPORT && bar == 5)) {
351                 device_printf(cbdev, "Invalid BAR number: %02x(%02x)\n",
352                     reg, bar);
353                 return (0);
354         }
355         bar = CARDBUS_BASE0_REG + bar * 4;
356         if (type == SYS_RES_MEMORY) {
357                 if (bar & TPL_BAR_REG_PREFETCHABLE)
358                         dinfo->mprefetchable |= BARBIT(bar);
359                 if (bar & TPL_BAR_REG_BELOW1MB)
360                         dinfo->mbelow1mb |= BARBIT(bar);
361         } else if (type == SYS_RES_IOPORT) {
362                 if (bar & TPL_BAR_REG_BELOW1MB)
363                         dinfo->ibelow1mb |= BARBIT(bar);
364         }
365         DEVPRINTF((cbdev, "Opening BAR: type=%s, bar=%02x, len=%04x%s%s\n",
366             (type == SYS_RES_MEMORY) ? "MEM" : "IO", bar, len,
367             (type == SYS_RES_MEMORY && dinfo->mprefetchable & BARBIT(bar)) ?
368             " (Prefetchable)" : "", type == SYS_RES_MEMORY ?
369             ((dinfo->mbelow1mb & BARBIT(bar)) ? " (Below 1Mb)" : "") :
370             (dinfo->ibelow1mb & BARBIT(bar)) ? " (Below 1Mb)" : "" ));
371
372         resource_list_add(&dinfo->pci.resources, type, bar, 0UL, ~0UL, len);
373
374         /*
375          * Mark the appropriate bit in the PCI command register so that
376          * device drivers will know which type of BARs can be used.
377          */
378         pci_enable_io(child, type);
379         return (0);
380 }
381
382 DECODE_PROTOTYPE(unhandled)
383 {
384         printf("TUPLE: %s [%d] is unhandled! Bailing...", info->name, len);
385         return (-1);
386 }
387
388 DECODE_PROTOTYPE(end)
389 {
390         printf("CIS reading done\n");
391         return (0);
392 }
393
394 /*
395  * Functions to read the a tuple from the card
396  */
397
398 static int
399 cardbus_read_tuple_conf(device_t cbdev, device_t child, u_int32_t start,
400     u_int32_t *off, int *tupleid, int *len, u_int8_t *tupledata)
401 {
402         int i, j;
403         u_int32_t e;
404         u_int32_t loc;
405
406         loc = start + *off;
407
408         e = pci_read_config(child, loc - loc % 4, 4);
409         for (j = loc % 4; j > 0; j--)
410                 e >>= 8;
411         *len = 0;
412         for (i = loc, j = -2; j < *len; j++, i++) {
413                 if (i % 4 == 0)
414                         e = pci_read_config(child, i, 4);
415                 if (j == -2)
416                         *tupleid = 0xff & e;
417                 else if (j == -1)
418                         *len = 0xff & e;
419                 else
420                         tupledata[j] = 0xff & e;
421                 e >>= 8;
422         }
423         *off += *len + 2;
424         return (0);
425 }
426
427 static int
428 cardbus_read_tuple_mem(device_t cbdev, struct resource *res, u_int32_t start,
429     u_int32_t *off, int *tupleid, int *len, u_int8_t *tupledata)
430 {
431         bus_space_tag_t bt;
432         bus_space_handle_t bh;
433         int ret;
434
435         bt = rman_get_bustag(res);
436         bh = rman_get_bushandle(res);
437
438         *tupleid = bus_space_read_1(bt, bh, start + *off);
439         *len = bus_space_read_1(bt, bh, start + *off + 1);
440         bus_space_read_region_1(bt, bh, *off + start + 2, tupledata, *len);
441         ret = 0;
442         *off += *len + 2;
443         return (ret);
444 }
445
446 static int
447 cardbus_read_tuple(device_t cbdev, device_t child, struct resource *res,
448     u_int32_t start, u_int32_t *off, int *tupleid, int *len,
449     u_int8_t *tupledata)
450 {
451         if (res == (struct resource*)~0UL) {
452                 return (cardbus_read_tuple_conf(cbdev, child, start, off,
453                     tupleid, len, tupledata));
454         } else {
455                 return (cardbus_read_tuple_mem(cbdev, res, start, off,
456                     tupleid, len, tupledata));
457         }
458 }
459
460 static void
461 cardbus_read_tuple_finish(device_t cbdev, device_t child, int rid,
462     struct resource *res)
463 {
464         if (res != (struct resource*)~0UL) {
465                 bus_release_resource(cbdev, SYS_RES_MEMORY, rid, res);
466                 pci_write_config(child, rid, 0, 4);
467                 PCI_DISABLE_IO(cbdev, child, SYS_RES_MEMORY);
468         }
469 }
470
471 static struct resource *
472 cardbus_read_tuple_init(device_t cbdev, device_t child, u_int32_t *start,
473     int *rid)
474 {
475         u_int32_t testval;
476         u_int32_t size;
477         struct resource *res;
478
479         switch (CARDBUS_CIS_SPACE(*start)) {
480         case CARDBUS_CIS_ASI_TUPLE:
481                 /* CIS in PCI config space need no initialization */
482                 return ((struct resource*)~0UL);
483         case CARDBUS_CIS_ASI_BAR0:
484         case CARDBUS_CIS_ASI_BAR1:
485         case CARDBUS_CIS_ASI_BAR2:
486         case CARDBUS_CIS_ASI_BAR3:
487         case CARDBUS_CIS_ASI_BAR4:
488         case CARDBUS_CIS_ASI_BAR5:
489                 *rid = CARDBUS_BASE0_REG + (CARDBUS_CIS_SPACE(*start) - 1) * 4;
490                 break;
491         case CARDBUS_CIS_ASI_ROM:
492                 *rid = CARDBUS_ROM_REG;
493 #if 0
494                 /*
495                  * This mask doesn't contain the bit that actually enables
496                  * the Option ROM.
497                  */
498                 pci_write_config(child, *rid, CARDBUS_ROM_ADDRMASK, 4);
499 #endif
500                 break;
501         default:
502                 device_printf(cbdev, "Unable to read CIS: Unknown space: %d\n",
503                     CARDBUS_CIS_SPACE(*start));
504                 return (NULL);
505         }
506
507         /* figure out how much space we need */
508         pci_write_config(child, *rid, 0xffffffff, 4);
509         testval = pci_read_config(child, *rid, 4);
510
511         /*
512          * This bit has a different meaning depending if we are dealing
513          * with a normal BAR or an Option ROM BAR.
514          */
515         if (((testval & 0x1) == 0x1) && (*rid != CARDBUS_ROM_REG)) {
516                 device_printf(cbdev, "CIS Space is IO, expecting memory.\n");
517                 return (NULL);
518         }
519
520         size = CARDBUS_MAPREG_MEM_SIZE(testval);
521         /* XXX Is this some kind of hack? */
522         if (size < 4096)
523                 size = 4096;
524         /* allocate the memory space to read CIS */
525         res = bus_alloc_resource(cbdev, SYS_RES_MEMORY, rid, 0, ~0, size,
526             rman_make_alignment_flags(size) | RF_ACTIVE);
527         if (res == NULL) {
528                 device_printf(cbdev, "Unable to allocate resource "
529                     "to read CIS.\n");
530                 return (NULL);
531         }
532         pci_write_config(child, *rid,
533             rman_get_start(res) | ((*rid == CARDBUS_ROM_REG)?
534                 CARDBUS_ROM_ENABLE : 0),
535             4);
536         PCI_ENABLE_IO(cbdev, child, SYS_RES_MEMORY);
537
538         /* Flip to the right ROM image if CIS is in ROM */
539         if (CARDBUS_CIS_SPACE(*start) == CARDBUS_CIS_ASI_ROM) {
540                 bus_space_tag_t bt;
541                 bus_space_handle_t bh;
542                 u_int32_t imagesize;
543                 u_int32_t imagebase = 0;
544                 u_int32_t pcidata;
545                 u_int16_t romsig;
546                 int romnum = 0;
547                 int imagenum;
548
549                 bt = rman_get_bustag(res);
550                 bh = rman_get_bushandle(res);
551
552                 imagenum = CARDBUS_CIS_ASI_ROM_IMAGE(*start);
553                 for (romnum = 0;; romnum++) {
554                         romsig = bus_space_read_2(bt, bh,
555                             imagebase + CARDBUS_EXROM_SIGNATURE);
556                         if (romsig != 0xaa55) {
557                                 device_printf(cbdev, "Bad header in rom %d: "
558                                     "[%x] %04x\n", romnum, imagebase + 
559                                     CARDBUS_EXROM_SIGNATURE, romsig);
560                                 bus_release_resource(cbdev, SYS_RES_MEMORY,
561                                     *rid, res);
562                                 *rid = 0;
563                                 return (NULL);
564                         }
565
566                         /*
567                          * If this was the Option ROM image that we were
568                          * looking for, then we are done.
569                          */
570                         if (romnum == imagenum)
571                                 break;
572
573                         /* Find out where the next Option ROM image is */
574                         pcidata = imagebase + bus_space_read_2(bt, bh,
575                             imagebase + CARDBUS_EXROM_DATA_PTR);
576                         imagesize = bus_space_read_2(bt, bh,
577                             pcidata + CARDBUS_EXROM_DATA_IMAGE_LENGTH);
578
579                         if (imagesize == 0) {
580                                 /*
581                                  * XXX some ROMs seem to have this as zero,
582                                  * can we assume this means 1 block?
583                                  */
584                                 device_printf(cbdev, "Warning, size of Option "
585                                     "ROM image %d is 0 bytes, assuming 512 "
586                                     "bytes.\n", romnum);
587                                 imagesize = 1;
588                         }
589
590                         /* Image size is in 512 byte units */
591                         imagesize <<= 9;
592
593                         if ((bus_space_read_1(bt, bh, pcidata + 
594                             CARDBUS_EXROM_DATA_INDICATOR) & 0x80) != 0) {
595                                 device_printf(cbdev, "Cannot find CIS in "
596                                     "Option ROM\n");
597                                 bus_release_resource(cbdev, SYS_RES_MEMORY,
598                                     *rid, res);
599                                 *rid = 0;
600                                 return (NULL);
601                         }
602                         imagebase += imagesize;
603                 }
604                 *start = imagebase + CARDBUS_CIS_ADDR(*start);
605         } else {
606                 *start = CARDBUS_CIS_ADDR(*start);
607         }
608
609         return (res);
610 }
611
612 /*
613  * Dispatch the right handler function per tuple
614  */
615
616 static int
617 decode_tuple(device_t cbdev, device_t child, int tupleid, int len,
618     u_int8_t *tupledata, u_int32_t start, u_int32_t *off,
619     struct tuple_callbacks *callbacks)
620 {
621         int i;
622         for (i = 0; callbacks[i].id != CISTPL_GENERIC; i++) {
623                 if (tupleid == callbacks[i].id)
624                         return (callbacks[i].func(cbdev, child, tupleid, len,
625                             tupledata, start, off, &callbacks[i]));
626         }
627
628         if (tupleid < CISTPL_CUSTOMSTART) {
629                 device_printf(cbdev, "Undefined tuple encountered, "
630                     "CIS parsing terminated\n");
631                 return (EINVAL);
632         }
633         return (callbacks[i].func(cbdev, child, tupleid, len,
634             tupledata, start, off, NULL));
635 }
636
637 static int
638 cardbus_parse_cis(device_t cbdev, device_t child,
639     struct tuple_callbacks *callbacks)
640 {
641         u_int8_t tupledata[MAXTUPLESIZE];
642         int tupleid;
643         int len;
644         int expect_linktarget;
645         u_int32_t start, off;
646         struct resource *res;
647         int rid;
648
649         bzero(tupledata, MAXTUPLESIZE);
650         expect_linktarget = TRUE;
651         if ((start = pci_read_config(child, CARDBUS_CIS_REG, 4)) == 0)
652                 return (ENXIO);
653         off = 0;
654         res = cardbus_read_tuple_init(cbdev, child, &start, &rid);
655         if (res == NULL)
656                 return (ENXIO);
657         do {
658                 if (0 != cardbus_read_tuple(cbdev, child, res, start, &off,
659                     &tupleid, &len, tupledata)) {
660                         device_printf(cbdev, "Failed to read CIS.\n");
661                         cardbus_read_tuple_finish(cbdev, child, rid, res);
662                         return (ENXIO);
663                 }
664
665                 if (expect_linktarget && tupleid != CISTPL_LINKTARGET) {
666                         device_printf(cbdev, "Expecting link target, got 0x%x\n",
667                             tupleid);
668                         cardbus_read_tuple_finish(cbdev, child, rid, res);
669                         return (EINVAL);
670                 }
671                 expect_linktarget = decode_tuple(cbdev, child, tupleid, len,
672                     tupledata, start, &off, callbacks);
673                 if (expect_linktarget != 0) {
674                         cardbus_read_tuple_finish(cbdev, child, rid, res);
675                         return (expect_linktarget);
676                 }
677         } while (tupleid != CISTPL_END);
678         cardbus_read_tuple_finish(cbdev, child, rid, res);
679         return (0);
680 }
681
682 static int
683 barsort(const void *a, const void *b)
684 {
685         return ((*(const struct resource_list_entry * const *)b)->count -
686             (*(const struct resource_list_entry * const *)a)->count);
687 }
688
689 static int
690 cardbus_alloc_resources(device_t cbdev, device_t child)
691 {
692         struct cardbus_devinfo *dinfo = device_get_ivars(child);
693         int count;
694         struct resource_list_entry *rle;
695         struct resource_list_entry **barlist;
696         int tmp;
697         u_int32_t mem_psize = 0, mem_nsize = 0, io_size = 0;
698         struct resource *res;
699         u_int32_t start,end;
700         int rid, flags;
701
702         count = 0;
703         SLIST_FOREACH(rle, &dinfo->pci.resources, link) {
704                 count++;
705         }
706         if (count == 0)
707                 return (0);
708         barlist = malloc(sizeof(struct resource_list_entry*) * count, M_DEVBUF,
709             M_WAITOK);
710         count = 0;
711         SLIST_FOREACH(rle, &dinfo->pci.resources, link) {
712                 barlist[count] = rle;
713                 if (rle->type == SYS_RES_IOPORT) {
714                         io_size += rle->count;
715                 } else if (rle->type == SYS_RES_MEMORY) {
716                         if (dinfo->mprefetchable & BARBIT(rle->rid))
717                                 mem_psize += rle->count;
718                         else
719                                 mem_nsize += rle->count;
720                 }
721                 count++;
722         }
723
724         /*
725          * We want to allocate the largest resource first, so that our
726          * allocated memory is packed.
727          */
728         qsort(barlist, count, sizeof(struct resource_list_entry*), barsort);
729
730         /* Allocate prefetchable memory */
731         flags = 0;
732         for (tmp = 0; tmp < count; tmp++) {
733                 if (barlist[tmp]->res == NULL &&
734                     barlist[tmp]->type == SYS_RES_MEMORY &&
735                     dinfo->mprefetchable & BARBIT(barlist[tmp]->rid)) {
736                         flags = rman_make_alignment_flags(barlist[tmp]->count);
737                         break;
738                 }
739         }
740         if (flags > 0) { /* If any prefetchable memory is requested... */
741                 /*
742                  * First we allocate one big space for all resources of this
743                  * type.  We do this because our parent, pccbb, needs to open
744                  * a window to forward all addresses within the window, and
745                  * it would be best if nobody else has resources allocated
746                  * within the window.
747                  * (XXX: Perhaps there might be a better way to do this?)
748                  */
749                 rid = 0;
750                 res = bus_alloc_resource(cbdev, SYS_RES_MEMORY, &rid, 0,
751                     (dinfo->mprefetchable & dinfo->mbelow1mb)?0xFFFFF:~0UL,
752                     mem_psize, flags);
753                 start = rman_get_start(res);
754                 end = rman_get_end(res);
755                 DEVPRINTF((cbdev, "Prefetchable memory at %x-%x\n", start, end));
756                 /*
757                  * Now that we know the region is free, release it and hand it
758                  * out piece by piece.
759                  */
760                 bus_release_resource(cbdev, SYS_RES_MEMORY, rid, res);
761                 for (tmp = 0; tmp < count; tmp++) {
762                         if (barlist[tmp]->res == NULL &&
763                             barlist[tmp]->type == SYS_RES_MEMORY &&
764                             dinfo->mprefetchable & BARBIT(barlist[tmp]->rid)) {
765                                 barlist[tmp]->res = bus_alloc_resource(cbdev,
766                                     barlist[tmp]->type,
767                                     &barlist[tmp]->rid, start, end,
768                                     barlist[tmp]->count,
769                                     rman_make_alignment_flags(
770                                     barlist[tmp]->count));
771                                 if (barlist[tmp]->res == NULL) {
772                                         mem_nsize += barlist[tmp]->count;
773                                         dinfo->mprefetchable &=
774                                             ~BARBIT(barlist[tmp]->rid);
775                                         DEVPRINTF((cbdev, "Cannot pre-allocate "
776                                             "prefetchable memory, will try as "
777                                             "non-prefetchable.\n"));
778                                 } else {
779                                         barlist[tmp]->start =
780                                             rman_get_start(barlist[tmp]->res);
781                                         barlist[tmp]->end =
782                                             rman_get_end(barlist[tmp]->res);
783                                         pci_write_config(child,
784                                             barlist[tmp]->rid,
785                                             barlist[tmp]->start, 4);
786                                         DEVPRINTF((cbdev, "Prefetchable memory "
787                                             "rid=%x at %lx-%lx\n",
788                                             barlist[tmp]->rid,
789                                             barlist[tmp]->start,
790                                             barlist[tmp]->end));
791                                 }
792                         }
793                 }
794         }
795
796         /* Allocate non-prefetchable memory */
797         flags = 0;
798         for (tmp = 0; tmp < count; tmp++) {
799                 if (barlist[tmp]->res == NULL &&
800                     barlist[tmp]->type == SYS_RES_MEMORY) {
801                         flags = rman_make_alignment_flags(barlist[tmp]->count);
802                         break;
803                 }
804         }
805         if (flags > 0) { /* If any non-prefetchable memory is requested... */
806                 /*
807                  * First we allocate one big space for all resources of this
808                  * type.  We do this because our parent, pccbb, needs to open
809                  * a window to forward all addresses within the window, and
810                  * it would be best if nobody else has resources allocated
811                  * within the window.
812                  * (XXX: Perhaps there might be a better way to do this?)
813                  */
814                 rid = 0;
815                 res = bus_alloc_resource(cbdev, SYS_RES_MEMORY, &rid, 0,
816                     ((~dinfo->mprefetchable) & dinfo->mbelow1mb)?0xFFFFF:~0UL,
817                     mem_nsize, flags);
818                 start = rman_get_start(res);
819                 end = rman_get_end(res);
820                 DEVPRINTF((cbdev, "Non-prefetchable memory at %x-%x\n",
821                     start, end));
822                 /*
823                  * Now that we know the region is free, release it and hand it
824                  * out piece by piece.
825                  */
826                 bus_release_resource(cbdev, SYS_RES_MEMORY, rid, res);
827                 for (tmp = 0; tmp < count; tmp++) {
828                         if (barlist[tmp]->res == NULL &&
829                             barlist[tmp]->type == SYS_RES_MEMORY) {
830                                 barlist[tmp]->res = bus_alloc_resource(cbdev,
831                                     barlist[tmp]->type, &barlist[tmp]->rid,
832                                     start, end, barlist[tmp]->count,
833                                     rman_make_alignment_flags(
834                                     barlist[tmp]->count));
835                                 if (barlist[tmp]->res == NULL) {
836                                         DEVPRINTF((cbdev, "Cannot pre-allocate "
837                                             "memory for cardbus device\n"));
838                                         free(barlist, M_DEVBUF);
839                                         return (ENOMEM);
840                                 }
841                                 barlist[tmp]->start =
842                                     rman_get_start(barlist[tmp]->res);
843                                 barlist[tmp]->end = rman_get_end(
844                                         barlist[tmp]->res);
845                                 pci_write_config(child, barlist[tmp]->rid,
846                                     barlist[tmp]->start, 4);
847                                 DEVPRINTF((cbdev, "Non-prefetchable memory "
848                                     "rid=%x at %lx-%lx (%lx)\n",
849                                     barlist[tmp]->rid, barlist[tmp]->start,
850                                     barlist[tmp]->end, barlist[tmp]->count));
851                         }
852                 }
853         }
854
855         /* Allocate IO ports */
856         flags = 0;
857         for (tmp = 0; tmp < count; tmp++) {
858                 if (barlist[tmp]->res == NULL &&
859                     barlist[tmp]->type == SYS_RES_IOPORT) {
860                         flags = rman_make_alignment_flags(barlist[tmp]->count);
861                         break;
862                 }
863         }
864         if (flags > 0) { /* If any IO port is requested... */
865                 /*
866                  * First we allocate one big space for all resources of this
867                  * type.  We do this because our parent, pccbb, needs to open
868                  * a window to forward all addresses within the window, and
869                  * it would be best if nobody else has resources allocated
870                  * within the window.
871                  * (XXX: Perhaps there might be a better way to do this?)
872                  */
873                 rid = 0;
874                 res = bus_alloc_resource(cbdev, SYS_RES_IOPORT, &rid, 0,
875                     (dinfo->ibelow1mb)?0xFFFFF:~0UL, io_size, flags);
876                 start = rman_get_start(res);
877                 end = rman_get_end(res);
878                 DEVPRINTF((cbdev, "IO port at %x-%x\n", start, end));
879                 /*
880                  * Now that we know the region is free, release it and hand it
881                  * out piece by piece.
882                  */
883                 bus_release_resource(cbdev, SYS_RES_IOPORT, rid, res);
884                 for (tmp = 0; tmp < count; tmp++) {
885                         if (barlist[tmp]->res == NULL &&
886                             barlist[tmp]->type == SYS_RES_IOPORT) {
887                                 barlist[tmp]->res = bus_alloc_resource(cbdev,
888                                     barlist[tmp]->type, &barlist[tmp]->rid,
889                                     start, end, barlist[tmp]->count,
890                                     rman_make_alignment_flags(
891                                     barlist[tmp]->count));
892                                 if (barlist[tmp]->res == NULL) {
893                                         DEVPRINTF((cbdev, "Cannot pre-allocate "
894                                             "IO port for cardbus device\n"));
895                                         free(barlist, M_DEVBUF);
896                                         return (ENOMEM);
897                                 }
898                                 barlist[tmp]->start =
899                                     rman_get_start(barlist[tmp]->res);
900                                 barlist[tmp]->end =
901                                     rman_get_end(barlist[tmp]->res);
902                         pci_write_config(child, barlist[tmp]->rid,
903                             barlist[tmp]->start, 4);
904                         DEVPRINTF((cbdev, "IO port rid=%x at %lx-%lx\n",
905                             barlist[tmp]->rid, barlist[tmp]->start,
906                             barlist[tmp]->end));
907                         }
908                 }
909         }
910
911         /* Allocate IRQ */
912         rid = 0;
913         res = bus_alloc_resource(cbdev, SYS_RES_IRQ, &rid, 0, ~0UL, 1,
914             RF_SHAREABLE);
915         resource_list_add(&dinfo->pci.resources, SYS_RES_IRQ, rid,
916             rman_get_start(res), rman_get_end(res), 1);
917         rle = resource_list_find(&dinfo->pci.resources, SYS_RES_IRQ, rid);
918         rle->res = res;
919         dinfo->pci.cfg.intline = rman_get_start(res);
920         pci_write_config(child, PCIR_INTLINE, rman_get_start(res), 1);
921
922         free(barlist, M_DEVBUF);
923         return (0);
924 }
925
926 /*
927  * Adding a memory/io resource (sans CIS)
928  */
929
930 static void
931 cardbus_add_map(device_t cbdev, device_t child, int reg)
932 {
933         struct cardbus_devinfo *dinfo = device_get_ivars(child);
934         struct resource_list_entry *rle;
935         u_int32_t size;
936         u_int32_t testval;
937         int type;
938
939         SLIST_FOREACH(rle, &dinfo->pci.resources, link) {
940                 if (rle->rid == reg)
941                         return;
942         }
943
944         if (reg == CARDBUS_ROM_REG)
945                 testval = CARDBUS_ROM_ADDRMASK;
946         else
947                 testval = ~0;
948
949         pci_write_config(child, reg, testval, 4);
950         testval = pci_read_config(child, reg, 4);
951
952         if (testval == ~0 || testval == 0)
953                 return;
954
955         if ((testval & 1) == 0)
956                 type = SYS_RES_MEMORY;
957         else
958                 type = SYS_RES_IOPORT;
959
960         size = CARDBUS_MAPREG_MEM_SIZE(testval);
961         device_printf(cbdev, "Resource not specified in CIS: id=%x, size=%x\n",
962             reg, size);
963         resource_list_add(&dinfo->pci.resources, type, reg, 0UL, ~0UL, size);
964 }
965
966 static void
967 cardbus_pickup_maps(device_t cbdev, device_t child)
968 {
969         struct cardbus_devinfo *dinfo = device_get_ivars(child);
970         struct cardbus_quirk *q;
971         int reg;
972
973         /*
974          * Try to pick up any resources that was not specified in CIS.
975          * Some devices (eg, 3c656) does not list all resources required by
976          * the driver in its CIS.
977          * XXX: should we do this or use quirks?
978          */
979         for (reg = 0; reg < dinfo->pci.cfg.nummaps; reg++) {
980                 cardbus_add_map(cbdev, child, PCIR_MAPS + reg * 4);
981         }
982
983         for (q = &cardbus_quirks[0]; q->devid; q++) {
984                 if (q->devid == ((dinfo->pci.cfg.device << 16) | dinfo->pci.cfg.vendor)
985                     && q->type == CARDBUS_QUIRK_MAP_REG) {
986                         cardbus_add_map(cbdev, child, q->arg1);
987                 }
988         }
989 }
990
991 int
992 cardbus_cis_read(device_t cbdev, device_t child, u_int8_t id,
993     struct cis_tupleinfo **buff, int *nret)
994 {
995         struct tuple_callbacks cisread_callbacks[] = {
996                 MAKETUPLE(NULL,                 nothing),
997                 /* first entry will be overwritten */
998                 MAKETUPLE(NULL,                 nothing),
999                 MAKETUPLE(DEVICE,               nothing),
1000                 MAKETUPLE(LONG_LINK_CB,         unhandled),
1001                 MAKETUPLE(INDIRECT,             unhandled),
1002                 MAKETUPLE(CONFIG_CB,            nothing),
1003                 MAKETUPLE(CFTABLE_ENTRY_CB,     nothing),
1004                 MAKETUPLE(LONGLINK_MFC,         unhandled),
1005                 MAKETUPLE(BAR,                  nothing),
1006                 MAKETUPLE(PWR_MGMNT,            nothing),
1007                 MAKETUPLE(EXTDEVICE,            nothing),
1008                 MAKETUPLE(CHECKSUM,             nothing),
1009                 MAKETUPLE(LONGLINK_A,           unhandled),
1010                 MAKETUPLE(LONGLINK_C,           unhandled),
1011                 MAKETUPLE(LINKTARGET,           nothing),
1012                 MAKETUPLE(NO_LINK,              nothing),
1013                 MAKETUPLE(VERS_1,               nothing),
1014                 MAKETUPLE(ALTSTR,               nothing),
1015                 MAKETUPLE(DEVICE_A,             nothing),
1016                 MAKETUPLE(JEDEC_C,              nothing),
1017                 MAKETUPLE(JEDEC_A,              nothing),
1018                 MAKETUPLE(CONFIG,               nothing),
1019                 MAKETUPLE(CFTABLE_ENTRY,        nothing),
1020                 MAKETUPLE(DEVICE_OC,            nothing),
1021                 MAKETUPLE(DEVICE_OA,            nothing),
1022                 MAKETUPLE(DEVICE_GEO,           nothing),
1023                 MAKETUPLE(DEVICE_GEO_A,         nothing),
1024                 MAKETUPLE(MANFID,               nothing),
1025                 MAKETUPLE(FUNCID,               nothing),
1026                 MAKETUPLE(FUNCE,                nothing),
1027                 MAKETUPLE(SWIL,                 nothing),
1028                 MAKETUPLE(VERS_2,               nothing),
1029                 MAKETUPLE(FORMAT,               nothing),
1030                 MAKETUPLE(GEOMETRY,             nothing),
1031                 MAKETUPLE(BYTEORDER,            nothing),
1032                 MAKETUPLE(DATE,                 nothing),
1033                 MAKETUPLE(BATTERY,              nothing),
1034                 MAKETUPLE(ORG,                  nothing),
1035                 MAKETUPLE(END,                  end),
1036                 MAKETUPLE(GENERIC,              nothing),
1037         };
1038         int ret;
1039
1040         cisread_callbacks[0].id = id;
1041         cisread_callbacks[0].name = "COPY";
1042         cisread_callbacks[0].func = decode_tuple_copy;
1043         ncisread_buf = 0;
1044         cisread_buf = NULL;
1045         ret = cardbus_parse_cis(cbdev, child, cisread_callbacks);
1046
1047         *buff = cisread_buf;
1048         *nret = ncisread_buf;
1049         return (ret);
1050 }
1051
1052 void
1053 cardbus_cis_free(device_t cbdev, struct cis_tupleinfo *buff, int *nret)
1054 {
1055         int i;
1056         for (i = 0; i < *nret; i++)
1057                 free(buff[i].data, M_DEVBUF);
1058         if (*nret > 0)
1059                 free(buff, M_DEVBUF);
1060 }
1061
1062 int
1063 cardbus_do_cis(device_t cbdev, device_t child)
1064 {
1065         int ret;
1066         struct tuple_callbacks init_callbacks[] = {
1067                 MAKETUPLE(NULL,                 generic),
1068                 MAKETUPLE(DEVICE,               generic),
1069                 MAKETUPLE(LONG_LINK_CB,         unhandled),
1070                 MAKETUPLE(INDIRECT,             unhandled),
1071                 MAKETUPLE(CONFIG_CB,            generic),
1072                 MAKETUPLE(CFTABLE_ENTRY_CB,     generic),
1073                 MAKETUPLE(LONGLINK_MFC,         unhandled),
1074                 MAKETUPLE(BAR,                  bar),
1075                 MAKETUPLE(PWR_MGMNT,            generic),
1076                 MAKETUPLE(EXTDEVICE,            generic),
1077                 MAKETUPLE(CHECKSUM,             generic),
1078                 MAKETUPLE(LONGLINK_A,           unhandled),
1079                 MAKETUPLE(LONGLINK_C,           unhandled),
1080                 MAKETUPLE(LINKTARGET,           linktarget),
1081                 MAKETUPLE(NO_LINK,              generic),
1082                 MAKETUPLE(VERS_1,               vers_1),
1083                 MAKETUPLE(ALTSTR,               generic),
1084                 MAKETUPLE(DEVICE_A,             generic),
1085                 MAKETUPLE(JEDEC_C,              generic),
1086                 MAKETUPLE(JEDEC_A,              generic),
1087                 MAKETUPLE(CONFIG,               generic),
1088                 MAKETUPLE(CFTABLE_ENTRY,        generic),
1089                 MAKETUPLE(DEVICE_OC,            generic),
1090                 MAKETUPLE(DEVICE_OA,            generic),
1091                 MAKETUPLE(DEVICE_GEO,           generic),
1092                 MAKETUPLE(DEVICE_GEO_A,         generic),
1093                 MAKETUPLE(MANFID,               manfid),
1094                 MAKETUPLE(FUNCID,               funcid),
1095                 MAKETUPLE(FUNCE,                funce),
1096                 MAKETUPLE(SWIL,                 generic),
1097                 MAKETUPLE(VERS_2,               generic),
1098                 MAKETUPLE(FORMAT,               generic),
1099                 MAKETUPLE(GEOMETRY,             generic),
1100                 MAKETUPLE(BYTEORDER,            generic),
1101                 MAKETUPLE(DATE,                 generic),
1102                 MAKETUPLE(BATTERY,              generic),
1103                 MAKETUPLE(ORG,                  generic),
1104                 MAKETUPLE(END,                  end),
1105                 MAKETUPLE(GENERIC,              generic),
1106         };
1107
1108         ret = cardbus_parse_cis(cbdev, child, init_callbacks);
1109         if (ret < 0)
1110                 return (ret);
1111         cardbus_pickup_maps(cbdev, child);
1112         return (cardbus_alloc_resources(cbdev, child));
1113 }