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